Class: ThemeCheck::LiquidNode

Inherits:
Node
  • Object
show all
Defined in:
lib/theme_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

Instance Method Summary collapse

Constructor Details

#initialize(value, parent, theme_file) ⇒ LiquidNode

Returns a new instance of LiquidNode.

Raises:

  • (ArgumentError)


8
9
10
11
12
13
14
15
# File 'lib/theme_check/liquid_node.rb', line 8

def initialize(value, parent, theme_file)
  raise ArgumentError, "Expected a Liquid AST Node" if value.is_a?(LiquidNode)
  @value = value
  @parent = parent
  @theme_file = theme_file
  @tag_markup = nil
  @line_number_offset = 0
end

Instance Attribute Details

#parentObject (readonly)

Returns the value of attribute parent.



6
7
8
# File 'lib/theme_check/liquid_node.rb', line 6

def parent
  @parent
end

#theme_fileObject (readonly)

Returns the value of attribute theme_file.



6
7
8
# File 'lib/theme_check/liquid_node.rb', line 6

def theme_file
  @theme_file
end

#valueObject (readonly)

Returns the value of attribute value.



6
7
8
# File 'lib/theme_check/liquid_node.rb', line 6

def value
  @value
end

Instance Method Details

#block?Boolean

A block of type of node?

Returns:

  • (Boolean)


141
142
143
# File 'lib/theme_check/liquid_node.rb', line 141

def block?
  block_tag? || block_body? || document?
end

#block_body?Boolean

The body of blocks

Returns:

  • (Boolean)


136
137
138
# File 'lib/theme_check/liquid_node.rb', line 136

def block_body?
  @value.is_a?(Liquid::BlockBody)
end

#block_body_end_indexObject



100
101
102
103
# File 'lib/theme_check/liquid_node.rb', line 100

def block_body_end_index
  return unless block_tag?
  block_regex.end(:body)
end

#block_body_start_indexObject



95
96
97
98
# File 'lib/theme_check/liquid_node.rb', line 95

def block_body_start_index
  return unless block_tag?
  block_regex.begin(:body)
end

#block_tag?Boolean

A tag %…endtag % node?

Returns:

  • (Boolean)


131
132
133
# File 'lib/theme_check/liquid_node.rb', line 131

def block_tag?
  @value.is_a?(Liquid::Block)
end

#childrenObject

Array of children nodes.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/theme_check/liquid_node.rb', line 18

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.map { |node| LiquidNode.new(node, self, @theme_file) }
  end
end

#comment?Boolean

A comment % block node?

Returns:

  • (Boolean)


120
121
122
# File 'lib/theme_check/liquid_node.rb', line 120

def comment?
  @value.is_a?(Liquid::Comment)
end

#document?Boolean Also known as: root?

Top level node of every liquid_file.

Returns:

  • (Boolean)


125
126
127
# File 'lib/theme_check/liquid_node.rb', line 125

def document?
  @value.is_a?(Liquid::Document)
end

#end_indexObject



73
74
75
# File 'lib/theme_check/liquid_node.rb', line 73

def end_index
  position.end_index
end

#end_tokenObject



204
205
206
207
208
209
210
211
# File 'lib/theme_check/liquid_node.rb', line 204

def end_token
  return "" if inside_liquid_tag?
  output = ""
  output += "-" if whitespace_trimmed_end?
  output += "}}" if variable?
  output += "%}" if tag?
  output
end

#end_token_indexObject



82
83
84
85
# File 'lib/theme_check/liquid_node.rb', line 82

def end_token_index
  return position.end_index if inside_liquid_tag?
  position.end_index + end_token.length
end

#inside_liquid_tag?Boolean

Is this node inside a ‘liquid … %` block?

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/theme_check/liquid_node.rb', line 158

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_numberObject

Most nodes have a line number, but it’s not guaranteed.



60
61
62
63
64
65
66
67
# File 'lib/theme_check/liquid_node.rb', line 60

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.

Returns:

  • (Boolean)


106
107
108
# File 'lib/theme_check/liquid_node.rb', line 106

def literal?
  @value.is_a?(String) || @value.is_a?(Integer)
end

#markupObject

The original source code of the node. Doesn’t contain wrapping braces.



45
46
47
48
49
50
51
# File 'lib/theme_check/liquid_node.rb', line 45

def markup
  if tag?
    tag_markup
  elsif @value.instance_variable_defined?(:@markup)
    @value.instance_variable_get(:@markup)
  end
end

#markup=(markup) ⇒ Object



53
54
55
56
57
# File 'lib/theme_check/liquid_node.rb', line 53

def markup=(markup)
  if @value.instance_variable_defined?(:@markup)
    @value.instance_variable_set(:@markup, markup)
  end
end

#render_end_tagObject



91
92
93
# File 'lib/theme_check/liquid_node.rb', line 91

def render_end_tag
  "#{start_token} #{@value.block_delimiter} #{end_token}"
end

#render_start_tagObject



87
88
89
# File 'lib/theme_check/liquid_node.rb', line 87

def render_start_tag
  "#{start_token} #{@value.raw}#{end_token}"
end

#sourceObject



151
152
153
# File 'lib/theme_check/liquid_node.rb', line 151

def source
  theme_file&.source
end

#start_indexObject



69
70
71
# File 'lib/theme_check/liquid_node.rb', line 69

def start_index
  position.start_index
end

#start_tokenObject



195
196
197
198
199
200
201
202
# File 'lib/theme_check/liquid_node.rb', line 195

def start_token
  return "" if inside_liquid_tag?
  output = ""
  output += "{{" if variable?
  output += "{%" if tag?
  output += "-" if whitespace_trimmed_start?
  output
end

#start_token_indexObject



77
78
79
80
# File 'lib/theme_check/liquid_node.rb', line 77

def start_token_index
  return position.start_index if inside_liquid_tag?
  position.start_index - (start_token.length + 1)
end

#tag?Boolean

A tag % node?

Returns:

  • (Boolean)


111
112
113
# File 'lib/theme_check/liquid_node.rb', line 111

def tag?
  @value.is_a?(Liquid::Tag)
end

#type_nameObject

The :under_score_name of this type of node. Used to dispatch to the ‘on_<type_name>` and `after_<type_name>` check methods.



147
148
149
# File 'lib/theme_check/liquid_node.rb', line 147

def type_name
  @type_name ||= StringHelpers.underscore(StringHelpers.demodulize(@value.class.name)).to_sym
end

#variable?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/theme_check/liquid_node.rb', line 115

def variable?
  @value.is_a?(Liquid::Variable)
end

#whitespace_trimmed_end?Boolean

Is this node inside a tag or variable ends starts by removing whitespace. i.e. -%} or -}}

Returns:

  • (Boolean)


185
186
187
188
189
190
191
192
193
# File 'lib/theme_check/liquid_node.rb', line 185

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 {{-

Returns:

  • (Boolean)


174
175
176
177
178
179
180
181
182
# File 'lib/theme_check/liquid_node.rb', line 174

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