astro-ghostcms/.pnpm-store/v3/files/84/e18fff65b72d3a7538e7960f138...

238 lines
6.8 KiB
Plaintext
Raw Permalink Normal View History

2024-02-14 14:10:47 +00:00
const defaultQuotedOptions = {
escape: 92,
throws: false
};
/**
* Check if given code is a number
*/
function isNumber(code) {
return code > 47 && code < 58;
}
/**
* Check if given character code is alpha code (letter through A to Z)
*/
function isAlpha(code, from, to) {
from = from || 65; // A
to = to || 90; // Z
code &= ~32; // quick hack to convert any char code to uppercase char code
return code >= from && code <= to;
}
/**
* Check if given character code is alpha-numeric (letter through A to Z or number)
*/
function isAlphaNumeric(code) {
return isNumber(code) || isAlpha(code);
}
function isAlphaNumericWord(code) {
return isNumber(code) || isAlphaWord(code);
}
function isAlphaWord(code) {
return code === 95 /* _ */ || isAlpha(code);
}
/**
* Check for Umlauts i.e. ä, Ä, ö, Ö, ü and Ü
*/
function isUmlaut(code) {
return code === 196
|| code == 214
|| code === 220
|| code === 228
|| code === 246
|| code === 252;
}
/**
* Check if given character code is a white-space character: a space character
* or line breaks
*/
function isWhiteSpace(code) {
return code === 32 /* space */
|| code === 9 /* tab */
|| code === 160; /* non-breaking space */
}
/**
* Check if given character code is a space character
*/
function isSpace(code) {
return isWhiteSpace(code)
|| code === 10 /* LF */
|| code === 13; /* CR */
}
/**
* Consumes 'single' or "double"-quoted string from given string, if possible
* @return `true` if quoted string was consumed. The contents of quoted string
* will be available as `stream.current()`
*/
function eatQuoted(stream, options) {
options = Object.assign(Object.assign({}, defaultQuotedOptions), options);
const start = stream.pos;
const quote = stream.peek();
if (stream.eat(isQuote)) {
while (!stream.eof()) {
switch (stream.next()) {
case quote:
stream.start = start;
return true;
case options.escape:
stream.next();
break;
}
}
// If were here then stream wasnt properly consumed.
// Revert stream and decide what to do
stream.pos = start;
if (options.throws) {
throw stream.error('Unable to consume quoted string');
}
}
return false;
}
/**
* Check if given character code is a quote character
*/
function isQuote(code) {
return code === 39 /* ' */ || code === 34 /* " */;
}
/**
* Eats paired characters substring, for example `(foo)` or `[bar]`
* @param open Character code of pair opening
* @param close Character code of pair closing
* @return Returns `true` if character pair was successfully consumed, its
* content will be available as `stream.current()`
*/
function eatPair(stream, open, close, options) {
options = Object.assign(Object.assign({}, defaultQuotedOptions), options);
const start = stream.pos;
if (stream.eat(open)) {
let stack = 1;
let ch;
while (!stream.eof()) {
if (eatQuoted(stream, options)) {
continue;
}
ch = stream.next();
if (ch === open) {
stack++;
}
else if (ch === close) {
stack--;
if (!stack) {
stream.start = start;
return true;
}
}
else if (ch === options.escape) {
stream.next();
}
}
// If were here then paired character cant be consumed
stream.pos = start;
if (options.throws) {
throw stream.error(`Unable to find matching pair for ${String.fromCharCode(open)}`);
}
}
return false;
}
/**
* A streaming, character code-based string reader
*/
class Scanner {
constructor(str, start, end) {
if (end == null && typeof str === 'string') {
end = str.length;
}
this.string = str;
this.pos = this.start = start || 0;
this.end = end || 0;
}
/**
* Returns true only if the stream is at the end of the file.
*/
eof() {
return this.pos >= this.end;
}
/**
* Creates a new stream instance which is limited to given `start` and `end`
* range. E.g. its `eof()` method will look at `end` property, not actual
* stream end
*/
limit(start, end) {
return new Scanner(this.string, start, end);
}
/**
* Returns the next character code in the stream without advancing it.
* Will return NaN at the end of the file.
*/
peek() {
return this.string.charCodeAt(this.pos);
}
/**
* Returns the next character in the stream and advances it.
* Also returns <code>undefined</code> when no more characters are available.
*/
next() {
if (this.pos < this.string.length) {
return this.string.charCodeAt(this.pos++);
}
}
/**
* `match` can be a character code or a function that takes a character code
* and returns a boolean. If the next character in the stream 'matches'
* the given argument, it is consumed and returned.
* Otherwise, `false` is returned.
*/
eat(match) {
const ch = this.peek();
const ok = typeof match === 'function' ? match(ch) : ch === match;
if (ok) {
this.next();
}
return ok;
}
/**
* Repeatedly calls <code>eat</code> with the given argument, until it
* fails. Returns <code>true</code> if any characters were eaten.
*/
eatWhile(match) {
const start = this.pos;
while (!this.eof() && this.eat(match)) { /* */ }
return this.pos !== start;
}
/**
* Backs up the stream n characters. Backing it up further than the
* start of the current token will cause things to break, so be careful.
*/
backUp(n) {
this.pos -= (n || 1);
}
/**
* Get the string between the start of the current token and the
* current stream position.
*/
current() {
return this.substring(this.start, this.pos);
}
/**
* Returns substring for given range
*/
substring(start, end) {
return this.string.slice(start, end);
}
/**
* Creates error object with current stream state
*/
error(message, pos = this.pos) {
return new ScannerError(`${message} at ${pos + 1}`, pos, this.string);
}
}
class ScannerError extends Error {
constructor(message, pos, str) {
super(message);
this.pos = pos;
this.string = str;
}
}
export { ScannerError, Scanner as default, eatPair, eatQuoted, isAlpha, isAlphaNumeric, isAlphaNumericWord, isAlphaWord, isNumber, isQuote, isSpace, isUmlaut, isWhiteSpace };
//# sourceMappingURL=scanner.js.map