@platformos/platformos-check-common 0.0.7 → 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 (309) hide show
  1. package/CHANGELOG.md +8 -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/doc-generator/DocBlockGenerator.d.ts +16 -0
  84. package/dist/doc-generator/DocBlockGenerator.js +464 -0
  85. package/dist/doc-generator/DocBlockGenerator.js.map +1 -0
  86. package/dist/doc-generator/index.d.ts +1 -0
  87. package/dist/doc-generator/index.js +6 -0
  88. package/dist/doc-generator/index.js.map +1 -0
  89. package/dist/find-root.d.ts +7 -10
  90. package/dist/find-root.js +10 -17
  91. package/dist/find-root.js.map +1 -1
  92. package/dist/fixes/autofix.d.ts +4 -4
  93. package/dist/fixes/autofix.js +2 -2
  94. package/dist/fixes/autofix.js.map +1 -1
  95. package/dist/fixes/correctors/index.js +4 -0
  96. package/dist/fixes/correctors/index.js.map +1 -1
  97. package/dist/index.d.ts +4 -5
  98. package/dist/index.js +34 -17
  99. package/dist/index.js.map +1 -1
  100. package/dist/jsonc/parse.d.ts +1 -1
  101. package/dist/jsonc/parse.js +1 -1
  102. package/dist/liquid-doc/arguments.d.ts +7 -8
  103. package/dist/liquid-doc/arguments.js +20 -28
  104. package/dist/liquid-doc/arguments.js.map +1 -1
  105. package/dist/liquid-doc/liquidDoc.d.ts +1 -1
  106. package/dist/liquid-doc/liquidDoc.js.map +1 -1
  107. package/dist/liquid-doc/utils.d.ts +1 -1
  108. package/dist/liquid-doc/utils.js +4 -3
  109. package/dist/liquid-doc/utils.js.map +1 -1
  110. package/dist/path.d.ts +1 -0
  111. package/dist/path.js +5 -1
  112. package/dist/path.js.map +1 -1
  113. package/dist/test/MockApp.d.ts +16 -0
  114. package/dist/test/MockApp.js +16 -0
  115. package/dist/test/MockApp.js.map +1 -0
  116. package/dist/test/MockFileSystem.d.ts +3 -3
  117. package/dist/test/MockFileSystem.js +6 -6
  118. package/dist/test/MockFileSystem.js.map +1 -1
  119. package/dist/test/index.d.ts +1 -1
  120. package/dist/test/index.js +1 -1
  121. package/dist/test/index.js.map +1 -1
  122. package/dist/test/test-helper.d.ts +10 -9
  123. package/dist/test/test-helper.js +15 -106
  124. package/dist/test/test-helper.js.map +1 -1
  125. package/dist/to-schema.d.ts +1 -1
  126. package/dist/to-source-code.d.ts +3 -2
  127. package/dist/to-source-code.js +20 -0
  128. package/dist/to-source-code.js.map +1 -1
  129. package/dist/tsconfig.tsbuildinfo +1 -1
  130. package/dist/types/platformos-liquid-docs.d.ts +128 -0
  131. package/dist/types/platformos-liquid-docs.js +3 -0
  132. package/dist/types/platformos-liquid-docs.js.map +1 -0
  133. package/dist/types/schemas/index.d.ts +0 -2
  134. package/dist/types/schemas/index.js.map +1 -1
  135. package/dist/types.d.ts +18 -67
  136. package/dist/types.js +3 -5
  137. package/dist/types.js.map +1 -1
  138. package/dist/utils/block.js.map +1 -1
  139. package/dist/utils/index.d.ts +0 -1
  140. package/dist/utils/index.js +0 -1
  141. package/dist/utils/index.js.map +1 -1
  142. package/dist/yaml/parse.d.ts +5 -0
  143. package/dist/yaml/parse.js +94 -0
  144. package/dist/yaml/parse.js.map +1 -0
  145. package/package.json +4 -3
  146. package/src/{AugmentedThemeDocset.spec.ts → AugmentedPlatformOSDocset.spec.ts} +47 -34
  147. package/src/AugmentedPlatformOSDocset.ts +89 -0
  148. package/src/JSONValidator.ts +1 -1
  149. package/src/checks/deprecated-filter/index.spec.ts +76 -248
  150. package/src/checks/deprecated-filter/index.ts +5 -53
  151. package/src/checks/deprecated-tag/index.spec.ts +85 -34
  152. package/src/checks/deprecated-tag/index.ts +27 -22
  153. package/src/checks/duplicate-function-arguments/index.ts +1 -1
  154. package/src/checks/duplicate-render-partial-arguments/index.ts +1 -1
  155. package/src/checks/graphql/index.ts +1 -1
  156. package/src/checks/img-width-and-height/index.ts +1 -1
  157. package/src/checks/index.ts +11 -80
  158. package/src/checks/invalid-hash-assign-target/index.spec.ts +14 -14
  159. package/src/checks/json-syntax-error/index.ts +1 -1
  160. package/src/checks/liquid-html-syntax-error/checks/InvalidBooleanExpression.spec.ts +0 -11
  161. package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.spec.ts +1 -2
  162. package/src/checks/liquid-html-syntax-error/index.spec.ts +1 -6
  163. package/src/checks/liquid-html-syntax-error/index.ts +2 -2
  164. package/src/checks/matching-translations/index.spec.ts +89 -346
  165. package/src/checks/matching-translations/index.ts +24 -35
  166. package/src/checks/metadata-params/index.ts +5 -7
  167. package/src/checks/missing-asset/index.ts +1 -1
  168. package/src/checks/{missing-template → missing-partial}/index.spec.ts +6 -6
  169. package/src/checks/{missing-template → missing-partial}/index.ts +6 -20
  170. package/src/checks/orphaned-partial/index.ts +3 -3
  171. package/src/checks/parser-blocking-script/index.spec.ts +0 -118
  172. package/src/checks/parser-blocking-script/index.ts +3 -33
  173. package/src/checks/parser-blocking-script/suggestions.ts +1 -28
  174. package/src/checks/translation-key-exists/index.ts +1 -1
  175. package/src/checks/unclosed-html-element/index.ts +5 -1
  176. package/src/checks/undefined-object/index.spec.ts +3 -109
  177. package/src/checks/undefined-object/index.ts +8 -33
  178. package/src/checks/unique-doc-param-names/index.ts +1 -1
  179. package/src/checks/unknown-filter/index.spec.ts +2 -2
  180. package/src/checks/unknown-filter/index.ts +3 -3
  181. package/src/checks/unknown-property/index.ts +1 -1
  182. package/src/checks/unrecognized-render-partial-arguments/index.spec.ts +5 -5
  183. package/src/checks/unrecognized-render-partial-arguments/index.ts +2 -5
  184. package/src/checks/unused-assign/index.spec.ts +0 -30
  185. package/src/checks/unused-assign/index.ts +1 -1
  186. package/src/checks/unused-doc-param/index.ts +1 -1
  187. package/src/checks/utils.ts +1 -1
  188. package/src/checks/valid-doc-param-types/index.ts +4 -4
  189. package/src/checks/valid-html-translation/index.spec.ts +42 -32
  190. package/src/checks/valid-html-translation/index.ts +7 -7
  191. package/src/checks/valid-json/index.ts +1 -1
  192. package/src/checks/valid-render-partial-argument-types/index.ts +2 -5
  193. package/src/checks/variable-name/index.ts +1 -1
  194. package/src/context-utils.spec.ts +49 -77
  195. package/src/context-utils.ts +39 -128
  196. package/src/disabled-checks/index.spec.ts +35 -0
  197. package/src/disabled-checks/index.ts +4 -2
  198. package/src/find-root.ts +12 -22
  199. package/src/fixes/autofix.spec.ts +2 -2
  200. package/src/fixes/autofix.ts +4 -4
  201. package/src/fixes/correctors/index.ts +4 -0
  202. package/src/ignore.spec.ts +0 -1
  203. package/src/index.ts +33 -21
  204. package/src/jsonc/parse.ts +1 -1
  205. package/src/liquid-doc/arguments.spec.ts +19 -45
  206. package/src/liquid-doc/arguments.ts +26 -39
  207. package/src/liquid-doc/liquidDoc.ts +1 -2
  208. package/src/liquid-doc/utils.ts +4 -3
  209. package/src/path.ts +1 -0
  210. package/src/test/{MockTheme.ts → MockApp.ts} +1 -1
  211. package/src/test/MockFileSystem.ts +6 -6
  212. package/src/test/index.ts +1 -1
  213. package/src/test/test-helper.ts +29 -127
  214. package/src/to-source-code.ts +20 -1
  215. package/src/types/{theme-liquid-docs.ts → platformos-liquid-docs.ts} +8 -13
  216. package/src/types/schemas/index.ts +0 -2
  217. package/src/types.ts +21 -92
  218. package/src/utils/index.ts +0 -1
  219. package/src/yaml/parse.ts +111 -0
  220. package/src/AugmentedThemeDocset.ts +0 -137
  221. package/src/checks/app-block-missing-schema/index.spec.ts +0 -121
  222. package/src/checks/app-block-missing-schema/index.ts +0 -46
  223. package/src/checks/app-block-valid-tags/index.spec.ts +0 -96
  224. package/src/checks/app-block-valid-tags/index.ts +0 -54
  225. package/src/checks/asset-preload/index.spec.ts +0 -78
  226. package/src/checks/asset-preload/index.ts +0 -65
  227. package/src/checks/asset-size-app-block-css/index.spec.ts +0 -88
  228. package/src/checks/asset-size-app-block-css/index.ts +0 -78
  229. package/src/checks/asset-size-app-block-javascript/index.spec.ts +0 -66
  230. package/src/checks/asset-size-app-block-javascript/index.ts +0 -78
  231. package/src/checks/asset-size-css/index.spec.ts +0 -166
  232. package/src/checks/asset-size-css/index.ts +0 -160
  233. package/src/checks/asset-size-javascript/index.spec.ts +0 -184
  234. package/src/checks/asset-size-javascript/index.ts +0 -144
  235. package/src/checks/block-id-usage/index.spec.ts +0 -76
  236. package/src/checks/block-id-usage/index.ts +0 -72
  237. package/src/checks/cdn-preconnect/index.spec.ts +0 -40
  238. package/src/checks/cdn-preconnect/index.ts +0 -43
  239. package/src/checks/content-for-header-modification/index.spec.ts +0 -65
  240. package/src/checks/content-for-header-modification/index.ts +0 -72
  241. package/src/checks/deprecate-bgsizes/index.spec.ts +0 -41
  242. package/src/checks/deprecate-bgsizes/index.ts +0 -49
  243. package/src/checks/deprecate-lazysizes/index.spec.ts +0 -26
  244. package/src/checks/deprecate-lazysizes/index.ts +0 -58
  245. package/src/checks/deprecated-filter/fixes.ts +0 -264
  246. package/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts +0 -1343
  247. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts +0 -613
  248. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts +0 -284
  249. package/src/checks/deprecated-fonts-on-settings-schema/index.spec.ts +0 -102
  250. package/src/checks/deprecated-fonts-on-settings-schema/index.ts +0 -66
  251. package/src/checks/duplicate-content-for-arguments/index.spec.ts +0 -98
  252. package/src/checks/duplicate-content-for-arguments/index.ts +0 -43
  253. package/src/checks/empty-block-content/index.spec.ts +0 -117
  254. package/src/checks/empty-block-content/index.ts +0 -60
  255. package/src/checks/hardcoded-routes/index.spec.ts +0 -58
  256. package/src/checks/hardcoded-routes/index.ts +0 -100
  257. package/src/checks/json-missing-block/index.spec.ts +0 -435
  258. package/src/checks/json-missing-block/index.ts +0 -56
  259. package/src/checks/json-missing-block/missing-block-utils.ts +0 -147
  260. package/src/checks/liquid-free-settings/index.spec.ts +0 -180
  261. package/src/checks/liquid-free-settings/index.ts +0 -79
  262. package/src/checks/missing-content-for-arguments/index.spec.ts +0 -144
  263. package/src/checks/missing-content-for-arguments/index.ts +0 -46
  264. package/src/checks/pagination-size/index.spec.ts +0 -158
  265. package/src/checks/pagination-size/index.ts +0 -104
  266. package/src/checks/remote-asset/index.spec.ts +0 -280
  267. package/src/checks/remote-asset/index.ts +0 -238
  268. package/src/checks/reserved-doc-param-names/index.spec.ts +0 -62
  269. package/src/checks/reserved-doc-param-names/index.ts +0 -57
  270. package/src/checks/schema-presets-block-order/index.spec.ts +0 -344
  271. package/src/checks/schema-presets-block-order/index.ts +0 -154
  272. package/src/checks/schema-presets-static-blocks/index.spec.ts +0 -145
  273. package/src/checks/schema-presets-static-blocks/index.ts +0 -126
  274. package/src/checks/static-stylesheet-and-javascript-tags/index.spec.ts +0 -257
  275. package/src/checks/static-stylesheet-and-javascript-tags/index.ts +0 -48
  276. package/src/checks/unique-settings-id/index.spec.ts +0 -24
  277. package/src/checks/unique-settings-id/index.ts +0 -84
  278. package/src/checks/unique-settings-id/test-data.ts +0 -1191
  279. package/src/checks/unique-static-block-id/index.spec.ts +0 -55
  280. package/src/checks/unique-static-block-id/index.ts +0 -60
  281. package/src/checks/unrecognized-content-for-arguments/index.spec.ts +0 -145
  282. package/src/checks/unrecognized-content-for-arguments/index.ts +0 -55
  283. package/src/checks/valid-block-target/index.spec.ts +0 -1396
  284. package/src/checks/valid-block-target/index.ts +0 -142
  285. package/src/checks/valid-content-for-argument-types/index.spec.ts +0 -382
  286. package/src/checks/valid-content-for-argument-types/index.ts +0 -42
  287. package/src/checks/valid-content-for-arguments/index.spec.ts +0 -107
  288. package/src/checks/valid-content-for-arguments/index.ts +0 -98
  289. package/src/checks/valid-local-blocks/index.spec.ts +0 -286
  290. package/src/checks/valid-local-blocks/index.ts +0 -100
  291. package/src/checks/valid-local-blocks/valid-block-utils.ts +0 -97
  292. package/src/checks/valid-schema/index.spec.ts +0 -174
  293. package/src/checks/valid-schema/index.ts +0 -41
  294. package/src/checks/valid-schema-name/index.spec.ts +0 -112
  295. package/src/checks/valid-schema-name/index.ts +0 -75
  296. package/src/checks/valid-settings-key/index.spec.ts +0 -321
  297. package/src/checks/valid-settings-key/index.ts +0 -144
  298. package/src/checks/valid-static-block-type/index.spec.ts +0 -38
  299. package/src/checks/valid-static-block-type/index.ts +0 -58
  300. package/src/checks/valid-visible-if/index.spec.ts +0 -619
  301. package/src/checks/valid-visible-if/index.ts +0 -184
  302. package/src/checks/valid-visible-if/visible-if-utils.ts +0 -158
  303. package/src/tags/content-for.ts +0 -25
  304. package/src/to-schema.ts +0 -231
  305. package/src/types/schemas/section.ts +0 -86
  306. package/src/types/schemas/theme-block.ts +0 -34
  307. package/src/types/theme-schemas.ts +0 -80
  308. package/src/utils/block.ts +0 -300
  309. package/src/utils/markup.ts +0 -10
@@ -1,142 +0,0 @@
1
- import { nodeAtPath } from '../../json';
2
- import { getSchema } from '../../to-schema';
3
- import {
4
- LiquidCheckDefinition,
5
- LiteralNode,
6
- Section,
7
- Severity,
8
- SourceCodeType,
9
- ThemeBlock,
10
- } from '../../types';
11
- import {
12
- getBlocks,
13
- reportWarning,
14
- validateBlockFileExistence,
15
- validateNestedBlocks,
16
- isInvalidPresetBlock,
17
- isInvalidDefaultBlock,
18
- } from '../../utils';
19
-
20
- export const ValidBlockTarget: LiquidCheckDefinition = {
21
- meta: {
22
- code: 'ValidBlockTarget',
23
- name: 'Validate block targeting in presets',
24
- docs: {
25
- description:
26
- 'Ensures block types only reference valid block types and respect parent-child relationships',
27
- recommended: true,
28
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/valid-block-target',
29
- },
30
- type: SourceCodeType.LiquidHtml,
31
- severity: Severity.ERROR,
32
- schema: {},
33
- targets: [],
34
- },
35
-
36
- create(context) {
37
- return {
38
- async LiquidRawTag(node) {
39
- if (node.name !== 'schema' || node.body.kind !== 'json') return;
40
-
41
- const offset = node.blockStartPosition.end;
42
- const schema = await getSchema(context);
43
- const { validSchema, ast } = schema ?? {};
44
- if (!validSchema || validSchema instanceof Error) return;
45
- if (!ast || ast instanceof Error) return;
46
- if (!schema) return;
47
- const { staticBlockDefs } = schema;
48
-
49
- const {
50
- rootLevelThemeBlocks,
51
- rootLevelLocalBlocks,
52
- presetLevelBlocks,
53
- defaultLevelBlocks,
54
- } = getBlocks(validSchema);
55
-
56
- if (rootLevelLocalBlocks.length > 0) return;
57
-
58
- let errorsInRootLevelBlocks = false;
59
- await Promise.all(
60
- rootLevelThemeBlocks.map(async ({ node, path }) => {
61
- const typeNode = nodeAtPath(ast, path)! as LiteralNode;
62
- const exists = await validateBlockFileExistence(node.type, context);
63
- if (!exists) {
64
- errorsInRootLevelBlocks = true;
65
- reportWarning(blockDoesNotExistError(node.type), offset, typeNode, context);
66
- }
67
- }),
68
- );
69
-
70
- if (errorsInRootLevelBlocks) return;
71
-
72
- for (const [depthStr, blocks] of Object.entries(presetLevelBlocks)) {
73
- const depth = parseInt(depthStr, 10);
74
-
75
- if (depth === 0) {
76
- await Promise.all(
77
- blocks.map(async ({ node, path }) => {
78
- const typeNode = nodeAtPath(ast, path)! as LiteralNode;
79
- const blockId = 'id' in node ? node.id! : path.at(-2)!;
80
- const isStaticBlock = !!node.static;
81
-
82
- if (isInvalidPresetBlock(blockId, node, rootLevelThemeBlocks, staticBlockDefs)) {
83
- const errorMessage = isStaticBlock
84
- ? `Could not find a static block of type "${node.type}" with id "${blockId}" in this file.`
85
- : reportMissingThemeBlockDefinitionError(node);
86
- reportWarning(errorMessage, offset, typeNode, context);
87
- }
88
-
89
- const exists = await validateBlockFileExistence(node.type, context);
90
- if (exists) {
91
- if ('blocks' in node && node.blocks) {
92
- await validateNestedBlocks(
93
- context,
94
- node,
95
- node.blocks,
96
- path.slice(0, -1),
97
- offset,
98
- ast,
99
- );
100
- }
101
- } else {
102
- reportWarning(blockDoesNotExistError(node.type), offset, typeNode, context);
103
- }
104
- }),
105
- );
106
- }
107
- }
108
-
109
- await Promise.all(
110
- defaultLevelBlocks.map(async ({ node, path }) => {
111
- const typeNode = nodeAtPath(ast, path)! as LiteralNode;
112
-
113
- if (isInvalidDefaultBlock(node, rootLevelThemeBlocks)) {
114
- reportWarning(
115
- reportMissingThemeBlockDefinitionError(node),
116
- offset,
117
- typeNode,
118
- context,
119
- );
120
- }
121
-
122
- const exists = await validateBlockFileExistence(node.type, context);
123
- if (!exists) {
124
- reportWarning(blockDoesNotExistError(node.type), offset, typeNode, context);
125
- }
126
- }),
127
- );
128
- },
129
- };
130
- },
131
- };
132
-
133
- function reportMissingThemeBlockDefinitionError(node: Section.Block | ThemeBlock.Block) {
134
- const isPrivateBlockType = node.type.startsWith('_');
135
- return isPrivateBlockType
136
- ? `Theme block type "${node.type}" is a private block so it must be explicitly allowed in "blocks" at the root of this schema.`
137
- : `Theme block type "${node.type}" must be allowed in "blocks" at the root of this schema.`;
138
- }
139
-
140
- function blockDoesNotExistError(name: string) {
141
- return `Theme block 'blocks/${name}.liquid' does not exist.`;
142
- }
@@ -1,382 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { runLiquidCheck, applySuggestions } from '../../test';
3
- import { ValidContentForArgumentTypes } from '.';
4
- import { BasicParamTypes } from '../../liquid-doc/utils';
5
-
6
- describe('Module: ValidContentForParamTypes', () => {
7
- describe('type validation', () => {
8
- const typeTests = [
9
- {
10
- type: 'string',
11
- validValues: ["'hello'", "''", 'product'],
12
- invalidValues: [
13
- { value: '123', actualType: BasicParamTypes.Number },
14
- { value: 'true', actualType: BasicParamTypes.Boolean },
15
- ],
16
- },
17
- {
18
- type: 'number',
19
- validValues: ['0', '123', '-1', 'product'],
20
- invalidValues: [
21
- { value: "'hello'", actualType: BasicParamTypes.String },
22
- { value: 'true', actualType: BasicParamTypes.Boolean },
23
- ],
24
- },
25
- {
26
- type: 'boolean',
27
- validValues: ['true', 'false', 'nil', 'empty', 'product', '123', "'hello'"],
28
- invalidValues: [],
29
- },
30
- {
31
- type: 'object',
32
- validValues: ['product', '(1..3)'],
33
- invalidValues: [
34
- { value: "'hello'", actualType: BasicParamTypes.String },
35
- { value: '123', actualType: BasicParamTypes.Number },
36
- { value: 'true', actualType: BasicParamTypes.Boolean },
37
- { value: 'empty', actualType: BasicParamTypes.Boolean },
38
- ],
39
- },
40
- ];
41
-
42
- for (const test of typeTests) {
43
- describe(`${test.type} validation`, () => {
44
- const makeBlock = (type: string) => `
45
- {% doc %}
46
- @param {${type}} param - Description
47
- {% enddoc %}
48
- <div>{{ param }}</div>
49
- `;
50
-
51
- test.validValues.forEach((value) => {
52
- it(`should accept ${value} for ${test.type}`, async () => {
53
- const sourceCode = `{% content_for 'block', type: 'card', param: ${value} %}`;
54
- const offenses = await runLiquidCheck(
55
- ValidContentForArgumentTypes,
56
- sourceCode,
57
- undefined,
58
- {},
59
- {
60
- 'blocks/card.liquid': makeBlock(test.type),
61
- },
62
- );
63
- expect(offenses).toHaveLength(0);
64
- });
65
- });
66
-
67
- test.invalidValues.forEach(({ value, actualType: expectedType }) => {
68
- it(`should reject ${value} for ${test.type}`, async () => {
69
- const sourceCode = `{% content_for 'block', type: 'card', param: ${value} %}`;
70
- const offenses = await runLiquidCheck(
71
- ValidContentForArgumentTypes,
72
- sourceCode,
73
- undefined,
74
- {},
75
- {
76
- 'blocks/card.liquid': makeBlock(test.type),
77
- },
78
- );
79
- expect(offenses).toHaveLength(1);
80
- expect(offenses[0].message).toBe(
81
- `Type mismatch for argument 'param': expected ${test.type}, got ${expectedType}`,
82
- );
83
- });
84
- });
85
- });
86
- }
87
- });
88
-
89
- describe('edge cases', () => {
90
- it('should handle mixed case type annotations', async () => {
91
- const sourceCode = `{% content_for 'block', type: 'card', text: "hello", count: 5, flag: true, data: product %}`;
92
- const offenses = await runLiquidCheck(
93
- ValidContentForArgumentTypes,
94
- sourceCode,
95
- undefined,
96
- {},
97
- {
98
- 'blocks/card.liquid': `
99
- {% doc %}
100
- @param {String} text - The text
101
- @param {NUMBER} count - The count
102
- @param {BOOLEAN} flag - The flag
103
- @param {Object} data - The data
104
- {% enddoc %}
105
- <div>{{ text }}{{ count }}{{ flag }}{{ data }}</div>
106
- `,
107
- },
108
- );
109
- expect(offenses).toHaveLength(0);
110
- });
111
-
112
- it('should ignore variable lookups', async () => {
113
- const sourceCode = `{% content_for 'block', type: 'card', title: product_title %}`;
114
- const offenses = await runLiquidCheck(
115
- ValidContentForArgumentTypes,
116
- sourceCode,
117
- undefined,
118
- {},
119
- {
120
- 'blocks/card.liquid': `
121
- {% doc %}
122
- @param {String} title - The title
123
- {% enddoc %}
124
- <div>{{ title }}</div>
125
- `,
126
- },
127
- );
128
- expect(offenses).toHaveLength(0);
129
- });
130
-
131
- it('should not report when partial has no doc comment', async () => {
132
- const sourceCode = `{% content_for 'block', type: 'card', title: 123 %}`;
133
- const offenses = await runLiquidCheck(
134
- ValidContentForArgumentTypes,
135
- sourceCode,
136
- undefined,
137
- {},
138
- {
139
- 'blocks/card.liquid': `<h1>This partial has no doc comment</h1>`,
140
- },
141
- );
142
- expect(offenses).toHaveLength(0);
143
- });
144
-
145
- it('should not enforce unsupported types', async () => {
146
- const sourceCode = `{% content_for 'block', type: 'card', title: 123 %}`;
147
- const offenses = await runLiquidCheck(
148
- ValidContentForArgumentTypes,
149
- sourceCode,
150
- undefined,
151
- {},
152
- {
153
- 'blocks/card.liquid': `
154
- {% doc %}
155
- @param {Unsupported} title - The title
156
- {% enddoc %}
157
- <div>{{ title }}</div>
158
- `,
159
- },
160
- );
161
- expect(offenses).toHaveLength(0);
162
- });
163
-
164
- it('should not report for unrecognized arguments', async () => {
165
- const sourceCode = `{% content_for 'block', type: 'card', title: "hello", unrecognized: 123 %}`;
166
- const offenses = await runLiquidCheck(
167
- ValidContentForArgumentTypes,
168
- sourceCode,
169
- undefined,
170
- {},
171
- {
172
- 'blocks/card.liquid': `
173
- {% doc %}
174
- @param {String} title - The title
175
- {% enddoc %}
176
- <div>{{ title }}</div>
177
- `,
178
- },
179
- );
180
- expect(offenses).toHaveLength(0);
181
- });
182
- });
183
-
184
- describe('suggestions', () => {
185
- const makeBlock = (type: string) => `
186
- {% doc %}
187
- @param {${type}} param - Description
188
- {% enddoc %}
189
- <div>{{ param }}</div>
190
- `;
191
-
192
- it('should suggest replacing with default value for type or removing value', async () => {
193
- const sourceCode = `{% content_for 'block', type: 'card', param: 123 %}`;
194
- const offenses = await runLiquidCheck(
195
- ValidContentForArgumentTypes,
196
- sourceCode,
197
- undefined,
198
- {},
199
- {
200
- 'blocks/card.liquid': makeBlock('string'),
201
- },
202
- );
203
-
204
- expect(offenses).toHaveLength(1);
205
- expect(offenses[0].suggest).toHaveLength(2);
206
- expect(offenses[0].suggest?.[0]?.message).toBe("Replace with default value '''' for string");
207
-
208
- const result = applySuggestions(sourceCode, offenses[0]);
209
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', param: '' %}`);
210
-
211
- const suggestions = applySuggestions(sourceCode, offenses[0]);
212
- expect(suggestions?.[1]).toEqual(`{% content_for 'block', type: 'card', param: %}`);
213
- });
214
-
215
- it('should allow users to fix a single argument when multiple are provided`', async () => {
216
- const sourceCode = `{% content_for 'block', type: 'card', title: 123, count: 5 %}`;
217
- const offenses = await runLiquidCheck(
218
- ValidContentForArgumentTypes,
219
- sourceCode,
220
- undefined,
221
- {},
222
- {
223
- 'blocks/card.liquid': `
224
- {% doc %}
225
- @param {string} title - The title
226
- @param {number} count - The count
227
- {% enddoc %}
228
- <div>{{ title }} {{ count }}</div>
229
- `,
230
- },
231
- );
232
-
233
- expect(offenses).toHaveLength(1);
234
- expect(offenses[0].message).toBe(
235
- "Type mismatch for argument 'title': expected string, got number",
236
- );
237
-
238
- const result = applySuggestions(sourceCode, offenses[0]);
239
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', title: '', count: 5 %}`);
240
- });
241
-
242
- it('should handle arguments with trailing commas', async () => {
243
- const sourceCode = `{% content_for 'block', type: 'card', param: 123, %}`;
244
- const offenses = await runLiquidCheck(
245
- ValidContentForArgumentTypes,
246
- sourceCode,
247
- undefined,
248
- {},
249
- {
250
- 'blocks/card.liquid': makeBlock('string'),
251
- },
252
- );
253
-
254
- expect(offenses).toHaveLength(1);
255
-
256
- const result = applySuggestions(sourceCode, offenses[0]);
257
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', param: '', %}`);
258
- });
259
-
260
- it('should handle arguments with complex spacing', async () => {
261
- const sourceCode = `{% content_for 'block', type: 'card',
262
- title: 123,
263
- count: 5
264
- %}`;
265
- const offenses = await runLiquidCheck(
266
- ValidContentForArgumentTypes,
267
- sourceCode,
268
- undefined,
269
- {},
270
- {
271
- 'blocks/card.liquid': `
272
- {% doc %}
273
- @param {string} title - The title
274
- @param {number} count - The count
275
- {% enddoc %}
276
- `,
277
- },
278
- );
279
-
280
- expect(offenses).toHaveLength(1);
281
-
282
- const result = applySuggestions(sourceCode, offenses[0]);
283
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card',
284
- title: '',
285
- count: 5
286
- %}`);
287
- });
288
-
289
- it('should handle argument with no space after colon', async () => {
290
- const sourceCode = `{% content_for 'block', type: 'card', param:123 %}`;
291
- const offenses = await runLiquidCheck(
292
- ValidContentForArgumentTypes,
293
- sourceCode,
294
- undefined,
295
- {},
296
- {
297
- 'blocks/card.liquid': makeBlock('string'),
298
- },
299
- );
300
-
301
- expect(offenses).toHaveLength(1);
302
-
303
- const result = applySuggestions(sourceCode, offenses[0]);
304
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', param:'' %}`);
305
- });
306
-
307
- it('should handle argument with multiple spaces after colon', async () => {
308
- const sourceCode = `{% content_for 'block', type: 'card', param: 123 %}`;
309
- const offenses = await runLiquidCheck(
310
- ValidContentForArgumentTypes,
311
- sourceCode,
312
- undefined,
313
- {},
314
- {
315
- 'blocks/card.liquid': makeBlock('string'),
316
- },
317
- );
318
-
319
- expect(offenses).toHaveLength(1);
320
-
321
- const result = applySuggestions(sourceCode, offenses[0]);
322
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', param: '' %}`);
323
- });
324
-
325
- it('should handle argument with newlines', async () => {
326
- const sourceCode = `{% content_for 'block', type: 'card', param:
327
- 123
328
- %}`;
329
- const offenses = await runLiquidCheck(
330
- ValidContentForArgumentTypes,
331
- sourceCode,
332
- undefined,
333
- {},
334
- {
335
- 'blocks/card.liquid': makeBlock('string'),
336
- },
337
- );
338
-
339
- expect(offenses).toHaveLength(1);
340
-
341
- const result = applySuggestions(sourceCode, offenses[0]);
342
- expect(result?.[0]).toEqual(`{% content_for 'block', type: 'card', param:
343
- ''
344
- %}`);
345
- });
346
-
347
- it('should suggest removal and replacement if expected type has a default value', async () => {
348
- const sourceCode = `{% content_for 'block', type: 'card', param: 123 %}`;
349
- const offenses = await runLiquidCheck(
350
- ValidContentForArgumentTypes,
351
- sourceCode,
352
- undefined,
353
- {},
354
- {
355
- 'blocks/card.liquid': makeBlock('string'),
356
- },
357
- );
358
-
359
- expect(offenses).toHaveLength(1);
360
- expect(offenses[0].suggest).toHaveLength(2);
361
- expect(offenses[0].suggest?.[0]?.message).toBe("Replace with default value '''' for string");
362
- expect(offenses[0].suggest?.[1]?.message).toBe('Remove value');
363
- });
364
-
365
- it("should only suggest removal if expected type default value is ''", async () => {
366
- const sourceCode = `{% content_for 'block', type: 'card', param: 123 %}`;
367
- const offenses = await runLiquidCheck(
368
- ValidContentForArgumentTypes,
369
- sourceCode,
370
- undefined,
371
- {},
372
- {
373
- 'blocks/card.liquid': makeBlock('object'),
374
- },
375
- );
376
-
377
- expect(offenses).toHaveLength(1);
378
- expect(offenses[0].suggest).toHaveLength(1);
379
- expect(offenses[0].suggest?.[0]?.message).toBe('Remove value');
380
- });
381
- });
382
- });
@@ -1,42 +0,0 @@
1
- import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';
2
- import { ContentForMarkup } from '@platformos/liquid-html-parser';
3
- import {
4
- findTypeMismatchParams,
5
- getBlockName,
6
- getLiquidDocParams,
7
- reportTypeMismatches,
8
- } from '../../liquid-doc/arguments';
9
-
10
- export const ValidContentForArgumentTypes: LiquidCheckDefinition = {
11
- meta: {
12
- code: 'ValidContentForArgumentTypes',
13
- name: 'Valid ContentFor Argument Types',
14
- docs: {
15
- description:
16
- 'This check ensures that arguments passed to static blocks match the expected types defined in the liquidDoc header if present.',
17
- recommended: true,
18
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/valid-content-for-argument-types',
19
- },
20
- type: SourceCodeType.LiquidHtml,
21
- severity: Severity.WARNING,
22
- schema: {},
23
- targets: [],
24
- },
25
-
26
- create(context) {
27
- return {
28
- async ContentForMarkup(node: ContentForMarkup) {
29
- const blockName = getBlockName(node);
30
-
31
- if (!blockName) return;
32
-
33
- const liquidDocParameters = await getLiquidDocParams(context, `blocks/${blockName}.liquid`);
34
-
35
- if (!liquidDocParameters) return;
36
-
37
- const typeMismatchParams = findTypeMismatchParams(liquidDocParameters, node.args);
38
- reportTypeMismatches(context, typeMismatchParams, liquidDocParameters);
39
- },
40
- };
41
- },
42
- };
@@ -1,107 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { ValidContentForArguments } from '.';
3
- import { runLiquidCheck } from '../../test';
4
-
5
- describe('Module: ValidContentForArguments', () => {
6
- describe('{% content_for "unknown" %}', () => {
7
- it('should not report offenses for strategies we do not know or support yet', async () => {
8
- const offenses = await runLiquidCheck(
9
- ValidContentForArguments,
10
- '{% content_for "snippet", closest.product: product %}',
11
- );
12
- expect(offenses).toHaveLength(0);
13
- });
14
- });
15
-
16
- describe('{% content_for "blocks" %}', () => {
17
- it('should accept `closest.*` kwargs', async () => {
18
- const offenses = await runLiquidCheck(
19
- ValidContentForArguments,
20
- '{% content_for "blocks", closest.product: product %}',
21
- );
22
- expect(offenses).toHaveLength(0);
23
- });
24
-
25
- it('should not accept `context.*` kwargs', async () => {
26
- const offenses = await runLiquidCheck(
27
- ValidContentForArguments,
28
- '{% content_for "blocks", context.product: product %}',
29
- );
30
- expect(offenses).toHaveLength(1);
31
- expect(offenses[0]!.message).to.equal(
32
- `{% content_for "blocks" %} only accepts 'closest.*' arguments`,
33
- );
34
- });
35
-
36
- it('should report offenses for non-`closest.*` kwargs', async () => {
37
- const offenses = await runLiquidCheck(
38
- ValidContentForArguments,
39
- '{% content_for "blocks", product: product %}',
40
- );
41
- expect(offenses).toHaveLength(1);
42
- expect(offenses[0]!.message).to.equal(
43
- `{% content_for "blocks" %} only accepts 'closest.*' arguments`,
44
- );
45
- });
46
- });
47
-
48
- describe('{% content_for "block", type: "", id: "" %}', () => {
49
- it('should accept valid arguments', async () => {
50
- const offenses = await runLiquidCheck(
51
- ValidContentForArguments,
52
- '{% content_for "block", type: "text", id: "static-block" %}',
53
- );
54
- expect(offenses).toHaveLength(0);
55
- });
56
-
57
- it(`should report an offense if 'type' is not a string`, async () => {
58
- const offenses = await runLiquidCheck(
59
- ValidContentForArguments,
60
- '{% content_for "block", type: 10, id: "static-block" %}',
61
- );
62
- expect(offenses).toHaveLength(1);
63
- expect(offenses[0].message).to.equal(`The 'type' argument should be a string`);
64
- });
65
-
66
- it(`should report an offense if 'id' is not a string`, async () => {
67
- const offenses = await runLiquidCheck(
68
- ValidContentForArguments,
69
- '{% content_for "block", type: "foo", id: (0..10) %}',
70
- );
71
- expect(offenses).toHaveLength(1);
72
- expect(offenses[0].message).to.equal(`The 'id' argument should be a string`);
73
- });
74
-
75
- it(`should accept static arguments`, async () => {
76
- const offenses = await runLiquidCheck(
77
- ValidContentForArguments,
78
- '{% content_for "block", type: "foo", id: "id", product: product %}',
79
- );
80
- expect(offenses).toHaveLength(0);
81
- });
82
-
83
- it(`should report an offense for reserved arguments`, async () => {
84
- const offenses = await runLiquidCheck(
85
- ValidContentForArguments,
86
- '{% content_for "block", type: "foo", id: "id", settings: settings %}',
87
- );
88
- expect(offenses).toHaveLength(1);
89
- expect(offenses[0].message).to.equal(
90
- `{% content_for "block" %} doesn't support 'settings' because it's a reserved argument.`,
91
- );
92
- });
93
-
94
- it(`should report offenses for multiple reserved arguments`, async () => {
95
- const offenses = await runLiquidCheck(
96
- ValidContentForArguments,
97
- '{% content_for "block", type: "foo", id: "id", settings: settings, section: section %}',
98
- );
99
- const messages = offenses.map((o) => o.message);
100
-
101
- expect(messages).to.deep.equal([
102
- `{% content_for "block" %} doesn't support 'settings' because it's a reserved argument.`,
103
- `{% content_for "block" %} doesn't support 'section' because it's a reserved argument.`,
104
- ]);
105
- });
106
- });
107
- });