core/parsers/layer.parser.ts
core/parsers/layer.parser.ts is a file in GovLab Docs. 72 lines of code and 18 definitions.
import {
LAYER_CLOSE_PREFIX as CLOSE_PREFIX,
LAYER_MARKER_END as MARKER_END,
LAYER_OPEN_PREFIX as OPEN_PREFIX,
} from "#configuration/constants/layer.constants";
import type { ConcernLayer, LayerDefect, LayerSplit } from "#types/markdown.types";
const markerId = function markerId(trimmed: string, prefix: string): string | null {
if (!trimmed.startsWith(prefix) || !trimmed.endsWith(MARKER_END)) {
return null;
}
const inner = trimmed.slice(prefix.length, trimmed.length - MARKER_END.length).trim();
return inner.length > 0 ? inner : null;
};
class LayerParser {
public readonly layers: ConcernLayer[] = [];
public readonly defects: LayerDefect[] = [];
private readonly seen = new Set<string>();
private openId: string | null = null;
private bodyLines: string[] = [];
public feed(raw: string): void {
const trimmed = raw.trim();
const opened = markerId(trimmed, OPEN_PREFIX);
if (opened !== null) {
this.open(opened);
return;
}
const closed = markerId(trimmed, CLOSE_PREFIX);
if (closed !== null) {
this.close(closed);
return;
}
if (this.openId !== null) {
this.bodyLines.push(raw);
}
}
public finish(): void {
if (this.openId !== null) {
this.defects.push({ code: "unclosed-marker", id: this.openId });
}
}
private open(id: string): void {
if (this.openId !== null) {
this.defects.push({ code: "unclosed-marker", id: this.openId });
}
if (this.seen.has(id)) {
this.defects.push({ code: "duplicate-marker", id });
}
this.seen.add(id);
this.openId = id;
this.bodyLines = [];
}
private close(id: string): void {
if (this.openId !== id) {
this.defects.push({ code: "orphan-close", id });
return;
}
this.layers.push({ body: this.bodyLines.join("\n"), id });
this.openId = null;
this.bodyLines = [];
}
}
export const splitConcernLayers = function splitConcernLayers(doc: string): LayerSplit {
const parser = new LayerParser();
for (const raw of doc.split("\n")) {
parser.feed(raw);
}
parser.finish();
return { defects: parser.defects, layers: parser.layers };
};
export const layerOf = function layerOf(doc: string, id: string): string | null {
return splitConcernLayers(doc).layers.find((layer) => layer.id === id)?.body ?? null;
};