Skip to content

Commit

Permalink
improve the performance of the with_scope attributes parsing + use a …
Browse files Browse the repository at this point in the history
…different name of the simple version of the parser
  • Loading branch information
did committed Sep 20, 2024
1 parent 7249945 commit 4e54eec
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 238 deletions.
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
require_relative 'liquid/drops/i18n_base'
require_relative 'liquid/tags/hybrid'
require_relative 'liquid/tags/concerns/section'
require_relative 'liquid/tags/concerns/attributes'
require_relative 'liquid/tags/concerns/simple_attributes_parser'
require_relative 'liquid/tags/section'
require_relative_all %w(. drops filters tags/concerns tags), 'liquid'
142 changes: 142 additions & 0 deletions lib/locomotive/steam/liquid/tags/concerns/attributes_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
module Locomotive
module Steam
module Liquid
module Tags
module Concerns

# The with_scope liquid tag lets the developer use a Ruby syntax to
# pass options which is difficult to implement with the Liquid parsing
# approach (see the SimpleAttributesParser for instance)
module AttributesParser
extend ActiveSupport::Concern

def parse_markup(markup)
parser = self.class.current_parser

# 'liquid_code.rb' is purely arbitrary
source_buffer = ::Parser::Source::Buffer.new('liquid_code.rb')
source_buffer.source = "{%s}" % markup

ast = parser.parse(source_buffer)
AstProcessor.new.process(ast)
end

class_methods do
def current_parser
(@current_parser ||= build_parser).tap do |parser|
parser.reset
end
end

def build_parser
::Parser::CurrentRuby.new.tap do |parser|
# Silent the error instead of logging them to STDERR (default behavior of the parser)
parser.diagnostics.consumer = ->(message) { true }
end
end
end

class AstProcessor
include AST::Processor::Mixin

def on_hash(node)
nodes = process_all(node)
nodes.inject({}) { |memo, sub_hash| memo.merge(sub_hash) }
end

def on_pair(node)
key_expr, right_expr = *node
{ process(key_expr) => process(right_expr) }
end

def on_sym(node)
node.children.first.to_sym
end

def on_array(node)
process_all(node)
end

def on_int(node)
node.children.first.to_i
end

def on_float(node)
node.children.first.to_f
end

def on_str(node)
node.children.first.to_s
end

def on_true(node)
true
end

def on_false(node)
false
end

def on_regexp(node)
regexp_expr, opts_expr = *node
Regexp.new(process(regexp_expr), process(opts_expr))
end

def on_regopt(node)
node.children ? node.children.join('') : nil
end

def on_deep_send(node)
source_expr, name_expr = *node

if source_expr.nil?
[name_expr.to_s]
elsif source_expr.type == :send
process(source_expr.updated(:deep_send, nil)) << name_expr.to_s
else
raise 'NOT IMPLEMENTED [DEEP_SEND]' # TODO
end
end

def on_send(node)
source_expr, name_expr = *node

if source_expr.nil?
::Liquid::Expression.parse(name_expr.to_s)
elsif name_expr == :+
process(source_expr)
elsif source_expr.type == :send
::Liquid::Expression.parse(
(process(source_expr.updated(:deep_send, nil)) << name_expr.to_s).join('.')
)
else
raise 'NOT IMPLEMENTED [SEND]' # TODO
end
end

# HACK: override the default process implementation
def process(node)
return if node.nil?

node = node.to_ast

# Invoke a specific handler
on_handler = :"on_#{node.type}"
if respond_to? on_handler
new_node = send on_handler, node
else
new_node = handler_missing(node)
end

# fix: the original method considered false as nil which is incorrect
node = new_node unless new_node.nil?

node
end
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ module Concerns
# Many of Liquid tags have attributes (like options)
# This module makes sure we use the same reliable way to
# extract and evaluate them.

module Attributes
module SimpleAttributesParser

attr_reader :attributes, :raw_attributes

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/consume.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Tags
#
class Consume < ::Liquid::Block

include Concerns::Attributes
include Concerns::SimpleAttributesParser

Syntax = /(#{::Liquid::VariableSignature}+)\s*from\s*(#{::Liquid::QuotedFragment}+),?(.+)?/o.freeze

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/editable/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Tags
module Editable
class Base < ::Liquid::Block

include Concerns::Attributes
include Concerns::SimpleAttributesParser

Syntax = /(#{::Liquid::QuotedFragment})(\s*,\s*#{::Liquid::Expression}+)?/o

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/inherited_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Tags
#
class InheritedBlock < ::Liquid::Block

include Concerns::Attributes
include Concerns::SimpleAttributesParser

SYNTAX = /(#{::Liquid::QuotedFragment}+)/o

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/link_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Liquid
module Tags
class LinkTo < Hybrid

include Concerns::Attributes
include Concerns::SimpleAttributesParser
include Concerns::I18nPage
include Concerns::Path

Expand Down
3 changes: 1 addition & 2 deletions lib/locomotive/steam/liquid/tags/locale_switcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ module Tags
# - "iso" is the default choice for label
# - " | " is the default separating code
#

class LocaleSwitcher < ::Liquid::Tag

include Concerns::Attributes
include Concerns::SimpleAttributesParser
include Concerns::I18nPage

attr_reader :attributes, :site, :page, :current_locale, :url_builder
Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/model_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Tags
#
class ModelForm < ::Liquid::Block

include Concerns::Attributes
include Concerns::SimpleAttributesParser

Syntax = /(#{::Liquid::QuotedFragment})\s*,*(.*)?/o.freeze

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/paginate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Tags
#
class Paginate < ::Liquid::Block

include Concerns::Attributes
include Concerns::SimpleAttributesParser

Syntax = /(#{::Liquid::QuotedFragment}+)\s+by\s+(#{::Liquid::QuotedFragment}+)/o

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/path_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Liquid
module Tags
class PathTo < ::Liquid::Tag

include Concerns::Attributes
include Concerns::SimpleAttributesParser
include Concerns::I18nPage
include Concerns::Path

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/redirect_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Tags

class RedirectTo < ::Liquid::Tag

include Concerns::Attributes
include Concerns::SimpleAttributesParser
include Concerns::I18nPage
include Concerns::Path

Expand Down
2 changes: 1 addition & 1 deletion lib/locomotive/steam/liquid/tags/section.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Tags
class Section < ::Liquid::Include

include Concerns::Section
include Concerns::Attributes
include Concerns::SimpleAttributesParser

Syntax = /(#{::Liquid::QuotedString}|#{::Liquid::VariableSignature}+)\s*,*(.*)?/o.freeze

Expand Down
Loading

0 comments on commit 4e54eec

Please sign in to comment.