@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.
- package/CHANGELOG.md +16 -0
- 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/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/index.js +2 -2
- 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 +20 -31
- 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 +7 -30
- 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 +2 -7
- package/dist/context-utils.js +39 -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/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 +4 -5
- package/dist/index.js +34 -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 +20 -28
- 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 +1 -1
- package/dist/liquid-doc/utils.js +4 -3
- package/dist/liquid-doc/utils.js.map +1 -1
- package/dist/path.d.ts +1 -0
- package/dist/path.js +5 -1
- package/dist/path.js.map +1 -1
- package/dist/test/MockApp.d.ts +16 -0
- 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-source-code.d.ts +4 -3
- 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 +18 -67
- package/dist/types.js +3 -5
- package/dist/types.js.map +1 -1
- package/dist/utils/file-utils.js +1 -2
- package/dist/utils/file-utils.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 +9 -9
- 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.ts +1 -1
- package/src/checks/graphql/index.ts +1 -1
- package/src/checks/img-width-and-height/index.ts +1 -1
- package/src/checks/index.ts +11 -80
- package/src/checks/invalid-hash-assign-target/index.spec.ts +14 -14
- package/src/checks/json-syntax-error/index.ts +1 -1
- 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/index.spec.ts +1 -6
- package/src/checks/liquid-html-syntax-error/index.ts +2 -2
- package/src/checks/matching-translations/index.spec.ts +89 -346
- package/src/checks/matching-translations/index.ts +24 -35
- package/src/checks/metadata-params/index.ts +5 -7
- 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 +6 -20
- 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 +3 -109
- package/src/checks/undefined-object/index.ts +8 -33
- 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 +1 -1
- 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 +1 -1
- 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 +39 -128
- package/src/disabled-checks/index.spec.ts +35 -0
- package/src/disabled-checks/index.ts +4 -2
- 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 +0 -1
- package/src/index.ts +33 -21
- package/src/jsonc/parse.ts +1 -1
- package/src/liquid-doc/arguments.spec.ts +19 -45
- package/src/liquid-doc/arguments.ts +26 -39
- package/src/liquid-doc/liquidDoc.ts +1 -2
- package/src/liquid-doc/utils.ts +4 -3
- package/src/path.ts +1 -0
- package/src/test/{MockTheme.ts → MockApp.ts} +1 -1
- package/src/test/MockFileSystem.ts +9 -6
- package/src/test/index.ts +1 -1
- package/src/test/test-helper.ts +29 -127
- package/src/to-source-code.ts +20 -1
- package/src/types/{theme-liquid-docs.ts → platformos-liquid-docs.ts} +8 -13
- package/src/types/schemas/index.ts +0 -2
- package/src/types.ts +21 -92
- package/src/utils/file-utils.ts +0 -1
- package/src/utils/index.ts +0 -1
- 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/section.ts +0 -86
- 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,72 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LiquidTag,
|
|
3
|
-
LiquidTagAssign,
|
|
4
|
-
LiquidTagCapture,
|
|
5
|
-
LiquidTagEcho,
|
|
6
|
-
NodeTypes,
|
|
7
|
-
Position,
|
|
8
|
-
} from '@platformos/liquid-html-parser';
|
|
9
|
-
import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';
|
|
10
|
-
import { isNodeOfType } from '../utils';
|
|
11
|
-
|
|
12
|
-
function isLiquidTagAssign(node: LiquidTag): node is LiquidTagAssign {
|
|
13
|
-
return node.name === 'assign' && typeof node.markup !== 'string';
|
|
14
|
-
}
|
|
15
|
-
function isLiquidTagCapture(node: LiquidTag): node is LiquidTagCapture {
|
|
16
|
-
return node.name === 'capture' && typeof node.markup !== 'string';
|
|
17
|
-
}
|
|
18
|
-
function isLiquidTagEcho(node: LiquidTag): node is LiquidTagEcho {
|
|
19
|
-
return node.name === 'echo' && typeof node.markup !== 'string';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const ContentForHeaderModification: LiquidCheckDefinition = {
|
|
23
|
-
meta: {
|
|
24
|
-
code: 'ContentForHeaderModification',
|
|
25
|
-
name: 'Do not depend on the content of content_for_header',
|
|
26
|
-
docs: {
|
|
27
|
-
description:
|
|
28
|
-
'Do not rely on the content of content_for_header as it might change in the future, which could cause your Liquid code behavior to change.',
|
|
29
|
-
url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/content-for-header-modification',
|
|
30
|
-
recommended: true,
|
|
31
|
-
},
|
|
32
|
-
type: SourceCodeType.LiquidHtml,
|
|
33
|
-
severity: Severity.ERROR,
|
|
34
|
-
schema: {},
|
|
35
|
-
targets: [],
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
create(context) {
|
|
39
|
-
function checkContentForHeader(node: any, position: Position) {
|
|
40
|
-
if (isNodeOfType(NodeTypes.VariableLookup, node) && node.name === 'content_for_header') {
|
|
41
|
-
context.report({
|
|
42
|
-
message: 'Do not rely on the content of `content_for_header`',
|
|
43
|
-
startIndex: position.start,
|
|
44
|
-
endIndex: position.end,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
async LiquidTag(node) {
|
|
51
|
-
if (isLiquidTagAssign(node)) {
|
|
52
|
-
checkContentForHeader(node.markup.value.expression, node.position);
|
|
53
|
-
} else if (isLiquidTagEcho(node)) {
|
|
54
|
-
checkContentForHeader(node.markup.expression, node.position);
|
|
55
|
-
} else if (isLiquidTagCapture(node) && node.children) {
|
|
56
|
-
for (const child of node.children) {
|
|
57
|
-
if (child.type === NodeTypes.LiquidVariableOutput && typeof child.markup !== 'string') {
|
|
58
|
-
checkContentForHeader(child.markup.expression, child.position);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
async LiquidVariableOutput(node) {
|
|
64
|
-
if (typeof node.markup === 'string') return;
|
|
65
|
-
|
|
66
|
-
if (node.markup.filters.length) {
|
|
67
|
-
checkContentForHeader(node.markup.expression, node.position);
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { expect, describe, it } from 'vitest';
|
|
2
|
-
import { DeprecateBgsizes } from './index';
|
|
3
|
-
import { runLiquidCheck, highlightedOffenses } from '../../test';
|
|
4
|
-
|
|
5
|
-
describe('Module: DeprecateBgsizes', () => {
|
|
6
|
-
it('should report offenses for deprecated attributes', async () => {
|
|
7
|
-
const sourceCode = `
|
|
8
|
-
<div class="lazyload" data-bgset="image.jpg"></div>
|
|
9
|
-
<div class="lazyload" data-bgset="image2.jpg"></div>
|
|
10
|
-
`;
|
|
11
|
-
|
|
12
|
-
const offenses = await runLiquidCheck(DeprecateBgsizes, sourceCode);
|
|
13
|
-
expect(offenses).to.have.length(4);
|
|
14
|
-
|
|
15
|
-
const errorMessages = offenses.map((offense) => offense.message);
|
|
16
|
-
expect(errorMessages).to.deep.equal([
|
|
17
|
-
'Use the native loading="lazy" attribute instead of lazysizes',
|
|
18
|
-
'Use the CSS imageset attribute instead of data-bgset',
|
|
19
|
-
'Use the native loading="lazy" attribute instead of lazysizes',
|
|
20
|
-
'Use the CSS imageset attribute instead of data-bgset',
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
|
|
24
|
-
expect(highlights).to.deep.equal([
|
|
25
|
-
'lazyload',
|
|
26
|
-
'data-bgset="image.jpg"',
|
|
27
|
-
'lazyload',
|
|
28
|
-
'data-bgset="image2.jpg"',
|
|
29
|
-
]);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should not report offenses for non-deprecated attributes', async () => {
|
|
33
|
-
const sourceCode = `
|
|
34
|
-
<div class="non-lazyload" data-non-bgset="image.jpg"></div>
|
|
35
|
-
<div class="non-lazyload" data-non-bgset="image2.jpg"></div>
|
|
36
|
-
`;
|
|
37
|
-
|
|
38
|
-
const offenses = await runLiquidCheck(DeprecateBgsizes, sourceCode);
|
|
39
|
-
expect(offenses).to.have.length(0);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Severity, SourceCodeType, LiquidCheckDefinition } from '../../types';
|
|
2
|
-
import { isAttr, isValuedHtmlAttribute, ValuedHtmlAttribute, valueIncludes } from '../utils';
|
|
3
|
-
|
|
4
|
-
export const DeprecateBgsizes: LiquidCheckDefinition = {
|
|
5
|
-
meta: {
|
|
6
|
-
code: 'DeprecateBgsizes',
|
|
7
|
-
name: 'Deprecate Bgsizes',
|
|
8
|
-
docs: {
|
|
9
|
-
description: 'This check is aimed at discouraging the use of the lazySizes bgset plugin.',
|
|
10
|
-
recommended: true,
|
|
11
|
-
url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/deprecate-bgsizes',
|
|
12
|
-
},
|
|
13
|
-
type: SourceCodeType.LiquidHtml,
|
|
14
|
-
severity: Severity.WARNING,
|
|
15
|
-
schema: {},
|
|
16
|
-
targets: [],
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
create(context) {
|
|
20
|
-
return {
|
|
21
|
-
async HtmlElement(node) {
|
|
22
|
-
const classAttributeWithLazyload: ValuedHtmlAttribute | undefined = node.attributes
|
|
23
|
-
.filter(isValuedHtmlAttribute)
|
|
24
|
-
.find((attr) => isAttr(attr, 'class') && valueIncludes(attr, 'lazyload'));
|
|
25
|
-
|
|
26
|
-
if (classAttributeWithLazyload) {
|
|
27
|
-
const attr = classAttributeWithLazyload;
|
|
28
|
-
context.report({
|
|
29
|
-
message: 'Use the native loading="lazy" attribute instead of lazysizes',
|
|
30
|
-
startIndex: attr.attributePosition.start,
|
|
31
|
-
endIndex: attr.attributePosition.end,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const dataBgsetAttr = node.attributes.find(
|
|
36
|
-
(attr) => isValuedHtmlAttribute(attr) && isAttr(attr, 'data-bgset'),
|
|
37
|
-
) as ValuedHtmlAttribute | undefined;
|
|
38
|
-
|
|
39
|
-
if (dataBgsetAttr) {
|
|
40
|
-
context.report({
|
|
41
|
-
message: 'Use the CSS imageset attribute instead of data-bgset',
|
|
42
|
-
startIndex: dataBgsetAttr.position.start,
|
|
43
|
-
endIndex: dataBgsetAttr.position.end,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { expect, describe, it } from 'vitest';
|
|
2
|
-
import { runLiquidCheck } from '../../test';
|
|
3
|
-
import { DeprecateLazysizes } from './index';
|
|
4
|
-
|
|
5
|
-
describe('Module: DeprecateLazysizes', () => {
|
|
6
|
-
it('should report data-srcset and data-sizes attributes', async () => {
|
|
7
|
-
const sourceCode = `
|
|
8
|
-
<img data-srcset="image.jpg" data-sizes="auto" class="lazyload" />
|
|
9
|
-
`;
|
|
10
|
-
|
|
11
|
-
const offenses = await runLiquidCheck(DeprecateLazysizes, sourceCode);
|
|
12
|
-
expect(offenses).to.have.length(1);
|
|
13
|
-
expect(offenses[0].message).to.equal(
|
|
14
|
-
'Use the native loading="lazy" attribute instead of lazysizes',
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should not report srcset and sizes attributes', async () => {
|
|
19
|
-
const sourceCode = `
|
|
20
|
-
<img srcset="image.jpg" sizes="auto" loading="lazy" />
|
|
21
|
-
`;
|
|
22
|
-
|
|
23
|
-
const offenses = await runLiquidCheck(DeprecateLazysizes, sourceCode);
|
|
24
|
-
expect(offenses).to.have.length(0);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Severity, SourceCodeType, LiquidCheckDefinition } from '../../types';
|
|
2
|
-
import {
|
|
3
|
-
ValuedHtmlAttribute,
|
|
4
|
-
isAttr,
|
|
5
|
-
isValuedHtmlAttribute,
|
|
6
|
-
isHtmlAttribute,
|
|
7
|
-
valueIncludes,
|
|
8
|
-
} from '../utils';
|
|
9
|
-
|
|
10
|
-
function showsLazysizesUsage(attr: ValuedHtmlAttribute) {
|
|
11
|
-
return isAttr(attr, 'data-srcset') || isAttr(attr, 'data-sizes');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const DeprecateLazysizes: LiquidCheckDefinition = {
|
|
15
|
-
meta: {
|
|
16
|
-
code: 'DeprecateLazysizes',
|
|
17
|
-
name: 'Deprecate Lazysizes',
|
|
18
|
-
docs: {
|
|
19
|
-
description:
|
|
20
|
-
'This check is aimed at discouraging the use of the lazysizes JavaScript library',
|
|
21
|
-
recommended: true,
|
|
22
|
-
url: 'https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/deprecate-lazysizes',
|
|
23
|
-
},
|
|
24
|
-
type: SourceCodeType.LiquidHtml,
|
|
25
|
-
severity: Severity.WARNING,
|
|
26
|
-
schema: {},
|
|
27
|
-
targets: [],
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
create(context) {
|
|
31
|
-
return {
|
|
32
|
-
async HtmlVoidElement(node) {
|
|
33
|
-
if (node.name !== 'img') return;
|
|
34
|
-
|
|
35
|
-
const attributes = node.attributes.filter(isHtmlAttribute);
|
|
36
|
-
const hasSrc = attributes.some((attr) => isAttr(attr, 'src'));
|
|
37
|
-
const hasNativeLoading = attributes.some((attr) => isAttr(attr, 'loading'));
|
|
38
|
-
if (hasSrc && hasNativeLoading) return;
|
|
39
|
-
|
|
40
|
-
const hasLazyloadClass = node.attributes
|
|
41
|
-
.filter(isValuedHtmlAttribute)
|
|
42
|
-
.some((attr) => isAttr(attr, 'class') && valueIncludes(attr, 'lazyload'));
|
|
43
|
-
if (!hasLazyloadClass) return;
|
|
44
|
-
|
|
45
|
-
const hasLazysizesAttribute = node.attributes
|
|
46
|
-
.filter(isValuedHtmlAttribute)
|
|
47
|
-
.some(showsLazysizesUsage);
|
|
48
|
-
if (!hasLazysizesAttribute) return;
|
|
49
|
-
|
|
50
|
-
context.report({
|
|
51
|
-
message: 'Use the native loading="lazy" attribute instead of lazysizes',
|
|
52
|
-
startIndex: node.position.start,
|
|
53
|
-
endIndex: node.position.end,
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
},
|
|
58
|
-
};
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LiquidArgument,
|
|
3
|
-
LiquidExpression,
|
|
4
|
-
LiquidFilter,
|
|
5
|
-
LiquidNamedArgument,
|
|
6
|
-
LiquidNumber,
|
|
7
|
-
LiquidString,
|
|
8
|
-
LiquidVariableLookup,
|
|
9
|
-
NodeTypes,
|
|
10
|
-
} from '@platformos/liquid-html-parser';
|
|
11
|
-
import { Fixer, LiquidHtmlSuggestion, SourceCodeType } from '../../types';
|
|
12
|
-
import { isNodeOfType } from '../utils';
|
|
13
|
-
|
|
14
|
-
type ImageSize = { width: number; height: number };
|
|
15
|
-
|
|
16
|
-
type Suggestion = LiquidHtmlSuggestion[] | undefined;
|
|
17
|
-
|
|
18
|
-
type FitlerParameters = Record<string, number | string | null>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Width and height values cannot exceed this maximum size.
|
|
22
|
-
*/
|
|
23
|
-
const MAX_SIZE = 5760;
|
|
24
|
-
|
|
25
|
-
const NAMED_SIZES: Record<string, number> = {
|
|
26
|
-
pico: 16,
|
|
27
|
-
icon: 32,
|
|
28
|
-
thumb: 50,
|
|
29
|
-
small: 100,
|
|
30
|
-
compact: 160,
|
|
31
|
-
medium: 240,
|
|
32
|
-
large: 480,
|
|
33
|
-
grande: 600,
|
|
34
|
-
original: 1024,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export function fixHexToRgba(node: LiquidFilter): Fixer<SourceCodeType.LiquidHtml> | undefined {
|
|
38
|
-
/**
|
|
39
|
-
* Cannot fix invalid usage.
|
|
40
|
-
*
|
|
41
|
-
* The `hex_to_rgba` filter is only valid with zero or one argument (`alpha`).
|
|
42
|
-
*/
|
|
43
|
-
if (node.args.length > 1) return;
|
|
44
|
-
|
|
45
|
-
const { start, end } = getFilterSourceStartAndEnd(node);
|
|
46
|
-
const alpha = getExpressionArgumentValue(node, 0);
|
|
47
|
-
|
|
48
|
-
let fixedFilter: string;
|
|
49
|
-
|
|
50
|
-
if (alpha) {
|
|
51
|
-
fixedFilter = ` color_to_rgb | color_modify: 'alpha', ${alpha}`;
|
|
52
|
-
} else {
|
|
53
|
-
fixedFilter = ' color_to_rgb';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return (corrector) => corrector.replace(start, end, fixedFilter);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function suggestImgTagFix(node: LiquidFilter): Suggestion {
|
|
60
|
-
const message = "Replace 'img_tag' with 'image_tag'.";
|
|
61
|
-
|
|
62
|
-
const alt = getExpressionArgumentValue(node, 0);
|
|
63
|
-
const cssClass = getExpressionArgumentValue(node, 1);
|
|
64
|
-
const sizeStr = getExpressionArgumentValue(node, 2);
|
|
65
|
-
|
|
66
|
-
const { width, height } = getImageSize(sizeStr, { width: -1, height: -1 });
|
|
67
|
-
const { start, end } = getFilterSourceStartAndEnd(node);
|
|
68
|
-
|
|
69
|
-
const imageUrlParameters: FitlerParameters = ensureImageValue({ width, height });
|
|
70
|
-
const imageTagParameters: FitlerParameters = {
|
|
71
|
-
width,
|
|
72
|
-
height,
|
|
73
|
-
alt: strValue(alt),
|
|
74
|
-
class: strValue(cssClass),
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const imageUrlFilter = buildFilterString('image_url', imageUrlParameters);
|
|
78
|
-
const imageTagFilter = buildFilterString('image_tag', imageTagParameters);
|
|
79
|
-
|
|
80
|
-
return [
|
|
81
|
-
{
|
|
82
|
-
message,
|
|
83
|
-
fix: (corrector) => {
|
|
84
|
-
const insert = `${imageUrlFilter} |${imageTagFilter}`;
|
|
85
|
-
corrector.replace(start, end, insert);
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function suggestImgUrlFix(node: LiquidFilter): Suggestion {
|
|
92
|
-
const message = "Replace 'img_url' with 'image_url'.";
|
|
93
|
-
|
|
94
|
-
const cropNode = getNamedArgumentNode(node, 'crop');
|
|
95
|
-
const formatNode = getNamedArgumentNode(node, 'format');
|
|
96
|
-
const scaleNode = getNamedArgumentNode(node, 'scale');
|
|
97
|
-
const sizeStr = getExpressionArgumentValue(node, 0);
|
|
98
|
-
const sizeNode = node.args.at(0);
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Cannot fix when 'scale' or 'size' node are variable lookups.
|
|
102
|
-
*/
|
|
103
|
-
if (isVariableLookup(scaleNode?.value) || isVariableLookup(sizeNode)) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const { width, height } = ensureImageValue(scaleImage(node, getImageSize(sizeStr)));
|
|
108
|
-
const { start, end } = getFilterSourceStartAndEnd(node);
|
|
109
|
-
|
|
110
|
-
const parameters: FitlerParameters = { width, height };
|
|
111
|
-
|
|
112
|
-
if (isStringLiteral(cropNode?.value)) {
|
|
113
|
-
parameters['crop'] = strValue(cropNode!.value.value);
|
|
114
|
-
}
|
|
115
|
-
if (isStringLiteral(formatNode?.value)) {
|
|
116
|
-
parameters['format'] = strValue(formatNode!.value.value);
|
|
117
|
-
}
|
|
118
|
-
if (isVariableLookup(formatNode?.value)) {
|
|
119
|
-
parameters['format'] = formatNode!.value.name;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return [
|
|
123
|
-
{
|
|
124
|
-
message,
|
|
125
|
-
fix: (corrector) => {
|
|
126
|
-
const insert = buildFilterString('image_url', parameters);
|
|
127
|
-
corrector.replace(start, end, insert);
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function suggestImageUrlFix(filter: string, node: LiquidFilter): Suggestion {
|
|
134
|
-
const message = `Replace '${filter}' with 'image_url'.`;
|
|
135
|
-
const sizeStr = getExpressionArgumentValue(node, 0);
|
|
136
|
-
|
|
137
|
-
const { width, height } = ensureImageValue(getImageSize(sizeStr));
|
|
138
|
-
const { start, end } = getFilterSourceStartAndEnd(node);
|
|
139
|
-
|
|
140
|
-
return [
|
|
141
|
-
{
|
|
142
|
-
message,
|
|
143
|
-
fix: (corrector) => {
|
|
144
|
-
const insert = buildFilterString('image_url', { width, height });
|
|
145
|
-
corrector.replace(start, end, insert);
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function getImageSize(size?: string, imageSize = { width: 100, height: 100 }): ImageSize {
|
|
152
|
-
if (!size) return { ...imageSize };
|
|
153
|
-
|
|
154
|
-
if (size in NAMED_SIZES) {
|
|
155
|
-
const s = NAMED_SIZES[size];
|
|
156
|
-
return { width: s, height: s };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const [width, height] = size.split('x').map((s) => parseInt(s));
|
|
160
|
-
|
|
161
|
-
return ensureImageSizeLimit({ width, height });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function scaleImage(node: LiquidFilter, imageSize: ImageSize): ImageSize {
|
|
165
|
-
const scale = parseInt(getNamedArgumentValue(node, 'scale') || '0') || 1;
|
|
166
|
-
|
|
167
|
-
return ensureImageSizeLimit({
|
|
168
|
-
width: imageSize.width * scale,
|
|
169
|
-
height: imageSize.height * scale,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function ensureImageSizeLimit(imageSize: ImageSize): ImageSize {
|
|
174
|
-
return {
|
|
175
|
-
width: Math.min(imageSize.width, MAX_SIZE),
|
|
176
|
-
height: Math.min(imageSize.height, MAX_SIZE),
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function ensureImageValue(imageSize: ImageSize): ImageSize {
|
|
181
|
-
let { width, height } = imageSize;
|
|
182
|
-
|
|
183
|
-
const isImageSizeUnset = (!height || height === -1) && (!width || width === -1);
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* If `image_url` is missing a width or height, we default to width=100, as
|
|
187
|
-
* the documentation mention an error is returned if neither are specified
|
|
188
|
-
* (interestingly, `image_url` doesn't actually fail during runtime tests).
|
|
189
|
-
*
|
|
190
|
-
* That default value is widely mentioned in the documentation and we've
|
|
191
|
-
* confirmed that in runtime tests.
|
|
192
|
-
*/
|
|
193
|
-
if (isImageSizeUnset) {
|
|
194
|
-
width = 100;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return { width, height };
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function getExpressionArgumentValue(node: LiquidFilter, index: number): string | undefined {
|
|
201
|
-
const arg = node.args.at(index);
|
|
202
|
-
|
|
203
|
-
if (isNumberLiteral(arg) || isStringLiteral(arg)) {
|
|
204
|
-
return arg.value;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function getNamedArgumentValue(node: LiquidFilter, propertyName: string) {
|
|
209
|
-
const argumentNode = getNamedArgumentNode(node, propertyName);
|
|
210
|
-
|
|
211
|
-
const valueNode = argumentNode?.value;
|
|
212
|
-
|
|
213
|
-
if (isNumberLiteral(valueNode) || isStringLiteral(valueNode)) {
|
|
214
|
-
return valueNode.value;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function getNamedArgumentNode(node: LiquidFilter, argName: string) {
|
|
219
|
-
const args = node.args;
|
|
220
|
-
|
|
221
|
-
return args.find(
|
|
222
|
-
(arg): arg is LiquidNamedArgument =>
|
|
223
|
-
isNodeOfType(NodeTypes.NamedArgument, arg) && arg.name === argName,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function buildFilterString(filter: string, filterParameters: FitlerParameters) {
|
|
228
|
-
const parameters = Object.entries(filterParameters)
|
|
229
|
-
.filter(([_key, value]) => value && value !== -1)
|
|
230
|
-
.map(([key, value]) => `${key}: ${value}`)
|
|
231
|
-
.join(', ');
|
|
232
|
-
|
|
233
|
-
if (!parameters) {
|
|
234
|
-
return ` ${filter}`;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return ` ${filter}: ${parameters}`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function getFilterSourceStartAndEnd(node: LiquidFilter) {
|
|
241
|
-
const position = node.position;
|
|
242
|
-
const pipePosition = node.source.slice(position.start).indexOf('|');
|
|
243
|
-
|
|
244
|
-
return {
|
|
245
|
-
start: position.start + pipePosition + 1,
|
|
246
|
-
end: position.end,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function strValue(value?: string) {
|
|
251
|
-
return value ? `'${value}'` : null;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function isVariableLookup(exp?: LiquidExpression | LiquidArgument): exp is LiquidVariableLookup {
|
|
255
|
-
return isNodeOfType(NodeTypes.VariableLookup, exp);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function isStringLiteral(exp?: LiquidExpression | LiquidArgument): exp is LiquidString {
|
|
259
|
-
return isNodeOfType(NodeTypes.String, exp);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function isNumberLiteral(exp?: LiquidExpression | LiquidArgument): exp is LiquidNumber {
|
|
263
|
-
return isNodeOfType(NodeTypes.Number, exp);
|
|
264
|
-
}
|