@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,435 +0,0 @@
1
- import { expect, describe, it } from 'vitest';
2
- import { JSONMissingBlock } from './index';
3
- import { check, MockTheme } from '../../test';
4
-
5
- describe('Module: JsonMissingBlock', () => {
6
- describe('File existence validation', () => {
7
- it('should report an offense when a block does not exist', async () => {
8
- const theme: MockTheme = {
9
- 'templates/product.failing.json': `{
10
- "sections": {
11
- "custom-section": {
12
- "type": "custom-section",
13
- "blocks": {
14
- "text_tqQTNE": {
15
- "type": "missing_block"
16
- }
17
- },
18
- "block_order": ["text_tqQTNE"]
19
- }
20
- },
21
- "order": ["custom-section"]
22
- }`,
23
- 'sections/custom-section.liquid': `
24
- {% schema %}
25
- {
26
- "name": "Custom Section",
27
- "blocks": [
28
- {
29
- "type": "missing_block"
30
- }
31
- ]
32
- }
33
- {% endschema %}
34
- `,
35
- };
36
-
37
- const offenses = await check(theme, [JSONMissingBlock]);
38
- expect(offenses).to.have.length(1);
39
- expect(offenses[0].message).to.equal(
40
- "Theme block 'blocks/missing_block.liquid' does not exist.",
41
- );
42
-
43
- const content = theme['templates/product.failing.json'];
44
- const erroredContent = content.slice(offenses[0].start.index, offenses[0].end.index);
45
- expect(erroredContent).to.equal('"missing_block"');
46
- });
47
-
48
- it('should not report an offense when block exists', async () => {
49
- const theme: MockTheme = {
50
- 'templates/product.valid.json': `{
51
- "sections": {
52
- "custom-section": {
53
- "type": "custom-section",
54
- "blocks": {
55
- "text_block": {
56
- "type": "text"
57
- }
58
- },
59
- "block_order": ["text_block"]
60
- }
61
- },
62
- "order": ["custom-section"]
63
- }`,
64
- 'sections/custom-section.liquid': `
65
- {% schema %}
66
- {
67
- "name": "Custom Section",
68
- "blocks": [
69
- {
70
- "type": "text"
71
- }
72
- ]
73
- }
74
- {% endschema %}
75
- `,
76
- 'blocks/text.liquid': '',
77
- };
78
-
79
- const offenses = await check(theme, [JSONMissingBlock]);
80
- expect(offenses).to.be.empty;
81
- });
82
-
83
- it('should report an offense when a nested block does not exist', async () => {
84
- const theme: MockTheme = {
85
- 'templates/product.nested.json': `{
86
- "sections": {
87
- "custom-section": {
88
- "type": "custom-section",
89
- "blocks": {
90
- "parent_block": {
91
- "type": "text",
92
- "blocks": {
93
- "child_block": {
94
- "type": "missing_nested"
95
- }
96
- }
97
- }
98
- },
99
- "block_order": ["parent_block"]
100
- }
101
- },
102
- "order": ["custom-section"]
103
- }`,
104
- 'sections/custom-section.liquid': `
105
- {% schema %}
106
- {
107
- "name": "Custom Section",
108
- "blocks": [
109
- {
110
- "type": "text"
111
- }
112
- ]
113
- }
114
- {% endschema %}
115
- `,
116
- 'blocks/text.liquid': `
117
- {% schema %}
118
- {
119
- "name": "Text Block",
120
- "blocks": [
121
- {
122
- "type": "missing_nested"
123
- }
124
- ]
125
- }
126
- {% endschema %}
127
- `,
128
- };
129
-
130
- const offenses = await check(theme, [JSONMissingBlock]);
131
- expect(offenses).to.have.length(1);
132
- expect(offenses[0].message).to.equal(
133
- "Theme block 'blocks/missing_nested.liquid' does not exist.",
134
- );
135
-
136
- const content = theme['templates/product.nested.json'];
137
- const erroredContent = content.slice(offenses[0].start.index, offenses[0].end.index);
138
- expect(erroredContent).to.equal('"missing_nested"');
139
- });
140
- });
141
-
142
- describe('Allowed block type validation', () => {
143
- it('should report an offense when block exists but is not in the section liquid schema', async () => {
144
- const theme: MockTheme = {
145
- 'templates/product.valid.json': `{
146
- "sections": {
147
- "custom-section": {
148
- "type": "custom-section",
149
- "blocks": {
150
- "text_block": {
151
- "type": "text"
152
- }
153
- },
154
- "block_order": ["text_block"]
155
- }
156
- },
157
- "order": ["custom-section"]
158
- }`,
159
- 'sections/custom-section.liquid': `
160
- {% schema %}
161
- {
162
- "name": "Custom Section",
163
- "blocks": [
164
- {
165
- "type": "image"
166
- }
167
- ]
168
- }
169
- {% endschema %}
170
- `,
171
- 'blocks/text.liquid': '',
172
- 'blocks/image.liquid': '',
173
- };
174
-
175
- const offenses = await check(theme, [JSONMissingBlock]);
176
- expect(offenses).to.have.length(1);
177
- expect(offenses[0].message).to.equal(
178
- "Block type 'text' is not allowed in 'sections/custom-section.liquid'.",
179
- );
180
-
181
- const content = theme['templates/product.valid.json'];
182
- const erroredContent = content.slice(offenses[0].start.index, offenses[0].end.index);
183
- expect(erroredContent).to.equal('"text"');
184
- });
185
-
186
- it('should report an offense when a nested block exists but is not in the block liquid schema', async () => {
187
- const theme: MockTheme = {
188
- 'templates/product.nested.json': `{
189
- "sections": {
190
- "custom-section": {
191
- "type": "custom-section",
192
- "blocks": {
193
- "parent_block": {
194
- "type": "text",
195
- "blocks": {
196
- "child_block": {
197
- "type": "missing_nested"
198
- }
199
- }
200
- }
201
- },
202
- "block_order": ["parent_block"]
203
- }
204
- },
205
- "order": ["custom-section"]
206
- }`,
207
- 'sections/custom-section.liquid': `
208
- {% schema %}
209
- {
210
- "name": "Custom Section",
211
- "blocks": [
212
- {
213
- "type": "text"
214
- }
215
- ]
216
- }
217
- {% endschema %}
218
- `,
219
- 'blocks/text.liquid': `
220
- {% schema %}
221
- {
222
- "name": "Text Block",
223
- "blocks": [
224
- {
225
- "type": "image"
226
- }
227
- ]
228
- }
229
- {% endschema %}
230
- `,
231
- 'blocks/image.liquid': '',
232
- 'blocks/missing_nested.liquid': '',
233
- };
234
-
235
- const offenses = await check(theme, [JSONMissingBlock]);
236
- expect(offenses).to.have.length(1);
237
- expect(offenses[0].message).to.equal(
238
- "Block type 'missing_nested' is not allowed in 'blocks/text.liquid'.",
239
- );
240
-
241
- const content = theme['templates/product.nested.json'];
242
- const erroredContent = content.slice(offenses[0].start.index, offenses[0].end.index);
243
- expect(erroredContent).to.equal('"missing_nested"');
244
- });
245
-
246
- it('should report an offense when a nested private block exists but is not in the block liquid schema', async () => {
247
- const theme: MockTheme = {
248
- 'templates/product.nested.json': `{
249
- "sections": {
250
- "custom-section": {
251
- "type": "custom-section",
252
- "blocks": {
253
- "parent_block": {
254
- "type": "text",
255
- "blocks": {
256
- "child_block": {
257
- "type": "_private_block"
258
- }
259
- }
260
- }
261
- },
262
- "block_order": ["parent_block"]
263
- }
264
- },
265
- "order": ["custom-section"]
266
- }`,
267
- 'sections/custom-section.liquid': `
268
- {% schema %}
269
- {
270
- "name": "Custom Section",
271
- "blocks": [
272
- {
273
- "type": "text"
274
- }
275
- ]
276
- }
277
- {% endschema %}
278
- `,
279
- 'blocks/text.liquid': `
280
- {% schema %}
281
- {
282
- "name": "Text Block",
283
- "blocks": [
284
- {
285
- "type": "@theme"
286
- }
287
- ]
288
- }
289
- {% endschema %}
290
- `,
291
- 'blocks/image.liquid': '',
292
- 'blocks/_private_block.liquid': '',
293
- };
294
-
295
- const offenses = await check(theme, [JSONMissingBlock]);
296
- expect(offenses).to.have.length(1);
297
- expect(offenses[0].message).to.equal(
298
- "Block type '_private_block' is not allowed in 'blocks/text.liquid'.",
299
- );
300
-
301
- const content = theme['templates/product.nested.json'];
302
- const erroredContent = content.slice(offenses[0].start.index, offenses[0].end.index);
303
- expect(erroredContent).to.equal('"_private_block"');
304
- });
305
-
306
- it('should not report an offense when a static block exists and is not in the block liquid schema', async () => {
307
- const theme: MockTheme = {
308
- 'templates/product.static.json': `{
309
- "sections": {
310
- "custom-section": {
311
- "type": "custom-section",
312
- "blocks": {
313
- "child_block": {
314
- "type": "text"
315
- },
316
- "static_block": {
317
- "type": "static_block",
318
- "static": true
319
- }
320
- },
321
- "block_order": ["child_block"]
322
- }
323
- },
324
- "order": ["custom-section"]
325
- }`,
326
- 'sections/custom-section.liquid': `
327
- {% schema %}
328
- {
329
- "name": "Custom Section",
330
- "blocks": [
331
- {
332
- "type": "text"
333
- }
334
- ]
335
- }
336
- {% endschema %}
337
- `,
338
- 'blocks/text.liquid': `
339
- {% schema %}
340
- {
341
- "name": "Text Block",
342
- "blocks": [
343
- {
344
- "type": "@theme"
345
- }
346
- ]
347
- }
348
- {% endschema %}
349
- `,
350
- 'blocks/static_block.liquid': `
351
- {% schema %}
352
- {
353
- "name": "Static Block",
354
- }
355
- {% endschema %}
356
- `,
357
- };
358
-
359
- const offenses = await check(theme, [JSONMissingBlock]);
360
- expect(offenses).to.have.length(0);
361
- });
362
- });
363
-
364
- describe('Edge case validation', () => {
365
- it('should ignore non-template JSON files', async () => {
366
- const theme: MockTheme = {
367
- 'config/index.json': `{
368
- "blocks": {
369
- "text_block": {
370
- "type": "nonexistent"
371
- }
372
- }
373
- }`,
374
- };
375
-
376
- const offenses = await check(theme, [JSONMissingBlock]);
377
- expect(offenses).to.be.empty;
378
- });
379
-
380
- it('should ignore templates with local blocks', async () => {
381
- const theme: MockTheme = {
382
- 'templates/product.nested.json': `{
383
- "sections": {
384
- "custom-section": {
385
- "type": "custom-section",
386
- "blocks": {
387
- "parent_block": {
388
- "type": "text",
389
- "blocks": {
390
- "child_block": {
391
- "type": "_private_block"
392
- }
393
- }
394
- }
395
- },
396
- "block_order": ["parent_block"]
397
- }
398
- },
399
- "order": ["custom-section"]
400
- }`,
401
- 'sections/custom-section.liquid': `
402
- {% schema %}
403
- {
404
- "name": "Custom Section",
405
- "blocks": [
406
- {
407
- "type": "text",
408
- "name": "Text Block"
409
- }
410
- ]
411
- }
412
- {% endschema %}
413
- `,
414
- 'blocks/text.liquid': `
415
- {% schema %}
416
- {
417
- "name": "Text Block",
418
- "blocks": [
419
- {
420
- "type": "image",
421
- "name": "Image Block"
422
- }
423
- ]
424
- }
425
- {% endschema %}
426
- `,
427
- 'blocks/image.liquid': '',
428
- 'blocks/_private_block.liquid': '',
429
- };
430
-
431
- const offenses = await check(theme, [JSONMissingBlock]);
432
- expect(offenses).to.be.empty;
433
- });
434
- });
435
- });
@@ -1,56 +0,0 @@
1
- import { getSchemaFromJSON } from '../../to-schema';
2
- import { JSONCheckDefinition, Severity, SourceCodeType } from '../../types';
3
- import { getAllBlocks, isPropertyNode } from './missing-block-utils';
4
-
5
- export const JSONMissingBlock: JSONCheckDefinition = {
6
- meta: {
7
- code: 'JSONMissingBlock',
8
- name: 'Check for missing blocks types in JSON templates',
9
- docs: {
10
- description: 'This check ensures that JSON templates contain valid block types.',
11
- recommended: true,
12
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/json-missing-block',
13
- },
14
- type: SourceCodeType.JSON,
15
- severity: Severity.ERROR,
16
- schema: {},
17
- targets: [],
18
- },
19
-
20
- create(context) {
21
- const relativePath = context.toRelativePath(context.file.uri);
22
- if (!relativePath.startsWith('templates/')) return {};
23
-
24
- return {
25
- async onCodePathEnd() {
26
- const schema = await getSchemaFromJSON(context);
27
- const { ast } = schema ?? {};
28
- if (!ast || ast instanceof Error) return;
29
- if (!schema) return;
30
-
31
- const sections = schema.parsed.sections;
32
- if (!sections) return;
33
-
34
- await Promise.all(
35
- Object.entries(sections).map(async ([sectionKey, section]) => {
36
- if (
37
- isPropertyNode(section) &&
38
- 'blocks' in section &&
39
- isPropertyNode(section.blocks) &&
40
- 'type' in section
41
- ) {
42
- await getAllBlocks(
43
- ast,
44
- 0,
45
- section.type,
46
- section.blocks,
47
- ['sections', sectionKey, 'blocks'],
48
- context,
49
- );
50
- }
51
- }),
52
- );
53
- },
54
- };
55
- },
56
- };
@@ -1,147 +0,0 @@
1
- import { Context, SourceCodeType, JSONNode } from '../../types';
2
- import { PropertyNode } from '../../jsonc/types';
3
- import { getLocEnd, getLocStart, nodeAtPath } from '../../json';
4
- import { doesFileExist } from '../../utils/file-utils';
5
-
6
- export function isPropertyNode(node: unknown): node is PropertyNode {
7
- return typeof node === 'object' && node !== null;
8
- }
9
-
10
- function isNestedBlock(currentPath: string[]): boolean {
11
- return currentPath.filter((segment) => segment === 'blocks').length > 1;
12
- }
13
-
14
- function reportWarning(
15
- message: string,
16
- offset: number,
17
- astNode: JSONNode,
18
- context: Context<SourceCodeType.JSON>,
19
- ) {
20
- context.report({
21
- message,
22
- startIndex: offset + getLocStart(astNode),
23
- endIndex: offset + getLocEnd(astNode),
24
- });
25
- }
26
-
27
- async function validateBlockFileExistence(
28
- blockType: string,
29
- context: Context<SourceCodeType.JSON>,
30
- ): Promise<boolean> {
31
- if (blockType === '@theme' || blockType === '@app') {
32
- return true;
33
- }
34
- const blockPath = `blocks/${blockType}.liquid`;
35
- return await doesFileExist(context, blockPath);
36
- }
37
-
38
- async function getThemeBlocks(
39
- sectionType: string,
40
- currentPath: string[],
41
- context: Context<SourceCodeType.JSON>,
42
- ): Promise<string[]> {
43
- const themeBlocks: string[] = [];
44
- if (!sectionType) return themeBlocks;
45
-
46
- const schema = isNestedBlock(currentPath)
47
- ? await context.getBlockSchema?.(sectionType)
48
- : await context.getSectionSchema?.(sectionType);
49
- if (!schema || schema instanceof Error) return themeBlocks;
50
-
51
- const { validSchema } = schema;
52
- if (!validSchema || validSchema instanceof Error) return themeBlocks;
53
-
54
- if (Array.isArray(validSchema.blocks)) {
55
- validSchema.blocks.forEach((block) => {
56
- if (!('name' in block) && block.type !== '@app') {
57
- themeBlocks.push(block.type);
58
- }
59
- });
60
- }
61
- return themeBlocks;
62
- }
63
-
64
- async function validateBlock(
65
- blockType: string,
66
- blockStatic: boolean,
67
- blockPath: JSONNode,
68
- ancestorType: string,
69
- currentPath: string[],
70
- offset: number,
71
- context: Context<SourceCodeType.JSON>,
72
- ) {
73
- const themeBlocks = await getThemeBlocks(ancestorType, currentPath, context);
74
- if (themeBlocks.length === 0) return;
75
-
76
- const exists = await validateBlockFileExistence(blockType, context);
77
- if (!exists) {
78
- reportWarning(
79
- `Theme block 'blocks/${blockType}.liquid' does not exist.`,
80
- offset,
81
- blockPath,
82
- context,
83
- );
84
- } else if (blockStatic) {
85
- // Static blocks are not required to be in the schema blocks array
86
- return;
87
- } else {
88
- const isPrivateBlock = blockType.startsWith('_');
89
- const schemaIncludesAtTheme = themeBlocks.includes('@theme');
90
- const schemaIncludesBlockType = themeBlocks.includes(blockType);
91
-
92
- if (
93
- !isPrivateBlock ? schemaIncludesBlockType || schemaIncludesAtTheme : schemaIncludesBlockType
94
- ) {
95
- return;
96
- } else {
97
- const location = isNestedBlock(currentPath) ? 'blocks' : 'sections';
98
- reportWarning(
99
- `Block type '${blockType}' is not allowed in '${location}/${ancestorType}.liquid'.`,
100
- offset,
101
- blockPath,
102
- context,
103
- );
104
- }
105
- }
106
- }
107
-
108
- export async function getAllBlocks(
109
- ast: JSONNode,
110
- offset: number,
111
- ancestorType: string,
112
- blocks: PropertyNode,
113
- currentPath: string[],
114
- context: Context<SourceCodeType.JSON>,
115
- ): Promise<void> {
116
- await Promise.all(
117
- Object.entries(blocks).map(async ([blockKey, block]) => {
118
- if (block.type) {
119
- const typePath = currentPath.concat(blockKey, 'type');
120
- const blockPath = nodeAtPath(ast, typePath)! as JSONNode;
121
-
122
- if (blockPath) {
123
- await validateBlock(
124
- block.type,
125
- block.static,
126
- blockPath,
127
- ancestorType,
128
- currentPath,
129
- offset,
130
- context,
131
- );
132
- }
133
- }
134
-
135
- if ('blocks' in block) {
136
- await getAllBlocks(
137
- ast,
138
- offset,
139
- block.type,
140
- block.blocks,
141
- currentPath.concat(blockKey, 'blocks'),
142
- context,
143
- );
144
- }
145
- }),
146
- );
147
- }