Class: PlatformosCheck::LiquidNode
- Defined in:
- lib/platformos_check/liquid_node.rb
Overview
A node from the Liquid AST, the result of parsing a liquid file.
Constant Summary collapse
- WHITESPACE =
/\s/
Instance Attribute Summary collapse
-
#app_file ⇒ Object
readonly
Returns the value of attribute app_file.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#value ⇒ Object
readonly
Returns the value of attribute value.
Instance Method Summary collapse
- #assigned_or_echoed_variable? ⇒ Boolean
-
#block? ⇒ Boolean
A block of type of node?.
-
#block_body? ⇒ Boolean
The body of blocks.
- #block_end_end_index ⇒ Object
- #block_end_markup ⇒ Object
- #block_end_start_index ⇒ Object
- #block_start_end_index ⇒ Object
- #block_start_markup ⇒ Object
- #block_start_start_index ⇒ Object
-
#block_tag? ⇒ Boolean
A tag %…endtag % node?.
-
#children ⇒ Object
Array of children nodes.
-
#comment? ⇒ Boolean
A comment % block node?.
-
#document? ⇒ Boolean
(also: #root?)
Top level node of every liquid_file.
- #end_column ⇒ Object
- #end_index ⇒ Object
- #end_row ⇒ Object
- #end_token ⇒ Object
- #filters ⇒ Object
- #function? ⇒ Boolean
-
#initialize(value, parent, app_file) ⇒ LiquidNode
constructor
A new instance of LiquidNode.
-
#inline_comment? ⇒ Boolean
# comment %.
- #inner_json ⇒ Object
- #inner_markup ⇒ Object
- #inner_markup_end_column ⇒ Object
- #inner_markup_end_index ⇒ Object
- #inner_markup_end_row ⇒ Object
- #inner_markup_start_column ⇒ Object
- #inner_markup_start_index ⇒ Object
- #inner_markup_start_row ⇒ Object
-
#inside_liquid_tag? ⇒ Boolean
Is this node inside a ‘liquid … %` block?.
-
#line_number ⇒ Object
Most nodes have a line number, but it’s not guaranteed.
-
#literal? ⇒ Boolean
Literals are hard-coded values in the liquid file.
-
#markup ⇒ Object
The original source code of the node.
- #markup=(markup) ⇒ Object
-
#outer_markup ⇒ Object
The original source code of the node.
- #outer_markup_end_column ⇒ Object
- #outer_markup_end_index ⇒ Object
- #outer_markup_end_row ⇒ Object
- #outer_markup_start_column ⇒ Object
- #outer_markup_start_index ⇒ Object
- #outer_markup_start_row ⇒ Object
- #parse_json? ⇒ Boolean
- #source ⇒ Object
- #start_column ⇒ Object
- #start_index ⇒ Object
- #start_row ⇒ Object
- #start_token ⇒ Object
-
#tag? ⇒ Boolean
A tag % node?.
-
#to_h ⇒ Object
For debugging purposes, this might be easier for the eyes.
-
#type_name ⇒ Object
The ‘:under_score_name` of this type of node.
- #variable? ⇒ Boolean
- #variable_lookup? ⇒ Boolean
-
#whitespace_trimmed_end? ⇒ Boolean
Is this node inside a tag or variable ends starts by removing whitespace.
-
#whitespace_trimmed_start? ⇒ Boolean
Is this node inside a tag or variable that starts by removing whitespace.
Constructor Details
#initialize(value, parent, app_file) ⇒ LiquidNode
Returns a new instance of LiquidNode.
8 9 10 11 12 13 14 15 16 |
# File 'lib/platformos_check/liquid_node.rb', line 8 def initialize(value, parent, app_file) raise ArgumentError, "Expected a Liquid AST Node" if value.is_a?(LiquidNode) @value = value @parent = parent @app_file = app_file @tag_markup = nil @line_number_offset = 0 end |
Instance Attribute Details
#app_file ⇒ Object (readonly)
Returns the value of attribute app_file.
6 7 8 |
# File 'lib/platformos_check/liquid_node.rb', line 6 def app_file @app_file end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
6 7 8 |
# File 'lib/platformos_check/liquid_node.rb', line 6 def parent @parent end |
#value ⇒ Object (readonly)
Returns the value of attribute value.
6 7 8 |
# File 'lib/platformos_check/liquid_node.rb', line 6 def value @value end |
Instance Method Details
#assigned_or_echoed_variable? ⇒ Boolean
148 149 150 |
# File 'lib/platformos_check/liquid_node.rb', line 148 def assigned_or_echoed_variable? variable? && start_token == "" end |
#block? ⇒ Boolean
A block of type of node?
183 184 185 |
# File 'lib/platformos_check/liquid_node.rb', line 183 def block? block_tag? || block_body? || document? end |
#block_body? ⇒ Boolean
The body of blocks
178 179 180 |
# File 'lib/platformos_check/liquid_node.rb', line 178 def block_body? @value.is_a?(Liquid::BlockBody) end |
#block_end_end_index ⇒ Object
258 259 260 261 262 |
# File 'lib/platformos_check/liquid_node.rb', line 258 def block_end_end_index return block_end_start_index unless tag? && block? @block_end_end_index ||= block_end_match&.end(0) || block_start_end_index end |
#block_end_markup ⇒ Object
248 249 250 |
# File 'lib/platformos_check/liquid_node.rb', line 248 def block_end_markup source[block_end_start_index...block_end_end_index] end |
#block_end_start_index ⇒ Object
252 253 254 255 256 |
# File 'lib/platformos_check/liquid_node.rb', line 252 def block_end_start_index return block_start_end_index unless tag? && block? @block_end_start_index ||= block_end_match&.begin(0) || block_start_end_index end |
#block_start_end_index ⇒ Object
244 245 246 |
# File 'lib/platformos_check/liquid_node.rb', line 244 def block_start_end_index @block_start_end_index ||= position.end_index + end_token.size end |
#block_start_markup ⇒ Object
230 231 232 |
# File 'lib/platformos_check/liquid_node.rb', line 230 def block_start_markup source[block_start_start_index...block_start_end_index] end |
#block_start_start_index ⇒ Object
234 235 236 237 238 239 240 241 242 |
# File 'lib/platformos_check/liquid_node.rb', line 234 def block_start_start_index @block_start_start_index ||= if inside_liquid_tag? backtrack_on_whitespace(source, start_index, /[ \t]/) elsif tag? backtrack_on_whitespace(source, start_index) - start_token.length else position.start_index - start_token.length end end |
#block_tag? ⇒ Boolean
A tag %…endtag % node?
173 174 175 |
# File 'lib/platformos_check/liquid_node.rb', line 173 def block_tag? @value.is_a?(Liquid::Block) end |
#children ⇒ Object
Array of children nodes.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/platformos_check/liquid_node.rb', line 19 def children @children ||= begin nodes = if comment? [] elsif defined?(@value.class::ParseTreeVisitor) @value.class::ParseTreeVisitor.new(@value, {}).children elsif @value.respond_to?(:nodelist) Array(@value.nodelist) else [] end # Work around a bug in Liquid::Variable::ParseTreeVisitor that doesn't return # the args in a hash as children nodes. nodes = nodes.flat_map do |node| case node when Hash node.values else node end end nodes .reject(&:nil?) # We don't want nil nodes, and they can happen .map { |node| LiquidNode.new(node, self, @app_file) } end end |
#comment? ⇒ Boolean
A comment % block node?
157 158 159 |
# File 'lib/platformos_check/liquid_node.rb', line 157 def comment? @value.is_a?(Liquid::Comment) end |
#document? ⇒ Boolean Also known as: root?
Top level node of every liquid_file.
167 168 169 |
# File 'lib/platformos_check/liquid_node.rb', line 167 def document? @value.is_a?(Liquid::Document) end |
#end_column ⇒ Object
130 131 132 |
# File 'lib/platformos_check/liquid_node.rb', line 130 def end_column position.end_column end |
#end_index ⇒ Object
122 123 124 |
# File 'lib/platformos_check/liquid_node.rb', line 122 def end_index position.end_index end |
#end_row ⇒ Object
126 127 128 |
# File 'lib/platformos_check/liquid_node.rb', line 126 def end_row position.end_row end |
#end_token ⇒ Object
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/platformos_check/liquid_node.rb', line 368 def end_token if inside_liquid_tag? && source[end_index] == "\n" "\n" elsif inside_liquid_tag? "" elsif variable? && source[end_index...end_index + 3] == "-}}" "-}}" elsif variable? && source[end_index...end_index + 2] == "}}" "}}" elsif tag? && whitespace_trimmed_end? "-%}" elsif tag? "%}" else # this could happen because we're in an assign statement (variable) "" end end |
#filters ⇒ Object
201 202 203 204 205 |
# File 'lib/platformos_check/liquid_node.rb', line 201 def filters raise TypeError, "Attempting to lookup filters of #{type_name}. Only variables have filters." unless variable? @value.filters end |
#function? ⇒ Boolean
191 192 193 |
# File 'lib/platformos_check/liquid_node.rb', line 191 def function? @value.is_a?(PlatformosCheck::Tags::Function) end |
#inline_comment? ⇒ Boolean
# comment %
162 163 164 |
# File 'lib/platformos_check/liquid_node.rb', line 162 def inline_comment? @value.is_a?(Liquid::InlineComment) end |
#inner_json ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/platformos_check/liquid_node.rb', line 85 def inner_json return nil unless parse_json? @inner_json ||= JSON.parse(inner_markup) rescue JSON::ParserError # Handled by ValidSchema @inner_json = nil end |
#inner_markup ⇒ Object
79 80 81 82 83 |
# File 'lib/platformos_check/liquid_node.rb', line 79 def inner_markup return '' unless block? @inner_markup ||= source[block_start_end_index...block_end_start_index] end |
#inner_markup_end_column ⇒ Object
308 309 310 |
# File 'lib/platformos_check/liquid_node.rb', line 308 def inner_markup_end_column inner_markup_position.end_column end |
#inner_markup_end_index ⇒ Object
292 293 294 |
# File 'lib/platformos_check/liquid_node.rb', line 292 def inner_markup_end_index inner_markup_position.end_index end |
#inner_markup_end_row ⇒ Object
304 305 306 |
# File 'lib/platformos_check/liquid_node.rb', line 304 def inner_markup_end_row inner_markup_position.end_row end |
#inner_markup_start_column ⇒ Object
300 301 302 |
# File 'lib/platformos_check/liquid_node.rb', line 300 def inner_markup_start_column inner_markup_position.start_column end |
#inner_markup_start_index ⇒ Object
288 289 290 |
# File 'lib/platformos_check/liquid_node.rb', line 288 def inner_markup_start_index inner_markup_position.start_index end |
#inner_markup_start_row ⇒ Object
296 297 298 |
# File 'lib/platformos_check/liquid_node.rb', line 296 def inner_markup_start_row inner_markup_position.start_row end |
#inside_liquid_tag? ⇒ Boolean
Is this node inside a ‘liquid … %` block?
315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/platformos_check/liquid_node.rb', line 315 def inside_liquid_tag? # What we're doing here is starting at the start of the tag and # backtrack on all the whitespace until we land on something. If # that something is {% or %-, then we can safely assume that # we're inside a full tag and not a liquid tag. @inside_liquid_tag ||= if tag? && start_index && source i = 1 i += 1 while source[start_index - i] =~ WHITESPACE && i < start_index first_two_backtracked_characters = source[(start_index - i - 1)..(start_index - i)] first_two_backtracked_characters != "{%" && first_two_backtracked_characters != "%-" else false end end |
#line_number ⇒ Object
Most nodes have a line number, but it’s not guaranteed.
101 102 103 104 105 106 107 108 |
# File 'lib/platformos_check/liquid_node.rb', line 101 def line_number if tag? && @value.respond_to?(:line_number) markup # initialize the line_number_offset @value.line_number - @line_number_offset elsif @value.respond_to?(:line_number) @value.line_number end end |
#literal? ⇒ Boolean
Literals are hard-coded values in the liquid file.
135 136 137 |
# File 'lib/platformos_check/liquid_node.rb', line 135 def literal? @value.is_a?(String) || @value.is_a?(Integer) end |
#markup ⇒ Object
The original source code of the node. Doesn’t contain wrapping braces.
48 49 50 51 52 53 54 55 56 |
# File 'lib/platformos_check/liquid_node.rb', line 48 def markup if tag? tag_markup elsif literal? value.to_s elsif @value.instance_variable_defined?(:@markup) @value.instance_variable_get(:@markup) end end |
#markup=(markup) ⇒ Object
94 95 96 97 98 |
# File 'lib/platformos_check/liquid_node.rb', line 94 def markup=(markup) return unless @value.instance_variable_defined?(:@markup) @value.instance_variable_set(:@markup, markup) end |
#outer_markup ⇒ Object
The original source code of the node. Does contain wrapping braces.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/platformos_check/liquid_node.rb', line 59 def outer_markup if literal? markup elsif variable_lookup? '' elsif variable? start_token + markup + end_token elsif tag? && block? start_index = block_start_start_index end_index = block_start_end_index end_index += inner_markup.size end_index = find_block_delimiter(end_index)&.end(0) source[start_index...end_index] elsif tag? source[block_start_start_index...block_start_end_index] else inner_markup end end |
#outer_markup_end_column ⇒ Object
284 285 286 |
# File 'lib/platformos_check/liquid_node.rb', line 284 def outer_markup_end_column outer_markup_position.end_column end |
#outer_markup_end_index ⇒ Object
268 269 270 |
# File 'lib/platformos_check/liquid_node.rb', line 268 def outer_markup_end_index outer_markup_position.end_index end |
#outer_markup_end_row ⇒ Object
280 281 282 |
# File 'lib/platformos_check/liquid_node.rb', line 280 def outer_markup_end_row outer_markup_position.end_row end |
#outer_markup_start_column ⇒ Object
276 277 278 |
# File 'lib/platformos_check/liquid_node.rb', line 276 def outer_markup_start_column outer_markup_position.start_column end |
#outer_markup_start_index ⇒ Object
264 265 266 |
# File 'lib/platformos_check/liquid_node.rb', line 264 def outer_markup_start_index outer_markup_position.start_index end |
#outer_markup_start_row ⇒ Object
272 273 274 |
# File 'lib/platformos_check/liquid_node.rb', line 272 def outer_markup_start_row outer_markup_position.start_row end |
#parse_json? ⇒ Boolean
187 188 189 |
# File 'lib/platformos_check/liquid_node.rb', line 187 def parse_json? @value.is_a?(PlatformosCheck::Tags::ParseJson) end |
#source ⇒ Object
207 208 209 |
# File 'lib/platformos_check/liquid_node.rb', line 207 def source app_file&.source end |
#start_column ⇒ Object
118 119 120 |
# File 'lib/platformos_check/liquid_node.rb', line 118 def start_column position.start_column end |
#start_index ⇒ Object
110 111 112 |
# File 'lib/platformos_check/liquid_node.rb', line 110 def start_index position.start_index end |
#start_row ⇒ Object
114 115 116 |
# File 'lib/platformos_check/liquid_node.rb', line 114 def start_row position.start_row end |
#start_token ⇒ Object
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/platformos_check/liquid_node.rb', line 352 def start_token if inside_liquid_tag? "" elsif variable? && source[start_index - 3..start_index - 1] == "{{-" "{{-" elsif variable? && source[start_index - 2..start_index - 1] == "{{" "{{" elsif tag? && whitespace_trimmed_start? "{%-" elsif tag? "{%" else "" end end |
#tag? ⇒ Boolean
A tag % node?
140 141 142 |
# File 'lib/platformos_check/liquid_node.rb', line 140 def tag? @value.is_a?(Liquid::Tag) end |
#to_h ⇒ Object
For debugging purposes, this might be easier for the eyes.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/platformos_check/liquid_node.rb', line 212 def to_h if literal? return @value elsif variable_lookup? return { type_name:, name: value.name.to_s, lookups: children.map(&:to_h) } end { type_name:, markup: outer_markup, children: children.map(&:to_h) } end |
#type_name ⇒ Object
The ‘:under_score_name` of this type of node. Used to dispatch to the `on_<type_name>` and `after_<type_name>` check methods.
197 198 199 |
# File 'lib/platformos_check/liquid_node.rb', line 197 def type_name @type_name ||= StringHelpers.underscore(StringHelpers.demodulize(@value.class.name)).to_sym end |
#variable? ⇒ Boolean
144 145 146 |
# File 'lib/platformos_check/liquid_node.rb', line 144 def variable? @value.is_a?(Liquid::Variable) end |
#variable_lookup? ⇒ Boolean
152 153 154 |
# File 'lib/platformos_check/liquid_node.rb', line 152 def variable_lookup? @value.is_a?(Liquid::VariableLookup) end |
#whitespace_trimmed_end? ⇒ Boolean
Is this node inside a tag or variable ends starts by removing whitespace. i.e. -%} or -}}
342 343 344 345 346 347 348 349 350 |
# File 'lib/platformos_check/liquid_node.rb', line 342 def whitespace_trimmed_end? @whitespace_trimmed_end ||= if end_index && source && !inside_liquid_tag? i = 0 i += 1 while source[end_index + i] =~ WHITESPACE && i < source.size source[end_index + i] == "-" else false end end |
#whitespace_trimmed_start? ⇒ Boolean
Is this node inside a tag or variable that starts by removing whitespace. i.e. {%- or {{-
331 332 333 334 335 336 337 338 339 |
# File 'lib/platformos_check/liquid_node.rb', line 331 def whitespace_trimmed_start? @whitespace_trimmed_start ||= if start_index && source && !inside_liquid_tag? i = 1 i += 1 while source[start_index - i] =~ WHITESPACE && i < start_index source[start_index - i] == "-" else false end end |