UNPKG

mini-preproc

Version:

A simple, light, and fast text preprocessor implemented as a node transform stream.

132 lines 4.46 kB
// copyright 2020, craigphicks, ISC license 'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createPreprocStream = void 0; const stream_1 = __importDefault(require("stream")); class MiniPreprocError extends Error { constructor(msg) { super("MiniPreprocError: " + msg); } } //const stream = require('stream'); class State { constructor(defs, opts = { strip: false }) { this.defs = { ...defs }; this.opts = { ...opts }; this.done = false; this.ifActive = false; this.ifTrue = false; } isDone() { return this.done; } doLine(linein) { let isCmd = false; let isPrefix = false; if (linein.substring(0, 4) !== "//--") { // no change in state } else { isPrefix = true; if (linein.substring(4, 6) === "IF") { if (this.ifActive) throw new MiniPreprocError('unexpected IF'); this.ifActive = true; let re = /\{\{\s*(\D\w+)\s*\}\}/.exec(linein.substring(6)); if (!re || re.length < 2) throw new MiniPreprocError(`invalid format "${linein.substring(4)}"`); this.ifTrue = Object.keys(this.defs).includes(re[1]) && this.defs[re[1]]; isCmd = true; } else if (linein.substring(4, 8) === "ELSE") { if (!this.ifActive) throw new MiniPreprocError('unexpected ELSE'); this.ifTrue = !this.ifTrue; isCmd = true; } else if (linein.substring(4, 9) === "ENDIF") { if (!this.ifActive) throw new MiniPreprocError('unexpected ENDIF'); this.ifActive = false; isCmd = true; } else if (linein.substring(4, 8) === "STOP") { if (this.ifActive) throw new MiniPreprocError('ENDIF required before STOP'); isCmd = true; this.done = true; } } if (isCmd) return (this.opts.strip ? null : linein); if (!this.ifActive) return linein; if (!this.ifTrue) { if (this.opts.strip) return null; return isPrefix ? linein : '//--' + linein; } return isPrefix ? linein.substring(4) : linein; } // do line } class MiniPreprocTransform extends stream_1.default.Transform { constructor(defs, opts) { super(); this._state = new State(defs, opts); this._leftover = ''; } _transform(chunk, _enc, callback) { try { if (this._state.isDone()) { if (this._leftover) { this.push(this._leftover); this._leftover = ''; } this.push(chunk); callback(); return; } let str = chunk.toString(); if (this._leftover) str = this._leftover + str; let lines = str.split('\n'); this._leftover = lines.splice(-1, 1)[0]; lines.forEach((line) => { if (this._state.isDone()) { this.push(line + '\n'); return; // from iter of forEach } let out = this._state.doLine(line); if (out === null) return; // from iter of forEach if (!Array.isArray(out)) { this.push(out + '\n'); return; // from iter of forEach } out.forEach((x) => { this.push(x + '\n'); }); }); callback(); } catch (e) { callback(e); //this.emit("error",e); } } ; _flush(callback) { if (this._leftover) this.push(this._leftover); this._leftover = ''; callback(); } ; } function createPreprocStream(defs, opts) { return new MiniPreprocTransform(defs, opts); } exports.createPreprocStream = createPreprocStream; //# sourceMappingURL=mini-preproc.js.map