shopify-theme-devtools 1.0.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.
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "shopify-theme-devtools",
3
+ "version": "1.0.0",
4
+ "description": "In-browser devtools panel for Shopify theme development - inspect Liquid context, metafields, settings, sections, and cart state",
5
+ "type": "module",
6
+ "main": "dist/theme-devtools.js",
7
+ "module": "dist/theme-devtools.js",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/theme-devtools.js",
11
+ "require": "./dist/theme-devtools.js"
12
+ },
13
+ "./liquid": "./src/liquid/theme-devtools-bridge.liquid",
14
+ "./dist/*": "./dist/*"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src/liquid",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "NODE_ENV=production vite build",
24
+ "build:dev": "vite build",
25
+ "dev": "vite",
26
+ "preview": "vite preview",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "shopify",
31
+ "theme",
32
+ "devtools",
33
+ "developer-tools",
34
+ "liquid",
35
+ "debugging",
36
+ "metafields",
37
+ "shopify-theme",
38
+ "shopify-development",
39
+ "theme-development"
40
+ ],
41
+ "author": "",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": ""
46
+ },
47
+ "bugs": {
48
+ "url": ""
49
+ },
50
+ "homepage": "",
51
+ "devDependencies": {
52
+ "terser": "^5.44.1",
53
+ "vite": "^5.4.11"
54
+ },
55
+ "dependencies": {
56
+ "lit": "^3.3.2"
57
+ },
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ }
61
+ }
@@ -0,0 +1,445 @@
1
+ {%- comment -%}
2
+ Theme Devtools Bridge
3
+ Renders devtools context and loads JS/CSS only on development/preview themes.
4
+
5
+ Usage: {% render 'theme-devtools-bridge' %}
6
+
7
+ Development: Set devtools_local to true and run `npm run dev`
8
+ Production: Set devtools_local to false and update devtools_cdn_base
9
+
10
+ Metafields: Add your custom namespaces to devtools_metafield_namespaces below
11
+ {%- endcomment -%}
12
+
13
+ {%- assign devtools_local = true -%}
14
+ {%- assign devtools_localhost = 'http://localhost:9999' -%}
15
+ {%- assign devtools_cdn_base = 'https://cdn.example.com/theme-devtools/v1.0.0' -%}
16
+
17
+ {%- comment -%} Configure your metafield namespaces here {%- endcomment -%}
18
+ {%- assign devtools_metafield_namespaces = 'custom,global,my_fields,shopify,descriptors' | split: ',' -%}
19
+
20
+ {%- comment -%}
21
+ Configure your theme settings to expose here.
22
+ Format: setting_id|type|label|group
23
+ Common types: color, text, checkbox, number, range, select, image_picker, font_picker
24
+ {%- endcomment -%}
25
+ {%- capture devtools_settings_config -%}
26
+ colors_accent_1|color|Accent 1|colors
27
+ colors_accent_2|color|Accent 2|colors
28
+ colors_text|color|Text color|colors
29
+ colors_background|color|Background|colors
30
+ colors_background_2|color|Secondary background|colors
31
+ colors_outline_button_labels|color|Outline button labels|colors
32
+ colors_solid_button_labels|color|Solid button labels|colors
33
+ type_header_font|font_picker|Header font|typography
34
+ type_body_font|font_picker|Body font|typography
35
+ type_header_font_size|range|Header font size|typography
36
+ type_body_font_size|range|Body font size|typography
37
+ page_width|range|Page width|layout
38
+ spacing_sections|range|Section spacing|layout
39
+ cart_type|select|Cart type|cart
40
+ cart_drawer_enabled|checkbox|Enable cart drawer|cart
41
+ show_vendor|checkbox|Show vendor|product
42
+ show_secondary_image|checkbox|Show secondary image|product
43
+ predictive_search_enabled|checkbox|Predictive search|search
44
+ social_twitter_link|text|Twitter link|social
45
+ social_facebook_link|text|Facebook link|social
46
+ social_instagram_link|text|Instagram link|social
47
+ favicon|image_picker|Favicon|favicon
48
+ checkout_logo|image_picker|Checkout logo|checkout
49
+ {%- endcapture -%}
50
+
51
+ {%- if theme.role == 'development' or theme.role == 'unpublished' -%}
52
+ {%- capture devtools_context -%}
53
+ {
54
+ "meta": {
55
+ "theme": {
56
+ "id": {{ theme.id | json }},
57
+ "name": {{ theme.name | json }},
58
+ "role": {{ theme.role | json }}
59
+ },
60
+ "template": {
61
+ "name": {{ template.name | json }},
62
+ "suffix": {{ template.suffix | json }},
63
+ "directory": {{ template.directory | json }}
64
+ },
65
+ "request": {
66
+ "host": {{ request.host | json }},
67
+ "path": {{ request.path | json }},
68
+ "page_type": {{ request.page_type | json }},
69
+ "design_mode": {{ request.design_mode | json }},
70
+ "visual_preview_mode": {{ request.visual_preview_mode | json }},
71
+ "locale": {
72
+ "iso_code": {{ request.locale.iso_code | json }},
73
+ "name": {{ request.locale.name | json }},
74
+ "primary": {{ request.locale.primary | json }}
75
+ },
76
+ "origin": {{ request.origin | json }}
77
+ },
78
+ "localization": {
79
+ "country": {
80
+ "iso_code": {{ localization.country.iso_code | json }},
81
+ "name": {{ localization.country.name | json }},
82
+ "currency": {
83
+ "iso_code": {{ localization.country.currency.iso_code | json }},
84
+ "symbol": {{ localization.country.currency.symbol | json }}
85
+ }
86
+ },
87
+ "language": {
88
+ "iso_code": {{ localization.language.iso_code | json }},
89
+ "name": {{ localization.language.name | json }}
90
+ },
91
+ "market": {
92
+ "id": {{ localization.market.id | json }},
93
+ "handle": {{ localization.market.handle | json }}
94
+ }
95
+ }
96
+ },
97
+ "objects": {
98
+ "shop": {
99
+ "id": {{ shop.id | json }},
100
+ "name": {{ shop.name | json }},
101
+ "domain": {{ shop.domain | json }},
102
+ "permanent_domain": {{ shop.permanent_domain | json }},
103
+ "url": {{ shop.url | json }},
104
+ "secure_url": {{ shop.secure_url | json }},
105
+ "email": {{ shop.email | json }},
106
+ "description": {{ shop.description | json }},
107
+ "address": {
108
+ "address1": {{ shop.address.address1 | json }},
109
+ "city": {{ shop.address.city | json }},
110
+ "province": {{ shop.address.province | json }},
111
+ "province_code": {{ shop.address.province_code | json }},
112
+ "zip": {{ shop.address.zip | json }},
113
+ "country": {{ shop.address.country | json }},
114
+ "country_code": {{ shop.address.country_code | json }}
115
+ },
116
+ "currency": {{ shop.currency | json }},
117
+ "money_format": {{ shop.money_format | json }},
118
+ "money_with_currency_format": {{ shop.money_with_currency_format | json }},
119
+ "enabled_currencies": {{ shop.enabled_currencies | map: 'iso_code' | json }},
120
+ "enabled_locales": {{ shop.enabled_locales | map: 'iso_code' | json }},
121
+ "metafields_count": {{ shop.metafields | size | json }}
122
+ },
123
+ {%- if customer -%}
124
+ "customer": {
125
+ "id": {{ customer.id | json }},
126
+ "email": "***@{{ customer.email | split: '@' | last }}",
127
+ "first_name": {{ customer.first_name | json }},
128
+ "last_name": {{ customer.last_name | json }},
129
+ "has_account": {{ customer.has_account | json }},
130
+ "accepts_marketing": {{ customer.accepts_marketing | json }},
131
+ "orders_count": {{ customer.orders_count | json }},
132
+ "total_spent": {{ customer.total_spent | json }},
133
+ "tags": {{ customer.tags | json }},
134
+ "default_address": {
135
+ "city": {{ customer.default_address.city | json }},
136
+ "province": {{ customer.default_address.province | json }},
137
+ "country": {{ customer.default_address.country | json }}
138
+ }
139
+ },
140
+ {%- else -%}
141
+ "customer": null,
142
+ {%- endif -%}
143
+ {%- if product -%}
144
+ "product": {
145
+ "id": {{ product.id | json }},
146
+ "title": {{ product.title | json }},
147
+ "handle": {{ product.handle | json }},
148
+ "type": {{ product.type | json }},
149
+ "vendor": {{ product.vendor | json }},
150
+ "available": {{ product.available | json }},
151
+ "published_at": {{ product.published_at | json }},
152
+ "created_at": {{ product.created_at | json }},
153
+ "tags": {{ product.tags | json }},
154
+ "price": {{ product.price | json }},
155
+ "price_min": {{ product.price_min | json }},
156
+ "price_max": {{ product.price_max | json }},
157
+ "price_varies": {{ product.price_varies | json }},
158
+ "compare_at_price": {{ product.compare_at_price | json }},
159
+ "compare_at_price_min": {{ product.compare_at_price_min | json }},
160
+ "compare_at_price_max": {{ product.compare_at_price_max | json }},
161
+ "compare_at_price_varies": {{ product.compare_at_price_varies | json }},
162
+ "variants_count": {{ product.variants | size | json }},
163
+ "options_count": {{ product.options | size | json }},
164
+ "options": {{ product.options_with_values | json }},
165
+ "images_count": {{ product.images | size | json }},
166
+ "featured_image": {{ product.featured_image | json }},
167
+ "has_only_default_variant": {{ product.has_only_default_variant | json }},
168
+ "requires_selling_plan": {{ product.requires_selling_plan | json }},
169
+ "selected_variant": {
170
+ "id": {{ product.selected_variant.id | json }},
171
+ "title": {{ product.selected_variant.title | json }},
172
+ "sku": {{ product.selected_variant.sku | json }},
173
+ "price": {{ product.selected_variant.price | json }},
174
+ "available": {{ product.selected_variant.available | json }}
175
+ },
176
+ "selected_or_first_available_variant": {
177
+ "id": {{ product.selected_or_first_available_variant.id | json }},
178
+ "title": {{ product.selected_or_first_available_variant.title | json }},
179
+ "sku": {{ product.selected_or_first_available_variant.sku | json }},
180
+ "price": {{ product.selected_or_first_available_variant.price | json }},
181
+ "available": {{ product.selected_or_first_available_variant.available | json }}
182
+ },
183
+ "url": {{ product.url | json }},
184
+ "metafields_count": {{ product.metafields | size | json }}
185
+ },
186
+ {%- else -%}
187
+ "product": null,
188
+ {%- endif -%}
189
+ {%- if collection -%}
190
+ "collection": {
191
+ "id": {{ collection.id | json }},
192
+ "title": {{ collection.title | json }},
193
+ "handle": {{ collection.handle | json }},
194
+ "description": {{ collection.description | truncate: 200 | json }},
195
+ "products_count": {{ collection.products_count | json }},
196
+ "all_products_count": {{ collection.all_products_count | json }},
197
+ "all_tags": {{ collection.all_tags | json }},
198
+ "all_vendors": {{ collection.all_vendors | json }},
199
+ "sort_by": {{ collection.sort_by | json }},
200
+ "default_sort_by": {{ collection.default_sort_by | json }},
201
+ "url": {{ collection.url | json }},
202
+ "image": {{ collection.image | json }}
203
+ },
204
+ {%- else -%}
205
+ "collection": null,
206
+ {%- endif -%}
207
+ {%- if article -%}
208
+ "article": {
209
+ "id": {{ article.id | json }},
210
+ "title": {{ article.title | json }},
211
+ "handle": {{ article.handle | json }},
212
+ "author": {{ article.author | json }},
213
+ "created_at": {{ article.created_at | json }},
214
+ "published_at": {{ article.published_at | json }},
215
+ "tags": {{ article.tags | json }},
216
+ "comments_count": {{ article.comments_count | json }},
217
+ "comments_enabled": {{ article.comments_enabled | json }},
218
+ "url": {{ article.url | json }},
219
+ "excerpt": {{ article.excerpt | truncate: 200 | json }}
220
+ },
221
+ {%- else -%}
222
+ "article": null,
223
+ {%- endif -%}
224
+ {%- if blog -%}
225
+ "blog": {
226
+ "id": {{ blog.id | json }},
227
+ "title": {{ blog.title | json }},
228
+ "handle": {{ blog.handle | json }},
229
+ "articles_count": {{ blog.articles_count | json }},
230
+ "all_tags": {{ blog.all_tags | json }},
231
+ "comments_enabled": {{ blog.comments_enabled | json }},
232
+ "url": {{ blog.url | json }}
233
+ },
234
+ {%- else -%}
235
+ "blog": null,
236
+ {%- endif -%}
237
+ {%- if page -%}
238
+ "page": {
239
+ "id": {{ page.id | json }},
240
+ "title": {{ page.title | json }},
241
+ "handle": {{ page.handle | json }},
242
+ "author": {{ page.author | json }},
243
+ "template_suffix": {{ page.template_suffix | json }},
244
+ "url": {{ page.url | json }}
245
+ },
246
+ {%- else -%}
247
+ "page": null,
248
+ {%- endif -%}
249
+ "cart": {{ cart | json }}
250
+ },
251
+ "metafields": {
252
+ {%- comment -%} Shop Metafields {%- endcomment -%}
253
+ "shop": {
254
+ {%- for ns in devtools_metafield_namespaces -%}
255
+ {%- assign shop_ns = shop.metafields[ns] -%}
256
+ {%- if shop_ns != blank -%}
257
+ "{{ ns }}": {
258
+ {%- for field in shop_ns -%}
259
+ "{{ field.first }}": {
260
+ "value": {{ field.last.value | json }},
261
+ "type": {{ field.last.type | json }}
262
+ }{%- unless forloop.last -%},{%- endunless -%}
263
+ {%- endfor -%}
264
+ }{%- unless forloop.last -%},{%- endunless -%}
265
+ {%- endif -%}
266
+ {%- endfor -%}
267
+ },
268
+ {%- comment -%} Product Metafields {%- endcomment -%}
269
+ {%- if product -%}
270
+ "product": {
271
+ {%- for ns in devtools_metafield_namespaces -%}
272
+ {%- assign product_ns = product.metafields[ns] -%}
273
+ {%- if product_ns != blank -%}
274
+ "{{ ns }}": {
275
+ {%- for field in product_ns -%}
276
+ "{{ field.first }}": {
277
+ "value": {{ field.last.value | json }},
278
+ "type": {{ field.last.type | json }}
279
+ }{%- unless forloop.last -%},{%- endunless -%}
280
+ {%- endfor -%}
281
+ }{%- unless forloop.last -%},{%- endunless -%}
282
+ {%- endif -%}
283
+ {%- endfor -%}
284
+ },
285
+ {%- else -%}
286
+ "product": null,
287
+ {%- endif -%}
288
+ {%- comment -%} Collection Metafields {%- endcomment -%}
289
+ {%- if collection -%}
290
+ "collection": {
291
+ {%- for ns in devtools_metafield_namespaces -%}
292
+ {%- assign collection_ns = collection.metafields[ns] -%}
293
+ {%- if collection_ns != blank -%}
294
+ "{{ ns }}": {
295
+ {%- for field in collection_ns -%}
296
+ "{{ field.first }}": {
297
+ "value": {{ field.last.value | json }},
298
+ "type": {{ field.last.type | json }}
299
+ }{%- unless forloop.last -%},{%- endunless -%}
300
+ {%- endfor -%}
301
+ }{%- unless forloop.last -%},{%- endunless -%}
302
+ {%- endif -%}
303
+ {%- endfor -%}
304
+ },
305
+ {%- else -%}
306
+ "collection": null,
307
+ {%- endif -%}
308
+ {%- comment -%} Customer Metafields {%- endcomment -%}
309
+ {%- if customer -%}
310
+ "customer": {
311
+ {%- for ns in devtools_metafield_namespaces -%}
312
+ {%- assign customer_ns = customer.metafields[ns] -%}
313
+ {%- if customer_ns != blank -%}
314
+ "{{ ns }}": {
315
+ {%- for field in customer_ns -%}
316
+ "{{ field.first }}": {
317
+ "value": {{ field.last.value | json }},
318
+ "type": {{ field.last.type | json }}
319
+ }{%- unless forloop.last -%},{%- endunless -%}
320
+ {%- endfor -%}
321
+ }{%- unless forloop.last -%},{%- endunless -%}
322
+ {%- endif -%}
323
+ {%- endfor -%}
324
+ },
325
+ {%- else -%}
326
+ "customer": null,
327
+ {%- endif -%}
328
+ {%- comment -%} Article Metafields {%- endcomment -%}
329
+ {%- if article -%}
330
+ "article": {
331
+ {%- for ns in devtools_metafield_namespaces -%}
332
+ {%- assign article_ns = article.metafields[ns] -%}
333
+ {%- if article_ns != blank -%}
334
+ "{{ ns }}": {
335
+ {%- for field in article_ns -%}
336
+ "{{ field.first }}": {
337
+ "value": {{ field.last.value | json }},
338
+ "type": {{ field.last.type | json }}
339
+ }{%- unless forloop.last -%},{%- endunless -%}
340
+ {%- endfor -%}
341
+ }{%- unless forloop.last -%},{%- endunless -%}
342
+ {%- endif -%}
343
+ {%- endfor -%}
344
+ },
345
+ {%- else -%}
346
+ "article": null,
347
+ {%- endif -%}
348
+ {%- comment -%} Page Metafields {%- endcomment -%}
349
+ {%- if page -%}
350
+ "page": {
351
+ {%- for ns in devtools_metafield_namespaces -%}
352
+ {%- assign page_ns = page.metafields[ns] -%}
353
+ {%- if page_ns != blank -%}
354
+ "{{ ns }}": {
355
+ {%- for field in page_ns -%}
356
+ "{{ field.first }}": {
357
+ "value": {{ field.last.value | json }},
358
+ "type": {{ field.last.type | json }}
359
+ }{%- unless forloop.last -%},{%- endunless -%}
360
+ {%- endfor -%}
361
+ }{%- unless forloop.last -%},{%- endunless -%}
362
+ {%- endif -%}
363
+ {%- endfor -%}
364
+ },
365
+ {%- else -%}
366
+ "page": null,
367
+ {%- endif -%}
368
+ {%- comment -%} Blog Metafields {%- endcomment -%}
369
+ {%- if blog -%}
370
+ "blog": {
371
+ {%- for ns in devtools_metafield_namespaces -%}
372
+ {%- assign blog_ns = blog.metafields[ns] -%}
373
+ {%- if blog_ns != blank -%}
374
+ "{{ ns }}": {
375
+ {%- for field in blog_ns -%}
376
+ "{{ field.first }}": {
377
+ "value": {{ field.last.value | json }},
378
+ "type": {{ field.last.type | json }}
379
+ }{%- unless forloop.last -%},{%- endunless -%}
380
+ {%- endfor -%}
381
+ }{%- unless forloop.last -%},{%- endunless -%}
382
+ {%- endif -%}
383
+ {%- endfor -%}
384
+ }
385
+ {%- else -%}
386
+ "blog": null
387
+ {%- endif -%}
388
+ },
389
+ "settings": {
390
+ {%- assign devtools_settings_lines = devtools_settings_config | strip | newline_to_br | split: '<br />' -%}
391
+ {%- assign devtools_current_group = '' -%}
392
+ {%- assign devtools_group_started = false -%}
393
+ {%- for line in devtools_settings_lines -%}
394
+ {%- assign line_stripped = line | strip -%}
395
+ {%- if line_stripped != blank -%}
396
+ {%- assign parts = line_stripped | split: '|' -%}
397
+ {%- assign setting_id = parts[0] -%}
398
+ {%- assign setting_type = parts[1] -%}
399
+ {%- assign setting_label = parts[2] -%}
400
+ {%- assign setting_group = parts[3] | default: 'theme' -%}
401
+ {%- if setting_group != devtools_current_group -%}
402
+ {%- if devtools_group_started -%}
403
+ },
404
+ {%- endif -%}
405
+ "{{ setting_group }}": {
406
+ {%- assign devtools_current_group = setting_group -%}
407
+ {%- assign devtools_group_started = true -%}
408
+ {%- assign devtools_first_in_group = true -%}
409
+ {%- endif -%}
410
+ {%- unless devtools_first_in_group -%},{%- endunless -%}
411
+ "{{ setting_id }}": {
412
+ "value": {{ settings[setting_id] | json }},
413
+ "type": {{ setting_type | json }},
414
+ "label": {{ setting_label | json }}
415
+ }
416
+ {%- assign devtools_first_in_group = false -%}
417
+ {%- endif -%}
418
+ {%- endfor -%}
419
+ {%- if devtools_group_started -%}
420
+ }
421
+ {%- endif -%}
422
+ },
423
+ "sectionSettings": {
424
+ {%- comment -%} Section settings are injected via JS from data attributes {%- endcomment -%}
425
+ },
426
+ "timestamp": {{ 'now' | date: '%s' | json }}
427
+ }
428
+ {%- endcapture -%}
429
+
430
+ <script type="application/json" id="__THEME_DEVTOOLS_CONTEXT__">
431
+ {{ devtools_context }}
432
+ </script>
433
+
434
+ <div id="__THEME_DEVTOOLS_ROOT__" style="display:contents;"></div>
435
+
436
+ {% comment %} theme-check-disable RemoteAsset {% endcomment %}
437
+ {%- if devtools_local -%}
438
+ <script type="module" src="{{ devtools_localhost }}/src/scripts/main.js"></script>
439
+ {%- else -%}
440
+ <script>window.__THEME_DEVTOOLS_CSS_URL__ = '{{ devtools_cdn_base }}/theme-devtools.css';</script>
441
+ <script src="{{ devtools_cdn_base }}/theme-devtools.js" defer></script>
442
+ {%- endif -%}
443
+ {% comment %} theme-check-enable RemoteAsset {% endcomment %}
444
+ {%- endif -%}
445
+