mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
Merge branch 'master' into dont_render_blank_blocks
Conflicts: lib/liquid/tags/cycle.rb lib/liquid/tags/increment.rb
This commit is contained in:
@@ -2,15 +2,15 @@
|
||||
# and use liquid as an template system for .liquid files
|
||||
#
|
||||
# Example
|
||||
#
|
||||
#
|
||||
# ActionView::Base::register_template_handler :liquid, LiquidView
|
||||
class LiquidView
|
||||
PROTECTED_ASSIGNS = %w( template_root response _session template_class action_name request_origin session template
|
||||
_response url _request _cookies variables_added _flash params _headers request cookies
|
||||
ignore_missing_templates flash _params logger before_filter_chain_aborted headers )
|
||||
PROTECTED_INSTANCE_VARIABLES = %w( @_request @controller @_first_render @_memoized__pick_template @view_paths
|
||||
PROTECTED_INSTANCE_VARIABLES = %w( @_request @controller @_first_render @_memoized__pick_template @view_paths
|
||||
@helpers @assigns_added @template @_render_stack @template_format @assigns )
|
||||
|
||||
|
||||
def self.call(template)
|
||||
"LiquidView.new(self).render(template, local_assigns)"
|
||||
end
|
||||
@@ -18,10 +18,10 @@ class LiquidView
|
||||
def initialize(view)
|
||||
@view = view
|
||||
end
|
||||
|
||||
|
||||
def render(template, local_assigns = nil)
|
||||
@view.controller.headers["Content-Type"] ||= 'text/html; charset=utf-8'
|
||||
|
||||
|
||||
# Rails 2.2 Template has source, but not locals
|
||||
if template.respond_to?(:source) && !template.respond_to?(:locals)
|
||||
assigns = (@view.instance_variables - PROTECTED_INSTANCE_VARIABLES).inject({}) do |hash, ivar|
|
||||
@@ -31,15 +31,15 @@ class LiquidView
|
||||
else
|
||||
assigns = @view.assigns.reject{ |k,v| PROTECTED_ASSIGNS.include?(k) }
|
||||
end
|
||||
|
||||
|
||||
source = template.respond_to?(:source) ? template.source : template
|
||||
local_assigns = (template.respond_to?(:locals) ? template.locals : local_assigns) || {}
|
||||
|
||||
|
||||
if content_for_layout = @view.instance_variable_get("@content_for_layout")
|
||||
assigns['content_for_layout'] = content_for_layout
|
||||
end
|
||||
assigns.merge!(local_assigns.stringify_keys)
|
||||
|
||||
|
||||
liquid = Liquid::Template.parse(source)
|
||||
liquid.render(assigns, :filters => [@view.controller.master_helper_module], :registers => {:action_view => @view, :controller => @view.controller})
|
||||
end
|
||||
@@ -48,4 +48,4 @@ class LiquidView
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ module Liquid
|
||||
|
||||
begin
|
||||
# If we get an Interrupt that means the block must stop processing. An
|
||||
# Interrupt is any command that stops block execution such as {% break %}
|
||||
# Interrupt is any command that stops block execution such as {% break %}
|
||||
# or {% continue %}
|
||||
if token.is_a? Continue or token.is_a? Break
|
||||
context.push_interrupt(token.interrupt)
|
||||
|
||||
+11
-11
@@ -1,7 +1,7 @@
|
||||
module Liquid
|
||||
# A Liquid file system is way to let your templates retrieve other templates for use with the include tag.
|
||||
#
|
||||
# You can implement subclasses that retrieve templates from the database, from the file system using a different
|
||||
# You can implement subclasses that retrieve templates from the database, from the file system using a different
|
||||
# path structure, you can provide them as hard-coded inline strings, or any manner that you see fit.
|
||||
#
|
||||
# You can add additional instance variables, arguments, or methods as needed.
|
||||
@@ -18,7 +18,7 @@ module Liquid
|
||||
raise FileSystemError, "This liquid context does not allow includes."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# This implements an abstract file system which retrieves template files named in a manner similar to Rails partials,
|
||||
# ie. with the template name prefixed with an underscore. The extension ".liquid" is also added.
|
||||
#
|
||||
@@ -27,36 +27,36 @@ module Liquid
|
||||
# Example:
|
||||
#
|
||||
# file_system = Liquid::LocalFileSystem.new("/some/path")
|
||||
#
|
||||
#
|
||||
# file_system.full_path("mypartial") # => "/some/path/_mypartial.liquid"
|
||||
# file_system.full_path("dir/mypartial") # => "/some/path/dir/_mypartial.liquid"
|
||||
#
|
||||
class LocalFileSystem
|
||||
attr_accessor :root
|
||||
|
||||
|
||||
def initialize(root)
|
||||
@root = root
|
||||
end
|
||||
|
||||
|
||||
def read_template_file(template_path, context)
|
||||
full_path = full_path(template_path)
|
||||
raise FileSystemError, "No such template '#{template_path}'" unless File.exists?(full_path)
|
||||
|
||||
|
||||
File.read(full_path)
|
||||
end
|
||||
|
||||
|
||||
def full_path(template_path)
|
||||
raise FileSystemError, "Illegal template name '#{template_path}'" unless template_path =~ /^[^.\/][a-zA-Z0-9_\/]+$/
|
||||
|
||||
|
||||
full_path = if template_path.include?('/')
|
||||
File.join(root, File.dirname(template_path), "_#{File.basename(template_path)}.liquid")
|
||||
else
|
||||
File.join(root, "_#{template_path}.liquid")
|
||||
end
|
||||
|
||||
|
||||
raise FileSystemError, "Illegal template path '#{File.expand_path(full_path)}'" unless File.expand_path(full_path) =~ /^#{File.expand_path(root)}/
|
||||
|
||||
|
||||
full_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+10
-10
@@ -10,26 +10,26 @@ module Liquid
|
||||
#
|
||||
class Assign < Tag
|
||||
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/o
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
if markup =~ Syntax
|
||||
@to = $1
|
||||
@from = Variable.new($2)
|
||||
else
|
||||
raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]")
|
||||
end
|
||||
|
||||
super
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
def render(context)
|
||||
val = @from.render(context)
|
||||
context.scopes.last[@to] = val
|
||||
context.resource_limits[:assign_score_current] += (val.respond_to?(:length) ? val.length : 1)
|
||||
''
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Template.register_tag('assign', Assign)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Template.register_tag('assign', Assign)
|
||||
end
|
||||
|
||||
@@ -8,8 +8,8 @@ module Liquid
|
||||
# {% break %}
|
||||
# {% endif %}
|
||||
# {% endfor %}
|
||||
#
|
||||
class Break < Tag
|
||||
#
|
||||
class Break < Tag
|
||||
|
||||
def interrupt
|
||||
BreakInterrupt.new
|
||||
|
||||
+33
-33
@@ -3,15 +3,15 @@ module Liquid
|
||||
Syntax = /(#{QuotedFragment})/o
|
||||
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/o
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
def initialize(tag_name, markup, tokens)
|
||||
@blocks = []
|
||||
|
||||
|
||||
if markup =~ Syntax
|
||||
@left = $1
|
||||
else
|
||||
raise SyntaxError.new("Syntax Error in tag 'case' - Valid syntax: case [condition]")
|
||||
end
|
||||
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
@@ -27,53 +27,53 @@ module Liquid
|
||||
end
|
||||
end
|
||||
|
||||
def render(context)
|
||||
context.stack do
|
||||
def render(context)
|
||||
context.stack do
|
||||
execute_else_block = true
|
||||
|
||||
|
||||
output = ''
|
||||
@blocks.each do |block|
|
||||
if block.else?
|
||||
if block.else?
|
||||
return render_all(block.attachment, context) if execute_else_block
|
||||
elsif block.evaluate(context)
|
||||
execute_else_block = false
|
||||
execute_else_block = false
|
||||
output << render_all(block.attachment, context)
|
||||
end
|
||||
end
|
||||
end
|
||||
output
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def record_when_condition(markup)
|
||||
while markup
|
||||
# Create a new nodelist and assign it to the new block
|
||||
if not markup =~ WhenSyntax
|
||||
raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ")
|
||||
end
|
||||
|
||||
markup = $2
|
||||
|
||||
block = Condition.new(@left, '==', $1)
|
||||
block.attach(@nodelist)
|
||||
@blocks.push(block)
|
||||
end
|
||||
end
|
||||
|
||||
def record_else_condition(markup)
|
||||
private
|
||||
|
||||
def record_when_condition(markup)
|
||||
while markup
|
||||
# Create a new nodelist and assign it to the new block
|
||||
if not markup =~ WhenSyntax
|
||||
raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ")
|
||||
end
|
||||
|
||||
markup = $2
|
||||
|
||||
block = Condition.new(@left, '==', $1)
|
||||
block.attach(@nodelist)
|
||||
@blocks.push(block)
|
||||
end
|
||||
end
|
||||
|
||||
def record_else_condition(markup)
|
||||
|
||||
if not markup.strip.empty?
|
||||
raise SyntaxError.new("Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) ")
|
||||
end
|
||||
|
||||
block = ElseCondition.new
|
||||
|
||||
block = ElseCondition.new
|
||||
block.attach(@nodelist)
|
||||
@blocks << block
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
Template.register_tag('case', Case)
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ module Liquid
|
||||
# {% continue %}
|
||||
# {% endif %}
|
||||
# {% endfor %}
|
||||
#
|
||||
#
|
||||
class Continue < Tag
|
||||
|
||||
def interrupt
|
||||
|
||||
+17
-20
@@ -1,5 +1,4 @@
|
||||
module Liquid
|
||||
|
||||
# Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
|
||||
#
|
||||
# {% for item in items %}
|
||||
@@ -15,32 +14,32 @@ module Liquid
|
||||
class Cycle < Tag
|
||||
SimpleSyntax = /^#{QuotedFragment}+/o
|
||||
NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/o
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
case markup
|
||||
when NamedSyntax
|
||||
@variables = variables_from_string($2)
|
||||
@name = $1
|
||||
@variables = variables_from_string($2)
|
||||
@name = $1
|
||||
when SimpleSyntax
|
||||
@variables = variables_from_string(markup)
|
||||
@name = "'#{@variables.to_s}'"
|
||||
@name = "'#{@variables.to_s}'"
|
||||
else
|
||||
raise SyntaxError.new("Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]")
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
context.registers[:cycle] ||= Hash.new(0)
|
||||
|
||||
|
||||
context.stack do
|
||||
key = context[@name]
|
||||
key = context[@name]
|
||||
iteration = context.registers[:cycle][key]
|
||||
result = context[@variables[iteration]]
|
||||
iteration += 1
|
||||
iteration = 0 if iteration >= @variables.size
|
||||
iteration += 1
|
||||
iteration = 0 if iteration >= @variables.size
|
||||
context.registers[:cycle][key] = iteration
|
||||
result
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
@@ -49,15 +48,13 @@ module Liquid
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def variables_from_string(markup)
|
||||
markup.split(',').collect do |var|
|
||||
var =~ /\s*(#{QuotedFragment})\s*/o
|
||||
$1 ? $1 : nil
|
||||
end.compact
|
||||
var =~ /\s*(#{QuotedFragment})\s*/o
|
||||
$1 ? $1 : nil
|
||||
end.compact
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
Template.register_tag('cycle', Cycle)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module Liquid
|
||||
|
||||
|
||||
# decrement is used in a place where one needs to insert a counter
|
||||
# into a template, and needs the counter to survive across
|
||||
# multiple instantiations of the template.
|
||||
@@ -19,21 +19,21 @@ module Liquid
|
||||
# Hello: -3
|
||||
#
|
||||
class Decrement < Tag
|
||||
def initialize(tag_name, markup, tokens)
|
||||
def initialize(tag_name, markup, tokens)
|
||||
@variable = markup.strip
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
value = context.environments.first[@variable] ||= 0
|
||||
value = value - 1
|
||||
context.environments.first[@variable] = value
|
||||
value.to_s
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
end
|
||||
|
||||
|
||||
Template.register_tag('decrement', Decrement)
|
||||
end
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
module Liquid
|
||||
class Ifchanged < Block
|
||||
|
||||
|
||||
def render(context)
|
||||
context.stack do
|
||||
|
||||
context.stack do
|
||||
|
||||
output = render_all(@nodelist, context)
|
||||
|
||||
|
||||
if output != context.registers[:ifchanged]
|
||||
context.registers[:ifchanged] = output
|
||||
output
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Template.register_tag('ifchanged', Ifchanged)
|
||||
end
|
||||
end
|
||||
|
||||
Template.register_tag('ifchanged', Ifchanged)
|
||||
end
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
module Liquid
|
||||
|
||||
# increment is used in a place where one needs to insert a counter
|
||||
# into a template, and needs the counter to survive across
|
||||
# multiple instantiations of the template.
|
||||
# (To achieve the survival, the application must keep the context)
|
||||
#
|
||||
# if the variable does not exist, it is created with value 0.
|
||||
|
||||
#
|
||||
# Hello: {% increment variable %}
|
||||
#
|
||||
# gives you:
|
||||
@@ -16,22 +15,21 @@ module Liquid
|
||||
# Hello: 2
|
||||
#
|
||||
class Increment < Tag
|
||||
def initialize(tag_name, markup, tokens)
|
||||
def initialize(tag_name, markup, tokens)
|
||||
@variable = markup.strip
|
||||
super
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
value = context.environments.first[@variable] ||= 0
|
||||
context.environments.first[@variable] = value + 1
|
||||
value.to_s
|
||||
end
|
||||
|
||||
|
||||
def blank?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Template.register_tag('increment', Increment)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user