@platformos/platformos-check-common 0.0.8 → 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 +8 -0
- package/README.md +4 -4
- package/dist/checks/graphql-variables/index.js +4 -0
- package/dist/checks/graphql-variables/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 +21 -3
- package/dist/checks/liquid-html-syntax-error/index.js.map +1 -1
- package/dist/checks/matching-translations/index.js +103 -68
- package/dist/checks/matching-translations/index.js.map +1 -1
- package/dist/checks/undefined-object/index.js +6 -1
- package/dist/checks/undefined-object/index.js.map +1 -1
- package/dist/context-utils.d.ts +16 -0
- package/dist/context-utils.js +30 -1
- package/dist/context-utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/liquid-doc/arguments.js +8 -1
- package/dist/liquid-doc/arguments.js.map +1 -1
- package/dist/liquid-doc/utils.d.ts +2 -2
- package/dist/liquid-doc/utils.js +10 -0
- package/dist/liquid-doc/utils.js.map +1 -1
- package/dist/path.d.ts +1 -1
- package/dist/path.js +12 -1
- package/dist/path.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/checks/duplicate-render-partial-arguments/index.spec.ts +12 -12
- 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 +1 -1
- package/src/checks/invalid-hash-assign-target/index.spec.ts +26 -26
- package/src/checks/json-syntax-error/index.ts +1 -1
- 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.ts +24 -3
- package/src/checks/matching-translations/index.spec.ts +114 -24
- package/src/checks/matching-translations/index.ts +102 -81
- package/src/checks/metadata-params/index.ts +1 -1
- package/src/checks/missing-partial/index.ts +6 -6
- package/src/checks/undefined-object/index.spec.ts +29 -2
- package/src/checks/undefined-object/index.ts +7 -1
- package/src/checks/unused-assign/index.ts +1 -1
- package/src/checks/valid-json/index.ts +1 -1
- package/src/checks/valid-render-partial-argument-types/index.spec.ts +13 -13
- package/src/context-utils.ts +42 -1
- package/src/disabled-checks/index.spec.ts +26 -61
- package/src/disabled-checks/index.ts +2 -4
- package/src/disabled-checks/test-checks.ts +4 -4
- package/src/ignore.spec.ts +4 -4
- package/src/index.ts +18 -0
- package/src/liquid-doc/arguments.ts +9 -3
- package/src/liquid-doc/liquidDoc.spec.ts +1 -1
- package/src/liquid-doc/utils.ts +13 -5
- package/src/path.ts +16 -1
- package/src/test/MockApp.ts +2 -2
- package/src/test/MockFileSystem.spec.ts +10 -11
- package/src/test/contain-offense.spec.ts +11 -3
- package/src/test/test-helper.ts +24 -28
- package/src/types.ts +8 -0
- package/src/visitor.spec.ts +2 -2
- package/src/types/schemas/index.ts +0 -3
- package/src/types/schemas/preset.ts +0 -52
- package/src/types/schemas/setting.ts +0 -320
- package/src/types/schemas/template.ts +0 -34
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
FunctionMarkup,
|
|
17
17
|
LiquidTagHashAssign,
|
|
18
18
|
LiquidTagGraphQL,
|
|
19
|
+
LiquidTagParseJson,
|
|
19
20
|
LiquidTagBackground,
|
|
20
21
|
BackgroundInlineMarkup,
|
|
21
22
|
} from '@platformos/liquid-html-parser';
|
|
@@ -76,7 +77,7 @@ export const UndefinedObject: LiquidCheckDefinition = {
|
|
|
76
77
|
async LiquidTag(node, ancestors) {
|
|
77
78
|
if (isWithinRawTagThatDoesNotParseItsContents(ancestors)) return;
|
|
78
79
|
|
|
79
|
-
if (isLiquidTagAssign(node) || isLiquidTagGraphQL(node)) {
|
|
80
|
+
if (isLiquidTagAssign(node) || isLiquidTagGraphQL(node) || isLiquidTagParseJson(node)) {
|
|
80
81
|
indexVariableScope(node.markup.name, {
|
|
81
82
|
start: node.blockStartPosition.end,
|
|
82
83
|
});
|
|
@@ -158,6 +159,7 @@ export const UndefinedObject: LiquidCheckDefinition = {
|
|
|
158
159
|
|
|
159
160
|
const parent = last(ancestors);
|
|
160
161
|
if (isLiquidTag(parent) && isLiquidTagCapture(parent)) return;
|
|
162
|
+
if (isLiquidTag(parent) && isLiquidTagParseJson(parent)) return;
|
|
161
163
|
|
|
162
164
|
// Skip the jobId variable in background tag markup - it's being defined, not used
|
|
163
165
|
if (isBackgroundInlineMarkup(parent) && parent.jobId === node) return;
|
|
@@ -275,6 +277,10 @@ function isLiquidTagGraphQL(node: LiquidTag): node is LiquidTagGraphQL {
|
|
|
275
277
|
return node.name === NamedTags.graphql && typeof node.markup !== 'string';
|
|
276
278
|
}
|
|
277
279
|
|
|
280
|
+
function isLiquidTagParseJson(node: LiquidTag): node is LiquidTagParseJson {
|
|
281
|
+
return node.name === NamedTags.parse_json && typeof node.markup !== 'string';
|
|
282
|
+
}
|
|
283
|
+
|
|
278
284
|
function isLiquidForTag(node: LiquidTag): node is LiquidTagFor {
|
|
279
285
|
return node.name === NamedTags.for && typeof node.markup !== 'string';
|
|
280
286
|
}
|
|
@@ -14,7 +14,7 @@ export const UnusedAssign: LiquidCheckDefinition = {
|
|
|
14
14
|
name: 'Prevent unused assigns',
|
|
15
15
|
docs: {
|
|
16
16
|
description:
|
|
17
|
-
'This check exists to prevent bloat
|
|
17
|
+
'This check exists to prevent bloat by surfacing variable definitions that are not used.',
|
|
18
18
|
recommended: true,
|
|
19
19
|
url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/unused-assign',
|
|
20
20
|
},
|
|
@@ -7,7 +7,7 @@ export const ValidJSON: JSONCheckDefinition = {
|
|
|
7
7
|
name: 'Enforce valid JSON',
|
|
8
8
|
docs: {
|
|
9
9
|
description:
|
|
10
|
-
'This check exists to prevent invalid JSON files in
|
|
10
|
+
'This check exists to prevent invalid JSON files in apps. Will check against schema if available.',
|
|
11
11
|
recommended: true,
|
|
12
12
|
url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/json-syntax-error',
|
|
13
13
|
},
|
|
@@ -41,7 +41,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
41
41
|
|
|
42
42
|
for (const test of typeTests) {
|
|
43
43
|
describe(`${test.type} validation`, () => {
|
|
44
|
-
const
|
|
44
|
+
const makePartial = (type: string) => `
|
|
45
45
|
{% doc %}
|
|
46
46
|
@param {${type}} param - Description
|
|
47
47
|
{% enddoc %}
|
|
@@ -57,7 +57,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
57
57
|
undefined,
|
|
58
58
|
{},
|
|
59
59
|
{
|
|
60
|
-
'app/views/partials/card.liquid':
|
|
60
|
+
'app/views/partials/card.liquid': makePartial(test.type),
|
|
61
61
|
},
|
|
62
62
|
);
|
|
63
63
|
expect(offenses).toHaveLength(0);
|
|
@@ -73,7 +73,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
73
73
|
undefined,
|
|
74
74
|
{},
|
|
75
75
|
{
|
|
76
|
-
'app/views/partials/card.liquid':
|
|
76
|
+
'app/views/partials/card.liquid': makePartial(test.type),
|
|
77
77
|
},
|
|
78
78
|
);
|
|
79
79
|
expect(offenses).toHaveLength(1);
|
|
@@ -226,7 +226,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
describe('suggestions', () => {
|
|
229
|
-
const
|
|
229
|
+
const makePartial = (type: string) => `
|
|
230
230
|
{% doc %}
|
|
231
231
|
@param {${type}} param - Description
|
|
232
232
|
{% enddoc %}
|
|
@@ -241,7 +241,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
241
241
|
undefined,
|
|
242
242
|
{},
|
|
243
243
|
{
|
|
244
|
-
'app/views/partials/card.liquid':
|
|
244
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
245
245
|
},
|
|
246
246
|
);
|
|
247
247
|
|
|
@@ -291,7 +291,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
291
291
|
undefined,
|
|
292
292
|
{},
|
|
293
293
|
{
|
|
294
|
-
'app/views/partials/card.liquid':
|
|
294
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
295
295
|
},
|
|
296
296
|
);
|
|
297
297
|
|
|
@@ -338,7 +338,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
338
338
|
undefined,
|
|
339
339
|
{},
|
|
340
340
|
{
|
|
341
|
-
'app/views/partials/card.liquid':
|
|
341
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
342
342
|
},
|
|
343
343
|
);
|
|
344
344
|
|
|
@@ -356,7 +356,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
356
356
|
undefined,
|
|
357
357
|
{},
|
|
358
358
|
{
|
|
359
|
-
'app/views/partials/card.liquid':
|
|
359
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
360
360
|
},
|
|
361
361
|
);
|
|
362
362
|
|
|
@@ -376,7 +376,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
376
376
|
undefined,
|
|
377
377
|
{},
|
|
378
378
|
{
|
|
379
|
-
'app/views/partials/card.liquid':
|
|
379
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
380
380
|
},
|
|
381
381
|
);
|
|
382
382
|
|
|
@@ -396,7 +396,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
396
396
|
undefined,
|
|
397
397
|
{},
|
|
398
398
|
{
|
|
399
|
-
'app/views/partials/card.liquid':
|
|
399
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
400
400
|
},
|
|
401
401
|
);
|
|
402
402
|
|
|
@@ -414,7 +414,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
414
414
|
undefined,
|
|
415
415
|
{},
|
|
416
416
|
{
|
|
417
|
-
'app/views/partials/card.liquid':
|
|
417
|
+
'app/views/partials/card.liquid': makePartial('object'),
|
|
418
418
|
},
|
|
419
419
|
);
|
|
420
420
|
|
|
@@ -431,7 +431,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
431
431
|
undefined,
|
|
432
432
|
{},
|
|
433
433
|
{
|
|
434
|
-
'app/views/partials/card.liquid':
|
|
434
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
435
435
|
},
|
|
436
436
|
);
|
|
437
437
|
|
|
@@ -452,7 +452,7 @@ describe('Module: ValidRenderPartialParamTypes', () => {
|
|
|
452
452
|
undefined,
|
|
453
453
|
{},
|
|
454
454
|
{
|
|
455
|
-
'app/views/partials/card.liquid':
|
|
455
|
+
'app/views/partials/card.liquid': makePartial('string'),
|
|
456
456
|
},
|
|
457
457
|
);
|
|
458
458
|
|
package/src/context-utils.ts
CHANGED
|
@@ -1,8 +1,49 @@
|
|
|
1
1
|
import { load } from 'js-yaml';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AbstractFileSystem,
|
|
4
|
+
FileTuple,
|
|
5
|
+
FileType,
|
|
6
|
+
TranslationProvider,
|
|
7
|
+
UriString,
|
|
8
|
+
} from '@platformos/platformos-common';
|
|
9
|
+
import { URI } from 'vscode-uri';
|
|
3
10
|
import { join } from './path';
|
|
4
11
|
import { SourceCodeType, App, Translations } from './types';
|
|
5
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Returns a function that loads and merges ALL translation files for a given
|
|
15
|
+
* locale within a specific translations base directory URI
|
|
16
|
+
* (e.g. `file:///app/translations` or
|
|
17
|
+
* `file:///modules/common-styling/public/translations`).
|
|
18
|
+
*
|
|
19
|
+
* Covers both the single-file layout (`{base}/{locale}.yml`) and the split-file
|
|
20
|
+
* layout (`{base}/{locale}/*.yml`).
|
|
21
|
+
*
|
|
22
|
+
* Only files whose first YAML key matches `locale` are included — this mirrors
|
|
23
|
+
* how platformOS determines a file's locale from its content, not its path.
|
|
24
|
+
*
|
|
25
|
+
* In-memory editor buffers take precedence over the filesystem so that unsaved
|
|
26
|
+
* changes are reflected immediately.
|
|
27
|
+
*/
|
|
28
|
+
export const makeGetTranslationsForBase = (fs: AbstractFileSystem, app: App) => {
|
|
29
|
+
const provider = new TranslationProvider(fs);
|
|
30
|
+
const cache = new Map<string, Promise<Translations>>();
|
|
31
|
+
|
|
32
|
+
return (translationBaseUri: string, locale: string): Promise<Translations> => {
|
|
33
|
+
const key = `${translationBaseUri}::${locale}`;
|
|
34
|
+
if (!cache.has(key)) {
|
|
35
|
+
const contentOverride = (uri: string): string | undefined =>
|
|
36
|
+
app.find((sc) => sc.type === SourceCodeType.YAML && sc.uri === uri)?.source;
|
|
37
|
+
|
|
38
|
+
cache.set(
|
|
39
|
+
key,
|
|
40
|
+
provider.loadAllTranslationsForBase(URI.parse(translationBaseUri), locale, contentOverride),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return cache.get(key)!;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
6
47
|
export type FileExists = (uri: string) => Promise<boolean>;
|
|
7
48
|
|
|
8
49
|
export const makeFileExists = (fs: AbstractFileSystem): FileExists =>
|
|
@@ -34,10 +34,10 @@ describe('Module: DisabledChecks', () => {
|
|
|
34
34
|
describe(`Comment variant`, () => {
|
|
35
35
|
it('should disable checks for the entire document if comment is placed on the first line', async () => {
|
|
36
36
|
for (const buildComment of commentTypes) {
|
|
37
|
-
const file = `${buildComment('
|
|
37
|
+
const file = `${buildComment('platformos-check-disable LiquidFilter')}
|
|
38
38
|
{% comment %}
|
|
39
39
|
This is some comment about the file...
|
|
40
|
-
Adding a comment here should not mess with
|
|
40
|
+
Adding a comment here should not mess with platformos-check-disable
|
|
41
41
|
{% endcomment %}
|
|
42
42
|
{{ 'asset' | random_filter }}
|
|
43
43
|
{% render 'something' %}`;
|
|
@@ -50,7 +50,7 @@ describe('Module: DisabledChecks', () => {
|
|
|
50
50
|
|
|
51
51
|
it('should disable all checks even if comment has additional spaces', async () => {
|
|
52
52
|
for (const buildComment of commentTypes) {
|
|
53
|
-
const file = `${buildComment('
|
|
53
|
+
const file = `${buildComment(' platformos-check-disable ')}
|
|
54
54
|
{{ 'asset' | random_filter }}
|
|
55
55
|
{% render 'something' %}`;
|
|
56
56
|
|
|
@@ -63,10 +63,10 @@ describe('Module: DisabledChecks', () => {
|
|
|
63
63
|
for (const buildComment of commentTypes) {
|
|
64
64
|
const file = `{{ 'asset-1' | random_filter }}
|
|
65
65
|
{% render 'something-1' %}
|
|
66
|
-
${buildComment('
|
|
66
|
+
${buildComment('platformos-check-disable')}
|
|
67
67
|
{{ 'asset-2' | random_filter }}
|
|
68
68
|
{% render 'something-2' %}
|
|
69
|
-
${buildComment('
|
|
69
|
+
${buildComment('platformos-check-enable')}
|
|
70
70
|
{{ 'asset-3' | random_filter }}`;
|
|
71
71
|
|
|
72
72
|
const offenses = await check({ 'code.liquid': file }, checks);
|
|
@@ -79,10 +79,10 @@ ${buildComment('theme-check-enable')}
|
|
|
79
79
|
|
|
80
80
|
it('should disable a specific check if check is included in the comment', async () => {
|
|
81
81
|
for (const buildComment of commentTypes) {
|
|
82
|
-
const file = `${buildComment('
|
|
82
|
+
const file = `${buildComment('platformos-check-disable LiquidFilter')}
|
|
83
83
|
{{ 'asset-1' | random_filter }}
|
|
84
84
|
{% render 'something' %}
|
|
85
|
-
${buildComment('
|
|
85
|
+
${buildComment('platformos-check-enable LiquidFilter')}
|
|
86
86
|
{{ 'asset-2' | random_filter }}`;
|
|
87
87
|
|
|
88
88
|
const offenses = await check({ 'code.liquid': file }, checks);
|
|
@@ -94,10 +94,10 @@ ${buildComment('theme-check-enable LiquidFilter')}
|
|
|
94
94
|
|
|
95
95
|
it('should disable multiple checks if checks are separated by a comma (and maybe some spaces)', async () => {
|
|
96
96
|
for (const buildComment of commentTypes) {
|
|
97
|
-
const file = `${buildComment('
|
|
97
|
+
const file = `${buildComment('platformos-check-disable LiquidFilter, RenderMarkup')}
|
|
98
98
|
{{ 'asset-1' | random_filter }}
|
|
99
99
|
{% render 'something' %}
|
|
100
|
-
${buildComment('
|
|
100
|
+
${buildComment('platformos-check-enable LiquidFilter,RenderMarkup')}
|
|
101
101
|
{{ 'asset-2' | random_filter }}`;
|
|
102
102
|
|
|
103
103
|
const offenses = await check({ 'code.liquid': file }, checks);
|
|
@@ -108,13 +108,13 @@ ${buildComment('theme-check-enable LiquidFilter,RenderMarkup')}
|
|
|
108
108
|
|
|
109
109
|
it('should enable specific checks individually', async () => {
|
|
110
110
|
for (const buildComment of commentTypes) {
|
|
111
|
-
const file = `${buildComment('
|
|
111
|
+
const file = `${buildComment('platformos-check-disable LiquidFilter, RenderMarkup')}
|
|
112
112
|
{{ 'asset-1' | random_filter }}
|
|
113
113
|
{% render 'something-1' %}
|
|
114
|
-
${buildComment('
|
|
114
|
+
${buildComment('platformos-check-enable RenderMarkup')}
|
|
115
115
|
{{ 'asset-2' | random_filter }}
|
|
116
116
|
{% render 'something-2' %}
|
|
117
|
-
${buildComment('
|
|
117
|
+
${buildComment('platformos-check-enable LiquidFilter')}
|
|
118
118
|
{{ 'asset-3' | random_filter }}
|
|
119
119
|
{% render 'something-3' %}`;
|
|
120
120
|
|
|
@@ -129,10 +129,10 @@ ${buildComment('theme-check-enable LiquidFilter')}
|
|
|
129
129
|
describe('Mix of general and specific commands', () => {
|
|
130
130
|
it('should not reenable specific check when all checks have been disabled before', async () => {
|
|
131
131
|
for (const buildComment of commentTypes) {
|
|
132
|
-
const file = `${buildComment('
|
|
132
|
+
const file = `${buildComment('platformos-check-disable')}
|
|
133
133
|
{{ 'asset-1' | random_filter }}
|
|
134
134
|
{% render 'something-1' %}
|
|
135
|
-
${buildComment('
|
|
135
|
+
${buildComment('platformos-check-enable RenderMarkup')}
|
|
136
136
|
{{ 'asset-2' | random_filter }}
|
|
137
137
|
{% render 'something-2' %}`;
|
|
138
138
|
const offenses = await check({ 'code.liquid': file }, checks);
|
|
@@ -142,10 +142,10 @@ ${buildComment('theme-check-enable RenderMarkup')}
|
|
|
142
142
|
|
|
143
143
|
it('should reenable all checks when specific ones have been disabled before', async () => {
|
|
144
144
|
for (const buildComment of commentTypes) {
|
|
145
|
-
const file = `${buildComment('
|
|
145
|
+
const file = `${buildComment('platformos-check-disable LiquidFilter, RenderMarkup')}
|
|
146
146
|
{{ 'asset-3' | random_filter }}
|
|
147
147
|
{% render 'something-3' %}
|
|
148
|
-
${buildComment('
|
|
148
|
+
${buildComment('platformos-check-enable')}
|
|
149
149
|
{{ 'asset-4' | random_filter }}
|
|
150
150
|
{% render 'something-4' %}`;
|
|
151
151
|
|
|
@@ -159,7 +159,7 @@ ${buildComment('theme-check-enable')}
|
|
|
159
159
|
|
|
160
160
|
describe('disable next line', () => {
|
|
161
161
|
it('should disable the next line if there is one', async () => {
|
|
162
|
-
const file = `{% #
|
|
162
|
+
const file = `{% # platformos-check-disable-next-line %}
|
|
163
163
|
{% render 'something' %}
|
|
164
164
|
{% render 'other-thing' %}`;
|
|
165
165
|
|
|
@@ -168,8 +168,8 @@ ${buildComment('theme-check-enable')}
|
|
|
168
168
|
expectRenderMarkupOffense(offenses, 'other-thing.liquid');
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
it("should not disable the liquid tag's children node if
|
|
172
|
-
const file = `{% #
|
|
171
|
+
it("should not disable the liquid tag's children node if platformos-check is disabled", async () => {
|
|
172
|
+
const file = `{% # platformos-check-disable-next-line %}
|
|
173
173
|
{% if condition %}
|
|
174
174
|
{% render 'something' %}
|
|
175
175
|
{% endif %}
|
|
@@ -183,7 +183,7 @@ ${buildComment('theme-check-enable')}
|
|
|
183
183
|
|
|
184
184
|
it('should disable the next line inside a liquid tag if there is one', async () => {
|
|
185
185
|
const file = `{% liquid
|
|
186
|
-
#
|
|
186
|
+
# platformos-check-disable-next-line
|
|
187
187
|
render 'something'
|
|
188
188
|
render 'other-thing'
|
|
189
189
|
%}`;
|
|
@@ -193,10 +193,10 @@ ${buildComment('theme-check-enable')}
|
|
|
193
193
|
expectRenderMarkupOffense(offenses, 'other-thing.liquid');
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
-
it("should disable the parent node's next node if
|
|
196
|
+
it("should disable the parent node's next node if platformos-check is disabled as the last child node", async () => {
|
|
197
197
|
const file = `{% liquid
|
|
198
198
|
if condition
|
|
199
|
-
#
|
|
199
|
+
# platformos-check-disable-next-line
|
|
200
200
|
elsif other_condition
|
|
201
201
|
endif
|
|
202
202
|
%}`;
|
|
@@ -210,11 +210,11 @@ ${buildComment('theme-check-enable')}
|
|
|
210
210
|
);
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
-
it('should not disable any checks if
|
|
213
|
+
it('should not disable any checks if platformos-check is disabled at the end', async () => {
|
|
214
214
|
const file = `{% liquid
|
|
215
215
|
echo hello
|
|
216
216
|
echo everyone
|
|
217
|
-
#
|
|
217
|
+
# platformos-check-disable-next-line
|
|
218
218
|
%}`;
|
|
219
219
|
|
|
220
220
|
const offenses = await check({ 'code.liquid': file }, [UndefinedObject]);
|
|
@@ -232,7 +232,7 @@ ${buildComment('theme-check-enable')}
|
|
|
232
232
|
});
|
|
233
233
|
|
|
234
234
|
it('should disable the next line if the content is an HTML tag with liquid', async () => {
|
|
235
|
-
const file = `{% #
|
|
235
|
+
const file = `{% # platformos-check-disable-next-line %}
|
|
236
236
|
<div class="{{ foo }}"></div>
|
|
237
237
|
<div class="{{ bar }}"></div>`;
|
|
238
238
|
|
|
@@ -246,7 +246,7 @@ ${buildComment('theme-check-enable')}
|
|
|
246
246
|
});
|
|
247
247
|
|
|
248
248
|
it('should not disable the next line if the specified rule does not exist', async () => {
|
|
249
|
-
const file = `{% #
|
|
249
|
+
const file = `{% # platformos-check-disable-next-line FAKE_RULE %}
|
|
250
250
|
<div class="{{ foo }}"></div>`;
|
|
251
251
|
|
|
252
252
|
const offenses = await check({ 'code.liquid': file }, [UndefinedObject]);
|
|
@@ -259,39 +259,4 @@ ${buildComment('theme-check-enable')}
|
|
|
259
259
|
});
|
|
260
260
|
});
|
|
261
261
|
});
|
|
262
|
-
|
|
263
|
-
describe('platformos-check prefix', () => {
|
|
264
|
-
it('should disable checks using platformos-check-disable prefix', async () => {
|
|
265
|
-
for (const buildComment of commentTypes) {
|
|
266
|
-
const file = `${buildComment('platformos-check-disable LiquidFilter')}
|
|
267
|
-
{{ 'asset' | random_filter }}
|
|
268
|
-
{% render 'something' %}`;
|
|
269
|
-
|
|
270
|
-
const offenses = await check({ 'code.liquid': file }, checks);
|
|
271
|
-
expect(offenses).to.have.length(1);
|
|
272
|
-
expectRenderMarkupOffense(offenses, 'something.liquid');
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it('should disable all checks using platformos-check-disable prefix', async () => {
|
|
277
|
-
for (const buildComment of commentTypes) {
|
|
278
|
-
const file = `${buildComment('platformos-check-disable')}
|
|
279
|
-
{{ 'asset' | random_filter }}
|
|
280
|
-
{% render 'something' %}`;
|
|
281
|
-
|
|
282
|
-
const offenses = await check({ 'code.liquid': file }, checks);
|
|
283
|
-
expect(offenses).to.have.length(0);
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should disable next line using platformos-check-disable-next-line prefix', async () => {
|
|
288
|
-
const file = `{% # platformos-check-disable-next-line %}
|
|
289
|
-
{% render 'something' %}
|
|
290
|
-
{% render 'other-thing' %}`;
|
|
291
|
-
|
|
292
|
-
const offenses = await check({ 'code.liquid': file }, checks);
|
|
293
|
-
expect(offenses).to.have.length(1);
|
|
294
|
-
expectRenderMarkupOffense(offenses, 'other-thing.liquid');
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
262
|
});
|
|
@@ -24,9 +24,7 @@ export function createDisabledChecksModule() {
|
|
|
24
24
|
node: LiquidTag | LiquidRawTag,
|
|
25
25
|
) {
|
|
26
26
|
const [_, command, checksJoined] =
|
|
27
|
-
value
|
|
28
|
-
.trim()
|
|
29
|
-
.match(/^(?:(?:platformos|theme)\-check\-(disable-next-line|disable|enable)) ?(.*)/) || [];
|
|
27
|
+
value.trim().match(/^(?:platformos\-check\-(disable-next-line|disable|enable)) ?(.*)/) || [];
|
|
30
28
|
|
|
31
29
|
const checks = checksJoined ? checksJoined.split(/,[ ]*/) : [SPECIFIC_CHECK_NOT_DEFINED];
|
|
32
30
|
|
|
@@ -135,7 +133,7 @@ export function findNextLinePosition(
|
|
|
135
133
|
* E.g. The following disables check for `elsif` tag
|
|
136
134
|
*
|
|
137
135
|
* {% if condition %}
|
|
138
|
-
* {% #platformos-check-disable-next-line %}
|
|
136
|
+
* {% # platformos-check-disable-next-line %}
|
|
139
137
|
* {% elsif other_condition %}
|
|
140
138
|
* {{ prouduct }}
|
|
141
139
|
* {% endif %}
|
|
@@ -45,14 +45,14 @@ export const RenderMarkup: LiquidCheckDefinition = {
|
|
|
45
45
|
create(context) {
|
|
46
46
|
return {
|
|
47
47
|
async RenderMarkup(node) {
|
|
48
|
-
if (node.
|
|
48
|
+
if (node.partial.type === NodeTypes.VariableLookup) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
context.report({
|
|
53
|
-
message: `'${node.
|
|
54
|
-
startIndex: node.
|
|
55
|
-
endIndex: node.
|
|
53
|
+
message: `'${node.partial.value}.liquid' can not be rendered`,
|
|
54
|
+
startIndex: node.partial.position.start,
|
|
55
|
+
endIndex: node.partial.position.end,
|
|
56
56
|
});
|
|
57
57
|
},
|
|
58
58
|
};
|
package/src/ignore.spec.ts
CHANGED
|
@@ -47,7 +47,7 @@ describe('Function: isIgnored', () => {
|
|
|
47
47
|
const result = isIgnored(
|
|
48
48
|
toUri('app/views/partials/foo.liquid'),
|
|
49
49
|
config({
|
|
50
|
-
checkIgnore: ['!
|
|
50
|
+
checkIgnore: ['!other-dir/*'],
|
|
51
51
|
globalIgnore: [],
|
|
52
52
|
}),
|
|
53
53
|
checkDef,
|
|
@@ -73,7 +73,7 @@ describe('Function: isIgnored', () => {
|
|
|
73
73
|
const result = isIgnored(
|
|
74
74
|
toUri('app/views/partials/foo.liquid'),
|
|
75
75
|
config({
|
|
76
|
-
checkIgnore: ['other-
|
|
76
|
+
checkIgnore: ['other-dir/*.liquid'],
|
|
77
77
|
globalIgnore: [],
|
|
78
78
|
}),
|
|
79
79
|
checkDef,
|
|
@@ -165,10 +165,10 @@ describe('Function: isIgnored', () => {
|
|
|
165
165
|
|
|
166
166
|
it('should work with only global ignore as well', () => {
|
|
167
167
|
const result = isIgnored(
|
|
168
|
-
toUri('layout
|
|
168
|
+
toUri('app/views/layouts/layout.liquid'),
|
|
169
169
|
config({
|
|
170
170
|
checkIgnore: [],
|
|
171
|
-
globalIgnore: ['layout
|
|
171
|
+
globalIgnore: ['app/views/layouts/layout.liquid'],
|
|
172
172
|
}),
|
|
173
173
|
);
|
|
174
174
|
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
makeFileSize,
|
|
6
6
|
makeGetDefaultLocale,
|
|
7
7
|
makeGetDefaultTranslations,
|
|
8
|
+
makeGetTranslationsForBase,
|
|
8
9
|
} from './context-utils';
|
|
9
10
|
import { createDisabledChecksModule } from './disabled-checks';
|
|
10
11
|
import { isIgnored } from './ignore';
|
|
@@ -47,6 +48,22 @@ export * from './context-utils';
|
|
|
47
48
|
export * from './find-root';
|
|
48
49
|
export * from './fixes';
|
|
49
50
|
export * from './ignore';
|
|
51
|
+
export {
|
|
52
|
+
FILE_TYPE_DIRS,
|
|
53
|
+
getAppPaths,
|
|
54
|
+
getFileType,
|
|
55
|
+
getModulePaths,
|
|
56
|
+
isApiCall,
|
|
57
|
+
isAuthorization,
|
|
58
|
+
isEmail,
|
|
59
|
+
isKnownLiquidFile,
|
|
60
|
+
isLayout,
|
|
61
|
+
isMigration,
|
|
62
|
+
isPage,
|
|
63
|
+
isPartial,
|
|
64
|
+
isSms,
|
|
65
|
+
PlatformOSFileType,
|
|
66
|
+
} from '@platformos/platformos-common';
|
|
50
67
|
export * from './json';
|
|
51
68
|
export * from './JSONValidator';
|
|
52
69
|
export * as path from './path';
|
|
@@ -80,6 +97,7 @@ export async function check(
|
|
|
80
97
|
fileSize: makeFileSize(fs),
|
|
81
98
|
getDefaultLocale: makeGetDefaultLocale(fs, rootUri),
|
|
82
99
|
getDefaultTranslations: makeGetDefaultTranslations(fs, app, rootUri),
|
|
100
|
+
getTranslationsForBase: makeGetTranslationsForBase(fs, app),
|
|
83
101
|
};
|
|
84
102
|
|
|
85
103
|
const { DisabledChecksVisitor, isDisabled } = createDisabledChecksModule();
|
|
@@ -121,7 +121,13 @@ export function findTypeMismatchParams(
|
|
|
121
121
|
const typeMismatchParams: LiquidNamedArgument[] = [];
|
|
122
122
|
|
|
123
123
|
for (const arg of providedParams) {
|
|
124
|
-
if (
|
|
124
|
+
// Skip if the value is a variable lookup (can't determine type statically)
|
|
125
|
+
// or if it has filters (graphql args may have filters, output type is unknown)
|
|
126
|
+
if (arg.value.type === NodeTypes.LiquidVariable) {
|
|
127
|
+
if (arg.value.expression.type === NodeTypes.VariableLookup || arg.value.filters.length > 0) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
} else if (arg.value.type === NodeTypes.VariableLookup) {
|
|
125
131
|
continue;
|
|
126
132
|
}
|
|
127
133
|
|
|
@@ -212,10 +218,10 @@ function isLastArg(node: RenderMarkup | FunctionMarkup, arg: LiquidNamedArgument
|
|
|
212
218
|
|
|
213
219
|
export function getPartialName(node: RenderMarkup | FunctionMarkup): string | undefined {
|
|
214
220
|
if (node.type === NodeTypes.RenderMarkup) {
|
|
215
|
-
if (!isLiquidString(node.
|
|
221
|
+
if (!isLiquidString(node.partial)) {
|
|
216
222
|
return;
|
|
217
223
|
}
|
|
218
|
-
return node.
|
|
224
|
+
return node.partial.value;
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
if (node.type === NodeTypes.FunctionMarkup) {
|
|
@@ -238,7 +238,7 @@ describe('Unit: extractDocDefinition', () => {
|
|
|
238
238
|
});
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
-
it('should return
|
|
241
|
+
it('should return partialDefinition without liquidDoc property if doc header is not present', async () => {
|
|
242
242
|
const ast = toAST(`
|
|
243
243
|
<div>No doc header here</div>
|
|
244
244
|
`);
|
package/src/liquid-doc/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LiquidExpression, NodeTypes } from '@platformos/liquid-html-parser';
|
|
1
|
+
import { LiquidExpression, LiquidVariable, NodeTypes } from '@platformos/liquid-html-parser';
|
|
2
2
|
import { assertNever } from '../utils';
|
|
3
3
|
import { isPartial } from '../path';
|
|
4
4
|
import { ObjectEntry, UriString } from '../types';
|
|
@@ -6,7 +6,7 @@ import { ObjectEntry, UriString } from '../types';
|
|
|
6
6
|
/**
|
|
7
7
|
* The base set of supported param types for LiquidDoc.
|
|
8
8
|
*
|
|
9
|
-
* This is used in conjunction with objects defined in [liquid docs](https://
|
|
9
|
+
* This is used in conjunction with objects defined in [liquid docs](https://documentation.platformos.com/api-reference/liquid/objects)
|
|
10
10
|
* to determine ALL supported param types for LiquidDoc.
|
|
11
11
|
*
|
|
12
12
|
* References `getValidParamTypes`
|
|
@@ -35,7 +35,7 @@ export function getDefaultValueForType(type: string | null) {
|
|
|
35
35
|
return '0';
|
|
36
36
|
case BasicParamTypes.Boolean:
|
|
37
37
|
return 'false';
|
|
38
|
-
case BasicParamTypes.Object: // Objects don't have a sensible default value
|
|
38
|
+
case BasicParamTypes.Object: // Objects don't have a sensible default value
|
|
39
39
|
default:
|
|
40
40
|
return '';
|
|
41
41
|
}
|
|
@@ -44,7 +44,15 @@ export function getDefaultValueForType(type: string | null) {
|
|
|
44
44
|
/**
|
|
45
45
|
* Casts the value of a LiquidNamedArgument to a string representing the type of the value.
|
|
46
46
|
*/
|
|
47
|
-
export function inferArgumentType(arg: LiquidExpression): BasicParamTypes {
|
|
47
|
+
export function inferArgumentType(arg: LiquidExpression | LiquidVariable): BasicParamTypes {
|
|
48
|
+
if (arg.type === NodeTypes.LiquidVariable) {
|
|
49
|
+
// A variable with filters — delegate to the base expression if there are no filters,
|
|
50
|
+
// otherwise we can't statically determine the filtered output type.
|
|
51
|
+
if (arg.filters.length > 0) return BasicParamTypes.Object;
|
|
52
|
+
const expr = arg.expression;
|
|
53
|
+
if (expr.type === NodeTypes.BooleanExpression) return BasicParamTypes.Object;
|
|
54
|
+
return inferArgumentType(expr);
|
|
55
|
+
}
|
|
48
56
|
switch (arg.type) {
|
|
49
57
|
case NodeTypes.String:
|
|
50
58
|
return BasicParamTypes.String;
|
|
@@ -87,7 +95,7 @@ export function filePathSupportsLiquidDoc(uri: UriString) {
|
|
|
87
95
|
|
|
88
96
|
/**
|
|
89
97
|
* Dynamically generates a map of LiquidDoc param types using object entries from
|
|
90
|
-
* [liquid docs](https://
|
|
98
|
+
* [liquid docs](https://documentation.platformos.com/api-reference/liquid/objects).
|
|
91
99
|
*
|
|
92
100
|
* This is used in conjunction with the base set of supported param.
|
|
93
101
|
*
|
package/src/path.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { RelativePath, UriString } from './types';
|
|
2
2
|
import { URI, Utils } from 'vscode-uri';
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
isPartial,
|
|
5
|
+
isLayout,
|
|
6
|
+
isPage,
|
|
7
|
+
isAuthorization,
|
|
8
|
+
isEmail,
|
|
9
|
+
isApiCall,
|
|
10
|
+
isSms,
|
|
11
|
+
isMigration,
|
|
12
|
+
isKnownLiquidFile,
|
|
13
|
+
getFileType,
|
|
14
|
+
getAppPaths,
|
|
15
|
+
getModulePaths,
|
|
16
|
+
PlatformOSFileType,
|
|
17
|
+
FILE_TYPE_DIRS,
|
|
18
|
+
} from '@platformos/platformos-common';
|
|
4
19
|
|
|
5
20
|
export { URI, Utils };
|
|
6
21
|
|