dugway 1.1.0 → 1.3.0
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 +4 -4
- data/.bundle/config +2 -0
- data/.github/workflows/main.yml +1 -1
- data/.gitignore +1 -0
- data/README.md +32 -7
- data/dugway.gemspec +11 -9
- data/lib/dugway/application.rb +5 -3
- data/lib/dugway/assets/big_cartel_logo.svg +4 -0
- data/lib/dugway/cli/build.rb +7 -1
- data/lib/dugway/cli/server.rb +69 -9
- data/lib/dugway/cli/templates/source/settings.json +8 -0
- data/lib/dugway/cli/validate.rb +9 -2
- data/lib/dugway/controller.rb +5 -1
- data/lib/dugway/liquid/drops/account_drop.rb +4 -0
- data/lib/dugway/liquid/drops/artists_drop.rb +12 -0
- data/lib/dugway/liquid/drops/base_drop.rb +27 -2
- data/lib/dugway/liquid/drops/categories_drop.rb +12 -0
- data/lib/dugway/liquid/drops/features_drop.rb +144 -0
- data/lib/dugway/liquid/drops/pages_drop.rb +30 -2
- data/lib/dugway/liquid/drops/product_drop.rb +11 -0
- data/lib/dugway/liquid/drops/products_drop.rb +39 -0
- data/lib/dugway/liquid/drops/theme_drop.rb +52 -6
- data/lib/dugway/liquid/drops/translations_drop.rb +122 -0
- data/lib/dugway/liquid/filters/core_filters.rb +169 -7
- data/lib/dugway/liquid/filters/font_filters.rb +1 -0
- data/lib/dugway/liquid/filters/util_filters.rb +1 -10
- data/lib/dugway/liquid/tags/get.rb +6 -6
- data/lib/dugway/liquid/tags/paginate.rb +61 -11
- data/lib/dugway/liquifier.rb +44 -8
- data/lib/dugway/store.rb +46 -3
- data/lib/dugway/theme.rb +151 -15
- data/lib/dugway/version.rb +1 -1
- data/lib/dugway.rb +55 -2
- data/locales/storefront.de.yml +81 -0
- data/locales/storefront.en-CA.yml +81 -0
- data/locales/storefront.en-GB.yml +81 -0
- data/locales/storefront.en-US.yml +81 -0
- data/locales/storefront.es-ES.yml +81 -0
- data/locales/storefront.es-MX.yml +81 -0
- data/locales/storefront.fr-CA.yml +81 -0
- data/locales/storefront.fr-FR.yml +81 -0
- data/locales/storefront.id.yml +81 -0
- data/locales/storefront.it.yml +81 -0
- data/locales/storefront.ja.yml +81 -0
- data/locales/storefront.ko.yml +81 -0
- data/locales/storefront.nl.yml +81 -0
- data/locales/storefront.pl.yml +81 -0
- data/locales/storefront.pt-BR.yml +81 -0
- data/locales/storefront.pt-PT.yml +81 -0
- data/locales/storefront.ro.yml +81 -0
- data/locales/storefront.sv.yml +81 -0
- data/locales/storefront.tr.yml +81 -0
- data/locales/storefront.zh-CN.yml +81 -0
- data/locales/storefront.zh-TW.yml +81 -0
- data/log/dugway.log +1 -0
- data/mise.toml +2 -0
- data/spec/features/page_rendering_spec.rb +4 -4
- data/spec/fixtures/theme/layout.html +2 -0
- data/spec/fixtures/theme/settings.json +6 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/units/dugway/liquid/drops/features_drop_spec.rb +182 -0
- data/spec/units/dugway/liquid/drops/pages_drop_spec.rb +186 -7
- data/spec/units/dugway/liquid/drops/product_drop_spec.rb +17 -0
- data/spec/units/dugway/liquid/drops/theme_drop_spec.rb +45 -0
- data/spec/units/dugway/liquid/drops/translations_drop_spec.rb +292 -0
- data/spec/units/dugway/liquid/filters/core_filters_spec.rb +301 -3
- data/spec/units/dugway/store_spec.rb +55 -0
- data/spec/units/dugway/theme_spec.rb +543 -1
- metadata +84 -25
@@ -40,21 +40,89 @@ module Dugway
|
|
40
40
|
when 'sign' then money_with_sign(amount)
|
41
41
|
when 'code' then money_with_code(amount)
|
42
42
|
when 'sign_and_code' then money_with_sign_and_code(amount)
|
43
|
-
|
43
|
+
when 'rounded' then
|
44
|
+
begin
|
45
|
+
number_to_currency(amount.ceil, { :unit => '', :format => '%n', :precision => 0 }).to_s.strip
|
46
|
+
rescue FrozenError => e
|
47
|
+
sprintf('%.0f', amount.ceil.to_f)
|
48
|
+
end
|
49
|
+
when 'sign_rounded' then money_with_sign(amount.ceil, 0)
|
50
|
+
when 'code_rounded' then money_with_code(amount.ceil, 0)
|
51
|
+
else
|
52
|
+
begin
|
53
|
+
number_to_currency(amount, { :unit => '', :format => '%n' }).to_s.strip
|
54
|
+
rescue FrozenError => e
|
55
|
+
# Fallback for frozen hash issues in newer Ruby versions
|
56
|
+
sprintf('%.2f', amount.to_f)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def product_price(product, money_format = nil, range_format = nil)
|
62
|
+
return unless product
|
63
|
+
|
64
|
+
if product['variable_pricing']
|
65
|
+
case range_format
|
66
|
+
when 'min_only'
|
67
|
+
money(product['min_price'], money_format)
|
68
|
+
when 'max_only'
|
69
|
+
money(product['max_price'], money_format)
|
70
|
+
else # default, nil, or any other value
|
71
|
+
format_price_range(product['min_price'], product['max_price'], money_format)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
money(product['default_price'] || product['price'], money_format)
|
44
75
|
end
|
45
76
|
end
|
46
77
|
|
47
|
-
def money_with_sign(amount)
|
48
|
-
|
49
|
-
|
78
|
+
def money_with_sign(amount, precision = nil)
|
79
|
+
begin
|
80
|
+
unit = I18n.translate('number.currency.format.unit')
|
81
|
+
options = { :unit => "<span class=\"currency_sign\">#{HTMLEntities.new.encode(unit, :named)}</span>" }
|
82
|
+
options[:precision] = precision if precision
|
83
|
+
number_to_currency(amount, options)
|
84
|
+
rescue FrozenError => e
|
85
|
+
# Fallback for frozen hash issues
|
86
|
+
format_string = precision == 0 ? '%.0f' : '%.2f'
|
87
|
+
"<span class=\"currency_sign\">$</span>#{sprintf(format_string, amount.to_f)}"
|
88
|
+
end
|
50
89
|
end
|
51
90
|
|
52
|
-
def money_with_code(amount)
|
53
|
-
|
91
|
+
def money_with_code(amount, precision = nil)
|
92
|
+
begin
|
93
|
+
# Format number without currency unit, respecting locale's number formatting rules
|
94
|
+
number_locale = normalize_currency_locale_for_formatting(currency['locale'])
|
95
|
+
options = { :unit => '', :format => '%n', :locale => number_locale }
|
96
|
+
options[:precision] = precision if precision
|
97
|
+
formatted_number = number_to_currency(amount, options).to_s.strip
|
98
|
+
|
99
|
+
# Use locale-specific format string to ensure proper currency code placement
|
100
|
+
# Keep original locale for bigcartel-currency-locales gem compatibility
|
101
|
+
format_string = I18n.translate('number.currency.format.format',
|
102
|
+
:locale => currency['locale'],
|
103
|
+
:default => '%u%n')
|
104
|
+
|
105
|
+
code_span = "<span class=\"currency_code\">#{currency['code']}</span>"
|
106
|
+
format_string.gsub('%n', formatted_number).gsub('%u', code_span)
|
107
|
+
rescue => e
|
108
|
+
# Fallback for frozen hash or I18n issues
|
109
|
+
format_string = precision == 0 ? '%.0f' : '%.2f'
|
110
|
+
"<span class=\"currency_code\">#{currency['code']}</span>#{sprintf(format_string, amount.to_f)}"
|
111
|
+
end
|
54
112
|
end
|
55
113
|
|
56
114
|
def money_with_sign_and_code(amount)
|
57
|
-
%{#{ money_with_sign(amount) } <span class="currency_code">#{ currency['code'] }</span>}
|
115
|
+
%{#{ money_with_sign(amount).to_s } <span class="currency_code">#{ currency['code'] }</span>}
|
116
|
+
end
|
117
|
+
|
118
|
+
# Liquid 5.x compatibility: ensure proper JSON output
|
119
|
+
def to_json(input)
|
120
|
+
# Handle Liquid Drops specially - use as_json for serialization
|
121
|
+
if input.respond_to?(:as_json)
|
122
|
+
JSON.generate(input.as_json)
|
123
|
+
else
|
124
|
+
JSON.generate(input)
|
125
|
+
end
|
58
126
|
end
|
59
127
|
|
60
128
|
# Shipping Filters
|
@@ -137,10 +205,104 @@ module Dugway
|
|
137
205
|
|
138
206
|
private
|
139
207
|
|
208
|
+
def currency
|
209
|
+
@context.registers[:currency]
|
210
|
+
end
|
211
|
+
|
140
212
|
def contact_tab_index
|
141
213
|
@contact_tab_index ||= 0
|
142
214
|
@contact_tab_index += 1
|
143
215
|
end
|
216
|
+
|
217
|
+
def format_price_range(min_price, max_price, money_format)
|
218
|
+
case money_format
|
219
|
+
when "sign"
|
220
|
+
format_range_with_sign(min_price, max_price)
|
221
|
+
when "code"
|
222
|
+
format_range_with_code(min_price, max_price)
|
223
|
+
when "sign_rounded"
|
224
|
+
format_range_with_sign(min_price.ceil, max_price.ceil, 0)
|
225
|
+
when "code_rounded"
|
226
|
+
format_range_with_code(min_price.ceil, max_price.ceil, 0)
|
227
|
+
when "rounded"
|
228
|
+
format_range_plain(min_price.ceil, max_price.ceil, 0)
|
229
|
+
else
|
230
|
+
format_range_plain(min_price, max_price)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def format_range_with_sign(min_price, max_price, precision = nil)
|
235
|
+
# Sign on both prices for clarity
|
236
|
+
# US: $10.00 - $20.00 | FR: 10,00 € - 20,00 €
|
237
|
+
min_formatted = money_with_sign(min_price, precision)
|
238
|
+
max_formatted = money_with_sign(max_price, precision)
|
239
|
+
"#{min_formatted} - #{max_formatted}"
|
240
|
+
end
|
241
|
+
|
242
|
+
def format_range_with_code(min_price, max_price, precision = nil)
|
243
|
+
# Single code in locale-appropriate position
|
244
|
+
# US: $10.00 - 20.00 USD | FR: 10,00 - 20,00 EUR
|
245
|
+
code_span = "<span class=\"currency_code\">#{currency['code']}</span>"
|
246
|
+
range_string = build_number_range(min_price, max_price, precision)
|
247
|
+
apply_currency_format(range_string, code_span)
|
248
|
+
end
|
249
|
+
|
250
|
+
def format_range_plain(min_price, max_price, precision = nil)
|
251
|
+
# No currency indicators
|
252
|
+
begin
|
253
|
+
options = { :unit => '', :format => '%n' }
|
254
|
+
options[:precision] = precision if precision
|
255
|
+
min_formatted = number_to_currency(min_price, options).to_s.strip
|
256
|
+
max_formatted = number_to_currency(max_price, options).to_s.strip
|
257
|
+
"#{min_formatted} - #{max_formatted}"
|
258
|
+
rescue FrozenError => e
|
259
|
+
# Fallback for frozen hash issues
|
260
|
+
format_string = precision == 0 ? '%.0f' : '%.2f'
|
261
|
+
"#{sprintf(format_string, min_price.to_f)} - #{sprintf(format_string, max_price.to_f)}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def build_number_range(min_price, max_price, precision = nil)
|
266
|
+
min_formatted = format_number_plain(min_price, precision)
|
267
|
+
max_formatted = format_number_plain(max_price, precision)
|
268
|
+
"#{min_formatted} - #{max_formatted}"
|
269
|
+
end
|
270
|
+
|
271
|
+
def format_number_plain(amount, precision = nil)
|
272
|
+
begin
|
273
|
+
number_locale = normalize_currency_locale_for_formatting(currency['locale'])
|
274
|
+
options = { :unit => '', :format => '%n', :locale => number_locale }
|
275
|
+
options[:precision] = precision if precision
|
276
|
+
number_to_currency(amount, options).to_s.strip
|
277
|
+
rescue FrozenError => e
|
278
|
+
format_string = precision == 0 ? '%.0f' : '%.2f'
|
279
|
+
sprintf(format_string, amount.to_f)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def apply_currency_format(range_string, currency_span)
|
284
|
+
# Use I18n to get locale-specific format like storefront does
|
285
|
+
begin
|
286
|
+
# Keep original locale for bigcartel-currency-locales gem compatibility
|
287
|
+
format_string = I18n.translate('number.currency.format.format',
|
288
|
+
locale: currency['locale'],
|
289
|
+
default: '%u%n')
|
290
|
+
format_string.gsub('%n', range_string).gsub('%u', currency_span)
|
291
|
+
rescue
|
292
|
+
# Fallback if I18n fails
|
293
|
+
"#{range_string} #{currency_span}"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def normalize_currency_locale_for_formatting(locale)
|
298
|
+
# Handle invalid 'eu' locale from production system for number formatting only
|
299
|
+
case locale
|
300
|
+
when 'eu'
|
301
|
+
'de-DE' # Use German locale for EUR number formatting (1.200,99 style)
|
302
|
+
else
|
303
|
+
locale
|
304
|
+
end
|
305
|
+
end
|
144
306
|
end
|
145
307
|
end
|
146
308
|
end
|
@@ -1,15 +1,6 @@
|
|
1
1
|
module Dugway
|
2
2
|
module Filters
|
3
3
|
module UtilFilters
|
4
|
-
private
|
5
|
-
|
6
|
-
# Registered Vars
|
7
|
-
|
8
|
-
def currency
|
9
|
-
@context.registers[:currency]
|
10
|
-
end
|
11
|
-
|
12
|
-
# Mimics
|
13
4
|
|
14
5
|
DEFAULT_CURRENCY_VALUES = { :format => "%u%n", :negative_format => "-%u%n", :unit => "$", :separator => ".", :delimiter => ",", :precision => 2, :significant => false, :strip_insignificant_zeros => false }
|
15
6
|
|
@@ -126,7 +117,7 @@ module Dugway
|
|
126
117
|
|
127
118
|
def content_tag(type, content, options = {})
|
128
119
|
result = tag(type, options, true)
|
129
|
-
result += content
|
120
|
+
result += content.to_s
|
130
121
|
result += "</#{type}>"
|
131
122
|
end
|
132
123
|
|
@@ -5,16 +5,16 @@ module Dugway
|
|
5
5
|
|
6
6
|
def initialize(tag_name, markup, tokens)
|
7
7
|
if markup =~ Syntax
|
8
|
-
@number_to_get =
|
9
|
-
@variable_name =
|
10
|
-
@collection_name =
|
8
|
+
@number_to_get = Regexp.last_match(1).present? ? Regexp.last_match(2) : nil
|
9
|
+
@variable_name = Regexp.last_match(3)
|
10
|
+
@collection_name = Regexp.last_match(4)
|
11
11
|
|
12
12
|
@attributes = {}
|
13
13
|
markup.scan(Liquid::TagAttributes) { |key, value|
|
14
14
|
@attributes[key] = value
|
15
15
|
}
|
16
16
|
else
|
17
|
-
raise SyntaxError
|
17
|
+
raise SyntaxError, "Syntax Error in tag 'get' - Valid syntax: get [number] [items] from [collection] order:[order]"
|
18
18
|
end
|
19
19
|
|
20
20
|
super
|
@@ -48,9 +48,9 @@ module Dugway
|
|
48
48
|
|
49
49
|
context[@variable_name] = context[@collection_name]
|
50
50
|
|
51
|
-
raise ArgumentError
|
51
|
+
raise ArgumentError, "Cannot get array '#{@collection_name}'. Not found." if context[@variable_name].total_entries.nil?
|
52
52
|
|
53
|
-
|
53
|
+
super(context)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -5,9 +5,9 @@ module Dugway
|
|
5
5
|
|
6
6
|
def initialize(tag_name, markup, tokens)
|
7
7
|
if markup =~ Syntax
|
8
|
-
@variable_name =
|
9
|
-
@collection_name =
|
10
|
-
@per_page =
|
8
|
+
@variable_name = Regexp.last_match(1)
|
9
|
+
@collection_name = Regexp.last_match(2)
|
10
|
+
@per_page = Regexp.last_match(3).present? ? Regexp.last_match(4) : nil
|
11
11
|
|
12
12
|
@attributes = { 'inner_window' => 3, 'outer_window' => 1 }
|
13
13
|
|
@@ -17,7 +17,7 @@ module Dugway
|
|
17
17
|
|
18
18
|
@limit = @attributes['limit']
|
19
19
|
else
|
20
|
-
raise SyntaxError
|
20
|
+
raise SyntaxError, "Syntax Error in tag 'paginate' - Valid syntax: paginate [variable] from [collection] by [number]"
|
21
21
|
end
|
22
22
|
|
23
23
|
super
|
@@ -29,6 +29,7 @@ module Dugway
|
|
29
29
|
@per_page = context[@per_page].present? ? context[@per_page] : (@per_page.present? ? @per_page.to_i : nil)
|
30
30
|
@order = context[@attributes['order']].present? ? context[@attributes['order']] : @attributes['order']
|
31
31
|
|
32
|
+
|
32
33
|
context.stack do
|
33
34
|
context['internal'] = {
|
34
35
|
'per_page' => @per_page,
|
@@ -37,21 +38,45 @@ module Dugway
|
|
37
38
|
'limit' => @limit
|
38
39
|
}
|
39
40
|
|
40
|
-
|
41
|
+
# Handle nested property access like "products.current"
|
42
|
+
collection = resolve_collection_path(context, @collection_name)
|
43
|
+
|
41
44
|
context[@variable_name] = collection
|
42
|
-
|
45
|
+
|
46
|
+
begin
|
47
|
+
current_page = collection.current_page
|
48
|
+
rescue StandardError => e
|
49
|
+
puts "Warning: Failed to get current_page: #{e.message}" if ENV['DEBUG']
|
50
|
+
current_page = 1
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
page_size = collection.per_page
|
55
|
+
offset = collection.offset
|
56
|
+
rescue StandardError => e
|
57
|
+
puts "Warning: Failed to get pagination info: #{e.message}" if ENV['DEBUG']
|
58
|
+
page_size = 10
|
59
|
+
offset = 0
|
60
|
+
end
|
43
61
|
|
44
62
|
pagination = {
|
45
|
-
'page_size' =>
|
63
|
+
'page_size' => page_size,
|
46
64
|
'current_page' => current_page,
|
47
|
-
'current_offset' =>
|
65
|
+
'current_offset' => offset
|
48
66
|
}
|
49
67
|
|
50
68
|
context['paginate'] = pagination
|
51
69
|
|
52
|
-
|
70
|
+
begin
|
71
|
+
collection_size = collection.total_entries
|
72
|
+
rescue StandardError => e
|
73
|
+
puts "Warning: Failed to get total_entries: #{e.message}" if ENV['DEBUG']
|
74
|
+
collection_size = collection.respond_to?(:size) ? collection.size : 0
|
75
|
+
end
|
53
76
|
|
54
|
-
|
77
|
+
if collection_size.nil? || collection_size == 0
|
78
|
+
return ""
|
79
|
+
end
|
55
80
|
|
56
81
|
page_count = collection.total_pages
|
57
82
|
|
@@ -103,12 +128,37 @@ module Dugway
|
|
103
128
|
}
|
104
129
|
end
|
105
130
|
|
106
|
-
|
131
|
+
super(context)
|
107
132
|
end
|
108
133
|
end
|
109
134
|
|
110
135
|
private
|
111
136
|
|
137
|
+
def resolve_collection_path(context, path)
|
138
|
+
return context[path] unless path.include?('.')
|
139
|
+
|
140
|
+
parts = path.split('.')
|
141
|
+
collection = context[parts.shift]
|
142
|
+
|
143
|
+
parts.each do |part|
|
144
|
+
break unless collection
|
145
|
+
|
146
|
+
if collection.respond_to?(part)
|
147
|
+
collection = collection.public_send(part)
|
148
|
+
elsif collection.respond_to?(:liquid_method_missing)
|
149
|
+
collection = collection.liquid_method_missing(part)
|
150
|
+
else
|
151
|
+
collection = nil
|
152
|
+
break
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
collection || []
|
157
|
+
rescue StandardError => e
|
158
|
+
puts "Warning: Failed to resolve collection '#{path}': #{e.message}" if ENV['DEBUG']
|
159
|
+
[]
|
160
|
+
end
|
161
|
+
|
112
162
|
def no_link(title)
|
113
163
|
{ 'title' => title.to_s, 'is_link' => false }
|
114
164
|
end
|
data/lib/dugway/liquifier.rb
CHANGED
@@ -16,6 +16,7 @@ module Dugway
|
|
16
16
|
class Liquifier
|
17
17
|
def initialize(request)
|
18
18
|
@request = request
|
19
|
+
load_theme_locales
|
19
20
|
end
|
20
21
|
|
21
22
|
def render(content, variables={})
|
@@ -41,7 +42,7 @@ module Dugway
|
|
41
42
|
|
42
43
|
def self.render_styles(css)
|
43
44
|
Liquid::Template.parse(css).render!(
|
44
|
-
{ 'theme' => Drops::ThemeDrop.new(Dugway.theme.customization) },
|
45
|
+
{ 'theme' => Drops::ThemeDrop.new(Dugway.theme.customization, Dugway.theme.settings) },
|
45
46
|
:registers => { :settings => Dugway.theme.settings }
|
46
47
|
)
|
47
48
|
end
|
@@ -68,7 +69,8 @@ module Dugway
|
|
68
69
|
{
|
69
70
|
'store' => Drops::AccountDrop.new(store.account),
|
70
71
|
'cart' => Drops::CartDrop.new(cart),
|
71
|
-
|
72
|
+
# Pass both customization and definitions to ThemeDrop
|
73
|
+
'theme' => Drops::ThemeDrop.new(theme.customization, theme.settings),
|
72
74
|
'pages' => Drops::PagesDrop.new(store.pages.map { |p| Drops::PageDrop.new(p) }),
|
73
75
|
'categories' => Drops::CategoriesDrop.new(store.categories.map { |c| Drops::CategoryDrop.new(c) }),
|
74
76
|
'artists' => Drops::ArtistsDrop.new(store.artists.map { |a| Drops::ArtistDrop.new(a) }),
|
@@ -77,6 +79,10 @@ module Dugway
|
|
77
79
|
'head_content' => [window_bigcartel_script, head_content].join,
|
78
80
|
'bigcartel_credit' => bigcartel_credit,
|
79
81
|
'powered_by_big_cartel' => powered_by_big_cartel,
|
82
|
+
'big_cartel_credit_logo' => big_cartel_credit_logo,
|
83
|
+
# Pass both customization and definitions to TranslationsDrop
|
84
|
+
'translations' => Drops::TranslationsDrop.new(theme.customization, theme.settings),
|
85
|
+
't' => Drops::TranslationsDrop.new(theme.customization, theme.settings),
|
80
86
|
}
|
81
87
|
end
|
82
88
|
|
@@ -109,17 +115,47 @@ module Dugway
|
|
109
115
|
"<script>#{script}</script>"
|
110
116
|
end
|
111
117
|
|
118
|
+
def read_svg_asset(filename)
|
119
|
+
File.read(File.join(File.dirname(__FILE__), 'assets', filename))
|
120
|
+
end
|
121
|
+
|
112
122
|
def bigcartel_credit
|
113
123
|
'<a href="http://bigcartel.com/" title="Start your own store at Big Cartel now">Online Store by Big Cartel</a>'
|
114
124
|
end
|
115
125
|
|
116
126
|
def powered_by_big_cartel
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
127
|
+
build_powered_by_link(include_text: true)
|
128
|
+
end
|
129
|
+
|
130
|
+
def big_cartel_credit_logo
|
131
|
+
build_powered_by_link(include_text: false)
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_powered_by_link(include_text: true)
|
135
|
+
svg_content = read_svg_asset('big_cartel_logo.svg')
|
136
|
+
|
137
|
+
text_span = include_text ? ' <span class="bigcartel-credit__text" aria-hidden="true">Powered by</span>' : ''
|
138
|
+
<<~HTML
|
139
|
+
<a class="bigcartel-credit" href="https://www.bigcartel.com/?utm_source=bigcartel&utm_medium=storefront&utm_campaign=123}" title="Powered by Big Cartel" data-bc-hook="attribution">
|
140
|
+
#{text_span}
|
141
|
+
#{svg_content}
|
142
|
+
</a>
|
143
|
+
HTML
|
144
|
+
end
|
145
|
+
|
146
|
+
# Load theme-specific override locales
|
147
|
+
def load_theme_locales
|
148
|
+
return unless Dugway.source_dir && Dir.exist?(File.dirname(Dugway.source_dir))
|
149
|
+
|
150
|
+
parent_dir = File.dirname(Dugway.source_dir)
|
151
|
+
theme_locales_dir = File.join(parent_dir, 'locales')
|
152
|
+
|
153
|
+
if Dir.exist?(theme_locales_dir)
|
154
|
+
theme_locales_path = File.expand_path(theme_locales_dir)
|
155
|
+
# Ensure theme locales are loaded *after* defaults to allow overrides
|
156
|
+
I18n.load_path |= Dir[File.join(theme_locales_path, 'storefront.*.yml')]
|
157
|
+
I18n.backend.reload!
|
158
|
+
end
|
123
159
|
end
|
124
160
|
end
|
125
161
|
end
|
data/lib/dugway/store.rb
CHANGED
@@ -8,8 +8,9 @@ module Dugway
|
|
8
8
|
default_timeout 5
|
9
9
|
headers 'User-Agent' => "Dugway #{ Dugway::VERSION }"
|
10
10
|
|
11
|
-
def initialize(subdomain)
|
11
|
+
def initialize(subdomain, store_options = {})
|
12
12
|
self.class.base_uri "https://api.bigcartel.com/#{ subdomain }"
|
13
|
+
@store_options = store_options || {}
|
13
14
|
end
|
14
15
|
|
15
16
|
def account
|
@@ -35,7 +36,7 @@ module Dugway
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def pages
|
38
|
-
@pages ||= theme_pages + custom_pages
|
39
|
+
@pages ||= theme_pages + custom_pages + external_pages + required_pages
|
39
40
|
end
|
40
41
|
|
41
42
|
def page(permalink)
|
@@ -124,13 +125,55 @@ module Dugway
|
|
124
125
|
end
|
125
126
|
|
126
127
|
def locale
|
127
|
-
currency['locale']
|
128
|
+
@store_options[:locale] || currency['locale']
|
129
|
+
end
|
130
|
+
|
131
|
+
def website
|
132
|
+
@store_options[:website] || account['website']
|
128
133
|
end
|
129
134
|
|
130
135
|
def instant_checkout?
|
131
136
|
Dugway.options.dig(:store, :instant_checkout) || false
|
132
137
|
end
|
133
138
|
|
139
|
+
def subscribe_url
|
140
|
+
@store_options[:subscribe_url] || account['subscribe_url']
|
141
|
+
end
|
142
|
+
|
143
|
+
def price_suffix
|
144
|
+
@store_options[:price_suffix]
|
145
|
+
end
|
146
|
+
|
147
|
+
def external_pages
|
148
|
+
@external_pages ||= begin
|
149
|
+
pages = []
|
150
|
+
if subscribe_url && !subscribe_url.empty?
|
151
|
+
pages << {
|
152
|
+
'name' => 'Subscribe',
|
153
|
+
'permalink' => 'subscribe',
|
154
|
+
'url' => subscribe_url,
|
155
|
+
'category' => 'external'
|
156
|
+
}
|
157
|
+
end
|
158
|
+
pages
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def required_pages
|
163
|
+
@required_pages ||= begin
|
164
|
+
required_pages_config = @store_options[:required_pages] || account['required_pages'] || []
|
165
|
+
required_pages_config.map do |page_config|
|
166
|
+
{
|
167
|
+
'name' => page_config['name'],
|
168
|
+
'permalink' => page_config['permalink'],
|
169
|
+
'url' => page_config['url'],
|
170
|
+
'category' => page_config['category'] || 'custom',
|
171
|
+
'required' => true
|
172
|
+
}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
134
177
|
private
|
135
178
|
|
136
179
|
def get(path)
|