@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,184 +0,0 @@
1
- import { expect, describe, it, afterEach, vi } from 'vitest';
2
- import { AssetSizeJavaScript } from '.';
3
- import { check, MockTheme } from '../../test';
4
- import { SchemaProp } from '../../types';
5
- import { hasRemoteAssetSizeExceededThreshold } from '../../utils/file-utils';
6
-
7
- vi.mock('../../utils/file-utils', async (importOriginal) => {
8
- const actual: any = await importOriginal();
9
- return {
10
- ...actual,
11
- hasRemoteAssetSizeExceededThreshold: vi.fn(),
12
- };
13
- });
14
-
15
- describe('Module: AssetSizeJavaScript', () => {
16
- const theme: MockTheme = {
17
- 'assets/theme.js': "console.log('hello world'); console.log('Oh. Hi Mark!')",
18
- 'templates/index.liquid': `
19
- <html>
20
- <head>
21
- <script src="{{ 'theme.js' | asset_url }}" defer></script>
22
- </head>
23
- </html>
24
- `,
25
- };
26
-
27
- const httpTest: MockTheme = {
28
- 'templates/index.liquid': `
29
- <html>
30
- <head>
31
- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" defer></script>
32
- </head>
33
- </html>
34
- `,
35
- };
36
-
37
- afterEach(() => {
38
- vi.clearAllMocks();
39
- });
40
-
41
- it('should not find file size for invalid URLs', async () => {
42
- const invalidUrls = [
43
- 'https://{{ settings.url }}',
44
- "{{ 'this_file_does_not_exist.js' | asset_url }}",
45
- '{% if on_product %}https://hello.world{% else %}https://hi.world{% endif %}',
46
- ];
47
-
48
- for (const url of invalidUrls) {
49
- const offenses = await check(
50
- { 'templates/index.liquid': `<script src="${url}" defer></script>` },
51
- [AssetSizeJavaScript],
52
- );
53
- expect(offenses).toHaveLength(0);
54
- }
55
- });
56
-
57
- it('should report a warning when the JavaScript http request exceeds the threshold', async () => {
58
- vi.mocked(hasRemoteAssetSizeExceededThreshold).mockReturnValue(Promise.resolve(true));
59
- const offenses = await check(
60
- httpTest,
61
- [AssetSizeJavaScript],
62
- {},
63
- {
64
- AssetSizeJavaScript: {
65
- enabled: true,
66
- thresholdInBytes: 1,
67
- },
68
- },
69
- );
70
-
71
- expect(offenses).toHaveLength(1);
72
- expect(offenses[0]).toMatchObject({
73
- message:
74
- 'JavaScript on every page load exceeds compressed size threshold (1 Bytes), consider using the import on interaction pattern.',
75
- uri: 'file:///templates/index.liquid',
76
- start: { index: 52 },
77
- end: { index: 121 },
78
- });
79
- });
80
-
81
- it('should not report any offenses if JavaScript is smaller than threshold', async () => {
82
- const offenses = await check(theme, [AssetSizeJavaScript]);
83
-
84
- expect(offenses).toHaveLength(0);
85
- });
86
-
87
- it('should report an offense if JavaScript is larger than threshold', async () => {
88
- const offenses = await check(
89
- theme,
90
- [AssetSizeJavaScript],
91
- {},
92
- {
93
- AssetSizeJavaScript: {
94
- enabled: true,
95
- thresholdInBytes: 2,
96
- },
97
- },
98
- );
99
-
100
- expect(offenses).toHaveLength(1);
101
- expect(offenses[0]).toMatchObject({
102
- message:
103
- 'JavaScript on every page load exceeds compressed size threshold (2 Bytes), consider using the import on interaction pattern.',
104
- uri: 'file:///templates/index.liquid',
105
- start: { index: 52 },
106
- end: { index: 80 },
107
- });
108
- });
109
-
110
- it('should not report any offenses for inline JavaScript', async () => {
111
- const inlineTheme: MockTheme = {
112
- 'templates/index.liquid': `
113
- <html>
114
- <head>
115
- <script>
116
- console.log('hello world');
117
- </script>
118
- </head>
119
- </html>
120
- `,
121
- };
122
-
123
- const offenses = await check(inlineTheme, [AssetSizeJavaScript]);
124
-
125
- expect(offenses).toHaveLength(0);
126
- });
127
-
128
- it('should report an offense if JS is larger than threshold', async () => {
129
- const extensionFiles: MockTheme = {
130
- 'assets/theme.js': 'console.log("hello world");',
131
- 'templates/index.liquid': `
132
- <html>
133
- <head>
134
- {{ 'theme.js' | asset_url | script_tag }}
135
- {{ "https://example.com" | script_tag }}
136
- </head>
137
- </html>
138
- `,
139
- };
140
-
141
- const offenses = await check(
142
- extensionFiles,
143
- [AssetSizeJavaScript],
144
- {},
145
- {
146
- AssetSizeJavaScript: {
147
- enabled: true,
148
- thresholdInBytes: 2,
149
- },
150
- },
151
- );
152
-
153
- expect(offenses).toHaveLength(2);
154
- expect(offenses[0]).toMatchObject({
155
- message:
156
- 'JavaScript on every page load exceeds compressed size threshold (2 Bytes), consider using the import on interaction pattern.',
157
- uri: 'file:///templates/index.liquid',
158
- start: { index: 48 },
159
- end: { index: 84 },
160
- });
161
- expect(offenses[1]).toMatchObject({
162
- message:
163
- 'JavaScript on every page load exceeds compressed size threshold (2 Bytes), consider using the import on interaction pattern.',
164
- uri: 'file:///templates/index.liquid',
165
- start: { index: 102 },
166
- end: { index: 123 },
167
- });
168
- });
169
-
170
- it('should not report any offenses if there is no javascript', async () => {
171
- const extensionFiles: MockTheme = {
172
- 'templates/index.liquid': `
173
- <html>
174
- <head>
175
- </head>
176
- </html>
177
- `,
178
- };
179
-
180
- const offenses = await check(extensionFiles, [AssetSizeJavaScript]);
181
-
182
- expect(offenses).toHaveLength(0);
183
- });
184
- });
@@ -1,144 +0,0 @@
1
- import {
2
- LiquidString,
3
- LiquidVariable,
4
- LiquidVariableOutput,
5
- NodeTypes,
6
- TextNode,
7
- } from '@platformos/liquid-html-parser';
8
- import {
9
- LiquidCheckDefinition,
10
- LiquidHtmlNode,
11
- SchemaProp,
12
- Severity,
13
- SourceCodeType,
14
- } from '../../types';
15
- import { last } from '../../utils';
16
- import {
17
- hasRemoteAssetSizeExceededThreshold,
18
- hasLocalAssetSizeExceededThreshold,
19
- } from '../../utils/file-utils';
20
- import { ValuedHtmlAttribute, isAttr, isNodeOfType, isValuedHtmlAttribute } from '../utils';
21
-
22
- const schema = {
23
- thresholdInBytes: SchemaProp.number(10000),
24
- };
25
-
26
- function isTextNode(node: LiquidHtmlNode): node is TextNode {
27
- return node.type === NodeTypes.TextNode;
28
- }
29
-
30
- function isLiquidVariableOutput(node: LiquidHtmlNode): node is LiquidVariableOutput {
31
- return node.type === NodeTypes.LiquidVariableOutput;
32
- }
33
-
34
- function isLiquidVariable(node: LiquidHtmlNode | string): node is LiquidVariable {
35
- return typeof node !== 'string' && node.type === NodeTypes.LiquidVariable;
36
- }
37
-
38
- function isString(node: LiquidHtmlNode): node is LiquidString {
39
- return node.type === NodeTypes.String;
40
- }
41
-
42
- export const AssetSizeJavaScript: LiquidCheckDefinition<typeof schema> = {
43
- meta: {
44
- code: 'AssetSizeJavaScript',
45
- name: 'Prevent Large JavaScript bundles',
46
- docs: {
47
- description: 'This check is aimed at preventing large JavaScript bundles for speed.',
48
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/asset-size-javascript',
49
- recommended: false,
50
- },
51
- type: SourceCodeType.LiquidHtml,
52
- severity: Severity.ERROR,
53
- schema,
54
- targets: [],
55
- },
56
-
57
- create(context) {
58
- if (!context.fileSize) {
59
- return {};
60
- }
61
-
62
- const thresholdInBytes = context.settings.thresholdInBytes;
63
-
64
- async function checkRemoteAssetSize(url: string, position: { start: number; end: number }) {
65
- if (await hasRemoteAssetSizeExceededThreshold(url, thresholdInBytes)) {
66
- context.report({
67
- message: `JavaScript on every page load exceeds compressed size threshold (${thresholdInBytes} Bytes), consider using the import on interaction pattern.`,
68
- startIndex: position.start,
69
- endIndex: position.end,
70
- });
71
- }
72
- }
73
-
74
- async function checkThemeAssetSize(srcValue: string, position: { start: number; end: number }) {
75
- if (
76
- await hasLocalAssetSizeExceededThreshold(context, `assets/${srcValue}`, thresholdInBytes)
77
- ) {
78
- context.report({
79
- message: `JavaScript on every page load exceeds compressed size threshold (${thresholdInBytes} Bytes), consider using the import on interaction pattern.`,
80
- startIndex: position.start,
81
- endIndex: position.end,
82
- });
83
- }
84
- }
85
-
86
- return {
87
- async HtmlRawNode(node) {
88
- if (node.name !== 'script') return;
89
-
90
- const src: ValuedHtmlAttribute | undefined = node.attributes
91
- .filter(isValuedHtmlAttribute)
92
- .find((attr) => isAttr(attr, 'src'));
93
- if (!src) return;
94
- if (src.value.length !== 1) return;
95
-
96
- if (isTextNode(src.value[0]) && /(https?:)?\/\//.test(src.value[0].value)) {
97
- const url = src.value[0].value;
98
- await checkRemoteAssetSize(url, src.attributePosition);
99
- }
100
-
101
- if (
102
- isLiquidVariableOutput(src.value[0]) &&
103
- isLiquidVariable(src.value[0].markup) &&
104
- isString(src.value[0].markup.expression) &&
105
- src.value[0].markup.filters.length === 1 &&
106
- src.value[0].markup.filters[0].name === 'asset_url'
107
- ) {
108
- const assetName = src.value[0].markup.expression.value;
109
- await checkThemeAssetSize(assetName, src.attributePosition);
110
- }
111
- },
112
-
113
- async LiquidFilter(node, ancestors) {
114
- if (node.name !== 'script_tag') return;
115
-
116
- const liquidVariableParent = last(ancestors);
117
-
118
- if (!liquidVariableParent || !isNodeOfType(NodeTypes.LiquidVariable, liquidVariableParent))
119
- return;
120
-
121
- if (liquidVariableParent.expression.type !== NodeTypes.String) return;
122
-
123
- if (
124
- liquidVariableParent.expression.value[0].length == 1 &&
125
- liquidVariableParent.filters.length == 1 &&
126
- /(https?:)?\/\//.test(liquidVariableParent.expression.value)
127
- ) {
128
- const url = liquidVariableParent.expression.value;
129
- await checkRemoteAssetSize(url, liquidVariableParent.expression.position);
130
- }
131
-
132
- if (
133
- liquidVariableParent.expression.value[0].length == 1 &&
134
- liquidVariableParent.filters.length == 2 &&
135
- liquidVariableParent.filters[0].name === 'asset_url' &&
136
- liquidVariableParent.filters[1].name === 'script_tag'
137
- ) {
138
- const js = liquidVariableParent.expression.value;
139
- await checkThemeAssetSize(js, liquidVariableParent.position);
140
- }
141
- },
142
- };
143
- },
144
- };
@@ -1,76 +0,0 @@
1
- import { expect, describe, it } from 'vitest';
2
- import { highlightedOffenses, runLiquidCheck } from '../../test';
3
- import { BlockIdUsage } from './index';
4
-
5
- describe('Module: ContentForHeaderModification', () => {
6
- it('reports offense with the use of block.id in an if liquid tag', async () => {
7
- const sourceCode = `
8
- {% if block.id == '123' %}
9
- No bueno
10
- {% endif %}
11
- `;
12
-
13
- const offenses = await runLiquidCheck(BlockIdUsage, sourceCode);
14
- expect(offenses).toHaveLength(1);
15
- expect(offenses[0].message).toEqual(
16
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
17
- );
18
-
19
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
20
- expect(highlights).toEqual(["block.id == '123'"]);
21
- });
22
-
23
- it('reports offense with the use of block.id in an elseif liquid tag', async () => {
24
- const sourceCode = `
25
- {% if potato == '123' %}
26
- No bueno
27
- {% elsif block.id == '123' %}
28
- No bueno
29
- {% endif %}
30
- `;
31
-
32
- const offenses = await runLiquidCheck(BlockIdUsage, sourceCode);
33
- expect(offenses).toHaveLength(1);
34
- expect(offenses[0].message).toEqual(
35
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
36
- );
37
-
38
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
39
- expect(highlights).toEqual(["block.id == '123'"]);
40
- });
41
-
42
- it('reports offense with the use of block.id in an unless liquid tag', async () => {
43
- const sourceCode = `
44
- {% unless block.id == '123' %}
45
- No bueno
46
- {% endunless %}
47
- `;
48
-
49
- const offenses = await runLiquidCheck(BlockIdUsage, sourceCode);
50
- expect(offenses).toHaveLength(1);
51
- expect(offenses[0].message).toEqual(
52
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
53
- );
54
-
55
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
56
- expect(highlights).toEqual(["block.id == '123'"]);
57
- });
58
-
59
- it('reports offense with the use of block.id in a case liquid tag', async () => {
60
- const sourceCode = `
61
- {% case block.id %}
62
- {% when '123' %}
63
- No bueno
64
- {% endcase %}
65
- `;
66
-
67
- const offenses = await runLiquidCheck(BlockIdUsage, sourceCode);
68
- expect(offenses).toHaveLength(1);
69
- expect(offenses[0].message).toEqual(
70
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
71
- );
72
-
73
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
74
- expect(highlights).toEqual(['block.id']);
75
- });
76
- });
@@ -1,72 +0,0 @@
1
- import {
2
- Position,
3
- LiquidTagNode,
4
- NodeTypes,
5
- LiquidVariableLookup,
6
- } from '@platformos/liquid-html-parser';
7
- import { Context, LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';
8
-
9
- export const BlockIdUsage: LiquidCheckDefinition = {
10
- meta: {
11
- code: 'BlockIdUsage',
12
- name: 'Do not rely on `block.id` in if/else/unless/case',
13
- docs: {
14
- description:
15
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
16
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/block-id-usage',
17
- recommended: true,
18
- },
19
- type: SourceCodeType.LiquidHtml,
20
- severity: Severity.WARNING,
21
- schema: {},
22
- targets: [],
23
- },
24
-
25
- create(context) {
26
- return {
27
- // BAD: {% if block.id == "123" %}
28
- // BAD: {% if block.id == some_variable %}
29
- // BAD: {% if block[id] == "id" or block.id %}
30
- // FINE: <div data-block-id="{{ block.id }}">
31
- // FINE: document.querySelector(`[data-block-id="${block.id}"]`)
32
- async Comparison(node, ancesors) {
33
- if (
34
- node.comparator === '==' &&
35
- node.left.type === NodeTypes.VariableLookup &&
36
- isUsingBlockId(node.left)
37
- ) {
38
- reportWarning(context, node.position);
39
- }
40
- },
41
-
42
- // BAD {% case block.id %}
43
- async VariableLookup(node, ancestors) {
44
- const parentNode = ancestors.at(-1);
45
- if (parentNode?.type === NodeTypes.LiquidTag && parentNode.name === 'case') {
46
- if (isUsingBlockId(node)) {
47
- reportWarning(context, node.position);
48
- }
49
- }
50
- },
51
- };
52
- },
53
- };
54
-
55
- function isUsingBlockId(node: LiquidVariableLookup) {
56
- return (
57
- node.type == NodeTypes.VariableLookup &&
58
- node.name === 'block' &&
59
- node.lookups[0] &&
60
- node.lookups[0].type === NodeTypes.String &&
61
- node.lookups[0].value === 'id'
62
- );
63
- }
64
-
65
- function reportWarning(context: any, position: Position) {
66
- context.report({
67
- message:
68
- 'The ID is dynamically generated by Shopify and is subject to change. You should avoid relying on a literal value of this ID.',
69
- startIndex: position.start,
70
- endIndex: position.end,
71
- });
72
- }
@@ -1,40 +0,0 @@
1
- import { expect, describe, it } from 'vitest';
2
- import { runLiquidCheck } from '../../test';
3
- import { CdnPreconnect } from './index';
4
-
5
- describe('Module: CdnPreconnect', () => {
6
- it('should report preconnect to cdn.shopify.com', async () => {
7
- const sourceCode = `
8
- <link rel="preconnect" href="https://cdn.shopify.com/"/>
9
- `;
10
-
11
- const offenses = await runLiquidCheck(CdnPreconnect, sourceCode);
12
- expect(offenses).to.have.length(1);
13
- expect(offenses[0].message).to.equal(
14
- 'Preconnecting to cdn.shopify.com is unnecessary and can lead to worse performance',
15
- );
16
- });
17
-
18
- it('should report crossorigin preconnect to cdn.shopify.com', async () => {
19
- const sourceCode = `
20
- <link rel="preconnect" href="https://cdn.shopify.com/" crossorigin/>
21
- `;
22
-
23
- const offenses = await runLiquidCheck(CdnPreconnect, sourceCode);
24
- expect(offenses).to.have.length(1);
25
- expect(offenses[0].message).to.equal(
26
- 'Preconnecting to cdn.shopify.com is unnecessary and can lead to worse performance',
27
- );
28
- });
29
-
30
- it('should not report other link types', async () => {
31
- const sourceCode = `
32
- <link rel="preload" href="https://example.com/foo.css" as="style"/>
33
- <link rel="stylesheet" href="https://example.com/bar.css"/>
34
- <link rel="icon"/>
35
- `;
36
-
37
- const offenses = await runLiquidCheck(CdnPreconnect, sourceCode);
38
- expect(offenses).to.have.length(0);
39
- });
40
- });
@@ -1,43 +0,0 @@
1
- import { Severity, SourceCodeType, LiquidCheckDefinition } from '../../types';
2
- import { isAttr, isValuedHtmlAttribute, valueIncludes } from '../utils';
3
-
4
- export const CdnPreconnect: LiquidCheckDefinition = {
5
- meta: {
6
- code: 'CdnPreconnect',
7
- name: 'CDN Preconnect',
8
- docs: {
9
- description: "This check is aimed at signaling the redundant preconnect to Shopify's CDN",
10
- recommended: true,
11
- url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/cdn-preconnect',
12
- },
13
- type: SourceCodeType.LiquidHtml,
14
- severity: Severity.ERROR,
15
- schema: {},
16
- targets: [],
17
- },
18
-
19
- create(context) {
20
- return {
21
- async HtmlVoidElement(node) {
22
- if (node.name !== 'link') return;
23
-
24
- const isPreconnect = node.attributes
25
- .filter(isValuedHtmlAttribute)
26
- .some((attr) => isAttr(attr, 'rel') && valueIncludes(attr, 'preconnect'));
27
- if (!isPreconnect) return;
28
-
29
- const isShopifyCdn = node.attributes
30
- .filter(isValuedHtmlAttribute)
31
- .some((attr) => isAttr(attr, 'href') && valueIncludes(attr, '.+cdn.shopify.com.+'));
32
- if (!isShopifyCdn) return;
33
-
34
- context.report({
35
- message:
36
- 'Preconnecting to cdn.shopify.com is unnecessary and can lead to worse performance',
37
- startIndex: node.position.start,
38
- endIndex: node.position.end,
39
- });
40
- },
41
- };
42
- },
43
- };
@@ -1,65 +0,0 @@
1
- import { expect, describe, it } from 'vitest';
2
- import { highlightedOffenses, runLiquidCheck } from '../../test';
3
- import { ContentForHeaderModification } from './index';
4
-
5
- describe('Module: ContentForHeaderModification', () => {
6
- it('reports a offense with the use of a filter', async () => {
7
- const sourceCode = "{{ content_for_header | split: ',' }}";
8
-
9
- const offenses = await runLiquidCheck(ContentForHeaderModification, sourceCode);
10
- expect(offenses).toHaveLength(1);
11
- expect(offenses[0].message).toEqual('Do not rely on the content of `content_for_header`');
12
-
13
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
14
- });
15
-
16
- it('reports offense with the use of assign', async () => {
17
- const sourceCode = '{% assign x = content_for_header %}';
18
-
19
- const offenses = await runLiquidCheck(ContentForHeaderModification, sourceCode);
20
- expect(offenses).toHaveLength(1);
21
- expect(offenses[0].message).toEqual('Do not rely on the content of `content_for_header`');
22
-
23
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
24
- expect(highlights).toEqual(['{% assign x = content_for_header %}']);
25
- });
26
-
27
- it('reports offense with the use of capture', async () => {
28
- const sourceCode = `
29
- {% capture x %}
30
- {{ content_for_header }}
31
- {% endcapture %}
32
- `;
33
-
34
- const offenses = await runLiquidCheck(ContentForHeaderModification, sourceCode);
35
- expect(offenses).toHaveLength(1);
36
- expect(offenses[0].message).toEqual('Do not rely on the content of `content_for_header`');
37
-
38
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
39
- expect(highlights).toEqual(['{{ content_for_header }}']);
40
- });
41
-
42
- it('reports offense with the use of echo', async () => {
43
- const sourceCode = `
44
- {% liquid
45
- echo content_for_header | split: ','
46
- %}
47
- `;
48
-
49
- const offenses = await runLiquidCheck(ContentForHeaderModification, sourceCode);
50
- expect(offenses).toHaveLength(1);
51
- expect(offenses[0].message).toEqual('Do not rely on the content of `content_for_header`');
52
-
53
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
54
- expect(highlights).toEqual(["echo content_for_header | split: ','"]);
55
- });
56
-
57
- it('does not report an offense with normal use', async () => {
58
- const sourceCode = '{{ content_for_header }}';
59
-
60
- const offenses = await runLiquidCheck(ContentForHeaderModification, sourceCode);
61
- expect(offenses).toHaveLength(0);
62
- const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
63
- expect(highlights).toHaveLength(0);
64
- });
65
- });