Class: Liquid2::CallTag

Inherits:
Tag show all
Defined in:
lib/liquid2/nodes/tags/macro.rb

Overview

The call tag.

Constant Summary collapse

DISABLED_TAGS =

Instance Attribute Summary collapse

Attributes inherited from Node

#blank, #token

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tag

#name

Methods inherited from Node

#block_scope, #children, #partial_scope, #render_with_disabled_tag_check, #template_scope

Constructor Details

#initialize(token, name, args, kwargs) ⇒ CallTag

Returns a new instance of CallTag.



71
72
73
74
75
76
77
# File 'lib/liquid2/nodes/tags/macro.rb', line 71

def initialize(token, name, args, kwargs)
  super(token)
  @macro_name = name
  @args = args
  @kwargs = kwargs
  @blank = false
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



55
56
57
# File 'lib/liquid2/nodes/tags/macro.rb', line 55

def args
  @args
end

#kwargsObject (readonly)

Returns the value of attribute kwargs.



55
56
57
# File 'lib/liquid2/nodes/tags/macro.rb', line 55

def kwargs
  @kwargs
end

#macro_nameObject (readonly)

Returns the value of attribute macro_name.



55
56
57
# File 'lib/liquid2/nodes/tags/macro.rb', line 55

def macro_name
  @macro_name
end

Class Method Details

.parse(token, parser) ⇒ CallTag

Parameters:

  • token ([Symbol, String?, Integer])
  • parser (Parser)

Returns:



62
63
64
65
66
67
68
69
# File 'lib/liquid2/nodes/tags/macro.rb', line 62

def self.parse(token, parser)
  name = parser.parse_name
  parser.next if parser.current_kind == :token_comma
  args, kwargs = parser.parse_arguments
  parser.carry_whitespace_control
  parser.eat(:token_tag_end)
  new(token, name, args, kwargs)
end

Instance Method Details

#expressionsObject



143
144
145
# File 'lib/liquid2/nodes/tags/macro.rb', line 143

def expressions
  [*@args, *@kwargs.map(&:value)]
end

#render(context, buffer) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/liquid2/nodes/tags/macro.rb', line 79

def render(context, buffer)
  # @type var params: Hash[String, Parameter]?
  # @type var block: Block
  params, block = context.tag_namespace[:macros][@macro_name]

  unless params
    buffer << Liquid2.to_output_string(context.env.undefined(@macro_name, node: self))
    return
  end

  # Parameter names mapped to default values. :undefined is used if there is no default.
  args = params.values.to_h { |p| [p.name, p.value] }
  excess_args = [] # : Array[untyped]
  excess_kwargs = {} # : Hash[String, untyped]

  # Update args with positional arguments.
  # Keyword arguments are pushed to the end if they appear before positional arguments.
  names = args.keys
  length = @args.length
  index = 0
  while index < length
    name = names[index]
    expr = @args[index]
    if name.nil?
      excess_args << expr
    else
      args[name] = expr
    end
    index += 1
  end

  # Update args with keyword arguments.
  @kwargs.each do |arg|
    if params.include?(arg.name)
      # This has the potential to override a positional argument.
      args[arg.name] = arg.value
    else
      excess_kwargs[arg.name] = arg.value
    end
  end

  # @type var namespace: Hash[String, untyped]
  namespace = {
    "args" => excess_args.map { |arg| context.evaluate(arg) },
    "kwargs" => excess_kwargs.transform_values! { |val| context.evaluate(val) }
  }

  args.each do |k, v|
    namespace[k] = if v == :undefined
                     context.env.undefined(k, node: params[k])
                   else
                     context.evaluate(v)
                   end
  end

  macro_context = context.copy(
    namespace,
    disabled_tags: DISABLED_TAGS,
    carry_loop_iterations: true
  )

  block.render(macro_context, buffer)
end