Plugins
A plugin extends how decks are compiled. It can:
- make components available as directives,
- add plugins of unified to the compiler, like math or syntax highlighting,
- use other plugins,
- set the options of other plugins.
A presentation theme can do the same.
The config
A plugin describes what it adds in its seminar config. A package puts it in
the seminar key of its package.json:
{
"name": "my-elements",
"seminar": {
"directives": {
"note": { "source": "my-elements", "exportName": "Note" }
}
}
}
A package with several configs, like several themes, can point to a JSON
file with the seminar export condition instead:
"exports": { ".": { "seminar": "./seminar.json", "default": "./dist/index.js" } }
A local module, like a theme in ./src/theme.tsx, exports the config as
seminar:
import type { SeminarConfig } from '@seminar/core';
export const seminar: SeminarConfig = {
plugins: ['@seminar/plugin-mathjax'],
options: { math: { font: 'newcm' } },
};
The config is read in Node when decks are compiled, not in the browser. So a
module with a config shouldn't use browser globals like window at the top
level. The packages it imports must be built to JavaScript.
Enabling plugins
List plugins in the options of the Seminar plugin of Vite or Rollup:
seminar({ plugins: ['my-elements'] });
With Vite, plugin names can also use the project's aliases, such as
plugins: ['@/presentation-plugin.ts']. Aliases apply to plugin references in
configs and to the source entries of compiler plugins too. See
Aliases and a default theme.
The configs of the plugins apply in order. The config of the theme of the deck applies last, so the theme can override the plugins.
Using other plugins
A plugin or a theme can use other plugins. List them in its plugins key:
{ "seminar": { "plugins": ["@seminar/plugin-shiki"] } }
They are loaded before it, so it can override their options. Each plugin is loaded once, even if several configs list it.
Options
Plugins of the compiler take no options directly. Configs set them in their
options key instead, by the name of the plugin's options:
export const seminar: SeminarConfig = {
options: { code: { theme: 'github-dark' } },
};
Decks override them in the key of the same name in their frontmatter:
code:
theme: min-light
Components read the options of the deck with useSeminarOptions(name) of
@seminar/core. The Deck gets them as its options prop.
Compiler plugins
A plugin can add plugins of unified to the compiler. List them in the mdx
key of its config:
{
"seminar": {
"mdx": {
"rehypePlugins": {
"after": [{ "source": "my-code/rehype", "exportName": "rehypeMyCode" }]
}
}
}
}
There are three stages:
remarkPluginswork on the Markdown syntax tree.rehypePluginswork on the HTML syntax tree.recmaPluginswork on the JavaScript of the compiled deck.
Each stage takes plugins that run before or after the plugins of Seminar.
Remark plugins in before can add syntax to Markdown, like math.
The plugins are loaded in Node when decks are compiled. They may use packages that decks shouldn't contain, like a highlighter. Their modules must be built to JavaScript.
If a plugin can't be loaded, you get a warning, and the deck is compiled without it.
@seminar/plugin-mathjax and @seminar/plugin-shiki are plugins like this.
Reading options
Plugins read their options with getSeminarOptions(file, name) of
@seminar/mdx. It merges the options of the plugins, the theme, and the
frontmatter, in this order. getSeminarOptionLayers returns them one by one,
with the file to resolve paths from.
Pick a name that isn't a key of the frontmatter of decks, like title or
theme.
Decks get the options of every name that a config sets. They are merged the
same way. To give components other values, call
setRuntimeSeminarOptions(file, name, code) in a remark or rehype plugin.
code is a JavaScript expression. It can use the imports that the plugin
adds to the deck.
@seminar/plugin-mathjax does this, since it merges macros, and gives
components functions that import the font of the deck.
Utilities
@seminar/mdx exports utilities for compiler plugins:
parseAttributeWordsreads attributes written like those of directives, but without braces, like in the first line of a code block.getStepPropsturns attributes into the props of a step.createStringAttribute,createEsm, andEXPLICIT_JSX_HASTcreate JSX elements and imports in the syntax trees of decks.