@platformos/platformos-check-common 0.0.7 → 0.0.9

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 (337) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +4 -4
  3. package/dist/AugmentedPlatformOSDocset.d.ts +11 -0
  4. package/dist/AugmentedPlatformOSDocset.js +81 -0
  5. package/dist/AugmentedPlatformOSDocset.js.map +1 -0
  6. package/dist/JSONValidator.js +1 -1
  7. package/dist/JSONValidator.js.map +1 -1
  8. package/dist/checks/deprecated-filter/index.js +4 -41
  9. package/dist/checks/deprecated-filter/index.js.map +1 -1
  10. package/dist/checks/deprecated-tag/index.js +21 -22
  11. package/dist/checks/deprecated-tag/index.js.map +1 -1
  12. package/dist/checks/duplicate-function-arguments/index.js +1 -1
  13. package/dist/checks/duplicate-function-arguments/index.js.map +1 -1
  14. package/dist/checks/duplicate-render-partial-arguments/index.js +1 -1
  15. package/dist/checks/duplicate-render-partial-arguments/index.js.map +1 -1
  16. package/dist/checks/graphql/index.js +1 -1
  17. package/dist/checks/graphql/index.js.map +1 -1
  18. package/dist/checks/graphql-variables/index.js +4 -0
  19. package/dist/checks/graphql-variables/index.js.map +1 -1
  20. package/dist/checks/img-width-and-height/index.js +1 -1
  21. package/dist/checks/img-width-and-height/index.js.map +1 -1
  22. package/dist/checks/index.d.ts +3 -3
  23. package/dist/checks/index.js +4 -79
  24. package/dist/checks/index.js.map +1 -1
  25. package/dist/checks/json-syntax-error/index.js +1 -1
  26. package/dist/checks/json-syntax-error/index.js.map +1 -1
  27. package/dist/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.js +1 -1
  28. package/dist/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.js.map +1 -1
  29. package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.d.ts +19 -0
  30. package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.js +79 -0
  31. package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.js.map +1 -0
  32. package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.d.ts +3 -0
  33. package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.js +32 -0
  34. package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.js.map +1 -0
  35. package/dist/checks/liquid-html-syntax-error/index.js +23 -5
  36. package/dist/checks/liquid-html-syntax-error/index.js.map +1 -1
  37. package/dist/checks/matching-translations/index.d.ts +2 -2
  38. package/dist/checks/matching-translations/index.js +114 -90
  39. package/dist/checks/matching-translations/index.js.map +1 -1
  40. package/dist/checks/metadata-params/index.js +6 -3
  41. package/dist/checks/metadata-params/index.js.map +1 -1
  42. package/dist/checks/missing-asset/index.js +1 -1
  43. package/dist/checks/missing-asset/index.js.map +1 -1
  44. package/dist/checks/missing-partial/index.d.ts +6 -0
  45. package/dist/checks/missing-partial/index.js +70 -0
  46. package/dist/checks/missing-partial/index.js.map +1 -0
  47. package/dist/checks/orphaned-partial/index.js +4 -4
  48. package/dist/checks/orphaned-partial/index.js.map +1 -1
  49. package/dist/checks/parser-blocking-script/index.js +10 -36
  50. package/dist/checks/parser-blocking-script/index.js.map +1 -1
  51. package/dist/checks/parser-blocking-script/suggestions.d.ts +1 -2
  52. package/dist/checks/parser-blocking-script/suggestions.js +1 -11
  53. package/dist/checks/parser-blocking-script/suggestions.js.map +1 -1
  54. package/dist/checks/reserved-doc-param-names/index.js +6 -5
  55. package/dist/checks/reserved-doc-param-names/index.js.map +1 -1
  56. package/dist/checks/translation-key-exists/index.js +1 -1
  57. package/dist/checks/translation-key-exists/index.js.map +1 -1
  58. package/dist/checks/unclosed-html-element/index.js +5 -1
  59. package/dist/checks/unclosed-html-element/index.js.map +1 -1
  60. package/dist/checks/undefined-object/index.js +13 -31
  61. package/dist/checks/undefined-object/index.js.map +1 -1
  62. package/dist/checks/unique-doc-param-names/index.js +1 -1
  63. package/dist/checks/unique-doc-param-names/index.js.map +1 -1
  64. package/dist/checks/unknown-filter/index.js +3 -3
  65. package/dist/checks/unknown-filter/index.js.map +1 -1
  66. package/dist/checks/unknown-property/index.js +1 -1
  67. package/dist/checks/unknown-property/index.js.map +1 -1
  68. package/dist/checks/unrecognized-render-partial-arguments/index.js +2 -2
  69. package/dist/checks/unrecognized-render-partial-arguments/index.js.map +1 -1
  70. package/dist/checks/unused-assign/index.js +1 -1
  71. package/dist/checks/unused-assign/index.js.map +1 -1
  72. package/dist/checks/unused-doc-param/index.js +1 -1
  73. package/dist/checks/unused-doc-param/index.js.map +1 -1
  74. package/dist/checks/utils.js +1 -1
  75. package/dist/checks/utils.js.map +1 -1
  76. package/dist/checks/valid-content-for-arguments/index.js +1 -1
  77. package/dist/checks/valid-content-for-arguments/index.js.map +1 -1
  78. package/dist/checks/valid-doc-param-types/index.js +4 -4
  79. package/dist/checks/valid-doc-param-types/index.js.map +1 -1
  80. package/dist/checks/valid-html-translation/index.d.ts +2 -2
  81. package/dist/checks/valid-html-translation/index.js +4 -4
  82. package/dist/checks/valid-html-translation/index.js.map +1 -1
  83. package/dist/checks/valid-json/index.js +1 -1
  84. package/dist/checks/valid-json/index.js.map +1 -1
  85. package/dist/checks/valid-render-partial-argument-types/index.js +2 -2
  86. package/dist/checks/valid-render-partial-argument-types/index.js.map +1 -1
  87. package/dist/checks/variable-name/index.js +1 -1
  88. package/dist/checks/variable-name/index.js.map +1 -1
  89. package/dist/context-utils.d.ts +18 -7
  90. package/dist/context-utils.js +68 -109
  91. package/dist/context-utils.js.map +1 -1
  92. package/dist/disabled-checks/index.js +4 -2
  93. package/dist/disabled-checks/index.js.map +1 -1
  94. package/dist/doc-generator/DocBlockGenerator.d.ts +16 -0
  95. package/dist/doc-generator/DocBlockGenerator.js +464 -0
  96. package/dist/doc-generator/DocBlockGenerator.js.map +1 -0
  97. package/dist/doc-generator/index.d.ts +1 -0
  98. package/dist/doc-generator/index.js +6 -0
  99. package/dist/doc-generator/index.js.map +1 -0
  100. package/dist/find-root.d.ts +7 -10
  101. package/dist/find-root.js +10 -17
  102. package/dist/find-root.js.map +1 -1
  103. package/dist/fixes/autofix.d.ts +4 -4
  104. package/dist/fixes/autofix.js +2 -2
  105. package/dist/fixes/autofix.js.map +1 -1
  106. package/dist/fixes/correctors/index.js +4 -0
  107. package/dist/fixes/correctors/index.js.map +1 -1
  108. package/dist/index.d.ts +5 -5
  109. package/dist/index.js +50 -17
  110. package/dist/index.js.map +1 -1
  111. package/dist/jsonc/parse.d.ts +1 -1
  112. package/dist/jsonc/parse.js +1 -1
  113. package/dist/liquid-doc/arguments.d.ts +7 -8
  114. package/dist/liquid-doc/arguments.js +28 -29
  115. package/dist/liquid-doc/arguments.js.map +1 -1
  116. package/dist/liquid-doc/liquidDoc.d.ts +1 -1
  117. package/dist/liquid-doc/liquidDoc.js.map +1 -1
  118. package/dist/liquid-doc/utils.d.ts +3 -3
  119. package/dist/liquid-doc/utils.js +14 -3
  120. package/dist/liquid-doc/utils.js.map +1 -1
  121. package/dist/path.d.ts +1 -0
  122. package/dist/path.js +16 -1
  123. package/dist/path.js.map +1 -1
  124. package/{src/test/MockTheme.ts → dist/test/MockApp.d.ts} +2 -3
  125. package/dist/test/MockApp.js +16 -0
  126. package/dist/test/MockApp.js.map +1 -0
  127. package/dist/test/MockFileSystem.d.ts +3 -3
  128. package/dist/test/MockFileSystem.js +6 -6
  129. package/dist/test/MockFileSystem.js.map +1 -1
  130. package/dist/test/index.d.ts +1 -1
  131. package/dist/test/index.js +1 -1
  132. package/dist/test/index.js.map +1 -1
  133. package/dist/test/test-helper.d.ts +10 -9
  134. package/dist/test/test-helper.js +15 -106
  135. package/dist/test/test-helper.js.map +1 -1
  136. package/dist/to-schema.d.ts +1 -1
  137. package/dist/to-source-code.d.ts +3 -2
  138. package/dist/to-source-code.js +20 -0
  139. package/dist/to-source-code.js.map +1 -1
  140. package/dist/tsconfig.tsbuildinfo +1 -1
  141. package/dist/types/platformos-liquid-docs.d.ts +128 -0
  142. package/dist/types/platformos-liquid-docs.js +3 -0
  143. package/dist/types/platformos-liquid-docs.js.map +1 -0
  144. package/dist/types/schemas/index.d.ts +0 -2
  145. package/dist/types/schemas/index.js.map +1 -1
  146. package/dist/types.d.ts +26 -67
  147. package/dist/types.js +3 -5
  148. package/dist/types.js.map +1 -1
  149. package/dist/utils/block.js.map +1 -1
  150. package/dist/utils/index.d.ts +0 -1
  151. package/dist/utils/index.js +0 -1
  152. package/dist/utils/index.js.map +1 -1
  153. package/dist/yaml/parse.d.ts +5 -0
  154. package/dist/yaml/parse.js +94 -0
  155. package/dist/yaml/parse.js.map +1 -0
  156. package/package.json +4 -3
  157. package/src/{AugmentedThemeDocset.spec.ts → AugmentedPlatformOSDocset.spec.ts} +47 -34
  158. package/src/AugmentedPlatformOSDocset.ts +89 -0
  159. package/src/JSONValidator.ts +1 -1
  160. package/src/checks/deprecated-filter/index.spec.ts +76 -248
  161. package/src/checks/deprecated-filter/index.ts +5 -53
  162. package/src/checks/deprecated-tag/index.spec.ts +85 -34
  163. package/src/checks/deprecated-tag/index.ts +27 -22
  164. package/src/checks/duplicate-function-arguments/index.ts +1 -1
  165. package/src/checks/duplicate-render-partial-arguments/index.spec.ts +12 -12
  166. package/src/checks/duplicate-render-partial-arguments/index.ts +1 -1
  167. package/src/checks/graphql/index.ts +1 -1
  168. package/src/checks/graphql-variables/index.spec.ts +95 -0
  169. package/src/checks/graphql-variables/index.ts +4 -0
  170. package/src/checks/img-width-and-height/index.ts +2 -2
  171. package/src/checks/index.ts +11 -80
  172. package/src/checks/invalid-hash-assign-target/index.spec.ts +27 -27
  173. package/src/checks/json-syntax-error/index.ts +2 -2
  174. package/src/checks/liquid-html-syntax-error/checks/InvalidBooleanExpression.spec.ts +0 -11
  175. package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.spec.ts +1 -2
  176. package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.ts +2 -2
  177. package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.spec.ts +259 -0
  178. package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.ts +89 -0
  179. package/src/checks/liquid-html-syntax-error/checks/UnknownTag.spec.ts +293 -0
  180. package/src/checks/liquid-html-syntax-error/checks/UnknownTag.ts +43 -0
  181. package/src/checks/liquid-html-syntax-error/index.spec.ts +1 -6
  182. package/src/checks/liquid-html-syntax-error/index.ts +26 -5
  183. package/src/checks/matching-translations/index.spec.ts +187 -354
  184. package/src/checks/matching-translations/index.ts +117 -107
  185. package/src/checks/metadata-params/index.ts +6 -8
  186. package/src/checks/missing-asset/index.ts +1 -1
  187. package/src/checks/{missing-template → missing-partial}/index.spec.ts +6 -6
  188. package/src/checks/{missing-template → missing-partial}/index.ts +12 -26
  189. package/src/checks/orphaned-partial/index.ts +3 -3
  190. package/src/checks/parser-blocking-script/index.spec.ts +0 -118
  191. package/src/checks/parser-blocking-script/index.ts +3 -33
  192. package/src/checks/parser-blocking-script/suggestions.ts +1 -28
  193. package/src/checks/translation-key-exists/index.ts +1 -1
  194. package/src/checks/unclosed-html-element/index.ts +5 -1
  195. package/src/checks/undefined-object/index.spec.ts +32 -111
  196. package/src/checks/undefined-object/index.ts +15 -34
  197. package/src/checks/unique-doc-param-names/index.ts +1 -1
  198. package/src/checks/unknown-filter/index.spec.ts +2 -2
  199. package/src/checks/unknown-filter/index.ts +3 -3
  200. package/src/checks/unknown-property/index.ts +1 -1
  201. package/src/checks/unrecognized-render-partial-arguments/index.spec.ts +5 -5
  202. package/src/checks/unrecognized-render-partial-arguments/index.ts +2 -5
  203. package/src/checks/unused-assign/index.spec.ts +0 -30
  204. package/src/checks/unused-assign/index.ts +2 -2
  205. package/src/checks/unused-doc-param/index.ts +1 -1
  206. package/src/checks/utils.ts +1 -1
  207. package/src/checks/valid-doc-param-types/index.ts +4 -4
  208. package/src/checks/valid-html-translation/index.spec.ts +42 -32
  209. package/src/checks/valid-html-translation/index.ts +7 -7
  210. package/src/checks/valid-json/index.ts +2 -2
  211. package/src/checks/valid-render-partial-argument-types/index.spec.ts +13 -13
  212. package/src/checks/valid-render-partial-argument-types/index.ts +2 -5
  213. package/src/checks/variable-name/index.ts +1 -1
  214. package/src/context-utils.spec.ts +49 -77
  215. package/src/context-utils.ts +81 -129
  216. package/src/disabled-checks/index.spec.ts +26 -26
  217. package/src/disabled-checks/index.ts +2 -2
  218. package/src/disabled-checks/test-checks.ts +4 -4
  219. package/src/find-root.ts +12 -22
  220. package/src/fixes/autofix.spec.ts +2 -2
  221. package/src/fixes/autofix.ts +4 -4
  222. package/src/fixes/correctors/index.ts +4 -0
  223. package/src/ignore.spec.ts +4 -5
  224. package/src/index.ts +51 -21
  225. package/src/jsonc/parse.ts +1 -1
  226. package/src/liquid-doc/arguments.spec.ts +19 -45
  227. package/src/liquid-doc/arguments.ts +35 -42
  228. package/src/liquid-doc/liquidDoc.spec.ts +1 -1
  229. package/src/liquid-doc/liquidDoc.ts +1 -2
  230. package/src/liquid-doc/utils.ts +17 -8
  231. package/src/path.ts +16 -0
  232. package/src/test/MockApp.ts +17 -0
  233. package/src/test/MockFileSystem.spec.ts +10 -11
  234. package/src/test/MockFileSystem.ts +6 -6
  235. package/src/test/contain-offense.spec.ts +11 -3
  236. package/src/test/index.ts +1 -1
  237. package/src/test/test-helper.ts +43 -145
  238. package/src/to-source-code.ts +20 -1
  239. package/src/types/{theme-liquid-docs.ts → platformos-liquid-docs.ts} +8 -13
  240. package/src/types.ts +29 -92
  241. package/src/utils/index.ts +0 -1
  242. package/src/visitor.spec.ts +2 -2
  243. package/src/yaml/parse.ts +111 -0
  244. package/src/AugmentedThemeDocset.ts +0 -137
  245. package/src/checks/app-block-missing-schema/index.spec.ts +0 -121
  246. package/src/checks/app-block-missing-schema/index.ts +0 -46
  247. package/src/checks/app-block-valid-tags/index.spec.ts +0 -96
  248. package/src/checks/app-block-valid-tags/index.ts +0 -54
  249. package/src/checks/asset-preload/index.spec.ts +0 -78
  250. package/src/checks/asset-preload/index.ts +0 -65
  251. package/src/checks/asset-size-app-block-css/index.spec.ts +0 -88
  252. package/src/checks/asset-size-app-block-css/index.ts +0 -78
  253. package/src/checks/asset-size-app-block-javascript/index.spec.ts +0 -66
  254. package/src/checks/asset-size-app-block-javascript/index.ts +0 -78
  255. package/src/checks/asset-size-css/index.spec.ts +0 -166
  256. package/src/checks/asset-size-css/index.ts +0 -160
  257. package/src/checks/asset-size-javascript/index.spec.ts +0 -184
  258. package/src/checks/asset-size-javascript/index.ts +0 -144
  259. package/src/checks/block-id-usage/index.spec.ts +0 -76
  260. package/src/checks/block-id-usage/index.ts +0 -72
  261. package/src/checks/cdn-preconnect/index.spec.ts +0 -40
  262. package/src/checks/cdn-preconnect/index.ts +0 -43
  263. package/src/checks/content-for-header-modification/index.spec.ts +0 -65
  264. package/src/checks/content-for-header-modification/index.ts +0 -72
  265. package/src/checks/deprecate-bgsizes/index.spec.ts +0 -41
  266. package/src/checks/deprecate-bgsizes/index.ts +0 -49
  267. package/src/checks/deprecate-lazysizes/index.spec.ts +0 -26
  268. package/src/checks/deprecate-lazysizes/index.ts +0 -58
  269. package/src/checks/deprecated-filter/fixes.ts +0 -264
  270. package/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts +0 -1343
  271. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts +0 -613
  272. package/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts +0 -284
  273. package/src/checks/deprecated-fonts-on-settings-schema/index.spec.ts +0 -102
  274. package/src/checks/deprecated-fonts-on-settings-schema/index.ts +0 -66
  275. package/src/checks/duplicate-content-for-arguments/index.spec.ts +0 -98
  276. package/src/checks/duplicate-content-for-arguments/index.ts +0 -43
  277. package/src/checks/empty-block-content/index.spec.ts +0 -117
  278. package/src/checks/empty-block-content/index.ts +0 -60
  279. package/src/checks/hardcoded-routes/index.spec.ts +0 -58
  280. package/src/checks/hardcoded-routes/index.ts +0 -100
  281. package/src/checks/json-missing-block/index.spec.ts +0 -435
  282. package/src/checks/json-missing-block/index.ts +0 -56
  283. package/src/checks/json-missing-block/missing-block-utils.ts +0 -147
  284. package/src/checks/liquid-free-settings/index.spec.ts +0 -180
  285. package/src/checks/liquid-free-settings/index.ts +0 -79
  286. package/src/checks/missing-content-for-arguments/index.spec.ts +0 -144
  287. package/src/checks/missing-content-for-arguments/index.ts +0 -46
  288. package/src/checks/pagination-size/index.spec.ts +0 -158
  289. package/src/checks/pagination-size/index.ts +0 -104
  290. package/src/checks/remote-asset/index.spec.ts +0 -280
  291. package/src/checks/remote-asset/index.ts +0 -238
  292. package/src/checks/reserved-doc-param-names/index.spec.ts +0 -62
  293. package/src/checks/reserved-doc-param-names/index.ts +0 -57
  294. package/src/checks/schema-presets-block-order/index.spec.ts +0 -344
  295. package/src/checks/schema-presets-block-order/index.ts +0 -154
  296. package/src/checks/schema-presets-static-blocks/index.spec.ts +0 -145
  297. package/src/checks/schema-presets-static-blocks/index.ts +0 -126
  298. package/src/checks/static-stylesheet-and-javascript-tags/index.spec.ts +0 -257
  299. package/src/checks/static-stylesheet-and-javascript-tags/index.ts +0 -48
  300. package/src/checks/unique-settings-id/index.spec.ts +0 -24
  301. package/src/checks/unique-settings-id/index.ts +0 -84
  302. package/src/checks/unique-settings-id/test-data.ts +0 -1191
  303. package/src/checks/unique-static-block-id/index.spec.ts +0 -55
  304. package/src/checks/unique-static-block-id/index.ts +0 -60
  305. package/src/checks/unrecognized-content-for-arguments/index.spec.ts +0 -145
  306. package/src/checks/unrecognized-content-for-arguments/index.ts +0 -55
  307. package/src/checks/valid-block-target/index.spec.ts +0 -1396
  308. package/src/checks/valid-block-target/index.ts +0 -142
  309. package/src/checks/valid-content-for-argument-types/index.spec.ts +0 -382
  310. package/src/checks/valid-content-for-argument-types/index.ts +0 -42
  311. package/src/checks/valid-content-for-arguments/index.spec.ts +0 -107
  312. package/src/checks/valid-content-for-arguments/index.ts +0 -98
  313. package/src/checks/valid-local-blocks/index.spec.ts +0 -286
  314. package/src/checks/valid-local-blocks/index.ts +0 -100
  315. package/src/checks/valid-local-blocks/valid-block-utils.ts +0 -97
  316. package/src/checks/valid-schema/index.spec.ts +0 -174
  317. package/src/checks/valid-schema/index.ts +0 -41
  318. package/src/checks/valid-schema-name/index.spec.ts +0 -112
  319. package/src/checks/valid-schema-name/index.ts +0 -75
  320. package/src/checks/valid-settings-key/index.spec.ts +0 -321
  321. package/src/checks/valid-settings-key/index.ts +0 -144
  322. package/src/checks/valid-static-block-type/index.spec.ts +0 -38
  323. package/src/checks/valid-static-block-type/index.ts +0 -58
  324. package/src/checks/valid-visible-if/index.spec.ts +0 -619
  325. package/src/checks/valid-visible-if/index.ts +0 -184
  326. package/src/checks/valid-visible-if/visible-if-utils.ts +0 -158
  327. package/src/tags/content-for.ts +0 -25
  328. package/src/to-schema.ts +0 -231
  329. package/src/types/schemas/index.ts +0 -5
  330. package/src/types/schemas/preset.ts +0 -52
  331. package/src/types/schemas/section.ts +0 -86
  332. package/src/types/schemas/setting.ts +0 -320
  333. package/src/types/schemas/template.ts +0 -34
  334. package/src/types/schemas/theme-block.ts +0 -34
  335. package/src/types/theme-schemas.ts +0 -80
  336. package/src/utils/block.ts +0 -300
  337. 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
- }