jscc
Version:
Tiny and powerful preprocessor for conditional comments and replacement of compile-time variables in text files
118 lines • 3.96 kB
JavaScript
"use strict";
const remapVars = require("./remap-vars");
/**
* Matches line-ending of win, mac, and unix type
*/
const EOLS = /[^\r\n]+/g;
/**
* Helper class for the `parseChunks` function.
*/
class ParseHelper {
/**
* @param source Original source
* @param props jscc properties
*/
constructor(source, props) {
this.source = source;
this.props = props;
this.lastPos = 0; // keep the next offset to flush
this.output = true; // output state, starts "active"
}
/**
* Final flush. The final output is always in "active" state.
*/
flush() {
return this.commit(this.lastPos, this.source.length);
}
/**
* Write pending changes.
*
* _IMPORTANT:_ `Parser.parse` can change the current jscc values,
* so this function _MUST BE_ called before the parsing to make any
* replacements with the current values.
*
* @param offset Starting position of the matched line
*/
flushPrev(offset) {
if (this.output) {
this.commit(this.lastPos, offset);
}
}
/**
* A line was processed, flush buffers as necessary.
*
* @param start Starting position of the chunk into the original buffer
* @param end Position of the character following the chunk
* @param output The updated output state
* @returns The updated position where to continue the search.
*/
flushLine(start, end, output) {
// Find the start of the next line in the buffer.
if (end < this.source.length) {
end += this.source.substr(end, 2) === '\r\n' ? 2 : 1;
}
if (output !== this.output) {
this.output = output;
this.flushit(start, end);
}
else if (output) {
// flushPrev was already called, so no need to commit
this.remove(start, end);
}
return end;
}
/**
* If the parsed `chunk` seems to contain varnames to replace, call the
* remapVars function which will make the replacement and store the chunk
* into the MagicString intance. Otherwise, do nothing.
*
* _NOTE:_ This function updates `this.lastPos`
*
* @param start Starting position of the chunk into the original buffer
* @param end Position of the character following the chunk
* @returns `true` if the chunk was changed
*/
commit(start, end) {
if (start >= end) {
return false;
}
this.lastPos = end;
// Get the fragment of source where to search varnames to replace
const chunk = this.source.slice(start, end);
// Call remapVars only if a memvar prefix exists in the chunk
return chunk.indexOf('$_') > -1 && remapVars(this.props, chunk, start);
}
/**
* Removes the block from the `start` to the `end` position, inclusive.
*
* _NOTE:_ This function updates `this.lastPos`
*
* @param start Starting position of the chunk into the original buffer
* @param end Position of the character following the chunk
* @returns Position of the character following the removed block.
*/
remove(start, end) {
this.lastPos = end;
const block = this.props.keepLines
? this.source.slice(start, end).replace(EOLS, '') : '';
this.props.magicStr.overwrite(start, end, block);
}
/**
* The output state changed, flush the buffer.
*
* @param start Start of current line
* @param end End of current line
*/
flushit(start, end) {
if (this.output) {
// Output begins, remove previous hidden block.
this.remove(this.lastPos, end);
}
else {
// Output ends, flush the already processed block.
this.commit(this.lastPos, start);
}
}
}
module.exports = ParseHelper;
//# sourceMappingURL=parse-helper.js.map