/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const base64VLQ = require("./base64-vlq"); const getNumberOfLines = require("./helpers").getNumberOfLines; const getUnfinishedLine = require("./helpers").getUnfinishedLine; const LINE_MAPPING = ";AACA"; class SourceNode { constructor(generatedCode, source, originalSource, startingLine) { this.generatedCode = generatedCode; this.originalSource = originalSource; this.source = source; this.startingLine = startingLine || 1; this._numberOfLines = getNumberOfLines(this.generatedCode); this._endsWithNewLine = generatedCode[generatedCode.length - 1] === "\n"; } clone() { return new SourceNode(this.generatedCode, this.source, this.originalSource, this.startingLine); } getGeneratedCode() { return this.generatedCode; } addGeneratedCode(code) { this.generatedCode += code; this._numberOfLines += getNumberOfLines(code); this._endsWithNewLine = code[code.length - 1] === "\n"; } getMappings(mappingsContext) { if(!this.generatedCode) return ""; const lines = this._numberOfLines; const sourceIdx = mappingsContext.ensureSource(this.source, this.originalSource); let mappings = "A"; // generated column 0 if(mappingsContext.unfinishedGeneratedLine) mappings = "," + base64VLQ.encode(mappingsContext.unfinishedGeneratedLine); mappings += base64VLQ.encode(sourceIdx - mappingsContext.currentSource); // source index mappings += base64VLQ.encode(this.startingLine - mappingsContext.currentOriginalLine); // original line index mappings += "A"; // original column 0 mappingsContext.currentSource = sourceIdx; mappingsContext.currentOriginalLine = this.startingLine + lines - 1; const unfinishedGeneratedLine = mappingsContext.unfinishedGeneratedLine = getUnfinishedLine(this.generatedCode) mappings += Array(lines).join(LINE_MAPPING); if(unfinishedGeneratedLine === 0) { mappings += ";"; } else { if(lines !== 0) { mappings += LINE_MAPPING; } mappingsContext.currentOriginalLine++; } return mappings; } mapGeneratedCode(fn) { throw new Error("Cannot map generated code on a SourceMap. Normalize to SingleLineNode first."); } getNormalizedNodes() { var results = []; var currentLine = this.startingLine; var generatedCode = this.generatedCode; var index = 0; var indexEnd = generatedCode.length; while(index < indexEnd) { // get one generated line var nextLine = generatedCode.indexOf("\n", index) + 1; if(nextLine === 0) nextLine = indexEnd; var lineGenerated = generatedCode.substr(index, nextLine - index); results.push(new SingleLineNode(lineGenerated, this.source, this.originalSource, currentLine)); // move cursors index = nextLine; currentLine++; } return results; } merge(otherNode) { if(otherNode instanceof SourceNode) { return this.mergeSourceNode(otherNode); } else if(otherNode instanceof SingleLineNode) { return this.mergeSingleLineNode(otherNode); } return false; } mergeSourceNode(otherNode) { if(this.source === otherNode.source && this._endsWithNewLine && this.startingLine + this._numberOfLines === otherNode.startingLine) { this.generatedCode += otherNode.generatedCode; this._numberOfLines += otherNode._numberOfLines; this._endsWithNewLine = otherNode._endsWithNewLine; return this; } return false; } mergeSingleLineNode(otherNode) { if(this.source === otherNode.source && this._endsWithNewLine && this.startingLine + this._numberOfLines === otherNode.line && otherNode._numberOfLines <= 1) { this.addSingleLineNode(otherNode); return this; } return false; } addSingleLineNode(otherNode) { this.generatedCode += otherNode.generatedCode; this._numberOfLines += otherNode._numberOfLines this._endsWithNewLine = otherNode._endsWithNewLine; } } module.exports = SourceNode; const SingleLineNode = require("./SingleLineNode"); // circular dependency