Markdown Features
Contented unified processor pipeline.
processor
.use(options.before)
.use(remarkGfm)
.use(remarkFrontmatter)
.use(remarkParse)
.use(remarkLink)
.use(remarkDirective)
.use(remarkDirectiveRehype)
.use(collectFields)
.use(resolveFields)
.use(validateFields)
.use(options.remarks)
.use(remarkRehype)
.use(options.rehypes)
.use(rehypeExternalLinks, { target: '_blank' })
.use(rehypeSlug)
.use(rehypeAutolinkHeadings)
.use(rehypeToc)
.use(rehypeHeading)
.use(rehypeMermaid)
.use(rehypeShiki, { highlighter })
.use(rehypeStringify)
.use(options.after);
GitHub Flavour Markdown
GitHub Flavored Markdown, often shortened as GFM, is the dialect of Markdown that is currently supported for user content on GitHub.com and GitHub Enterprise.
This formal specification, based on the CommonMark Spec, defines the syntax and semantics of this dialect.
Frontmatter
---
title: Markdown Flavour
---
Linking
[Heading](#heading)
[External](https://example.com)
Relative Linking (manual):
[Relative Example 1](relative)
[Relative Example 2](to/folder/page-1)
[Relative Example 3](../back/page-3)
Relative Linking (automatic), give these 3 files:
1. 01-about.md
2. docs/01-introduction.md
3. docs/01-others/02-usage.md
[Automatic Relative Linking](./01-about.md):
- When you reference this link in the root dir of the pipeline `about` will be resolved.
- When you reference this link in the `docs` dir of the pipeline `../about` will be resolved.
- When you reference this link in the `docs/01-others` dir of the pipeline `../../about` will be resolved.
[Automatic Relative Linking](./docs/01-introduction.md):
- When you reference this link in the root dir of the pipeline `docs/introduction` will be resolved.
- When you reference this link in the `docs` dir of the pipeline `introduction` will be resolved.
- When you reference this link in the `docs/01-others` dir of the pipeline `../introduction` will be resolved.
It is highly recommended to use relative links for internal linking and avoid using absolute links. This is because contented pipelines are designed to be portable and can be deployed to different sites or domains. By using absolute links, you're assuming that the content will always be deployed to the same domain or the same path. When using relative links, contented will automatically resolve the links to the correct destination.
For example:
/** @type {import('@contentedjs/contented').ContentedConfig} */
const config = {
preview: {
url: 'https://preview.contented.dev',
name: 'Preview Contented',
},
processor: {
rootDir: '../docs',
pipelines: [
{
type: 'ExampleType',
pattern: 'example-docs/**/*md',
processor: 'md',
transform: (file) => {
// Notice that the path example-docs/ is removed. There is no way to know how you path is structured.
// You need therefore use relative links that works universally across all sites.
// This is intentional to make contented pipelines portable.
file.path = file.path.replaceAll(/^\/example-docs\/?/g, '/');
file.sections = file.sections.slice(1);
return file;
},
},
],
},
};
export default config;
Pipeline Processed: -> /[path] (note docs/example-docs/ is removed)
/docs/example-docs/page-1 -> /page-1
/docs/example-docs/page-2 -> /page-2
/docs/example-docs/folder/page-3 -> /folder/page-3
Preview: -> https://preview.contented.dev/[type]/[path]
/page-1 -> https://preview.contented.dev/example/page-1
/page-2 -> https://preview.contented.dev/example/page-2
/folder/page-3 -> https://preview.contented.dev/example/folder/page-3
Another Site: -> https://developer-docs.com/product-example/docs/[path]
/page-1 -> https://developer-docs.com/product-example/docs/page-1
/page-2 -> https://developer-docs.com/product-example/docs/page-2
/folder/page-3 -> https://developer-docs.com/product-example/docs/folder/page-3
Note how "Another Site" consumed the same contented pipeline but deployed to a different domain and path with its own custom prefix. If you used absolute links, the links would be broken.
It is also highly advised against linking to another "Type"
as you're assuming that the other site will be
structured the same way as your site with the same prefix or even publishing that "Type"
at all.
Mermaid
```mermaid
graph LR
Start --> Stop
```
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
Directives
They can be declared via long-form :::div{class="table-fixed"}
or short-form :::div{.table-fixed}
Table Directive
Header 1 | Header 2 | Header 3 |
---|---|---|
Cell 1 | Cell 2 | Cell 3 |
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1 | Cell 2 | Cell 3 |
Table Fixed | Header 2 | Header 3 |
---|---|---|
Cell 1 | Cell 2 | Cell 3 |
:::div{class="table-fixed"}
| Table Fixed | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1 | Cell 2 | Cell 3 |
:::
Table Auto | Header 2 | Header 3 |
---|---|---|
Cell 1 | Cell 2 | Cell 3 |
:::div{class="table-auto"}
| Table Auto | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1 | Cell 2 | Cell 3 |
:::
Admonitions Directive
Admonitions with remark-directive
and remark-directive-rehype
.
This is div{.admonitions}
.
:::div{.admonitions}
This is `div{.admonitions}`.
:::
This is div{.admonitions.red}
.
:::div{.admonitions.red}
This is `div{.admonitions.red}`.
:::
This is div{.admonitions.yellow}
.
:::div{.admonitions.yellow}
This is `div{.admonitions.yellow}`.
:::
This is div{.admonitions.green}
.
:::div{.admonitions.green}
This is `div{.admonitions.green}`.
:::
Codeblock Directive
Codeblock with Header
const a: number = 1;
const b: number = 2;
:::codeblock-header{filename="example.ts" language="TypeScript"}
```ts
const a: number = 1;
const b: number = 2;
```
:::
Codeblock with Language Selector
const a: number = 1;
const b: number = 2;
::::codeblock-group
:::codeblock-header{filename="example.ts" language="TypeScript"}
```ts
const a: number = 1;
const b: number = 2;
```
:::
:::codeblock-header{filename="example.js" language="JavaScript"}
```js
const a = 1;
const b = 2;
```
:::
::::