Skip to content

Commit

Permalink
Revert "refactor($theme-default): leverage markdown-it-table-of-conte…
Browse files Browse the repository at this point in the history
…nts (#1436)"

This reverts commit cab5b83.
  • Loading branch information
ulivz committed May 12, 2019
1 parent cab5b83 commit 8013417
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 65 deletions.
3 changes: 3 additions & 0 deletions packages/@vuepress/core/lib/client/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Content from './components/Content.js'
import ContentSlotsDistributor from './components/ContentSlotsDistributor'
import OutboundLink from './components/OutboundLink.vue'
import ClientOnly from './components/ClientOnly'
import TOC from './components/TOC.vue'

// suggest dev server restart on base change
if (module.hot) {
Expand Down Expand Up @@ -46,6 +47,8 @@ Vue.component('ClientOnly', ClientOnly)
// core components
Vue.component('Layout', getLayoutAsyncComponent('Layout'))
Vue.component('NotFound', getLayoutAsyncComponent('NotFound'))
// markdown components
Vue.component('TOC', TOC)

// global helper for adding base path to absolute urls
Vue.prototype.$withBase = function (path) {
Expand Down
20 changes: 20 additions & 0 deletions packages/@vuepress/core/lib/client/components/HeaderList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<template>
<component :is="listType[0]">
<li v-for="(item, index) in items" :key="index">
<router-link :to="'#' + item.slug" v-text="item.title" />
<HeaderList v-if="item.children" :items="item.children" :list-type="innerListType" />
</li>
</component>
</template>

<script>
export default {
name: 'HeaderList',
props: ['items', 'listType'],
computed: {
innerListType () {
return this.listType.slice(Math.min(this.listType.length - 1, 1))
}
}
}
</script>
57 changes: 57 additions & 0 deletions packages/@vuepress/core/lib/client/components/TOC.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div>
<slot name="header" />
<HeaderList :items="groupedHeaders" :list-type="listTypes" />
<slot name="footer" />
</div>
</template>

<script>
import HeaderList from './HeaderList.vue'
export default {
props: {
listType: {
type: [String, Array],
default: 'ul'
},
includeLevel: {
type: Array,
default: () => [2, 3]
}
},
components: { HeaderList },
computed: {
listTypes () {
return typeof this.listType === 'string' ? [this.listType] : this.listType
},
groupedHeaders () {
return this.groupHeaders(this.$page.headers).list
}
},
methods: {
groupHeaders (headers, startLevel = 1) {
const list = []
let index = 0
while (index < headers.length) {
const header = headers[index]
if (header.level < startLevel) break
if (header.level > startLevel) {
const result = this.groupHeaders(headers.slice(index), header.level)
if (list.length) {
list[list.length - 1].children = result.list
} else {
list.push(...result.list)
}
index += result.index
} else {
if (header.level <= this.includeLevel[1] && header.level >= this.includeLevel[0]) {
list.push({ ...header })
}
index += 1
}
}
return { list, index }
}
}
}
</script>
6 changes: 6 additions & 0 deletions packages/@vuepress/markdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const componentPlugin = require('./lib/component')
const hoistScriptStylePlugin = require('./lib/hoist')
const convertRouterLinkPlugin = require('./lib/link')
const snippetPlugin = require('./lib/snippet')
const tocPlugin = require('./lib/tableOfContents')
const emojiPlugin = require('markdown-it-emoji')
const anchorPlugin = require('markdown-it-anchor')
const {
Expand All @@ -31,6 +32,7 @@ module.exports = (markdown = {}) => {
const {
externalLinks,
anchor,
toc,
plugins,
lineNumbers,
beforeInstantiate,
Expand Down Expand Up @@ -91,6 +93,10 @@ module.exports = (markdown = {}) => {
}, anchor)])
.end()

.plugin(PLUGINS.TOC)
.use(tocPlugin, [toc])
.end()

if (lineNumbers) {
config
.plugin(PLUGINS.LINE_NUMBERS)
Expand Down
83 changes: 83 additions & 0 deletions packages/@vuepress/markdown/lib/tableOfContents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// reference: https://github.com/Oktavilla/markdown-it-table-of-contents

const defaults = {
includeLevel: [2, 3],
containerClass: 'table-of-contents',
markerPattern: /^\[\[toc\]\]/im,
listType: 'ul',
containerHeaderHtml: '',
containerFooterHtml: ''
}

module.exports = (md, options) => {
options = Object.assign({}, defaults, options)
const tocRegexp = options.markerPattern

function toc (state, silent) {
var token
var match

// Reject if the token does not start with [
if (state.src.charCodeAt(state.pos) !== 0x5B /* [ */) {
return false
}
// Don't run any pairs in validation mode
if (silent) {
return false
}

// Detect TOC markdown
match = tocRegexp.exec(state.src)
match = !match ? [] : match.filter(function (m) { return m })
if (match.length < 1) {
return false
}

// Build content
token = state.push('toc_open', 'toc', 1)
token.markup = '[[toc]]'
token = state.push('toc_body', '', 0)
token = state.push('toc_close', 'toc', -1)

// Update pos so the parser can continue
var newline = state.src.indexOf('\n')
if (newline !== -1) {
state.pos = state.pos + newline
} else {
state.pos = state.pos + state.posMax + 1
}

return true
}

md.renderer.rules.toc_open = function () {
return vBindEscape`<TOC
:class=${options.containerClass}
:list-type=${options.listType}
:include-level=${options.includeLevel}
>`
}

md.renderer.rules.toc_body = function () {
return `<template slot="header">${options.containerHeaderHtml}</template>`
+ `<template slot="footer">${options.containerFooterHtml}</template>`
}

md.renderer.rules.toc_close = function () {
return `</TOC>`
}

// Insert TOC
md.inline.ruler.after('emphasis', 'toc', toc)
}

/** escape double quotes in v-bind derivatives */
function vBindEscape (strs, ...args) {
return strs.reduce((prev, curr, index) => {
return prev + curr + (index >= args.length
? ''
: `"${JSON.stringify(args[index])
.replace(/"/g, "'")
.replace(/([^\\])(\\\\)*\\'/g, (_, char) => char + '\\u0022')}"`)
}, '')
}
13 changes: 2 additions & 11 deletions packages/@vuepress/theme-default/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,10 @@ module.exports = (options, ctx) => ({
}
},

extendMarkdown (md) {
if (options.toc !== false) {
md.use(require('markdown-it-table-of-contents'), {
includeLevel: [2, 3],
...options.toc
})
}
},

plugins: [
['@vuepress/active-header-links', options.activeHeaderLinks],
['@vuepress/search'],
['@vuepress/nprogress'],
'@vuepress/search',
'@vuepress/plugin-nprogress',
['container', {
type: 'tip',
defaultTitle: {
Expand Down
1 change: 0 additions & 1 deletion packages/@vuepress/theme-default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"@vuepress/plugin-nprogress": "^1.0.0-alpha.47",
"@vuepress/plugin-search": "^1.0.0-alpha.47",
"docsearch.js": "^2.5.2",
"markdown-it-table-of-contents": "^0.4.3",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"vuepress-plugin-container": "^2.0.0"
Expand Down
15 changes: 15 additions & 0 deletions packages/docs/docs/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ Options for [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-

The key and value pair will be added to `<a>` tags that point to an external link. The default option will open external links in a new window.

### markdown.toc

- Type: `Object`

This attribute will control the behaviour of `[[TOC]]`. It contains the following options:

- includeLevel: [number, number], level of headers to be included, defaults to `[2, 3]`.
- containerClass: string, the class name for the container, defaults to `table-of-contents`.
- markerPattern: RegExp, the regular expression for the marker to be replaced with TOC, defaults to `/^\[\[toc\]\]/im`.
- listType: string or Array, labels for all levels of the list, defaults to `"ul"`.
- containerHeaderHtml: string, an HTML string for container header, defaults to `""`.
- containerFooterHtml: string, an HTML string for container footer, defaults to `""`.

We also provide a [global component TOC](../guide/using-vue.md#toc) which allows for more free control by passing props directly to `<TOC>`.

### markdown.plugins

You can install any markdown-it plugins through `markdown.plugins` option. It is similar with [using VuePress plugins](../plugin/using-a-plugin.html#using-a-plugin). You can either use Babel style or object style. The `markdown-it-` prefix is optional and can omit in the list.
Expand Down
12 changes: 8 additions & 4 deletions packages/docs/docs/guide/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,25 @@ For more details, check out the [Front Matter](./frontmatter.md) page.

A list of all emojis available can be found [here](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.json).

## Table of Contents <Badge text="default theme"/>
## Table of Contents

**Input**

```md
[[toc]]
```

or

```md
<TOC/>
```

**Output**

[[toc]]

Rendering of TOC can be configured using the [`themeConfig.toc`](../theme/default-theme-config.md#table-of-contents) option.

> You can also use the official plugin [vuepress-plugin-toc](https://vuepress.github.io/plugins/toc/) for an advanced `<TOC/>` component.
Rendering of TOC can be configured using the [`markdown.toc`](../config/README.md#markdown-toc) option, or as props of [TOC component](./using-vue.md#toc), like `<TOC list-type="ol" :include-level="[2, Infinity]"/>`.

## Custom Containers <Badge text="default theme"/>

Expand Down
22 changes: 22 additions & 0 deletions packages/docs/docs/guide/using-vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,28 @@ Specify a specific slot for a specific page (.md) for rendering. This will be ve
- [Markdown Slot](./markdown-slot.md)
- [Writing a theme > Content Outlet](../theme/writing-a-theme.md#content-outlet)

### TOC <Badge text="1.0.0-alpha.41+"/>

- **Props**:
- `listType` - string or Array, defaults to `"ul"`
- `includeLevel` - [number, number], defaults to `[2, 3]`

- **Slots**: `header`, `footer`

- **Usage**:

You can add a custom table of contents by specify some props to this component. `includeLevel` decides which level of headers should be included. `listType` decides the tags of lists. If specified as an array, the component will take the first element as the first-level list type and so on. If there are not enough values provided, the last value will be used for all the remaining list types.

``` md
<TOC :list-type="['ol', 'ul']">
<p slot="header"><strong>Custom Table of Contents</strong></p>
</TOC>
```

<TOC :list-type="['ol', 'ul']">
<p slot="header"><strong>Custom Table of Contents</strong></p>
</TOC>

### Badge <Badge text="beta" type="warn"/> <Badge text="0.10.1+"/> <Badge text="default theme"/>

- **Props**:
Expand Down
20 changes: 0 additions & 20 deletions packages/docs/docs/theme/default-theme-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,26 +304,6 @@ sidebar: false
---
```

## Table Of Contents

``` js
// .vuepress/config.js
module.exports = {
themeConfig: {
toc: {
sidebar: 'auto'
}
}
}
```

Options for [markdown-it-table-of-contents](https://github.com/Oktavilla/markdown-it-table-of-contents#options). The default options are `{ includeLevel: [2, 3] }`.

::: tip
1. You should always use [`markdown.slugify`](../config/#markdown-slugify) instead of `themeConfig.toc.slugify` if you want to customize header ids.
2. Setting `themeConfig.toc` to `false` will disable the `[[toc]]` syntax (in case you want to switch to other plugins, such as [vuepress-plugin-toc](https://vuepress.github.io/plugins/toc/)).
:::

## Search Box

### Built-in Search
Expand Down
15 changes: 15 additions & 0 deletions packages/docs/docs/zh/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,21 @@ VuePress 提供了一种添加额外样式的简便方法。你可以创建一

这个键值对将会作为特性被增加到是外部链接的 `<a>` 标签上,默认的选项将会在新窗口中打开一个该外部链接。

### markdown.toc

- 类型: `Object`

这个值将会控制 `[[TOC]]` 默认行为。它包含下面的选项:

- includeLevel: [number, number],决定哪些级别的标题会被显示在目录中,默认值为 `[2, 3]`
- containerClass: string,决定了目录容器的类名,默认值为 `table-of-contents`
- markerPattern: RegExp,决定了标题匹配的正则表达式,默认值为 `/^\[\[toc\]\]/im`
- listType: string 或 Array,决定了各级列表的标签,默认值为 `"ul"`
- containerHeaderHtml: string,在目录开头插入的 HTML 字符串,默认值为 `""`
- containerFooterHtml: string,在目录结尾插入的 HTML 字符串,默认值为 `""`

此外,我们还提供了[全局组件 TOC](../guide/using-vue.md#toc),可以通过直接向 `<TOC>` 传递属性实现更加自由的控制。

### markdown.plugins

你可以使用 `markdown.plugins` 来安装 markdown-it 插件。它的使用方法与[安装一个 VuePress 插件](../plugin/using-a-plugin.html#using-a-plugin)类似。你可以使用 Babel 语法或对象语法。`markdown-it-` 前缀同样是可以忽略的。
Expand Down
12 changes: 8 additions & 4 deletions packages/docs/docs/zh/guide/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,25 @@ lang: en-US

:tada: :100:

## 目录 <Badge text="默认主题"/>
## 目录

**输入**

```md
[[toc]]
```

或者

```md
<TOC/>
```

**输出**

[[toc]]

目录(Table of Contents)的渲染可以通过 [`themeConfig.toc`](../theme/default-theme-config.md#table-of-contents) 选项来配置。

> 如果想要使用高级的 `<TOC/>` 组件,你也可以使用官方提供的 [vuepress-plugin-toc](https://vuepress.github.io/plugins/toc/) 插件。
目录(Table of Contents)的渲染可以通过 [`markdown.toc`](../config/README.md#markdown-toc) 选项来配置,也可以在 [TOC 组件](./using-vue.md#toc)中直接传入,如 `<TOC list-type="ol" :include-level="[2, Infinity]"/>`

## 自定义容器 <Badge text="默认主题"/>

Expand Down
Loading

0 comments on commit 8013417

Please sign in to comment.