|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- "use strict";
- /**
- * Code generator for i18n js resource
- */
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.generate = void 0;
- const shared_1 = require("@intlify/shared");
- const acorn_1 = require("acorn");
- const escodegen_1 = require("escodegen");
- const estree_walker_1 = require("estree-walker");
- const codegen_1 = require("./codegen");
- /**
- * @internal
- */
- function generate(targetSource, { type = 'plain', bridge = false, exportESM = false, filename = 'vue-i18n-loader.js', inSourceMap = undefined, locale = '', isGlobal = false, sourceMap = false, env = 'development', forceStringify = false, onError = undefined, strictMessage = true, escapeHtml = false, useClassComponent = false, allowDynamic = false }, injector) {
- const target = Buffer.isBuffer(targetSource)
- ? targetSource.toString()
- : targetSource;
- const value = target;
- const options = {
- type,
- bridge,
- exportESM,
- source: value,
- sourceMap,
- locale,
- isGlobal,
- inSourceMap,
- env,
- filename,
- forceStringify,
- onError,
- strictMessage,
- escapeHtml,
- useClassComponent
- };
- const generator = (0, codegen_1.createCodeGenerator)(options);
- const ast = (0, acorn_1.parse)(value, {
- ecmaVersion: 'latest',
- sourceType: 'module',
- sourceFile: filename,
- allowImportExportEverywhere: true
- });
- const exportResult = scanAst(ast);
- if (!allowDynamic) {
- // if (!astExportDefaultWithObject.length) {
- if (!exportResult || exportResult !== 'object') {
- throw new Error(`You need to define an object as the locale message with 'export default'.`);
- }
- }
- else {
- if (!exportResult) {
- throw new Error(`You need to define 'export default' that will return the locale messages.`);
- }
- if (exportResult !== 'object') {
- /**
- * NOTE:
- * If `allowDynamic` is `true`, do not transform the code by this function, return it as is.
- * This means that the user **must transform locale messages ownself**.
- * Especially at the production, you need to do locale messages pre-compiling.
- */
- return {
- ast,
- code: value,
- map: inSourceMap
- };
- }
- }
- const codeMaps = generateNode(generator, ast, options, injector);
- const { code, map } = generator.context();
- // if (map) {
- // const s = new SourceMapConsumer((map as any).toJSON())
- // s.eachMapping(m => {
- // console.log('sourcemap json', m)
- // })
- // }
- // prettier-ignore
- const newMap = map
- ? (0, codegen_1.mapLinesColumns)(map.toJSON(), codeMaps, inSourceMap) || null // eslint-disable-line @typescript-eslint/no-explicit-any
- : null;
- return {
- ast,
- code,
- map: newMap != null ? newMap : undefined
- };
- }
- exports.generate = generate;
- function scanAst(ast) {
- if (ast.type !== 'Program') {
- throw new Error('Invalid AST: does not have Program node');
- }
- let ret = false;
- for (const node of ast.body) {
- if (node.type === 'ExportDefaultDeclaration') {
- if (node.declaration.type === 'ObjectExpression') {
- ret = 'object';
- break;
- }
- else if (node.declaration.type === 'FunctionDeclaration') {
- ret = 'function';
- break;
- }
- else if (node.declaration.type === 'ArrowFunctionExpression') {
- ret = 'arrow-function';
- break;
- }
- }
- }
- return ret;
- }
- function generateNode(generator, node, options, injector) {
- const propsCountStack = [];
- const pathStack = [];
- const itemsCountStack = [];
- const skipStack = [];
- const { forceStringify } = generator.context();
- const codeMaps = new Map();
- const { type, bridge, exportESM, sourceMap, isGlobal, locale, useClassComponent } = options;
- const componentNamespace = '_Component';
- (0, estree_walker_1.walk)(node, {
- /**
- * NOTE:
- * force cast to Node of `estree-walker@3.x`,
- * because `estree-walker@3.x` is not dual packages,
- * so it's support only esm only ...
- */
- // @ts-ignore
- enter(node, parent) {
- switch (node.type) {
- case 'Program':
- if (type === 'plain') {
- generator.push(`const resource = `);
- }
- else if (type === 'sfc') {
- // for 'sfc'
- const variableName = type === 'sfc' ? (!isGlobal ? '__i18n' : '__i18nGlobal') : '';
- const localeName = type === 'sfc' ? (locale != null ? locale : `""`) : '';
- const exportSyntax = bridge
- ? exportESM
- ? `export default`
- : `module.exports =`
- : `export default`;
- generator.push(`${exportSyntax} function (Component) {`);
- generator.indent();
- // prettier-ignore
- const componentVariable = bridge
- ? `Component.options || Component`
- : useClassComponent
- ? `Component.__o || Component`
- : `Component`;
- // prettier-ignore
- generator.pushline(`const ${componentNamespace} = ${componentVariable}`);
- generator.pushline(`${componentNamespace}.${variableName} = ${componentNamespace}.${variableName} || []`);
- generator.push(`${componentNamespace}.${variableName}.push({`);
- generator.indent();
- generator.pushline(`"locale": ${JSON.stringify(localeName)},`);
- generator.push(`"resource": `);
- }
- break;
- case 'ObjectExpression':
- generator.push(`{`);
- generator.indent();
- propsCountStack.push(node.properties.length);
- if (parent != null && parent.type === 'ArrayExpression') {
- const lastIndex = itemsCountStack.length - 1;
- const currentCount = parent.elements.length - itemsCountStack[lastIndex];
- pathStack.push(currentCount.toString());
- itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
- }
- break;
- case 'Property':
- if (parent != null && parent.type === 'ObjectExpression') {
- if (node != null) {
- if (isJSONablePrimitiveLiteral(node.value) &&
- (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
- // prettier-ignore
- const name = node.key.type === 'Literal'
- ? String(node.key.value)
- : node.key.name;
- if ((node.value.type === 'Literal' &&
- (0, shared_1.isString)(node.value.value)) ||
- node.value.type === 'TemplateLiteral') {
- const value = getValue(node.value);
- generator.push(`${JSON.stringify(name)}: `);
- pathStack.push(name);
- const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
- sourceMap && map != null && codeMaps.set(value, map);
- generator.push(`${code}`, node.value, value);
- skipStack.push(false);
- }
- else {
- const value = getValue(node.value);
- if (forceStringify) {
- const strValue = JSON.stringify(value);
- generator.push(`${JSON.stringify(name)}: `);
- pathStack.push(name);
- const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
- sourceMap && map != null && codeMaps.set(strValue, map);
- generator.push(`${code}`, node.value, strValue);
- }
- else {
- generator.push(`${JSON.stringify(name)}: ${JSON.stringify(value)}`);
- pathStack.push(name);
- }
- skipStack.push(false);
- }
- }
- else if ((node.value.type === 'FunctionExpression' ||
- node.value.type === 'ArrowFunctionExpression') &&
- (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
- // prettier-ignore
- const name = node.key.type === 'Literal'
- ? String(node.key.value)
- : node.key.name;
- generator.push(`${JSON.stringify(name)}: `);
- pathStack.push(name);
- const code = (0, escodegen_1.generate)(node.value);
- generator.push(`${code}`, node.value, code);
- skipStack.push(false);
- }
- else if ((node.value.type === 'ObjectExpression' ||
- node.value.type === 'ArrayExpression') &&
- (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
- // prettier-ignore
- const name = node.key.type === 'Literal'
- ? String(node.key.value)
- : node.key.name;
- generator.push(`${JSON.stringify(name)}: `);
- pathStack.push(name);
- }
- else {
- // for Regex, function, etc.
- skipStack.push(true);
- }
- }
- const lastIndex = propsCountStack.length - 1;
- propsCountStack[lastIndex] = --propsCountStack[lastIndex];
- }
- break;
- case 'ArrayExpression':
- generator.push(`[`);
- generator.indent();
- if (parent != null && parent.type === 'ArrayExpression') {
- const lastIndex = itemsCountStack.length - 1;
- const currentCount = parent.elements.length - itemsCountStack[lastIndex];
- pathStack.push(currentCount.toString());
- itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
- }
- itemsCountStack.push(node.elements.length);
- break;
- default:
- if (node != null && parent != null) {
- if (parent.type === 'ArrayExpression') {
- const lastIndex = itemsCountStack.length - 1;
- const currentCount = parent.elements.length - itemsCountStack[lastIndex];
- pathStack.push(currentCount.toString());
- if (isJSONablePrimitiveLiteral(node)) {
- if ((node.type === 'Literal' && (0, shared_1.isString)(node.value)) ||
- node.type === 'TemplateLiteral') {
- const value = getValue(node);
- const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
- sourceMap && map != null && codeMaps.set(value, map);
- generator.push(`${code}`, node, value);
- }
- else {
- const value = getValue(node);
- if (forceStringify) {
- const strValue = JSON.stringify(value);
- const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
- sourceMap && map != null && codeMaps.set(strValue, map);
- generator.push(`${code}`, node, strValue);
- }
- else {
- generator.push(`${JSON.stringify(value)}`);
- }
- }
- skipStack.push(false);
- }
- else {
- // for Regex, function, etc.
- skipStack.push(true);
- }
- itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
- }
- }
- else {
- // ...
- }
- break;
- }
- },
- /**
- * NOTE:
- * force cast to Node of `estree-walker@3.x`,
- * because `estree-walker@3.x` is not dual packages,
- * so it's support only esm only ...
- */
- // @ts-ignore
- leave(node, parent) {
- switch (node.type) {
- case 'Program':
- if (type === 'sfc') {
- generator.deindent();
- generator.push(`})`);
- if (bridge && injector) {
- generator.newline();
- generator.pushline(`${componentNamespace}.__i18nBridge = ${componentNamespace}.__i18nBridge || []`);
- generator.pushline(`${componentNamespace}.__i18nBridge.push('${injector()}')`);
- generator.pushline(`delete ${componentNamespace}._Ctor`);
- }
- generator.deindent();
- generator.pushline(`}`);
- }
- else if (type === 'plain') {
- generator.push(`\n`);
- generator.push('export default resource');
- }
- break;
- case 'ObjectExpression':
- if (propsCountStack[propsCountStack.length - 1] === 0) {
- pathStack.pop();
- propsCountStack.pop();
- }
- generator.deindent();
- generator.push(`}`);
- if (parent != null && parent.type === 'ArrayExpression') {
- if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
- pathStack.pop();
- generator.pushline(`,`);
- }
- }
- break;
- case 'Property':
- if (parent != null && parent.type === 'ObjectExpression') {
- if (propsCountStack[propsCountStack.length - 1] !== 0) {
- pathStack.pop();
- if (!skipStack.pop()) {
- generator.pushline(`,`);
- }
- }
- }
- break;
- case 'ArrayExpression':
- if (itemsCountStack[itemsCountStack.length - 1] === 0) {
- pathStack.pop();
- itemsCountStack.pop();
- }
- generator.deindent();
- generator.push(`]`);
- if (parent != null && parent.type === 'ArrayExpression') {
- if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
- pathStack.pop();
- if (!skipStack.pop()) {
- generator.pushline(`,`);
- }
- }
- }
- break;
- case 'Literal':
- if (parent != null && parent.type === 'ArrayExpression') {
- if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
- pathStack.pop();
- if (!skipStack.pop()) {
- generator.pushline(`,`);
- }
- }
- else {
- if (!skipStack.pop()) {
- generator.pushline(`,`);
- }
- }
- }
- break;
- default:
- break;
- }
- }
- });
- return codeMaps;
- }
- function isJSONablePrimitiveLiteral(node) {
- return ((node.type === 'Literal' &&
- ((0, shared_1.isString)(node.value) ||
- (0, shared_1.isNumber)(node.value) ||
- (0, shared_1.isBoolean)(node.value) ||
- node.value === null)) ||
- node.type === 'TemplateLiteral');
- // NOTE: the following code is same the above code
- /*
- if (node.type === 'Literal') {
- if (
- isString(node.value) ||
- isNumber(node.value) ||
- isBoolean(node.value) ||
- node.value === null
- ) {
- return true
- } else if (isRegExp(node.value)) {
- return false
- } else {
- return false
- }
- } else if (node.type === 'TemplateLiteral') {
- return true
- } else {
- return false
- }
- */
- }
- function getValue(node) {
- // prettier-ignore
- return node.type === 'Literal'
- ? node.value
- : node.type === 'TemplateLiteral'
- ? node.quasis.map(quasi => quasi.value.cooked).join('')
- : undefined;
- }
|