UNPKG

@lingui/cli

Version:

CLI for working wit message catalogs

157 lines (156 loc) 5.77 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.babelRe = void 0; exports.extractFromFileWithBabel = extractFromFileWithBabel; exports.getBabelParserOptions = getBabelParserOptions; const core_1 = require("@babel/core"); const babel_plugin_extract_messages_1 = __importDefault(require("@lingui/babel-plugin-extract-messages")); const babel_plugin_lingui_macro_1 = __importDefault(require("@lingui/babel-plugin-lingui-macro")); exports.babelRe = new RegExp("\\.(" + [...core_1.DEFAULT_EXTENSIONS, ".ts", ".mts", ".cts", ".tsx"] .map((ext) => ext.slice(1)) .join("|") + ")$", "i"); const inlineSourceMapsRE = new RegExp(/\/[/*][#@]\s+sourceMappingURL=data:application\/json;(?:charset:utf-8;)?base64,/i); /** * Create a source mapper which could read original positions * from either inline sourcemaps or from external passed as `sourceMaps` argument. * * Warning! You have to call destroy method after you finish working with a mapper. * * @param code source code * @param sourceMaps Raw Sourcemaps object to mapping from. Check the https://github.com/mozilla/source-map#new-sourcemapconsumerrawsourcemap */ async function createSourceMapper(code, sourceMaps) { let sourceMapsConsumer; if (sourceMaps) { const { SourceMapConsumer } = await import("source-map"); sourceMapsConsumer = await new SourceMapConsumer(sourceMaps); } else if (code.search(inlineSourceMapsRE) != -1) { const { SourceMapConsumer } = await import("source-map"); const { fromSource } = await import("convert-source-map"); const t = fromSource(code).toObject(); sourceMapsConsumer = await new SourceMapConsumer(t); } return { destroy: () => { if (sourceMapsConsumer) { sourceMapsConsumer.destroy(); } }, originalPositionFor: (origin) => { if (!sourceMapsConsumer) { return origin; } const [_, line, column] = origin; const mappedPosition = sourceMapsConsumer.originalPositionFor({ line, column, }); return [mappedPosition.source, mappedPosition.line, mappedPosition.column]; }, }; } /** * @public * * Low level function used in default Lingui extractor. * This function setup source maps and lingui plugins needed for * extraction process but leaving `parserOptions` up to userland implementation. * * * @example * ```ts * const extractor: ExtractorType = { * ... * async extract(filename, code, onMessageExtracted, ctx) { * return extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, { * // https://babeljs.io/docs/babel-parser#plugins * plugins: [ * "decorators-legacy", * "typescript", * "jsx", * ], * }) * }, * } * ``` */ async function extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, parserOpts, skipMacroPlugin = false) { const mapper = await createSourceMapper(code, ctx === null || ctx === void 0 ? void 0 : ctx.sourceMaps); await (0, core_1.transformAsync)(code, { // don't generate code code: false, babelrc: false, configFile: false, filename: filename, inputSourceMap: ctx === null || ctx === void 0 ? void 0 : ctx.sourceMaps, parserOpts, plugins: [ ...(!skipMacroPlugin ? [ [ babel_plugin_lingui_macro_1.default, { extract: true, linguiConfig: ctx.linguiConfig, }, ], ] : []), [ babel_plugin_extract_messages_1.default, { onMessageExtracted: (msg) => { return onMessageExtracted(Object.assign(Object.assign({}, msg), { origin: mapper.originalPositionFor(msg.origin) })); }, }, ], ], }); mapper.destroy(); } function getBabelParserOptions(filename, parserOptions) { // https://babeljs.io/docs/en/babel-parser#latest-ecmascript-features const parserPlugins = [ "importAttributes", // stage3 "explicitResourceManagement", // stage3, "decoratorAutoAccessors", // stage3, "deferredImportEvaluation", // stage3 ]; if ([/\.ts$/, /\.mts$/, /\.cts$/, /\.tsx$/].some((r) => filename.match(r))) { parserPlugins.push("typescript"); if (parserOptions.tsExperimentalDecorators) { parserPlugins.push("decorators-legacy"); } else { parserPlugins.push("decorators"); } } else { parserPlugins.push("decorators"); if (parserOptions === null || parserOptions === void 0 ? void 0 : parserOptions.flow) { parserPlugins.push("flow"); } } if ([/\.js$/, /\.jsx$/, /\.tsx$/].some((r) => filename.match(r))) { parserPlugins.push("jsx"); } return parserPlugins; } const extractor = { match(filename) { return exports.babelRe.test(filename); }, async extract(filename, code, onMessageExtracted, ctx) { const parserOptions = ctx.linguiConfig.extractorParserOptions; return extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, { plugins: getBabelParserOptions(filename, parserOptions), }); }, }; exports.default = extractor;