shoperb_liquid 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rubocop.yml +131 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +143 -0
- data/Rakefile +4 -0
- data/lib/shoperb_liquid/configuration.rb +169 -0
- data/lib/shoperb_liquid/drops/account_drop.rb +9 -0
- data/lib/shoperb_liquid/drops/address_drop.rb +121 -0
- data/lib/shoperb_liquid/drops/array_drop.rb +18 -0
- data/lib/shoperb_liquid/drops/attribute_drop.rb +21 -0
- data/lib/shoperb_liquid/drops/base.rb +65 -0
- data/lib/shoperb_liquid/drops/blog_category_drop.rb +56 -0
- data/lib/shoperb_liquid/drops/blog_post_drop.rb +46 -0
- data/lib/shoperb_liquid/drops/cart_drop.rb +42 -0
- data/lib/shoperb_liquid/drops/cart_item_drop.rb +111 -0
- data/lib/shoperb_liquid/drops/categories_drop.rb +13 -0
- data/lib/shoperb_liquid/drops/category_drop.rb +110 -0
- data/lib/shoperb_liquid/drops/collection_drop.rb +117 -0
- data/lib/shoperb_liquid/drops/country_drop.rb +37 -0
- data/lib/shoperb_liquid/drops/currency_drop.rb +17 -0
- data/lib/shoperb_liquid/drops/customer_credit_drop.rb +23 -0
- data/lib/shoperb_liquid/drops/customer_credits_drop.rb +18 -0
- data/lib/shoperb_liquid/drops/customer_drop.rb +108 -0
- data/lib/shoperb_liquid/drops/customer_group_drop.rb +17 -0
- data/lib/shoperb_liquid/drops/gift_card_drop.rb +34 -0
- data/lib/shoperb_liquid/drops/image_drop.rb +27 -0
- data/lib/shoperb_liquid/drops/integration_drop.rb +25 -0
- data/lib/shoperb_liquid/drops/integrations_drop.rb +17 -0
- data/lib/shoperb_liquid/drops/language_drop.rb +17 -0
- data/lib/shoperb_liquid/drops/link_drop.rb +53 -0
- data/lib/shoperb_liquid/drops/media_file_drop.rb +29 -0
- data/lib/shoperb_liquid/drops/menu_drop.rb +25 -0
- data/lib/shoperb_liquid/drops/menus_drop.rb +16 -0
- data/lib/shoperb_liquid/drops/meta_drop.rb +21 -0
- data/lib/shoperb_liquid/drops/order_drop.rb +148 -0
- data/lib/shoperb_liquid/drops/order_item_attribute_drop.rb +8 -0
- data/lib/shoperb_liquid/drops/order_item_attributes_drop.rb +19 -0
- data/lib/shoperb_liquid/drops/order_item_drop.rb +159 -0
- data/lib/shoperb_liquid/drops/order_return_drop.rb +43 -0
- data/lib/shoperb_liquid/drops/order_return_item_drop.rb +30 -0
- data/lib/shoperb_liquid/drops/order_return_item_entity_drop.rb +13 -0
- data/lib/shoperb_liquid/drops/order_return_parcel_drop.rb +29 -0
- data/lib/shoperb_liquid/drops/order_returns_drop.rb +13 -0
- data/lib/shoperb_liquid/drops/orders_drop.rb +14 -0
- data/lib/shoperb_liquid/drops/page_drop.rb +26 -0
- data/lib/shoperb_liquid/drops/pages_drop.rb +12 -0
- data/lib/shoperb_liquid/drops/payment_card_drop.rb +29 -0
- data/lib/shoperb_liquid/drops/payment_method_drop.rb +41 -0
- data/lib/shoperb_liquid/drops/payment_provider_drop.rb +23 -0
- data/lib/shoperb_liquid/drops/product_attribute_drop.rb +14 -0
- data/lib/shoperb_liquid/drops/product_collection_drop.rb +41 -0
- data/lib/shoperb_liquid/drops/product_collections_drop.rb +12 -0
- data/lib/shoperb_liquid/drops/product_drop.rb +195 -0
- data/lib/shoperb_liquid/drops/product_type_drop.rb +25 -0
- data/lib/shoperb_liquid/drops/product_types_drop.rb +15 -0
- data/lib/shoperb_liquid/drops/products_drop.rb +44 -0
- data/lib/shoperb_liquid/drops/refund_drop.rb +22 -0
- data/lib/shoperb_liquid/drops/refund_item_drop.rb +18 -0
- data/lib/shoperb_liquid/drops/review_drop.rb +37 -0
- data/lib/shoperb_liquid/drops/search_drop.rb +45 -0
- data/lib/shoperb_liquid/drops/shipping_item_drop.rb +29 -0
- data/lib/shoperb_liquid/drops/shipping_method_drop.rb +25 -0
- data/lib/shoperb_liquid/drops/shipping_parcel_drop.rb +25 -0
- data/lib/shoperb_liquid/drops/shop_drop.rb +81 -0
- data/lib/shoperb_liquid/drops/subscription_drop.rb +51 -0
- data/lib/shoperb_liquid/drops/subscription_plan_drop.rb +63 -0
- data/lib/shoperb_liquid/drops/theme_section_blocks_drop.rb +19 -0
- data/lib/shoperb_liquid/drops/theme_section_drop.rb +30 -0
- data/lib/shoperb_liquid/drops/theme_section_image_drop.rb +11 -0
- data/lib/shoperb_liquid/drops/theme_section_settings_drop.rb +40 -0
- data/lib/shoperb_liquid/drops/theme_settings_drop.rb +60 -0
- data/lib/shoperb_liquid/drops/url_drop.rb +218 -0
- data/lib/shoperb_liquid/drops/variant_attribute_drop.rb +8 -0
- data/lib/shoperb_liquid/drops/variant_drop.rb +206 -0
- data/lib/shoperb_liquid/drops/variants_drop.rb +13 -0
- data/lib/shoperb_liquid/drops/vendor_drop.rb +77 -0
- data/lib/shoperb_liquid/drops/vendors_drop.rb +13 -0
- data/lib/shoperb_liquid/errors.rb +6 -0
- data/lib/shoperb_liquid/ext/array.rb +7 -0
- data/lib/shoperb_liquid/ext/context.rb +12 -0
- data/lib/shoperb_liquid/ext/models.rb +55 -0
- data/lib/shoperb_liquid/ext/template.rb +13 -0
- data/lib/shoperb_liquid/filters/asset_filters.rb +57 -0
- data/lib/shoperb_liquid/filters/collection_filters.rb +26 -0
- data/lib/shoperb_liquid/filters/datum_filters.rb +150 -0
- data/lib/shoperb_liquid/filters/extension_filters.rb +35 -0
- data/lib/shoperb_liquid/filters/html_filters.rb +46 -0
- data/lib/shoperb_liquid/filters/theme_filters.rb +22 -0
- data/lib/shoperb_liquid/filters/translate_filters.rb +16 -0
- data/lib/shoperb_liquid/filters/url_filters.rb +60 -0
- data/lib/shoperb_liquid/registers.rb +76 -0
- data/lib/shoperb_liquid/tags/cache_tag.rb +45 -0
- data/lib/shoperb_liquid/tags/form_tag.rb +47 -0
- data/lib/shoperb_liquid/tags/layout_tag.rb +21 -0
- data/lib/shoperb_liquid/tags/paginate_tag.rb +134 -0
- data/lib/shoperb_liquid/tags/products_filter_tag.rb +106 -0
- data/lib/shoperb_liquid/tags/section_tag.rb +113 -0
- data/lib/shoperb_liquid.rb +46 -0
- data/shoperb_liquid.gemspec +24 -0
- metadata +223 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module ShoperbLiquid
|
2
|
+
module CollectionFilters
|
3
|
+
|
4
|
+
def with_custom_field(input, name, value, leave_blank=true)
|
5
|
+
ary = Liquid::StandardFilters::InputIterator.new(input, context)
|
6
|
+
|
7
|
+
ary.select do |el|
|
8
|
+
hash_value = el.custom_fields[name]
|
9
|
+
if hash_value
|
10
|
+
if hash_value["set_values"] == []
|
11
|
+
leave_blank
|
12
|
+
elsif !value || value == ""
|
13
|
+
false
|
14
|
+
else
|
15
|
+
hash_value["set_values"].include?(value)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
# if true and not present, then leacing in collection
|
19
|
+
leave_blank
|
20
|
+
end
|
21
|
+
end
|
22
|
+
# filter_array(input, property, target_value) { |ary, &block| ary.select(&block) }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
#
|
5
|
+
# Helpers for working with strings,
|
6
|
+
# numbers, money, dates, weight units
|
7
|
+
#
|
8
|
+
module DatumFilters
|
9
|
+
include ActionView::Helpers::NumberHelper
|
10
|
+
include ActionView::Helpers::OutputSafetyHelper
|
11
|
+
|
12
|
+
# either with symbol or code
|
13
|
+
def money(money)
|
14
|
+
_money(money, precision: money_precision(money))
|
15
|
+
end
|
16
|
+
|
17
|
+
def money_with_cents(money)
|
18
|
+
_money(money, precision: 2)
|
19
|
+
end
|
20
|
+
|
21
|
+
# with both symbol and code
|
22
|
+
def money_with_currency(money)
|
23
|
+
"#{_money(money, precision: 2)} #{shop.currency.code}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def money_precision(money)
|
27
|
+
fmt = "%05.2f" % money.to_f
|
28
|
+
_, cost_cents = fmt.split "."
|
29
|
+
|
30
|
+
cost_cents.to_i == 0 ? 0 : 2
|
31
|
+
end
|
32
|
+
|
33
|
+
# just numbers
|
34
|
+
def money_without_currency(money)
|
35
|
+
number_to_currency(money, unit: "", delimiter: " ")
|
36
|
+
end
|
37
|
+
|
38
|
+
def without_cents(money)
|
39
|
+
money.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
def num_with_2_meaning_nums(money)
|
43
|
+
"%05.2f" % money
|
44
|
+
end
|
45
|
+
|
46
|
+
def weight_with_unit(weight, precision=nil)
|
47
|
+
return if weight.nil?
|
48
|
+
|
49
|
+
weight = "%.#{precision}f" % weight if precision
|
50
|
+
|
51
|
+
"#{weight} #{shop.metric? ? "kg" : "lbs"}" # TODO
|
52
|
+
end
|
53
|
+
|
54
|
+
def dimension_with_unit(size)
|
55
|
+
"#{size} #{shop.metric? ? "cm" : "inch"}" # TODO
|
56
|
+
end
|
57
|
+
|
58
|
+
def upcase(value)
|
59
|
+
value.to_s.upcase
|
60
|
+
end
|
61
|
+
|
62
|
+
def downcase(value)
|
63
|
+
value.to_s.downcase
|
64
|
+
end
|
65
|
+
|
66
|
+
def titleize(value)
|
67
|
+
value.to_s.titlecase
|
68
|
+
end
|
69
|
+
|
70
|
+
def size(value)
|
71
|
+
value.size rescue value.to_s.size
|
72
|
+
end
|
73
|
+
|
74
|
+
def date(value, formatting)
|
75
|
+
return unless value
|
76
|
+
|
77
|
+
value = Time.at(value) if value.is_a?(Integer)
|
78
|
+
value = Time.now if value.eql?("now")
|
79
|
+
date = value.kind_of?(String) ? Date.parse(value) : value
|
80
|
+
I18n.l(date, format: formatting)
|
81
|
+
end
|
82
|
+
|
83
|
+
def pluck(value, key)
|
84
|
+
value.pluck(key)
|
85
|
+
end
|
86
|
+
|
87
|
+
def json(value)
|
88
|
+
value.to_json if value.is_a?(CollectionDrop)
|
89
|
+
end
|
90
|
+
|
91
|
+
def debug(object)
|
92
|
+
safe_join(["<pre>".html_safe, object.inspect, "</pre>".html_safe], "\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
def numeric(value)
|
96
|
+
value.to_i
|
97
|
+
end
|
98
|
+
|
99
|
+
def plus(value, add)
|
100
|
+
value.to_i + add
|
101
|
+
end
|
102
|
+
|
103
|
+
def minus(value, remove)
|
104
|
+
value.to_i - remove
|
105
|
+
end
|
106
|
+
|
107
|
+
def decimal_plus(value, add)
|
108
|
+
value.to_d + add.to_d
|
109
|
+
end
|
110
|
+
|
111
|
+
def decimal_minus(value, remove)
|
112
|
+
value.to_d - remove.to_d
|
113
|
+
end
|
114
|
+
|
115
|
+
# we use default times filter
|
116
|
+
# def times(value, times)
|
117
|
+
# value.to_i * times.to_i
|
118
|
+
# end
|
119
|
+
|
120
|
+
def decimal_times(value, times)
|
121
|
+
value.to_d * times.to_d
|
122
|
+
end
|
123
|
+
|
124
|
+
def random(value, limit=nil)
|
125
|
+
return value unless limit
|
126
|
+
value.to_a.sample limit
|
127
|
+
end
|
128
|
+
deprecate :random, deprecator: ::ActiveSupport::Deprecation
|
129
|
+
|
130
|
+
def sum(collection, field)
|
131
|
+
collection.pluck(field).sum
|
132
|
+
end
|
133
|
+
|
134
|
+
protected
|
135
|
+
|
136
|
+
def shop
|
137
|
+
@context["shop"]
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def _money(money, **args)
|
143
|
+
if shop.currency.symbol
|
144
|
+
number_to_currency(money, unit: shop.currency.symbol, format: "%u%n", delimiter: " ", **args)
|
145
|
+
else
|
146
|
+
number_to_currency(money, unit: shop.currency.code, format: "%n %u", delimiter: " ", **args)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
#
|
5
|
+
# Translating of strings in the theme
|
6
|
+
#
|
7
|
+
module ExtensionFilters
|
8
|
+
def sort(input, property = nil)
|
9
|
+
if input.is_a?(Hash)
|
10
|
+
# replacing values
|
11
|
+
property = 0 if property == "key"
|
12
|
+
property = 1 if property == "value"
|
13
|
+
|
14
|
+
ret = if property
|
15
|
+
input.sort{|a,b| nil_safe_compare(a[property],b[property])}.to_h
|
16
|
+
else
|
17
|
+
input.sort{|a,b| nil_safe_compare(a,b)}.to_h
|
18
|
+
end
|
19
|
+
return ret
|
20
|
+
end
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def nil_safe_compare(a, b)
|
25
|
+
a = a.to_s if a.is_a?(Array)
|
26
|
+
b = b.inspect if b.is_a?(Array)
|
27
|
+
if !a.nil? && !b.nil?
|
28
|
+
a <=> b
|
29
|
+
else
|
30
|
+
a.nil? ? 1 : -1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ShoperbLiquid
|
2
|
+
module HtmlFilters
|
3
|
+
def modulo_word(word, index, modulo)
|
4
|
+
index.to_i % modulo == 0 ? word : ""
|
5
|
+
end
|
6
|
+
|
7
|
+
def default_pagination(paginate, *args)
|
8
|
+
return "" if paginate["parts"].empty?
|
9
|
+
|
10
|
+
previous_label = ShoperbLiquid.config.translator.translate("navigation.previous")
|
11
|
+
next_label = ShoperbLiquid.config.translator.translate("navigation.next")
|
12
|
+
|
13
|
+
previous_link = link("previous", previous_label, paginate)
|
14
|
+
next_link = link("next", next_label, paginate)
|
15
|
+
|
16
|
+
links = ""
|
17
|
+
paginate["parts"].each do |part|
|
18
|
+
links << (if part["is_link"]
|
19
|
+
"<a class=\"page\" href=\"#{part["url"]}\">#{part["title"]}</a>"
|
20
|
+
elsif part["current"]
|
21
|
+
"<span class=\"page current\">#{part["title"]}</span>"
|
22
|
+
else
|
23
|
+
"<span class=\"page gap\">#{part["title"]}</span>"
|
24
|
+
end)
|
25
|
+
end
|
26
|
+
|
27
|
+
%{
|
28
|
+
<div class="pagination">
|
29
|
+
#{previous_link}
|
30
|
+
#{links}
|
31
|
+
#{next_link}
|
32
|
+
</div>
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def link(type, label, paginate)
|
39
|
+
if paginate[type].blank?
|
40
|
+
"<span class=\"disabled prev-page\">#{label}</span>"
|
41
|
+
else
|
42
|
+
"<a href=\"#{paginate[type]["url"]}\" class=\"prev-page\">#{label}</a>"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
module ThemeFilters
|
5
|
+
#
|
6
|
+
# returns content with values
|
7
|
+
# taken from settins
|
8
|
+
#
|
9
|
+
def customize(asset_path, settings_drop)
|
10
|
+
Theme.current.assets.find_by(
|
11
|
+
file: asset_path
|
12
|
+
).customize(
|
13
|
+
settings_drop,
|
14
|
+
host: ShoperbLiquid.config.assets_remote_host
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def image_size(image, size)
|
19
|
+
(image[size].try(:url) if image) || image
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
#
|
5
|
+
# Translating of strings in the theme
|
6
|
+
#
|
7
|
+
module TranslateFilters
|
8
|
+
def translate(string, args = {})
|
9
|
+
args[:theme] = @context.registers[:theme]
|
10
|
+
translation = ShoperbLiquid.config.translator.translate(string, **args.symbolize_keys)
|
11
|
+
Liquid::Template.parse(translation || "").render(args.stringify_keys)
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :t, :translate
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
module UrlFilters
|
5
|
+
include ActionView::Helpers::UrlHelper
|
6
|
+
|
7
|
+
def link_to_category(category)
|
8
|
+
link_to category.name, category.url, category.name
|
9
|
+
end
|
10
|
+
|
11
|
+
def link_to_product(product)
|
12
|
+
link_to product.name, product.url, product.name
|
13
|
+
end
|
14
|
+
|
15
|
+
def link_to_page(page)
|
16
|
+
link_to page.name, page.url, page.name
|
17
|
+
end
|
18
|
+
|
19
|
+
def link_to_collection(collection)
|
20
|
+
link_to collection.name, collection.url, collection.name
|
21
|
+
end
|
22
|
+
|
23
|
+
def link_to_order(obj)
|
24
|
+
link_to obj.name, obj.url, obj.name
|
25
|
+
end
|
26
|
+
|
27
|
+
def link_to_locale(text, locale)
|
28
|
+
link_to text, url_to_locale(locale)
|
29
|
+
end
|
30
|
+
|
31
|
+
def url_to_locale(locale)
|
32
|
+
pars = {locale: locale}
|
33
|
+
pars[:query] = @context["params"]["query"] if @context["params"]["query"].present? # need for search
|
34
|
+
|
35
|
+
controller = @context.registers[:controller]
|
36
|
+
if @context["params"]["id"] && (obj = @context["object"]) && obj.respond_to?(:permalink)
|
37
|
+
pars["id"] = in_locale(locale) {obj.record.to_param}
|
38
|
+
end
|
39
|
+
controller.url_for(pars)
|
40
|
+
end
|
41
|
+
|
42
|
+
def link_to_root(text)
|
43
|
+
link_to text, "/#{@context["params"]["locale"]}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def link_to(text, url, title=nil)
|
47
|
+
super text, url, title: title
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def in_locale(local_locale)
|
52
|
+
klass = ::Shoperb::Theme::Editor::Translations
|
53
|
+
old = klass.locale
|
54
|
+
klass.locale = local_locale
|
55
|
+
resp = yield
|
56
|
+
klass.locale = old
|
57
|
+
resp
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "request_store"
|
4
|
+
|
5
|
+
module ShoperbLiquid
|
6
|
+
module Registers
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def register_filters
|
10
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::UrlFilters
|
11
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::DatumFilters
|
12
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::AssetFilters
|
13
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::CollectionFilters
|
14
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::HtmlFilters
|
15
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::TranslateFilters
|
16
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::ExtensionFilters
|
17
|
+
Liquid::Environment.default.register_filter ShoperbLiquid::ThemeFilters
|
18
|
+
end
|
19
|
+
|
20
|
+
def register_tags
|
21
|
+
Liquid::Environment.default.register_tag "layout", ShoperbLiquid::LayoutTag
|
22
|
+
Liquid::Environment.default.register_tag "paginate", ShoperbLiquid::PaginateTag
|
23
|
+
Liquid::Environment.default.register_tag "form", ShoperbLiquid::FormTag
|
24
|
+
Liquid::Environment.default.register_tag "section", ShoperbLiquid::SectionTag
|
25
|
+
Liquid::Environment.default.register_tag "cache", ShoperbLiquid::CacheTag
|
26
|
+
Liquid::Environment.default.register_tag "products_filter", ShoperbLiquid::ProductsFilterTag
|
27
|
+
''
|
28
|
+
end
|
29
|
+
|
30
|
+
def options(context, locals)
|
31
|
+
context.instance_eval do
|
32
|
+
params = self.params
|
33
|
+
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
34
|
+
params = params.to_h.with_indifferent_access
|
35
|
+
|
36
|
+
{
|
37
|
+
errors: CollectionDrop.new(flash[:errors]),
|
38
|
+
meta: MetaDrop.new(locals.delete(:meta)),
|
39
|
+
categories: CategoriesDrop.new,
|
40
|
+
cart: CartDrop.new(current_cart),
|
41
|
+
carts: CollectionDrop.new(current_carts.map{|cart| CartDrop.new(cart)}),
|
42
|
+
menus: MenusDrop.new,
|
43
|
+
pages: PagesDrop.new,
|
44
|
+
blog_posts: CollectionDrop.new(BlogPost.active),
|
45
|
+
blog_categories: CollectionDrop.new(BlogCategory.active),
|
46
|
+
countries: CollectionDrop.new(Country.all),
|
47
|
+
vendors: VendorsDrop.new,
|
48
|
+
brands: VendorsDrop.new,
|
49
|
+
media_files: CollectionDrop.new(MediaFile.includes(:file)),
|
50
|
+
search: SearchDrop.new(params[:query], params[:options]),
|
51
|
+
shop: ShopDrop.new(locals[:shop]),
|
52
|
+
current_page: (params[:page].to_i rescue 1),
|
53
|
+
path: request.path,
|
54
|
+
params: params,
|
55
|
+
flash: flash.to_hash.stringify_keys,
|
56
|
+
get_params: request.query_parameters,
|
57
|
+
template_name: locals[:template].to_s,
|
58
|
+
url: Url::GetDrop.new,
|
59
|
+
form_actions: Url::PostDrop.new,
|
60
|
+
paths: Url::PostDrop.new, # alias
|
61
|
+
geoip: RequestStore["country_code"],
|
62
|
+
collections: ProductCollectionsDrop.new,
|
63
|
+
products: ProductsDrop.new,
|
64
|
+
account: CustomerDrop.new(current_customer),
|
65
|
+
settings: ThemeSettingsDrop.new(current_settings),
|
66
|
+
preview: params[:theme_id].present?,
|
67
|
+
edit_preview: params[:iframe_uuid].present?,
|
68
|
+
integrations: IntegrationsDrop.new(locals[:shop].grouped_integrations),
|
69
|
+
preconnects: defined?(ResourceHints) ? ResourceHints.preconnects : [],
|
70
|
+
product_types: ProductTypesDrop.new,
|
71
|
+
plans: CollectionDrop.new(CustomerSubscriptionPlan.active),
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
# Example {% cache product, arg1, arg2 %}
|
5
|
+
class CacheTag < ::Liquid::Block
|
6
|
+
def initialize(tag_name, markup, tokens)
|
7
|
+
super
|
8
|
+
@attrs = markup.split(/[, ]/).select(&:present?).map(&:strip)
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(context)
|
12
|
+
context.stack do
|
13
|
+
key_lookup = [
|
14
|
+
"liquid.cached",
|
15
|
+
cache_key(context.registers[:theme]),
|
16
|
+
@markup,
|
17
|
+
::I18n.locale.to_s,
|
18
|
+
]
|
19
|
+
|
20
|
+
@attrs.each do |attr|
|
21
|
+
key = cache_key(context[attr])
|
22
|
+
key_lookup << (key || attr)
|
23
|
+
end
|
24
|
+
|
25
|
+
ShoperbLiquid.config.cache.fetch(key_lookup) do
|
26
|
+
super(context)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# using activerecord cache key when possible
|
32
|
+
def cache_key(object)
|
33
|
+
instance = nil
|
34
|
+
instance = object if object.respond_to?(:updated_at)
|
35
|
+
instance = object.record if object.respond_to?(:record)
|
36
|
+
instance = object.collection if object.respond_to?(:collection)
|
37
|
+
|
38
|
+
if instance && instance.respond_to?(:cache_key)
|
39
|
+
instance.cache_key
|
40
|
+
else
|
41
|
+
object
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
# Generates feedback form
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
#
|
8
|
+
# {% form 'name' %}
|
9
|
+
# html
|
10
|
+
# {% endform %}
|
11
|
+
# <input name="subject"> - will be used for subject. Other ones will be used for body
|
12
|
+
#
|
13
|
+
class FormTag < ::Liquid::Block
|
14
|
+
SYNTAX = /(#{::Liquid::QuotedFragment})/
|
15
|
+
|
16
|
+
def initialize(tag_name, markup, tokens)
|
17
|
+
super
|
18
|
+
|
19
|
+
if markup =~ SYNTAX
|
20
|
+
@subject = $1.strip[1..-2]
|
21
|
+
else
|
22
|
+
raise ShoperbLiquid::SyntaxError, "Error in tag 'layout' - Valid syntax: form 'form_name'"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def render(context)
|
27
|
+
context.stack do
|
28
|
+
nodelist = []
|
29
|
+
nodelist << %(<form action='/submit-form' method="post">)
|
30
|
+
nodelist << %(<input type="text" name="contact_form_name" value="#{@subject}" style="color: black; display: none;" />)
|
31
|
+
nodelist << auth_token(context)
|
32
|
+
nodelist << super(context)
|
33
|
+
nodelist << %(</form>)
|
34
|
+
|
35
|
+
nodelist.join
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# returns input with protection token and honeypot protection
|
40
|
+
def auth_token(context)
|
41
|
+
controller = context.registers[:controller]
|
42
|
+
value = controller.send(:form_authenticity_token)
|
43
|
+
|
44
|
+
%(<input type="hidden" name="authenticity_token" value="#{value}"> <input autocomplete="nope" type="search" tabindex="-1" name="shoperb_first_last_name_1" value="" style="color: black; display: none;" />)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
class LayoutTag < ::Liquid::Tag
|
5
|
+
SYNTAX = /(#{::Liquid::QuotedFragment}+)(\s+(#{::Liquid::QuotedFragment}+))?/
|
6
|
+
|
7
|
+
def initialize(tag_name, markup, tokens)
|
8
|
+
super
|
9
|
+
|
10
|
+
if markup =~ SYNTAX
|
11
|
+
@layout_name = $1
|
12
|
+
else
|
13
|
+
raise ShoperbLiquid::SyntaxError, "Error in tag 'layout' - Valid syntax: layout '[layout|none]'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(context)
|
18
|
+
context.registers[:layouts] = @layout_name == "none" ? nil : @layout_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShoperbLiquid
|
4
|
+
# StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/
|
5
|
+
# FirstFilterArgument = /#{FilterArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
6
|
+
# OtherFilterArgument = /#{ArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
7
|
+
# SpacelessFilter = /^(?:'[^']+'|"[^"]+"|[^'"])*#{FilterSeparator}(?:#{StrictQuotedFragment})(?:#{FirstFilterArgument}(?:#{OtherFilterArgument})*)?/o
|
8
|
+
# Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o
|
9
|
+
# Paginate a collection
|
10
|
+
#
|
11
|
+
# Usage:
|
12
|
+
#
|
13
|
+
# {% paginate contents.projects by 5 %}
|
14
|
+
# {% for project in paginate.collection %}
|
15
|
+
# {{ project.name }}
|
16
|
+
# {% endfor %}
|
17
|
+
# {% endpaginate %}
|
18
|
+
#
|
19
|
+
class PaginateTag < ::Liquid::Block
|
20
|
+
Syntax = /(#{::Liquid::QuotedFragment})\s*(by\s*(\w+))?/
|
21
|
+
DEFAULT_PER = 20
|
22
|
+
MAXIMUM_PER = 100
|
23
|
+
|
24
|
+
def initialize(tag_name, markup, tokens)
|
25
|
+
super
|
26
|
+
|
27
|
+
if markup =~ Syntax
|
28
|
+
@collection_name = $1
|
29
|
+
@page_size = $2 ? $3 : DEFAULT_PER # save number hardcoded or variable name
|
30
|
+
|
31
|
+
@attributes = { "window_size" => 3 }
|
32
|
+
|
33
|
+
markup.scan(Liquid::TagAttributes) do |key, value|
|
34
|
+
@attributes[key] = value
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise ShoperbLiquid::SyntaxError, "Syntax Error in 'paginate' - Valid syntax: paginate <collection> by <number>"
|
38
|
+
end
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_page_number(per)
|
44
|
+
return @get_page_number if @get_page_number
|
45
|
+
|
46
|
+
@get_page_number = per.to_i
|
47
|
+
@get_page_number = (@context.scopes.last[per] || DEFAULT_PER).to_i if @get_page_number == 0
|
48
|
+
@get_page_number = MAXIMUM_PER if @get_page_number > MAXIMUM_PER
|
49
|
+
|
50
|
+
@get_page_number
|
51
|
+
end
|
52
|
+
|
53
|
+
# @page_size - is number or reference
|
54
|
+
def render(context)
|
55
|
+
@context = context
|
56
|
+
|
57
|
+
context.stack do
|
58
|
+
collection = context[@collection_name]
|
59
|
+
collection ||= CollectionDrop.new(Product.none)
|
60
|
+
|
61
|
+
current = context["current_page"].to_i == 0 ? 1 : context["current_page"].to_i
|
62
|
+
pagy,scope = collection.send(:paginate, current, get_page_number(@page_size))
|
63
|
+
|
64
|
+
paginator = {
|
65
|
+
total: pagy.count,
|
66
|
+
last: pagy.count - 1,
|
67
|
+
pages: pagy.pages,
|
68
|
+
size: pagy.limit,
|
69
|
+
offset: pagy.offset,
|
70
|
+
first: 1,
|
71
|
+
page: current,
|
72
|
+
previous: nil,
|
73
|
+
next: nil,
|
74
|
+
parts: [],
|
75
|
+
collection: scope,
|
76
|
+
}
|
77
|
+
|
78
|
+
path = context["path"]
|
79
|
+
other_params = context["get_params"]
|
80
|
+
|
81
|
+
has_prev_page = (paginator[:page] - 1) >= 1
|
82
|
+
has_next_page = (paginator[:page] + 1) <= pagy.pages
|
83
|
+
|
84
|
+
previous_text = ShoperbLiquid.config.translator.translate("navigation.previous", locale: context.registers[:locale])
|
85
|
+
next_text = ShoperbLiquid.config.translator.translate("navigation.next", locale: context.registers[:locale])
|
86
|
+
|
87
|
+
paginator[:previous] = link(previous_text, paginator[:page] - 1, path, other_params) if has_prev_page
|
88
|
+
paginator[:next] = link(next_text, paginator[:page] + 1, path, other_params) if has_next_page
|
89
|
+
|
90
|
+
hellip_break = false
|
91
|
+
|
92
|
+
if paginator[:pages] > 1
|
93
|
+
1.upto(paginator[:pages]) do |page|
|
94
|
+
if paginator[:page] == page
|
95
|
+
paginator[:parts] << no_link(page)
|
96
|
+
elsif page == 1
|
97
|
+
paginator[:parts] << link(page, page, path, other_params)
|
98
|
+
elsif page == paginator[:pages]
|
99
|
+
paginator[:parts] << link(page, page, path, other_params)
|
100
|
+
elsif page <= paginator[:page] - window_size || page >= paginator[:page] + window_size
|
101
|
+
next if hellip_break
|
102
|
+
paginator[:parts] << no_link("…")
|
103
|
+
hellip_break = true
|
104
|
+
next
|
105
|
+
else
|
106
|
+
paginator[:parts] << link(page, page, path, other_params)
|
107
|
+
end
|
108
|
+
|
109
|
+
hellip_break = false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context["paginate"] = paginator.stringify_keys!
|
114
|
+
|
115
|
+
super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def window_size
|
122
|
+
@attributes["window_size"]
|
123
|
+
end
|
124
|
+
|
125
|
+
def no_link(title)
|
126
|
+
{ "title" => title, "is_link" => false, "current" => title != "…" }
|
127
|
+
end
|
128
|
+
|
129
|
+
def link(title, page, path, other_params={})
|
130
|
+
params = other_params.merge("page" => page)
|
131
|
+
{ "title" => title, "url" => path + "?#{params.to_query}", "is_link" => true }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|