A shell script template engine for generating HTML markup
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

85 lines
1.7 KiB

import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
export class CharacterStream {
constructor() {
this.reset();
}
reset() {
this._data = '';
this.fileName = '';
this._pos = 0;
this.line = 0;
this.column = 0;
}
async loadFile(fileName) {
this.reset();
this.fileName = basename(fileName);
this._data = await readFile(fileName, 'utf-8');
}
peek(length = 1) {
return this._data.substring(this._pos, this._pos + length);
}
peekWhile(predicate) {
let buffer = '';
for (
let offset = 0, c = this._data[this._pos + offset];
c !== undefined && predicate(c);
offset++, c = this._data[this._pos + offset]
) {
buffer += c;
}
return buffer;
}
// Peek first character after any characters that match predicate
peekAfter(predicate) {
const skip = this.peekWhile(predicate);
return this.peek(skip.length + 1).substring(skip.length);
}
isNext(str) {
return this.peek(str.length) === str;
}
next(length = 1) {
const chunk = this.peek(length);
this._pos += chunk.length;
this.line += this._countOccurrences(chunk, '\n');
const lastNewLine = chunk.lastIndexOf('\n');
if (lastNewLine === -1) {
this.column += chunk.length;
} else {
this.column = chunk.length - lastNewLine - 1;
}
return chunk;
}
nextWhile(predicate) {
return this.next(this.peekWhile(predicate).length);
}
_countOccurrences = (str, substr) => {
let count = 0;
let i = 0;
while(true) {
i = str.indexOf(substr, i);
if (i === -1) break;
i += substr.length;
count++;
}
return count;
}
eof() {
return this.peek() === '';
}
}