94 lines
3.2 KiB
Markdown
94 lines
3.2 KiB
Markdown
---
|
|
tags: api/space-lua maturity/experimental
|
|
references:
|
|
- libraries/Library/Std/APIs/Syntax.md
|
|
- client/markdown_parser/custom_syntax.ts
|
|
- client/codemirror/custom_syntax_widget.ts
|
|
---
|
|
|
|
Enables defining simple custom syntax extensions to [[Markdown]]. Custom syntax lets you define new delimiter-based regions (both inline and block) that are recognized by the parser and can be styled or rendered as [[Space Lua/Widget|Widgets]].
|
|
|
|
# API
|
|
## syntax.define(spec)
|
|
Registers a custom syntax extension. The extension will be active after the next editor state rebuild (e.g. on page reload or config change).
|
|
|
|
`spec` is a table that can contain:
|
|
* `name` (required): AST node name (e.g. `"LatexInline"`)
|
|
* `startMarker` (required): Regex string for start delimiter (e.g. `"\\$"`)
|
|
* `endMarker` (required): Regex string for end delimiter
|
|
* `mode` (required): `"block"` or `"inline"`
|
|
* CSS styling used when _not_ [[Live Preview|Live Previewing]]:
|
|
* `startMarkerClass`: CSS class for the start marker
|
|
* `bodyClass`: CSS class for the body content between markers
|
|
* `endMarkerClass`: CSS class for the end marker
|
|
* CSS styling applied when Live Previewing:
|
|
* `renderClass`: CSS class applied to the rendered widget
|
|
* `renderWidget`: Callback `function(body, pageName)` returning [[API/widget|widget]] content for Live Preview.
|
|
* `renderHtml`: Callback `function(body, pageName)` returning an HTML string or `HTMLElement` (e.g. via `dom.*`) for use when rendering to HTML.
|
|
|
|
# Escaping
|
|
Within the body of an inline syntax extension, backslash (`\`) acts as an escape character. Use `\` before the end marker to include it literally in the body. The render callback receives the **raw** body text with escape sequences intact; the renderer is responsible for unescaping if needed.
|
|
|
|
# Example
|
|
Define an inline LaTeX syntax using `$` delimiters:
|
|
|
|
```space-lua
|
|
syntax.define {
|
|
name = "LatexInline",
|
|
startMarker = "\\$(?!\\{)",
|
|
endMarker = "\\$(?!\\{)",
|
|
mode = "inline",
|
|
--startMarkerClass = "sb-latex-mark",
|
|
--bodyClass = "sb-latex-body",
|
|
--endMarkerClass = "sb-latex-mark",
|
|
renderClass = "sb-latex-inline-preview",
|
|
renderWidget = function(body, pageName)
|
|
return widget.html(dom.i { body })
|
|
end,
|
|
renderHtml = function(body, pageName)
|
|
return dom.i { body }
|
|
end
|
|
}
|
|
```
|
|
|
|
This will recognize `$E=mc^2$` in your text and render the body using the provided callback (in this case it just makes it italic): $E=mc^2$.
|
|
|
|
> **note** Note
|
|
> The `(?!\{)` negative lookahead prevents `$` from clashing with the `${expr}` Lua expression syntax. Without it, `$math ${expr} more$` would prematurely close at the `$` in `${expr}`.
|
|
|
|
A block-level variant using `$$` fences:
|
|
|
|
```space-lua
|
|
syntax.define {
|
|
name = "LatexBlock",
|
|
startMarker = "^\\|\\|$",
|
|
endMarker = "^\\|\\|$",
|
|
mode = "block",
|
|
startMarkerClass = "sb-latex-mark",
|
|
bodyClass = "sb-latex-body",
|
|
endMarkerClass = "sb-latex-mark",
|
|
renderWidget = function(body, pageName)
|
|
return widget.htmlBlock(dom.marquee { body })
|
|
end,
|
|
renderHtml = function(body, pageName)
|
|
return dom.marquee { body }
|
|
end
|
|
}
|
|
```
|
|
|
|
This recognizes fenced blocks:
|
|
|
|
||
|
|
E = mc^2
|
|
||
|
|
|
|
You can style these with [[Space Style]]:
|
|
```space-style
|
|
.sb-latex-mark {
|
|
color: cyan;
|
|
}
|
|
.sb-latex-body {
|
|
color: gray;
|
|
}
|
|
```
|