@platformos/platformos-check-common 0.0.6 → 0.0.8

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