72 lines
2 KiB
TypeScript
72 lines
2 KiB
TypeScript
export type DistinguisherParser<T> = (distinguisher: string) => T;
|
|
export type DocumentParser<T> = (document: string[]) => T;
|
|
|
|
const LEADING_WHITESPACE = /^([ \t]+)/;
|
|
const ENTRY = /^(.+?):\s*(.*)/;
|
|
|
|
export class Idv {
|
|
collections: Record<string, undefined | [string, string[]][]> = {};
|
|
|
|
public static parse(input: string): Idv {
|
|
const lines = input.split("\n").map((line) => line.trimEnd());
|
|
return Idv.parseLines(lines);
|
|
}
|
|
static parseLines(input: string[]): Idv {
|
|
const idv = new Idv();
|
|
let currentDocument: string[] = [];
|
|
|
|
input.forEach((line) => {
|
|
const indent = LEADING_WHITESPACE.exec(line)?.[1];
|
|
if (indent) {
|
|
// TODO
|
|
} else if (line == "") {
|
|
// TODO
|
|
} else if (line[0] == "#") {
|
|
// skip
|
|
} else {
|
|
const matches = ENTRY.exec(line);
|
|
if (matches) {
|
|
const [, collection, distinguisher] = matches;
|
|
|
|
if (idv.collections[collection] == undefined) {
|
|
idv.collections[collection] = [];
|
|
}
|
|
|
|
currentDocument = [];
|
|
idv.collections[collection].push([distinguisher, currentDocument]);
|
|
} else {
|
|
throw new Error("Failed to parse a property");
|
|
}
|
|
}
|
|
});
|
|
|
|
return idv;
|
|
}
|
|
|
|
public getProperty<T>(
|
|
name: string,
|
|
parseDistinguisher: DistinguisherParser<T>,
|
|
parseDocument: DocumentParser<T>
|
|
): T | null {
|
|
const firstEntry = this.collections[name]?.[0];
|
|
return firstEntry && firstEntry[1].length > 0
|
|
? parseDocument(firstEntry[1])
|
|
: firstEntry?.[0]
|
|
? parseDistinguisher(firstEntry[0])
|
|
: null;
|
|
}
|
|
|
|
public getList<T>(
|
|
name: string,
|
|
parseDistinguisher: DistinguisherParser<T>,
|
|
parseDocument: DocumentParser<T>
|
|
): T[] {
|
|
return (this.collections[name] ?? []).map(([distinguisher, document]) =>
|
|
document.length > 0
|
|
? parseDocument(document)
|
|
: parseDistinguisher(distinguisher)
|
|
);
|
|
}
|
|
}
|
|
|
|
export const StringFromDocument = (lines: string[]) => lines.join("\n");
|