vue-simple-compiler
Version:
A lib to compile Vue Single-File Component into plain JavaScript & CSS.
206 lines (205 loc) • 7.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.shiftSourceMap = exports.bundleSourceMap = exports.chainSourceMap = exports.hackGeneratorProps = exports.getGeneratorSources = exports.getConsumerSources = void 0;
const source_map_1 = require("source-map");
const getConsumerSources = (consumer) => {
// source-map's type definition is incomplete
const con = consumer;
return con.sources;
};
exports.getConsumerSources = getConsumerSources;
const getGeneratorSources = (generator) => {
// source-map's type definition is incomplete
const gen = generator;
return gen._sources.toArray();
};
exports.getGeneratorSources = getGeneratorSources;
const hackGeneratorProps = (generator, props) => {
// source-map's type definition is incomplete
const gen = generator;
if (props.file) {
gen._file = props.file;
}
if (props.sourceRoot) {
gen._sourceRoot = props.sourceRoot;
}
if (props.sources) {
gen._sources = {
toArray() {
return props.sources;
},
indexOf(source) {
return props.sources.indexOf(source);
},
};
}
};
exports.hackGeneratorProps = hackGeneratorProps;
const genJSON = (generator) => {
// source-map's type definition is incomplete
const gen = generator;
return gen.toJSON();
};
/**
* Chain source maps of two code blocks.
* credit: https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/compileTemplate.ts
*/
const chainSourceMap = (oldMap, newMap) => {
if (!oldMap)
return newMap;
if (!newMap)
return oldMap;
const oldMapConsumer = new source_map_1.SourceMapConsumer(oldMap);
const newMapConsumer = new source_map_1.SourceMapConsumer(newMap);
const mergedMapGenerator = new source_map_1.SourceMapGenerator();
newMapConsumer.eachMapping((m) => {
if (m.originalLine == null) {
return;
}
const origPosInOldMap = oldMapConsumer.originalPositionFor({
line: m.originalLine,
column: m.originalColumn,
});
if (origPosInOldMap.source == null) {
return;
}
mergedMapGenerator.addMapping({
generated: {
line: m.generatedLine,
column: m.generatedColumn,
},
original: {
line: origPosInOldMap.line ?? 0,
column: m.originalColumn,
},
source: origPosInOldMap.source,
name: origPosInOldMap.name ?? '',
});
});
const sourceFileSet = new Set((0, exports.getGeneratorSources)(mergedMapGenerator));
(0, exports.getConsumerSources)(oldMapConsumer).forEach((sourceFile) => {
sourceFileSet.add(sourceFile);
});
const sources = Array.from(sourceFileSet);
(0, exports.hackGeneratorProps)(mergedMapGenerator, {
file: oldMap.file,
sourceRoot: oldMap.sourceRoot,
sources,
});
sources.forEach((sourceFile) => {
const sourceContent = oldMapConsumer.sourceContentFor(sourceFile);
if (sourceContent) {
mergedMapGenerator.setSourceContent(sourceFile, sourceContent);
}
});
return genJSON(mergedMapGenerator);
};
exports.chainSourceMap = chainSourceMap;
/**
* Bundle source maps of multiple code blocks into one.
* - assume source roots of all the blocks are the same
* - pick the generated file name from the first block
*/
const bundleSourceMap = (list) => {
if (list.length === 1) {
return list[0];
}
let code = '';
let lineOffset = 0;
const generator = new source_map_1.SourceMapGenerator();
// for hack the source map
let firstSourceMap;
const sourceFileSet = new Set();
const sourceFileMap = new Map();
// const gen = generator as any
list.forEach((block) => {
code += `${block.code}\n`;
if (block.sourceMap) {
firstSourceMap = firstSourceMap || block.sourceMap;
block.sourceMap.sources.forEach((sourceFile, index) => {
sourceFileSet.add(sourceFile);
if (block.sourceMap.sourcesContent[index] &&
!sourceFileMap.has(sourceFile)) {
sourceFileMap.set(sourceFile, block.sourceMap.sourcesContent[index]);
}
});
const consumer = new source_map_1.SourceMapConsumer(block.sourceMap);
consumer.eachMapping((m) => {
generator.addMapping({
generated: {
line: m.generatedLine + lineOffset,
column: m.generatedColumn,
},
original: {
line: m.originalLine,
column: m.originalColumn,
},
source: m.source,
name: m.name,
});
});
}
lineOffset += block.code.split(/\r?\n/).length;
});
if (firstSourceMap) {
const sources = Array.from(sourceFileSet);
(0, exports.hackGeneratorProps)(generator, {
file: firstSourceMap.file,
sourceRoot: firstSourceMap.sourceRoot,
sources,
});
sources.forEach((sourceFile) => {
const sourceContent = sourceFileMap.get(sourceFile);
if (sourceContent) {
generator.setSourceContent(sourceFile, sourceContent);
}
});
}
return { code, sourceMap: genJSON(generator) };
};
exports.bundleSourceMap = bundleSourceMap;
/**
* Shift the source map of a single source file.
* It's used for adjusting the source map when you generate it from a block of the whole file, which causes line offset.
*/
const shiftSourceMap = (map, offset, newFileMap) => {
const consumer = new source_map_1.SourceMapConsumer(map);
const generator = new source_map_1.SourceMapGenerator();
const sourceFileSet = new Set();
const sourceFileMap = new Map();
consumer.eachMapping((m) => {
const source = (newFileMap || {})[m.source] || {
name: m.source,
code: consumer.sourceContentFor(m.source) || '',
};
sourceFileSet.add(source.name);
if (source.code) {
sourceFileMap.set(source.name, source.code);
}
generator.addMapping({
generated: {
line: m.generatedLine,
column: m.generatedColumn,
},
original: {
line: m.originalLine + offset,
column: m.originalColumn,
},
source: source.name,
name: m.name,
});
});
(0, exports.hackGeneratorProps)(generator, {
file: map.file,
sourceRoot: map.sourceRoot,
sources: Array.from(sourceFileSet),
});
Array.from(sourceFileSet).forEach((sourceFile) => {
const sourceContent = sourceFileMap.get(sourceFile);
if (sourceContent) {
generator.setSourceContent(sourceFile, sourceContent);
}
});
return genJSON(generator);
};
exports.shiftSourceMap = shiftSourceMap;