Skip to content

Instantly share code, notes, and snippets.

@Geobert
Last active December 11, 2019 21:08
Show Gist options
  • Save Geobert/1c6fffd806c019dd79cffe66a1beacf1 to your computer and use it in GitHub Desktop.
Save Geobert/1c6fffd806c019dd79cffe66a1beacf1 to your computer and use it in GitHub Desktop.
use std::io::Write;
use std::sync::Arc;
use liquid::compiler::{Language, ParseTag, TagReflection, TagTokenIter, TryMatchToken};
use liquid::error::Result;
use liquid::interpreter::{Context, PartialStore, Renderable};
use liquid::partials::{InMemorySource, LazyCompiler, PartialCompiler};
use liquid::value::Value;
#[derive(Debug)]
struct Youtube {
id: String,
class: Option<String>,
partial: Box<dyn PartialStore + Send + Sync>,
}
impl Renderable for Youtube {
fn render_to(&self, writer: &mut dyn Write, context: &mut Context) -> Result<()> {
context.run_in_scope(|mut scope| -> Result<()> {
let stack = scope.stack_mut();
stack.set("id", Value::scalar(self.id.clone()));
if let Some(class) = &self.class {
stack.set("class", Value::scalar(class.clone()));
}
let partial = self.partial.get("youtube_snippet")?;
partial.render_to(writer, &mut scope)?;
Ok(())
})?;
Ok(())
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct YoutubeTag {}
impl YoutubeTag {
pub fn new() -> Self {
Self::default()
}
}
impl TagReflection for YoutubeTag {
fn tag(&self) -> &'static str {
"youtube"
}
fn description(&self) -> &'static str {
"shortcode for embedding YouTube videos"
}
}
impl ParseTag for YoutubeTag {
fn parse(
&self,
mut arguments: TagTokenIter,
options: &Language,
) -> Result<Box<dyn Renderable>> {
let id = arguments.expect_next("YouTube video's id expected.")?;
let id = match id.expect_literal() {
TryMatchToken::Matches(id) => id.to_str().to_string(),
TryMatchToken::Fails(id) => id.as_str().to_string(),
};
dbg!(&id);
let class = if let Ok(class) = arguments.expect_next("") {
let c = match class.expect_literal() {
TryMatchToken::Matches(c) => c.to_str().to_string(),
TryMatchToken::Fails(c) => c.as_str().to_string(),
};
Some(c)
} else {
None
};
dbg!(&class);
arguments.expect_nothing()?;
let snippet = r#"<div {% if class %}class="{{ class }}"{% endif %}>
<iframe src="https://www.youtube.com/embed/{{ id }}"
webkitallowfullscreen mozallowfullscreen allowfullscreen frameborder="0"></iframe></div>"#;
let mut partial = InMemorySource::new();
partial.add("youtube_snippet", snippet);
let compiler = LazyCompiler::new(partial);
let partial = compiler.compile(Arc::new(options.clone()))?;
Ok(Box::new(Youtube { id, class, partial }))
}
// fn reflection(&self) -> &dyn TagReflection {
// self
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment