72 lines
1.7 KiB
Plaintext
72 lines
1.7 KiB
Plaintext
import { Line, Tokens, BlockMarkers, Markers } from '../primitives.js';
|
|
import { seedTokens, splitSpace, splitCR } from '../util.js';
|
|
|
|
export interface Options {
|
|
startLine: number;
|
|
markers: BlockMarkers;
|
|
}
|
|
|
|
export type Parser = (source: string) => Line[] | null;
|
|
|
|
export default function getParser({
|
|
startLine = 0,
|
|
markers = Markers,
|
|
}: Partial<Options> = {}): Parser {
|
|
let block: Line[] | null = null;
|
|
let num = startLine;
|
|
|
|
return function parseSource(source: string): Line[] | null {
|
|
let rest = source;
|
|
const tokens: Tokens = seedTokens();
|
|
|
|
[tokens.lineEnd, rest] = splitCR(rest);
|
|
[tokens.start, rest] = splitSpace(rest);
|
|
|
|
if (
|
|
block === null &&
|
|
rest.startsWith(markers.start) &&
|
|
!rest.startsWith(markers.nostart)
|
|
) {
|
|
block = [];
|
|
tokens.delimiter = rest.slice(0, markers.start.length);
|
|
rest = rest.slice(markers.start.length);
|
|
[tokens.postDelimiter, rest] = splitSpace(rest);
|
|
}
|
|
|
|
if (block === null) {
|
|
num++;
|
|
return null;
|
|
}
|
|
|
|
const isClosed = rest.trimRight().endsWith(markers.end);
|
|
|
|
if (
|
|
tokens.delimiter === '' &&
|
|
rest.startsWith(markers.delim) &&
|
|
!rest.startsWith(markers.end)
|
|
) {
|
|
tokens.delimiter = markers.delim;
|
|
rest = rest.slice(markers.delim.length);
|
|
[tokens.postDelimiter, rest] = splitSpace(rest);
|
|
}
|
|
|
|
if (isClosed) {
|
|
const trimmed = rest.trimRight();
|
|
tokens.end = rest.slice(trimmed.length - markers.end.length);
|
|
rest = trimmed.slice(0, -markers.end.length);
|
|
}
|
|
|
|
tokens.description = rest;
|
|
block.push({ number: num, source, tokens });
|
|
num++;
|
|
|
|
if (isClosed) {
|
|
const result = block.slice();
|
|
block = null;
|
|
return result;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
}
|