line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
21
|
|
|
21
|
|
94
|
use strict; |
|
21
|
|
|
|
|
34
|
|
|
21
|
|
|
|
|
745
|
|
4
|
21
|
|
|
21
|
|
97
|
use warnings; |
|
21
|
|
|
|
|
32
|
|
|
21
|
|
|
|
|
720
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token; |
7
|
21
|
|
|
21
|
|
97
|
use base 'WWW::Shopify::Liquid::Element'; |
|
21
|
|
|
|
|
34
|
|
|
21
|
|
|
|
|
8095
|
|
8
|
748
|
|
|
748
|
|
3844
|
sub new { return bless { line => $_[1], core => $_[2] }, $_[0]; }; |
9
|
0
|
|
|
0
|
|
0
|
sub stringify { return $_[0]->{core}; } |
10
|
0
|
|
|
0
|
|
0
|
sub tokens { return $_[0]; } |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Operator; |
13
|
21
|
|
|
21
|
|
118
|
use base 'WWW::Shopify::Liquid::Token'; |
|
21
|
|
|
|
|
37
|
|
|
21
|
|
|
|
|
6511
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Operand; |
16
|
21
|
|
|
21
|
|
111
|
use base 'WWW::Shopify::Liquid::Token'; |
|
21
|
|
|
|
|
38
|
|
|
21
|
|
|
|
|
5511
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::String; |
19
|
21
|
|
|
21
|
|
115
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
31
|
|
|
21
|
|
|
|
|
6921
|
|
20
|
74
|
|
|
74
|
|
82
|
sub process { my ($self, $hash) = @_; return $self->{core}; } |
|
74
|
|
|
|
|
217
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Number; |
23
|
21
|
|
|
21
|
|
116
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
39
|
|
|
21
|
|
|
|
|
6413
|
|
24
|
10
|
|
|
10
|
|
18
|
sub process { my ($self, $hash) = @_; return $self->{core}; } |
|
10
|
|
|
|
|
38
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Bool; |
27
|
21
|
|
|
21
|
|
116
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
31
|
|
|
21
|
|
|
|
|
6108
|
|
28
|
0
|
|
|
0
|
|
0
|
sub process { my ($self, $hash) = @_; return $self->{core}; } |
|
0
|
|
|
|
|
0
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Variable; |
31
|
21
|
|
|
21
|
|
117
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
32
|
|
|
21
|
|
|
|
|
5469
|
|
32
|
|
|
|
|
|
|
|
33
|
21
|
|
|
21
|
|
13556
|
use Data::Dumper; |
|
21
|
|
|
|
|
123908
|
|
|
21
|
|
|
|
|
1750
|
|
34
|
21
|
|
|
21
|
|
163
|
use Scalar::Util qw(looks_like_number reftype); |
|
21
|
|
|
|
|
39
|
|
|
21
|
|
|
|
|
6246
|
|
35
|
|
|
|
|
|
|
|
36
|
314
|
|
|
314
|
|
391
|
sub new { my $package = shift; return bless { line => shift, core => [@_] }, $package; }; |
|
314
|
|
|
|
|
1769
|
|
37
|
|
|
|
|
|
|
sub process { |
38
|
36
|
|
|
36
|
|
44
|
my ($self, $hash, $action) = @_; |
39
|
36
|
|
|
|
|
40
|
my $place = $hash; |
40
|
|
|
|
|
|
|
|
41
|
36
|
50
|
|
|
|
96
|
return $self->{core} if $self->is_processed($self->{core}); |
42
|
36
|
|
|
|
|
44
|
foreach my $part (@{$self->{core}}) { |
|
36
|
|
|
|
|
75
|
|
43
|
47
|
50
|
|
|
|
110
|
if (ref($part) eq 'WWW::Shopify::Liquid::Token::Variable::Processing') { |
44
|
0
|
|
|
|
|
0
|
$place = $part->$action($hash, $place); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
else { |
47
|
47
|
50
|
|
|
|
105
|
my $key = $self->is_processed($part) ? $part : $part->$action($hash); |
48
|
47
|
50
|
33
|
|
|
207
|
return $self unless defined $key && $key ne ''; |
49
|
47
|
100
|
66
|
|
|
344
|
if (reftype($place) && reftype($place) eq "HASH" && exists $place->{$key}) { |
|
|
50
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
50
|
45
|
|
|
|
|
112
|
$place = $place->{$key}; |
51
|
|
|
|
|
|
|
} elsif (reftype($place) && reftype($place) eq "ARRAY" && looks_like_number($key) && defined $place->[$key]) { |
52
|
2
|
|
|
|
|
7
|
$place = $place->[$key]; |
53
|
|
|
|
|
|
|
} else { |
54
|
0
|
|
|
|
|
0
|
return $self; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
} |
59
|
36
|
|
|
|
|
91
|
return $place; |
60
|
|
|
|
|
|
|
} |
61
|
0
|
|
|
0
|
|
0
|
sub stringify { return join(".", map { $_->stringify } @{$_[0]->{core}}); } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Variable::Processing; |
64
|
21
|
|
|
21
|
|
121
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
39
|
|
|
21
|
|
|
|
|
6545
|
|
65
|
21
|
|
|
21
|
|
127
|
use Data::Dumper; |
|
21
|
|
|
|
|
50
|
|
|
21
|
|
|
|
|
2617
|
|
66
|
|
|
|
|
|
|
sub process { |
67
|
0
|
|
|
0
|
|
0
|
my ($self, $hash, $argument, $action) = @_; |
68
|
0
|
0
|
|
|
|
0
|
return $self if !$self->is_processed($argument); |
69
|
0
|
|
|
|
|
0
|
my $result = $self->{core}->operate($hash, $argument); |
70
|
0
|
0
|
|
|
|
0
|
return $self if !$self->is_processed($result); |
71
|
0
|
|
|
|
|
0
|
return $result; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Grouping; |
76
|
21
|
|
|
21
|
|
111
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
38
|
|
|
21
|
|
|
|
|
6910
|
|
77
|
26
|
|
|
26
|
|
52
|
sub new { my $package = shift; return bless { line => shift, members => [@_] }, $package; }; |
|
26
|
|
|
|
|
151
|
|
78
|
15
|
|
|
15
|
|
21
|
sub members { return @{$_[0]->{members}}; } |
|
15
|
|
|
|
|
186
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Text; |
81
|
21
|
|
|
21
|
|
119
|
use base 'WWW::Shopify::Liquid::Token::Operand'; |
|
21
|
|
|
|
|
36
|
|
|
21
|
|
|
|
|
8183
|
|
82
|
|
|
|
|
|
|
sub new { |
83
|
194
|
|
|
194
|
|
694
|
my $self = { line => $_[1], core => $_[2] }; |
84
|
194
|
|
|
|
|
271
|
my $package = $_[0]; |
85
|
194
|
100
|
66
|
|
|
1288
|
$package = 'WWW::Shopify::Liquid::Token::Text::Whitespace' if !defined $_[2] || $_[2] =~ m/^\s*$/; |
86
|
194
|
|
|
|
|
724
|
return bless $self, $package; |
87
|
|
|
|
|
|
|
}; |
88
|
4
|
|
|
4
|
|
7
|
sub process { my ($self, $hash) = @_; return $self->{core}; } |
|
4
|
|
|
|
|
14
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Text::Whitespace; |
91
|
21
|
|
|
21
|
|
124
|
use base 'WWW::Shopify::Liquid::Token::Text'; |
|
21
|
|
|
|
|
37
|
|
|
21
|
|
|
|
|
6563
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Tag; |
94
|
21
|
|
|
21
|
|
130
|
use base 'WWW::Shopify::Liquid::Token'; |
|
21
|
|
|
|
|
47
|
|
|
21
|
|
|
|
|
8113
|
|
95
|
279
|
|
|
279
|
|
1383
|
sub new { return bless { line => $_[1], tag => $_[2], arguments => $_[3] }, $_[0] }; |
96
|
1592
|
|
|
1592
|
|
6780
|
sub tag { return $_[0]->{tag}; } |
97
|
6
|
|
|
6
|
|
18
|
sub stringify { return $_[0]->tag; } |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Output; |
100
|
21
|
|
|
21
|
|
124
|
use base 'WWW::Shopify::Liquid::Token'; |
|
21
|
|
|
|
|
40
|
|
|
21
|
|
|
|
|
6541
|
|
101
|
93
|
|
|
93
|
|
398
|
sub new { return bless { line => $_[1], core => $_[2] }, $_[0]; }; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Token::Separator; |
104
|
21
|
|
|
21
|
|
114
|
use base 'WWW::Shopify::Liquid::Token'; |
|
21
|
|
|
|
|
39
|
|
|
21
|
|
|
|
|
5643
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Lexer; |
108
|
21
|
|
|
21
|
|
116
|
use base 'WWW::Shopify::Liquid::Pipeline'; |
|
21
|
|
|
|
|
38
|
|
|
21
|
|
|
|
|
6402
|
|
109
|
21
|
|
|
21
|
|
152
|
use Scalar::Util qw(looks_like_number); |
|
21
|
|
|
|
|
43
|
|
|
21
|
|
|
|
|
40110
|
|
110
|
|
|
|
|
|
|
|
111
|
23
|
|
|
23
|
0
|
283
|
sub new { return bless { operators => {}, lexing_halters => {}, transparent_filters => {} }, $_[0]; } |
112
|
909
|
|
|
909
|
0
|
4440
|
sub operators { return $_[0]->{operators}; } |
113
|
460
|
|
|
460
|
0
|
3546
|
sub register_operator { $_[0]->{operators}->{$_} = $_[1] for ($_[1]->symbol); } |
114
|
|
|
|
|
|
|
sub register_tag { |
115
|
322
|
|
|
322
|
0
|
442
|
my ($self, $package) = @_; |
116
|
322
|
100
|
100
|
|
|
1667
|
$self->{lexing_halters}->{$package->name} = $package if $package->is_enclosing && $package->inner_halt_lexing; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
sub register_filter { |
119
|
1311
|
|
|
1311
|
0
|
1423
|
my ($self, $package) = @_; |
120
|
1311
|
100
|
|
|
|
11021
|
$self->{transparent_filters}->{$package->name} = $package if ($package->transparent); |
121
|
|
|
|
|
|
|
} |
122
|
429
|
|
|
429
|
0
|
1927
|
sub transparent_filters { return $_[0]->{transparent_filters}; } |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub parse_token { |
125
|
636
|
|
|
636
|
0
|
809
|
my ($self, $line, $token) = @_; |
126
|
|
|
|
|
|
|
# Strip token of whitespace. |
127
|
636
|
50
|
|
|
|
1081
|
return undef unless defined $token; |
128
|
636
|
|
|
|
|
2706
|
$token =~ s/^\s*(.*?)\s*$/$1/; |
129
|
636
|
100
|
|
|
|
1209
|
return WWW::Shopify::Liquid::Token::Operator->new($line, $token) if $self->operators->{$token}; |
130
|
462
|
100
|
100
|
|
|
2104
|
return WWW::Shopify::Liquid::Token::String->new($line, $1) if $token =~ m/^'(.*)'$/ || $token =~ m/^"(.*)"$/; |
131
|
415
|
100
|
|
|
|
1513
|
return WWW::Shopify::Liquid::Token::Number->new($line, $1) if looks_like_number($token); |
132
|
333
|
50
|
|
|
|
615
|
return WWW::Shopify::Liquid::Token::NULL->new() if $token eq ''; |
133
|
333
|
100
|
100
|
|
|
1256
|
return WWW::Shopify::Liquid::Token::Separator->new($line, $token) if ($token eq ":" || $token eq ","); |
134
|
|
|
|
|
|
|
# We're a variable. Let's see what's going on. Split along non quoted . and [ ] fields. |
135
|
314
|
|
|
|
|
520
|
my ($squot, $dquot, $start, @parts) = (0,0,0); |
136
|
|
|
|
|
|
|
# customer['test']['b'] |
137
|
314
|
|
|
|
|
351
|
my $open_bracket = 0; |
138
|
314
|
|
|
|
|
1849
|
while ($token =~ m/(\.|\[|\]|(?
|
139
|
460
|
|
|
|
|
654
|
my $sym = $&; |
140
|
460
|
50
|
33
|
|
|
1286
|
if (!$squot && !$dquot) { |
141
|
460
|
100
|
100
|
|
|
1191
|
$open_bracket-- if ($sym && $sym eq "]"); |
142
|
460
|
100
|
100
|
|
|
3394
|
if (($sym eq "." || $sym eq "]" || $sym eq "[" || !$sym) && $open_bracket == 0) { |
|
|
|
100
|
|
|
|
|
143
|
442
|
|
|
|
|
1031
|
my $contents = substr($token, $start, $-[0] - $start); |
144
|
442
|
100
|
66
|
|
|
1633
|
if (defined $contents && $contents ne "") { |
145
|
440
|
|
|
|
|
617
|
my @variables = (); |
146
|
440
|
100
|
100
|
|
|
1456
|
if (!$sym || $sym eq "." || $sym eq "[") { |
|
|
50
|
100
|
|
|
|
|
147
|
424
|
100
|
|
|
|
786
|
@variables = $self->transparent_filters->{$contents} ? WWW::Shopify::Liquid::Token::Variable::Processing->new($line, $self->transparent_filters->{$contents}) : WWW::Shopify::Liquid::Token::String->new($line, $contents); |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
elsif ($sym eq "]") { |
150
|
16
|
|
|
|
|
55
|
@variables = $self->parse_expression($line, $contents); |
151
|
|
|
|
|
|
|
} |
152
|
440
|
50
|
|
|
|
1069
|
if (int(@variables) > 0) { |
153
|
440
|
100
|
|
|
|
698
|
if (int(@variables) == 1) { |
154
|
436
|
|
|
|
|
696
|
push(@parts, @variables); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
else { |
157
|
4
|
|
|
|
|
20
|
push(@parts, WWW::Shopify::Liquid::Token::Grouping->new($line, @variables)) ; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
} |
163
|
460
|
100
|
66
|
|
|
2714
|
$start = $+[0] if $sym ne '"' && $sym ne "'" && !$open_bracket; |
|
|
|
100
|
|
|
|
|
164
|
460
|
100
|
100
|
|
|
1484
|
$open_bracket++ if ($sym && $sym eq "["); |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
} |
167
|
460
|
50
|
|
|
|
775
|
$squot = !$squot if $token eq "'"; |
168
|
460
|
50
|
|
|
|
2340
|
$dquot = !$dquot if $token eq '"'; |
169
|
|
|
|
|
|
|
} |
170
|
314
|
|
|
|
|
941
|
return WWW::Shopify::Liquid::Token::Variable->new($line, @parts); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# Returns a single token repsending the whole a expression. |
174
|
|
|
|
|
|
|
sub parse_expression { |
175
|
401
|
|
|
401
|
0
|
649
|
my ($self, $line, $exp) = @_; |
176
|
401
|
100
|
66
|
|
|
10865
|
return () if !defined $exp || $exp eq ''; |
177
|
273
|
|
|
|
|
375
|
my @tokens = (); |
178
|
273
|
|
|
|
|
470
|
my ($start_paren, $start_space, $level, $squot, $dquot, $start_sq, $sq_level) = (undef, 0, 0, 0, 0, undef, 0); |
179
|
|
|
|
|
|
|
# We regex along parentheses, quotation marks (both kinds), whitespace, and non-word-operators. |
180
|
|
|
|
|
|
|
# We sort along length, so that we make sure to get all the largest operators first, so that way if a larger operator is made from a smaller one (=, ==) |
181
|
|
|
|
|
|
|
# There's no confusion, we always try to match the largest first. |
182
|
273
|
|
|
|
|
279
|
my $non_word_operators = join("|", map { quotemeta($_) } grep { $_ =~ m/^\W+$/; } sort { length($b) <=> length($a) } keys(%{$self->operators})); |
|
4368
|
|
|
|
|
5278
|
|
|
5733
|
|
|
|
|
8893
|
|
|
18769
|
|
|
|
|
15187
|
|
|
273
|
|
|
|
|
548
|
|
183
|
273
|
|
|
|
|
4893
|
while ($exp =~ m/(?:\(|\)|\]|\[|(?
|
184
|
1002
|
|
|
|
|
3283
|
my ($rs, $re, $rc, $whitespace, $nword_op) = ($-[0], $+[0], $&, $1, $2); |
185
|
1002
|
100
|
66
|
|
|
3123
|
if (!$squot && !$dquot) { |
186
|
924
|
100
|
66
|
|
|
1891
|
$start_paren = $re if $rc eq "(" && $level++ == 0; |
187
|
924
|
100
|
66
|
|
|
1712
|
$start_sq = $re if $rc eq "[" && $sq_level++ == 0; |
188
|
|
|
|
|
|
|
# Deal with parentheses; always the highest level of operation. |
189
|
924
|
100
|
66
|
|
|
1623
|
if ($rc eq ")" && --$level == 0) { |
190
|
21
|
|
|
|
|
43
|
$start_space = $re; |
191
|
21
|
|
|
|
|
148
|
push(@tokens, WWW::Shopify::Liquid::Token::Grouping->new($line, $self->parse_expression($line, substr($exp, $start_paren, $rs - $start_paren)))); |
192
|
|
|
|
|
|
|
} |
193
|
924
|
100
|
|
|
|
1305
|
--$sq_level if $rc eq "]"; |
194
|
924
|
100
|
100
|
|
|
2996
|
if ($level == 0 && $sq_level == 0) { |
195
|
|
|
|
|
|
|
# If we're only spaces, that means we're a new a token. |
196
|
835
|
100
|
100
|
|
|
1909
|
if (defined $whitespace || $nword_op) { |
197
|
751
|
50
|
|
|
|
1125
|
if (defined $start_space) { |
198
|
751
|
|
|
|
|
1223
|
my $contents = substr($exp, $start_space, $rs - $start_space); |
199
|
751
|
100
|
|
|
|
2851
|
push(@tokens, $self->parse_token($line, $contents)) if $contents !~ m/^\s*$/; |
200
|
|
|
|
|
|
|
} |
201
|
751
|
100
|
|
|
|
1429
|
push(@tokens, $self->parse_token($line, $nword_op)) if $nword_op; |
202
|
751
|
|
|
|
|
859
|
$start_space = $re; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
} |
206
|
1002
|
100
|
66
|
|
|
2106
|
$squot = !$squot if ($rc eq "'" && !$dquot); |
207
|
1002
|
100
|
66
|
|
|
7347
|
$dquot = !$dquot if ($rc eq '"' && !$squot); |
208
|
|
|
|
|
|
|
} |
209
|
273
|
50
|
|
|
|
539
|
die WWW::Shopify::Liquid::Exception::Lexer::UnbalancedBrace->new($line) unless $level == 0; |
210
|
|
|
|
|
|
|
# Go through and combine any -1 from OP NUM to NUM. |
211
|
384
|
100
|
33
|
|
|
3003
|
my @ids = grep { |
|
|
|
33
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
212
|
273
|
|
|
|
|
610
|
$tokens[$_]->isa('WWW::Shopify::Liquid::Token::Number') && |
213
|
|
|
|
|
|
|
$tokens[$_-1]->isa('WWW::Shopify::Liquid::Token::Operator') && $tokens[$_-1]->{core} eq "-" && |
214
|
|
|
|
|
|
|
($_ == 1 || $tokens[$_-2]->isa('WWW::Shopify::Liquid::Token::Separator') || $tokens[$_-2]->isa('WWW::Shopify::Liquid::Token::Operator')) |
215
|
|
|
|
|
|
|
} 1..$#tokens; |
216
|
273
|
|
|
|
|
557
|
for (@ids) { $tokens[$_]->{core} *= -1; $tokens[$_-1] = undef; } |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
13
|
|
217
|
273
|
|
|
|
|
345
|
return grep { defined $_ } @tokens; |
|
657
|
|
|
|
|
1959
|
|
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub parse_text { |
221
|
78
|
|
|
78
|
0
|
77300
|
my ($self, $text) = @_; |
222
|
78
|
50
|
|
|
|
271
|
return () unless defined $text; |
223
|
78
|
|
|
|
|
143
|
my @tokens = (); |
224
|
78
|
|
|
|
|
127
|
my $start = 0; |
225
|
78
|
|
|
|
|
117
|
my $line = 1; |
226
|
78
|
|
|
|
|
106
|
my $column = 0; |
227
|
78
|
|
|
|
|
106
|
my $lexing_halter = undef; |
228
|
|
|
|
|
|
|
|
229
|
78
|
|
|
|
|
101
|
my $start_line = 1; |
230
|
78
|
|
|
|
|
107
|
my $start_column = 0; |
231
|
78
|
|
|
|
|
101
|
my $line_position = 0; |
232
|
|
|
|
|
|
|
|
233
|
78
|
50
|
|
|
|
235
|
return (WWW::Shopify::Liquid::Token::Text->new(1, '')) if $text eq ''; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# No need to worry about quotations; liquid overrides everything. |
236
|
78
|
|
|
|
|
861
|
while ($text =~ m/(?:(?:{%\s*(\w+)\s*(.*?)\s*%})|(?:{{\s*(.*?)\s*}})|(\n)|$)/g) { |
237
|
581
|
|
|
|
|
1270
|
my ($tag, $arguments, $output) = ($1, $2, $3); |
238
|
581
|
100
|
|
|
|
1127
|
if (defined $4) { |
239
|
134
|
|
|
|
|
124
|
++$line; |
240
|
134
|
|
|
|
|
232
|
$line_position = $+[0]; |
241
|
134
|
|
|
|
|
751
|
next; |
242
|
|
|
|
|
|
|
}; |
243
|
447
|
|
|
|
|
918
|
my $column = $+[0] - $line_position; |
244
|
447
|
|
|
|
|
1115
|
my $position = [$start_line, $start_column, $-[0]]; |
245
|
447
|
100
|
100
|
|
|
3768
|
if ($tag && !$lexing_halter && exists $self->{lexing_halters}->{$tag}) { |
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
246
|
4
|
|
|
|
|
8
|
$lexing_halter = $tag; |
247
|
4
|
|
|
|
|
17
|
push(@tokens, WWW::Shopify::Liquid::Token::Tag->new($position, $tag, [$self->parse_expression($position, $arguments)])); |
248
|
4
|
|
|
|
|
14
|
$start = $+[0]; |
249
|
4
|
|
|
|
|
9
|
$start_line = $line; |
250
|
4
|
|
|
|
|
7
|
$start_column = $column; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
elsif ($tag && $lexing_halter && $tag eq "end" . $lexing_halter) { |
253
|
4
|
|
|
|
|
8
|
$lexing_halter = undef; |
254
|
|
|
|
|
|
|
} |
255
|
447
|
100
|
|
|
|
793
|
if (!$lexing_halter) { |
256
|
436
|
100
|
|
|
|
1175
|
if ($start < $-[0]) { |
257
|
192
|
|
|
|
|
750
|
push(@tokens, WWW::Shopify::Liquid::Token::Text->new($position, substr($text, $start, $-[0] - $start))); |
258
|
192
|
|
|
|
|
295
|
$start_line = $line; |
259
|
192
|
|
|
|
|
332
|
$start_column = $-[0] - $line_position; |
260
|
192
|
|
|
|
|
478
|
$position = [$start_line, $start_column, $-[0]]; |
261
|
|
|
|
|
|
|
} |
262
|
436
|
100
|
|
|
|
1246
|
push(@tokens, WWW::Shopify::Liquid::Token::Tag->new($position, $tag, [$self->parse_expression($position, $arguments)])) if $tag; |
263
|
436
|
100
|
|
|
|
931
|
push(@tokens, WWW::Shopify::Liquid::Token::Output->new($position, [$self->parse_expression($position, $output)])) if $output; |
264
|
436
|
|
|
|
|
767
|
$start = $+[0]; |
265
|
436
|
|
|
|
|
495
|
$start_line = $line; |
266
|
436
|
|
|
|
|
2135
|
$start_column = $column; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
} |
269
|
78
|
|
|
|
|
857
|
return @tokens; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub unparse_token { |
273
|
10
|
|
|
10
|
0
|
10
|
my ($self, $token) = @_; |
274
|
10
|
50
|
|
|
|
17
|
return '' unless $token; |
275
|
10
|
100
|
|
|
|
30
|
return join(".", map { $_->{core} } @{$token->{core}}) if $token->isa('WWW::Shopify::Liquid::Token::Variable'); |
|
6
|
|
|
|
|
26
|
|
|
5
|
|
|
|
|
6
|
|
276
|
5
|
100
|
|
|
|
16
|
return "(" . join("", map { $self->unparse_token($_); } @{$token->{members}}) . ")" if $token->isa('WWW::Shopify::Liquid::Token::Grouping'); |
|
3
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
2
|
|
277
|
4
|
|
|
|
|
10
|
return $token->{core}; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub unparse_expression { |
281
|
5
|
|
|
5
|
0
|
6
|
my ($self, @tokens) = @_; |
282
|
5
|
|
|
|
|
5
|
return join(' ', map { $self->unparse_token($_) } @tokens); |
|
7
|
|
|
|
|
10
|
|
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub unparse_text_segment { |
286
|
15
|
|
|
15
|
0
|
12
|
my ($self, $token) = @_; |
287
|
15
|
100
|
|
|
|
38
|
if ($token->isa('WWW::Shopify::Liquid::Token::Tag')) { |
288
|
8
|
100
|
|
|
|
22
|
return "{%" . $token->{tag} . "%}" if !$token->{arguments}; |
289
|
3
|
|
|
|
|
5
|
return "{%" . $token->{tag} . " " . $self->unparse_expression(@{$token->{arguments}}) . "%}"; |
|
3
|
|
|
|
|
6
|
|
290
|
|
|
|
|
|
|
} |
291
|
7
|
100
|
|
|
|
22
|
return "{{" . $self->unparse_expression(@{$token->{core}}) . "}}" if $token->isa('WWW::Shopify::Liquid::Token::Output'); |
|
2
|
|
|
|
|
6
|
|
292
|
5
|
|
|
|
|
9
|
return $token->{core}; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub unparse_text { |
296
|
1
|
|
|
1
|
0
|
7
|
my ($self, @tokens) = @_; |
297
|
1
|
|
|
|
|
2
|
return join('', map { $self->unparse_text_segment($_) } @tokens); |
|
15
|
|
|
|
|
18
|
|
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
1; |