zhang-wei-jian's picture
:rocket:
7d73cf2
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapLinesColumns = exports.generateMessageFunction = exports.createCodeGenerator = void 0;
const message_compiler_1 = require("@intlify/message-compiler");
const source_map_1 = require("source-map");
const shared_1 = require("@intlify/shared");
function createCodeGenerator(options = {
filename: 'bundle.json',
sourceMap: false,
env: 'development',
forceStringify: false
}) {
const { sourceMap, source, filename } = options;
const _context = Object.assign({
code: '',
column: 1,
line: 1,
offset: 0,
map: undefined,
indentLevel: 0
}, options);
const context = () => _context;
function push(code, node, name) {
_context.code += code;
if (_context.map && node) {
if (node.loc && node.loc !== message_compiler_1.LocationStub) {
addMapping(node.loc.start, name);
}
advancePositionWithSource(_context, code);
}
}
function _newline(n) {
push('\n' + ` `.repeat(n));
}
function indent(withNewLine = true) {
const level = ++_context.indentLevel;
withNewLine && _newline(level);
}
function deindent(withNewLine = true) {
const level = --_context.indentLevel;
withNewLine && _newline(level);
}
function newline() {
_newline(_context.indentLevel);
}
function pushline(code, node, name) {
push(code, node, name);
newline();
}
function addMapping(loc, name) {
_context.map.addMapping({
name,
source: _context.filename,
original: {
line: loc.line,
column: loc.column - 1
},
generated: {
line: _context.line,
column: _context.column - 1
}
});
}
if (sourceMap && source) {
_context.map = new source_map_1.SourceMapGenerator();
_context.map.setSourceContent(filename, source);
}
return {
context,
push,
indent,
deindent,
newline,
pushline
};
}
exports.createCodeGenerator = createCodeGenerator;
function advancePositionWithSource(pos, source, numberOfCharacters = source.length) {
if (pos.offset == null) {
return pos;
}
let linesCount = 0;
let lastNewLinePos = -1;
for (let i = 0; i < numberOfCharacters; i++) {
if (source.charCodeAt(i) === 10 /* newline char code */) {
linesCount++;
lastNewLinePos = i;
}
}
pos.offset += numberOfCharacters;
pos.line += linesCount;
pos.column =
lastNewLinePos === -1
? pos.column + numberOfCharacters
: numberOfCharacters - lastNewLinePos;
return pos;
}
const DETECT_MESSAGE = `Detected HTML in '{msg}' message.`;
const ON_ERROR_NOOP = () => { }; // eslint-disable-line @typescript-eslint/no-empty-function
function parsePath(path) {
return path ? path.join('.') : '';
}
function generateMessageFunction(msg, options, path) {
const env = options.env != null ? options.env : 'development';
const strictMessage = (0, shared_1.isBoolean)(options.strictMessage)
? options.strictMessage
: true;
const escapeHtml = !!options.escapeHtml;
const onError = options.onError || ON_ERROR_NOOP;
const errors = [];
let detecteHtmlInMsg = false;
if ((0, message_compiler_1.detectHtmlTag)(msg)) {
detecteHtmlInMsg = true;
if (strictMessage) {
const errMsg = (0, shared_1.format)(DETECT_MESSAGE, { msg });
onError((0, shared_1.format)(errMsg), {
source: msg,
path: parsePath(path)
});
}
}
const _msg = detecteHtmlInMsg && escapeHtml ? (0, shared_1.escapeHtml)(msg) : msg;
const newOptions = Object.assign({ mode: 'arrow' }, options);
newOptions.onError = (err) => {
if (onError) {
const extra = {
source: msg,
path: parsePath(path),
code: err.code,
domain: err.domain,
location: err.location
};
onError(err.message, extra);
errors.push(err);
}
};
const { code, ast, map } = (0, message_compiler_1.baseCompile)(_msg, newOptions);
const occured = errors.length > 0;
const genCode = !occured
? env === 'development'
? `(()=>{const fn=${code};fn.source=${JSON.stringify(msg)};return fn;})()`
: `${code}`
: _msg;
return { code: genCode, ast, map, errors };
}
exports.generateMessageFunction = generateMessageFunction;
function mapLinesColumns(resMap, codeMaps, inSourceMap) {
if (!resMap) {
return null;
}
const resMapConsumer = new source_map_1.SourceMapConsumer(resMap);
const inMapConsumer = inSourceMap ? new source_map_1.SourceMapConsumer(inSourceMap) : null;
const mergedMapGenerator = new source_map_1.SourceMapGenerator();
let inMapFirstItem = null;
if (inMapConsumer) {
inMapConsumer.eachMapping(m => {
if (inMapFirstItem) {
return;
}
inMapFirstItem = m;
});
}
resMapConsumer.eachMapping(res => {
if (res.originalLine == null) {
return;
}
const map = codeMaps.get(res.name);
if (!map) {
return;
}
let inMapOrigin = null;
if (inMapConsumer) {
inMapOrigin = inMapConsumer.originalPositionFor({
line: res.originalLine,
column: res.originalColumn - 1
});
if (inMapOrigin.source == null) {
inMapOrigin = null;
return;
}
}
const mapConsumer = new source_map_1.SourceMapConsumer(map);
mapConsumer.eachMapping(m => {
mergedMapGenerator.addMapping({
original: {
line: inMapFirstItem
? inMapFirstItem.originalLine + res.originalLine - 2
: res.originalLine,
column: inMapFirstItem
? inMapFirstItem.originalColumn + res.originalColumn
: res.originalColumn
},
generated: {
line: inMapFirstItem
? inMapFirstItem.generatedLine + res.originalLine - 2
: res.originalLine,
// map column with message format compilation code map
column: inMapFirstItem
? inMapFirstItem.generatedColumn +
res.originalColumn +
m.generatedColumn
: res.originalColumn + m.generatedColumn
},
source: inMapOrigin ? inMapOrigin.source : res.source,
name: m.name // message format compilation code
});
});
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const generator = mergedMapGenerator;
// const targetConsumer = inMapConsumer || resMapConsumer
const targetConsumer = inMapConsumer || resMapConsumer;
targetConsumer.sources.forEach((sourceFile) => {
generator._sources.add(sourceFile);
const sourceContent = targetConsumer.sourceContentFor(sourceFile);
if (sourceContent != null) {
mergedMapGenerator.setSourceContent(sourceFile, sourceContent);
}
});
generator._sourceRoot = inSourceMap
? inSourceMap.sourceRoot
: resMap.sourceRoot;
generator._file = inSourceMap ? inSourceMap.file : resMap.file;
return generator.toJSON();
}
exports.mapLinesColumns = mapLinesColumns;