diff --git a/example/server/example_servlet.rb b/example/server/example_servlet.rb
index d2d4fd6a..e9d024d0 100644
--- a/example/server/example_servlet.rb
+++ b/example/server/example_servlet.rb
@@ -27,6 +27,15 @@ class Servlet < LiquidServlet
{ 'products' => products_list, 'more_products' => more_products_list, 'description' => description, 'section' => 'Snowboards', 'cool_products' => true }
end
+ def settings
+ {
+ 'settings' => {
+ 'text' => 'Liquid',
+ 'font' => 'Arial'
+ }
+ }
+ end
+
private
def products_list
diff --git a/example/server/templates/ico.liquid b/example/server/templates/ico.liquid
new file mode 100644
index 00000000..e69de29b
diff --git a/example/server/templates/settings.liquid b/example/server/templates/settings.liquid
new file mode 100644
index 00000000..e7c0cd62
--- /dev/null
+++ b/example/server/templates/settings.liquid
@@ -0,0 +1,121 @@
+
+
+
let
+
+
+
+
+
+
Liquid source
+
+{%- raw -%}
+{% assign text = "My text" %}
+{{ settings }}
+{{ text }}
+{%- endraw -%}
+
+
+
+
HTML output
+
+{% assign text = "My text" %}
+{{ settings }}
+{{ text -}}
+
+
+
+
+
+
+
Liquid source
+
+ {%- raw -%}
+{% let (text, font): settings %}
+ text: {{ text }},
+ font: {{ font }}
+{% endlet %}
+ {%- endraw -%}
+
+
+
+
HTML output
+
+{%- let (text, font): settings %}
+ text: {{ text }},
+ font: {{ font }}
+{% endlet -%}
+
+
+
+
+
+
+
Liquid source
+
+ {%- raw -%}
+{% let font: settings.font %}
+ text: {{ text }},
+ font: {{ font }}
+{% endlet %}
+ {%- endraw -%}
+
+
+
+
HTML output
+
+{%- let font: settings.font %}
+ text: {{ text }},
+ font: {{ font }}
+{% endlet -%}
+
+
+
+
+
+
+
Liquid source
+
+ {%- raw -%}
+Global is not impacted:
+ - text: {{ text }},
+ - font: {{ font }}
+ {%- endraw -%}
+
+
+
+
HTML output
+
+Global is not impacted:
+ - text: {{ text }},
+ - font: {{ font }}
+
+
+
diff --git a/lib/liquid/tags.rb b/lib/liquid/tags.rb
index 916a63bd..f8808813 100644
--- a/lib/liquid/tags.rb
+++ b/lib/liquid/tags.rb
@@ -1,24 +1,25 @@
# frozen_string_literal: true
-require_relative "tags/table_row"
-require_relative "tags/echo"
-require_relative "tags/if"
-require_relative "tags/break"
-require_relative "tags/inline_comment"
-require_relative "tags/for"
-require_relative "tags/assign"
-require_relative "tags/ifchanged"
-require_relative "tags/case"
-require_relative "tags/include"
-require_relative "tags/continue"
-require_relative "tags/capture"
-require_relative "tags/decrement"
-require_relative "tags/unless"
-require_relative "tags/increment"
-require_relative "tags/comment"
-require_relative "tags/raw"
-require_relative "tags/render"
-require_relative "tags/cycle"
+require_relative 'tags/table_row'
+require_relative 'tags/echo'
+require_relative 'tags/if'
+require_relative 'tags/break'
+require_relative 'tags/inline_comment'
+require_relative 'tags/for'
+require_relative 'tags/assign'
+require_relative 'tags/ifchanged'
+require_relative 'tags/case'
+require_relative 'tags/include'
+require_relative 'tags/continue'
+require_relative 'tags/capture'
+require_relative 'tags/decrement'
+require_relative 'tags/unless'
+require_relative 'tags/increment'
+require_relative 'tags/comment'
+require_relative 'tags/raw'
+require_relative 'tags/render'
+require_relative 'tags/cycle'
+require_relative 'tags/let'
module Liquid
module Tags
@@ -42,6 +43,7 @@ module Liquid
'if' => If,
'echo' => Echo,
'tablerow' => TableRow,
+ 'let' => Let,
}.freeze
end
end
diff --git a/lib/liquid/tags/let.rb b/lib/liquid/tags/let.rb
new file mode 100644
index 00000000..26059a53
--- /dev/null
+++ b/lib/liquid/tags/let.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Liquid
+ class Let < Liquid::Block
+ MULTI_ASSIGNMENT = /\A\(\s*(?[^)]+)\s*\):\s*(?[^\s]+)\z/
+ VAR_ASSIGNMENTS = /(?[\w-]+)\s*:\s*(?[^\s,]+)/
+
+ def initialize(tag_name, markup, options)
+ super(tag_name, markup, options)
+ @assignments = parse_markup(markup.strip)
+ end
+
+ def render(context)
+ subcontext = context.new_isolated_subcontext
+
+ @assignments.each do |var, expression|
+ subcontext[var] = lookup(context, expression)
+ end
+
+ super(subcontext)
+ end
+
+ private
+
+ def parse_markup(markup)
+ if (m = MULTI_ASSIGNMENT.match(markup))
+ variables = m[:vars].split(/\s*,\s*/)
+ source = m[:source]
+ variables.map { |v| [v, "#{source}.#{v}"] }.to_h
+ else
+ markup.scan(VAR_ASSIGNMENTS).to_h
+ end
+ end
+
+ def lookup(context, expression)
+ variable_lookup = Liquid::VariableLookup.new(expression)
+ variable_lookup.evaluate(context)
+ end
+ end
+end