UNPKG

@vendure/ngx-translate-extract

Version:
154 lines (153 loc) 6.33 kB
import { parseTemplate, BindingPipe, LiteralPrimitive, Conditional, Binary, LiteralMap, LiteralArray, Interpolation, Call, TmplAstIfBlock, TmplAstSwitchBlock, TmplAstDeferredBlock, TmplAstForLoopBlock, KeyedRead, ASTWithSource, ParenthesizedExpression, } from '@angular/compiler'; import { getNodesFromSwitchBlockTmpl } from '../utils/ast-helpers.js'; import { TranslationCollection } from '../utils/translation.collection.js'; import { isPathAngularComponent, extractComponentInlineTemplate } from '../utils/utils.js'; export const TRANSLATE_PIPE_NAMES = ['translate', 'marker']; function traverseAstNodes(nodes, visitor, accumulator = []) { for (const node of nodes) { if (node) { traverseAstNode(node, visitor, accumulator); } } return accumulator; } function traverseAstNode(node, visitor, accumulator = []) { accumulator.push(...visitor(node)); const children = []; if ('children' in node && node.children) { children.push(...node.children); } if (node instanceof TmplAstForLoopBlock) { children.push(node.empty); } if (node instanceof TmplAstDeferredBlock) { children.push(node.error); children.push(node.loading); children.push(node.placeholder); } if (node instanceof TmplAstIfBlock) { children.push(...node.branches.flatMap((inner) => inner.children)); } if (node instanceof TmplAstSwitchBlock) { const blockChildren = getNodesFromSwitchBlockTmpl(node); children.push(...blockChildren); } return traverseAstNodes(children, visitor, accumulator); } export class PipeParser { extract(source, filePath) { if (filePath && isPathAngularComponent(filePath)) { source = extractComponentInlineTemplate(source); } let collection = new TranslationCollection(); const nodes = this.parseTemplate(source, filePath); const pipes = traverseAstNodes(nodes, (node) => this.findPipesInNode(node)); pipes.forEach((pipe) => { this.parseTranslationKeysFromPipe(pipe).forEach((key) => { if (key === '') { return; } collection = collection.add(key, '', filePath); }); }); return collection; } findPipesInNode(node) { const ret = []; if ('value' in node && node.value instanceof ASTWithSource) { ret.push(...this.getTranslatablesFromAst(node.value.ast)); } if ('attributes' in node && Array.isArray(node.attributes)) { const translatableAttributes = node.attributes.filter((attr) => TRANSLATE_PIPE_NAMES.includes(attr.name)); ret.push(...ret, ...translatableAttributes); } if ('inputs' in node && Array.isArray(node.inputs)) { node.inputs.forEach((input) => { if (input.value instanceof ASTWithSource) { ret.push(...this.getTranslatablesFromAst(input.value.ast)); } }); } if ('templateAttrs' in node && Array.isArray(node.templateAttrs)) { node.templateAttrs.forEach((attr) => { if (attr.value instanceof ASTWithSource) { ret.push(...this.getTranslatablesFromAst(attr.value.ast)); } }); } return ret; } parseTranslationKeysFromPipe(pipeContent) { const ret = []; if (pipeContent instanceof LiteralPrimitive) { ret.push(`${pipeContent.value}`); } else if (pipeContent instanceof Conditional) { ret.push(...this.parseTranslationKeysFromPipe(pipeContent.trueExp)); ret.push(...this.parseTranslationKeysFromPipe(pipeContent.falseExp)); } else if (pipeContent instanceof BindingPipe) { ret.push(...this.parseTranslationKeysFromPipe(pipeContent.exp)); } else if (pipeContent instanceof ParenthesizedExpression) { ret.push(...this.parseTranslationKeysFromPipe(pipeContent.expression)); } else if (this.isLogicalOrNullishCoalescingExpression(pipeContent)) { if (pipeContent.left instanceof LiteralPrimitive) { ret.push(`${pipeContent.left.value}`); } if (pipeContent.right instanceof LiteralPrimitive) { ret.push(`${pipeContent.right.value}`); } } return ret; } getTranslatablesFromAst(ast) { if (ast instanceof BindingPipe) { if (TRANSLATE_PIPE_NAMES.includes(ast.name)) { return [ast, ...this.getTranslatablesFromAsts(ast.args)]; } return this.getTranslatablesFromAsts([ast.exp, ...ast.args]); } if (ast instanceof Interpolation) { return this.getTranslatablesFromAsts(ast.expressions); } if (ast instanceof Conditional) { return this.getTranslatablesFromAsts([ast.trueExp, ast.falseExp]); } if (ast instanceof Binary) { if (ast?.left && ast?.right) { return this.getTranslatablesFromAsts([ast.left, ast.right]); } } if (ast instanceof LiteralMap) { return this.getTranslatablesFromAsts(ast.values); } if (ast instanceof LiteralArray) { return this.getTranslatablesFromAsts(ast.expressions); } if (ast instanceof Call) { return this.getTranslatablesFromAsts(ast.args); } if (ast instanceof KeyedRead) { return this.getTranslatablesFromAsts([ast.receiver, ast.key]); } if (ast instanceof ParenthesizedExpression) { return this.getTranslatablesFromAsts([ast.expression]); } return []; } getTranslatablesFromAsts(asts) { return this.flatten(asts.map((ast) => this.getTranslatablesFromAst(ast))); } flatten(array) { return [].concat(...array); } parseTemplate(template, path) { return parseTemplate(template, path).nodes; } isLogicalOrNullishCoalescingExpression(expr) { return (expr instanceof Binary && (expr.operation === '&&' || expr.operation === '||' || expr.operation === '??')); } }