Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New attribute parser for the with_scope tag #239

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1.4
ruby-version: 3.3.5
bundler-cache: true
cache-version: 1

Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ group :test do

gem 'rack-test', '~> 2.1.0'

gem 'simplecov', '~> 0.22.0', require: false
gem 'simplecov', '~> 0.22.0', require: false
end
7 changes: 5 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ PATH
morphine (~> 0.1.1)
multi_json (~> 1.15.0)
nokogiri (~> 1.15.6)
parser (~> 3.3)
pony (~> 1.12)
rack-cache (>= 1.7, < 2)
rack-rewrite (~> 1.5.1)
Expand All @@ -41,6 +42,7 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.2)
attr_extras (7.1.0)
base64 (0.2.0)
bcrypt (3.1.20)
Expand Down Expand Up @@ -120,9 +122,10 @@ GEM
nokogiri (1.15.6)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.15.6-x86_64-darwin)
racc (~> 1.4)
origin (2.3.1)
parser (3.3.5.0)
ast (~> 2.4.1)
racc
pony (1.13.1)
mail (>= 2.0)
public_suffix (6.0.0)
Expand Down
4 changes: 3 additions & 1 deletion lib/locomotive/steam/liquid.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require 'liquid'
require 'parser/current'
require 'ast'

require_relative 'liquid/errors'
require_relative 'liquid/patches'
Expand All @@ -7,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
Loading