| /* |
| 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 |