add tex parsing

This commit is contained in:
Eric Rykwalder 2022-03-09 16:55:54 -05:00
parent 1b3e3db022
commit d149bc1dfd
3 changed files with 128 additions and 0 deletions

View file

@ -28,6 +28,9 @@ const specParser = new SpecParser(parser, {
YF: "YAMLFrontMatter",
ym: "YAMLMarker",
yc: "YAMLContent",
XB: "TexBlock",
XI: "TexInline",
xm: "TexMarker",
});
/*
@ -189,6 +192,60 @@ Line 5}
`
);
test(
"Tex Block (End Leaf)",
`
{P:plaintext}
{XB:{xm:$$}tex content
- still tex
> and still tex
{xm:$$}}
`
);
test(
"Tex Block (Tailing Text)",
`
{XB:{xm:$$}tex content{xm:$$}} {P:plaintext}
`
);
test(
"Tex Block (Unterminated)",
`
{XB:{xm:$$}tex content
# this is never terminated
}`
);
test(
"Tex Inline (1)",
`
{P:plaintext {XI:{xm:$}tex content{xm:$}} more plaintext}
{P:{XI:{xm:$}1.234{xm:$}}}
`
);
test(
"Tex Inline (2)",
`
{P:$not tex$1.234}
{P:$also not tex $}
{P:$ still not tex$}
{P:{XI:{xm:$}actually tex
{xm:$}}}
{P:{XI:{xm:$}tex
more text
{xm:$}}}
`
);
test(
"YAMLFrontMatter",
`

View file

@ -317,6 +317,75 @@ export const TaskList: MarkdownConfig = {
};
/* End Copyright */
export const Tex: MarkdownConfig = {
defineNodes: ["TexBlock", "TexInline", "TexMarker"],
parseBlock: [
{
name: "TexBlock",
endLeaf: (_, line: Line) =>
line.text.slice(line.pos, line.pos + 2) == "$$",
// This is an imperfect match for HyperMD, because
// in HyperMD the block can start even in inline content.
parse(cx: BlockContext, line: Line) {
if (line.text.slice(line.pos, line.pos + 2) != "$$") {
return false;
}
const start = cx.lineStart + line.pos;
const markers = [cx.elt("TexMarker", start, start + 2)];
const regex = /(^|[^\\])\$\$/;
let remaining = line.text.slice(line.pos + 2);
let startOffset = 2;
let match;
while (!(match = regex.exec(remaining)) && cx.nextLine()) {
remaining = line.text;
startOffset = 0;
}
let end;
if (match) {
const lineEnd = match.index + match[0].length + startOffset;
end = cx.lineStart + lineEnd;
markers.push(cx.elt("TexMarker", end - 2, end));
if (
lineEnd == line.text.length ||
/^\s+$/.test(line.text.slice(lineEnd))
) {
cx.nextLine();
} else {
line.pos = line.skipSpace(lineEnd);
}
} else {
end = cx.lineStart + line.text.length;
}
cx.addElement(cx.elt("TexBlock", start, end, markers));
return true;
},
},
],
parseInline: [
{
name: "TexInline",
parse(cx: InlineContext, next: number, pos: number) {
let match = /^\$[^$\s]/.exec(cx.text.slice(pos - cx.offset));
if (!match) {
return -1;
}
const start = pos;
match = /[^\t \\]\$(\D|$)/.exec(cx.text.slice(pos - cx.offset + 1));
if (!match) {
return -1;
}
const end = start + 1 + match.index + 2;
return cx.addElement(
cx.elt("TexInline", start, end, [
cx.elt("TexMarker", start, start + 1),
cx.elt("TexMarker", end - 1, end),
])
);
},
},
],
};
export const YAMLFrontMatter: MarkdownConfig = {
defineNodes: ["YAMLFrontMatter", "YAMLMarker", "YAMLContent"],
parseBlock: [
@ -357,6 +426,7 @@ export const ObsidianMDExtensions = [
Strikethrough,
Table,
TaskList,
Tex,
YAMLFrontMatter,
];

View file

@ -5,5 +5,6 @@ export {
ObsidianMDExtensions,
parser,
TaskList,
Tex,
YAMLFrontMatter,
} from "./extensions";