Skip to content

Commit

Permalink
feat(tags): add more shopify tags
Browse files Browse the repository at this point in the history
Implement four shopify tags:
- increment
- decrement
- ifchanged
- tablerow

Closes #163
  • Loading branch information
Goncalerta committed Oct 17, 2018
1 parent 079f8ad commit 1866073
Show file tree
Hide file tree
Showing 6 changed files with 569 additions and 45 deletions.
45 changes: 45 additions & 0 deletions liquid-interpreter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,42 @@ impl<'a, 'g> CycleState<'a, 'g> {
}
}

/// Remembers the content of the last rendered `ifstate` block.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct IfChangedState {
last_rendered: Option<String>,
}

impl IfChangedState {
/// Checks whether or not a new rendered `&str` is different from
/// `last_rendered` and updates `last_rendered` value to the new value.
pub fn has_changed(&mut self, rendered: &str) -> bool {
let has_changed = if let Some(last_rendered) = &self.last_rendered {
last_rendered != rendered
} else {
true
};
self.last_rendered = Some(rendered.to_owned());

has_changed
}
}

/// Stack of variables.
#[derive(Debug, Clone)]
pub struct Stack<'g> {
globals: Option<&'g Globals>,
stack: Vec<Object>,
// State of variables created through increment or decrement tags.
indexes: Object,
}

impl<'g> Stack<'g> {
/// Create an empty stack
pub fn empty() -> Self {
Self {
globals: None,
indexes: Object::new(),
// Mutable frame for globals.
stack: vec![Object::new()],
}
Expand Down Expand Up @@ -169,6 +193,20 @@ impl<'g> Stack<'g> {
self.globals
.ok_or_else(|| Error::with_msg("Invalid index").context("index", name.to_owned()))
.and_then(|g| g.get(name))
.or_else(|err| self.get_index(name).ok_or_else(|| err))
}

/// Used by increment and decrement tags
pub fn set_index<S>(&mut self, name: S, val: Value) -> Option<Value>
where
S: Into<borrow::Cow<'static, str>>,
{
self.indexes.insert(name.into(), val)
}

/// Used by increment and decrement tags
pub fn get_index<'a>(&'a self, name: &str) -> Option<&'a Value> {
self.indexes.get(name)
}

/// Sets a value in the global context.
Expand Down Expand Up @@ -255,6 +293,7 @@ impl<'g> ContextBuilder<'g> {
stack,
interrupt: InterruptState::default(),
cycles: CycleStateInner::default(),
ifchanged: IfChangedState::default(),
filters: self.filters,
}
}
Expand All @@ -273,6 +312,7 @@ pub struct Context<'g> {

interrupt: InterruptState,
cycles: CycleStateInner,
ifchanged: IfChangedState,

filters: sync::Arc<HashMap<&'static str, BoxedValueFilter>>,
}
Expand Down Expand Up @@ -311,6 +351,11 @@ impl<'g> Context<'g> {
CycleState { context: self }
}

/// Access the block's `IfChangedState`.
pub fn ifchanged(&mut self) -> &mut IfChangedState {
&mut self.ifchanged
}

/// Access the current `Stack`.
pub fn stack(&self) -> &Stack {
&self.stack
Expand Down
4 changes: 4 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,18 @@ impl ParserBuilder {
.tag("continue", tags::continue_tag as compiler::FnParseTag)
.tag("cycle", tags::cycle_tag as compiler::FnParseTag)
.tag("include", tags::include_tag as compiler::FnParseTag)
.tag("increment", tags::increment_tag as compiler::FnParseTag)
.tag("decrement", tags::decrement_tag as compiler::FnParseTag)
}

/// Register built-in Liquid blocks
pub fn liquid_blocks(self) -> Self {
self.block("raw", tags::raw_block as compiler::FnParseBlock)
.block("if", tags::if_block as compiler::FnParseBlock)
.block("unless", tags::unless_block as compiler::FnParseBlock)
.block("ifchanged", tags::ifchanged_block as compiler::FnParseBlock)
.block("for", tags::for_block as compiler::FnParseBlock)
.block("tablerow", tags::tablerow_block as compiler::FnParseBlock)
.block("comment", tags::comment_block as compiler::FnParseBlock)
.block("capture", tags::capture_block as compiler::FnParseBlock)
.block("case", tags::case_block as compiler::FnParseBlock)
Expand Down

0 comments on commit 1866073

Please sign in to comment.