core/matchers/markdown.matcher.ts
core/matchers/markdown.matcher.ts is a file in Bane's Lab Site. 88 lines of code and 22 definitions.
import {
BULLET_MARKS,
COMMENT_CLOSE,
COMMENT_OPEN,
FRONTMATTER_FENCE,
HEADING_MARK,
HEADING_MAX_LEVEL,
ORDERED_CLOSE,
RULE_CHARS,
RULE_MIN_LENGTH,
TABLE_PIPE,
TABLE_RULE_CHARS,
} from "#configuration/constants/markdown.constants";
import { DIGITS } from "#configuration/constants/syntax.constants";
import { LINE_BREAK } from "#configuration/constants/code.constants";
import { SPACE } from "#configuration/constants/document.constants";
const charsOf = function charsOf(text: string): string[] {
const chars: string[] = [];
for (const char of text) {
chars.push(char);
}
return chars;
};
export const isRule = function isRule(line: string): boolean {
const chars = charsOf(line.trim()).filter((char) => char !== SPACE);
const [first] = chars;
return (
chars.length >= RULE_MIN_LENGTH &&
first !== undefined &&
RULE_CHARS.has(first) &&
chars.every((char) => char === first)
);
};
export const headingLevel = function headingLevel(line: string): number {
let level = 0;
while (level < line.length && line.charAt(level) === HEADING_MARK) {
level += 1;
}
return level > 0 && level <= HEADING_MAX_LEVEL && line.charAt(level) === SPACE ? level : 0;
};
export const bulletText = function bulletText(line: string): string | null {
const trimmed = line.trim();
return BULLET_MARKS.has(trimmed.charAt(0)) && trimmed.charAt(1) === SPACE ? trimmed.slice(2) : null;
};
export const orderedText = function orderedText(line: string): string | null {
const trimmed = line.trim();
let digits = 0;
while (digits < trimmed.length && DIGITS.includes(trimmed.charAt(digits))) {
digits += 1;
}
const closes = trimmed.charAt(digits) === ORDERED_CLOSE && trimmed.charAt(digits + 1) === SPACE;
return digits > 0 && closes ? trimmed.slice(digits + 2) : null;
};
export const cellsOf = function cellsOf(line: string): string[] {
const trimmed = line.trim();
const inner = trimmed.startsWith(TABLE_PIPE) ? trimmed.slice(1) : trimmed;
const body = inner.endsWith(TABLE_PIPE) ? inner.slice(0, -1) : inner;
return body.split(TABLE_PIPE).map((cell) => cell.trim());
};
export const isTableRule = function isTableRule(line: string): boolean {
const trimmed = line.trim();
return (
trimmed.includes(TABLE_PIPE) &&
charsOf(trimmed).every((char) => char === TABLE_PIPE || TABLE_RULE_CHARS.has(char))
);
};
const uncommented = function uncommented(text: string): string {
let out = "";
let at = 0;
while (at < text.length) {
const open = text.indexOf(COMMENT_OPEN, at);
if (open === -1) {
return out + text.slice(at);
}
const close = text.indexOf(COMMENT_CLOSE, open + COMMENT_OPEN.length);
out += text.slice(at, open);
at = close === -1 ? text.length : close + COMMENT_CLOSE.length;
}
return out;
};
export const bodyLines = function bodyLines(text: string): string[] {
const lines = uncommented(text).split(LINE_BREAK);
if (lines[0]?.trim() !== FRONTMATTER_FENCE) {
return lines;
}
const close = lines.findIndex((line, index) => index > 0 && line.trim() === FRONTMATTER_FENCE);
return close === -1 ? lines : lines.slice(close + 1);
};