@shopify/theme-check-common
Advanced tools
Comparing version 2.0.4 to 2.1.0
# @shopify/theme-check-common | ||
## 2.1.0 | ||
### Minor Changes | ||
- 042f1e0: Breaking: internal rename of `schemaValidators` to `jsonValidationSet` | ||
This breaks the browser dependencies public API (for `startServer` and `runChecks`) and will thus require some code changes in those contexts. | ||
The node packages absorb the dependency injection and are not breaking. | ||
- a9ae65f: Add Language Server and Theme Check support for checkout.liquid objects | ||
## 2.0.4 | ||
@@ -4,0 +16,0 @@ |
@@ -43,4 +43,26 @@ "use strict"; | ||
]; | ||
const toObjectEntry = (name) => ({ name }); | ||
const undocumentedObjectEntryKeys = [ | ||
'locale', | ||
'direction', | ||
'skip_to_content_link', | ||
'checkout_html_classes', | ||
'checkout_stylesheets', | ||
'checkout_scripts', | ||
'content_for_logo', | ||
'breadcrumb', | ||
'order_summary_toggle', | ||
'content_for_order_summary', | ||
'alternative_payment_methods', | ||
'content_for_footer', | ||
'tracking_code', | ||
]; | ||
const toObjectEntry = (name, access, returnType) => ({ | ||
name, | ||
...(access && { access }), | ||
...(returnType && { return_type: returnType }), | ||
}); | ||
const undocumentedObjects = ['customer_address', 'product_variant']; | ||
const legacyCheckoutEntries = undocumentedObjectEntryKeys.map((objectKey) => toObjectEntry(objectKey, { global: false, parents: [], template: [] }, [ | ||
{ type: 'string', name: '' }, | ||
])); | ||
const toTagEntry = (name) => ({ name }); | ||
@@ -60,3 +82,7 @@ const undocumentedTags = ['elsif', 'ifchanged', 'when', 'schema']; | ||
this.objects = (0, utils_1.memo)(async () => { | ||
return [...(await this.themeDocset.objects()), ...undocumentedObjects.map(toObjectEntry)]; | ||
return [ | ||
...(await this.themeDocset.objects()), | ||
...undocumentedObjects.map((obj) => toObjectEntry(obj)), | ||
...legacyCheckoutEntries, | ||
]; | ||
}); | ||
@@ -63,0 +89,0 @@ this.tags = (0, utils_1.memo)(async () => { |
@@ -138,2 +138,19 @@ "use strict"; | ||
function getContextualObjects(relativePath) { | ||
if (relativePath.startsWith('layout/checkout.liquid')) { | ||
return [ | ||
'locale', | ||
'direction', | ||
'skip_to_content_link', | ||
'checkout_html_classes', | ||
'checkout_stylesheets', | ||
'checkout_scripts', | ||
'content_for_logo', | ||
'breadcrumb', | ||
'order_summary_toggle', | ||
'content_for_order_summary', | ||
'alternative_payment_methods', | ||
'content_for_footer', | ||
'tracking_code', | ||
]; | ||
} | ||
if (relativePath.startsWith('sections/')) { | ||
@@ -140,0 +157,0 @@ return ['section', 'predictive_search', 'recommendations']; |
@@ -55,3 +55,3 @@ "use strict"; | ||
} | ||
const validateSectionSchema = await ((_a = context.schemaValidators) === null || _a === void 0 ? void 0 : _a.validateSectionSchema()); | ||
const validateSectionSchema = await ((_a = context.jsonValidationSet) === null || _a === void 0 ? void 0 : _a.validateSectionSchema()); | ||
if (!validateSectionSchema) { | ||
@@ -58,0 +58,0 @@ return; |
import { Config, Dependencies, Offense, Theme } from './types'; | ||
export * from './AugmentedThemeDocset'; | ||
export * from './AugmentedSchemaValidators'; | ||
export * from './AugmentedJsonValidationSet'; | ||
export * from './fixes'; | ||
@@ -5,0 +5,0 @@ export * from './types'; |
@@ -37,5 +37,5 @@ "use strict"; | ||
const AugmentedThemeDocset_1 = require("./AugmentedThemeDocset"); | ||
const AugmentedSchemaValidators_1 = require("./AugmentedSchemaValidators"); | ||
const AugmentedJsonValidationSet_1 = require("./AugmentedJsonValidationSet"); | ||
__exportStar(require("./AugmentedThemeDocset"), exports); | ||
__exportStar(require("./AugmentedSchemaValidators"), exports); | ||
__exportStar(require("./AugmentedJsonValidationSet"), exports); | ||
__exportStar(require("./fixes"), exports); | ||
@@ -59,4 +59,4 @@ __exportStar(require("./types"), exports); | ||
} | ||
if (dependencies.schemaValidators && !dependencies.schemaValidators.isAugmented) { | ||
dependencies.schemaValidators = new AugmentedSchemaValidators_1.AugmentedSchemaValidators(dependencies.schemaValidators); | ||
if (dependencies.jsonValidationSet && !dependencies.jsonValidationSet.isAugmented) { | ||
dependencies.jsonValidationSet = new AugmentedJsonValidationSet_1.AugmentedJsonValidationSet(dependencies.jsonValidationSet); | ||
} | ||
@@ -63,0 +63,0 @@ for (const type of Object.values(types_1.SourceCodeType)) { |
@@ -5,3 +5,3 @@ import { NodeTypes as LiquidHtmlNodeTypes, LiquidHtmlNode } from '@shopify/liquid-html-parser'; | ||
import { StringCorrector, JSONCorrector } from './fixes'; | ||
import { ThemeDocset, JsonSchemaValidators } from './types/theme-liquid-docs'; | ||
import { ThemeDocset, JsonValidationSet } from './types/theme-liquid-docs'; | ||
export * from './types/theme-liquid-docs'; | ||
@@ -195,3 +195,3 @@ export * from './types/schema-prop-factory'; | ||
themeDocset?: ThemeDocset; | ||
schemaValidators?: JsonSchemaValidators; | ||
jsonValidationSet?: JsonValidationSet; | ||
} | ||
@@ -198,0 +198,0 @@ type StaticContextProperties<T extends SourceCodeType> = T extends SourceCodeType ? { |
@@ -20,3 +20,3 @@ import { Translations } from '..'; | ||
*/ | ||
export interface JsonSchemaValidators { | ||
export interface JsonValidationSet { | ||
/** Whether it was augmented prior to being passed. */ | ||
@@ -26,2 +26,6 @@ isAugmented?: boolean; | ||
validateSectionSchema(): Promise<ValidateFunction>; | ||
/** Retrieves the JSON schema of the {% schema %} JSON blobs in sections/*.liquid files */ | ||
sectionSchema(): Promise<string>; | ||
/** Retrieves the JSON schema of the locales/*.json files */ | ||
translationSchema(): Promise<string>; | ||
} | ||
@@ -28,0 +32,0 @@ /** |
{ | ||
"name": "@shopify/theme-check-common", | ||
"version": "2.0.4", | ||
"version": "2.1.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -35,3 +35,3 @@ import { describe, beforeEach, it, expect } from 'vitest'; | ||
expect(objects).to.have.length.greaterThanOrEqual(2); | ||
expect(objects).to.have.length.greaterThanOrEqual(15); | ||
}); | ||
@@ -43,2 +43,16 @@ | ||
expect(objects).to.deep.include({ name: 'customer_address' }); | ||
expect(objects).to.deep.include({ | ||
name: 'locale', | ||
access: { | ||
global: false, | ||
parents: [], | ||
template: [], | ||
}, | ||
return_type: [ | ||
{ | ||
type: 'string', | ||
name: '', | ||
}, | ||
], | ||
}); | ||
}); | ||
@@ -45,0 +59,0 @@ }); |
@@ -1,2 +0,10 @@ | ||
import { FilterEntry, ObjectEntry, TagEntry, ThemeDocset, Translations } from './types'; | ||
import { | ||
Access, | ||
FilterEntry, | ||
ObjectEntry, | ||
TagEntry, | ||
ThemeDocset, | ||
Translations, | ||
ReturnType, | ||
} from './types'; | ||
import { memo } from './utils'; | ||
@@ -43,4 +51,30 @@ | ||
const toObjectEntry = (name: string): ObjectEntry => ({ name }); | ||
const undocumentedObjectEntryKeys = [ | ||
'locale', | ||
'direction', | ||
'skip_to_content_link', | ||
'checkout_html_classes', | ||
'checkout_stylesheets', | ||
'checkout_scripts', | ||
'content_for_logo', | ||
'breadcrumb', | ||
'order_summary_toggle', | ||
'content_for_order_summary', | ||
'alternative_payment_methods', | ||
'content_for_footer', | ||
'tracking_code', | ||
]; | ||
const toObjectEntry = (name: string, access?: Access, returnType?: ReturnType[]): ObjectEntry => ({ | ||
name, | ||
...(access && { access }), | ||
...(returnType && { return_type: returnType }), | ||
}); | ||
const undocumentedObjects = ['customer_address', 'product_variant']; | ||
const legacyCheckoutEntries: ObjectEntry[] = undocumentedObjectEntryKeys.map((objectKey) => | ||
toObjectEntry(objectKey, { global: false, parents: [], template: [] }, [ | ||
{ type: 'string', name: '' }, | ||
]), | ||
); | ||
@@ -64,3 +98,7 @@ const toTagEntry = (name: string): TagEntry => ({ name }); | ||
objects = memo(async (): Promise<ObjectEntry[]> => { | ||
return [...(await this.themeDocset.objects()), ...undocumentedObjects.map(toObjectEntry)]; | ||
return [ | ||
...(await this.themeDocset.objects()), | ||
...undocumentedObjects.map((obj) => toObjectEntry(obj)), | ||
...legacyCheckoutEntries, | ||
]; | ||
}); | ||
@@ -67,0 +105,0 @@ |
@@ -301,2 +301,27 @@ import { expect, describe, it } from 'vitest'; | ||
it('should support contextual exceptions for checkout.liquid', async () => { | ||
let offenses: Offense[]; | ||
const contexts: [string, string][] = [ | ||
['locale', 'layout/checkout.liquid'], | ||
['direction', 'layout/checkout.liquid'], | ||
['skip_to_content_link', 'layout/checkout.liquid'], | ||
['checkout_html_classes', 'layout/checkout.liquid'], | ||
['checkout_stylesheets', 'layout/checkout.liquid'], | ||
['checkout_scripts', 'layout/checkout.liquid'], | ||
['content_for_logo', 'layout/checkout.liquid'], | ||
['breadcrumb', 'layout/checkout.liquid'], | ||
['order_summary_toggle', 'layout/checkout.liquid'], | ||
['content_for_order_summary', 'layout/checkout.liquid'], | ||
['alternative_payment_methods', 'layout/checkout.liquid'], | ||
['content_for_footer', 'layout/checkout.liquid'], | ||
['tracking_code', 'layout/checkout.liquid'], | ||
]; | ||
for (const [object, goodPath] of contexts) { | ||
offenses = await runLiquidCheck(UndefinedObject, `{{ ${object} }}`, goodPath); | ||
expect(offenses).toHaveLength(0); | ||
offenses = await runLiquidCheck(UndefinedObject, `{{ ${object} }}`, 'file.liquid'); | ||
expect(offenses).toHaveLength(1); | ||
} | ||
}); | ||
it('should report an offense for forloop/tablerowloop used outside of context', async () => { | ||
@@ -303,0 +328,0 @@ const sourceCode = ` |
@@ -172,2 +172,19 @@ import { | ||
function getContextualObjects(relativePath: string): string[] { | ||
if (relativePath.startsWith('layout/checkout.liquid')) { | ||
return [ | ||
'locale', | ||
'direction', | ||
'skip_to_content_link', | ||
'checkout_html_classes', | ||
'checkout_stylesheets', | ||
'checkout_scripts', | ||
'content_for_logo', | ||
'breadcrumb', | ||
'order_summary_toggle', | ||
'content_for_order_summary', | ||
'alternative_payment_methods', | ||
'content_for_footer', | ||
'tracking_code', | ||
]; | ||
} | ||
if (relativePath.startsWith('sections/')) { | ||
@@ -174,0 +191,0 @@ return ['section', 'predictive_search', 'recommendations']; |
@@ -47,3 +47,3 @@ import lodashSet from 'lodash/set'; | ||
const buildMockDeps = (errors?: any[]): Partial<Dependencies> => ({ | ||
schemaValidators: { | ||
jsonValidationSet: { | ||
async validateSectionSchema() { | ||
@@ -61,2 +61,10 @@ const mockValidator: ValidateFunction = () => { | ||
}, | ||
async sectionSchema() { | ||
return JSON.stringify(VALID_SECTION_SCHEMA); | ||
}, | ||
async translationSchema() { | ||
return '{}'; | ||
}, | ||
}, | ||
@@ -63,0 +71,0 @@ }); |
@@ -56,3 +56,3 @@ import parseToAst, { Location } from 'json-to-ast'; | ||
const validateSectionSchema = await context.schemaValidators?.validateSectionSchema(); | ||
const validateSectionSchema = await context.jsonValidationSet?.validateSectionSchema(); | ||
if (!validateSectionSchema) { | ||
@@ -59,0 +59,0 @@ return; |
@@ -28,6 +28,6 @@ import { | ||
import { AugmentedThemeDocset } from './AugmentedThemeDocset'; | ||
import { AugmentedSchemaValidators } from './AugmentedSchemaValidators'; | ||
import { AugmentedJsonValidationSet } from './AugmentedJsonValidationSet'; | ||
export * from './AugmentedThemeDocset'; | ||
export * from './AugmentedSchemaValidators'; | ||
export * from './AugmentedJsonValidationSet'; | ||
export * from './fixes'; | ||
@@ -59,4 +59,4 @@ export * from './types'; | ||
if (dependencies.schemaValidators && !dependencies.schemaValidators.isAugmented) { | ||
dependencies.schemaValidators = new AugmentedSchemaValidators(dependencies.schemaValidators); | ||
if (dependencies.jsonValidationSet && !dependencies.jsonValidationSet.isAugmented) { | ||
dependencies.jsonValidationSet = new AugmentedJsonValidationSet(dependencies.jsonValidationSet); | ||
} | ||
@@ -63,0 +63,0 @@ |
@@ -15,3 +15,3 @@ import { NodeTypes as LiquidHtmlNodeTypes, LiquidHtmlNode } from '@shopify/liquid-html-parser'; | ||
import { ThemeDocset, JsonSchemaValidators } from './types/theme-liquid-docs'; | ||
import { ThemeDocset, JsonValidationSet } from './types/theme-liquid-docs'; | ||
@@ -265,3 +265,3 @@ export * from './types/theme-liquid-docs'; | ||
themeDocset?: ThemeDocset; | ||
schemaValidators?: JsonSchemaValidators; | ||
jsonValidationSet?: JsonValidationSet; | ||
} | ||
@@ -268,0 +268,0 @@ |
@@ -26,3 +26,3 @@ import { Translations } from '..'; | ||
*/ | ||
export interface JsonSchemaValidators { | ||
export interface JsonValidationSet { | ||
/** Whether it was augmented prior to being passed. */ | ||
@@ -33,2 +33,8 @@ isAugmented?: boolean; | ||
validateSectionSchema(): Promise<ValidateFunction>; | ||
/** Retrieves the JSON schema of the {% schema %} JSON blobs in sections/*.liquid files */ | ||
sectionSchema(): Promise<string>; | ||
/** Retrieves the JSON schema of the locales/*.json files */ | ||
translationSchema(): Promise<string>; | ||
} | ||
@@ -35,0 +41,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
812065
14802