@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,184 +0,0 @@
1
- import { type LiquidVariableLookup } from '@platformos/liquid-html-parser';
2
- import {
3
- Severity,
4
- SourceCodeType,
5
- type LiquidCheckDefinition,
6
- type JSONCheckDefinition,
7
- } from '../../types';
8
- import { getLocStart, nodeAtPath } from '../../json';
9
- import { getSchema, isBlockSchema, isSectionSchema } from '../../to-schema';
10
- import { reportWarning } from '../../utils';
11
- import {
12
- getGlobalSettings,
13
- getVariableLookupsInExpression,
14
- validateLookup,
15
- offsetAdjust,
16
- type Vars,
17
- } from './visible-if-utils';
18
-
19
- // Note that unlike most other files in the `checks` directory, this exports two
20
- // checks: one for Liquid files and one for 'config/settings_schema.json'. They
21
- // perform the same check using the same logic (modulo differences extracting
22
- // the schema and determining warning start and end indices).
23
-
24
- const meta = {
25
- code: 'ValidVisibleIf',
26
- name: 'Validate visible_if expressions',
27
- docs: {
28
- description:
29
- 'Ensures visible_if expressions are well-formed and only reference settings keys that are defined',
30
- recommended: true,
31
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/valid-visible-if',
32
- },
33
- severity: Severity.ERROR,
34
- schema: {},
35
- targets: [],
36
- };
37
-
38
- export const ValidVisibleIf: LiquidCheckDefinition = {
39
- meta: { ...meta, type: SourceCodeType.LiquidHtml },
40
-
41
- create(context) {
42
- return {
43
- async LiquidRawTag(node) {
44
- if (node.name !== 'schema' || node.body.kind !== 'json') return;
45
-
46
- const schema = await getSchema(context);
47
-
48
- const { validSchema, ast } = schema ?? {};
49
- if (
50
- !validSchema ||
51
- validSchema instanceof Error ||
52
- !validSchema.settings?.some((setting) => 'visible_if' in setting) ||
53
- !ast ||
54
- ast instanceof Error
55
- ) {
56
- return;
57
- }
58
-
59
- const offset = node.blockStartPosition.end;
60
- const settings = Object.fromEntries(
61
- (await getGlobalSettings(context)).map((s) => [s, true] as const),
62
- );
63
- const currentFileSettings = Object.fromEntries(
64
- validSchema.settings.map((setting) => [setting.id, true] as const),
65
- );
66
-
67
- const vars: Vars = { settings };
68
- if (isSectionSchema(schema)) {
69
- vars.section = { settings: currentFileSettings };
70
- } else if (isBlockSchema(schema)) {
71
- vars.block = { settings: currentFileSettings };
72
- }
73
-
74
- for (const [i, setting] of validSchema.settings.entries()) {
75
- if (!('visible_if' in setting) || typeof setting.visible_if !== 'string') continue;
76
-
77
- const visibleIfNode = nodeAtPath(ast, ['settings', i, 'visible_if'])!;
78
-
79
- const varLookupsOrWarning = await getVariableLookupsInExpression(setting.visible_if);
80
- if (varLookupsOrWarning === null) continue;
81
-
82
- if ('warning' in varLookupsOrWarning) {
83
- reportWarning(varLookupsOrWarning.warning, offset, visibleIfNode, context);
84
- continue;
85
- }
86
-
87
- const report = (message: string | null, lookup: LiquidVariableLookup) => {
88
- if (typeof message === 'string') {
89
- context.report({
90
- message,
91
- // the JSONNode start location returned by `getLocStart`
92
- // includes the opening quotation mark — whereas when we parse
93
- // the inner expression, 0 is the location _inside_ the quotes.
94
- // we add 1 to the offsets to compensate.
95
- startIndex:
96
- offset + getLocStart(visibleIfNode) + lookup.position.start + offsetAdjust + 1,
97
- endIndex:
98
- offset + getLocStart(visibleIfNode) + lookup.position.end + offsetAdjust + 1,
99
- });
100
- }
101
- };
102
-
103
- for (const lookup of varLookupsOrWarning) {
104
- if (lookup.name === 'section' && isBlockSchema(schema)) {
105
- //no-op, we don't know what section this block will be used in, so we can't validate that the setting exists
106
- } else if (lookup.name === 'section' && !isSectionSchema(schema)) {
107
- report(
108
- `Invalid visible_if: can't refer to "section" when not in a section or block file.`,
109
- lookup,
110
- );
111
- } else if (lookup.name === 'block' && !isBlockSchema(schema)) {
112
- report(
113
- `Invalid visible_if: can't refer to "block" when not in a block file.`,
114
- lookup,
115
- );
116
- } else {
117
- report(validateLookup(lookup, vars), lookup);
118
- }
119
- }
120
- }
121
- },
122
- };
123
- },
124
- };
125
-
126
- export const ValidVisibleIfSettingsSchema: JSONCheckDefinition = {
127
- meta: { ...meta, type: SourceCodeType.JSON },
128
-
129
- create(context) {
130
- const relativePath = context.toRelativePath(context.file.uri);
131
- if (relativePath !== 'config/settings_schema.json') return {};
132
-
133
- return {
134
- async Property(node) {
135
- if (node.key.value !== 'visible_if' || node.value.type !== 'Literal') return;
136
- const visibleIfExpression = node.value.value;
137
- if (typeof visibleIfExpression !== 'string') return;
138
- const offset = node.value.loc.start.offset;
139
-
140
- const varLookupsOrWarning = await getVariableLookupsInExpression(visibleIfExpression);
141
- if (varLookupsOrWarning === null) return;
142
-
143
- if ('warning' in varLookupsOrWarning) {
144
- context.report({
145
- message: varLookupsOrWarning.warning,
146
- startIndex: node.value.loc.start.offset,
147
- endIndex: node.value.loc.end.offset,
148
- });
149
- return;
150
- }
151
-
152
- const settings = Object.fromEntries(
153
- (await getGlobalSettings(context)).map((s) => [s, true] as const),
154
- );
155
-
156
- const vars: Vars = { settings };
157
-
158
- const report = (message: string | null, lookup: LiquidVariableLookup) => {
159
- if (typeof message === 'string') {
160
- context.report({
161
- message,
162
- startIndex: offset + lookup.position.start + offsetAdjust + 1,
163
- endIndex: offset + lookup.position.end + offsetAdjust + 1,
164
- });
165
- }
166
- };
167
-
168
- for (const lookup of varLookupsOrWarning) {
169
- // settings_schema.json can't reference `section` or `block`.
170
- if (lookup.name === 'section') {
171
- report(
172
- `Invalid visible_if: can't refer to "section" when not in a section file.`,
173
- lookup,
174
- );
175
- } else if (lookup.name === 'block') {
176
- report(`Invalid visible_if: can't refer to "block" when not in a block file.`, lookup);
177
- } else {
178
- report(validateLookup(lookup, vars), lookup);
179
- }
180
- }
181
- },
182
- };
183
- },
184
- };
@@ -1,158 +0,0 @@
1
- import {
2
- type LiquidVariableLookup,
3
- NodeTypes,
4
- toLiquidHtmlAST,
5
- } from '@platformos/liquid-html-parser';
6
- import { Context, SourceCodeType } from '../..';
7
- import { parseJSON } from '../../json';
8
- import { visit } from '../../visitor';
9
-
10
- export type Vars = { [key: string]: Vars | true };
11
-
12
- export const variableExpressionMatcher = /{{(.+?)}}/;
13
- export const adjustedPrefix = '{% if ';
14
- export const adjustedSuffix = ' %}{% endif %}';
15
- export const offsetAdjust = '{{'.length - adjustedPrefix.length;
16
-
17
- export async function getVariableLookupsInExpression(
18
- expression: string,
19
- ): Promise<LiquidVariableLookup[] | { warning: string } | null> {
20
- // As of February 2025, parsers other than LiquidJS don't yet support
21
- // expressions in {{ variable }} tags. So we have to do something a little
22
- // gnarly — before parsing it we extract the expression from within the tag
23
- // and plunk it into an `{% if <expression> %}{% endif %}` statement instead.
24
- // This requires us to adjust the reported character ranges and offer slightly
25
- // less useful messages on syntax errors, but otherwise should behave
26
- // similarly to a proper `{{ <expression> }}` syntax whenever it lands.
27
- const match = variableExpressionMatcher.exec(expression);
28
- if (match == null) {
29
- return {
30
- warning: `Invalid visible_if expression. It should take the form "{{ <expression> }}".`,
31
- };
32
- }
33
- const unwrappedExpression = match[1];
34
-
35
- const adjustedExpression = `${adjustedPrefix}${unwrappedExpression}${adjustedSuffix}`;
36
-
37
- try {
38
- const innerAst = toLiquidHtmlAST(adjustedExpression, {
39
- mode: 'strict',
40
- allowUnclosedDocumentNode: false,
41
- });
42
-
43
- if (innerAst.children.length !== 1) {
44
- throw new Error('Unexpected child count for DocumentNode');
45
- }
46
-
47
- const ifTag = innerAst.children[0];
48
-
49
- if (ifTag.type !== 'LiquidTag' || ifTag.name !== 'if') {
50
- throw new Error("Expected DocumentNode to contain 'if' tag");
51
- }
52
-
53
- const expressionNode = ifTag.markup;
54
- if (typeof expressionNode === 'string') {
55
- return {
56
- warning: `Invalid visible_if expression.`,
57
- };
58
- }
59
-
60
- if (
61
- expressionNode.type === NodeTypes.LiquidLiteral &&
62
- ['true', 'false'].includes(expressionNode.keyword)
63
- ) {
64
- // Those are OK
65
- return null;
66
- }
67
-
68
- const vars = await visit<SourceCodeType.LiquidHtml, LiquidVariableLookup>(ifTag, {
69
- VariableLookup: async (node) => node,
70
- });
71
-
72
- if (vars.length === 0) {
73
- return {
74
- warning: `visible_if expression contains no references to any settings. This is likely an error.`,
75
- };
76
- }
77
-
78
- return vars;
79
- } catch (error) {
80
- if (error instanceof SyntaxError) {
81
- // Because of our hackish approach, the underlying error is likely to
82
- // include an incorrect character range and/or mention {% if %} tags.
83
- // Squelch the details and just report it as a simple syntax error.
84
- return { warning: 'Syntax error: cannot parse visible_if expression.' };
85
- }
86
-
87
- return { warning: String(error) };
88
- }
89
- }
90
-
91
- export function validateLookup(lookup: LiquidVariableLookup, vars: Vars): string | null {
92
- const normalized = getNormalizedLookups(lookup);
93
-
94
- const poppedSegments = [];
95
- let scope = vars;
96
- while (normalized.length > 0) {
97
- const segment = normalized.shift()!;
98
- poppedSegments.push(segment);
99
-
100
- // "noUncheckedIndexedAccess" is false in our tsconfig.json
101
- const next = scope[segment] as true | Vars | undefined;
102
-
103
- if (!next) {
104
- return `Invalid variable: "${poppedSegments.join('.')}" was not found.`;
105
- }
106
-
107
- if (typeof next === 'boolean') {
108
- if (normalized.length > 0) {
109
- return `Invalid variable: "${poppedSegments.join(
110
- '.',
111
- )}" refers to a variable, but is being used here as a namespace.`;
112
- }
113
- return null;
114
- }
115
-
116
- scope = next;
117
- }
118
-
119
- // note this is the reverse of the above similar-looking case
120
- return `Invalid variable: "${poppedSegments.join(
121
- '.',
122
- )}" refers to a namespace, but is being used here as a variable.`;
123
- }
124
-
125
- function getNormalizedLookups(lookup: LiquidVariableLookup) {
126
- const nestedLookups = lookup.lookups.map((lookup) => {
127
- if (lookup.type !== NodeTypes.String) {
128
- throw new Error(`Expected lookups to be String nodes: ${JSON.stringify(lookup)}`);
129
- }
130
- return lookup.value;
131
- });
132
-
133
- return [lookup.name, ...nestedLookups];
134
- }
135
-
136
- export async function getGlobalSettings(context: Context<SourceCodeType>) {
137
- const globalSettings: string[] = [];
138
-
139
- try {
140
- const uri = context.toUri('config/settings_schema.json');
141
- const settingsFile = await context.fs.readFile(uri);
142
- const settings = parseJSON(settingsFile);
143
- if (Array.isArray(settings)) {
144
- for (const group of settings) {
145
- if ('settings' in group && Array.isArray(group.settings)) {
146
- globalSettings.push(
147
- ...group.settings.map((setting: any) => setting.id).filter((id: any) => id),
148
- );
149
- }
150
- }
151
- }
152
- } catch (e) {
153
- console.error('Error fetching global settings:', e);
154
- // ignore absent or malformed settings schema
155
- }
156
-
157
- return globalSettings;
158
- }
@@ -1,25 +0,0 @@
1
- export const RESERVED_CONTENT_FOR_ARGUMENTS = [
2
- 'attributes',
3
- 'block',
4
- 'blocks',
5
- 'class',
6
- 'context',
7
- 'inherit',
8
- 'resource',
9
- 'resources',
10
- 'schema',
11
- 'section',
12
- 'sections',
13
- 'settings',
14
- 'snippet',
15
- 'snippets',
16
- 'src',
17
- 'style',
18
- 'styles',
19
- 'template',
20
- 'templates',
21
- ];
22
-
23
- export const REQUIRED_CONTENT_FOR_ARGUMENTS = ['id', 'type'];
24
-
25
- export const CLOSEST_ARGUMENT = 'closest.';
package/src/to-schema.ts DELETED
@@ -1,231 +0,0 @@
1
- import {
2
- ContentForMarkup,
3
- LiquidRawTag,
4
- NamedTags,
5
- NodeTypes,
6
- } from '@platformos/liquid-html-parser';
7
- import { isPartial as isPartialPath } from '@platformos/platformos-common';
8
- import { parseJSON } from './json';
9
- import * as path from './path';
10
- import { toJSONAST } from './to-source-code';
11
- import {
12
- AppBlockSchema,
13
- ThemeBlockSchema,
14
- IsValidSchema,
15
- LiquidHtmlNode,
16
- SectionSchema,
17
- SourceCode,
18
- SourceCodeType,
19
- ThemeBlock,
20
- ThemeSchemaType,
21
- UriString,
22
- Context,
23
- Schema,
24
- StaticBlockDef,
25
- } from './types';
26
- import { visit } from './visitor';
27
-
28
- export async function toSchema(
29
- mode: 'app' | 'theme',
30
- uri: UriString,
31
- sourceCode: SourceCode,
32
- isValidSchema: IsValidSchema | undefined,
33
- isStrict: boolean = true,
34
- ): Promise<AppBlockSchema | SectionSchema | ThemeBlockSchema | undefined> {
35
- if (sourceCode.type !== SourceCodeType.LiquidHtml) return undefined;
36
- switch (true) {
37
- case mode === 'app' && isBlock(uri):
38
- return toAppBlockSchema(uri, sourceCode.ast, isStrict);
39
- case mode === 'theme' && isBlock(uri):
40
- return toBlockSchema(uri, sourceCode.ast, isValidSchema, isStrict);
41
- case mode === 'theme' && isSection(uri):
42
- return toSectionSchema(uri, sourceCode.ast, isValidSchema, isStrict);
43
- default:
44
- return undefined;
45
- }
46
- }
47
-
48
- export function isBlock(uri: UriString) {
49
- return path.dirname(uri).endsWith('blocks');
50
- }
51
-
52
- export function isSection(uri: UriString) {
53
- return path.dirname(uri).endsWith('sections');
54
- }
55
-
56
- export function isPartial(uri: UriString) {
57
- return isPartialPath(uri);
58
- }
59
-
60
- // Legacy alias for backwards compatibility
61
- export const isSnippet = isPartial;
62
-
63
- export function isBlockSchema(
64
- schema: AppBlockSchema | SectionSchema | ThemeBlockSchema | undefined,
65
- ): schema is ThemeBlockSchema {
66
- return schema?.type === ThemeSchemaType.Block;
67
- }
68
-
69
- export function isSectionSchema(
70
- schema: AppBlockSchema | SectionSchema | ThemeBlockSchema | undefined,
71
- ): schema is SectionSchema {
72
- return schema?.type === ThemeSchemaType.Section;
73
- }
74
-
75
- async function toValidSchema<T>(
76
- uri: string,
77
- schemaNode: LiquidRawTag | Error,
78
- parsed: any | Error,
79
- isValidSchema: IsValidSchema | undefined,
80
- ): Promise<T | Error> {
81
- if (!isValidSchema) return new Error('No JSON validator provided');
82
- if (schemaNode instanceof Error) return parsed;
83
- if (await isValidSchema(uri, schemaNode.body.value)) {
84
- return parsed as T;
85
- } else {
86
- return new Error('Invalid schema');
87
- }
88
- }
89
-
90
- export async function toBlockSchema(
91
- uri: UriString,
92
- liquidAst: LiquidHtmlNode | Error,
93
- isValidSchema: IsValidSchema | undefined,
94
- isStrict: boolean,
95
- ): Promise<ThemeBlockSchema> {
96
- const name = path.basename(uri, '.liquid');
97
- const schemaNode = await toSchemaNode(liquidAst);
98
- const staticBlockDefs = await toStaticBlockDefs(liquidAst);
99
- const parsed = toParsed(schemaNode, isStrict);
100
- const ast = toAst(schemaNode);
101
-
102
- return {
103
- type: ThemeSchemaType.Block,
104
- validSchema: await toValidSchema<ThemeBlock.Schema>(uri, schemaNode, parsed, isValidSchema),
105
- offset: schemaNode instanceof Error ? 0 : schemaNode.blockStartPosition.end,
106
- name,
107
- parsed,
108
- ast,
109
- value: schemaNode instanceof Error ? '' : schemaNode.body.value,
110
- staticBlockDefs,
111
- };
112
- }
113
-
114
- // Coincidentally very similar right now... but could be different in the future
115
- // given there might be a plan to support folders in the blocks folder.
116
- // e.g. if we start having a stricter "parsed" object / ways to get settings.
117
- export async function toSectionSchema(
118
- uri: UriString,
119
- liquidAst: LiquidHtmlNode | Error,
120
- isValidSchema: IsValidSchema | undefined,
121
- isStrict: boolean,
122
- ): Promise<SectionSchema> {
123
- const name = path.basename(uri, '.liquid');
124
- const schemaNode = await toSchemaNode(liquidAst);
125
- const staticBlockDefs = await toStaticBlockDefs(liquidAst);
126
- const parsed = toParsed(schemaNode, isStrict);
127
- const ast = toAst(schemaNode);
128
-
129
- return {
130
- type: ThemeSchemaType.Section,
131
- validSchema: await toValidSchema(uri, schemaNode, parsed, isValidSchema),
132
- offset: schemaNode instanceof Error ? 0 : schemaNode.blockStartPosition.end,
133
- name,
134
- parsed,
135
- ast,
136
- value: schemaNode instanceof Error ? '' : schemaNode.body.value,
137
- staticBlockDefs,
138
- };
139
- }
140
-
141
- // validSchema not implemented yet. You can still `visit` the ast.
142
- export async function toAppBlockSchema(
143
- uri: UriString,
144
- liquidAst: LiquidHtmlNode | Error,
145
- isStrict: boolean,
146
- ): Promise<AppBlockSchema> {
147
- const name = path.basename(uri, '.liquid');
148
- const schemaNode = await toSchemaNode(liquidAst);
149
- const parsed = toParsed(schemaNode, isStrict);
150
- const ast = toAst(schemaNode);
151
-
152
- return {
153
- type: ThemeSchemaType.AppBlock,
154
- offset: schemaNode instanceof Error ? 0 : schemaNode.blockStartPosition.end,
155
- name,
156
- parsed,
157
- ast,
158
- value: schemaNode instanceof Error ? '' : schemaNode.body.value,
159
- };
160
- }
161
-
162
- async function toSchemaNode(ast: LiquidHtmlNode | Error): Promise<Error | LiquidRawTag> {
163
- if (ast instanceof Error) return ast;
164
- return (
165
- (
166
- await visit<SourceCodeType.LiquidHtml, LiquidRawTag>(ast, {
167
- async LiquidRawTag(node) {
168
- if (node.name === 'schema') {
169
- return node;
170
- }
171
- },
172
- })
173
- )[0] ?? new Error('No schema tag found')
174
- );
175
- }
176
-
177
- async function toStaticBlockDefs(ast: LiquidHtmlNode | Error): Promise<StaticBlockDef[]> {
178
- if (ast instanceof Error) return [];
179
- return await visit<SourceCodeType.LiquidHtml, StaticBlockDef>(ast, {
180
- async LiquidTag(node) {
181
- if (node.name !== NamedTags.content_for) return;
182
- if (typeof node.markup === 'string') return;
183
- const contentForMarkup: ContentForMarkup = node.markup;
184
- if (contentForMarkup.contentForType.value !== 'block') return;
185
- const type = contentForMarkup.args.find((x) => x.name === 'type');
186
- const id = contentForMarkup.args.find((x) => x.name === 'id');
187
- if (!type || !id) return;
188
- if (type.value.type !== NodeTypes.String) return;
189
- if (id.value.type !== NodeTypes.String) return;
190
-
191
- return {
192
- type: type.value.value,
193
- id: id.value.value,
194
- };
195
- },
196
- });
197
- }
198
-
199
- export function getSchema(context: Context<SourceCodeType.LiquidHtml, Schema>) {
200
- const name = path.basename(context.file.uri, '.liquid');
201
- switch (true) {
202
- case isBlock(context.file.uri):
203
- return context.getBlockSchema?.(name);
204
- case isSection(context.file.uri):
205
- return context.getSectionSchema?.(name);
206
- default:
207
- return undefined;
208
- }
209
- }
210
-
211
- export async function getSchemaFromJSON(context: Context<SourceCodeType.JSON, Schema>) {
212
- const originalSource = context.file.source;
213
-
214
- const parsed = parseJSON(originalSource);
215
- const ast = toJSONAST(originalSource);
216
-
217
- return {
218
- parsed,
219
- ast,
220
- };
221
- }
222
-
223
- function toParsed(schemaNode: LiquidRawTag | Error, isStrict: boolean): any | Error {
224
- if (schemaNode instanceof Error) return schemaNode;
225
- return parseJSON(schemaNode.body.value, undefined, isStrict);
226
- }
227
-
228
- function toAst(schemaNode: LiquidRawTag | Error): SourceCode<SourceCodeType.JSON>['ast'] | Error {
229
- if (schemaNode instanceof Error) return schemaNode;
230
- return toJSONAST(schemaNode.body.value);
231
- }
@@ -1,5 +0,0 @@
1
- export { ThemeBlock } from './theme-block';
2
- export { Section } from './section';
3
- export { Setting } from './setting';
4
- export { Preset } from './preset';
5
- export { Template } from './template';
@@ -1,52 +0,0 @@
1
- import { Setting } from './setting';
2
-
3
- export declare namespace Preset {
4
- // Preset definitions
5
- export type Preset =
6
- | {
7
- name: string;
8
- settings?: Setting.Values;
9
- blocks?: PresetBlockHash;
10
- block_order?: string[];
11
- }
12
- | {
13
- name: string;
14
- settings?: Setting.Values;
15
- blocks?: PresetBlockForArray[];
16
- }
17
- | { name: string; settings?: Setting.Values };
18
-
19
- // Reuse the block preset types from ThemeBlock namespace
20
- export type PresetBlockBase = {
21
- type: string;
22
- settings?: Setting.Values;
23
- static?: boolean;
24
- blocks?: PresetBlockHash | PresetBlockForArray[];
25
- };
26
-
27
- export type PresetBlockForHash = PresetBlockBase & {
28
- block_order?: string[];
29
- };
30
-
31
- export type PresetBlockForArray = PresetBlockBase & {
32
- id?: string;
33
- };
34
-
35
- // Hash format for blocks
36
- export type PresetBlockHash = {
37
- [id: string]: PresetBlockForHash;
38
- };
39
-
40
- /** Base type for presets */
41
- export type BlockPresetBase = {
42
- /** Refers to a block type. blocks/{type}.liquid */
43
- type: string;
44
- settings?: Setting.Values;
45
- };
46
-
47
- // prettier-ignore
48
- export type Block = (
49
- | PresetBlockForHash
50
- | PresetBlockForArray
51
- );
52
- }