@platformos/platformos-check-common 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/AugmentedPlatformOSDocset.d.ts +11 -0
  3. package/dist/AugmentedPlatformOSDocset.js +81 -0
  4. package/dist/AugmentedPlatformOSDocset.js.map +1 -0
  5. package/dist/JSONValidator.js +1 -1
  6. package/dist/JSONValidator.js.map +1 -1
  7. package/dist/checks/deprecated-filter/index.js +4 -41
  8. package/dist/checks/deprecated-filter/index.js.map +1 -1
  9. package/dist/checks/deprecated-tag/index.js +21 -22
  10. package/dist/checks/deprecated-tag/index.js.map +1 -1
  11. package/dist/checks/duplicate-function-arguments/index.js +1 -1
  12. package/dist/checks/duplicate-function-arguments/index.js.map +1 -1
  13. package/dist/checks/duplicate-render-partial-arguments/index.js +1 -1
  14. package/dist/checks/duplicate-render-partial-arguments/index.js.map +1 -1
  15. package/dist/checks/graphql/index.js +1 -1
  16. package/dist/checks/graphql/index.js.map +1 -1
  17. package/dist/checks/img-width-and-height/index.js +1 -1
  18. package/dist/checks/img-width-and-height/index.js.map +1 -1
  19. package/dist/checks/index.d.ts +3 -3
  20. package/dist/checks/index.js +4 -79
  21. package/dist/checks/index.js.map +1 -1
  22. package/dist/checks/json-syntax-error/index.js +1 -1
  23. package/dist/checks/json-syntax-error/index.js.map +1 -1
  24. package/dist/checks/liquid-html-syntax-error/index.js +2 -2
  25. package/dist/checks/liquid-html-syntax-error/index.js.map +1 -1
  26. package/dist/checks/matching-translations/index.d.ts +2 -2
  27. package/dist/checks/matching-translations/index.js +20 -31
  28. package/dist/checks/matching-translations/index.js.map +1 -1
  29. package/dist/checks/metadata-params/index.js +6 -3
  30. package/dist/checks/metadata-params/index.js.map +1 -1
  31. package/dist/checks/missing-asset/index.js +1 -1
  32. package/dist/checks/missing-asset/index.js.map +1 -1
  33. package/dist/checks/missing-partial/index.d.ts +6 -0
  34. package/dist/checks/missing-partial/index.js +70 -0
  35. package/dist/checks/missing-partial/index.js.map +1 -0
  36. package/dist/checks/orphaned-partial/index.js +4 -4
  37. package/dist/checks/orphaned-partial/index.js.map +1 -1
  38. package/dist/checks/parser-blocking-script/index.js +10 -36
  39. package/dist/checks/parser-blocking-script/index.js.map +1 -1
  40. package/dist/checks/parser-blocking-script/suggestions.d.ts +1 -2
  41. package/dist/checks/parser-blocking-script/suggestions.js +1 -11
  42. package/dist/checks/parser-blocking-script/suggestions.js.map +1 -1
  43. package/dist/checks/reserved-doc-param-names/index.js +6 -5
  44. package/dist/checks/reserved-doc-param-names/index.js.map +1 -1
  45. package/dist/checks/translation-key-exists/index.js +1 -1
  46. package/dist/checks/translation-key-exists/index.js.map +1 -1
  47. package/dist/checks/unclosed-html-element/index.js +5 -1
  48. package/dist/checks/unclosed-html-element/index.js.map +1 -1
  49. package/dist/checks/undefined-object/index.js +7 -30
  50. package/dist/checks/undefined-object/index.js.map +1 -1
  51. package/dist/checks/unique-doc-param-names/index.js +1 -1
  52. package/dist/checks/unique-doc-param-names/index.js.map +1 -1
  53. package/dist/checks/unknown-filter/index.js +3 -3
  54. package/dist/checks/unknown-filter/index.js.map +1 -1
  55. package/dist/checks/unknown-property/index.js +1 -1
  56. package/dist/checks/unknown-property/index.js.map +1 -1
  57. package/dist/checks/unrecognized-render-partial-arguments/index.js +2 -2
  58. package/dist/checks/unrecognized-render-partial-arguments/index.js.map +1 -1
  59. package/dist/checks/unused-assign/index.js +1 -1
  60. package/dist/checks/unused-assign/index.js.map +1 -1
  61. package/dist/checks/unused-doc-param/index.js +1 -1
  62. package/dist/checks/unused-doc-param/index.js.map +1 -1
  63. package/dist/checks/utils.js +1 -1
  64. package/dist/checks/utils.js.map +1 -1
  65. package/dist/checks/valid-content-for-arguments/index.js +1 -1
  66. package/dist/checks/valid-content-for-arguments/index.js.map +1 -1
  67. package/dist/checks/valid-doc-param-types/index.js +4 -4
  68. package/dist/checks/valid-doc-param-types/index.js.map +1 -1
  69. package/dist/checks/valid-html-translation/index.d.ts +2 -2
  70. package/dist/checks/valid-html-translation/index.js +4 -4
  71. package/dist/checks/valid-html-translation/index.js.map +1 -1
  72. package/dist/checks/valid-json/index.js +1 -1
  73. package/dist/checks/valid-json/index.js.map +1 -1
  74. package/dist/checks/valid-render-partial-argument-types/index.js +2 -2
  75. package/dist/checks/valid-render-partial-argument-types/index.js.map +1 -1
  76. package/dist/checks/variable-name/index.js +1 -1
  77. package/dist/checks/variable-name/index.js.map +1 -1
  78. package/dist/context-utils.d.ts +2 -7
  79. package/dist/context-utils.js +39 -109
  80. package/dist/context-utils.js.map +1 -1
  81. package/dist/disabled-checks/index.js +4 -2
  82. package/dist/disabled-checks/index.js.map +1 -1
  83. package/dist/find-root.d.ts +7 -10
  84. package/dist/find-root.js +10 -17
  85. package/dist/find-root.js.map +1 -1
  86. package/dist/fixes/autofix.d.ts +4 -4
  87. package/dist/fixes/autofix.js +2 -2
  88. package/dist/fixes/autofix.js.map +1 -1
  89. package/dist/fixes/correctors/index.js +4 -0
  90. package/dist/fixes/correctors/index.js.map +1 -1
  91. package/dist/index.d.ts +4 -5
  92. package/dist/index.js +34 -17
  93. package/dist/index.js.map +1 -1
  94. package/dist/jsonc/parse.d.ts +1 -1
  95. package/dist/jsonc/parse.js +1 -1
  96. package/dist/liquid-doc/arguments.d.ts +7 -8
  97. package/dist/liquid-doc/arguments.js +20 -28
  98. package/dist/liquid-doc/arguments.js.map +1 -1
  99. package/dist/liquid-doc/liquidDoc.d.ts +1 -1
  100. package/dist/liquid-doc/liquidDoc.js.map +1 -1
  101. package/dist/liquid-doc/utils.d.ts +1 -1
  102. package/dist/liquid-doc/utils.js +4 -3
  103. package/dist/liquid-doc/utils.js.map +1 -1
  104. package/dist/path.d.ts +1 -0
  105. package/dist/path.js +5 -1
  106. package/dist/path.js.map +1 -1
  107. package/dist/test/MockApp.d.ts +16 -0
  108. package/dist/test/MockApp.js +16 -0
  109. package/dist/test/MockApp.js.map +1 -0
  110. package/dist/test/MockFileSystem.d.ts +3 -3
  111. package/dist/test/MockFileSystem.js +6 -6
  112. package/dist/test/MockFileSystem.js.map +1 -1
  113. package/dist/test/index.d.ts +1 -1
  114. package/dist/test/index.js +1 -1
  115. package/dist/test/index.js.map +1 -1
  116. package/dist/test/test-helper.d.ts +10 -9
  117. package/dist/test/test-helper.js +15 -106
  118. package/dist/test/test-helper.js.map +1 -1
  119. package/dist/to-source-code.d.ts +4 -3
  120. package/dist/to-source-code.js +20 -0
  121. package/dist/to-source-code.js.map +1 -1
  122. package/dist/tsconfig.tsbuildinfo +1 -1
  123. package/dist/types/platformos-liquid-docs.d.ts +128 -0
  124. package/dist/types/platformos-liquid-docs.js +3 -0
  125. package/dist/types/platformos-liquid-docs.js.map +1 -0
  126. package/dist/types/schemas/index.d.ts +0 -2
  127. package/dist/types/schemas/index.js.map +1 -1
  128. package/dist/types.d.ts +18 -67
  129. package/dist/types.js +3 -5
  130. package/dist/types.js.map +1 -1
  131. package/dist/utils/file-utils.js +1 -2
  132. package/dist/utils/file-utils.js.map +1 -1
  133. package/dist/utils/index.d.ts +0 -1
  134. package/dist/utils/index.js +0 -1
  135. package/dist/utils/index.js.map +1 -1
  136. package/dist/yaml/parse.d.ts +5 -0
  137. package/dist/yaml/parse.js +94 -0
  138. package/dist/yaml/parse.js.map +1 -0
  139. package/package.json +9 -9
  140. package/src/{AugmentedThemeDocset.spec.ts → AugmentedPlatformOSDocset.spec.ts} +47 -34
  141. package/src/AugmentedPlatformOSDocset.ts +89 -0
  142. package/src/JSONValidator.ts +1 -1
  143. package/src/checks/deprecated-filter/index.spec.ts +76 -248
  144. package/src/checks/deprecated-filter/index.ts +5 -53
  145. package/src/checks/deprecated-tag/index.spec.ts +85 -34
  146. package/src/checks/deprecated-tag/index.ts +27 -22
  147. package/src/checks/duplicate-function-arguments/index.ts +1 -1
  148. package/src/checks/duplicate-render-partial-arguments/index.ts +1 -1
  149. package/src/checks/graphql/index.ts +1 -1
  150. package/src/checks/img-width-and-height/index.ts +1 -1
  151. package/src/checks/index.ts +11 -80
  152. package/src/checks/invalid-hash-assign-target/index.spec.ts +14 -14
  153. package/src/checks/json-syntax-error/index.ts +1 -1
  154. package/src/checks/liquid-html-syntax-error/checks/InvalidBooleanExpression.spec.ts +0 -11
  155. package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.spec.ts +1 -2
  156. package/src/checks/liquid-html-syntax-error/index.spec.ts +1 -6
  157. package/src/checks/liquid-html-syntax-error/index.ts +2 -2
  158. package/src/checks/matching-translations/index.spec.ts +89 -346
  159. package/src/checks/matching-translations/index.ts +24 -35
  160. package/src/checks/metadata-params/index.ts +5 -7
  161. package/src/checks/missing-asset/index.ts +1 -1
  162. package/src/checks/{missing-template → missing-partial}/index.spec.ts +6 -6
  163. package/src/checks/{missing-template → missing-partial}/index.ts +6 -20
  164. package/src/checks/orphaned-partial/index.ts +3 -3
  165. package/src/checks/parser-blocking-script/index.spec.ts +0 -118
  166. package/src/checks/parser-blocking-script/index.ts +3 -33
  167. package/src/checks/parser-blocking-script/suggestions.ts +1 -28
  168. package/src/checks/translation-key-exists/index.ts +1 -1
  169. package/src/checks/unclosed-html-element/index.ts +5 -1
  170. package/src/checks/undefined-object/index.spec.ts +3 -109
  171. package/src/checks/undefined-object/index.ts +8 -33
  172. package/src/checks/unique-doc-param-names/index.ts +1 -1
  173. package/src/checks/unknown-filter/index.spec.ts +2 -2
  174. package/src/checks/unknown-filter/index.ts +3 -3
  175. package/src/checks/unknown-property/index.ts +1 -1
  176. package/src/checks/unrecognized-render-partial-arguments/index.spec.ts +5 -5
  177. package/src/checks/unrecognized-render-partial-arguments/index.ts +2 -5
  178. package/src/checks/unused-assign/index.spec.ts +0 -30
  179. package/src/checks/unused-assign/index.ts +1 -1
  180. package/src/checks/unused-doc-param/index.ts +1 -1
  181. package/src/checks/utils.ts +1 -1
  182. package/src/checks/valid-doc-param-types/index.ts +4 -4
  183. package/src/checks/valid-html-translation/index.spec.ts +42 -32
  184. package/src/checks/valid-html-translation/index.ts +7 -7
  185. package/src/checks/valid-json/index.ts +1 -1
  186. package/src/checks/valid-render-partial-argument-types/index.ts +2 -5
  187. package/src/checks/variable-name/index.ts +1 -1
  188. package/src/context-utils.spec.ts +49 -77
  189. package/src/context-utils.ts +39 -128
  190. package/src/disabled-checks/index.spec.ts +35 -0
  191. package/src/disabled-checks/index.ts +4 -2
  192. package/src/find-root.ts +12 -22
  193. package/src/fixes/autofix.spec.ts +2 -2
  194. package/src/fixes/autofix.ts +4 -4
  195. package/src/fixes/correctors/index.ts +4 -0
  196. package/src/ignore.spec.ts +0 -1
  197. package/src/index.ts +33 -21
  198. package/src/jsonc/parse.ts +1 -1
  199. package/src/liquid-doc/arguments.spec.ts +19 -45
  200. package/src/liquid-doc/arguments.ts +26 -39
  201. package/src/liquid-doc/liquidDoc.ts +1 -2
  202. package/src/liquid-doc/utils.ts +4 -3
  203. package/src/path.ts +1 -0
  204. package/src/test/{MockTheme.ts → MockApp.ts} +1 -1
  205. package/src/test/MockFileSystem.ts +9 -6
  206. package/src/test/index.ts +1 -1
  207. package/src/test/test-helper.ts +29 -127
  208. package/src/to-source-code.ts +20 -1
  209. package/src/types/{theme-liquid-docs.ts → platformos-liquid-docs.ts} +8 -13
  210. package/src/types/schemas/index.ts +0 -2
  211. package/src/types.ts +21 -92
  212. package/src/utils/file-utils.ts +0 -1
  213. package/src/utils/index.ts +0 -1
  214. package/src/yaml/parse.ts +111 -0
  215. package/src/AugmentedThemeDocset.ts +0 -137
  216. package/src/checks/app-block-missing-schema/index.spec.ts +0 -121
  217. package/src/checks/app-block-missing-schema/index.ts +0 -46
  218. package/src/checks/app-block-valid-tags/index.spec.ts +0 -96
  219. package/src/checks/app-block-valid-tags/index.ts +0 -54
  220. package/src/checks/asset-preload/index.spec.ts +0 -78
  221. package/src/checks/asset-preload/index.ts +0 -65
  222. package/src/checks/asset-size-app-block-css/index.spec.ts +0 -88
  223. package/src/checks/asset-size-app-block-css/index.ts +0 -78
  224. package/src/checks/asset-size-app-block-javascript/index.spec.ts +0 -66
  225. package/src/checks/asset-size-app-block-javascript/index.ts +0 -78
  226. package/src/checks/asset-size-css/index.spec.ts +0 -166
  227. package/src/checks/asset-size-css/index.ts +0 -160
  228. package/src/checks/asset-size-javascript/index.spec.ts +0 -184
  229. package/src/checks/asset-size-javascript/index.ts +0 -144
  230. package/src/checks/block-id-usage/index.spec.ts +0 -76
  231. package/src/checks/block-id-usage/index.ts +0 -72
  232. package/src/checks/cdn-preconnect/index.spec.ts +0 -40
  233. package/src/checks/cdn-preconnect/index.ts +0 -43
  234. package/src/checks/content-for-header-modification/index.spec.ts +0 -65
  235. package/src/checks/content-for-header-modification/index.ts +0 -72
  236. package/src/checks/deprecate-bgsizes/index.spec.ts +0 -41
  237. package/src/checks/deprecate-bgsizes/index.ts +0 -49
  238. package/src/checks/deprecate-lazysizes/index.spec.ts +0 -26
  239. package/src/checks/deprecate-lazysizes/index.ts +0 -58
  240. package/src/checks/deprecated-filter/fixes.ts +0 -264
  241. package/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts +0 -1343
  242. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts +0 -613
  243. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts +0 -284
  244. package/src/checks/deprecated-fonts-on-settings-schema/index.spec.ts +0 -102
  245. package/src/checks/deprecated-fonts-on-settings-schema/index.ts +0 -66
  246. package/src/checks/duplicate-content-for-arguments/index.spec.ts +0 -98
  247. package/src/checks/duplicate-content-for-arguments/index.ts +0 -43
  248. package/src/checks/empty-block-content/index.spec.ts +0 -117
  249. package/src/checks/empty-block-content/index.ts +0 -60
  250. package/src/checks/hardcoded-routes/index.spec.ts +0 -58
  251. package/src/checks/hardcoded-routes/index.ts +0 -100
  252. package/src/checks/json-missing-block/index.spec.ts +0 -435
  253. package/src/checks/json-missing-block/index.ts +0 -56
  254. package/src/checks/json-missing-block/missing-block-utils.ts +0 -147
  255. package/src/checks/liquid-free-settings/index.spec.ts +0 -180
  256. package/src/checks/liquid-free-settings/index.ts +0 -79
  257. package/src/checks/missing-content-for-arguments/index.spec.ts +0 -144
  258. package/src/checks/missing-content-for-arguments/index.ts +0 -46
  259. package/src/checks/pagination-size/index.spec.ts +0 -158
  260. package/src/checks/pagination-size/index.ts +0 -104
  261. package/src/checks/remote-asset/index.spec.ts +0 -280
  262. package/src/checks/remote-asset/index.ts +0 -238
  263. package/src/checks/reserved-doc-param-names/index.spec.ts +0 -62
  264. package/src/checks/reserved-doc-param-names/index.ts +0 -57
  265. package/src/checks/schema-presets-block-order/index.spec.ts +0 -344
  266. package/src/checks/schema-presets-block-order/index.ts +0 -154
  267. package/src/checks/schema-presets-static-blocks/index.spec.ts +0 -145
  268. package/src/checks/schema-presets-static-blocks/index.ts +0 -126
  269. package/src/checks/static-stylesheet-and-javascript-tags/index.spec.ts +0 -257
  270. package/src/checks/static-stylesheet-and-javascript-tags/index.ts +0 -48
  271. package/src/checks/unique-settings-id/index.spec.ts +0 -24
  272. package/src/checks/unique-settings-id/index.ts +0 -84
  273. package/src/checks/unique-settings-id/test-data.ts +0 -1191
  274. package/src/checks/unique-static-block-id/index.spec.ts +0 -55
  275. package/src/checks/unique-static-block-id/index.ts +0 -60
  276. package/src/checks/unrecognized-content-for-arguments/index.spec.ts +0 -145
  277. package/src/checks/unrecognized-content-for-arguments/index.ts +0 -55
  278. package/src/checks/valid-block-target/index.spec.ts +0 -1396
  279. package/src/checks/valid-block-target/index.ts +0 -142
  280. package/src/checks/valid-content-for-argument-types/index.spec.ts +0 -382
  281. package/src/checks/valid-content-for-argument-types/index.ts +0 -42
  282. package/src/checks/valid-content-for-arguments/index.spec.ts +0 -107
  283. package/src/checks/valid-content-for-arguments/index.ts +0 -98
  284. package/src/checks/valid-local-blocks/index.spec.ts +0 -286
  285. package/src/checks/valid-local-blocks/index.ts +0 -100
  286. package/src/checks/valid-local-blocks/valid-block-utils.ts +0 -97
  287. package/src/checks/valid-schema/index.spec.ts +0 -174
  288. package/src/checks/valid-schema/index.ts +0 -41
  289. package/src/checks/valid-schema-name/index.spec.ts +0 -112
  290. package/src/checks/valid-schema-name/index.ts +0 -75
  291. package/src/checks/valid-settings-key/index.spec.ts +0 -321
  292. package/src/checks/valid-settings-key/index.ts +0 -144
  293. package/src/checks/valid-static-block-type/index.spec.ts +0 -38
  294. package/src/checks/valid-static-block-type/index.ts +0 -58
  295. package/src/checks/valid-visible-if/index.spec.ts +0 -619
  296. package/src/checks/valid-visible-if/index.ts +0 -184
  297. package/src/checks/valid-visible-if/visible-if-utils.ts +0 -158
  298. package/src/tags/content-for.ts +0 -25
  299. package/src/to-schema.ts +0 -231
  300. package/src/types/schemas/section.ts +0 -86
  301. package/src/types/schemas/theme-block.ts +0 -34
  302. package/src/types/theme-schemas.ts +0 -80
  303. package/src/utils/block.ts +0 -300
  304. package/src/utils/markup.ts +0 -10
@@ -1,98 +0,0 @@
1
- import { ContentForMarkup, NodeTypes } from '@platformos/liquid-html-parser';
2
- import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';
3
- import {
4
- CLOSEST_ARGUMENT,
5
- REQUIRED_CONTENT_FOR_ARGUMENTS,
6
- RESERVED_CONTENT_FOR_ARGUMENTS,
7
- } from '../../tags/content-for';
8
-
9
- export const ValidContentForArguments: LiquidCheckDefinition = {
10
- meta: {
11
- code: 'ValidContentForArguments',
12
- name: 'Prevent the use of invalid arguments to the content_for tag',
13
- docs: {
14
- description:
15
- 'This check is aimed at preventing the use of invalid arguments for the content_for tag.',
16
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/valid-content-for-arguments',
17
- recommended: true,
18
- },
19
- type: SourceCodeType.LiquidHtml,
20
- severity: Severity.ERROR,
21
- schema: {},
22
- targets: [],
23
- },
24
-
25
- create(context) {
26
- const validationStrategies = {
27
- blocks: (node: ContentForMarkup) => {
28
- const problematicArguments = node.args.filter(
29
- (arg) => !arg.name.startsWith(CLOSEST_ARGUMENT),
30
- );
31
-
32
- for (const arg of problematicArguments) {
33
- context.report({
34
- message: `{% content_for "blocks" %} only accepts 'closest.*' arguments`,
35
- startIndex: arg.position.start,
36
- endIndex: arg.position.end,
37
- });
38
- }
39
- },
40
-
41
- block: (node: ContentForMarkup) => {
42
- // Make sure the id and string arguments are present and are strings
43
- for (const requiredArgumentName of REQUIRED_CONTENT_FOR_ARGUMENTS) {
44
- const arg = node.args.find((arg) => arg.name === requiredArgumentName);
45
-
46
- if (!arg) {
47
- context.report({
48
- message: `{% content_for "block" %} requires a '${requiredArgumentName}' argument`,
49
- startIndex: node.position.start,
50
- endIndex: node.position.end,
51
- suggest: [],
52
- });
53
- continue;
54
- }
55
-
56
- const argValueNode = arg.value;
57
- if (argValueNode.type !== NodeTypes.String) {
58
- context.report({
59
- message: `The '${requiredArgumentName}' argument should be a string`,
60
- startIndex: argValueNode.position.start,
61
- endIndex: argValueNode.position.end,
62
- suggest: [],
63
- });
64
- }
65
- }
66
-
67
- const problematicArguments = node.args.filter((arg) =>
68
- RESERVED_CONTENT_FOR_ARGUMENTS.includes(arg.name),
69
- );
70
-
71
- for (const arg of problematicArguments) {
72
- context.report({
73
- message: `{% content_for "block" %} doesn't support '${arg.name}' because it's a reserved argument.`,
74
- startIndex: arg.position.start,
75
- endIndex: arg.position.end,
76
- });
77
- }
78
- },
79
- };
80
-
81
- return {
82
- async LiquidTag(node) {
83
- if (node.name !== 'content_for' || typeof node.markup === 'string') {
84
- return;
85
- }
86
-
87
- /** "block", "blocks", etc. */
88
- const contentForType = node.markup.contentForType.value;
89
- const validate = validationStrategies[contentForType as keyof typeof validationStrategies];
90
- if (!validate) {
91
- return;
92
- }
93
-
94
- validate(node.markup);
95
- },
96
- };
97
- },
98
- };
@@ -1,286 +0,0 @@
1
- import { expect, describe, it } from 'vitest';
2
- import { ValidLocalBlocks } from './index';
3
- import { check, MockTheme } from '../../test';
4
-
5
- describe('ValidLocalBlocks with array-style blocks', () => {
6
- it('should report errors when root level local blocks are defined in a block bucket', async () => {
7
- const theme: MockTheme = {
8
- 'blocks/local-blocks.liquid': `
9
- {% schema %}
10
- {
11
- "name": "Block name",
12
- "blocks": [
13
- {
14
- "type": "local_block",
15
- "name": "Local Block"
16
- }
17
- ]
18
- }
19
- {% endschema %}
20
- `,
21
- };
22
-
23
- const offenses = await check(theme, [ValidLocalBlocks]);
24
- expect(offenses).to.have.length(1);
25
- expect(offenses[0].message).to.equal('Local scoped blocks are not supported in theme blocks.');
26
- });
27
-
28
- it('should report errors when sections use theme blocks together with locally scoped blocks in root level', async () => {
29
- const theme: MockTheme = {
30
- 'blocks/text.liquid': '',
31
- 'sections/local-blocks.liquid': `
32
- {% schema %}
33
- {
34
- "name": "Section name",
35
- "blocks": [
36
- {
37
- "type": "text"
38
- },
39
- {
40
- "type": "local_block",
41
- "name": "Local Block"
42
- }
43
- ]
44
- }
45
- {% endschema %}
46
- `,
47
- };
48
- const offenses = await check(theme, [ValidLocalBlocks]);
49
- expect(offenses).to.have.length(1);
50
- expect(offenses[0].message).to.equal(
51
- 'Sections cannot use theme blocks together with locally scoped blocks.',
52
- );
53
- });
54
-
55
- it('should report errors when sections use static theme blocks together with locally scoped blocks', async () => {
56
- const theme: MockTheme = {
57
- 'sections/local-blocks.liquid': `
58
- {% schema %}
59
- {
60
- "name": "Section name",
61
- "blocks": [
62
- {
63
- "type": "local_block",
64
- "name": "Local Block"
65
- }
66
- ],
67
- "presets": [
68
- {
69
- "name": "Default",
70
- "blocks": [
71
- {
72
- "id": "static_block",
73
- "type": "static_block",
74
- "static": true
75
- }
76
- ]
77
- }
78
- ]
79
- }
80
- {% endschema %}
81
- `,
82
- };
83
- const offenses = await check(theme, [ValidLocalBlocks]);
84
- expect(offenses).to.have.length(1);
85
- expect(offenses[0].message).to.equal(
86
- 'Sections cannot use static theme blocks together with locally scoped blocks.',
87
- );
88
- });
89
-
90
- it('should report errors with correct indices when sections use static theme blocks together with locally scoped blocks', async () => {
91
- const theme: MockTheme = {
92
- 'sections/local-blocks.liquid': `
93
- {% schema %}
94
- {
95
- "name": "Section name",
96
- "blocks": [
97
- {
98
- "type": "local_block",
99
- "name": "Local Block"
100
- }
101
- ],
102
- "presets": [
103
- {
104
- "name": "Default",
105
- "blocks": [
106
- {
107
- "id": "static_block",
108
- "type": "static_block",
109
- "static": true
110
- }
111
- ]
112
- }
113
- ]
114
- }
115
- {% endschema %}
116
- `,
117
- };
118
- const offenses = await check(theme, [ValidLocalBlocks]);
119
- expect(offenses).to.have.length(1);
120
-
121
- const content = theme['sections/local-blocks.liquid'];
122
- const errorContent = content.slice(offenses[0].start.index, offenses[0].end.index);
123
- expect(errorContent).to.equal('"static_block"');
124
- });
125
- });
126
-
127
- describe('ValidLocalBlocks on edge cases', () => {
128
- it('should not report errors for block setting types', async () => {
129
- const theme: MockTheme = {
130
- 'sections/local-blocks.liquid': `
131
- {% schema %}
132
- {
133
- "name": "Section name",
134
- "blocks": [
135
- {
136
- "type": "@app"
137
- },
138
- {
139
- "type": "link_list",
140
- "name": "Link list",
141
- "settings": [
142
- {
143
- "type": "inline_richtext",
144
- "id": "heading",
145
- "default": "Heading"
146
- },
147
- {
148
- "type": "link_list",
149
- "id": "menu",
150
- "default": "Footer"
151
- }
152
- ]
153
- }
154
- ]
155
- }
156
- {% endschema %}
157
- `,
158
- };
159
-
160
- const offenses = await check(theme, [ValidLocalBlocks]);
161
- expect(offenses).to.be.empty;
162
- });
163
-
164
- it('should not report errors when @app is used alongside static blocks', async () => {
165
- const theme: MockTheme = {
166
- 'sections/local-blocks.liquid': `
167
- {% schema %}
168
- {
169
- "name": "Section name",
170
- "blocks": [
171
- {
172
- "type": "@app"
173
- },
174
- {
175
- "type": "static_block",
176
- "static": true
177
- }
178
- ]
179
- }
180
- {% endschema %}
181
- `,
182
- };
183
-
184
- const offenses = await check(theme, [ValidLocalBlocks]);
185
- expect(offenses).to.be.empty;
186
- });
187
-
188
- it('should not report errors on themes that define local blocks at the root level and use them in presets', async () => {
189
- const theme: MockTheme = {
190
- 'sections/local-blocks.liquid': `
191
- {% schema %}
192
- {
193
- "name": "Section name",
194
- "blocks": [
195
- {
196
- "type": "local_block",
197
- "name": "Local Block"
198
- }
199
- ],
200
- "presets": [
201
- {
202
- "name": "Default",
203
- "blocks": [
204
- {
205
- "type": "local_block"
206
- }
207
- ]
208
- }
209
- ]
210
- }
211
- {% endschema %}
212
- `,
213
- };
214
-
215
- const offenses = await check(theme, [ValidLocalBlocks]);
216
- expect(offenses).to.be.empty;
217
- });
218
-
219
- it('should not report errors on older themes that define local blocks at the root level and use them in hash-style presets', async () => {
220
- const theme: MockTheme = {
221
- 'sections/local-blocks.liquid': `
222
- {% schema %}
223
- {
224
- "name": "Section name",
225
- "blocks": [
226
- {
227
- "type": "local_block",
228
- "name": "Local Block"
229
- }
230
- ],
231
- "presets": [
232
- {
233
- "name": "Default",
234
- "blocks": {
235
- "local_block": {
236
- "type": "local_block"
237
- }
238
- }
239
- }
240
- ]
241
- }
242
- {% endschema %}
243
- `,
244
- };
245
- const offenses = await check(theme, [ValidLocalBlocks]);
246
- expect(offenses).to.be.empty;
247
- });
248
-
249
- it('should not report errors when preset blocks have a name property', async () => {
250
- const theme: MockTheme = {
251
- 'blocks/product-grid.liquid': `
252
- {% schema %}
253
- {
254
- "name": "Product grid",
255
- "blocks": [{ "type": "product-card" }],
256
- "presets": [
257
- {
258
- "name": "Product grid",
259
- "blocks": {
260
- "product-grid-card": {
261
- "type": "product-card",
262
- "static": true,
263
- "blocks": {
264
- "card_gallery_eK4Hr7": {
265
- "type": "card-gallery",
266
- "name": "potato",
267
- },
268
- "group_4RMFLV": {
269
- "type": "group"
270
- }
271
- },
272
- "block_order": ["card_gallery_eK4Hr7", "group_4RMFLV"]
273
- }
274
- }
275
- }
276
- ]
277
- }
278
- {% endschema %}
279
-
280
- `,
281
- };
282
-
283
- const offenses = await check(theme, [ValidLocalBlocks]);
284
- expect(offenses).to.be.empty;
285
- });
286
- });
@@ -1,100 +0,0 @@
1
- import {
2
- LiquidCheckDefinition,
3
- Preset,
4
- Severity,
5
- SourceCodeType,
6
- Section,
7
- LiteralNode,
8
- } from '../../types';
9
- import { nodeAtPath } from '../../json';
10
- import { getSchema } from '../../to-schema';
11
- import { isBlock, isSection } from '../../to-schema';
12
- import { getBlocks, reportWarning } from './valid-block-utils';
13
-
14
- type BlockNodeWithPath = {
15
- node: Section.Block | Preset.Block;
16
- path: string[];
17
- };
18
-
19
- export const ValidLocalBlocks: LiquidCheckDefinition = {
20
- meta: {
21
- code: 'ValidLocalBlocks',
22
- name: 'Prevent mixing static and local blocks in non-theme sections',
23
- docs: {
24
- description:
25
- 'Ensures sections without theme block support do not mix static and local blocks',
26
- recommended: true,
27
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/valid-local-blocks',
28
- },
29
- type: SourceCodeType.LiquidHtml,
30
- severity: Severity.ERROR,
31
- schema: {},
32
- targets: [],
33
- },
34
-
35
- create(context) {
36
- return {
37
- async LiquidRawTag(node) {
38
- if (node.name !== 'schema' || node.body.kind !== 'json') return;
39
-
40
- const offset = node.blockStartPosition.end;
41
- const schema = await getSchema(context);
42
- const { validSchema, ast } = schema ?? {};
43
- if (!validSchema || validSchema instanceof Error) return;
44
- if (!ast || ast instanceof Error) return;
45
- if (!schema) return;
46
-
47
- const {
48
- staticBlockLocations,
49
- localBlockLocations,
50
- themeBlockLocations,
51
- hasRootLevelThemeBlocks,
52
- } = getBlocks(validSchema);
53
-
54
- if (isSection(context.file.uri)) {
55
- if (staticBlockLocations.length > 0 && localBlockLocations.length > 0) {
56
- staticBlockLocations.forEach((blockWithPath: BlockNodeWithPath) => {
57
- const astNode = nodeAtPath(ast, blockWithPath.path)! as LiteralNode;
58
- reportWarning(
59
- `Sections cannot use static theme blocks together with locally scoped blocks.`,
60
- offset,
61
- astNode,
62
- context,
63
- );
64
- });
65
- }
66
-
67
- if (
68
- hasRootLevelThemeBlocks &&
69
- localBlockLocations.length > 0 &&
70
- themeBlockLocations.length > 0
71
- ) {
72
- localBlockLocations.forEach((blockWithPath: BlockNodeWithPath) => {
73
- const astNode = nodeAtPath(ast, blockWithPath.path)! as LiteralNode;
74
- reportWarning(
75
- 'Sections cannot use theme blocks together with locally scoped blocks.',
76
- offset,
77
- astNode,
78
- context,
79
- );
80
- });
81
- }
82
- }
83
-
84
- if (isBlock(context.file.uri)) {
85
- if (localBlockLocations.length > 0) {
86
- localBlockLocations.forEach((blockWithPath: BlockNodeWithPath) => {
87
- const astNode = nodeAtPath(ast, blockWithPath.path)! as LiteralNode;
88
- reportWarning(
89
- 'Local scoped blocks are not supported in theme blocks.',
90
- offset,
91
- astNode,
92
- context,
93
- );
94
- });
95
- }
96
- }
97
- },
98
- };
99
- },
100
- };
@@ -1,97 +0,0 @@
1
- import { getLocEnd, getLocStart } from '../../json';
2
- import { Preset, ThemeBlock, Section, Context, SourceCodeType, LiteralNode } from '../../types';
3
-
4
- type BlockNodeWithPath = {
5
- node: Section.Block | ThemeBlock.Block | Preset.Block;
6
- path: string[];
7
- };
8
-
9
- export function getBlocks(validSchema: ThemeBlock.Schema | Section.Schema): {
10
- staticBlockLocations: BlockNodeWithPath[];
11
- localBlockLocations: BlockNodeWithPath[];
12
- themeBlockLocations: BlockNodeWithPath[];
13
- hasRootLevelThemeBlocks: boolean;
14
- } {
15
- const staticBlockLocations: BlockNodeWithPath[] = [];
16
- const localBlockLocations: BlockNodeWithPath[] = [];
17
- const themeBlockLocations: BlockNodeWithPath[] = [];
18
-
19
- const rootLevelBlocks = validSchema.blocks;
20
- const presets = validSchema.presets;
21
-
22
- function categorizeBlock(
23
- block: Section.Block | ThemeBlock.Block | Preset.Block,
24
- currentPath: string[],
25
- inPreset: boolean = false,
26
- ) {
27
- if (!block) return;
28
- const hasStatic = 'static' in block;
29
- const hasName = 'name' in block;
30
-
31
- if (hasStatic) {
32
- staticBlockLocations.push({ node: block, path: currentPath.concat('type') });
33
- } else if (hasName && !inPreset) {
34
- localBlockLocations.push({ node: block, path: currentPath.concat('type') });
35
- } else if (block.type !== '@app') {
36
- themeBlockLocations.push({ node: block, path: currentPath.concat('type') });
37
- }
38
-
39
- if ('blocks' in block) {
40
- if (Array.isArray(block.blocks)) {
41
- block.blocks.forEach((nestedBlock: Preset.PresetBlockForArray, index: number) => {
42
- categorizeBlock(nestedBlock, currentPath.concat('blocks', String(index)), inPreset);
43
- });
44
- } else if (typeof block.blocks === 'object' && block.blocks !== null) {
45
- Object.entries(block.blocks).forEach(([key, nestedBlock]) => {
46
- categorizeBlock(nestedBlock, currentPath.concat('blocks', key), inPreset);
47
- });
48
- }
49
- }
50
- }
51
-
52
- if (Array.isArray(rootLevelBlocks)) {
53
- rootLevelBlocks.forEach((block, index) => {
54
- categorizeBlock(block, ['blocks', String(index)]);
55
- });
56
- }
57
-
58
- if (presets) {
59
- presets.forEach((preset: Preset.Preset, presetIndex: number) => {
60
- if ('blocks' in preset && preset.blocks) {
61
- if (Array.isArray(preset.blocks)) {
62
- preset.blocks.forEach((block: Preset.PresetBlockForArray, blockIndex: number) => {
63
- categorizeBlock(
64
- block,
65
- ['presets', String(presetIndex), 'blocks', String(blockIndex)],
66
- true,
67
- );
68
- });
69
- } else if (typeof preset.blocks === 'object') {
70
- Object.entries(preset.blocks).forEach(([key, block]) => {
71
- categorizeBlock(block, ['presets', String(presetIndex), 'blocks', key], true);
72
- });
73
- }
74
- }
75
- });
76
- }
77
-
78
- return {
79
- staticBlockLocations,
80
- localBlockLocations,
81
- themeBlockLocations,
82
- hasRootLevelThemeBlocks: themeBlockLocations.some((block) => block.path[0] === 'blocks'),
83
- };
84
- }
85
-
86
- export function reportWarning(
87
- message: string,
88
- offset: number,
89
- astNode: LiteralNode,
90
- context: Context<SourceCodeType.LiquidHtml>,
91
- ) {
92
- context.report({
93
- message,
94
- startIndex: offset + getLocStart(astNode),
95
- endIndex: offset + getLocEnd(astNode),
96
- });
97
- }