Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rehype plugins #65

Merged
merged 16 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions docs/components/bases/CodeGroup.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<template>
<div class="code-group">
<div class="rounded-t border-b-2 border-gray-700 px-2 bg-gray-800 text-sm text-white relative ">
<div class="rounded-t border-b-2 border-gray-700 px-2 bg-gray-800 text-sm text-white relative">
<button
v-for="({ label }, i) in tabs"
ref="tabs"
:key="label"
class="px-4 py-3 text-gray-400 font-bold font-mono"
:class="[activeTabIndex === i && 'active']"
@click="updateTabs(i)"
>
{{ label }}
</button>
>{{ label }}</button>
<span ref="highlight-underline" class="highlight-underline" />
</div>
<slot />
Expand All @@ -31,7 +29,7 @@ export default {
}
},
created () {
this.$slots.default.map((slot) => {
this.$slots.default.filter(slot => Boolean(slot.componentOptions)).map((slot) => {
this.tabs.push({
label: slot.componentOptions.propsData.label,
elm: null
Expand All @@ -40,7 +38,7 @@ export default {
this.activeTabIndex = 0
},
mounted () {
this.tabs = this.$slots.default.map((slot) => {
this.tabs = this.$slots.default.filter(slot => Boolean(slot.componentOptions)).map((slot) => {
return {
label: slot.componentOptions.propsData.label,
elm: slot.elm
Expand Down
2 changes: 1 addition & 1 deletion docs/content/en/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ category: Getting started

```js
export default {
modules: [,
modules: [
'@nuxt/content'
],
generate: {
Expand Down
21 changes: 21 additions & 0 deletions docs/content/en/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Changelog
description: 'Learn the changes made of the different versions of @nuxt/content module.'
position: 8
category: Getting started
---

## v2.0.0

### Markdown plugins

<base-alert>
markdown.basePlugins and markdown.plugins have been removed in favor of markdown.remarkPlugins and markdown.rehypePlugins.
</base-alert>

- Overriding plugins options can still be done but with prefixing by `remark` or `rehype`, for examps `externalLinks` becomes `remarkExternalLinks`.
- You can now override all plugins or append a new plugin using `remarkPlugins` / `rehypePlugins`.
- You can use local plugins using `~/plugins/remark-plugin.js`.
- You can register and configure plugins on the same line like `['remark-plugin', { option: 1 }]`.

Everything is documented in [this section](/configuration#markdown).
156 changes: 127 additions & 29 deletions docs/content/en/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ export default {
}
```

See [defaults options](#defaults).
Before diving into the individual attributes, please have a look [at the default settings](#defaults) of the module.

### Merging defaults

You can define every option either as function or as static value (primitives, objects, arrays, ...).
if you use a function, the default value will be provided as the first argument.

If you *don't* use a function to define you properties, the module will try to
merge them with the default values. This can be handy for `markdown.remarkPlugins`, `markdown.rehypePlugins` and so on because
the defaults are quite sensible. If you don't want to have the defaults include, just use a function.

## Properties

Expand Down Expand Up @@ -79,46 +88,128 @@ content: {

### `markdown`

This module uses [remark](https://github.com/remarkjs/remark) under the hood to compile markdown files into JSON AST that will be stored into the `body` variable.
This module uses [remark](https://github.com/remarkjs/remark) and [rehype](https://github.com/rehypejs/rehype) under the hood to compile markdown files into JSON AST that will be stored into the `body` variable.

By default, this module uses plugins to improve markdown parsing. You can add your own by using `plugins` or override the default ones by using `basePlugins`. Each plugin is configured using its name in camelCase: `remark-external-links` => `externalLinks`.
<base-alert type="info">
The following explanation is valid for both `remarkPlugins` and `rehypePlugins`
</base-alert>

> You check for remark plugins [here](https://github.com/remarkjs/remark/blob/master/doc/plugins.md#list-of-plugins)
To configure how the module will parse Markdown, you can:

### `markdown.basePlugins`
- Add a new plugin to the defaults:

- Type: `Array`
- Default: `['remark-squeeze-paragraphs', 'remark-slug', 'remark-autolink-headings', 'remark-external-links', 'remark-footnotes']`
```js{}[nuxt.config.js]
export default {
content: {
markdown: {
remarkPlugins: ['remark-emoji']
}
}
}
```

### `markdown.plugins`
- Override the default plugins:

- Type: `Array`
- Default: `[]`
```js{}[nuxt.config.js]
export default {
content: {
markdown: {
remarkPlugins: () => ['remark-emoji']
}
}
}
```

### `markdown.externalLinks`
- Use local plugins

- Type: `Object`
- Default: `{}`
```js{}[nuxt.config.js]
export default {
content: {
markdown: {
remarkPlugins: [
'~/plugins/my-custom-remark-plugin.js'
]
}
}
}
```

You can control the behaviour of links via this option. You can check here for [options](https://github.com/remarkjs/remark-external-links#api).
- Provide options directly in the definition

```js{}[nuxt.config.js]
content: {
markdown: {
externalLinks: {
target: '_self' // disable target="_blank"
rel: false // disable rel="nofollow noopener"
export default {
content: {
markdown: {
remarkPlugins: [
['remark-emoji', { emoticon: true }]
]
}
}
}
```

### `markdown.footnotes`
- Provide options using the name of the plugin in `camelCase`

- Type: `Object`
- Default: `{ inlineNotes: true }`
```js{}[nuxt.config.js]
export default {
content: {
markdown: {
// https://github.com/remarkjs/remark-external-links#options
remarkExternalLinks: {
target: '_self',
rel: 'nofollow'
}
}
}
}
```

<base-alert>
When adding a new plugin, make sure to install it in your dependencies:
</base-alert>

<code-group>
<code-block label="Yarn" active>

```bash
yarn add remark-emoji
```

</code-block>
<code-block label="NPM">

```bash
npm install remark-emoji
```

</code-block>
</code-group>

```js{}[nuxt.config.js]
export default {
content: {
markdown: {
remarkPlugins: ['remark-emoji']
}
}
}
```

### `markdown.remarkPlugins`

- Type: `Array`
- Default: `['remark-squeeze-paragraphs', 'remark-slug', 'remark-autolink-headings', 'remark-external-links', 'remark-footnotes']`
- Version: **v2.0.0**

> You can take a look at the list of [remark plugins](https://github.com/remarkjs/remark/blob/master/doc/plugins.md#list-of-plugins).

### `markdown.rehypePlugins`

- Type: `Array`
- Default: `['rehype-minify-whitespace', 'rehype-sort-attribute-values', 'rehype-sort-attributes', 'rehype-raw']`
- Version: **v2.0.0**

You can control the behaviour of footnotes via this option. You can check here for [options](https://github.com/remarkjs/remark-footnotes#remarkusefootnotes-options).
> You can take a look at the list of [rehype plugins](https://github.com/rehypejs/rehype/blob/master/doc/plugins.md#list-of-plugins).

### `markdown.prism.theme`

Expand Down Expand Up @@ -177,12 +268,19 @@ export default {
fullTextSearchFields: ['title', 'description', 'slug', 'text'],
nestedProperties: [],
markdown: {
externalLinks: {},
footnotes: {
inlineNotes: true
},
basePlugins: ['remark-squeeze-paragraphs', 'remark-slug', 'remark-autolink-headings', 'remark-external-links', 'remark-footnotes'],
plugins: [],
remarkPlugins: [
'remark-squeeze-paragraphs',
'remark-slug',
'remark-autolink-headings',
'remark-external-links',
'remark-footnotes'
],
rehypePlugins: [
'rehype-minify-whitespace',
'rehype-sort-attribute-values',
'rehype-sort-attributes',
'rehype-raw'
],
prism: {
theme: 'prismjs/themes/prism.css'
}
Expand Down
8 changes: 5 additions & 3 deletions docs/content/en/writing.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ It will be transformed to it's JSON AST structure, and by using the `nuxt-conten
```

> The links in headings are empty and therefore hidden, so it's up to you to style them. For an example, try hovering one of the headers in these docs.

### Links

Links are transformed to add valid `target` and `rel` attributes. You can change this behaviour, see [configuration](/configuration#markdownexternallinks). Relative links are also automatically transformed to `nuxt-link` to provide navigation between page components with enhanced performance through smart prefetching.
Links are transformed to add valid `target` and `rel` attributes using [remark-external-links](https://github.com/remarkjs/remark-external-links). You can check [here](/configuration#markdown) to learn how to configure this plugin.

Relative links are also automatically transformed to [nuxt-link](https://nuxtjs.org/api/components-nuxt-link/) to provide navigation between page components with enhanced performance through smart prefetching.

Here is an example using external, relative, markdown and html links:

Expand All @@ -116,7 +118,7 @@ title: Home

### Footnotes

This module supports extended markdown syntax for footnotes.
This module supports extended markdown syntax for footnotes using [remark-footnotes](https://github.com/remarkjs/remark-footnotes). You can check [here](/configuration#markdown) to learn how to configure this plugin.

Here is an example using footnotes:

Expand Down
59 changes: 21 additions & 38 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,23 @@ const defu = require('defu')
const middleware = require('./middleware')
const Database = require('./database')
const WS = require('./ws')
const { getDefaults, mergeConfig, processMarkdownOptions } = require('./utils')

const defaults = {
watch: false,
apiPrefix: '_content',
dir: 'content',
fullTextSearchFields: ['title', 'description', 'slug', 'text'],
nestedProperties: [],
markdown: {
basePlugins: [
'remark-squeeze-paragraphs',
'remark-slug',
'remark-autolink-headings',
'remark-external-links',
'remark-footnotes'
],
plugins: [
],
footnotes: {
inlineNotes: true
},
externalLinks: {},
prism: {
theme: 'prismjs/themes/prism.css'
}
},
yaml: {},
csv: {}
}
module.exports = async function (moduleOptions) {
const isSSG = this.options.dev === false && (this.options.target === 'static' || this.options._generate)

module.exports = async function () {
const isSSG =
this.options.dev === false &&
(this.options.target === 'static' || this.options._generate)
const options = defu(
{
watch: this.options.dev,
...this.options.content
},
defaults
)
const { content = {} } = Object.assign({}, this.options)
Object.assign(content, moduleOptions)

const defaults = getDefaults({ dev: this.options.dev })

const mergedConfig = mergeConfig(content, defaults)
const options = defu(mergedConfig, defaults)
options.dir = resolve(this.options.srcDir, options.dir)

// Load markdown plugins
processMarkdownOptions(options, this.nuxt.resolver.resolvePath)

options.apiPrefixWithBase = options.apiPrefix
if (this.options.router.base) {
let baseRouter = this.options.router.base
Expand Down Expand Up @@ -182,3 +156,12 @@ module.exports = async function () {

module.exports.Database = Database
module.exports.middleware = middleware
module.exports.getOptions = (userOptions = {}) => {
const defaults = getDefaults({ dev: process.env.NODE_ENV !== 'production' })
const mergedConfig = mergeConfig(userOptions, defaults)
const options = defu(mergedConfig, defaults)

processMarkdownOptions(options)

return options
}
Loading