mirror of
https://github.com/danbulant/lezer-markdown-obsidian
synced 2026-07-06 03:20:34 +00:00
add tex parsing
This commit is contained in:
parent
1b3e3db022
commit
d149bc1dfd
3 changed files with 128 additions and 0 deletions
|
|
@ -28,6 +28,9 @@ const specParser = new SpecParser(parser, {
|
||||||
YF: "YAMLFrontMatter",
|
YF: "YAMLFrontMatter",
|
||||||
ym: "YAMLMarker",
|
ym: "YAMLMarker",
|
||||||
yc: "YAMLContent",
|
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(
|
test(
|
||||||
"YAMLFrontMatter",
|
"YAMLFrontMatter",
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,75 @@ export const TaskList: MarkdownConfig = {
|
||||||
};
|
};
|
||||||
/* End Copyright */
|
/* 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 = {
|
export const YAMLFrontMatter: MarkdownConfig = {
|
||||||
defineNodes: ["YAMLFrontMatter", "YAMLMarker", "YAMLContent"],
|
defineNodes: ["YAMLFrontMatter", "YAMLMarker", "YAMLContent"],
|
||||||
parseBlock: [
|
parseBlock: [
|
||||||
|
|
@ -357,6 +426,7 @@ export const ObsidianMDExtensions = [
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
Table,
|
Table,
|
||||||
TaskList,
|
TaskList,
|
||||||
|
Tex,
|
||||||
YAMLFrontMatter,
|
YAMLFrontMatter,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@ export {
|
||||||
ObsidianMDExtensions,
|
ObsidianMDExtensions,
|
||||||
parser,
|
parser,
|
||||||
TaskList,
|
TaskList,
|
||||||
|
Tex,
|
||||||
YAMLFrontMatter,
|
YAMLFrontMatter,
|
||||||
} from "./extensions";
|
} from "./extensions";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue