@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.
- package/CHANGELOG.md +16 -0
- package/README.md +4 -4
- package/dist/AugmentedPlatformOSDocset.d.ts +11 -0
- package/dist/AugmentedPlatformOSDocset.js +81 -0
- package/dist/AugmentedPlatformOSDocset.js.map +1 -0
- package/dist/JSONValidator.js +1 -1
- package/dist/JSONValidator.js.map +1 -1
- package/dist/checks/deprecated-filter/index.js +4 -41
- package/dist/checks/deprecated-filter/index.js.map +1 -1
- package/dist/checks/deprecated-tag/index.js +21 -22
- package/dist/checks/deprecated-tag/index.js.map +1 -1
- package/dist/checks/duplicate-function-arguments/index.js +1 -1
- package/dist/checks/duplicate-function-arguments/index.js.map +1 -1
- package/dist/checks/duplicate-render-partial-arguments/index.js +1 -1
- package/dist/checks/duplicate-render-partial-arguments/index.js.map +1 -1
- package/dist/checks/graphql/index.js +1 -1
- package/dist/checks/graphql/index.js.map +1 -1
- package/dist/checks/graphql-variables/index.js +4 -0
- package/dist/checks/graphql-variables/index.js.map +1 -1
- package/dist/checks/img-width-and-height/index.js +1 -1
- package/dist/checks/img-width-and-height/index.js.map +1 -1
- package/dist/checks/index.d.ts +3 -3
- package/dist/checks/index.js +4 -79
- package/dist/checks/index.js.map +1 -1
- package/dist/checks/json-syntax-error/index.js +1 -1
- package/dist/checks/json-syntax-error/index.js.map +1 -1
- package/dist/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.js +1 -1
- package/dist/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.js.map +1 -1
- package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.d.ts +19 -0
- package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.js +79 -0
- package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.js.map +1 -0
- package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.d.ts +3 -0
- package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.js +32 -0
- package/dist/checks/liquid-html-syntax-error/checks/UnknownTag.js.map +1 -0
- package/dist/checks/liquid-html-syntax-error/index.js +23 -5
- package/dist/checks/liquid-html-syntax-error/index.js.map +1 -1
- package/dist/checks/matching-translations/index.d.ts +2 -2
- package/dist/checks/matching-translations/index.js +114 -90
- package/dist/checks/matching-translations/index.js.map +1 -1
- package/dist/checks/metadata-params/index.js +6 -3
- package/dist/checks/metadata-params/index.js.map +1 -1
- package/dist/checks/missing-asset/index.js +1 -1
- package/dist/checks/missing-asset/index.js.map +1 -1
- package/dist/checks/missing-partial/index.d.ts +6 -0
- package/dist/checks/missing-partial/index.js +70 -0
- package/dist/checks/missing-partial/index.js.map +1 -0
- package/dist/checks/orphaned-partial/index.js +4 -4
- package/dist/checks/orphaned-partial/index.js.map +1 -1
- package/dist/checks/parser-blocking-script/index.js +10 -36
- package/dist/checks/parser-blocking-script/index.js.map +1 -1
- package/dist/checks/parser-blocking-script/suggestions.d.ts +1 -2
- package/dist/checks/parser-blocking-script/suggestions.js +1 -11
- package/dist/checks/parser-blocking-script/suggestions.js.map +1 -1
- package/dist/checks/reserved-doc-param-names/index.js +6 -5
- package/dist/checks/reserved-doc-param-names/index.js.map +1 -1
- package/dist/checks/translation-key-exists/index.js +1 -1
- package/dist/checks/translation-key-exists/index.js.map +1 -1
- package/dist/checks/unclosed-html-element/index.js +5 -1
- package/dist/checks/unclosed-html-element/index.js.map +1 -1
- package/dist/checks/undefined-object/index.js +13 -31
- package/dist/checks/undefined-object/index.js.map +1 -1
- package/dist/checks/unique-doc-param-names/index.js +1 -1
- package/dist/checks/unique-doc-param-names/index.js.map +1 -1
- package/dist/checks/unknown-filter/index.js +3 -3
- package/dist/checks/unknown-filter/index.js.map +1 -1
- package/dist/checks/unknown-property/index.js +1 -1
- package/dist/checks/unknown-property/index.js.map +1 -1
- package/dist/checks/unrecognized-render-partial-arguments/index.js +2 -2
- package/dist/checks/unrecognized-render-partial-arguments/index.js.map +1 -1
- package/dist/checks/unused-assign/index.js +1 -1
- package/dist/checks/unused-assign/index.js.map +1 -1
- package/dist/checks/unused-doc-param/index.js +1 -1
- package/dist/checks/unused-doc-param/index.js.map +1 -1
- package/dist/checks/utils.js +1 -1
- package/dist/checks/utils.js.map +1 -1
- package/dist/checks/valid-content-for-arguments/index.js +1 -1
- package/dist/checks/valid-content-for-arguments/index.js.map +1 -1
- package/dist/checks/valid-doc-param-types/index.js +4 -4
- package/dist/checks/valid-doc-param-types/index.js.map +1 -1
- package/dist/checks/valid-html-translation/index.d.ts +2 -2
- package/dist/checks/valid-html-translation/index.js +4 -4
- package/dist/checks/valid-html-translation/index.js.map +1 -1
- package/dist/checks/valid-json/index.js +1 -1
- package/dist/checks/valid-json/index.js.map +1 -1
- package/dist/checks/valid-render-partial-argument-types/index.js +2 -2
- package/dist/checks/valid-render-partial-argument-types/index.js.map +1 -1
- package/dist/checks/variable-name/index.js +1 -1
- package/dist/checks/variable-name/index.js.map +1 -1
- package/dist/context-utils.d.ts +18 -7
- package/dist/context-utils.js +68 -109
- package/dist/context-utils.js.map +1 -1
- package/dist/disabled-checks/index.js +4 -2
- package/dist/disabled-checks/index.js.map +1 -1
- package/dist/doc-generator/DocBlockGenerator.d.ts +16 -0
- package/dist/doc-generator/DocBlockGenerator.js +464 -0
- package/dist/doc-generator/DocBlockGenerator.js.map +1 -0
- package/dist/doc-generator/index.d.ts +1 -0
- package/dist/doc-generator/index.js +6 -0
- package/dist/doc-generator/index.js.map +1 -0
- package/dist/find-root.d.ts +7 -10
- package/dist/find-root.js +10 -17
- package/dist/find-root.js.map +1 -1
- package/dist/fixes/autofix.d.ts +4 -4
- package/dist/fixes/autofix.js +2 -2
- package/dist/fixes/autofix.js.map +1 -1
- package/dist/fixes/correctors/index.js +4 -0
- package/dist/fixes/correctors/index.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +50 -17
- package/dist/index.js.map +1 -1
- package/dist/jsonc/parse.d.ts +1 -1
- package/dist/jsonc/parse.js +1 -1
- package/dist/liquid-doc/arguments.d.ts +7 -8
- package/dist/liquid-doc/arguments.js +28 -29
- package/dist/liquid-doc/arguments.js.map +1 -1
- package/dist/liquid-doc/liquidDoc.d.ts +1 -1
- package/dist/liquid-doc/liquidDoc.js.map +1 -1
- package/dist/liquid-doc/utils.d.ts +3 -3
- package/dist/liquid-doc/utils.js +14 -3
- package/dist/liquid-doc/utils.js.map +1 -1
- package/dist/path.d.ts +1 -0
- package/dist/path.js +16 -1
- package/dist/path.js.map +1 -1
- package/{src/test/MockTheme.ts → dist/test/MockApp.d.ts} +2 -3
- package/dist/test/MockApp.js +16 -0
- package/dist/test/MockApp.js.map +1 -0
- package/dist/test/MockFileSystem.d.ts +3 -3
- package/dist/test/MockFileSystem.js +6 -6
- package/dist/test/MockFileSystem.js.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +1 -1
- package/dist/test/index.js.map +1 -1
- package/dist/test/test-helper.d.ts +10 -9
- package/dist/test/test-helper.js +15 -106
- package/dist/test/test-helper.js.map +1 -1
- package/dist/to-schema.d.ts +1 -1
- package/dist/to-source-code.d.ts +3 -2
- package/dist/to-source-code.js +20 -0
- package/dist/to-source-code.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/platformos-liquid-docs.d.ts +128 -0
- package/dist/types/platformos-liquid-docs.js +3 -0
- package/dist/types/platformos-liquid-docs.js.map +1 -0
- package/dist/types/schemas/index.d.ts +0 -2
- package/dist/types/schemas/index.js.map +1 -1
- package/dist/types.d.ts +26 -67
- package/dist/types.js +3 -5
- package/dist/types.js.map +1 -1
- package/dist/utils/block.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/yaml/parse.d.ts +5 -0
- package/dist/yaml/parse.js +94 -0
- package/dist/yaml/parse.js.map +1 -0
- package/package.json +4 -3
- package/src/{AugmentedThemeDocset.spec.ts → AugmentedPlatformOSDocset.spec.ts} +47 -34
- package/src/AugmentedPlatformOSDocset.ts +89 -0
- package/src/JSONValidator.ts +1 -1
- package/src/checks/deprecated-filter/index.spec.ts +76 -248
- package/src/checks/deprecated-filter/index.ts +5 -53
- package/src/checks/deprecated-tag/index.spec.ts +85 -34
- package/src/checks/deprecated-tag/index.ts +27 -22
- package/src/checks/duplicate-function-arguments/index.ts +1 -1
- package/src/checks/duplicate-render-partial-arguments/index.spec.ts +12 -12
- package/src/checks/duplicate-render-partial-arguments/index.ts +1 -1
- package/src/checks/graphql/index.ts +1 -1
- package/src/checks/graphql-variables/index.spec.ts +95 -0
- package/src/checks/graphql-variables/index.ts +4 -0
- package/src/checks/img-width-and-height/index.ts +2 -2
- package/src/checks/index.ts +11 -80
- package/src/checks/invalid-hash-assign-target/index.spec.ts +27 -27
- package/src/checks/json-syntax-error/index.ts +2 -2
- package/src/checks/liquid-html-syntax-error/checks/InvalidBooleanExpression.spec.ts +0 -11
- package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.spec.ts +1 -2
- package/src/checks/liquid-html-syntax-error/checks/InvalidLoopArguments.ts +2 -2
- package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.spec.ts +259 -0
- package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.ts +89 -0
- package/src/checks/liquid-html-syntax-error/checks/UnknownTag.spec.ts +293 -0
- package/src/checks/liquid-html-syntax-error/checks/UnknownTag.ts +43 -0
- package/src/checks/liquid-html-syntax-error/index.spec.ts +1 -6
- package/src/checks/liquid-html-syntax-error/index.ts +26 -5
- package/src/checks/matching-translations/index.spec.ts +187 -354
- package/src/checks/matching-translations/index.ts +117 -107
- package/src/checks/metadata-params/index.ts +6 -8
- package/src/checks/missing-asset/index.ts +1 -1
- package/src/checks/{missing-template → missing-partial}/index.spec.ts +6 -6
- package/src/checks/{missing-template → missing-partial}/index.ts +12 -26
- package/src/checks/orphaned-partial/index.ts +3 -3
- package/src/checks/parser-blocking-script/index.spec.ts +0 -118
- package/src/checks/parser-blocking-script/index.ts +3 -33
- package/src/checks/parser-blocking-script/suggestions.ts +1 -28
- package/src/checks/translation-key-exists/index.ts +1 -1
- package/src/checks/unclosed-html-element/index.ts +5 -1
- package/src/checks/undefined-object/index.spec.ts +32 -111
- package/src/checks/undefined-object/index.ts +15 -34
- package/src/checks/unique-doc-param-names/index.ts +1 -1
- package/src/checks/unknown-filter/index.spec.ts +2 -2
- package/src/checks/unknown-filter/index.ts +3 -3
- package/src/checks/unknown-property/index.ts +1 -1
- package/src/checks/unrecognized-render-partial-arguments/index.spec.ts +5 -5
- package/src/checks/unrecognized-render-partial-arguments/index.ts +2 -5
- package/src/checks/unused-assign/index.spec.ts +0 -30
- package/src/checks/unused-assign/index.ts +2 -2
- package/src/checks/unused-doc-param/index.ts +1 -1
- package/src/checks/utils.ts +1 -1
- package/src/checks/valid-doc-param-types/index.ts +4 -4
- package/src/checks/valid-html-translation/index.spec.ts +42 -32
- package/src/checks/valid-html-translation/index.ts +7 -7
- package/src/checks/valid-json/index.ts +2 -2
- package/src/checks/valid-render-partial-argument-types/index.spec.ts +13 -13
- package/src/checks/valid-render-partial-argument-types/index.ts +2 -5
- package/src/checks/variable-name/index.ts +1 -1
- package/src/context-utils.spec.ts +49 -77
- package/src/context-utils.ts +81 -129
- package/src/disabled-checks/index.spec.ts +26 -26
- package/src/disabled-checks/index.ts +2 -2
- package/src/disabled-checks/test-checks.ts +4 -4
- package/src/find-root.ts +12 -22
- package/src/fixes/autofix.spec.ts +2 -2
- package/src/fixes/autofix.ts +4 -4
- package/src/fixes/correctors/index.ts +4 -0
- package/src/ignore.spec.ts +4 -5
- package/src/index.ts +51 -21
- package/src/jsonc/parse.ts +1 -1
- package/src/liquid-doc/arguments.spec.ts +19 -45
- package/src/liquid-doc/arguments.ts +35 -42
- package/src/liquid-doc/liquidDoc.spec.ts +1 -1
- package/src/liquid-doc/liquidDoc.ts +1 -2
- package/src/liquid-doc/utils.ts +17 -8
- package/src/path.ts +16 -0
- package/src/test/MockApp.ts +17 -0
- package/src/test/MockFileSystem.spec.ts +10 -11
- package/src/test/MockFileSystem.ts +6 -6
- package/src/test/contain-offense.spec.ts +11 -3
- package/src/test/index.ts +1 -1
- package/src/test/test-helper.ts +43 -145
- package/src/to-source-code.ts +20 -1
- package/src/types/{theme-liquid-docs.ts → platformos-liquid-docs.ts} +8 -13
- package/src/types.ts +29 -92
- package/src/utils/index.ts +0 -1
- package/src/visitor.spec.ts +2 -2
- package/src/yaml/parse.ts +111 -0
- package/src/AugmentedThemeDocset.ts +0 -137
- package/src/checks/app-block-missing-schema/index.spec.ts +0 -121
- package/src/checks/app-block-missing-schema/index.ts +0 -46
- package/src/checks/app-block-valid-tags/index.spec.ts +0 -96
- package/src/checks/app-block-valid-tags/index.ts +0 -54
- package/src/checks/asset-preload/index.spec.ts +0 -78
- package/src/checks/asset-preload/index.ts +0 -65
- package/src/checks/asset-size-app-block-css/index.spec.ts +0 -88
- package/src/checks/asset-size-app-block-css/index.ts +0 -78
- package/src/checks/asset-size-app-block-javascript/index.spec.ts +0 -66
- package/src/checks/asset-size-app-block-javascript/index.ts +0 -78
- package/src/checks/asset-size-css/index.spec.ts +0 -166
- package/src/checks/asset-size-css/index.ts +0 -160
- package/src/checks/asset-size-javascript/index.spec.ts +0 -184
- package/src/checks/asset-size-javascript/index.ts +0 -144
- package/src/checks/block-id-usage/index.spec.ts +0 -76
- package/src/checks/block-id-usage/index.ts +0 -72
- package/src/checks/cdn-preconnect/index.spec.ts +0 -40
- package/src/checks/cdn-preconnect/index.ts +0 -43
- package/src/checks/content-for-header-modification/index.spec.ts +0 -65
- package/src/checks/content-for-header-modification/index.ts +0 -72
- package/src/checks/deprecate-bgsizes/index.spec.ts +0 -41
- package/src/checks/deprecate-bgsizes/index.ts +0 -49
- package/src/checks/deprecate-lazysizes/index.spec.ts +0 -26
- package/src/checks/deprecate-lazysizes/index.ts +0 -58
- package/src/checks/deprecated-filter/fixes.ts +0 -264
- package/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts +0 -1343
- package/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts +0 -613
- package/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts +0 -284
- package/src/checks/deprecated-fonts-on-settings-schema/index.spec.ts +0 -102
- package/src/checks/deprecated-fonts-on-settings-schema/index.ts +0 -66
- package/src/checks/duplicate-content-for-arguments/index.spec.ts +0 -98
- package/src/checks/duplicate-content-for-arguments/index.ts +0 -43
- package/src/checks/empty-block-content/index.spec.ts +0 -117
- package/src/checks/empty-block-content/index.ts +0 -60
- package/src/checks/hardcoded-routes/index.spec.ts +0 -58
- package/src/checks/hardcoded-routes/index.ts +0 -100
- package/src/checks/json-missing-block/index.spec.ts +0 -435
- package/src/checks/json-missing-block/index.ts +0 -56
- package/src/checks/json-missing-block/missing-block-utils.ts +0 -147
- package/src/checks/liquid-free-settings/index.spec.ts +0 -180
- package/src/checks/liquid-free-settings/index.ts +0 -79
- package/src/checks/missing-content-for-arguments/index.spec.ts +0 -144
- package/src/checks/missing-content-for-arguments/index.ts +0 -46
- package/src/checks/pagination-size/index.spec.ts +0 -158
- package/src/checks/pagination-size/index.ts +0 -104
- package/src/checks/remote-asset/index.spec.ts +0 -280
- package/src/checks/remote-asset/index.ts +0 -238
- package/src/checks/reserved-doc-param-names/index.spec.ts +0 -62
- package/src/checks/reserved-doc-param-names/index.ts +0 -57
- package/src/checks/schema-presets-block-order/index.spec.ts +0 -344
- package/src/checks/schema-presets-block-order/index.ts +0 -154
- package/src/checks/schema-presets-static-blocks/index.spec.ts +0 -145
- package/src/checks/schema-presets-static-blocks/index.ts +0 -126
- package/src/checks/static-stylesheet-and-javascript-tags/index.spec.ts +0 -257
- package/src/checks/static-stylesheet-and-javascript-tags/index.ts +0 -48
- package/src/checks/unique-settings-id/index.spec.ts +0 -24
- package/src/checks/unique-settings-id/index.ts +0 -84
- package/src/checks/unique-settings-id/test-data.ts +0 -1191
- package/src/checks/unique-static-block-id/index.spec.ts +0 -55
- package/src/checks/unique-static-block-id/index.ts +0 -60
- package/src/checks/unrecognized-content-for-arguments/index.spec.ts +0 -145
- package/src/checks/unrecognized-content-for-arguments/index.ts +0 -55
- package/src/checks/valid-block-target/index.spec.ts +0 -1396
- package/src/checks/valid-block-target/index.ts +0 -142
- package/src/checks/valid-content-for-argument-types/index.spec.ts +0 -382
- package/src/checks/valid-content-for-argument-types/index.ts +0 -42
- package/src/checks/valid-content-for-arguments/index.spec.ts +0 -107
- package/src/checks/valid-content-for-arguments/index.ts +0 -98
- package/src/checks/valid-local-blocks/index.spec.ts +0 -286
- package/src/checks/valid-local-blocks/index.ts +0 -100
- package/src/checks/valid-local-blocks/valid-block-utils.ts +0 -97
- package/src/checks/valid-schema/index.spec.ts +0 -174
- package/src/checks/valid-schema/index.ts +0 -41
- package/src/checks/valid-schema-name/index.spec.ts +0 -112
- package/src/checks/valid-schema-name/index.ts +0 -75
- package/src/checks/valid-settings-key/index.spec.ts +0 -321
- package/src/checks/valid-settings-key/index.ts +0 -144
- package/src/checks/valid-static-block-type/index.spec.ts +0 -38
- package/src/checks/valid-static-block-type/index.ts +0 -58
- package/src/checks/valid-visible-if/index.spec.ts +0 -619
- package/src/checks/valid-visible-if/index.ts +0 -184
- package/src/checks/valid-visible-if/visible-if-utils.ts +0 -158
- package/src/tags/content-for.ts +0 -25
- package/src/to-schema.ts +0 -231
- package/src/types/schemas/index.ts +0 -5
- package/src/types/schemas/preset.ts +0 -52
- package/src/types/schemas/section.ts +0 -86
- package/src/types/schemas/setting.ts +0 -320
- package/src/types/schemas/template.ts +0 -34
- package/src/types/schemas/theme-block.ts +0 -34
- package/src/types/theme-schemas.ts +0 -80
- package/src/utils/block.ts +0 -300
- package/src/utils/markup.ts +0 -10
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { vi, expect, describe, it, afterEach } from 'vitest';
|
|
2
|
-
import { AssetSizeCSS } 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: AssetSizeCSS', () => {
|
|
16
|
-
const extensionFiles: MockTheme = {
|
|
17
|
-
'assets/theme.css': '* { color: green !important; }',
|
|
18
|
-
'templates/index.liquid': `
|
|
19
|
-
<html>
|
|
20
|
-
<head>
|
|
21
|
-
<link href="{{ 'theme.css' | asset_url }}" rel="stylesheet">
|
|
22
|
-
</head>
|
|
23
|
-
</html>
|
|
24
|
-
`,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const httpTest: MockTheme = {
|
|
28
|
-
'templates/index.liquid': `
|
|
29
|
-
<html>
|
|
30
|
-
<head>
|
|
31
|
-
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
32
|
-
</head>
|
|
33
|
-
</html>
|
|
34
|
-
`,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
afterEach(() => {
|
|
38
|
-
vi.clearAllMocks();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should not report any offenses if CSS is smaller than threshold', async () => {
|
|
42
|
-
const offenses = await check(extensionFiles, [AssetSizeCSS]);
|
|
43
|
-
|
|
44
|
-
expect(offenses).toHaveLength(0);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should report an offense if CSS is larger than threshold', async () => {
|
|
48
|
-
const offenses = await check(
|
|
49
|
-
extensionFiles,
|
|
50
|
-
[AssetSizeCSS],
|
|
51
|
-
{},
|
|
52
|
-
{
|
|
53
|
-
AssetSizeCSS: {
|
|
54
|
-
enabled: true,
|
|
55
|
-
thresholdInBytes: 1,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
expect(offenses).toHaveLength(1);
|
|
61
|
-
expect(offenses[0]).toMatchObject({
|
|
62
|
-
message: 'The CSS file size exceeds the threshold of 1 bytes',
|
|
63
|
-
uri: 'file:///templates/index.liquid',
|
|
64
|
-
start: { index: 51 },
|
|
65
|
-
end: { index: 80 },
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should report a warning when the CSS file size exceeds the threshold', async () => {
|
|
70
|
-
vi.mocked(hasRemoteAssetSizeExceededThreshold).mockReturnValue(Promise.resolve(true));
|
|
71
|
-
const offenses = await check(
|
|
72
|
-
httpTest,
|
|
73
|
-
[AssetSizeCSS],
|
|
74
|
-
{},
|
|
75
|
-
{
|
|
76
|
-
AssetSizeCSS: {
|
|
77
|
-
enabled: true,
|
|
78
|
-
thresholdInBytes: 1,
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
expect(offenses).toHaveLength(1);
|
|
84
|
-
expect(offenses[0]).toMatchObject({
|
|
85
|
-
message: 'The CSS file size exceeds the threshold of 1 bytes',
|
|
86
|
-
uri: 'file:///templates/index.liquid',
|
|
87
|
-
start: { index: 51 },
|
|
88
|
-
end: { index: 122 },
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should not report any offenses if CSS is smaller than threshold 2', async () => {
|
|
93
|
-
vi.mocked(hasRemoteAssetSizeExceededThreshold).mockResolvedValue(false);
|
|
94
|
-
const extensionFiles: MockTheme = {
|
|
95
|
-
'assets/theme.css': 'console.log("hello world");',
|
|
96
|
-
'templates/index.liquid': `
|
|
97
|
-
<html>
|
|
98
|
-
<head>
|
|
99
|
-
{{ 'theme.css' | asset_url | stylesheet_tag }}
|
|
100
|
-
{{ "https://example.com" | stylesheet_tag }}
|
|
101
|
-
</head>
|
|
102
|
-
</html>
|
|
103
|
-
`,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const offenses = await check(extensionFiles, [AssetSizeCSS]);
|
|
107
|
-
|
|
108
|
-
expect(offenses).toHaveLength(0);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should report an offense if CSS is larger than threshold 2', async () => {
|
|
112
|
-
vi.mocked(hasRemoteAssetSizeExceededThreshold).mockResolvedValue(true);
|
|
113
|
-
const extensionFiles: MockTheme = {
|
|
114
|
-
'assets/theme.css': 'console.log("hello world");',
|
|
115
|
-
'templates/index.liquid': `
|
|
116
|
-
<html>
|
|
117
|
-
<head>
|
|
118
|
-
{{ 'theme.css' | asset_url | stylesheet_tag }}
|
|
119
|
-
{{ "https://example.com" | stylesheet_tag }}
|
|
120
|
-
</head>
|
|
121
|
-
</html>
|
|
122
|
-
`,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const offenses = await check(
|
|
126
|
-
extensionFiles,
|
|
127
|
-
[AssetSizeCSS],
|
|
128
|
-
{},
|
|
129
|
-
{
|
|
130
|
-
AssetSizeCSS: {
|
|
131
|
-
enabled: true,
|
|
132
|
-
thresholdInBytes: 2,
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
expect(offenses).toHaveLength(2);
|
|
138
|
-
expect(offenses[0]).toMatchObject({
|
|
139
|
-
message: 'The CSS file size exceeds the threshold of 2 bytes',
|
|
140
|
-
uri: 'file:///templates/index.liquid',
|
|
141
|
-
start: { index: 48 },
|
|
142
|
-
end: { index: 89 },
|
|
143
|
-
});
|
|
144
|
-
expect(offenses[1]).toMatchObject({
|
|
145
|
-
message: 'The CSS file size exceeds the threshold of 2 bytes',
|
|
146
|
-
uri: 'file:///templates/index.liquid',
|
|
147
|
-
start: { index: 107 },
|
|
148
|
-
end: { index: 128 },
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should not report any offenses if there is no stylesheet', async () => {
|
|
153
|
-
const extensionFiles: MockTheme = {
|
|
154
|
-
'templates/index.liquid': `
|
|
155
|
-
<html>
|
|
156
|
-
<head>
|
|
157
|
-
</head>
|
|
158
|
-
</html>
|
|
159
|
-
`,
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const offenses = await check(extensionFiles, [AssetSizeCSS]);
|
|
163
|
-
|
|
164
|
-
expect(offenses).toHaveLength(0);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LiquidHtmlNode,
|
|
3
|
-
LiquidString,
|
|
4
|
-
LiquidVariable,
|
|
5
|
-
LiquidVariableOutput,
|
|
6
|
-
NodeTypes,
|
|
7
|
-
TextNode,
|
|
8
|
-
} from '@platformos/liquid-html-parser';
|
|
9
|
-
import { LiquidCheckDefinition, SchemaProp, Severity, SourceCodeType } from '../../types';
|
|
10
|
-
import { last } from '../../utils';
|
|
11
|
-
import {
|
|
12
|
-
hasRemoteAssetSizeExceededThreshold,
|
|
13
|
-
hasLocalAssetSizeExceededThreshold,
|
|
14
|
-
} from '../../utils/file-utils';
|
|
15
|
-
import {
|
|
16
|
-
ValuedHtmlAttribute,
|
|
17
|
-
isAttr,
|
|
18
|
-
isNodeOfType,
|
|
19
|
-
isValuedHtmlAttribute,
|
|
20
|
-
valueIncludes,
|
|
21
|
-
} from '../utils';
|
|
22
|
-
|
|
23
|
-
const schema = {
|
|
24
|
-
thresholdInBytes: SchemaProp.number(100000),
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function isTextNode(node: LiquidHtmlNode): node is TextNode {
|
|
28
|
-
return node.type === NodeTypes.TextNode;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function isLiquidVariableOutput(node: LiquidHtmlNode): node is LiquidVariableOutput {
|
|
32
|
-
return node.type === NodeTypes.LiquidVariableOutput;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function isLiquidVariable(node: LiquidHtmlNode | string): node is LiquidVariable {
|
|
36
|
-
return typeof node !== 'string' && node.type === NodeTypes.LiquidVariable;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function isString(node: LiquidHtmlNode): node is LiquidString {
|
|
40
|
-
return node.type === NodeTypes.String;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const AssetSizeCSS: LiquidCheckDefinition<typeof schema> = {
|
|
44
|
-
meta: {
|
|
45
|
-
code: 'AssetSizeCSS',
|
|
46
|
-
aliases: ['AssetSizeCSSStylesheetTag'],
|
|
47
|
-
name: 'Prevent Large CSS bundles',
|
|
48
|
-
docs: {
|
|
49
|
-
description: 'This check is aimed at preventing large CSS bundles for speed.',
|
|
50
|
-
url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/asset-size-css',
|
|
51
|
-
recommended: false,
|
|
52
|
-
},
|
|
53
|
-
type: SourceCodeType.LiquidHtml,
|
|
54
|
-
severity: Severity.ERROR,
|
|
55
|
-
schema,
|
|
56
|
-
targets: [],
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
create(context) {
|
|
60
|
-
if (!context.fileSize) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const thresholdInBytes = context.settings.thresholdInBytes;
|
|
65
|
-
|
|
66
|
-
async function checkRemoteAssetSize(url: string, position: { start: number; end: number }) {
|
|
67
|
-
if (await hasRemoteAssetSizeExceededThreshold(url, thresholdInBytes)) {
|
|
68
|
-
context.report({
|
|
69
|
-
message: `The CSS file size exceeds the threshold of ${thresholdInBytes} bytes`,
|
|
70
|
-
startIndex: position.start,
|
|
71
|
-
endIndex: position.end,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function checkThemeAssetSize(srcValue: string, position: { start: number; end: number }) {
|
|
77
|
-
if (
|
|
78
|
-
await hasLocalAssetSizeExceededThreshold(context, `assets/${srcValue}`, thresholdInBytes)
|
|
79
|
-
) {
|
|
80
|
-
context.report({
|
|
81
|
-
message: `The CSS file size exceeds the threshold of ${thresholdInBytes} bytes`,
|
|
82
|
-
startIndex: position.start,
|
|
83
|
-
endIndex: position.end,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
async HtmlVoidElement(node) {
|
|
90
|
-
if (node.name !== 'link') return;
|
|
91
|
-
|
|
92
|
-
const relIsStylesheet = node.attributes
|
|
93
|
-
.filter(isValuedHtmlAttribute)
|
|
94
|
-
.find((attr) => isAttr(attr, 'rel') && valueIncludes(attr, 'stylesheet'));
|
|
95
|
-
if (!relIsStylesheet) return;
|
|
96
|
-
|
|
97
|
-
const href: ValuedHtmlAttribute | undefined = node.attributes
|
|
98
|
-
.filter(isValuedHtmlAttribute)
|
|
99
|
-
.find((attr) => isAttr(attr, 'href'));
|
|
100
|
-
if (!href) return;
|
|
101
|
-
if (href.value.length !== 1) return;
|
|
102
|
-
|
|
103
|
-
/* This ensures that the link entered is a text and not anything else like http//..{}
|
|
104
|
-
This also checks if the value starts with 'http://', 'https://' or '//' to ensure its a valid link. */
|
|
105
|
-
if (isTextNode(href.value[0]) && /(https?:)?\/\//.test(href.value[0].value)) {
|
|
106
|
-
const url = href.value[0].value;
|
|
107
|
-
await checkRemoteAssetSize(url, href.attributePosition);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/* This code checks if we have a link with a liquid variable
|
|
111
|
-
and that its a string with one filter, `asset_url`. This is done to ensure our .css link is
|
|
112
|
-
entered with a 'asset_url' to produce valid output. */
|
|
113
|
-
if (
|
|
114
|
-
isLiquidVariableOutput(href.value[0]) &&
|
|
115
|
-
isLiquidVariable(href.value[0].markup) &&
|
|
116
|
-
isString(href.value[0].markup.expression) &&
|
|
117
|
-
href.value[0].markup.filters.length === 1 &&
|
|
118
|
-
href.value[0].markup.filters[0].name === 'asset_url'
|
|
119
|
-
) {
|
|
120
|
-
const assetName = href.value[0].markup.expression.value;
|
|
121
|
-
await checkThemeAssetSize(assetName, href.attributePosition);
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
async LiquidFilter(node, ancestors) {
|
|
126
|
-
if (node.name !== 'stylesheet_tag') return;
|
|
127
|
-
|
|
128
|
-
const liquidVariableParent = last(ancestors);
|
|
129
|
-
|
|
130
|
-
if (!liquidVariableParent || !isNodeOfType(NodeTypes.LiquidVariable, liquidVariableParent))
|
|
131
|
-
return;
|
|
132
|
-
|
|
133
|
-
if (liquidVariableParent.expression.type !== NodeTypes.String) return;
|
|
134
|
-
|
|
135
|
-
/* This code ensures we have a liquid variable with 1 expression, 1 filter, and that it is a valid http link.
|
|
136
|
-
This is done to ensure a valid http link is entered with 1 filter being the `stylesheet_tag` for valid output. */
|
|
137
|
-
if (
|
|
138
|
-
liquidVariableParent.expression.value[0].length == 1 &&
|
|
139
|
-
liquidVariableParent.filters.length == 1 &&
|
|
140
|
-
/(https?:)?\/\//.test(liquidVariableParent.expression.value)
|
|
141
|
-
) {
|
|
142
|
-
const url = liquidVariableParent.expression.value;
|
|
143
|
-
await checkRemoteAssetSize(url, liquidVariableParent.expression.position);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* This code ensures we have a liquid variable with 1 expression, 2 filters being asset_url and stylesheet_tag
|
|
147
|
-
This is done to ensure a .css file has the 'asset_url' and 'stylesheet_tag' to produce the appropriate output. */
|
|
148
|
-
if (
|
|
149
|
-
liquidVariableParent.expression.value[0].length == 1 &&
|
|
150
|
-
liquidVariableParent.filters.length == 2 &&
|
|
151
|
-
liquidVariableParent.filters[0].name === 'asset_url' &&
|
|
152
|
-
liquidVariableParent.filters[1].name === 'stylesheet_tag'
|
|
153
|
-
) {
|
|
154
|
-
const css = liquidVariableParent.expression.value;
|
|
155
|
-
await checkThemeAssetSize(css, liquidVariableParent.position);
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
},
|
|
160
|
-
};
|
|
@@ -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
|
-
};
|