theme-check 1.13.0 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,7 @@
3
3
  "category": "html",
4
4
  "deprecated": false,
5
5
  "deprecation_reason": "",
6
- "description": "Because there are many different form types available in Shopify themes, the `form` tag requires a type. Depending on the\nform type, an additional parameter might be required. You can specify the following form types:\n\n- [`activate_customer_password`](/api/liquid/tags/form#form-activate_customer_password)\n- [`cart`](/api/liquid/tags/form#form-cart)\n- [`contact`](/api/liquid/tags/form#form-contact)\n- [`create_customer`](/api/liquid/tags/form#form-create_customer)\n- [`currency`](/api/liquid/tags/form#form-currency)\n- [`customer`](/api/liquid/tags/form#form-customer)\n- [`customer_address`](/api/liquid/tags/form#form-customer_address)\n- [`customer_login`](/api/liquid/tags/form#form-customer_login)\n- [`guest_login`](/api/liquid/tags/form#form-guest_login)\n- [`localization`](/api/liquid/tags/form#form-localization)\n- [`new_comment`](/api/liquid/tags/form#form-new_comment)\n- [`product`](/api/liquid/tags/form#form-product)\n- [`recover_customer_password`](/api/liquid/tags/form#form-recover_customer_password)\n- [`reset_customer_password`](/api/liquid/tags/form#form-reset_customer_password)\n- [`storefront_password`](/api/liquid/tags/form#form-storefront_password)",
6
+ "description": "Because there are many different form types available in Shopify themes, the `form` tag requires a type. Depending on the\nform type, an additional parameter might be required. You can specify the following form types:\n\n- [`activate_customer_password`](/docs/api/liquid/tags/form#form-activate_customer_password)\n- [`cart`](/docs/api/liquid/tags/form#form-cart)\n- [`contact`](/docs/api/liquid/tags/form#form-contact)\n- [`create_customer`](/docs/api/liquid/tags/form#form-create_customer)\n- [`currency`](/docs/api/liquid/tags/form#form-currency)\n- [`customer`](/docs/api/liquid/tags/form#form-customer)\n- [`customer_address`](/docs/api/liquid/tags/form#form-customer_address)\n- [`customer_login`](/docs/api/liquid/tags/form#form-customer_login)\n- [`guest_login`](/docs/api/liquid/tags/form#form-guest_login)\n- [`localization`](/docs/api/liquid/tags/form#form-localization)\n- [`new_comment`](/docs/api/liquid/tags/form#form-new_comment)\n- [`product`](/docs/api/liquid/tags/form#form-product)\n- [`recover_customer_password`](/docs/api/liquid/tags/form#form-recover_customer_password)\n- [`reset_customer_password`](/docs/api/liquid/tags/form#form-reset_customer_password)\n- [`storefront_password`](/docs/api/liquid/tags/form#form-storefront_password)",
7
7
  "parameters": [
8
8
  {
9
9
  "description": "The desired URL to redirect to when the form submits.",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  {
42
42
  "name": "cart",
43
- "description": "Generates a form for creating a checkout based on the items currently in the cart. The `cart` form requires a [`cart` object](/api/liquid/objects/cart) as a parameter.\nTo learn more about using the cart form in your theme, refer to the [`cart` template](/themes/architecture/templates/cart#proceed-to-checkout).\n",
43
+ "description": "Generates a form for creating a checkout based on the items currently in the cart. The `cart` form requires a [`cart` object](/docs/api/liquid/objects/cart) as a parameter.\nTo learn more about using the cart form in your theme, refer to the [`cart` template](/themes/architecture/templates/cart#proceed-to-checkout).\n",
44
44
  "syntax": "{% form 'cart', cart %}\n form_content\n{% endform %}\n",
45
45
  "path": "/",
46
46
  "raw_liquid": "{% form 'cart', cart %}\n <!-- form content -->\n{% endform %}",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  {
72
72
  "name": "currency",
73
- "description": "> Deprecated:\n> The `currency` form is deprecated and has been replaced by the [`localization` form](/api/liquid/tags/form#form-localization).\n\nGenerates a form for customers to select their preferred currency.\n\n> Tip:\n> Use the [`currency_selector` filter](/api/liquid/filters/currency_selector) to include a currency selector inside the form.\n",
73
+ "description": "> Deprecated:\n> The `currency` form is deprecated and has been replaced by the [`localization` form](/docs/api/liquid/tags/form#form-localization).\n\nGenerates a form for customers to select their preferred currency.\n\n> Tip:\n> Use the [`currency_selector` filter](/docs/api/liquid/filters/currency_selector) to include a currency selector inside the form.\n",
74
74
  "syntax": "{% form 'currency' %}\n form_content\n{% endform %}\n",
75
75
  "path": "/",
76
76
  "raw_liquid": "{% form 'currency' %}\n {{ form | currency_selector }}\n{% endform %}",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  {
82
82
  "name": "customer",
83
- "description": "Generates a form for creating a new customer without registering a new account. This form is useful for collecting customer information when you don't want customers to log in to your store, such as building a list of emails from a newsletter signup.\n\n> Tip:\n> To generate a form that registers a customer account, use the [`create_customer` form](/api/liquid/tags/form#form-create_customer).\n\nTo learn more about using this form, and its contents, refer to [Email consent](/themes/customer-engagement/email-consent#newsletter-sign-up-form).\n",
83
+ "description": "Generates a form for creating a new customer without registering a new account. This form is useful for collecting customer information when you don't want customers to log in to your store, such as building a list of emails from a newsletter signup.\n\n> Tip:\n> To generate a form that registers a customer account, use the [`create_customer` form](/docs/api/liquid/tags/form#form-create_customer).\n\nTo learn more about using this form, and its contents, refer to [Email consent](/themes/customer-engagement/email-consent#newsletter-sign-up-form).\n",
84
84
  "syntax": "{% form 'customer' %}\n form_content\n{% endform %}\n",
85
85
  "path": "/",
86
86
  "raw_liquid": "{% form 'customer' %}\n <!-- form content -->\n{% endform %}",
@@ -120,7 +120,7 @@
120
120
  },
121
121
  {
122
122
  "name": "localization",
123
- "description": "Generates a form for customers to select their preferred country so that they're shown the appropriate language and currency. The `localization` form can contain one of two selectors:\n\n- A country selector\n- A language selector\n\n> Note:\n> The `localization` form replaces the deprecated [`currency` form](/api/liquid/tags/form#form-currency).\n\nTo learn more about using this form, and its contents, refer to [Support multiple currencies and languages](/themes/internationalization/multiple-currencies-languages).\n",
123
+ "description": "Generates a form for customers to select their preferred country so that they're shown the appropriate language and currency. The `localization` form can contain one of two selectors:\n\n- A country selector\n- A language selector\n\n> Note:\n> The `localization` form replaces the deprecated [`currency` form](/docs/api/liquid/tags/form#form-currency).\n\nTo learn more about using this form, and its contents, refer to [Support multiple currencies and languages](/themes/internationalization/multiple-currencies-languages).\n",
124
124
  "syntax": "{% form 'localization' %}\n form_content\n{% endform %}\n",
125
125
  "path": "/",
126
126
  "raw_liquid": "{% form 'localization' %}\n <!-- form content -->\n{% endform %}",
@@ -130,7 +130,7 @@
130
130
  },
131
131
  {
132
132
  "name": "new_comment",
133
- "description": "Generates a form for creating a new comment on an article. The `new_comment` form requires an [`article` object](/api/liquid/objects/article) as a parameter.\nTo learn more about using this form, and its contents, refer to the [`article` template](/themes/architecture/templates/article#the-comment-form).\n",
133
+ "description": "Generates a form for creating a new comment on an article. The `new_comment` form requires an [`article` object](/docs/api/liquid/objects/article) as a parameter.\nTo learn more about using this form, and its contents, refer to the [`article` template](/themes/architecture/templates/article#the-comment-form).\n",
134
134
  "syntax": "{% form 'new_comment', article %}\n form_content\n{% endform %}\n",
135
135
  "path": "/blogs/potion-notions/how-to-tell-if-you-have-run-out-of-invisibility-potion",
136
136
  "raw_liquid": "{% form 'new_comment', article %}\n <!-- form content -->\n{% endform %}",
@@ -140,7 +140,7 @@
140
140
  },
141
141
  {
142
142
  "name": "product",
143
- "description": "Generates a form for adding a product variant to the cart. The `product` form requires a [`product` object](/api/liquid/objects/product) as a parameter.\nTo learn more about using this form, and its contents, refer to the [`product` template](/themes/architecture/templates/product#the-product-form).\n",
143
+ "description": "Generates a form for adding a product variant to the cart. The `product` form requires a [`product` object](/docs/api/liquid/objects/product) as a parameter.\nTo learn more about using this form, and its contents, refer to the [`product` template](/themes/architecture/templates/product#the-product-form).\n",
144
144
  "syntax": "{% form 'product', product %}\n form_content\n{% endform %}\n",
145
145
  "path": "/products/health-potion",
146
146
  "raw_liquid": "{% form 'product', product %}\n <!-- form content -->\n{% endform %}",
@@ -180,7 +180,7 @@
180
180
  },
181
181
  {
182
182
  "name": "return_to",
183
- "description": "By default, each form type redirects customers to a specific page after the form submits. For example, the `product` form redirects to the cart page.\n\nThe `return_to` parameter allows you to specify a URL to redirect to. This can be done with the following values:\n\n| Value | Description |\n| --- | --- |\n| `back` | Redirect back to the same page that the customer was on before submitting the form. |\n| A relative path | A specific URL path. For example `/collections/all`. |\n| A [`routes` attribute](/api/liquid/objects/routes) | For example, `routes.root_url` |\n",
183
+ "description": "By default, each form type redirects customers to a specific page after the form submits. For example, the `product` form redirects to the cart page.\n\nThe `return_to` parameter allows you to specify a URL to redirect to. This can be done with the following values:\n\n| Value | Description |\n| --- | --- |\n| `back` | Redirect back to the same page that the customer was on before submitting the form. |\n| A relative path | A specific URL path. For example `/collections/all`. |\n| A [`routes` attribute](/docs/api/liquid/objects/routes) | For example, `routes.root_url` |\n",
184
184
  "syntax": "{% form 'form_type', return_to: string %}\n content\n{% endform %}\n",
185
185
  "path": "/",
186
186
  "raw_liquid": "{% form 'customer_login', return_to: routes.root_url %}\n <!-- form content -->\n{% endform %}",
@@ -234,7 +234,7 @@
234
234
  "category": "variable",
235
235
  "deprecated": false,
236
236
  "deprecation_reason": "",
237
- "description": "You can create variables of any [basic type](/api/liquid/basics#types), [object](/api/liquid/objects), or object property.",
237
+ "description": "You can create variables of any [basic type](/docs/api/liquid/basics#types), [object](/docs/api/liquid/objects), or object property.",
238
238
  "parameters": [
239
239
 
240
240
  ],
@@ -272,7 +272,7 @@
272
272
  "parameters": [
273
273
 
274
274
  ],
275
- "summary": "Stops a [`for` loop](/api/liquid/tags/for) from iterating.",
275
+ "summary": "Stops a [`for` loop](/docs/api/liquid/tags/for) from iterating.",
276
276
  "name": "break",
277
277
  "syntax": "{% break %}",
278
278
  "syntax_keywords": [
@@ -415,7 +415,7 @@
415
415
  },
416
416
  {
417
417
  "name": "Inline comments inside `liquid` tags",
418
- "description": "You can use inline comment tags inside [`liquid` tags](/api/liquid/tags/liquid). The tag must be used for each line that you want to comment.\n",
418
+ "description": "You can use inline comment tags inside [`liquid` tags](/docs/api/liquid/tags/liquid). The tag must be used for each line that you want to comment.\n",
419
419
  "syntax": "",
420
420
  "path": "/",
421
421
  "raw_liquid": "{% liquid\n # this is a comment\n assign topic = 'Learning about comments!'\n echo topic\n%}",
@@ -433,7 +433,7 @@
433
433
  "parameters": [
434
434
 
435
435
  ],
436
- "summary": "Causes a [`for` loop](/api/liquid/tags/for) to skip to the next iteration.",
436
+ "summary": "Causes a [`for` loop](/docs/api/liquid/tags/for) to skip to the next iteration.",
437
437
  "name": "continue",
438
438
  "syntax": "{% continue %}",
439
439
  "syntax_keywords": [
@@ -460,7 +460,7 @@
460
460
  "parameters": [
461
461
 
462
462
  ],
463
- "summary": "Loops through a group of strings and outputs them one at a time for each iteration of a [`for` loop](/api/liquid/tags/for).",
463
+ "summary": "Loops through a group of strings and outputs them one at a time for each iteration of a [`for` loop](/docs/api/liquid/tags/for).",
464
464
  "name": "cycle",
465
465
  "syntax": "{% cycle string, string, ... %}",
466
466
  "syntax_keywords": [
@@ -493,7 +493,7 @@
493
493
  "category": "variable",
494
494
  "deprecated": false,
495
495
  "deprecation_reason": "",
496
- "description": "Variables that are declared with `decrement` are unique to the [layout](/themes/architecture/layouts), [template](/themes/architecture/templates),\nor [section](/themes/architecture/sections) file that they're created in. However, the variable is shared across\n[snippets](/themes/architecture#snippets) included in the file.\n\nSimilarly, variables that are created with `decrement` are independent from those created with [`assign`](/api/liquid/tags/assign)\nand [`capture`](/api/liquid/tags/capture). However, `decrement` and [`increment`](/api/liquid/tags/increment) share\nvariables.",
496
+ "description": "Variables that are declared with `decrement` are unique to the [layout](/themes/architecture/layouts), [template](/themes/architecture/templates),\nor [section](/themes/architecture/sections) file that they're created in. However, the variable is shared across\n[snippets](/themes/architecture#snippets) included in the file.\n\nSimilarly, variables that are created with `decrement` are independent from those created with [`assign`](/docs/api/liquid/tags/assign)\nand [`capture`](/docs/api/liquid/tags/capture). However, `decrement` and [`increment`](/docs/api/liquid/tags/increment) share\nvariables.",
497
497
  "parameters": [
498
498
 
499
499
  ],
@@ -523,7 +523,7 @@
523
523
  "category": "syntax",
524
524
  "deprecated": false,
525
525
  "deprecation_reason": "",
526
- "description": "Using the `echo` tag is the same as wrapping an expression in curly brackets (`{{` and `}}`). However, unlike the curly\nbracket method, you can use the `echo` tag inside [`liquid` tags](/api/liquid/tags/liquid).\n\n> Tip:\n> You can use [filters](/api/liquid/filters) on expressions inside `echo` tags.",
526
+ "description": "Using the `echo` tag is the same as wrapping an expression in curly brackets (`{{` and `}}`). However, unlike the curly\nbracket method, you can use the `echo` tag inside [`liquid` tags](/docs/api/liquid/tags/liquid).\n\n> Tip:\n> You can use [filters](/docs/api/liquid/filters) on expressions inside `echo` tags.",
527
527
  "parameters": [
528
528
 
529
529
  ],
@@ -553,7 +553,7 @@
553
553
  "category": "iteration",
554
554
  "deprecated": false,
555
555
  "deprecation_reason": "",
556
- "description": "You can do a maximum of 50 iterations with a `for` loop. If you need to iterate over more than 50 items, then use the\n[`paginate` tag](/api/liquid/tags/paginate) to split the items over multiple pages.\n\n> Tip:\n> Every `for` loop has an associated [`forloop` object](/api/liquid/objects/forloop) with information about the loop.",
556
+ "description": "You can do a maximum of 50 iterations with a `for` loop. If you need to iterate over more than 50 items, then use the\n[`paginate` tag](/docs/api/liquid/tags/paginate) to split the items over multiple pages.\n\n> Tip:\n> Every `for` loop has an associated [`forloop` object](/docs/api/liquid/objects/forloop) with information about the loop.",
557
557
  "parameters": [
558
558
  {
559
559
  "description": "The number of iterations to perform.",
@@ -705,8 +705,8 @@
705
705
  {
706
706
  "category": "theme",
707
707
  "deprecated": true,
708
- "deprecation_reason": "Deprecated because the way that variables are handled reduces performance and makes code harder to both read and maintain.\n\nThe `include` tag has been replaced by [`render`](/api/liquid/tags/render).",
709
- "description": "Inside the snippet, you can access and alter variables that are [created](/api/liquid/tags/variable-tags) outside of the\nsnippet.",
708
+ "deprecation_reason": "Deprecated because the way that variables are handled reduces performance and makes code harder to both read and maintain.\n\nThe `include` tag has been replaced by [`render`](/docs/api/liquid/tags/render).",
709
+ "description": "Inside the snippet, you can access and alter variables that are [created](/docs/api/liquid/tags/variable-tags) outside of the\nsnippet.",
710
710
  "parameters": [
711
711
 
712
712
  ],
@@ -727,7 +727,7 @@
727
727
  "category": "variable",
728
728
  "deprecated": false,
729
729
  "deprecation_reason": "",
730
- "description": "Variables that are declared with `increment` are unique to the [layout](/themes/architecture/layouts), [template](/themes/architecture/templates),\nor [section](/themes/architecture/sections) file that they're created in. However, the variable is shared across\n[snippets](/themes/architecture#snippets) included in the file.\n\nSimilarly, variables that are created with `increment` are independent from those created with [`assign`](/api/liquid/tags/assign)\nand [`capture`](/api/liquid/tags/capture). However, `increment` and [`decrement`](/api/liquid/tags/decrement) share\nvariables.",
730
+ "description": "Variables that are declared with `increment` are unique to the [layout](/themes/architecture/layouts), [template](/themes/architecture/templates),\nor [section](/themes/architecture/sections) file that they're created in. However, the variable is shared across\n[snippets](/themes/architecture#snippets) included in the file.\n\nSimilarly, variables that are created with `increment` are independent from those created with [`assign`](/docs/api/liquid/tags/assign)\nand [`capture`](/docs/api/liquid/tags/capture). However, `increment` and [`decrement`](/docs/api/liquid/tags/decrement) share\nvariables.",
731
731
  "parameters": [
732
732
 
733
733
  ],
@@ -787,7 +787,7 @@
787
787
  "category": "theme",
788
788
  "deprecated": false,
789
789
  "deprecation_reason": "",
790
- "description": "Inside snippets and app blocks, you can't directly access variables that are [created](/api/liquid/tags/variable-tags) outside\nof the snippet or app block. However, you can [specify variables as parameters](/api/liquid/tags/render#render-passing-variables-to-a-snippet)\nto pass outside variables to snippets.\n\nWhile you can't directly access created variables, you can access global objects, as well as any objects that are\ndirectly accessible outside the snippet or app block. For example, a snippet or app block inside the [product template](/themes/architecture/templates/product)\ncan access the [`product` object](/api/liquid/objects/product), and a snippet or app block inside a [section](/themes/architecture/sections)\ncan access the [`section` object](/api/liquid/objects/section).\n\nOutside a snippet or app block, you can't access variables created inside the snippet or app block.\n\n> Note:\n> When you render a snippet using the `render` tag, you can't use the [`include` tag](/api/liquid/tags/include)\n> inside the snippet.",
790
+ "description": "Inside snippets and app blocks, you can't directly access variables that are [created](/docs/api/liquid/tags/variable-tags) outside\nof the snippet or app block. However, you can [specify variables as parameters](/docs/api/liquid/tags/render#render-passing-variables-to-a-snippet)\nto pass outside variables to snippets.\n\nWhile you can't directly access created variables, you can access global objects, as well as any objects that are\ndirectly accessible outside the snippet or app block. For example, a snippet or app block inside the [product template](/themes/architecture/templates/product)\ncan access the [`product` object](/docs/api/liquid/objects/product), and a snippet or app block inside a [section](/themes/architecture/sections)\ncan access the [`section` object](/docs/api/liquid/objects/section).\n\nOutside a snippet or app block, you can't access variables created inside the snippet or app block.\n\n> Note:\n> When you render a snippet using the `render` tag, you can't use the [`include` tag](/docs/api/liquid/tags/include)\n> inside the snippet.",
791
791
  "parameters": [
792
792
 
793
793
  ],
@@ -803,7 +803,7 @@
803
803
  "examples": [
804
804
  {
805
805
  "name": "for",
806
- "description": "You can render a snippet for every item in an array using the `for` parameter. You can also supply an optional `as` parameter to be able to reference the current item in the iteration inside the snippet.\nAdditionally, you can access a [`forloop` object](/api/liquid/objects/forloop) for the loop inside the snippet.\n",
806
+ "description": "You can render a snippet for every item in an array using the `for` parameter. You can also supply an optional `as` parameter to be able to reference the current item in the iteration inside the snippet.\nAdditionally, you can access a [`forloop` object](/docs/api/liquid/objects/forloop) for the loop inside the snippet.\n",
807
807
  "syntax": "{% render 'filename' for array as item %}",
808
808
  "path": "/",
809
809
  "raw_liquid": "",
@@ -813,7 +813,7 @@
813
813
  },
814
814
  {
815
815
  "name": "Passing variables to a snippet",
816
- "description": "Variables that have been [created](/api/liquid/tags/variable-tags) outside of a snippet can be passed to a snippet as parameters on the `render` tag.\n\n> Note:\n> Any changes that are made to a passed variable apply only within the snippet.\n",
816
+ "description": "Variables that have been [created](/docs/api/liquid/tags/variable-tags) outside of a snippet can be passed to a snippet as parameters on the `render` tag.\n\n> Note:\n> Any changes that are made to a passed variable apply only within the snippet.\n",
817
817
  "syntax": "{% render 'filename', variable: value %}",
818
818
  "path": "/",
819
819
  "raw_liquid": "",
@@ -837,7 +837,7 @@
837
837
  "category": "iteration",
838
838
  "deprecated": false,
839
839
  "deprecation_reason": "",
840
- "description": "The `tablerow` tag must be wrapped in HTML `<table>` and `</table>` tags.\n\n> Tip:\n> Every `tablerow` loop has an associated [`tablerowloop` object](/api/liquid/objects/tablerowloop) with information about the loop.",
840
+ "description": "The `tablerow` tag must be wrapped in HTML `<table>` and `</table>` tags.\n\n> Tip:\n> Every `tablerow` loop has an associated [`tablerowloop` object](/docs/api/liquid/objects/tablerowloop) with information about the loop.",
841
841
  "parameters": [
842
842
  {
843
843
  "description": "The number of columns that the table should have.",
@@ -946,7 +946,7 @@
946
946
  "category": "conditional",
947
947
  "deprecated": false,
948
948
  "deprecation_reason": "",
949
- "description": "> Tip:\n> Similar to the [`if` tag](/api/liquid/tags/if), you can use `elsif` to add more conditions to an `unless` tag.",
949
+ "description": "> Tip:\n> Similar to the [`if` tag](/docs/api/liquid/tags/if), you can use `elsif` to add more conditions to an `unless` tag.",
950
950
  "parameters": [
951
951
 
952
952
  ],
@@ -976,11 +976,41 @@
976
976
  }
977
977
  ]
978
978
  },
979
+ {
980
+ "category": "theme",
981
+ "deprecated": false,
982
+ "deprecation_reason": "",
983
+ "description": "Rendering a section with the `section` tag renders a section statically. To learn more about sections and how to use\nthem in your theme, refer to [Render a section](/themes/architecture/sections#render-a-section).",
984
+ "parameters": [
985
+
986
+ ],
987
+ "summary": "Renders a [section](/themes/architecture/sections).",
988
+ "name": "section",
989
+ "syntax": "{% section 'name' %}",
990
+ "syntax_keywords": [
991
+ {
992
+ "keyword": "name",
993
+ "description": "The name of the section file you want to render."
994
+ }
995
+ ],
996
+ "examples": [
997
+ {
998
+ "name": "",
999
+ "description": "",
1000
+ "syntax": "",
1001
+ "path": "/",
1002
+ "raw_liquid": "{% section 'header' %}",
1003
+ "parameter": false,
1004
+ "display_type": "text",
1005
+ "show_data_tab": true
1006
+ }
1007
+ ]
1008
+ },
979
1009
  {
980
1010
  "category": "iteration",
981
1011
  "deprecated": false,
982
1012
  "deprecation_reason": "",
983
- "description": "Because [`for` loops](/api/liquid/tags/for) are limited to 50 iterations per page, you need to use the `paginate` tag to\niterate over an array that has more than 50 items. The following arrays can be paginated:\n\n- [`all_products`](/api/liquid/objects/all_products)\n- [`article.comments`](/api/liquid/objects/article#article-comments)\n- [`blog.articles`](/api/liquid/objects/blog#blog-articles)\n- [`collections`](/api/liquid/objects/collections)\n- [`collection.products`](/api/liquid/objects/collection#collection-products)\n- [`customer.addresses`](/api/liquid/objects/customer#customer-addresses)\n- [`customer.orders`](/api/liquid/objects/customer#customer-orders)\n- [`pages`](/api/liquid/objects/pages)\n- [`search.results`](/api/liquid/objects/search#search-results)\n- [`collection_list` settings](/themes/architecture/settings/input-settings#collection_list)\n- [`product_list` settings](/themes/architecture/settings/input-settings#product_list)\n\nWithin the `paginate` tag, you have access to the [`paginate` object](/api/liquid/objects/paginate). You can use this\nobject, or the [`default_pagination` filter](/api/liquid/filters/default_pagination), to build page navigation.",
1013
+ "description": "Because [`for` loops](/docs/api/liquid/tags/for) are limited to 50 iterations per page, you need to use the `paginate` tag to\niterate over an array that has more than 50 items. The following arrays can be paginated:\n\n- [`all_products`](/docs/api/liquid/objects/all_products)\n- [`article.comments`](/docs/api/liquid/objects/article#article-comments)\n- [`blog.articles`](/docs/api/liquid/objects/blog#blog-articles)\n- [`collections`](/docs/api/liquid/objects/collections)\n- [`collection.products`](/docs/api/liquid/objects/collection#collection-products)\n- [`customer.addresses`](/docs/api/liquid/objects/customer#customer-addresses)\n- [`customer.orders`](/docs/api/liquid/objects/customer#customer-orders)\n- [`pages`](/docs/api/liquid/objects/pages)\n- [`search.results`](/docs/api/liquid/objects/search#search-results)\n- [`collection_list` settings](/themes/architecture/settings/input-settings#collection_list)\n- [`product_list` settings](/themes/architecture/settings/input-settings#product_list)\n\nWithin the `paginate` tag, you have access to the [`paginate` object](/docs/api/liquid/objects/paginate). You can use this\nobject, or the [`default_pagination` filter](/docs/api/liquid/filters/default_pagination), to build page navigation.",
984
1014
  "parameters": [
985
1015
  {
986
1016
  "description": "The number of pages to display in the pagination.",
@@ -1025,7 +1055,7 @@
1025
1055
  },
1026
1056
  {
1027
1057
  "name": "Paginating setting arrays",
1028
- "description": "To allow the pagination of `product_list` and `collection_list` settings to operate independently from other paginated lists on a page, these lists use a pagination query parameter with a unique key. The key is automatically assigned by the `paginate` tag, and you don't need to reference the key in your code. However, you can access the key using [`paginate.page_param`](/api/liquid/objects/paginate#paginate-page_param).\n\n> Tip:\n> To paginate two arrays independently without refreshing the entire page, you can use the [Section Rendering API](/api/section-rendering).\n",
1058
+ "description": "To allow the pagination of `product_list` and `collection_list` settings to operate independently from other paginated lists on a page, these lists use a pagination query parameter with a unique key. The key is automatically assigned by the `paginate` tag, and you don't need to reference the key in your code. However, you can access the key using [`paginate.page_param`](/docs/api/liquid/objects/paginate#paginate-page_param).\n\n> Tip:\n> To paginate two arrays independently without refreshing the entire page, you can use the [Section Rendering API](/api/section-rendering).\n",
1029
1059
  "syntax": "",
1030
1060
  "path": "/",
1031
1061
  "raw_liquid": "",
@@ -1100,7 +1130,7 @@
1100
1130
  "category": "theme",
1101
1131
  "deprecated": false,
1102
1132
  "deprecation_reason": "",
1103
- "description": "You need to use these tags only if your section or app block is meant to be installed on multiple themes or stores. Otherwise, you should include the JavaScript that your section needs in your theme's [`assets`](/themes/architecture#assets) directory. Each section or app block can have only one `{% stylesheet %}` tag.\n\nTo learn more about how section-specific CSS is loaded and run, refer to the documentation for [sections](/themes/architecture/sections/section-assets#stylesheet).\n> Caution:\n> Liquid isn't rendered inside of `{% stylesheet %}` tags. Including Liquid code can cause syntax errors.",
1133
+ "description": "You need to use these tags only if your section or app block is meant to be installed on multiple themes or stores. Otherwise, you should include the CSS styles that your section needs in your theme's [`assets`](/themes/architecture#assets) directory. Each section or app block can have only one `{% stylesheet %}` tag.\n\nTo learn more about how section-specific CSS is loaded and run, refer to the documentation for [sections](/themes/architecture/sections/section-assets#stylesheet).\n> Caution:\n> Liquid isn't rendered inside of `{% stylesheet %}` tags. Including Liquid code can cause syntax errors.",
1104
1134
  "parameters": [
1105
1135
 
1106
1136
  ],
@@ -1117,6 +1147,27 @@
1117
1147
 
1118
1148
  ]
1119
1149
  },
1150
+ {
1151
+ "category": "theme",
1152
+ "deprecated": false,
1153
+ "deprecation_reason": "",
1154
+ "description": "Use this tag to render section groups as part of the theme's [layout](/themes/architecture/layouts) content. Place the `sections` tag where you want to render it in the layout.\n\nTo learn more about section groups and how to use them in your theme, refer to [Section groups](/themes/architecture/section-groups#usage).",
1155
+ "parameters": [
1156
+
1157
+ ],
1158
+ "summary": "Renders a [section group](/themes/architecture/section-groups).",
1159
+ "name": "sections",
1160
+ "syntax": "{% sections 'name' %}",
1161
+ "syntax_keywords": [
1162
+ {
1163
+ "keyword": "name",
1164
+ "description": "The name of the section group file you want to render."
1165
+ }
1166
+ ],
1167
+ "examples": [
1168
+
1169
+ ]
1170
+ },
1120
1171
  {
1121
1172
  "category": "html",
1122
1173
  "deprecated": false,
@@ -1151,7 +1202,7 @@
1151
1202
  "category": "conditional",
1152
1203
  "deprecated": false,
1153
1204
  "deprecation_reason": "",
1154
- "description": "You can use the `else` tag with the following tags:\n\n- [`case`](/api/liquid/tags/case)\n- [`if`](/api/liquid/tags/if)\n- [`unless`](/api/liquid/tags/unless)",
1205
+ "description": "You can use the `else` tag with the following tags:\n\n- [`case`](/docs/api/liquid/tags/case)\n- [`if`](/docs/api/liquid/tags/if)\n- [`unless`](/docs/api/liquid/tags/unless)",
1155
1206
  "parameters": [
1156
1207
 
1157
1208
  ],
@@ -1185,7 +1236,7 @@
1185
1236
  "parameters": [
1186
1237
 
1187
1238
  ],
1188
- "summary": "Allows you to specify a default expression to execute when a [`for` loop](/api/liquid/tags/for) has zero length.",
1239
+ "summary": "Allows you to specify a default expression to execute when a [`for` loop](/docs/api/liquid/tags/for) has zero length.",
1189
1240
  "name": "else",
1190
1241
  "syntax": "{% for variable in array %}\n first_expression\n{% else %}\n second_expression\n{% endfor %}",
1191
1242
  "syntax_keywords": [
@@ -1223,7 +1274,7 @@
1223
1274
  "category": "syntax",
1224
1275
  "deprecated": false,
1225
1276
  "deprecation_reason": "",
1226
- "description": "Because the tags don't have delimeters, each tag needs to be on its own line.\n\n> Tip:\n> Use the [`echo` tag](/api/liquid/tags/echo) to output an expression inside `liquid` tags.",
1277
+ "description": "Because the tags don't have delimeters, each tag needs to be on its own line.\n\n> Tip:\n> Use the [`echo` tag](/docs/api/liquid/tags/echo) to output an expression inside `liquid` tags.",
1227
1278
  "parameters": [
1228
1279
 
1229
1280
  ],
@@ -8,17 +8,19 @@ Very often, webpages contain many images that contribute to data-usage and how f
8
8
 
9
9
  _Quoted from [MDN - Lazy loading][mdn]_
10
10
 
11
+ As a general rule you should apply `loading="lazy"` to elements that are **not initially visible** when the page loads. Only images that require user interaction (scrolling, hovering, clicking etc.) to be seen can be safely lazy loaded without negatively impacting the rendering performance.
12
+
11
13
  ## Check Details
12
14
 
13
- This check is aimed at defering loading non-critical images.
15
+ This check is aimed at deferring loading non-critical images.
14
16
 
15
17
  :-1: Examples of **incorrect** code for this check:
16
18
 
17
19
  ```liquid
18
20
  <img src="a.jpg">
19
21
 
20
- <!-- Replaces lazysize.js -->
21
- <img src="a.jpg" class="lazyload">
22
+ <!-- Replaces lazysizes.js -->
23
+ <img data-src="a.jpg" class="lazyload">
22
24
 
23
25
  <!-- `auto` is deprecated -->
24
26
  <img src="a.jpg" loading="auto">
@@ -29,7 +31,7 @@ This check is aimed at defering loading non-critical images.
29
31
  ```liquid
30
32
  <img src="a.jpg" loading="lazy">
31
33
 
32
- <!-- `eager` is also accepted, but prefer `lazy` -->
34
+ <!-- `eager` is also accepted -->
33
35
  <img src="a.jpg" loading="eager">
34
36
  ```
35
37
 
@@ -44,7 +46,7 @@ ImgLazyLoading:
44
46
 
45
47
  ## When Not To Use It
46
48
 
47
- If you don't want to defer loading of images, then it's safe to disable this rule.
49
+ There should be no cases where disabling this rule is needed. When it comes to rendering performance, it is generally better to specify `loading="eager"` as a default. You may want to do that for sections that are often placed in different parts of the page (top, middle, bottom), which makes it hard to reason about which value should be used.
48
50
 
49
51
  ## Version
50
52
 
@@ -19,7 +19,7 @@ The following examples contain code snippets that either fail or pass this check
19
19
  "en": {
20
20
  "title": "Welcome", "product": "Product"
21
21
  },
22
- "fr": { "title": "Bienvenue", "produit": "Produit" }
22
+ "fr": { "title": "Bienvenue", "product": "Produit" }
23
23
  }
24
24
  }
25
25
  {% endschema %}
@@ -33,11 +33,11 @@ The following examples contain code snippets that either fail or pass this check
33
33
  "locales": {
34
34
  "en": {
35
35
  "title": "Welcome",
36
- "missing": "Product"
36
+ "product": "Product"
37
37
  },
38
38
  "fr": {
39
39
  "title": "Bienvenue",
40
- "missing": "TODO"
40
+ "product": "Produit"
41
41
  }
42
42
  }
43
43
  }
@@ -10,11 +10,7 @@ module ThemeCheck
10
10
  def on_img(node)
11
11
  loading = node.attributes["loading"]&.downcase
12
12
  return if ACCEPTED_LOADING_VALUES.include?(loading)
13
- if loading == "auto"
14
- add_offense("Prefer loading=\"lazy\" to defer loading of images", node: node)
15
- else
16
- add_offense("Add a loading=\"lazy\" attribute to defer loading of images", node: node)
17
- end
13
+ add_offense("Use loading=\"eager\" for images visible in the viewport on load and loading=\"lazy\" for others", node: node)
18
14
  end
19
15
  end
20
16
  end
@@ -15,6 +15,7 @@ module ThemeCheck
15
15
  @include_categories = []
16
16
  @exclude_categories = []
17
17
  @auto_correct = false
18
+ @update_docs = false
18
19
  @config_path = nil
19
20
  @fail_level = :error
20
21
  @format = :text
@@ -65,6 +66,10 @@ module ThemeCheck
65
66
  "--print",
66
67
  "Output active config to STDOUT"
67
68
  ) { @command = :print }
69
+ @option_parser.on(
70
+ "--update-docs",
71
+ "Update Theme Check docs (objects, filters, and tags)"
72
+ ) { @update_docs = true }
68
73
  @option_parser.on(
69
74
  "-h", "--help",
70
75
  "Show this. Hi!"
@@ -181,6 +186,8 @@ module ThemeCheck
181
186
  end
182
187
 
183
188
  def check(out_stream = STDOUT)
189
+ update_docs
190
+
184
191
  STDERR.puts "Checking #{@config.root} ..."
185
192
  storage = ThemeCheck::FileSystemStorage.new(@config.root, ignored_patterns: @config.ignored_patterns)
186
193
  theme = ThemeCheck::Theme.new(storage)
@@ -199,6 +206,14 @@ module ThemeCheck
199
206
  end
200
207
  end
201
208
 
209
+ def update_docs
210
+ return unless @update_docs
211
+
212
+ STDERR.puts 'Updating documentation...'
213
+
214
+ ThemeCheck::ShopifyLiquid::SourceManager.download
215
+ end
216
+
202
217
  def profile
203
218
  require 'ruby-prof-flamegraph'
204
219
 
@@ -15,8 +15,10 @@ module ThemeCheck
15
15
  return [] unless can_complete?(content, cursor)
16
16
 
17
17
  context = context_with_cursor_before_potential_filter_separator(context)
18
- available_filters_for(determine_input_type(context))
19
- .select { |w| w.name.start_with?(partial(content, cursor)) }
18
+ variable_lookup = VariableLookupFinder.lookup(context)
19
+ denied_filters = denied_filters_for(variable_lookup)
20
+ available_filters_for(determine_input_type(variable_lookup))
21
+ .select { |filter| filter.name.start_with?(partial(content, cursor)) && denied_filters.none?(filter.name) }
20
22
  .map { |filter| filter_to_completion(filter) }
21
23
  end
22
24
 
@@ -38,14 +40,18 @@ module ThemeCheck
38
40
  context.clone_and_overwrite(col: context.col + diff)
39
41
  end
40
42
 
41
- def determine_input_type(context)
42
- variable_lookup = VariableLookupFinder.lookup(context)
43
+ def determine_input_type(variable_lookup)
44
+ return if variable_lookup.nil?
43
45
 
44
- if variable_lookup
45
- object, property = VariableLookupTraverser.lookup_object_and_property(variable_lookup)
46
- return property.return_type if property
47
- return object.name if object
48
- end
46
+ object, property = VariableLookupTraverser.lookup_object_and_property(variable_lookup)
47
+ return property.return_type if property
48
+ return object.name if object
49
+ end
50
+
51
+ def denied_filters_for(variable_lookup)
52
+ return [] if variable_lookup.nil?
53
+
54
+ VariableLookupTraverser.find_object(variable_lookup.name).denied_filters
49
55
  end
50
56
 
51
57
  def available_filters_for(input_type)
@@ -16,7 +16,7 @@ module ThemeCheck
16
16
  private
17
17
 
18
18
  def title(entry)
19
- "### #{entry.name}"
19
+ "### [#{entry.name}](#{entry.shopify_dev_url})"
20
20
  end
21
21
 
22
22
  def body(entry)
@@ -10,7 +10,9 @@ module ThemeCheck
10
10
 
11
11
  attr_reader :hash
12
12
 
13
- def_delegators :return_type_instance, :generic_type?, :array_type?, :array_type, :to_s
13
+ def_delegators :return_type_instance, :generic_type?, :array_type?, :array_type, :to_s, :denied_filters
14
+
15
+ SHOPIFY_DEV_ROOT_URL = "https://shopify.dev/api/liquid"
14
16
 
15
17
  def initialize(hash = {})
16
18
  @hash = hash || {}
@@ -39,6 +41,10 @@ module ThemeCheck
39
41
  hash['deprecation_reason'] || nil
40
42
  end
41
43
 
44
+ def shopify_dev_url
45
+ SHOPIFY_DEV_ROOT_URL
46
+ end
47
+
42
48
  attr_writer :return_type
43
49
 
44
50
  def return_type
@@ -10,7 +10,11 @@ module ThemeCheck
10
10
  end
11
11
 
12
12
  def input_type
13
- hash['syntax'].split(' | ')[0]
13
+ @input_type ||= hash['syntax'].split(' | ')[0]
14
+ end
15
+
16
+ def shopify_dev_url
17
+ "#{SHOPIFY_DEV_ROOT_URL}/filters/#{hash['name']}"
14
18
  end
15
19
  end
16
20
  end
@@ -6,7 +6,13 @@ module ThemeCheck
6
6
  class ObjectEntry < BaseEntry
7
7
  def properties
8
8
  (hash['properties'] || [])
9
- .map { |hash| PropertyEntry.new(hash) }
9
+ .map do |prop_hash|
10
+ PropertyEntry.new(prop_hash, hash['name'])
11
+ end
12
+ end
13
+
14
+ def shopify_dev_url
15
+ "#{SHOPIFY_DEV_ROOT_URL}/objects/#{hash['name']}"
10
16
  end
11
17
  end
12
18
  end
@@ -8,6 +8,10 @@ module ThemeCheck
8
8
  nil
9
9
  end
10
10
 
11
+ def shopify_dev_url
12
+ "#{SHOPIFY_DEV_ROOT_URL}/filters/#{hash['name']}"
13
+ end
14
+
11
15
  private
12
16
 
13
17
  def return_type_hash
@@ -3,7 +3,19 @@
3
3
  module ThemeCheck
4
4
  module ShopifyLiquid
5
5
  class SourceIndex
6
- class PropertyEntry < BaseEntry; end
6
+ class PropertyEntry < BaseEntry
7
+ attr_reader :parent_name
8
+
9
+ def initialize(hash, parent_name)
10
+ @hash = hash || {}
11
+ @return_type = nil
12
+ @parent_name = parent_name
13
+ end
14
+
15
+ def shopify_dev_url
16
+ "#{SHOPIFY_DEV_ROOT_URL}/objects/#{parent_name}##{parent_name}-#{hash['name']}"
17
+ end
18
+ end
7
19
  end
8
20
  end
9
21
  end
@@ -24,6 +24,10 @@ module ThemeCheck
24
24
  hash['array_value']
25
25
  end
26
26
 
27
+ def denied_filters
28
+ hash['denied_filters'] || []
29
+ end
30
+
27
31
  private
28
32
 
29
33
  def return_type_hash
@@ -14,6 +14,10 @@ module ThemeCheck
14
14
  'type' => "tag<#{name}>",
15
15
  }
16
16
  end
17
+
18
+ def shopify_dev_url
19
+ "#{SHOPIFY_DEV_ROOT_URL}/tags/#{hash['name']}"
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- VERSION = "1.13.0"
3
+ VERSION = "1.15.0"
4
4
  end