A react-static plugin to create nested pages from a given source directory.
$ yarn add react-static-plugin-md-pages
# or
npm install --save react-static-plugin-md-pages
Add the plugin to your static.config.js
in the plugins array.
// static.config.js
export default {
plugins: [
[
'react-static-plugin-md-pages',
{
location: './docs', // path to markdown files' directory
pathPrefix: '', // prefix for added react-static routes (if any)
template: './src/template.js', // path to React template component
remarkPlugins: [], // add additional remark plugins here
}
]
]
};
Your markdown file may contain frontmatter data. This data will be reflected in the data you'll get from this plugin's React API.
An example will look like this:
---
title: architecture
order: 1
template: ../src/components/template.js
---
All of these properties are optional. The title
may be used to change
the page's title, but by default the plugin will generate a title from your
first h1
heading in your markdown file.
The order
property specifies the order in which your markdown files will
be sorted in, which will be reflected in the React API as
well.
Lastly, the template
property may be used to override the default React template component
that this specific page is using. The path must be relative to the current file.
There are a couple of changes and features that will be applied to your markdown content
automatically. It's best to be aware of them before adding your own remark
plugins.
If you're adding links to your markdown files they'll be transformed to automatically point
at the react-static
routes this plugin creates, so that your markdown files may remain compatible
with GitHub for instance. These links will be transformed:
[Some link](./other-route.md)
[Some other link](./folder/README.md)
And end up being this in react-static
:
[Some link](./other-route)
[Some other link](./folder)
Note: This does not apply to
<a>
tags in your markdown file!
When you're adding images to your markdown, they'll be automatically imported and sent through the Webpack pipeline, so you won't have to reference images in your public folder absolutely.
![This image will be imported!](./some-logo.png)
Note: This does not apply to
<img>
tags in your markdown file!
All headings (h1
, h2
, h3
, ...) will have an added id
prop that contains their sluggified
string contents. The slugger we use is github-slugger
.
# Before
<h1 id="after">After</h1>
Howver, you won't need to generate these slugs in your app code again if you plan on using anchor tags. The data that the React API returns contains headings and slug data for any given markdown page.
The plugin will scan the given location
folder directory for
.md
files which will be added to react-static
as individual pages.
The directories the markdown file is located in and the filename
itself will be taken into account when adding routes.
The search itself starts from the react-static
root that is
configured in config.paths.root
(which defaults to the current
working directory).
For instance, if location is set to ./docs
and the given list of
files is the following:
|- docs
|- getting-started.md
|- basics
|- installation.md
|- advanced
|- README.md
|- api.md
The output of routes will be:
/getting-started
/basics/installation
/advanced
(index route)/api
Any file that is named README.md
or index.md
(case-insensitive) will
be considered an index route. So in the example above ./docs/advanced/README.md
became /advanced
instead of /advanced/readme
.
If this option is set, all routes will be prefixed with what you pass
to this option. For instance, setting it to docs
will turn /getting-started
to /docs/getting-started
.
Like with routes in react-static
's getRoutes
, you'll likely want to wrap
your markdown content in React components. This may be done by pointing
template
at your template component, e.g. ./src/components/template.js
.
When rendered the component will receive the markdown content as JSX, the
content will be passed as the children
prop.
An example for a component may look like the following:
// ./src/components/template.js
export default ({ children }) => (
<main>
{children}
</main>
);
Your markdown files will be parsed using remark before being converted to JSX on the client-side. You may pass more remark plugins that your markdown will be run through during build time.
{
remarkPlugins: [
[require('remark-emoji'), { padSpaceAfter: true }]
]
}
This may be used to override the order of some pages, which is useful for folders that
need sorting, but don't have index files (README.md
or index.md
).
The order
config can be set to an object of routeName
to a number, where the route's
name is either a folder name or a filename.
Since by default the order is alphabetic, if you have two folders, one named basics/
and one
named advanced/
, you can swap their order as so:
{
order: {
basics: 0,
advanced: 1,
}
}
This plugin provides two hooks useMarkdownPage
and useMarkdownTree
. The former returns
information about the current page's markdown data and the latter returns a nested tree of
all markdown pages.
The useMarkdownPage
hook is available as long as you are on any of the markdown page, useMarkdownTree
is available in any react-static page.
useMarkdownPage()
// => Page
useMarkdownTree()
// => { ...Page, key: string, children: Page[] }
As shown above, the tree version of the hook returns additional data apart from the common
Page
data, which also contains a key
— the node's directory or filename — and children — the
child Page
s or nodes.
A Page
is an object that contains more information about the markdown file. Specifically it'll
contain:
path
: The route to the page, including thepathPrefix
(if any has been set)originalPath
: The original path to the markdown file (which is useful as a unique key)frontmatter
: The JSON object of frontmatter data (*normalized)headings
: A list of allh1
,h2
, andh3
headings in the markdown file
The frontmatter
data is normalised. This means that when your markdown file doesn't have any
frontmatter data it'll still be provided, and when you left out frontmatter.title
it will default
to the page's first h1
heading.
The headings
array contains all h1
, h2
, and h3
headings as objects. These objects have
a value
property (the stringified content of the heading), a slug
property (the slugified
content of the heading), and a depth property (1 | 2 | 3
depending on the level of the heading.)
The JSX that the markdown content is rendered as internally uses
@mdx-js/react
. By default it will render out
as normal HTML-ified markdown content. However, it's possible to use the MDXProvider
from
@mdx-js/react
to modify the output.
Read more about the MDXProvider
in the MDX guides.
Experimental: This project is quite new. We're not sure what our ongoing maintenance plan for this project will be. Bug reports, feature requests and pull requests are welcome. If you like this project, let us know!