Skip to content

Commit 35a71a1

Browse files
authored
docs: add parser customization (preparser, but also link vite config) (#91)
1 parent eb148aa commit 35a71a1

2 files changed

Lines changed: 181 additions & 0 deletions

File tree

.vitepress/config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ const Customizations = [
164164
text: 'Configure Mermaid',
165165
link: '/custom/config-mermaid',
166166
},
167+
{
168+
text: 'Configure Parser',
169+
link: '/custom/config-parser',
170+
},
167171
{
168172
text: 'Configure Shortcuts',
169173
link: '/custom/config-shortcuts',

custom/config-parser.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Configure and Extend the Parser
2+
3+
Slidev parses your presentation file (e.g. `slides.md`) in three steps:
4+
5+
1. A "preparsing" step is carried out: the file is split into slides using the `---` separator, and considering the possible frontmatter blocks.
6+
2. Each slide is parsed with an external library.
7+
3. Slidev resolves the special frontmatter property `src: ....`, which allows to include other md files.
8+
9+
## Markdown Parser
10+
11+
Configuring the markdown parser used in step 2 can be done by [configuring Vite internal plugins](/custom/config-vite#configure-internal-plugins).
12+
13+
## Preparser Extensions
14+
15+
> Available since v0.37.0
16+
17+
:::warning
18+
Important: when modifying the preparser configuration, you need to stop and start slidev again (restart might not be sufficient).
19+
:::
20+
21+
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](/guide/editors) due to implicit changes in the syntax.
22+
23+
To customize it, create a `./setup/preparser.ts` file with the following content:
24+
25+
26+
```ts
27+
import { definePreparserSetup } from '@slidev/types'
28+
29+
export default definePreparserSetup((filepath) => {
30+
return [
31+
{
32+
transformRawLines(lines) {
33+
for (const i in lines) {
34+
if (lines[i] === '@@@')
35+
lines[i] = 'HELLO'
36+
}
37+
},
38+
}
39+
]
40+
})
41+
```
42+
43+
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:
44+
- `definePreparserSetup` must be called with a function as parameter.
45+
- The function receives the file path (of the root presentation file) and could use this information (e.g., enable extensions based on the presentation file).
46+
- The function must return a list of preparser extensions.
47+
- An extension can contain:
48+
- 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.
49+
- 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, possibly `undefined` if no modifications have been done).
50+
- a `name`
51+
52+
## Example Preparser Extensions
53+
54+
### Use case 1: compact syntax top-level presentation
55+
56+
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:
57+
58+
```md
59+
60+
@cover: /nice.jpg
61+
# Welcome
62+
@src: page1.md
63+
@src: page2.md
64+
@cover: /break.jpg
65+
@src: pages3-4.md
66+
@cover: https://source.unsplash.com/collection/94734566/1920x1080
67+
# Questions?
68+
see you next time
69+
70+
```
71+
72+
To allow these `@src:` and `@cover:` syntaxes, create a `./setup/preparser.ts` file with the following content:
73+
74+
75+
```ts
76+
import { definePreparserSetup } from '@slidev/types'
77+
78+
export default definePreparserSetup((filepath) => {
79+
return [
80+
{
81+
transformRawLines(lines) {
82+
let i = 0
83+
while (i < lines.length) {
84+
const l = lines[i]
85+
if (l.match(/^@cover:/i)) {
86+
lines.splice(i, 1,
87+
'---',
88+
'layout: cover',
89+
`background: ${l.replace(/^@cover: */i, '')}`,
90+
'---',
91+
'')
92+
continue
93+
}
94+
if (l.match(/^@src:/i)) {
95+
lines.splice(i, 1,
96+
'---',
97+
`src: ${l.replace(/^@src: */i, '')}`,
98+
'---',
99+
'')
100+
continue
101+
}
102+
i++
103+
}
104+
}
105+
},
106+
]
107+
})
108+
```
109+
110+
And that's it.
111+
112+
113+
### Use case 2: using custom frontmatter to wrap slides
114+
115+
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.
116+
For instance, you might want to write your `slides.md` as follows:
117+
118+
```md
119+
120+
121+
122+
---
123+
layout: quote
124+
_scale: 0.75
125+
---
126+
127+
# Welcome
128+
129+
> great!
130+
131+
---
132+
_scale: 4
133+
---
134+
# Break
135+
136+
---
137+
138+
# Ok
139+
140+
---
141+
layout: center
142+
_scale: 2.5
143+
---
144+
# Questions?
145+
see you next time
146+
147+
```
148+
149+
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).
150+
151+
152+
To handle this `_scale: ...` syntax in the frontmatter, create a `./setup/preparser.ts` file with the following content:
153+
154+
155+
```ts
156+
import { definePreparserSetup } from '@slidev/types'
157+
158+
export default definePreparserSetup((filepath) => {
159+
return [
160+
{
161+
transformSlide(content, frontmatter) {
162+
if ('_scale' in frontmatter) {
163+
return [
164+
`<Transform :scale=${frontmatter['_scale']}>`,
165+
'',
166+
content,
167+
'',
168+
'</Transform>'
169+
].join('\n')
170+
}
171+
},
172+
},
173+
]
174+
})
175+
```
176+
177+
And that's it.

0 commit comments

Comments
 (0)