(https://github.com/ulivz)
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vuepress-plugin-schema2md
2 |
3 | [](https://npmjs.com/package/vuepress-plugin-schema2md) [](https://npmjs.com/package/vuepress-plugin-schema2md) 
4 |
5 | ## Feature
6 |
7 | - 📄 Generate dynamic VuePress pages from JSON Schemas.
8 | - ❤️ HMR Support!
9 | - 🎁 Support extra markdown file to be merged into final content.
10 |
11 | ## Example
12 |
13 | 
14 |
15 |
16 | Tip. you can execute npm run docs:dev
on thie repo to check out this example.
17 |
18 |
19 |
20 | ## Install
21 |
22 | ```bash
23 | yarn add vuepress-plugin-schema2md -D
24 | # OR npm install vuepress-plugin-schema2md -D
25 | ```
26 |
27 | ## Usage
28 |
29 | ```js
30 | // .vuepress/config.js
31 | module.exports = {
32 | plugins: [
33 | [
34 | 'schema2md', {
35 | // Options
36 | }
37 | ]
38 | ]
39 | }
40 | ```
41 |
42 | ## Options
43 |
44 | ### pages
45 |
46 | - Type: `Record`
47 | - Description: describe the generated pages.
48 |
49 | e.g.
50 |
51 | ```js
52 | // .vuepress/config.js
53 | module.exports = {
54 | plugins: ['schema2md', {
55 | pages: {
56 | '/config/': {
57 | schemaPath: '/path/to/your/schema.json'
58 | }
59 | }
60 | }]
61 | }
62 | ```
63 |
64 | Then you will get a dynamic page with route `/config/`, whose content is generated by [schema2md](https://github.com/rich-lab/schema2md) from `'/path/to/your/schema.json'`,
65 |
66 | For typings of interface `ITransformOptions`, plead head [schema2md](https://github.com/rich-lab/schema2md).
67 |
68 | ### cwd
69 |
70 | - Type: `string`
71 | - Description: Current working directory, used to calcaulate absolute path for "schemaPath" and "outputPath" with relative path, defaults to `process.cwd()`.
72 |
73 | ### locale
74 |
75 | - Type: `string`
76 | - Description: Global locale.
77 |
78 | ### write
79 |
80 | - Type: `boolean`
81 | - Description: whether to generate the markdown content to disk.
82 |
83 | If you want to check out the generated markdown, you could do like this:
84 |
85 | ```diff
86 | // .vuepress/config.js
87 | module.exports = {
88 | plugins: ['schema2md', {
89 | + write: true,
90 | pages: {
91 | '/config/': {
92 | schemaPath: '/path/to/your/schema.json'
93 | + outputPath: 'docs/config/README.md', // You shouldn't commit this file.
94 | }
95 | }
96 | }]
97 | }
98 | ```
99 |
100 | ## Contributing
101 |
102 | 1. Fork it!
103 | 2. Create your feature branch: `git checkout -b my-new-feature`
104 | 3. Commit your changes: `git commit -am 'Add some feature'`
105 | 4. Push to the branch: `git push origin my-new-feature`
106 | 5. Submit a pull request :D
107 |
108 |
109 | ## Author
110 |
111 | **vuepress-plugin-schema2md** © [ULIVZ](https://github.com/ulivz), Released under the [MIT](./LICENSE) License.
112 |
113 |
114 | > [github.com/ulivz](https://github.com/ulivz) · GitHub [@ULIVZ](https://github.com/ulivz) · Twitter [@_ulivz](https://twitter.com/_ulivz)
115 |
116 |
117 |
--------------------------------------------------------------------------------
/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | const plugin = require('../lib')
2 |
3 | it('simple', async () => {
4 | expect(typeof plugin).toBe('function')
5 | })
6 |
7 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | const { join, resolve } = require('path')
2 | const pkg = require('../../package')
3 |
4 | module.exports = {
5 | title: pkg.name,
6 | description: pkg.description,
7 | additionalPages: [
8 | {
9 | path: '/',
10 | filePath: resolve(__dirname, '../../README.md')
11 | },
12 | ],
13 | themeConfig: {
14 | nav: [
15 | { text: 'foo.config.js', link: '/config/' },
16 | ],
17 | },
18 | plugins: [
19 | [require('../../lib'), {
20 | cwd: __dirname,
21 | pages: {
22 | '/config/': {
23 | schemaPath: 'schemas/schema.json'
24 | }
25 | }
26 | }]
27 | ],
28 | }
29 |
--------------------------------------------------------------------------------
/docs/.vuepress/schemas/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "foo.config.js",
3 | "description": "Description of foo.config.js",
4 | "properties": {
5 | "type": {
6 | "description": "TYPE's description",
7 | "type": "string",
8 | "enum": [
9 | "foo",
10 | "bar"
11 | ]
12 | },
13 | "env": {
14 | "description": "ENV's description",
15 | "type": "string"
16 | },
17 | "name": {
18 | "description": "ENV's description",
19 | "type": "string"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/docs/.vuepress/schemas/schema.md:
--------------------------------------------------------------------------------
1 | ## type
2 |
3 | extra content of type.
4 |
5 | ::: warning WARN
6 | This is a warning of type's usage.
7 | :::
8 |
9 | ## env
10 |
11 | extra content of env.
12 |
13 | ::: tip TIP
14 | This is a env of env's usage.
15 | :::
16 |
17 | ## env
18 |
19 | extra content of name.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Vuepress-plugin-schema2md © 2016-present.
3 | * @author ulivz
4 | * @date March.7th, 2020
5 | */
6 |
7 | const { watch } = require('chokidar')
8 | const {
9 | logger,
10 | fs,
11 | chalk: { cyan },
12 | } = require('@vuepress/shared-utils')
13 | const {
14 | resolveSchemaMarkdownPath,
15 | batchTransform,
16 | normalizePath,
17 | transform,
18 | } = require('schema2md')
19 |
20 | let watcher
21 |
22 | module.exports = (options, ctx) => {
23 | /**
24 | * Watch scheme file and emit the temp markdown file when it's changed.
25 | *
26 | * @param {object} paths
27 | * @param {function} callback
28 | */
29 | function addSchemaListener(paths, callback) {
30 | if (watcher) {
31 | return
32 | }
33 |
34 | const watchPaths = paths.reduce((memo, p) => {
35 | memo.push(p.schemaPath)
36 | memo.push(p.schemaMarkdownPath)
37 | return memo
38 | }, [])
39 |
40 | watcher = watch(watchPaths, {
41 | ignoreInitial: true,
42 | })
43 |
44 | const handleSchemaChange = schemaPath => {
45 | let target
46 | if (schemaPath.endsWith('.json')) {
47 | target = paths.find(p => p.schemaPath === schemaPath)
48 | } else {
49 | target = paths.find(p => p.schemaMarkdownPath === schemaPath)
50 | }
51 |
52 | const { sitePath } = target
53 | const targetPage = ctx.pages.find(page => page.path === sitePath)
54 | if (targetPage) {
55 | const { _filePath } = targetPage
56 | return {
57 | sitePath,
58 | filePath: _filePath,
59 | schemaPath,
60 | }
61 | }
62 | }
63 |
64 | watcher.on('change', schemaPath => {
65 | logger.tip(`[schema2md] ${cyan(schemaPath)} changed`)
66 | const ret = handleSchemaChange(schemaPath)
67 | callback(ret)
68 | })
69 |
70 | watcher.on('unlink', schemaPath => {
71 | logger.tip(`[schema2md] ${cyan(schemaPath)} removed`)
72 | const ret = handleSchemaChange(schemaPath)
73 | fs.removeSync(ret.filePath)
74 | })
75 | }
76 |
77 | return {
78 | async additionalPages() {
79 | const { cwd = process.cwd(), locale, write = false, pages } = options
80 | const pagePaths = Object.keys(pages)
81 | const configs = pagePaths.map(p => pages[p])
82 |
83 | const schemaPaths = pagePaths.map(p => {
84 | const abSchemaPath = normalizePath(cwd, pages[p].schemaPath)
85 | return {
86 | sitePath: p,
87 | schemaMarkdownPath: resolveSchemaMarkdownPath(
88 | pages[p].schemaMarkdown,
89 | abSchemaPath,
90 | ),
91 | schemaPath: abSchemaPath,
92 | }
93 | })
94 |
95 | addSchemaListener(schemaPaths, async ret => {
96 | const targetConfog = pages[ret.sitePath]
97 | if (targetConfog) {
98 | const content = await transform({
99 | cwd,
100 | locale,
101 | write,
102 | ...targetConfog,
103 | })
104 | await fs.writeFile(ret.filePath, content, 'utf-8')
105 | }
106 | })
107 |
108 | const ret = await batchTransform({
109 | cwd,
110 | locale,
111 | write,
112 | configs,
113 | })
114 |
115 | return pagePaths.map((path, index) => ({
116 | path,
117 | content: ret[index],
118 | }))
119 | },
120 |
121 | generated() {
122 | if (watcher) {
123 | watcher.close && watcher.close()
124 | }
125 | },
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuepress-plugin-schema2md",
3 | "version": "0.2.2",
4 | "description": "A VuePress plugin to help you generate pages via JSON Schema (HMR Support).",
5 | "main": "lib/index.js",
6 | "files": [
7 | "lib"
8 | ],
9 | "scripts": {
10 | "test": "jest",
11 | "cov": "jest --coverage",
12 | "lint": "eslint --fix lib",
13 | "prepublishOnly": "conventional-changelog -p angular -r 2 -i CHANGELOG.md -s",
14 | "docs:dev": "vuepress dev docs --temp docs/.temp",
15 | "docs:build": "npm run docs:prepare && vuepress build docs --temp docs/.temp",
16 | "depcost": "depcost --record --npm-client=npm",
17 | "postpublish": "npm run depcost"
18 | },
19 | "repository": {
20 | "url": "https://github.com/rich-lab/json-schema-2-markdown",
21 | "type": "git"
22 | },
23 | "author": "ulivz ",
24 | "license": "MIT",
25 | "dependencies": {
26 | "chokidar": "^3.3.1",
27 | "schema2md": "^0.1.5"
28 | },
29 | "devDependencies": {
30 | "vuepress": "^1.3.1",
31 | "@vuepress/shared-utils": "^1.3.1",
32 | "jest-cli": "^25.1.0",
33 | "eslint": "^6.8.0",
34 | "eslint-config-lab": "^0.1.4",
35 | "depcost": "^0.2.1"
36 | },
37 | "publishConfig": {
38 | "registry": "https://registry.npmjs.org/"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------