feat: add transformations for latex in oxhugofm (#510)

ox-hugo currently supports the following syntax for latex equations:
- https://orgmode.org/manual/LaTeX-fragments.html
- https://ox-hugo.scripter.co/doc/equations

This syntax is supported by mathjax as is mentioned in the ox-hugo documentation.

But quartz uses remark-math which has some issues with the \( \) syntax.
See https://github.com/remarkjs/remark-math/issues/39

This change adds few more transformations to the OxHugoFlavouredMarkdown
plugin, which makes a best effort conversion of this syntax into what
the Quartz Latex transformer plugin supports.

With these changes, the generated files show latex formatting with
default quartz configuration.

Sidenote on `\_` escape by ox-hugo:

ox-hugo escapes, _ using \_, we match against it after we transform
equations into what quartz supports($$ and $).

This could be achieved using lookaround like regex as follows
```js
(?<=(\$|\$\$)[\s\S]*) -> Positive lookbehind for $ or $$
\\_ -> Matches \_
(?=[\s\S]*(?:\1)) Positive lookahead for $ or $$ if matched
const escapedUnderscoreRegex = new RegExp(/(?<=(\$|\$\$)[\s\S]*)\\_(?=[\s\S]*(?:\1))/, "g")
````

But since lookahead/behind can slow things down on large files, we just
look up all equations with $ and $$ delimiters and then try replacing \_
This commit is contained in:
Hrishikesh Barman 2023-09-30 00:05:26 +05:30 committed by GitHub
parent 22b559b31b
commit b38d9322b1
2 changed files with 36 additions and 0 deletions

View File

@ -32,6 +32,7 @@ Quartz by default doesn't understand `org-roam` files as they aren't Markdown. Y
- `replaceFigureWithMdImg`: Whether to replace `<figure/>` with `![]()` - `replaceFigureWithMdImg`: Whether to replace `<figure/>` with `![]()`
- Formatting - Formatting
- `removeHugoShortcode`: Whether to remove hugo shortcode syntax (`{{}}`) - `removeHugoShortcode`: Whether to remove hugo shortcode syntax (`{{}}`)
- `replaceOrgLatex`: Whether to replace org-mode formatting for latex fragments with what `Plugin.Latex` supports.
> [!warning] > [!warning]
> >

View File

@ -9,6 +9,9 @@ export interface Options {
removeHugoShortcode: boolean removeHugoShortcode: boolean
/** Replace <figure/> with ![]() */ /** Replace <figure/> with ![]() */
replaceFigureWithMdImg: boolean replaceFigureWithMdImg: boolean
/** Replace org latex fragments with $ and $$ */
replaceOrgLatex: boolean
} }
const defaultOptions: Options = { const defaultOptions: Options = {
@ -16,12 +19,27 @@ const defaultOptions: Options = {
removePredefinedAnchor: true, removePredefinedAnchor: true,
removeHugoShortcode: true, removeHugoShortcode: true,
replaceFigureWithMdImg: true, replaceFigureWithMdImg: true,
replaceOrgLatex: true,
} }
const relrefRegex = new RegExp(/\[([^\]]+)\]\(\{\{< relref "([^"]+)" >\}\}\)/, "g") const relrefRegex = new RegExp(/\[([^\]]+)\]\(\{\{< relref "([^"]+)" >\}\}\)/, "g")
const predefinedHeadingIdRegex = new RegExp(/(.*) {#(?:.*)}/, "g") const predefinedHeadingIdRegex = new RegExp(/(.*) {#(?:.*)}/, "g")
const hugoShortcodeRegex = new RegExp(/{{(.*)}}/, "g") const hugoShortcodeRegex = new RegExp(/{{(.*)}}/, "g")
const figureTagRegex = new RegExp(/< ?figure src="(.*)" ?>/, "g") const figureTagRegex = new RegExp(/< ?figure src="(.*)" ?>/, "g")
// \\\\\( -> matches \\(
// (.+?) -> Lazy match for capturing the equation
// \\\\\) -> matches \\)
const inlineLatexRegex = new RegExp(/\\\\\((.+?)\\\\\)/, "g")
// (?:\\begin{equation}|\\\\\(|\\\\\[) -> start of equation
// ([\s\S]*?) -> Matches the block equation
// (?:\\\\\]|\\\\\)|\\end{equation}) -> end of equation
const blockLatexRegex = new RegExp(
/(?:\\begin{equation}|\\\\\(|\\\\\[)([\s\S]*?)(?:\\\\\]|\\\\\)|\\end{equation})/,
"g",
)
// \$\$[\s\S]*?\$\$ -> Matches block equations
// \$.*?\$ -> Matches inline equations
const quartzLatexRegex = new RegExp(/\$\$[\s\S]*?\$\$|\$.*?\$/, "g")
/** /**
* ox-hugo is an org exporter backend that exports org files to hugo-compatible * ox-hugo is an org exporter backend that exports org files to hugo-compatible
@ -67,6 +85,23 @@ export const OxHugoFlavouredMarkdown: QuartzTransformerPlugin<Partial<Options> |
return `![](${src})` return `![](${src})`
}) })
} }
if (opts.replaceOrgLatex) {
src = src.toString()
src = src.replaceAll(inlineLatexRegex, (value, ...capture) => {
const [eqn] = capture
return `$${eqn}$`
})
src = src.replaceAll(blockLatexRegex, (value, ...capture) => {
const [eqn] = capture
return `$$${eqn}$$`
})
// ox-hugo escapes _ as \_
src = src.replaceAll(quartzLatexRegex, (value) => {
return value.replaceAll("\\_", "_")
})
}
return src return src
}, },
} }