liquidum 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +39 -0
  4. data/Rakefile +37 -0
  5. data/app/controllers/liquidum/application_controller.rb +5 -0
  6. data/app/controllers/liquidum/completions_controller.rb +15 -0
  7. data/app/controllers/liquidum/sandbox_controller.rb +28 -0
  8. data/app/helpers/liquidum/application_helper.rb +4 -0
  9. data/app/jobs/liquidum/application_job.rb +4 -0
  10. data/app/models/concerns/liquidum/to_liquid.rb +17 -0
  11. data/app/views/liquidum/sandbox/index.html.slim +13 -0
  12. data/config/routes.rb +4 -0
  13. data/lib/liquidum/configuration.rb +23 -0
  14. data/lib/liquidum/drop.rb +69 -0
  15. data/lib/liquidum/engine.rb +15 -0
  16. data/lib/liquidum/liquid/drops/active_storage_attached_many_drop.rb +14 -0
  17. data/lib/liquidum/liquid/drops/active_storage_attached_one_drop.rb +21 -0
  18. data/lib/liquidum/liquid/drops/active_storage_attachment_drop.rb +19 -0
  19. data/lib/liquidum/liquid/drops/enumerator_lazy_drop.rb +7 -0
  20. data/lib/liquidum/liquid/filters/array_wrap_filter.rb +14 -0
  21. data/lib/liquidum/liquid/filters/encode_filter.rb +14 -0
  22. data/lib/liquidum/liquid/filters/format_filter.rb +14 -0
  23. data/lib/liquidum/liquid/filters/localize_filter.rb +15 -0
  24. data/lib/liquidum/liquid/filters/strptime_filter.rb +14 -0
  25. data/lib/liquidum/liquid/filters/sum_filter.rb +16 -0
  26. data/lib/liquidum/liquid/filters/timezone_filter.rb +18 -0
  27. data/lib/liquidum/liquid/filters/to_filter.rb +46 -0
  28. data/lib/liquidum/liquid/filters/translate_filter.rb +45 -0
  29. data/lib/liquidum/liquid/filters/where_exp_filter.rb +70 -0
  30. data/lib/liquidum/liquid/liquid_helpers.rb +163 -0
  31. data/lib/liquidum/liquid/liquid_template_extensions.rb +34 -0
  32. data/lib/liquidum/liquid/liquidum_block.rb +5 -0
  33. data/lib/liquidum/liquid/liquidum_tag.rb +5 -0
  34. data/lib/liquidum/liquid/parser.rb +53 -0
  35. data/lib/liquidum/liquid/tags/helper_tag.rb +30 -0
  36. data/lib/liquidum/liquid/tags/render_tag.rb +19 -0
  37. data/lib/liquidum/version.rb +5 -0
  38. data/lib/liquidum.rb +77 -0
  39. metadata +318 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c706ca4c829ea154f07046f2d670039b0f7c0a83f317d04461c630c37e2228a5
4
+ data.tar.gz: 7b791bd8ca4f80aaebb89bf7bced6905625c2054d766acafc248f68148631591
5
+ SHA512:
6
+ metadata.gz: f5592e44012744611615e275e54cc5023d043b2d8e37babf792f03d3179bab71c368cc24462d2bf9e3344a07044cb44346791c00a071237258aa97e320b31de7
7
+ data.tar.gz: 1cd597b5d26227b7e950e197bc0de59b93d792b58778d5e7f179e3faa0f6bf40c42d3308a2fcb8eb90fa69b3124ae75c9e6af4ee649e496a6c86b3fe6f29d66e
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2019 Tom de Grunt
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Liquidum
2
+
3
+ Simplified use of Shopify's liquid, including some handy filters, tags and drops.
4
+
5
+ ## Usage
6
+
7
+ Basically it's as easy as:
8
+
9
+ ```ruby
10
+ Liquidum.render("{{payload.test}}", assigns: { 'payload' => { 'test' => 'blah' } })
11
+ ```
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'liquidum'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ ```bash
24
+ $ bundle
25
+ ```
26
+
27
+ Or install it yourself as:
28
+
29
+ ```bash
30
+ $ gem install liquidum
31
+ ```
32
+
33
+ ## Contributing
34
+
35
+ Contribution directions go here.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Liquidum'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ t.warning = false
31
+ end
32
+
33
+ task default: :test
34
+
35
+ # Adds the Auxilium semver task
36
+ spec = Gem::Specification.find_by_name 'auxilium'
37
+ load "#{spec.gem_dir}/lib/tasks/semver.rake"
@@ -0,0 +1,5 @@
1
+ module Liquidum
2
+ class ApplicationController < ::ApplicationController
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require_dependency "liquidum/application_controller"
2
+
3
+ module Liquidum
4
+ class CompletionsController < ApplicationController
5
+ def index
6
+ q = params[:q]
7
+ klass = q.classify.safe_constantize
8
+ drop = q.classify.concat('Drop').safe_constantize
9
+ invokables = drop&.invokable_methods || []
10
+ # drop_relations = klass.reflect_on_all_associations.map(&:name).select {|n| invokables.include?(n.to_s) }
11
+
12
+ render json: { q: q, completions: invokables }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require_dependency 'liquidum/application_controller'
2
+
3
+ module Liquidum
4
+ class SandboxController < ApplicationController
5
+ before_action :set_objects
6
+ class Sandbox
7
+ include ActiveModel::Model
8
+
9
+ attr_accessor :template, :context, :result
10
+ end
11
+
12
+ def index; end
13
+
14
+ def create
15
+ @sandbox.result = Liquidum.render(@sandbox.template, assigns: JSON.parse(@sandbox.context))
16
+ render :index
17
+ end
18
+
19
+ private
20
+
21
+ def set_objects
22
+ @sandbox = Sandbox.new(template: params.dig(:sandbox_controller_sandbox, :template) || '{{test}}',
23
+ context: params.dig(:sandbox_controller_sandbox,
24
+ :context) || '{"test": "context"}',
25
+ result: '')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ module Liquidum
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Liquidum
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_literal_strings: true
2
+
3
+ module Liquidum
4
+ module ToLiquid
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ def to_liquid
9
+ klass = "#{self.class.name}Drop".safe_constantize
10
+ klass ||= "#{self.class.base_class.name}Drop".safe_constantize if self.class.respond_to?(:base_class)
11
+ raise "No Drop defined for #{self.class.name}" unless klass
12
+
13
+ klass.new(self)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ = sts.form_for(@sandbox, url: sandbox_index_path, data: { turbo: false }) do |f|
2
+ = sts.card(title: 'Liquid Sandbox') do |card|
3
+ - card.action
4
+ = f.submit t('.render')
5
+ = sts.tabs do |t|
6
+ - t.tab :main
7
+ .grid.grid-cols-12.gap-4
8
+ .col-span-12
9
+ = f.editor :context, mode: "application/json"
10
+ .col-span-12
11
+ = f.editor :template, mode: "text/plain"
12
+ .col-span-12
13
+ = f.editor :result, mode: "text/plain", read_only: true
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Liquidum::Engine.routes.draw do
2
+ resources :completions
3
+ resources :sandbox
4
+ end
@@ -0,0 +1,23 @@
1
+ module Liquidum
2
+ class Configuration
3
+ attr_writer :logger
4
+ attr_accessor :liquidum_file_system
5
+ attr_writer :i18n_store
6
+
7
+ def initialize
8
+ @logger = Logger.new(STDOUT)
9
+ @logger.level = Logger::INFO
10
+ @liquidum_file_system = 'Liquidum::LiquidumFileSystem'
11
+ @i18n_store = ->(context, block) { nil }
12
+ end
13
+
14
+ # logger [Object].
15
+ def logger
16
+ @logger.is_a?(Proc) ? instance_exec(&@logger) : @logger
17
+ end
18
+
19
+ def i18n_store(context, &block)
20
+ @i18n_store.is_a?(Proc) ? instance_exec(context, block, &@i18n_store) : @i18n_store
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Liquidum
4
+ class Drop < Liquid::Drop
5
+ delegate :id, :errors, to: :@object
6
+
7
+ def initialize(object)
8
+ @object = object
9
+ end
10
+
11
+ def is_for_a?(klass)
12
+ @object.is_a?(klass)
13
+ end
14
+
15
+ def to_gid
16
+ @object.to_gid
17
+ end
18
+
19
+ def to_sgid
20
+ @object.to_sgid
21
+ end
22
+
23
+ def to_h(max_level = 3, current_level: 0)
24
+ return if current_level > max_level
25
+
26
+ h = {}
27
+
28
+ public_methods(false).each do |pm|
29
+ result = send(pm)
30
+
31
+ h[pm] = if result.is_a? ApplicationDrop
32
+ result.to_h(max_level, current_level: current_level + 1)
33
+ elsif result.is_a? Enumerator::Lazy
34
+ result.map { |r| r.to_h(max_level, current_level: current_level + 1) }.force
35
+ else
36
+ result
37
+ end
38
+ end
39
+ h
40
+ end
41
+
42
+ class << self
43
+ def association(*associations)
44
+ associations.each do |name|
45
+ define_method(name) do
46
+ if @object.class.respond_to?(:reflect_on_all_associations)
47
+ relation = @object.class.reflect_on_all_associations.find do |a|
48
+ a.name == name
49
+ end
50
+ end
51
+ return unless relation
52
+
53
+ klass = "#{relation.class_name}Drop".classify.safe_constantize
54
+
55
+ Rails.logger.warn "No #{klass}" and return unless klass
56
+
57
+ if relation.collection?
58
+ # FIXME: The LazyDrop has unexpected side effects for exisiting templates, this needs to be discussed further
59
+ # Enumerator::LazyDrop.new(@object.send(name).lazy.map { |o| klass.new(o) })
60
+ @object.send(name).map { |o| klass.new(o) }
61
+ else
62
+ klass.new(@object.send(name)) unless @object.send(name).nil?
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,15 @@
1
+
2
+ module Liquidum
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Liquidum
5
+
6
+ config.autoload_paths << File.expand_path(File.join(File.dirname(__FILE__), '.', 'liquid'))
7
+
8
+ initializer 'liquidum.config' do |_app|
9
+ path = File.expand_path(File.join(File.dirname(__FILE__), '.', 'liquid', '{tags,filters,drops}', '*.rb'))
10
+ Dir.glob(path).each do |c|
11
+ require_dependency(c)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveStorageAttachedManyDrop < Liquidum::Drop
4
+ include Enumerable
5
+
6
+ def initialize(object)
7
+ super
8
+ @object = @object.map { |a| ActiveStorage::AttachmentDrop.new(a) }
9
+ end
10
+
11
+ def each(&block)
12
+ @object.each(&block)
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveStorageAttachedOneDrop < Liquidum::Drop
4
+ def download
5
+ @object.download
6
+ end
7
+
8
+ def filename
9
+ @object.filename.to_s
10
+ end
11
+
12
+ def content_type
13
+ @object.content_type
14
+ end
15
+
16
+ def to_io
17
+ return unless @object.attached?
18
+
19
+ StringIO.new(@object.download)
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveStorage::AttachmentDrop < Liquidum::Drop
4
+ def download
5
+ @object.download
6
+ end
7
+
8
+ def filename
9
+ @object.filename.to_s
10
+ end
11
+
12
+ def content_type
13
+ @object.content_type
14
+ end
15
+
16
+ def [](something)
17
+ @object.send(something).to_s
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Enumerator::LazyDrop < Liquidum::Drop
4
+ def liquid_method_missing(method)
5
+ @object.send(method)
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArrayWrapFilter
4
+ # Wraps an object into an array if it is not already an array.
5
+ #
6
+ # Example:
7
+ # <div class="summary">{%assign res = payload.test['MESSAGE']['ITEM'] | array_wrap %}{%for item in res %}{{item['PN']['$']}}{%endfor%}</div>
8
+ ##
9
+ def array_wrap(input)
10
+ Array.wrap(input)
11
+ end
12
+ end
13
+
14
+ Liquid::Template.register_filter(ArrayWrapFilter)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EncodeFilter
4
+ # Encode text
5
+ #
6
+ # Example:
7
+ # <div class="summary">{{title | encode: 'utf-8'}}</div>
8
+ ##
9
+ def encode(input, encoding, options = {})
10
+ input.encode(encoding)
11
+ end
12
+ end
13
+
14
+ Liquid::Template.register_filter(EncodeFilter)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FormatFilter
4
+ # Applies format to input
5
+ #
6
+ # Example:
7
+ # <div class="summary">{{title | format: '%20s'}}</div>
8
+ ##
9
+ def format(input, format_string)
10
+ Kernel.format(format_string, input)
11
+ end
12
+ end
13
+
14
+ Liquid::Template.register_filter(FormatFilter)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LocalizeFilter
4
+ # Localize date/time
5
+ # See: http://guides.rubyonrails.org/i18n.html
6
+ #
7
+ # Examples:
8
+ #
9
+ # {{ date_time | localize: 'nl', '%d %b %R' }}
10
+ def localize(input, locale = 'en', format = nil)
11
+ I18n.l(input, format: format, locale: locale)
12
+ end
13
+ end
14
+
15
+ Liquid::Template.register_filter(LocalizeFilter)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StrptimeFilter
4
+ # Converts string to date time using format
5
+ #
6
+ # Example:
7
+ # <div class="date">{{'08012020 09:01:00'| strptime: '%D%M%Y %H:%S:%M'}}</div>
8
+ ##
9
+ def strptime(input, format_string)
10
+ DateTime.strptime(input, format_string)
11
+ end
12
+ end
13
+
14
+ Liquid::Template.register_filter(StrptimeFilter)
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SumFilter
4
+ # Sums the items in the array
5
+ #
6
+ # input - the object array
7
+ #
8
+ # Returns the sum
9
+ def sum(input)
10
+ return input unless input.respond_to?(:sum)
11
+
12
+ input = input.values if input.is_a?(Hash) # FIXME
13
+ input.sum
14
+ end
15
+ end
16
+ Liquid::Template.register_filter(SumFilter)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimezoneFilter
4
+ # Convert between timezones
5
+ # Inspired by: http://customer.io/docs/dates-timezones.html
6
+ # See: http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html
7
+ #
8
+ # Examples:
9
+ #
10
+ # {{ date_time | timezone: 'Europe/Amsterdam' }}
11
+ #
12
+ # Changes like +3 or -4 or not (yet) possible
13
+ def timezone(input, to_zone = 'UTC')
14
+ input.utc.in_time_zone(to_zone)
15
+ end
16
+ end
17
+
18
+ Liquid::Template.register_filter(TimezoneFilter)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ToFilter
4
+ # Turn object in something else
5
+ #
6
+ # Example:
7
+ # {{message.payload | to: 'json'}}
8
+ # {{message.payload | to: 'yaml'}}
9
+ #
10
+ # Advanced example:
11
+ # {{payload | to: 'json', pretty: true}}
12
+ # {%assign today = 'now'|to: 'date'%}
13
+ #
14
+ def to(input, format, options = {})
15
+ case format
16
+ when 'yaml'
17
+ to_dump = input
18
+ to_dump = to_dump.to_h if input.is_a?(HashWithIndifferentAccess)
19
+ result = YAML.dump(to_dump)
20
+ result = result.gsub(/^---\n/, '') if options['inline']
21
+ result
22
+ when 'json'
23
+ if options['pretty']
24
+ JSON.pretty_generate(input)
25
+ else
26
+ input.to_json
27
+ end
28
+ when 'date'
29
+ date = Liquid::Utils.to_date(input)
30
+
31
+ return input if date.to_s.empty?
32
+ return date if options[:format].to_s.empty?
33
+
34
+ date.strftime(options[:format].to_s)
35
+ when 'sgid'
36
+ return '' if input.nil? || !input.respond_to?(:to_sgid)
37
+
38
+ # Should accept for and expires_on options but vorto/nuntius does not allow that
39
+ input.to_sgid.to_s
40
+ else
41
+ raise 'No to format given'
42
+ end
43
+ end
44
+ end
45
+
46
+ Liquid::Template.register_filter(ToFilter)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TranslateFilter
4
+ # Translate text
5
+ #
6
+ # Example:
7
+ # <div class="summary">{{'.title' | t}}</div>
8
+ #
9
+ # provide optional locale to translate the text in, if you don't pass it it will use I18n.locale
10
+ #
11
+ # <div class="summary">{{'.title' | t: locale: 'nl'}}</div>
12
+ #
13
+ # you can provide additional arguments to be used for interpolation:
14
+ #
15
+ # <div class="summary">{{'.title' | t: gender: 'm', locale: 'nl'}}</div>
16
+ #
17
+
18
+ def translate(input, options = {})
19
+ result = nil
20
+
21
+ Liquidum.config.i18n_store(@context) do |obj|
22
+ locale = options.delete('locale')
23
+
24
+ key = input
25
+ scope = nil
26
+
27
+ if key.start_with?('.')
28
+ key = input[1..-1]
29
+ scope = obj.translation_scope
30
+ end
31
+
32
+ result = I18n.t(key, locale: locale, scope: scope, cascade: { skip_root: false },
33
+ **options.symbolize_keys)
34
+ if result
35
+ result = I18n::Backend::Simple.new.send(:interpolate, I18n.locale, result,
36
+ options.symbolize_keys)
37
+ end
38
+ end
39
+
40
+ result
41
+ end
42
+ alias t translate
43
+ end
44
+
45
+ Liquid::Template.register_filter(TranslateFilter)
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhereExpFilter
4
+ # Filters an array of objects against an expression
5
+ #
6
+ # input - the object array
7
+ # variable - the variable to assign each item to in the expression
8
+ # expression - a Liquid comparison expression passed in as a string
9
+ #
10
+ # Returns the filtered array of objects
11
+ def where_exp(input, variable, expression)
12
+ return input unless input.respond_to?(:select)
13
+
14
+ input = input.values if input.is_a?(Hash) # FIXME
15
+
16
+ condition = parse_condition(expression)
17
+ @context.stack do
18
+ input.select do |object|
19
+ @context[variable] = object
20
+ condition.evaluate(@context)
21
+ end
22
+ end || []
23
+ end
24
+
25
+ private
26
+
27
+ # Parse a string to a Liquid Condition
28
+ def parse_condition(exp)
29
+ parser = Liquid::Parser.new(exp)
30
+ condition = parse_binary_comparison(parser)
31
+
32
+ parser.consume(:end_of_string)
33
+ condition
34
+ end
35
+
36
+ # Generate a Liquid::Condition object from a Liquid::Parser object additionally processing
37
+ # the parsed expression based on whether the expression consists of binary operations with
38
+ # Liquid operators `and` or `or`
39
+ #
40
+ # - parser: an instance of Liquid::Parser
41
+ #
42
+ # Returns an instance of Liquid::Condition
43
+ def parse_binary_comparison(parser)
44
+ parse_comparison(parser).tap do |condition|
45
+ binary_operator = parser.id?("and") || parser.id?("or")
46
+ condition.send(binary_operator, parse_comparison(parser)) if binary_operator
47
+ end
48
+ end
49
+
50
+ # Generates a Liquid::Condition object from a Liquid::Parser object based on whether the parsed
51
+ # expression involves a "comparison" operator (e.g. <, ==, >, !=, etc)
52
+ #
53
+ # - parser: an instance of Liquid::Parser
54
+ #
55
+ # Returns an instance of Liquid::Condition
56
+ def parse_comparison(parser)
57
+ left_operand = Liquid::Expression.parse(parser.expression)
58
+ operator = parser.consume?(:comparison)
59
+
60
+ # No comparison-operator detected. Initialize a Liquid::Condition using only left operand
61
+ return Liquid::Condition.new(left_operand) unless operator
62
+
63
+ # Parse what remained after extracting the left operand and the `:comparison` operator
64
+ # and initialize a Liquid::Condition object using the operands and the comparison-operator
65
+ Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression))
66
+ end
67
+
68
+ end
69
+
70
+ Liquid::Template.register_filter(WhereExpFilter)