ficdown.js/src/Util.ts

101 lines
2.9 KiB
TypeScript

import { Anchor, Href, BoolHash, AltText } from './Model';
export class Util {
public static regexLib: { [name: string]: () => RegExp } = {
anchors: () => /(\[((?:[^\[\]]+|\[(?:[^\[\]]+|\[(?:[^\[\]]+|\[(?:[^\[\]]+|\[(?:[^\[\]]+|\[(?:[^\[\]]+|\[\])*\])*\])*\])*\])*\])*)\]\([ ]*((?:[^()\s]+|\((?:[^()\s]+|\((?:[^()\s]+|\((?:[^()\s]+|\((?:[^()\s]+|\((?:[^()\s]+|\(\))*\))*\))*\))*\))*\))*)[ ]*((['"])(.*?)\5[ ]*)?\))/gm,
href: () => /^(?:\/([a-zA-Z](?:-?[a-zA-Z0-9])*))?(?:\?((?:!?[a-zA-Z](?:-?[a-zA-Z0-9])*)(?:&!?[a-zA-Z](?:-?[a-zA-Z0-9])*)*)?)?(?:#((?:[a-zA-Z](?:-?[a-zA-Z0-9])*)(?:\+[a-zA-Z](?:-?[a-zA-Z0-9])*)*))?$/,
trim: () => /^\s+|\s+$/g,
altText: () => /^((?:[^|\\]|\\.)*)(?:\|((?:[^|\\]|\\.)+))?$/,
escapeChar: () => /\\(?=[^\\])/g,
emptyListItem: () => /^[ ]*-\s*([\r\n]+|$)/gm,
};
private static matchToAnchor(match: RegExpExecArray): Anchor {
const result = {
anchor: match[1],
text: match[2],
href: match[3],
title: match[6],
};
if(result.href.indexOf('"') === 0 || result.href.indexOf("'") === 0) {
result.title = result.href.substring(1, result.href.length - 1);
result.href = '';
}
return result;
}
public static matchAnchor(text: string): Anchor | undefined {
const match = this.regexLib.anchors().exec(text);
if(match) return this.matchToAnchor(match);
}
public static matchAnchors(text: string): Anchor[] {
let match: RegExpExecArray | null;
const anchors: Anchor[] = [];
const regex = this.regexLib.anchors();
while((match = regex.exec(text)) !== null) {
anchors.push(this.matchToAnchor(match));
}
return anchors;
}
public static matchHref(text: string): Href | undefined {
const match = this.regexLib.href().exec(text);
if(match) {
return {
target: match[1],
conditions: match[2],
toggles: match[3],
};
}
}
public static trimText(text: string): string {
return text.replace(this.regexLib.trim(), '');
}
public static normalize(text: string): string {
return text.toLowerCase().replace(/^\W+|\W+$/g, '').replace(/\W+/g, '-');
}
public static toBoolHash(names: string[]): BoolHash | undefined {
if(names) {
const hash: BoolHash = {};
for(let name of names) {
if(name.indexOf('!') === 0) {
hash[name.substring(1, name.length)] = false;
} else {
hash[name] = true;
}
}
return hash;
}
}
public static conditionsMet(state: BoolHash, conditions?: BoolHash): boolean {
if(!conditions) return true;
for(let [cond, val] of Object.entries(conditions)) {
if((val && !state[cond]) || (!val && state[cond])) {
return false;
}
}
return true;
}
public static splitAltText(text: string): AltText {
const match = this.regexLib.altText().exec(text);
if(match) {
return {
passed: match[1],
failed: match[2],
};
}
return {};
}
}