Skip to content

Instantly share code, notes, and snippets.

@Geobert
Created December 11, 2019 21:09
Show Gist options
  • Select an option

  • Save Geobert/d16ba0a151b7cd7c812265ad2f895dae to your computer and use it in GitHub Desktop.

Select an option

Save Geobert/d16ba0a151b7cd7c812265ad2f895dae to your computer and use it in GitHub Desktop.
use std::collections::HashMap;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use liquid::compiler::{Language, ParseTag, TagReflection, TagTokenIter};
use liquid::error::Result;
use liquid::interpreter::{Context, PartialStore, Renderable};
use liquid::partials::{InMemorySource, LazyCompiler, PartialCompiler};
use liquid::value::Value;
use super::parse_params;
#[derive(Debug)]
struct Generic {
params: HashMap<String, String>,
tag_name: String,
partial: Box<dyn PartialStore + Send + Sync>,
}
impl Renderable for Generic {
fn render_to(&self, writer: &mut dyn Write, context: &mut Context) -> Result<()> {
context.run_in_scope(|mut scope| -> Result<()> {
let stack = scope.stack_mut();
self.params.clone().into_iter().for_each(|(k, v)| {
stack.set(k, Value::scalar(v));
});
let partial = self.partial.get(&self.tag_name)?;
partial.render_to(writer, &mut scope)?;
Ok(())
})?;
Ok(())
}
}
#[derive(Clone, Debug, Default)]
pub struct GenericTag {
tag_name: String,
tag_snippet: String,
}
impl GenericTag {
pub fn new(path: &Path) -> Self {
let snippet = std::fs::read_to_string(&path)
.expect(&format!("Error while reading {}", path.display()));
GenericTag {
tag_name: path
.file_name()
.expect("Should have a filename")
.to_string_lossy()
.to_string(),
tag_snippet: snippet,
}
}
}
impl TagReflection for GenericTag {
fn tag(&self) -> &'static str {
self.tag_name
}
fn description(&self) -> &'static str {
""
}
}
impl ParseTag for GenericTag {
fn parse(
&self,
mut arguments: TagTokenIter,
options: &Language,
) -> Result<Box<dyn Renderable>> {
let mut params = HashMap::new();
while let Some(token) = arguments.next() {
let key = token.as_str().to_string();
let value = parse_params(&mut arguments)?.to_str().to_string();
params.insert(key, value);
}
let mut partial = InMemorySource::new();
partial.add(&self.tag_name, &self.tag_snippet);
let compiler = LazyCompiler::new(partial);
let partial = compiler.compile(Arc::new(options.clone()))?;
Ok(Box::new(Generic {
params,
tag_name: self.tag_name.clone(),
partial,
}))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment