liquor 0.1.1 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -9
- data/Gemfile +7 -0
- data/Guardfile +11 -0
- data/MIT-LICENSE +6 -2
- data/README.md +4 -122
- data/Rakefile +20 -23
- data/doc/language-spec.html +768 -0
- data/doc/language-spec.md +698 -0
- data/lib/liquor.rb +39 -68
- data/lib/liquor/ast_tools.rb +28 -0
- data/lib/liquor/compiler.rb +110 -0
- data/lib/liquor/context.rb +76 -254
- data/lib/liquor/diagnostics.rb +151 -0
- data/lib/liquor/drop/drop.rb +168 -0
- data/lib/liquor/drop/drop_delegation.rb +24 -0
- data/lib/liquor/drop/drop_scope.rb +118 -0
- data/lib/liquor/drop/dropable.rb +17 -0
- data/lib/liquor/emitter.rb +313 -0
- data/lib/liquor/extensions/kaminari.rb +14 -0
- data/lib/liquor/extensions/pagination.rb +235 -0
- data/lib/liquor/extensions/rails.rb +97 -0
- data/lib/liquor/extensions/thinking_sphinx.rb +14 -0
- data/lib/liquor/extensions/tire.rb +30 -0
- data/lib/liquor/external.rb +79 -0
- data/lib/liquor/function.rb +94 -0
- data/lib/liquor/grammar/lexer.rb +1223 -0
- data/lib/liquor/grammar/lexer.rl +297 -0
- data/lib/liquor/grammar/parser.racc +288 -0
- data/lib/liquor/grammar/parser.rb +885 -0
- data/lib/liquor/library.rb +41 -0
- data/lib/liquor/manager.rb +146 -0
- data/lib/liquor/runtime.rb +167 -0
- data/lib/liquor/stdlib/builtin_functions.rb +315 -0
- data/lib/liquor/stdlib/builtin_tags.rb +228 -0
- data/lib/liquor/stdlib/html_truncater.rb +162 -0
- data/lib/liquor/stdlib/partial_tags.rb +76 -0
- data/lib/liquor/tag.rb +83 -14
- data/lib/liquor/version.rb +1 -1
- data/liquor.gemspec +29 -6
- data/spec/builtins_spec.rb +264 -0
- data/spec/compiler_spec.rb +136 -0
- data/spec/context_spec.rb +49 -0
- data/spec/drop_delegation_spec.rb +21 -0
- data/spec/drop_spec.rb +222 -0
- data/spec/errors_spec.rb +40 -0
- data/spec/external_spec.rb +207 -0
- data/spec/function_spec.rb +80 -0
- data/spec/lexer_spec.rb +173 -0
- data/spec/library_spec.rb +18 -0
- data/spec/manager_spec.rb +84 -0
- data/spec/parser_spec.rb +381 -0
- data/spec/partials_spec.rb +74 -0
- data/spec/runtime_spec.rb +97 -0
- data/spec/spec_helper.rb +94 -0
- data/spec/tag_spec.rb +7 -0
- metadata +216 -173
- data/AUTHORS +0 -2
- data/CHANGELOG +0 -48
- data/Gemfile.lock +0 -91
- data/History.txt +0 -44
- data/LICENSE +0 -23
- data/example/server/example_servlet.rb +0 -37
- data/example/server/liquid_servlet.rb +0 -28
- data/example/server/liquor_servlet.rb +0 -28
- data/example/server/server.rb +0 -12
- data/example/server/templates/index.liquid +0 -6
- data/example/server/templates/index.liquor +0 -6
- data/example/server/templates/products.liquid +0 -45
- data/example/server/templates/products.liquor +0 -45
- data/init.rb +0 -8
- data/lib/extras/liquid_view.rb +0 -51
- data/lib/extras/liquor_view.rb +0 -51
- data/lib/liquor/block.rb +0 -101
- data/lib/liquor/condition.rb +0 -120
- data/lib/liquor/document.rb +0 -17
- data/lib/liquor/drop.rb +0 -256
- data/lib/liquor/errors.rb +0 -11
- data/lib/liquor/extensions.rb +0 -72
- data/lib/liquor/file_system.rb +0 -62
- data/lib/liquor/htmltags.rb +0 -74
- data/lib/liquor/module_ex.rb +0 -60
- data/lib/liquor/standardfilters.rb +0 -315
- data/lib/liquor/strainer.rb +0 -58
- data/lib/liquor/tags/assign.rb +0 -33
- data/lib/liquor/tags/capture.rb +0 -35
- data/lib/liquor/tags/case.rb +0 -83
- data/lib/liquor/tags/comment.rb +0 -9
- data/lib/liquor/tags/content_for.rb +0 -54
- data/lib/liquor/tags/cycle.rb +0 -59
- data/lib/liquor/tags/for.rb +0 -136
- data/lib/liquor/tags/if.rb +0 -80
- data/lib/liquor/tags/ifchanged.rb +0 -20
- data/lib/liquor/tags/include.rb +0 -56
- data/lib/liquor/tags/unless.rb +0 -33
- data/lib/liquor/tags/yield.rb +0 -49
- data/lib/liquor/template.rb +0 -181
- data/lib/liquor/variable.rb +0 -52
- data/performance/shopify.rb +0 -92
- data/performance/shopify/comment_form.rb +0 -33
- data/performance/shopify/database.rb +0 -45
- data/performance/shopify/json_filter.rb +0 -7
- data/performance/shopify/liquid.rb +0 -18
- data/performance/shopify/liquor.rb +0 -18
- data/performance/shopify/money_filter.rb +0 -18
- data/performance/shopify/paginate.rb +0 -93
- data/performance/shopify/shop_filter.rb +0 -98
- data/performance/shopify/tag_filter.rb +0 -25
- data/performance/shopify/vision.database.yml +0 -945
- data/performance/shopify/weight_filter.rb +0 -11
- data/performance/tests/dropify/article.liquid +0 -74
- data/performance/tests/dropify/blog.liquid +0 -33
- data/performance/tests/dropify/cart.liquid +0 -66
- data/performance/tests/dropify/collection.liquid +0 -22
- data/performance/tests/dropify/index.liquid +0 -47
- data/performance/tests/dropify/page.liquid +0 -8
- data/performance/tests/dropify/product.liquid +0 -68
- data/performance/tests/dropify/theme.liquid +0 -105
- data/performance/tests/ripen/article.liquid +0 -74
- data/performance/tests/ripen/blog.liquid +0 -13
- data/performance/tests/ripen/cart.liquid +0 -54
- data/performance/tests/ripen/collection.liquid +0 -29
- data/performance/tests/ripen/index.liquid +0 -32
- data/performance/tests/ripen/page.liquid +0 -4
- data/performance/tests/ripen/product.liquid +0 -75
- data/performance/tests/ripen/theme.liquid +0 -85
- data/performance/tests/tribble/404.liquid +0 -56
- data/performance/tests/tribble/article.liquid +0 -98
- data/performance/tests/tribble/blog.liquid +0 -41
- data/performance/tests/tribble/cart.liquid +0 -134
- data/performance/tests/tribble/collection.liquid +0 -70
- data/performance/tests/tribble/index.liquid +0 -94
- data/performance/tests/tribble/page.liquid +0 -56
- data/performance/tests/tribble/product.liquid +0 -116
- data/performance/tests/tribble/search.liquid +0 -51
- data/performance/tests/tribble/theme.liquid +0 -90
- data/performance/tests/vogue/article.liquid +0 -66
- data/performance/tests/vogue/blog.liquid +0 -32
- data/performance/tests/vogue/cart.liquid +0 -58
- data/performance/tests/vogue/collection.liquid +0 -19
- data/performance/tests/vogue/index.liquid +0 -22
- data/performance/tests/vogue/page.liquid +0 -3
- data/performance/tests/vogue/product.liquid +0 -62
- data/performance/tests/vogue/theme.liquid +0 -122
- data/test/assign_test.rb +0 -11
- data/test/block_test.rb +0 -58
- data/test/capture_test.rb +0 -41
- data/test/condition_test.rb +0 -115
- data/test/content_for_test.rb +0 -15
- data/test/context_test.rb +0 -479
- data/test/drop_test.rb +0 -162
- data/test/error_handling_test.rb +0 -89
- data/test/extra/breakpoint.rb +0 -547
- data/test/extra/caller.rb +0 -80
- data/test/file_system_test.rb +0 -30
- data/test/filter_test.rb +0 -147
- data/test/helper.rb +0 -24
- data/test/html_tag_test.rb +0 -31
- data/test/if_else_test.rb +0 -139
- data/test/include_tag_test.rb +0 -129
- data/test/module_ex_test.rb +0 -89
- data/test/output_test.rb +0 -121
- data/test/parsing_quirks_test.rb +0 -54
- data/test/regexp_test.rb +0 -45
- data/test/security_test.rb +0 -41
- data/test/standard_filter_test.rb +0 -170
- data/test/standard_tag_test.rb +0 -405
- data/test/statements_test.rb +0 -137
- data/test/strainer_test.rb +0 -27
- data/test/template_test.rb +0 -82
- data/test/test_helper.rb +0 -28
- data/test/unless_else_test.rb +0 -27
- data/test/variable_test.rb +0 -173
- data/test/yield_test.rb +0 -24
@@ -0,0 +1,228 @@
|
|
1
|
+
module Liquor
|
2
|
+
module Builtins
|
3
|
+
include Library
|
4
|
+
|
5
|
+
tag "declare" do |emit, context, node|
|
6
|
+
arg, kw = check_args node,
|
7
|
+
:ident,
|
8
|
+
:"=" => :expr
|
9
|
+
|
10
|
+
var_name, = nvalue(arg)
|
11
|
+
expr = kw[:"="]
|
12
|
+
|
13
|
+
expr_result = emit.expr(expr)
|
14
|
+
|
15
|
+
context.declare var_name, nloc(arg)
|
16
|
+
emit.out! %Q|#{context.access(var_name)} = #{expr_result}\n|
|
17
|
+
end
|
18
|
+
|
19
|
+
tag "assign" do |emit, context, node|
|
20
|
+
arg, kw = check_args node,
|
21
|
+
:ident,
|
22
|
+
:"=" => :expr
|
23
|
+
|
24
|
+
var_name, = nvalue(arg)
|
25
|
+
expr = kw[:"="]
|
26
|
+
|
27
|
+
expr_result = emit.expr(expr)
|
28
|
+
|
29
|
+
unless context.variable? var_name
|
30
|
+
context.declare var_name, nloc(arg)
|
31
|
+
end
|
32
|
+
|
33
|
+
emit.out! %Q|#{context.access(var_name)} = #{expr_result}\n|
|
34
|
+
end
|
35
|
+
|
36
|
+
class ForLoop
|
37
|
+
include Liquor::External
|
38
|
+
|
39
|
+
def initialize(length)
|
40
|
+
@length = length
|
41
|
+
@index = 0
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :length
|
45
|
+
attr_accessor :index
|
46
|
+
|
47
|
+
def next!
|
48
|
+
@index += 1
|
49
|
+
end
|
50
|
+
|
51
|
+
def rindex
|
52
|
+
@length - @index - 1
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_first
|
56
|
+
@index == 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_last
|
60
|
+
@index == @length - 1
|
61
|
+
end
|
62
|
+
|
63
|
+
export :length, :index, :rindex, :is_first, :is_last
|
64
|
+
end
|
65
|
+
|
66
|
+
tag "for" do |emit, context, node|
|
67
|
+
name, arg, *kwargs = nvalue(node)
|
68
|
+
|
69
|
+
if kwargs.empty?
|
70
|
+
raise SyntaxError.new("unexpected end of tag, expecting one of: `in:', `from:'.", nloc(node))
|
71
|
+
elsif kwname(kwargs[0]) == 'in'
|
72
|
+
arg, kw = check_args node,
|
73
|
+
:ident,
|
74
|
+
:in => :expr,
|
75
|
+
:do => :block
|
76
|
+
elsif kwname(kwargs[0]) == 'from'
|
77
|
+
arg, kw = check_args node,
|
78
|
+
:ident,
|
79
|
+
:from => :expr,
|
80
|
+
:to => :expr,
|
81
|
+
:do => :block
|
82
|
+
else
|
83
|
+
raise SyntaxError.new("unexpected `#{kwname(kwargs[0])}:', expecting one of: `in:', `from:'.", nloc(kwargs[0]))
|
84
|
+
end
|
85
|
+
|
86
|
+
var_name, = nvalue(arg)
|
87
|
+
indexer_name = "#{var_name}_loop"
|
88
|
+
|
89
|
+
context.nest do
|
90
|
+
if kw[:in]
|
91
|
+
indexer = %{Liquor::Builtins::ForLoop.new(#{emit.check_tuple(kw[:in])}.size)}
|
92
|
+
seq = emit.check_tuple(kw[:in])
|
93
|
+
elsif kw[:from]
|
94
|
+
indexer = %{Liquor::Builtins::ForLoop.new(#{emit.check_integer(kw[:to])} - #{emit.check_integer(kw[:from])})}
|
95
|
+
from, to = emit.check_integer(kw[:from]), emit.check_integer(kw[:to])
|
96
|
+
end
|
97
|
+
|
98
|
+
context.declare var_name, nloc(arg)
|
99
|
+
context.declare indexer_name
|
100
|
+
|
101
|
+
if kw[:in]
|
102
|
+
emit.out! %Q|#{context.access indexer_name} = #{indexer}\n|
|
103
|
+
emit.out! %Q|for #{context.access(var_name)} in #{seq}\n|
|
104
|
+
elsif kw[:from]
|
105
|
+
emit.out! %Q|#{context.access indexer_name} = #{indexer}\n|
|
106
|
+
emit.out! %Q<#{from}.upto(#{to}) do |#{context.access(var_name)}|\n>
|
107
|
+
end
|
108
|
+
|
109
|
+
emit.compile_block kw[:do]
|
110
|
+
|
111
|
+
emit.out! %Q|#{context.access indexer_name}.next!\n|
|
112
|
+
emit.out! %Q|end\n|
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
tag "if", continuations: %w(elsif) do |emit, context, node|
|
117
|
+
tag_name, arg, *kwargs = nvalue(node)
|
118
|
+
|
119
|
+
state = :begin
|
120
|
+
while state
|
121
|
+
case state
|
122
|
+
when :begin
|
123
|
+
if arg.nil?
|
124
|
+
if kwargs.empty?
|
125
|
+
raise SyntaxError.new("unexpected end of tag, expecting `expression'", nloc(node))
|
126
|
+
else
|
127
|
+
raise SyntaxError.new("unexpected `#{kwname(kwargs[0])}:', expecting `expression'", nloc(kwargs[0]))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
emit.out! %Q|if #{emit.convert_boolean(arg)}\n|
|
132
|
+
state = :then
|
133
|
+
|
134
|
+
when :elsif
|
135
|
+
kwarg = kwargs.shift
|
136
|
+
|
137
|
+
if kwarg.nil?
|
138
|
+
state = nil
|
139
|
+
elsif kwname(kwarg) == 'elsif'
|
140
|
+
check_arg_type(kwarg, :expr)
|
141
|
+
|
142
|
+
emit.out! %Q|elsif #{emit.convert_boolean(kwvalue(kwarg))}\n|
|
143
|
+
state = :then
|
144
|
+
elsif kwname(kwarg) == 'else'
|
145
|
+
check_arg_type(kwarg, :block)
|
146
|
+
|
147
|
+
emit.out! %Q|else\n|
|
148
|
+
emit.compile_block kwvalue(kwarg)
|
149
|
+
state = :end
|
150
|
+
else
|
151
|
+
raise SyntaxError.new("unexpected `#{kwname(kwarg)}', expecting one of: `elsif:', `else:'")
|
152
|
+
end
|
153
|
+
|
154
|
+
when :then
|
155
|
+
kwarg = kwargs.shift
|
156
|
+
if kwarg.nil?
|
157
|
+
raise SyntaxError.new("unexpected end of tag, expecting `then:'", nloc(node))
|
158
|
+
elsif kwname(kwarg) != 'then'
|
159
|
+
raise SyntaxError.new("unexpected `#{kwname(kwarg)}', expecting `then:'", nloc(kwarg))
|
160
|
+
end
|
161
|
+
|
162
|
+
check_arg_type(kwarg, :block)
|
163
|
+
|
164
|
+
emit.compile_block kwvalue(kwarg)
|
165
|
+
state = :elsif
|
166
|
+
|
167
|
+
when :end
|
168
|
+
if kwargs.any?
|
169
|
+
raise SyntaxError.new("unexpected `#{kwname(kwargs.first)}', expecting end of tag", nloc(kwarg))
|
170
|
+
end
|
171
|
+
|
172
|
+
state = nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
emit.out! %Q|end\n|
|
177
|
+
end
|
178
|
+
|
179
|
+
tag "unless" do |emit, context, node|
|
180
|
+
arg, kw = check_args node,
|
181
|
+
:expr,
|
182
|
+
:then => :block
|
183
|
+
|
184
|
+
emit.out! %Q|unless #{emit.convert_boolean(arg)}\n|
|
185
|
+
emit.compile_block kw[:then]
|
186
|
+
emit.out! %Q|end\n|
|
187
|
+
end
|
188
|
+
|
189
|
+
tag "capture" do |emit, context, node|
|
190
|
+
tag, arg, *kwargs = nvalue(node)
|
191
|
+
|
192
|
+
if kwargs.count == 1 && kwname(kwargs.first) == 'yield'
|
193
|
+
arg, kw = check_args node,
|
194
|
+
:ident,
|
195
|
+
:yield => :string
|
196
|
+
|
197
|
+
var_name, = nvalue(arg)
|
198
|
+
fragment = kw[:yield]
|
199
|
+
|
200
|
+
context.declare var_name, nloc(arg)
|
201
|
+
access_var_name = context.access(var_name)
|
202
|
+
|
203
|
+
context.nest do
|
204
|
+
emit.out! %Q|#{access_var_name} = #{emit.storage}[#{emit.expr(fragment)}].to_s\n|
|
205
|
+
end
|
206
|
+
else
|
207
|
+
arg, kw = check_args node,
|
208
|
+
:ident,
|
209
|
+
:"=" => :block
|
210
|
+
|
211
|
+
var_name, = nvalue(arg)
|
212
|
+
block = kw[:"="]
|
213
|
+
|
214
|
+
context.declare var_name, nloc(arg)
|
215
|
+
access_var_name = context.access(var_name)
|
216
|
+
|
217
|
+
context.nest do
|
218
|
+
capture_var_name = emit.capture do
|
219
|
+
emit.compile_block block
|
220
|
+
end
|
221
|
+
|
222
|
+
emit.out! %Q|#{access_var_name} = #{capture_var_name}\n|
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# Thanks to https://gist.github.com/101410 and other sources
|
2
|
+
|
3
|
+
module Liquor::HTMLTruncater
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def truncate(input, number = 300, truncate_string = "...")
|
7
|
+
doc = Nokogiri::HTML(input.to_s, nil, "UTF-8")
|
8
|
+
|
9
|
+
current = doc.children.first
|
10
|
+
count = 0
|
11
|
+
|
12
|
+
while true
|
13
|
+
# we found a text node
|
14
|
+
if current.is_a?(Nokogiri::XML::Text)
|
15
|
+
count += current.text.mb_chars.length
|
16
|
+
# we reached our limit, let's get outta here!
|
17
|
+
break if count > number
|
18
|
+
previous = current
|
19
|
+
end
|
20
|
+
|
21
|
+
if current.children.length > 0
|
22
|
+
# this node has children, can't be a text node,
|
23
|
+
# lets descend and look for text nodes
|
24
|
+
current = current.children.first
|
25
|
+
elsif !current.next.nil?
|
26
|
+
#this has no children, but has a sibling, let's check it out
|
27
|
+
current = current.next
|
28
|
+
else
|
29
|
+
# we are the last child, we need to ascend until we are
|
30
|
+
# either done or find a sibling to continue on to
|
31
|
+
n = current
|
32
|
+
while !n.is_a?(Nokogiri::HTML::Document) and n.parent.next.nil?
|
33
|
+
n = n.parent
|
34
|
+
end
|
35
|
+
|
36
|
+
# we've reached the top and found no more text nodes, break
|
37
|
+
if n.is_a?(Nokogiri::HTML::Document)
|
38
|
+
break;
|
39
|
+
else
|
40
|
+
current = n.parent.next
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if count >= number
|
46
|
+
unless count == number
|
47
|
+
new_content = current.text.mb_chars
|
48
|
+
|
49
|
+
index = number-(count-new_content.length)-1
|
50
|
+
if index >= 0
|
51
|
+
new_content = new_content[0..index]
|
52
|
+
current.send(:native_content=, new_content + truncate_string)
|
53
|
+
else
|
54
|
+
current = previous
|
55
|
+
current.send(:native_content=, current.content + truncate_string)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# remove everything else
|
60
|
+
while !current.is_a?(Nokogiri::HTML::Document)
|
61
|
+
while !current.next.nil?
|
62
|
+
current.next.remove
|
63
|
+
end
|
64
|
+
current = current.parent
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# now we grab the html and not the text.
|
69
|
+
# we do first because nokogiri adds html and body tags
|
70
|
+
# which we don't want
|
71
|
+
if doc.root.present?
|
72
|
+
doc.root.children.first.inner_html
|
73
|
+
else # no root element present (probably empty?), will return the first element
|
74
|
+
doc.children.first.inner_html
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def truncate_words(input, num_words, truncate_string = "...")
|
79
|
+
doc = Nokogiri::HTML(input)
|
80
|
+
|
81
|
+
current = doc.children.first
|
82
|
+
count = 0
|
83
|
+
|
84
|
+
while true
|
85
|
+
# we found a text node
|
86
|
+
if current.is_a?(Nokogiri::XML::Text)
|
87
|
+
count += current.text.split.length
|
88
|
+
# we reached our limit, let's get outta here!
|
89
|
+
break if count > num_words
|
90
|
+
previous = current
|
91
|
+
end
|
92
|
+
|
93
|
+
if current.children.length > 0
|
94
|
+
# this node has children, can't be a text node,
|
95
|
+
# lets descend and look for text nodes
|
96
|
+
current = current.children.first
|
97
|
+
elsif !current.next.nil?
|
98
|
+
#this has no children, but has a sibling, let's check it out
|
99
|
+
current = current.next
|
100
|
+
else
|
101
|
+
# we are the last child, we need to ascend until we are
|
102
|
+
# either done or find a sibling to continue on to
|
103
|
+
n = current
|
104
|
+
while !n.is_a?(Nokogiri::HTML::Document) and n.parent.next.nil?
|
105
|
+
n = n.parent
|
106
|
+
end
|
107
|
+
|
108
|
+
# we've reached the top and found no more text nodes, break
|
109
|
+
if n.is_a?(Nokogiri::HTML::Document)
|
110
|
+
break;
|
111
|
+
else
|
112
|
+
current = n.parent.next
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
if count >= num_words
|
118
|
+
unless count == num_words
|
119
|
+
new_content = current.text.split
|
120
|
+
|
121
|
+
# If we're here, the last text node we counted eclipsed the number of words
|
122
|
+
# that we want, so we need to cut down on words. The easiest way to think about
|
123
|
+
# this is that without this node we'd have fewer words than the limit, so all
|
124
|
+
# the previous words plus a limited number of words from this node are needed.
|
125
|
+
# We simply need to figure out how many words are needed and grab that many.
|
126
|
+
# Then we need to -subtract- an index, because the first word would be index zero.
|
127
|
+
|
128
|
+
# For example, given:
|
129
|
+
# <p>Testing this HTML truncater.</p><p>To see if its working.</p>
|
130
|
+
# Let's say I want 6 words. The correct returned string would be:
|
131
|
+
# <p>Testing this HTML truncater.</p><p>To see...</p>
|
132
|
+
# All the words in both paragraphs = 9
|
133
|
+
# The last paragraph is the one that breaks the limit. How many words would we
|
134
|
+
# have without it? 4. But we want up to 6, so we might as well get that many.
|
135
|
+
# 6 - 4 = 2, so we get 2 words from this node, but words #1-2 are indices #0-1, so
|
136
|
+
# we subtract 1. If this gives us -1, we want nothing from this node. So go back to
|
137
|
+
# the previous node instead.
|
138
|
+
index = num_words-(count-new_content.length)-1
|
139
|
+
if index >= 0
|
140
|
+
new_content = new_content[0..index]
|
141
|
+
current.content = new_content.join(' ') + truncate_string
|
142
|
+
else
|
143
|
+
current = previous
|
144
|
+
current.content = current.content + truncate_string
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# remove everything else
|
149
|
+
while !current.is_a?(Nokogiri::HTML::Document)
|
150
|
+
while !current.next.nil?
|
151
|
+
current.next.remove
|
152
|
+
end
|
153
|
+
current = current.parent
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# now we grab the html and not the text.
|
158
|
+
# we do first because nokogiri adds html and body tags
|
159
|
+
# which we don't want
|
160
|
+
doc.root.children.first.inner_html
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Liquor
|
2
|
+
module Partials
|
3
|
+
include Library
|
4
|
+
|
5
|
+
tag "yield" do |emit, context, node|
|
6
|
+
tag, arg, *kwargs = nvalue(node)
|
7
|
+
|
8
|
+
if arg.nil? # {% yield %}
|
9
|
+
check_args node,
|
10
|
+
nil
|
11
|
+
|
12
|
+
emit.cat! context.access('_inner_template')
|
13
|
+
else
|
14
|
+
if kwargs.count == 0
|
15
|
+
# {% yield "name" %}
|
16
|
+
arg, kw = check_args node,
|
17
|
+
:string
|
18
|
+
|
19
|
+
name, = nvalue(arg)
|
20
|
+
|
21
|
+
emit.cat! %Q|#{emit.storage}[#{name.inspect}].to_s|
|
22
|
+
else
|
23
|
+
# {% yield "name" if_none: %} block {% end yield %}
|
24
|
+
arg, kw = check_args node,
|
25
|
+
:string,
|
26
|
+
:if_none => :block
|
27
|
+
|
28
|
+
name, = nvalue(arg)
|
29
|
+
|
30
|
+
emit.out! %Q|if #{emit.storage}.include?(#{name.inspect})\n|
|
31
|
+
emit.cat! %Q| #{emit.storage}[#{name.inspect}].to_s|
|
32
|
+
emit.out! %Q|else\n|
|
33
|
+
emit.compile_block kw[:if_none]
|
34
|
+
emit.out! %Q|end\n|
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
tag "content_for" do |emit, context, node|
|
40
|
+
arg, kw = check_args node,
|
41
|
+
:string,
|
42
|
+
:"capture" => :block
|
43
|
+
|
44
|
+
name, = nvalue(arg)
|
45
|
+
block = kw[:"capture"]
|
46
|
+
|
47
|
+
context.nest do
|
48
|
+
capture_var_name = emit.capture do
|
49
|
+
emit.compile_block block
|
50
|
+
end
|
51
|
+
|
52
|
+
emit.out! %Q|#{emit.storage}[#{name.inspect}] = #{capture_var_name}\n|
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
tag "include" do |emit, context, node|
|
57
|
+
arg, kw = check_args node,
|
58
|
+
:string
|
59
|
+
|
60
|
+
name, = nvalue(arg)
|
61
|
+
|
62
|
+
context.nest do
|
63
|
+
manager = context.compiler.manager
|
64
|
+
|
65
|
+
source = manager.fetch_partial "_#{name}"
|
66
|
+
if source.nil?
|
67
|
+
raise ArgumentError.new("partial `#{name}' does not exist", nloc(arg))
|
68
|
+
elsif source == :syntax_error
|
69
|
+
# Do nothing. The manager has already reported the error.
|
70
|
+
else
|
71
|
+
emit.compile_block source
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|