Warning
This part of the documentation will assume you have working knowledge in TypeScript and will include code snippets that describe the interface of what Quartz plugins should look like.
Quartz’s plugins are a series of transformations over content. This is illustrated in the diagram of the processing pipeline below:
All plugins are defined as a function that takes in a single parameter for options type OptionType = object | undefined
and return an object that corresponds to the type of plugin it is.
The following sections will go into detail for what methods can be implemented for each plugin type. Before we do that, let’s clarify a few more ambiguous types:
BuildCtx
is defined inquartz/ctx.ts
. It consists ofargv
: The command line arguments passed to the Quartz build commandcfg
: The full Quartz configurationallSlugs
: a list of all the valid content slugs (see paths for more information on what aServerSlug
is)
StaticResources
is defined inquartz/resources.tsx
. It consists ofcss
: a list of URLs for stylesheets that should be loadedjs
: a list of scripts that should be loaded. A script is described with theJSResource
type which is also defined inquartz/resources.tsx
. It allows you to define a load time (either before or after the DOM has been loaded), whether it should be a module, and either the source URL or the inline content of the script.
Transformers
Transformers map over content, taking a Markdown file and outputting modified content or adding metadata to the file itself.
All transformer plugins must define at least a name
field to register the plugin and a few optional functions that allow you to hook into various parts of transforming a single Markdown file.
textTransform
performs a text-to-text transformation before a file is parsed into the Markdown AST.markdownPlugins
defines a list of remark plugins.remark
is a tool that transforms Markdown to Markdown in a structured way.htmlPlugins
defines a list of rehype plugins. Similar to howremark
works,rehype
is a tool that transforms HTML to HTML in a structured way.externalResources
defines any external resources the plugin may need to load on the client-side for it to work properly.
Normally for both remark
and rehype
, you can find existing plugins that you can use to . If you’d like to create your own remark
or rehype
plugin, checkout the guide to creating a plugin using unified
(the underlying AST parser and transformer library).
A good example of a transformer plugin that borrows from the remark
and rehype
ecosystems is the Latex plugin:
Another common thing that transformer plugins will do is parse a file and add extra data for that file:
Finally, you can also perform transformations over Markdown or HTML ASTs using the visit
function from the unist-util-visit
package or the findAndReplace
function from the mdast-util-find-and-replace
package.
All transformer plugins can be found under quartz/plugins/transformers
. If you decide to write your own transformer plugin, don’t forget to re-export it under quartz/plugins/transformers/index.ts
A parting word: transformer plugins are quite complex so don’t worry if you don’t get them right away. Take a look at the built in transformers and see how they operate over content to get a better sense for how to accomplish what you are trying to do.
Filters
Filters filter content, taking the output of all the transformers and determining what files to actually keep and what to discard.
A filter plugin must define a name
field and a shouldPublish
function that takes in a piece of content that has been processed by all the transformers and returns a true
or false
depending on whether it should be passed to the emitter plugins or not.
For example, here is the built-in plugin for removing drafts:
Emitters
Emitters reduce over content, taking in a list of all the transformed and filtered content and creating output files.
An emitter plugin must define a name
field, an emit
function, and a getQuartzComponents
function. emit
is responsible for looking at all the parsed and filtered content and then appropriately creating files and returning a list of paths to files the plugin created.
Creating new files can be done via regular Node fs module (i.e. fs.cp
or fs.writeFile
) or via the write
function in quartz/plugins/emitters/helpers.ts
if you are creating files that contain text. write
has the following signature:
This is a thin wrapper around writing to the appropriate output folder and ensuring that intermediate directories exist. If you choose to use the native Node fs
APIs, ensure you emit to the argv.output
folder as well.
If you are creating an emitter plugin that needs to render components, there are three more things to be aware of:
- Your component should use
getQuartzComponents
to declare a list ofQuartzComponents
that it uses to construct the page. See the page on creating components for more information. - You can use the
renderPage
function defined inquartz/components/renderPage.tsx
to render Quartz components into HTML. - If you need to render an HTML AST to JSX, you can use the
htmlToJsx
function fromquartz/util/jsx.ts
. An example of this can be found inquartz/components/pages/Content.tsx
.
For example, the following is a simplified version of the content page plugin that renders every single page.
Note that it takes in a FullPageLayout
as the options. It’s made by combining a SharedLayout
and a PageLayout
both of which are provided through the quartz.layout.ts
file.
Hint
Look in
quartz/plugins
for more examples of plugins in Quartz as reference for your own plugins!