Configure and Extend the Parser
Kolibry parses your presentation file (e.g. slides.md
) in three steps:
- A "preparsing" step is carried out: the file is split into slides using the
---
separator, and considering the possible frontmatter blocks. - Each slide is parsed with an external library.
- Kolibry resolves the special frontmatter property
src: ....
, which allows to include other md files.
Markdown Parser
Configuring the markdown parser used in step 2 can be done by configuring Vite internal plugins.
Preparser Extensions
WARNING
Important: when modifying the preparser configuration, you need to stop and start kolibry again (restart might not be sufficient).
The preparser (step 1 above) is highly extensible and allows to implement custom syntaxes for your md files. Extending the preparser is considered an advanced feature and is susceptible to break editor integrations due to implicit changes in the syntax.
To customize it, create a ./setup/preparser.ts
file with the following content:
import { definePreparserSetup } from '@kolibry/types'
export default definePreparserSetup(({filepath, headmatter}) => {
return [
{
transformRawLines(lines) {
for (const i in lines) {
if (lines[i] === '@@@')
lines[i] = 'HELLO'
}
},
}
]
})
This example systematically replaces any @@@
line by a line with hello
. It illustrates the structure of a preparser configuration file and some of the main concepts the preparser involves:
definePreparserSetup
must be called with a function as parameter.- The function receives the file path (of the root presentation file) and headmatter (from the md file). It could use this information (e.g., enable extensions based on the presentation file).
- The function must return a list of preparser extensions.
- An extension can contain:
- a
transformRawLines(lines)
function that runs just after parsing the headmatter of the md file and receives a list of all lines (from the md file). The function can mutate the list arbitrarily. - a
transformSlide(content, frontmatter)
function that is called for each slide, just after splitting the file, and receives the slide content as a string and the frontmatter of the slide as an object. The function can mutate the frontmatter and must return the content string (possibly modified, possiblyundefined
if no modifications have been done). - a
name
- a
Example Preparser Extensions
Use case 1: compact syntax top-level presentation
Imagine a situation where (part of) your presentation is mainly showing cover images and including other md files. You might want a compact notation where for instance (part of) slides.md
is as follows:
@cover: /nice.jpg
# Welcome
@src: page1.md
@src: page2.md
@cover: /break.jpg
@src: pages3-4.md
@cover: https://source.unsplash.com/collection/94734566/1920x1080
# Questions?
see you next time
To allow these @src:
and @cover:
syntaxes, create a ./setup/preparser.ts
file with the following content:
import { definePreparserSetup } from '@kolibry/types'
export default definePreparserSetup(() => {
return [
{
transformRawLines(lines) {
let i = 0
while (i < lines.length) {
const l = lines[i]
if (l.match(/^@cover:/i)) {
lines.splice(i, 1,
'---',
'layout: cover',
`background: ${l.replace(/^@cover: */i, '')}`,
'---',
'')
continue
}
if (l.match(/^@src:/i)) {
lines.splice(i, 1,
'---',
`src: ${l.replace(/^@src: */i, '')}`,
'---',
'')
continue
}
i++
}
}
},
]
})
And that's it.
Use case 2: using custom frontmatter to wrap slides
Imagine a case where you often want to scale some of your slides but still want to use a variety of existing layouts so create a new layout would not be suited. For instance, you might want to write your slides.md
as follows:
---
layout: quote
_scale: 0.75
---
# Welcome
> great!
---
_scale: 4
---
# Break
---
# Ok
---
layout: center
_scale: 2.5
---
# Questions?
see you next time
Here we used an underscore in _scale
to avoid possible conflicts with existing frontmatter properties (indeed, the case of scale
, without underscore would cause potential problems).
To handle this _scale: ...
syntax in the frontmatter, create a ./setup/preparser.ts
file with the following content:
import { definePreparserSetup } from '@kolibry/types'
export default definePreparserSetup(() => {
return [
{
transformSlide(content, frontmatter) {
if ('_scale' in frontmatter) {
return [
`<Transform :scale=${frontmatter['_scale']}>`,
'',
content,
'',
'</Transform>'
].join('\n')
}
},
},
]
})
And that's it.