agilitic-liquid 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ module Liquid
2
+
3
+ class Tag
4
+ attr_accessor :nodelist
5
+
6
+ def initialize(tag_name, markup, tokens)
7
+ @tag_name = tag_name
8
+ @markup = markup
9
+ parse(tokens)
10
+ end
11
+
12
+ def parse(tokens)
13
+ end
14
+
15
+ def name
16
+ self.class.name.downcase
17
+ end
18
+
19
+ def render(context)
20
+ ''
21
+ end
22
+ end
23
+
24
+
25
+ end
26
+
@@ -0,0 +1,33 @@
1
+ module Liquid
2
+
3
+ # Assign sets a variable in your template.
4
+ #
5
+ # {% assign foo = 'monkey' %}
6
+ #
7
+ # You can then use the variable later in the page.
8
+ #
9
+ # {{ monkey }}
10
+ #
11
+ class Assign < Tag
12
+ Syntax = /(#{VariableSignature}+)\s*=\s*(#{QuotedFragment}+)/
13
+
14
+ def initialize(tag_name, markup, tokens)
15
+ if markup =~ Syntax
16
+ @to = $1
17
+ @from = $2
18
+ else
19
+ raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]")
20
+ end
21
+
22
+ super
23
+ end
24
+
25
+ def render(context)
26
+ context.scopes.last[@to.to_s] = context[@from]
27
+ ''
28
+ end
29
+
30
+ end
31
+
32
+ Template.register_tag('assign', Assign)
33
+ end
@@ -0,0 +1,35 @@
1
+ module Liquid
2
+
3
+ # Capture stores the result of a block into a variable without rendering it inplace.
4
+ #
5
+ # {% capture heading %}
6
+ # Monkeys!
7
+ # {% endcapture %}
8
+ # ...
9
+ # <h1>{{ monkeys }}</h1>
10
+ #
11
+ # Capture is useful for saving content for use later in your template, such as
12
+ # in a sidebar or footer.
13
+ #
14
+ class Capture < Block
15
+ Syntax = /(\w+)/
16
+
17
+ def initialize(tag_name, markup, tokens)
18
+ if markup =~ Syntax
19
+ @to = $1
20
+ else
21
+ raise SyntaxError.new("Syntax Error in 'capture' - Valid syntax: capture [var]")
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ def render(context)
28
+ output = super
29
+ context[@to] = output.join
30
+ ''
31
+ end
32
+ end
33
+
34
+ Template.register_tag('capture', Capture)
35
+ end
@@ -0,0 +1,83 @@
1
+ module Liquid
2
+ class Case < Block
3
+ Syntax = /(#{QuotedFragment})/
4
+ WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/
5
+
6
+ def initialize(tag_name, markup, tokens)
7
+ @blocks = []
8
+
9
+ if markup =~ Syntax
10
+ @left = $1
11
+ else
12
+ raise SyntaxError.new("Syntax Error in tag 'case' - Valid syntax: case [condition]")
13
+ end
14
+
15
+ super
16
+ end
17
+
18
+ def unknown_tag(tag, markup, tokens)
19
+ @nodelist = []
20
+ case tag
21
+ when 'when'
22
+ record_when_condition(markup)
23
+ when 'else'
24
+ record_else_condition(markup)
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ def render(context)
31
+ context.stack do
32
+ execute_else_block = true
33
+
34
+ @blocks.inject([]) do |output, block|
35
+
36
+ if block.else?
37
+
38
+ return render_all(block.attachment, context) if execute_else_block
39
+
40
+ elsif block.evaluate(context)
41
+
42
+ execute_else_block = false
43
+ output += render_all(block.attachment, context)
44
+ end
45
+
46
+ output
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def record_when_condition(markup)
54
+ while markup
55
+ # Create a new nodelist and assign it to the new block
56
+ if not markup =~ WhenSyntax
57
+ raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ")
58
+ end
59
+
60
+ markup = $2
61
+
62
+ block = Condition.new(@left, '==', $1)
63
+ block.attach(@nodelist)
64
+ @blocks.push(block)
65
+ end
66
+ end
67
+
68
+ def record_else_condition(markup)
69
+
70
+ if not markup.strip.empty?
71
+ raise SyntaxError.new("Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) ")
72
+ end
73
+
74
+ block = ElseCondition.new
75
+ block.attach(@nodelist)
76
+ @blocks << block
77
+ end
78
+
79
+
80
+ end
81
+
82
+ Template.register_tag('case', Case)
83
+ end
@@ -0,0 +1,9 @@
1
+ module Liquid
2
+ class Comment < Block
3
+ def render(context)
4
+ ''
5
+ end
6
+ end
7
+
8
+ Template.register_tag('comment', Comment)
9
+ end
@@ -0,0 +1,59 @@
1
+ module Liquid
2
+
3
+ # Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
4
+ #
5
+ # {% for item in items %}
6
+ # <div class="{% cycle 'red', 'green', 'blue' %}"> {{ item }} </div>
7
+ # {% end %}
8
+ #
9
+ # <div class="red"> Item one </div>
10
+ # <div class="green"> Item two </div>
11
+ # <div class="blue"> Item three </div>
12
+ # <div class="red"> Item four </div>
13
+ # <div class="green"> Item five</div>
14
+ #
15
+ class Cycle < Tag
16
+ SimpleSyntax = /^#{QuotedFragment}+/
17
+ NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/
18
+
19
+ def initialize(tag_name, markup, tokens)
20
+ case markup
21
+ when NamedSyntax
22
+ @variables = variables_from_string($2)
23
+ @name = $1
24
+ when SimpleSyntax
25
+ @variables = variables_from_string(markup)
26
+ @name = "'#{@variables.to_s}'"
27
+ else
28
+ raise SyntaxError.new("Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]")
29
+ end
30
+ super
31
+ end
32
+
33
+ def render(context)
34
+ context.registers[:cycle] ||= Hash.new(0)
35
+
36
+ context.stack do
37
+ key = context[@name]
38
+ iteration = context.registers[:cycle][key]
39
+ result = context[@variables[iteration]]
40
+ iteration += 1
41
+ iteration = 0 if iteration >= @variables.size
42
+ context.registers[:cycle][key] = iteration
43
+ result
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def variables_from_string(markup)
50
+ markup.split(',').collect do |var|
51
+ var =~ /\s*(#{QuotedFragment})\s*/
52
+ $1 ? $1 : nil
53
+ end.compact
54
+ end
55
+
56
+ end
57
+
58
+ Template.register_tag('cycle', Cycle)
59
+ end
@@ -0,0 +1,136 @@
1
+ module Liquid
2
+
3
+ # "For" iterates over an array or collection.
4
+ # Several useful variables are available to you within the loop.
5
+ #
6
+ # == Basic usage:
7
+ # {% for item in collection %}
8
+ # {{ forloop.index }}: {{ item.name }}
9
+ # {% endfor %}
10
+ #
11
+ # == Advanced usage:
12
+ # {% for item in collection %}
13
+ # <div {% if forloop.first %}class="first"{% endif %}>
14
+ # Item {{ forloop.index }}: {{ item.name }}
15
+ # </div>
16
+ # {% endfor %}
17
+ #
18
+ # You can also define a limit and offset much like SQL. Remember
19
+ # that offset starts at 0 for the first item.
20
+ #
21
+ # {% for item in collection limit:5 offset:10 %}
22
+ # {{ item.name }}
23
+ # {% end %}
24
+ #
25
+ # To reverse the for loop simply use {% for item in collection reversed %}
26
+ #
27
+ # == Available variables:
28
+ #
29
+ # forloop.name:: 'item-collection'
30
+ # forloop.length:: Length of the loop
31
+ # forloop.index:: The current item's position in the collection;
32
+ # forloop.index starts at 1.
33
+ # This is helpful for non-programmers who start believe
34
+ # the first item in an array is 1, not 0.
35
+ # forloop.index0:: The current item's position in the collection
36
+ # where the first item is 0
37
+ # forloop.rindex:: Number of items remaining in the loop
38
+ # (length - index) where 1 is the last item.
39
+ # forloop.rindex0:: Number of items remaining in the loop
40
+ # where 0 is the last item.
41
+ # forloop.first:: Returns true if the item is the first item.
42
+ # forloop.last:: Returns true if the item is the last item.
43
+ #
44
+ class For < Block
45
+ Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/
46
+
47
+ def initialize(tag_name, markup, tokens)
48
+ if markup =~ Syntax
49
+ @variable_name = $1
50
+ @collection_name = $2
51
+ @name = "#{$1}-#{$2}"
52
+ @reversed = $3
53
+ @attributes = {}
54
+ markup.scan(TagAttributes) do |key, value|
55
+ @attributes[key] = value
56
+ end
57
+ else
58
+ raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]")
59
+ end
60
+
61
+ super
62
+ end
63
+
64
+ def render(context)
65
+ context.registers[:for] ||= Hash.new(0)
66
+
67
+ collection = context[@collection_name]
68
+ collection = collection.to_a if collection.is_a?(Range)
69
+
70
+ return '' unless collection.respond_to?(:each)
71
+
72
+ from = if @attributes['offset'] == 'continue'
73
+ context.registers[:for][@name].to_i
74
+ else
75
+ context[@attributes['offset']].to_i
76
+ end
77
+
78
+ limit = context[@attributes['limit']]
79
+ to = limit ? limit.to_i + from : nil
80
+
81
+
82
+ segment = slice_collection_using_each(collection, from, to)
83
+
84
+ return '' if segment.empty?
85
+
86
+ segment.reverse! if @reversed
87
+
88
+ result = []
89
+
90
+ length = segment.length
91
+
92
+ # Store our progress through the collection for the continue flag
93
+ context.registers[:for][@name] = from + segment.length
94
+
95
+ context.stack do
96
+ segment.each_with_index do |item, index|
97
+ context[@variable_name] = item
98
+ context['forloop'] = {
99
+ 'name' => @name,
100
+ 'length' => length,
101
+ 'index' => index + 1,
102
+ 'index0' => index,
103
+ 'rindex' => length - index,
104
+ 'rindex0' => length - index -1,
105
+ 'first' => (index == 0),
106
+ 'last' => (index == length - 1) }
107
+
108
+ result << render_all(@nodelist, context)
109
+ end
110
+ end
111
+ result
112
+ end
113
+
114
+ def slice_collection_using_each(collection, from, to)
115
+ segments = []
116
+ index = 0
117
+ yielded = 0
118
+ collection.each do |item|
119
+
120
+ if to && to <= index
121
+ break
122
+ end
123
+
124
+ if from <= index
125
+ segments << item
126
+ end
127
+
128
+ index += 1
129
+ end
130
+
131
+ segments
132
+ end
133
+ end
134
+
135
+ Template.register_tag('for', For)
136
+ end
@@ -0,0 +1,79 @@
1
+ module Liquid
2
+
3
+ # If is the conditional block
4
+ #
5
+ # {% if user.admin %}
6
+ # Admin user!
7
+ # {% else %}
8
+ # Not admin user
9
+ # {% endif %}
10
+ #
11
+ # There are {% if count < 5 %} less {% else %} more {% endif %} items than you need.
12
+ #
13
+ #
14
+ class If < Block
15
+ SyntaxHelp = "Syntax Error in tag 'if' - Valid syntax: if [expression]"
16
+ Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/
17
+
18
+ def initialize(tag_name, markup, tokens)
19
+
20
+ @blocks = []
21
+
22
+ push_block('if', markup)
23
+
24
+ super
25
+ end
26
+
27
+ def unknown_tag(tag, markup, tokens)
28
+ if ['elsif', 'else'].include?(tag)
29
+ push_block(tag, markup)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def render(context)
36
+ context.stack do
37
+ @blocks.each do |block|
38
+ if block.evaluate(context)
39
+ return render_all(block.attachment, context)
40
+ end
41
+ end
42
+ ''
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def push_block(tag, markup)
49
+ block = if tag == 'else'
50
+ ElseCondition.new
51
+ else
52
+
53
+ expressions = markup.split(/\b(and|or)\b/).reverse
54
+ raise(SyntaxError, SyntaxHelp) unless expressions.shift =~ Syntax
55
+
56
+ condition = Condition.new($1, $2, $3)
57
+
58
+ while not expressions.empty?
59
+ operator = expressions.shift
60
+
61
+ raise(SyntaxError, SyntaxHelp) unless expressions.shift.to_s =~ Syntax
62
+
63
+ new_condition = Condition.new($1, $2, $3)
64
+ new_condition.send(operator.to_sym, condition)
65
+ condition = new_condition
66
+ end
67
+
68
+ condition
69
+ end
70
+
71
+ @blocks.push(block)
72
+ @nodelist = block.attach(Array.new)
73
+ end
74
+
75
+
76
+ end
77
+
78
+ Template.register_tag('if', If)
79
+ end