├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── LICENSE
├── README-zh_CN.md
├── README.md
├── lerna.json
├── package.json
└── packages
├── vuepress-plugin-dumi-previewer
├── README-zh_CN.md
├── README.md
├── package.json
└── src
│ ├── Previewer.vue
│ ├── enhanceAppFile.js
│ ├── highlight.js
│ └── index.js
└── vuepress-theme-dumi
├── README-zh_CN.md
├── README.md
├── components
├── AlgoliaSearchBox.vue
├── DropdownLink.vue
├── DropdownTransition.vue
├── Home.vue
├── NavLink.vue
├── NavLinks.vue
├── Navbar.vue
├── Page.vue
├── PageEdit.vue
├── PageNav.vue
├── Sidebar.vue
├── SidebarButton.vue
├── SidebarGroup.vue
├── SidebarLink.vue
└── SidebarLinks.vue
├── global-components
├── Badge.vue
├── CodeBlock.vue
└── CodeGroup.vue
├── index.js
├── layouts
├── 404.vue
└── Layout.vue
├── noopModule.js
├── package.json
├── styles
├── arrow.styl
├── code.styl
├── config.styl
├── custom-blocks.styl
├── index.styl
├── mobile.styl
├── palette.styl
├── toc.styl
└── wrapper.styl
└── util
└── index.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | env: {
4 | browser: true,
5 | node: true,
6 | es6: true
7 | },
8 | extends: [
9 | 'standard',
10 | 'plugin:vue/essential'
11 | ],
12 | plugins: [
13 | 'vue'
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn-error.log
3 | .idea
4 | yarn.lock
5 | .DS_Store
6 | .vscode
7 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Oreki S.H.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README-zh_CN.md:
--------------------------------------------------------------------------------
1 |
vuepress-theme-dumi
2 |
3 | 📖 适配VuePress的dumi样式主题.
4 |
5 | English | 简体中文
6 |
7 | ## 安装
8 |
9 | * 首先安装 [VuePress v1.x](https://github.com/vuejs/vuepress)
10 |
11 | * 接着安装主题
12 |
13 | ```bash
14 | $ npm i -D @vuepress-dumi/vuepress-theme-dumi
15 | # OR
16 | $ yarn add -D @vuepress-dumi/vuepress-theme-dumi
17 | ```
18 |
19 | ## 用法
20 |
21 | 配置VuePress的config.js文件
22 |
23 | ```js
24 | // .vuepress/config.js
25 | module.exports = {
26 | theme: '@vuepress-dumi/dumi',
27 | }
28 | ```
29 |
30 | ## 预览
31 |
32 | 
33 | 
34 | 
35 |
36 | 💡注意: 如果你需要引入element-ui, 则需要指定async-validator的版本:
37 |
38 | ``` bash
39 | $ npm i -D async-validator@1.11.5
40 | # OR
41 | $ yarn add -D async-validator@1.11.5
42 | ```
43 |
44 | ## 代码预览器用法
45 |
46 | 💡注意: `demo`之前的空格是必需的
47 |
48 | ```md
49 | ::: demo
50 | click me
51 |
52 |
61 | :::
62 | ```
63 |
64 | 如果你需要将代码限制在当前代码块的作用域内, 可以使用`demo[scope]`
65 |
66 | 💡注意: ` `标签是必需的, 并且你不能在scope模式下使用`import`语句。另外如果你在一个markdown文件中同时使用`demo[scope]`和`demo`,可能会出现一些报错
67 |
68 | ```md
69 | ::: demo[scope]
70 |
71 | {{ foo }}
72 |
73 |
74 |
81 | :::
82 | ```
83 |
84 | ```md
85 | ::: demo[scope]
86 |
87 | {{ foo }}
88 |
89 |
90 |
97 | :::
98 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | vuepress-theme-dumi
2 |
3 | 📖 A dumi style theme for VuePress.
4 |
5 | English | 简体中文
6 |
7 | ## Install
8 |
9 | * First of all, install [vuepress v1.x](https://github.com/vuejs/vuepress)
10 |
11 | * Then install the theme
12 |
13 | ```bash
14 | $ npm i -D @vuepress-dumi/vuepress-theme-dumi
15 | # OR
16 | $ yarn add -D @vuepress-dumi/vuepress-theme-dumi
17 | ```
18 |
19 | ## Usage
20 | Write vuepress config
21 |
22 | ```js
23 | // .vuepress/config.js
24 | module.exports = {
25 | theme: '@vuepress-dumi/dumi',
26 | }
27 | ```
28 |
29 | ## Preview
30 |
31 | 
32 | 
33 | 
34 |
35 | 💡attention: if you want to import element-ui like me, you need install async-validator@1.11.5
36 |
37 | ``` bash
38 | $ npm i -D async-validator@1.11.5
39 | # OR
40 | $ yarn add -D async-validator@1.11.5
41 | ```
42 |
43 | ## Code Previewer Usage
44 |
45 | 💡attention: whitespace is in need before `demo`
46 |
47 | ```md
48 | ::: demo
49 | click me
50 |
51 |
60 | :::
61 | ```
62 |
63 | If you need code scope, you can use `demo[scope]`.
64 |
65 | 💡attention: ` ` is in need, and you can not use `import` statment in scope mode. And if you use `demo[scope]` and `demo` in one markdown file, browser may print some error.
66 |
67 | ```md
68 | ::: demo[scope]
69 |
70 | {{ foo }}
71 |
72 |
73 |
80 | :::
81 | ```
82 |
83 | ```md
84 | ::: demo[scope]
85 |
86 | {{ foo }}
87 |
88 |
89 |
96 | :::
97 | ```
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*"
4 | ],
5 | "version": "0.3.8"
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "version": "0.3.7",
4 | "workspaces": [
5 | "packages/*"
6 | ],
7 | "devDependencies": {
8 | "eslint": "^7.19.0",
9 | "eslint-config-standard": "^16.0.2",
10 | "eslint-plugin-import": "^2.22.1",
11 | "eslint-plugin-node": "^11.1.0",
12 | "eslint-plugin-promise": "^4.2.1",
13 | "eslint-plugin-vue": "^7.5.0",
14 | "husky": "^4.3.8",
15 | "lerna": "^3.22.1",
16 | "lint-staged": "^10.5.4"
17 | },
18 | "scripts": {
19 | "lint": "eslint --ext .js,.vue ./",
20 | "lintfix": "eslint --fix --ext .js,.vue ./",
21 | "patch": "node_modules/.bin/lerna version patch --no-git-tag-version"
22 | },
23 | "lint-staged": {
24 | "*.{js,vue}": "npm run lint"
25 | },
26 | "husky": {
27 | "hooks": {
28 | "pre-commit": "lint-staged"
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/README-zh_CN.md:
--------------------------------------------------------------------------------
1 | vuepress-plugin-dumi-previewer
2 |
3 | English | 简体中文
4 |
5 | 💡注意: `demo`之前的空格是必需的
6 |
7 | ```md
8 | ::: demo
9 | click me
10 |
11 |
20 | :::
21 | ```
22 |
23 | 如果你需要将代码限制在当前代码块的作用域内, 可以使用`demo[scope]`
24 |
25 | 💡注意: ` `标签是必需的, 并且你不能在scope模式下使用`import`语句。另外如果你在一个markdown文件中同时使用`demo[scope]`和`demo`,可能会出现一些报错
26 |
27 | ```md
28 | ::: demo[scope]
29 |
30 | {{ foo }}
31 |
32 |
33 |
40 | :::
41 | ```
42 |
43 | ```md
44 | ::: demo[scope]
45 |
46 | {{ foo }}
47 |
48 |
49 |
56 | :::
57 | ```
58 |
59 | ## 安装
60 |
61 | * 首先安装 [VuePress v1.x](https://github.com/vuejs/vuepress)
62 |
63 | * 接着安装插件
64 |
65 | ```bash
66 | $ npm i -D @vuepress-dumi/vuepress-plugin-dumi-previewer
67 | # OR
68 | $ yarn add -D @vuepress-dumi/vuepress-plugin-dumi-previewer
69 | ```
70 |
71 | ## 用法
72 |
73 | 配置VuePress的config.js文件
74 |
75 | ```js
76 | // .vuepress/config.js
77 | module.exports = {
78 | plugins: ['@vuepress-dumi/dumi-previewer'],
79 | }
80 | ```
81 |
82 | ## 预览
83 |
84 | 
85 |
86 | 💡注意: 如果你需要引入element-ui, 则需要指定async-validator的版本:
87 |
88 | ``` bash
89 | $ npm i -D async-validator@1.11.5
90 | # OR
91 | $ yarn add -D async-validator@1.11.5
92 | ```
93 |
94 | ## 致谢
95 |
96 | 本项目受到以下开源项目的启发, 感谢他们的杰出贡献
97 |
98 | - [dumi](https://github.com/umijs/dumi)
99 | - [vuepress-plugin-demo-code](https://github.com/BuptStEve/vuepress-plugin-demo-code)
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/README.md:
--------------------------------------------------------------------------------
1 | vuepress-plugin-dumi-previewer
2 |
3 | English | 简体中文
4 |
5 | 💡attention: whitespace is in need before `demo`
6 |
7 | ```md
8 | ::: demo
9 | click me
10 |
11 |
20 | :::
21 | ```
22 |
23 | If you need code scope, you can use `demo[scope]`.
24 |
25 | 💡attention: ` ` is in need, and you can not use `import` statment in scope mode. And if you use `demo[scope]` and `demo` in one markdown file, browser may print some error.
26 |
27 | ```md
28 | ::: demo[scope]
29 |
30 | {{ foo }}
31 |
32 |
33 |
40 | :::
41 | ```
42 |
43 | ```md
44 | ::: demo[scope]
45 |
46 | {{ foo }}
47 |
48 |
49 |
56 | :::
57 | ```
58 |
59 | ## Install
60 |
61 | * First of all, install [vuepress v1.x](https://github.com/vuejs/vuepress)
62 |
63 | * Then install the plugin
64 |
65 | ```bash
66 | $ npm i -D @vuepress-dumi/vuepress-plugin-dumi-previewer
67 | # OR
68 | $ yarn add -D @vuepress-dumi/vuepress-plugin-dumi-previewer
69 | ```
70 |
71 | ## Usage
72 | Write vuepress config
73 |
74 | ```js
75 | // .vuepress/config.js
76 | module.exports = {
77 | plugins: ['@vuepress-dumi/dumi-previewer'],
78 | }
79 | ```
80 |
81 | ## Preview
82 |
83 | 
84 |
85 | 💡attention: if you want to import element-ui like me, you need install async-validator@1.11.5
86 |
87 | ``` bash
88 | $ npm i -D async-validator@1.11.5
89 | # OR
90 | $ yarn add -D async-validator@1.11.5
91 | ```
92 |
93 | ## Thanks
94 |
95 | This repo is inspired by the following projects, Thanks for their great work.
96 |
97 | - [dumi](https://github.com/umijs/dumi)
98 | - [vuepress-plugin-demo-code](https://github.com/BuptStEve/vuepress-plugin-demo-code)
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@vuepress-dumi/vuepress-plugin-dumi-previewer",
3 | "version": "0.3.11",
4 | "description": "A dumi style code previewer plugin for VuePress.",
5 | "keywords": [
6 | "vue",
7 | "vuepress",
8 | "plugin",
9 | "documentation",
10 | "dumi",
11 | "code",
12 | "previewer"
13 | ],
14 | "author": "OrekiSH ",
15 | "homepage": "https://github.com/OrekiSH/vuepress-dumi",
16 | "license": "MIT",
17 | "main": "src/index.js",
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/OrekiSH/vuepress-dumi.git",
21 | "directory": "packages/vuepress-plugin-dumi-previewer"
22 | },
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "bugs": {
27 | "url": "https://github.com/OrekiSH/vuepress-dumi/issues"
28 | },
29 | "dependencies": {
30 | "@babel/standalone": "^7.14.0",
31 | "@vuepress/markdown": "^1.8.0",
32 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
33 | "babel-plugin-syntax-jsx": "^6.18.0",
34 | "babel-plugin-transform-vue-jsx": "^3.7.0",
35 | "copy-to-clipboard": "^3.3.1",
36 | "markdown-it-container": "^3.0.0",
37 | "vue-template-compiler": "^2.6.12"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/src/Previewer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
30 |
31 |
36 |
37 |
38 |
39 |
42 |
46 |
47 |
48 |
49 |
50 |
171 |
172 |
259 |
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/src/enhanceAppFile.js:
--------------------------------------------------------------------------------
1 | import Previewer from './Previewer.vue'
2 |
3 | export default ({ Vue }) => {
4 | Vue.component('Previewer', Previewer)
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/src/highlight.js:
--------------------------------------------------------------------------------
1 | const prism = require('prismjs')
2 | const escapeHtml = require('escape-html')
3 | const loadLanguages = require('prismjs/components/index')
4 |
5 | function wrap (code, lang) {
6 | if (lang === 'text') {
7 | code = escapeHtml(code)
8 | }
9 | return `${code}
`
10 | }
11 |
12 | function getLangCodeFromExtension (extension) {
13 | const extensionMap = {
14 | vue: 'markup',
15 | html: 'markup',
16 | md: 'markdown',
17 | rb: 'ruby',
18 | ts: 'typescript',
19 | py: 'python',
20 | sh: 'bash',
21 | yml: 'yaml',
22 | styl: 'stylus',
23 | kt: 'kotlin',
24 | rs: 'rust'
25 | }
26 |
27 | return extensionMap[extension] || extension
28 | }
29 |
30 | module.exports = (str, lang) => {
31 | if (!lang) {
32 | return wrap(str, 'text')
33 | }
34 | lang = lang.toLowerCase()
35 | const rawLang = lang
36 |
37 | lang = getLangCodeFromExtension(lang)
38 |
39 | if (!prism.languages[lang]) {
40 | try {
41 | loadLanguages([lang])
42 | } catch (e) {
43 | console.warn(`[vuepress] Syntax highlight for language "${lang}" is not supported.`)
44 | }
45 | }
46 | if (prism.languages[lang]) {
47 | const code = prism.highlight(str, prism.languages[lang], lang)
48 | return wrap(code, rawLang)
49 | }
50 | return wrap(str, 'text')
51 | }
52 |
--------------------------------------------------------------------------------
/packages/vuepress-plugin-dumi-previewer/src/index.js:
--------------------------------------------------------------------------------
1 | const markdownItContainer = require('markdown-it-container')
2 |
3 | module.exports = (options = {}) => {
4 | const { marker = 'demo', scopeMaker = 'demo[scope]' } = options
5 |
6 | function render (tokens, idx, endType, scope) {
7 | const { nesting } = tokens[idx]
8 |
9 | if (nesting === -1) {
10 | return '\n'
11 | }
12 |
13 | let htmlStr = ''
14 | let lastLine = 0
15 |
16 | for (let index = idx; index < tokens.length; index++) {
17 | const { map, type, content } = tokens[index]
18 |
19 | if (type === endType) break
20 |
21 | // add empty lines
22 | if (map) {
23 | const delta = map[0] - (lastLine || map[1])
24 |
25 | if (delta > 0) {
26 | htmlStr += '\n'.repeat(delta)
27 | }
28 |
29 | lastLine = map[1]
30 | }
31 |
32 | htmlStr += content
33 | }
34 |
35 | return `
36 |
40 |
41 | `
42 | }
43 |
44 | function slotRender (tokens, index) {
45 | return render(tokens, index, `container_${marker}_close`, false)
46 | }
47 |
48 | function scopeRender (tokens, index) {
49 | return render(tokens, index, `container_${scopeMaker}_close`, true)
50 | }
51 |
52 | return {
53 | name: 'vuepress-plugin-dumi-previewer',
54 | enhanceAppFiles: [
55 | require.resolve('./enhanceAppFile.js')
56 | ],
57 | extendMarkdown: (md) => {
58 | md.use(markdownItContainer, marker, { render: slotRender })
59 | md.use(markdownItContainer, scopeMaker, { render: scopeRender })
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/README-zh_CN.md:
--------------------------------------------------------------------------------
1 | vuepress-theme-dumi
2 |
3 | 📖 适配VuePress的dumi样式主题.
4 |
5 | English | 简体中文
6 |
7 | ## 安装
8 |
9 | * 首先安装 [VuePress v1.x](https://github.com/vuejs/vuepress)
10 |
11 | * 接着安装主题
12 |
13 | ```bash
14 | $ npm i -D @vuepress-dumi/vuepress-theme-dumi
15 | # OR
16 | $ yarn add -D @vuepress-dumi/vuepress-theme-dumi
17 | ```
18 |
19 | ## 用法
20 |
21 | 配置VuePress的config.js文件
22 |
23 | ```js
24 | // .vuepress/config.js
25 | module.exports = {
26 | theme: '@vuepress-dumi/dumi',
27 | }
28 | ```
29 |
30 | ## 预览
31 |
32 | 
33 | 
34 | 
35 |
36 | 💡注意: 如果你需要引入element-ui, 则需要指定async-validator的版本:
37 |
38 | ``` bash
39 | $ npm i -D async-validator@1.11.5
40 | # OR
41 | $ yarn add -D async-validator@1.11.5
42 | ```
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/README.md:
--------------------------------------------------------------------------------
1 | vuepress-theme-dumi
2 |
3 | 📖 A dumi style theme for VuePress.
4 |
5 | English | 简体中文
6 |
7 | ## Install
8 |
9 | * First of all, install [vuepress v1.x](https://github.com/vuejs/vuepress)
10 |
11 | * Then install the theme
12 |
13 | ```bash
14 | $ npm i -D @vuepress-dumi/vuepress-theme-dumi
15 | # OR
16 | $ yarn add -D @vuepress-dumi/vuepress-theme-dumi
17 | ```
18 |
19 | ## Usage
20 | Write vuepress config
21 |
22 | ```js
23 | // .vuepress/config.js
24 | module.exports = {
25 | theme: '@vuepress-dumi/dumi',
26 | }
27 | ```
28 |
29 | ## Preview
30 |
31 | 
32 | 
33 | 
34 |
35 | 💡attention: if you want to import element-ui like me, you need install async-validator@1.11.5
36 |
37 | ``` bash
38 | $ npm i -D async-validator@1.11.5
39 | # OR
40 | $ yarn add -D async-validator@1.11.5
41 | ```
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/AlgoliaSearchBox.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
77 |
78 |
172 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/DropdownLink.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 | {{ item.text }}
13 |
16 |
17 |
23 | {{ item.text }}
24 |
28 |
29 |
30 |
31 |
35 |
40 |
41 | {{ subItem.text }}
42 |
43 |
44 |
63 |
64 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
134 |
135 |
250 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/DropdownTransition.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
34 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
37 |
38 |
42 |
47 |
{{ feature.title }}
48 |
{{ feature.details }}
49 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
62 |
63 |
85 |
86 |
176 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/NavLink.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 | {{ item.text }}
10 |
11 |
19 | {{ item.text }}
20 |
21 |
22 |
23 |
24 |
91 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/NavLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
16 |
20 |
21 |
22 |
23 |
30 | {{ repoLabel }}
31 |
32 |
33 |
34 |
35 |
36 |
124 |
125 |
184 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
15 | {{ $siteTitle }}
21 |
22 |
23 |
36 |
37 |
38 |
39 |
94 |
95 |
173 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
23 |
24 |
32 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/PageEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
19 | {{ lastUpdatedText }}:
20 | {{ lastUpdated }}
21 |
22 |
23 |
24 |
25 |
121 |
122 |
156 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/PageNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 | ←
12 |
19 | {{ prev.title || prev.path }}
20 |
21 |
22 |
23 |
24 |
29 | {{ prev.title || prev.path }}
30 |
31 |
32 |
33 |
37 |
43 | {{ next.title || next.path }}
44 |
45 |
46 |
47 |
48 |
52 | {{ next.title || next.path }}
53 |
54 | →
55 |
56 |
57 |
58 |
59 |
60 |
147 |
148 |
164 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
27 |
28 |
67 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/SidebarButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
40 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/SidebarGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
55 |
56 |
57 |
83 |
84 |
143 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/SidebarLink.vue:
--------------------------------------------------------------------------------
1 |
102 |
103 |
154 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/components/SidebarLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
104 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/global-components/Badge.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
45 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/global-components/CodeBlock.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
25 |
26 |
37 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/global-components/CodeGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
17 | {{ tab.title }}
18 |
19 |
20 |
21 |
22 |
23 |
// Make sure to add code blocks to your code group
27 |
28 |
29 |
30 |
70 |
71 |
106 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // Theme API.
4 | module.exports = (options, ctx) => {
5 | const { themeConfig, siteConfig } = ctx
6 |
7 | // resolve algolia
8 | const isAlgoliaSearch = (
9 | themeConfig.algolia ||
10 | Object
11 | .keys((siteConfig.locales && themeConfig.locales) || {})
12 | .some(base => themeConfig.locales[base].algolia)
13 | )
14 |
15 | const enableSmoothScroll = themeConfig.smoothScroll === true
16 |
17 | return {
18 | alias () {
19 | return {
20 | '@AlgoliaSearchBox': isAlgoliaSearch
21 | ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue')
22 | : path.resolve(__dirname, 'noopModule.js')
23 | }
24 | },
25 |
26 | plugins: [
27 | ['@vuepress/active-header-links', options.activeHeaderLinks],
28 | '@vuepress/search',
29 | '@vuepress/plugin-nprogress',
30 | ['container', {
31 | type: 'tip',
32 | defaultTitle: {
33 | '/': 'TIP',
34 | '/zh/': '提示'
35 | }
36 | }],
37 | ['container', {
38 | type: 'warning',
39 | defaultTitle: {
40 | '/': 'WARNING',
41 | '/zh/': '注意'
42 | }
43 | }],
44 | ['container', {
45 | type: 'danger',
46 | defaultTitle: {
47 | '/': 'WARNING',
48 | '/zh/': '警告'
49 | }
50 | }],
51 | ['container', {
52 | type: 'details',
53 | before: info => `${info ? `${info} ` : ''}\n`,
54 | after: () => ' \n'
55 | }],
56 | ['smooth-scroll', enableSmoothScroll],
57 | '@vuepress-dumi/dumi-previewer',
58 | ]
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/layouts/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
404
5 |
6 |
{{ getMsg() }}
7 |
8 |
9 | Take me home.
10 |
11 |
12 |
13 |
14 |
15 |
31 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/layouts/Layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
152 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/noopModule.js:
--------------------------------------------------------------------------------
1 | export default {}
2 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@vuepress-dumi/vuepress-theme-dumi",
3 | "version": "0.3.11",
4 | "description": "📖 A dumi style theme for VuePress.",
5 | "keywords": [
6 | "vue",
7 | "vuepress",
8 | "theme",
9 | "documentation",
10 | "dumi"
11 | ],
12 | "author": "OrekiSH ",
13 | "homepage": "https://github.com/OrekiSH/vuepress-dumi",
14 | "license": "MIT",
15 | "main": "index.js",
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/OrekiSH/vuepress-dumi.git",
19 | "directory": "packages/vuepress-theme-dumi"
20 | },
21 | "publishConfig": {
22 | "access": "public"
23 | },
24 | "bugs": {
25 | "url": "https://github.com/OrekiSH/vuepress-dumi/issues"
26 | },
27 | "dependencies": {
28 | "@vuepress-dumi/vuepress-plugin-dumi-previewer": "latest"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/arrow.styl:
--------------------------------------------------------------------------------
1 | @require './config'
2 |
3 | .arrow
4 | display inline-block
5 | width 0
6 | height 0
7 | &.up
8 | border-left 4px solid transparent
9 | border-right 4px solid transparent
10 | border-bottom 6px solid $arrowBgColor
11 | &.down
12 | border-left 4px solid transparent
13 | border-right 4px solid transparent
14 | border-top 6px solid $arrowBgColor
15 | &.right
16 | border-top 4px solid transparent
17 | border-bottom 4px solid transparent
18 | border-left 6px solid $arrowBgColor
19 | &.left
20 | border-top 4px solid transparent
21 | border-bottom 4px solid transparent
22 | border-right 6px solid $arrowBgColor
23 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/code.styl:
--------------------------------------------------------------------------------
1 | {$contentClass}
2 | code
3 | color lighten($textColor, 20%)
4 | padding 0.2rem 0.4rem
5 | margin 0
6 | font-size 0.85em
7 | color: #d56161
8 | background: darken(#f9fafb, 1%)
9 |
10 | .token
11 | &.deleted
12 | color #EC5975
13 | &.inserted
14 | color $accentColor
15 |
16 | {$contentClass}
17 | pre, pre[class*="language-"]
18 | line-height 1.4
19 | padding 1.25rem 1.5rem
20 | margin 0.85rem 0
21 | background-color $codeBgColor
22 | border-radius 4px
23 | overflow auto
24 | code
25 | color #fff
26 | padding 0
27 | background-color transparent
28 | border-radius 0
29 |
30 | div[class*="language-"]
31 | position relative
32 | background-color $codeBgColor
33 | border-radius 4px
34 | .highlight-lines
35 | user-select none
36 | padding-top 1.3rem
37 | position absolute
38 | top 0
39 | left 0
40 | width 100%
41 | line-height 1.4
42 | .highlighted
43 | background-color rgba(0, 0, 0, 66%)
44 | pre, pre[class*="language-"]
45 | background transparent
46 | position relative
47 | z-index 1
48 | &::before
49 | position absolute
50 | z-index 3
51 | top 0.8em
52 | right 1em
53 | font-size 0.75rem
54 | color rgba(255, 255, 255, 0.4)
55 | &:not(.line-numbers-mode)
56 | .line-numbers-wrapper
57 | display none
58 | &.line-numbers-mode
59 | .highlight-lines .highlighted
60 | position relative
61 | &:before
62 | content ' '
63 | position absolute
64 | z-index 3
65 | left 0
66 | top 0
67 | display block
68 | width $lineNumbersWrapperWidth
69 | height 100%
70 | background-color rgba(0, 0, 0, 66%)
71 | pre
72 | padding-left $lineNumbersWrapperWidth + 1 rem
73 | vertical-align middle
74 | .line-numbers-wrapper
75 | position absolute
76 | top 0
77 | width $lineNumbersWrapperWidth
78 | text-align center
79 | color rgba(255, 255, 255, 0.3)
80 | padding 1.25rem 0
81 | line-height 1.4
82 | br
83 | user-select none
84 | .line-number
85 | position relative
86 | z-index 4
87 | user-select none
88 | font-size 0.85em
89 | &::after
90 | content ''
91 | position absolute
92 | z-index 2
93 | top 0
94 | left 0
95 | width $lineNumbersWrapperWidth
96 | height 100%
97 | border-radius 4px 0 0 4px
98 | border-right 1px solid rgba(0, 0, 0, 66%)
99 | background-color $codeBgColor
100 |
101 |
102 | for lang in $codeLang
103 | div{'[class~="language-' + lang + '"]'}
104 | &:before
105 | content ('' + lang)
106 |
107 | div[class~="language-javascript"]
108 | &:before
109 | content "js"
110 |
111 | div[class~="language-typescript"]
112 | &:before
113 | content "ts"
114 |
115 | div[class~="language-markup"]
116 | &:before
117 | content "html"
118 |
119 | div[class~="language-markdown"]
120 | &:before
121 | content "md"
122 |
123 | div[class~="language-json"]:before
124 | content "json"
125 |
126 | div[class~="language-ruby"]:before
127 | content "rb"
128 |
129 | div[class~="language-python"]:before
130 | content "py"
131 |
132 | div[class~="language-bash"]:before
133 | content "sh"
134 |
135 | div[class~="language-php"]:before
136 | content "php"
137 |
138 | @import '~prismjs/themes/prism-tomorrow.css'
139 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/config.styl:
--------------------------------------------------------------------------------
1 | $contentClass = '.theme-dumi-content'
2 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/custom-blocks.styl:
--------------------------------------------------------------------------------
1 | .custom-block
2 | box-shadow 0 6px 16px -2px rgba(0, 0, 0, 0.06)
3 | .custom-block-title
4 | font-weight 600
5 | margin-bottom -0.4rem
6 | &.tip, &.warning, &.danger
7 | padding .1rem 1.5rem
8 | border-left-width .5rem
9 | border-left-style solid
10 | margin 1rem 0
11 | &.tip
12 | border-color #8cd225
13 | background-color #f3f5f7
14 | &.warning
15 | background-color rgba(255,229,100,.3)
16 | border-color darken(#ffc121, 35%)
17 | color darken(#ffc121, 70%)
18 | .custom-block-title
19 | color darken(#ffc121, 50%)
20 | a
21 | color $textColor
22 | &.danger
23 | background-color #ffe6e6
24 | border-color darken(#ff4646, 20%)
25 | color darken(#ff4646, 70%)
26 | .custom-block-title
27 | color darken(#ff4646, 40%)
28 | a
29 | color $textColor
30 | &.details
31 | display block
32 | position relative
33 | border-radius 2px
34 | margin 1.6em 0
35 | padding 1.6em
36 | background-color #eee
37 | h4
38 | margin-top 0
39 | figure, p
40 | &:last-child
41 | margin-bottom 0
42 | padding-bottom 0
43 | summary
44 | outline none
45 | cursor pointer
46 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/index.styl:
--------------------------------------------------------------------------------
1 | @require './config'
2 | @require './code'
3 | @require './custom-blocks'
4 | @require './arrow'
5 | @require './wrapper'
6 | @require './toc'
7 |
8 | html, body
9 | padding 0
10 | margin 0
11 | background-color #fff
12 |
13 | body
14 | font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
15 | -webkit-font-smoothing antialiased
16 | -moz-osx-font-smoothing grayscale
17 | font-size 15px
18 | color $textColor
19 |
20 | .page
21 | padding-left $sidebarWidth
22 |
23 | .navbar
24 | position fixed
25 | z-index 20
26 | top 0
27 | left 0
28 | right 0
29 | height $navbarHeight
30 | background-color #fff
31 | box-sizing border-box
32 | box-shadow 0 8px 24px -2px rgba(0, 0, 0, 0.05)
33 |
34 | .sidebar-mask
35 | position fixed
36 | z-index 9
37 | top 0
38 | left 0
39 | width 100vw
40 | height 100vh
41 | display none
42 |
43 | .sidebar
44 | font-size 16px
45 | background-color #fff
46 | width $sidebarWidth
47 | position fixed
48 | z-index 10
49 | margin 0
50 | top $navbarHeight
51 | left 0
52 | bottom 0
53 | box-sizing border-box
54 | border-right 1px solid $borderColor
55 | overflow-y auto
56 |
57 | {$contentClass}:not(.custom)
58 | @extend $wrapper
59 | > *:first-child
60 | margin-top $navbarHeight
61 |
62 | a:hover
63 | text-decoration underline
64 |
65 | p.demo
66 | padding 1rem 1.5rem
67 | border 1px solid #ddd
68 | border-radius 4px
69 |
70 | img
71 | max-width 100%
72 |
73 | {$contentClass}.custom
74 | padding 0
75 | margin 0
76 |
77 | img
78 | max-width 100%
79 |
80 | a
81 | font-weight 500
82 | color $accentColor
83 | text-decoration none
84 |
85 | p a code
86 | font-weight 400
87 | color $accentColor
88 |
89 | p span
90 | .icon.outbound
91 | color $accentColor
92 |
93 | kbd
94 | background #eee
95 | border solid 0.15rem #ddd
96 | border-bottom solid 0.25rem #ddd
97 | border-radius 0.15rem
98 | padding 0 0.15em
99 |
100 | blockquote:not([class])
101 | font-size 1rem
102 | color #999;
103 | border-left .2rem solid #dfe2e5
104 | margin 1rem 0
105 | padding .25rem 0 .25rem 1rem
106 |
107 | & > p
108 | margin 0
109 |
110 | ul:not([class]), ol:not([class])
111 | padding-left 1.2em
112 |
113 | strong
114 | font-weight 600
115 |
116 | h1, h2, h3, h4, h5, h6
117 | font-weight 600
118 | line-height 1.25
119 |
120 | {$contentClass}:not(.custom) > &
121 | margin-top (0.5rem - $navbarHeight)
122 | padding-top ($navbarHeight + 2rem)
123 | margin-bottom 0
124 |
125 | &:first-child
126 | margin-top -1.5rem
127 | margin-bottom 1rem
128 |
129 | + p, + pre, + .custom-block
130 | margin-top 2rem
131 |
132 | &:focus .header-anchor,
133 | &:hover .header-anchor
134 | opacity: 1
135 |
136 | h1:not([class])
137 | font-size 2.2rem
138 |
139 | h2:not([class])
140 | font-size 1.65rem
141 | padding-bottom .3rem
142 | margin-bottom: .5rem
143 |
144 | h3:not([class])
145 | font-size 1.35rem
146 |
147 | a.header-anchor
148 | font-size 0.85em
149 | float left
150 | margin-left -0.87em
151 | padding-right 0.23em
152 | margin-top 0.125em
153 | opacity 0
154 |
155 | &:focus,
156 | &:hover
157 | text-decoration none
158 |
159 | code:not([class]), kbd:not([class]), .line-number
160 | font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace
161 |
162 | p:not([class]), ul:not([class]), ol:not([class])
163 | line-height 1.7
164 |
165 | hr:not([class])
166 | border 0
167 | border-top 1px solid $borderColor
168 |
169 | {$contentClass}
170 | table:not([class])
171 | border-collapse collapse
172 | margin 1rem 0
173 | display block
174 | overflow-x auto
175 | color: #454d64
176 |
177 | tr:not([class])
178 | border-top 1px solid #ebedf1
179 |
180 | th:not([class])
181 | background: #f9fafb
182 | font-weight: 500
183 | text-align: left
184 |
185 | th:not([class]), td:not([class])
186 | border 1px solid #ebedf1
187 | padding 10px 24px
188 |
189 | .theme-container
190 | &.sidebar-open
191 | .sidebar-mask
192 | display: block
193 |
194 | &.no-navbar
195 | {$contentClass}:not(.custom) > h1, h2, h3, h4, h5, h6
196 | margin-top 1.5rem
197 | padding-top 0
198 |
199 | .sidebar
200 | top 0
201 |
202 | @media (min-width: ($MQMobile + 1px))
203 | .theme-container.no-sidebar
204 | .sidebar
205 | display none
206 |
207 | .page
208 | padding-left 0
209 |
210 | @require 'mobile.styl'
211 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/mobile.styl:
--------------------------------------------------------------------------------
1 | @require './config'
2 |
3 | $mobileSidebarWidth = $sidebarWidth * 0.82
4 |
5 | // narrow desktop / iPad
6 | @media (max-width: $MQNarrow)
7 | .sidebar
8 | font-size 15px
9 | width $mobileSidebarWidth
10 | .page
11 | padding-left $mobileSidebarWidth
12 |
13 | // wide mobile
14 | @media (max-width: $MQMobile)
15 | .sidebar
16 | top 0
17 | padding-top $navbarHeight
18 | transform translateX(-100%)
19 | transition transform .2s ease
20 | .page
21 | padding-left 0
22 | .theme-container
23 | &.sidebar-open
24 | .sidebar
25 | transform translateX(0)
26 | &.no-navbar
27 | .sidebar
28 | padding-top: 0
29 |
30 | // narrow mobile
31 | @media (max-width: $MQMobileNarrow)
32 | h1
33 | font-size 1.9rem
34 | {$contentClass}
35 | div[class*="language-"]
36 | margin 0.85rem -1.5rem
37 | border-radius 0
38 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/palette.styl:
--------------------------------------------------------------------------------
1 | // colors
2 | $accentColor = #4569d4
3 | $textColor = #454d64
4 | $borderColor = #ebedf1
5 | $codeBgColor = #282c34
6 | $arrowBgColor = lighten(#4d5164, 10%)
7 | $badgeTipColor = #42b983
8 | $badgeWarningColor = darken(#ffe564, 35%)
9 | $badgeErrorColor = #DA5961
10 |
11 | // layout
12 | $navbarHeight = 4rem
13 | $sidebarWidth = 20rem
14 | $contentWidth = 740px
15 | $homePageWidth = 960px
16 |
17 | // responsive breakpoints
18 | $MQNarrow = 959px
19 | $MQMobile = 719px
20 | $MQMobileNarrow = 419px
21 |
22 | // code
23 | $lineNumbersWrapperWidth = 3.5rem
24 | $codeLang = js ts html md vue css sass scss less stylus go java c sh yaml py docker dockerfile makefile
25 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/toc.styl:
--------------------------------------------------------------------------------
1 | .table-of-contents
2 | .badge
3 | vertical-align middle
4 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/styles/wrapper.styl:
--------------------------------------------------------------------------------
1 | $wrapper
2 | max-width $contentWidth
3 | margin 0 auto
4 | padding 2rem 2.5rem
5 | @media (max-width: $MQNarrow)
6 | padding 2rem
7 | @media (max-width: $MQMobileNarrow)
8 | padding 1.5rem
9 |
10 |
--------------------------------------------------------------------------------
/packages/vuepress-theme-dumi/util/index.js:
--------------------------------------------------------------------------------
1 | export const hashRE = /#.*$/
2 | export const extRE = /\.(md|html)$/
3 | export const endingSlashRE = /\/$/
4 | export const outboundRE = /^[a-z]+:/i
5 |
6 | export function normalize (path) {
7 | return decodeURI(path)
8 | .replace(hashRE, '')
9 | .replace(extRE, '')
10 | }
11 |
12 | export function getHash (path) {
13 | const match = path.match(hashRE)
14 | if (match) {
15 | return match[0]
16 | }
17 | }
18 |
19 | export function isExternal (path) {
20 | return outboundRE.test(path)
21 | }
22 |
23 | export function isMailto (path) {
24 | return /^mailto:/.test(path)
25 | }
26 |
27 | export function isTel (path) {
28 | return /^tel:/.test(path)
29 | }
30 |
31 | export function ensureExt (path) {
32 | if (isExternal(path)) {
33 | return path
34 | }
35 | const hashMatch = path.match(hashRE)
36 | const hash = hashMatch ? hashMatch[0] : ''
37 | const normalized = normalize(path)
38 |
39 | if (endingSlashRE.test(normalized)) {
40 | return path
41 | }
42 | return normalized + '.html' + hash
43 | }
44 |
45 | export function isActive (route, path) {
46 | const routeHash = decodeURIComponent(route.hash)
47 | const linkHash = getHash(path)
48 | if (linkHash && routeHash !== linkHash) {
49 | return false
50 | }
51 | const routePath = normalize(route.path)
52 | const pagePath = normalize(path)
53 | return routePath === pagePath
54 | }
55 |
56 | export function resolvePage (pages, rawPath, base) {
57 | if (isExternal(rawPath)) {
58 | return {
59 | type: 'external',
60 | path: rawPath
61 | }
62 | }
63 | if (base) {
64 | rawPath = resolvePath(rawPath, base)
65 | }
66 | const path = normalize(rawPath)
67 | for (let i = 0; i < pages.length; i++) {
68 | if (normalize(pages[i].regularPath) === path) {
69 | return Object.assign({}, pages[i], {
70 | type: 'page',
71 | path: ensureExt(pages[i].path)
72 | })
73 | }
74 | }
75 | console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
76 | return {}
77 | }
78 |
79 | function resolvePath (relative, base, append) {
80 | const firstChar = relative.charAt(0)
81 | if (firstChar === '/') {
82 | return relative
83 | }
84 |
85 | if (firstChar === '?' || firstChar === '#') {
86 | return base + relative
87 | }
88 |
89 | const stack = base.split('/')
90 |
91 | // remove trailing segment if:
92 | // - not appending
93 | // - appending to trailing slash (last segment is empty)
94 | if (!append || !stack[stack.length - 1]) {
95 | stack.pop()
96 | }
97 |
98 | // resolve relative path
99 | const segments = relative.replace(/^\//, '').split('/')
100 | for (let i = 0; i < segments.length; i++) {
101 | const segment = segments[i]
102 | if (segment === '..') {
103 | stack.pop()
104 | } else if (segment !== '.') {
105 | stack.push(segment)
106 | }
107 | }
108 |
109 | // ensure leading slash
110 | if (stack[0] !== '') {
111 | stack.unshift('')
112 | }
113 |
114 | return stack.join('/')
115 | }
116 |
117 | /**
118 | * @param { Page } page
119 | * @param { string } regularPath
120 | * @param { SiteData } site
121 | * @param { string } localePath
122 | * @returns { SidebarGroup }
123 | */
124 | export function resolveSidebarItems (page, regularPath, site, localePath) {
125 | const { pages, themeConfig } = site
126 |
127 | const localeConfig = localePath && themeConfig.locales
128 | ? themeConfig.locales[localePath] || themeConfig
129 | : themeConfig
130 |
131 | const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
132 | if (pageSidebarConfig === 'auto') {
133 | return resolveHeaders(page)
134 | }
135 |
136 | const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
137 | if (!sidebarConfig) {
138 | return []
139 | } else {
140 | const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
141 | if (config === 'auto') {
142 | return resolveHeaders(page)
143 | }
144 | return config
145 | ? config.map(item => resolveItem(item, pages, base))
146 | : []
147 | }
148 | }
149 |
150 | /**
151 | * @param { Page } page
152 | * @returns { SidebarGroup }
153 | */
154 | function resolveHeaders (page) {
155 | const headers = groupHeaders(page.headers || [])
156 | return [{
157 | type: 'group',
158 | collapsable: false,
159 | title: page.title,
160 | path: null,
161 | children: headers.map(h => ({
162 | type: 'auto',
163 | title: h.title,
164 | basePath: page.path,
165 | path: page.path + '#' + h.slug,
166 | children: h.children || []
167 | }))
168 | }]
169 | }
170 |
171 | export function groupHeaders (headers) {
172 | // group h3s under h2
173 | headers = headers.map(h => Object.assign({}, h))
174 | let lastH2
175 | headers.forEach(h => {
176 | if (h.level === 2) {
177 | lastH2 = h
178 | } else if (lastH2) {
179 | (lastH2.children || (lastH2.children = [])).push(h)
180 | }
181 | })
182 | return headers.filter(h => h.level === 2)
183 | }
184 |
185 | export function resolveNavLinkItem (linkItem) {
186 | return Object.assign(linkItem, {
187 | type: linkItem.items && linkItem.items.length ? 'links' : 'link'
188 | })
189 | }
190 |
191 | /**
192 | * @param { Route } route
193 | * @param { Array | Array | [link: string]: SidebarConfig } config
194 | * @returns { base: string, config: SidebarConfig }
195 | */
196 | export function resolveMatchingConfig (regularPath, config) {
197 | if (Array.isArray(config)) {
198 | return {
199 | base: '/',
200 | config: config
201 | }
202 | }
203 | for (const base in config) {
204 | if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
205 | return {
206 | base,
207 | config: config[base]
208 | }
209 | }
210 | }
211 | return {}
212 | }
213 |
214 | function ensureEndingSlash (path) {
215 | return /(\.html|\/)$/.test(path)
216 | ? path
217 | : path + '/'
218 | }
219 |
220 | function resolveItem (item, pages, base, groupDepth = 1) {
221 | if (typeof item === 'string') {
222 | return resolvePage(pages, item, base)
223 | } else if (Array.isArray(item)) {
224 | return Object.assign(resolvePage(pages, item[0], base), {
225 | title: item[1]
226 | })
227 | } else {
228 | const children = item.children || []
229 | if (children.length === 0 && item.path) {
230 | return Object.assign(resolvePage(pages, item.path, base), {
231 | title: item.title
232 | })
233 | }
234 | return {
235 | type: 'group',
236 | path: item.path,
237 | title: item.title,
238 | sidebarDepth: item.sidebarDepth,
239 | initialOpenGroupIndex: item.initialOpenGroupIndex,
240 | children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
241 | collapsable: item.collapsable !== false
242 | }
243 | }
244 | }
245 |
--------------------------------------------------------------------------------