@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,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
- });