UNPKG

@shopify/theme-language-server-common

Version:

<h1 align="center" style="position: relative;" > <br> <img src="https://github.com/Shopify/theme-check-vscode/blob/main/images/shopify_glyph.png?raw=true" alt="logo" width="141" height="160"> <br> Theme Language Server </h1>

100 lines 4.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.contextualizedLabel = exports.fileMatch = exports.TranslationFileContributions = void 0; const theme_check_common_1 = require("@shopify/theme-check-common"); const translations_1 = require("../translations"); function nodeAtLocation(ast, location) { return location.reduce((value, segment) => { var _a; if (value && typeof value !== 'string') { switch (value.type) { case 'Object': { return (_a = value.children.find((child) => child.key.value === segment)) === null || _a === void 0 ? void 0 : _a.value; } case 'Array': { if (typeof segment !== 'number') return undefined; return value.children[segment]; } case 'Identifier': { return undefined; // trying to [segment] onto a string or number } case 'Literal': { return undefined; // trying to [segment] onto a string or number } case 'Property': { return undefined; // this shouldn't be happening } } } }, ast); } const nothing = undefined; class TranslationFileContributions { constructor(documentManager) { this.documentManager = documentManager; this.filePatterns = [/^.*\/locales\/[^\/]*\.json$/]; } getInfoContribution(uri, location) { // TODO: This is a hack to get around the fact that the JSON language service // actually is not typed properly and performs "if-undefined-skip" logic. // https://github.com/microsoft/vscode-json-languageservice/pull/222 // would fix this, but it's not merged yet. if (!fileMatch(uri, this.filePatterns)) return nothing; const doc = this.documentManager.get(uri); if (!doc || location.length === 0 || doc.type !== theme_check_common_1.SourceCodeType.JSON) return nothing; const ast = doc.ast; if (ast instanceof Error) return nothing; const node = nodeAtLocation(ast, location); switch (true) { // Because the JSON language service doesn't support composition of hover info, // We have to hardcode the docs for the translation file schema here. case ['zero', 'one', 'two', 'few', 'many', 'other'].includes(location.at(-1)): { if (!node || node.type !== 'Literal' || typeof node.value !== 'string') { return Promise.resolve([`Pluralized translations should have a string value`]); } return Promise.resolve([contextualizedLabel(uri, location.slice(0, -1), node.value)]); } case location.at(-1).toString().endsWith('_html'): { if (!node || node.type !== 'Literal' || typeof node.value !== 'string') { return Promise.resolve([`Translations ending in '_html' should have a string value`]); } return Promise.resolve([ contextualizedLabel(uri, location, node.value), `The '_html' suffix prevents the HTML content from being escaped.`, ]); } default: { if (!node || node.type !== 'Literal' || typeof node.value !== 'string') { return Promise.resolve([`Translation group: ${location.join('.')}`]); } return Promise.resolve([contextualizedLabel(uri, location, node.value)]); } } } async collectDefaultCompletions(uri, result) { } async collectPropertyCompletions(uri, location, currentWord, addValue, isLast, result) { } async collectValueCompletions(uri, location, propertyKey, result) { } } exports.TranslationFileContributions = TranslationFileContributions; function fileMatch(uri, patterns) { return patterns.some((pattern) => pattern.test(uri)); } exports.fileMatch = fileMatch; function contextualizedLabel(uri, str, value) { if (uri.includes('.schema')) { return marked(`"t:${str.join('.')}"`, 'json'); } else { const params = (0, translations_1.extractParams)(value); return marked(`{{ '${str.join('.')}' | t${(0, translations_1.paramsString)(params)} }}`, 'liquid'); } } exports.contextualizedLabel = contextualizedLabel; function marked(value, language = 'liquid') { return { language, value }; } //# sourceMappingURL=TranslationFileContributions.js.map