diff --git a/docs/content/en/snippets.md b/docs/content/en/snippets.md
index 8bf8ab1d5..d58ceb598 100644
--- a/docs/content/en/snippets.md
+++ b/docs/content/en/snippets.md
@@ -356,3 +356,81 @@ export default {
}
}
```
+
+### Remark Plugin
+
+Nuxt Content used [remark](https://github.com/remarkjs/remark) under the hood to process markdown documents. Creating remark plugins is a way to manipulate document and add new features contents.
+
+#### List all contributors
+
+Let's say you want to list all contributors of the project in a document. You can create a plugin that fetches all contributors and injects them into document data.
+
+- Create the plugin, this plugin fetches the contributors if `fetchContributors` is set to `true`
+
+```js [~~/plugins/contributors.js]
+const fetch = require('node-fetch')
+
+module.exports = function () {
+ return async (tree, { data }) => {
+ if (data.fetchContributors) {
+ const contributors = await fetch(
+ 'https://api.github.com/repos/nuxt/content/contributors'
+ ).then(res => res.json())
+ .then(res => res.map(({ login }) => login))
+
+ data.$contributors = [...new Set(contributors)]
+ }
+ return tree
+ }
+}
+```
+
+- Register plugin in Nuxt config
+
+```js{}[nuxt.config.js]
+export default {
+ contents: {
+ markdown: {
+ remarkPlugins: [
+ '~~/plugins/contributors.js'
+ ]
+ }
+ }
+}
+```
+
+- Create a simple component to show contributors
+
+```vue{}[~~/components/List.vue]
+
+
+
+
+
diff --git a/example/content/authors-page.md b/example/content/authors-page.md
new file mode 100644
index 000000000..2f7422de5
--- /dev/null
+++ b/example/content/authors-page.md
@@ -0,0 +1,9 @@
+---
+title: Auto generated authors list
+
+---
+
+Authors list:
+
+
+
\ No newline at end of file
diff --git a/example/nuxt.config.ts b/example/nuxt.config.ts
index 264bc35f7..297c744d8 100644
--- a/example/nuxt.config.ts
+++ b/example/nuxt.config.ts
@@ -16,6 +16,11 @@ const config: NuxtConfig = {
nestedProperties: ['categories.slug'],
extendParser: {
'.custom': file => ({ body: file.split('\n').map(line => line.trim()) })
+ },
+ markdown: {
+ remarkPlugins: [
+ '~/utils/contributors'
+ ]
}
}
};
diff --git a/example/pages/authors.vue b/example/pages/authors.vue
new file mode 100644
index 000000000..6f1de230b
--- /dev/null
+++ b/example/pages/authors.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/example/utils/contributors.js b/example/utils/contributors.js
new file mode 100644
index 000000000..afb8b6f98
--- /dev/null
+++ b/example/utils/contributors.js
@@ -0,0 +1,26 @@
+const fetch = require('node-fetch')
+
+module.exports = function () {
+ return async (tree, file) => {
+ let filePath
+ tree.children = tree.children.map((node) => {
+ const TAG_REGEX = /\s*<(authors)\s*/i
+ if (node.type === 'html' && node.value.match(TAG_REGEX)) {
+ filePath = 'README.md' // detect file path
+ node.value = node.value.replace(TAG_REGEX, '<$1 :items="$authors" ')
+ }
+ return node
+ })
+ if (filePath) {
+ const commits = await fetch(
+ 'https://api.github.com/repos/nuxt/content/commits?path=' + filePath
+ ).then(res => res.json())
+ const authors = commits
+ .map(commit => commit.author.login)
+ .filter(Boolean)
+
+ file.data.$authors = [...new Set(authors)]
+ }
+ return tree
+ }
+}
diff --git a/packages/content/parsers/markdown/index.js b/packages/content/parsers/markdown/index.js
index 92440e7ce..3954721df 100644
--- a/packages/content/parsers/markdown/index.js
+++ b/packages/content/parsers/markdown/index.js
@@ -73,9 +73,10 @@ class Markdown {
/**
* Generate json body
* @param {string} content - JSON AST generated from markdown.
+ * @param {object} data - document data
* @returns {object} JSON AST body
*/
- async generateBody (content) {
+ async generateBody (content, data = {}) {
let { highlighter } = this.options
if (typeof highlighter === 'function' && highlighter.length === 0) {
highlighter = await highlighter()
@@ -93,7 +94,7 @@ class Markdown {
stream
.use(jsonCompiler)
- .process(content, (error, file) => {
+ .process({ data, contents: content }, (error, file) => {
/* istanbul ignore if */
if (error) {
return reject(error)
@@ -120,8 +121,9 @@ class Markdown {
async toJSON (file) {
const { data, content, ...rest } = matter(file, { excerpt: true, excerpt_separator: '' })
+ const documentData = data || {}
// Compile markdown from file content to JSON
- const body = await this.generateBody(content)
+ const body = await this.generateBody(content, documentData)
// Generate toc from body
const toc = this.generateToc(body)
@@ -134,7 +136,7 @@ class Markdown {
return {
description,
- ...data,
+ ...documentData,
toc,
body,
text: content,