├── src
├── web
│ ├── rdoc.tree.data.json
│ ├── index.js
│ └── Router.js
├── commands
│ ├── clean.js
│ └── initProject.js
├── build.js
├── publish.js
├── conf
│ ├── webpack.config.server.js
│ ├── webpack.config.js
│ ├── path.js
│ ├── webpack.config.dev.js
│ └── webpack.config.prod.js
├── utils
│ └── initCatch.js
└── server.js
├── rdoc.png
├── theme
└── default
│ ├── lib
│ └── markdown
│ │ ├── style
│ │ ├── diff.less
│ │ ├── xml.less
│ │ ├── swift.less
│ │ ├── css.less
│ │ ├── javascript.less
│ │ ├── index.less
│ │ └── default.less
│ │ ├── Link.less
│ │ ├── InlineCode.less
│ │ ├── Link.js
│ │ ├── InlineCode.js
│ │ └── index.js
│ ├── favicon.ico
│ ├── component
│ ├── Loading
│ │ ├── index.less
│ │ └── index.js
│ ├── Footer
│ │ ├── index.less
│ │ └── index.js
│ ├── NoMatch
│ │ ├── index.js
│ │ └── index.less
│ └── Header
│ │ ├── index.less
│ │ └── index.js
│ ├── routes
│ └── Pages
│ │ └── index.js
│ ├── layout
│ ├── IndexLayout.less
│ ├── BasicLayout.less
│ ├── IndexLayout.js
│ └── BasicLayout.js
│ ├── index.html
│ ├── index.less
│ ├── rdoc.logo.svg
│ └── index.js
├── templates
└── default
│ ├── introduce
│ ├── api
│ │ ├── README.md
│ │ ├── markdown-config.md
│ │ ├── commands.md
│ │ ├── conf.md
│ │ └── theme-api.md
│ ├── guides
│ │ ├── README.md
│ │ ├── add-blog.md
│ │ ├── website.md
│ │ ├── menu-sort.md
│ │ ├── add-index.md
│ │ ├── link.md
│ │ ├── insert-img.md
│ │ ├── html.md
│ │ ├── custom-menu.md
│ │ └── theme.md
│ ├── getting-started
│ │ ├── README.md
│ │ ├── install.md
│ │ ├── site-preparation.md
│ │ ├── publish.md
│ │ └── site-creation.md
│ ├── README.md
│ ├── assets
│ │ └── react-logo.svg
│ ├── precautions.md
│ └── init-project.md
│ ├── github
│ └── README.md
│ ├── about
│ └── README.md
│ ├── _.gitignore
│ ├── _.editorconfig
│ ├── faq
│ └── README.md
│ ├── _package.json
│ └── home
│ └── README.md
├── .npmignore
├── .gitignore
├── .editorconfig
├── .github
└── FUNDING.yml
├── .babelrc.js
├── .eslintrc.js
├── .bin
└── rdoc.js
├── package.json
├── README_zh.md
└── README.md
/src/web/rdoc.tree.data.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/rdoc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jaywcjlove/rdoc/HEAD/rdoc.png
--------------------------------------------------------------------------------
/theme/default/lib/markdown/style/diff.less:
--------------------------------------------------------------------------------
1 | .language-diff {
2 |
3 | }
--------------------------------------------------------------------------------
/theme/default/lib/markdown/style/xml.less:
--------------------------------------------------------------------------------
1 | .language-html, .xml{
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/templates/default/introduce/api/README.md:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/templates/default/introduce/guides/README.md:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/templates/default/introduce/getting-started/README.md:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/theme/default/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jaywcjlove/rdoc/HEAD/theme/default/favicon.ico
--------------------------------------------------------------------------------
/templates/default/github/README.md:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/templates/default/introduce/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .cache
2 | .gitignore
3 | .editorconfig
4 | .rdoc-dist
5 | node_modules
6 | package-lock.json
7 | dist
8 | rdoc.png
9 |
--------------------------------------------------------------------------------
/theme/default/component/Loading/index.less:
--------------------------------------------------------------------------------
1 | .loading {
2 | text-align: center;
3 | min-height: 450px;
4 | padding: 30px 0;
5 | }
6 |
--------------------------------------------------------------------------------
/templates/default/about/README.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | 这是一个文档生成工具,用于生成文档网站或简单的博客网站,你可以放到项目中依赖,也可以单独使用,更轻松的制作一个网站或者文档网站。
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .rdoc-dist
3 | package-lock.json
4 | .cache
5 | .DS_Store
6 |
7 | *.bak
8 | *.tem
9 | *.log
10 | *.temp
11 | #.swp
12 | *.*~
13 | ~*.*
14 |
--------------------------------------------------------------------------------
/theme/default/lib/markdown/Link.less:
--------------------------------------------------------------------------------
1 | .frame {
2 | width: 100%;
3 | min-height: 400px;
4 | border: 1px solid #e9e9e9;
5 | border-radius: 3px;
6 | background: #fff;
7 | }
8 |
--------------------------------------------------------------------------------
/templates/default/_.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | .DS_Store
4 | .cache
5 | .rdoc-dist
6 |
7 | *.bak
8 | *.log
9 | *.tem
10 | *.temp
11 | #.swp
12 | *.*~
13 | ~*.*
14 |
--------------------------------------------------------------------------------
/theme/default/routes/Pages/index.js:
--------------------------------------------------------------------------------
1 | import Markdown from '../../lib/markdown';
2 |
3 | export default class Pages extends Markdown {
4 | constructor(props) {
5 | super(props);
6 | this.page = props.page;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/theme/default/component/Loading/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.less';
3 |
4 | const Loading = () => {
5 | return (
6 |
7 | 正在加载中....
8 |
9 | );
10 | };
11 |
12 | export default Loading;
13 |
--------------------------------------------------------------------------------
/theme/default/layout/IndexLayout.less:
--------------------------------------------------------------------------------
1 | .header {
2 | background-color: transparent;
3 | box-shadow: 0 0 0 #fff;
4 | border-bottom: 0;
5 | background-color: rgba(255, 255, 255, 0.9);
6 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
7 | }
8 | .wapper {
9 | min-height: 500px;
10 | padding: 57px 0 0 0;
11 | }
12 |
--------------------------------------------------------------------------------
/theme/default/lib/markdown/style/swift.less:
--------------------------------------------------------------------------------
1 | .language-swift {
2 | .keyword, .selector-tag, .subst {
3 | color: #C600AA;
4 | font-weight: normal;
5 | }
6 | .meta {
7 | color: #C526D0;
8 | font-weight: normal;
9 | }
10 | .type, .class .title {
11 | color: #7C10B2;
12 | font-weight: normal;
13 | }
14 | }
--------------------------------------------------------------------------------
/theme/default/component/Footer/index.less:
--------------------------------------------------------------------------------
1 | .footer {
2 | font-size: 14px;
3 | text-align: center;
4 | border-top: 1px solid #e9e9e9;
5 | margin-top: 50px;
6 | padding: 20px 0 50px 0;
7 | clear: both;
8 | color: #999;
9 | a {
10 | color: #758AC5;
11 | &:hover {
12 | color: #0800ff;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/web/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-named-as-default-member */
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import '@babel/polyfill';
5 | // eslint-disable-next-line import/no-named-as-default
6 | import RouterRoot from './Router';
7 |
8 | ReactDOM.render(
9 | ,
10 | document.getElementById('root')
11 | );
12 |
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [*.less]
16 | indent_style = space
17 | indent_size = 2
18 |
19 | [Makefile]
20 | indent_style = tab
21 |
--------------------------------------------------------------------------------
/templates/default/_.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [*.less]
16 | indent_style = space
17 | indent_size = 2
18 |
19 | [Makefile]
20 | indent_style = tab
21 |
--------------------------------------------------------------------------------
/src/commands/clean.js:
--------------------------------------------------------------------------------
1 | const FS = require('fs-extra');
2 | const paths = require('../conf/path');
3 |
4 | module.exports = function (params) {
5 | if (params.build && FS.pathExistsSync(paths.appBuildDist)) {
6 | // 清空目录
7 | FS.emptyDirSync(paths.appBuildDist);
8 | }
9 | if (params.clean && FS.pathExistsSync(paths.catchDirPath)) {
10 | // 清空目录
11 | FS.emptyDirSync(paths.catchDirPath);
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/templates/default/faq/README.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | 这里可以问一些常见问题。
7 |
8 | 1. 是否支持 Markdown 中写代码?
9 |
10 | > 支持在 Markdown 中写HTML、CSS。
11 |
12 | 2. 文档是否支持目录层级?
13 |
14 | > 支持菜单无线层级,在文件夹中建立文件夹,相对应建立 `README.md`
15 |
16 | 3. 新增文件不能热加载,监听文件变化?
17 |
18 | > 新增一个 `Markdown` 文件是支持热加载的,需要如下步骤:
19 | > - 添加完成之后必须 `Markdown` 文件不能为空。
20 | > - 如果只是添加注释配置或者空格,一样视为空。
21 | > - 在其它已加载的 `Markdown` 文件中保存一下。
22 |
--------------------------------------------------------------------------------
/theme/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <%= htmlWebpackPlugin.options.title %>
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: jaywcjlove
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: npm/rdoc
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | custom: https://jaywcjlove.github.io/sponsor.html
10 |
--------------------------------------------------------------------------------
/templates/default/introduce/assets/react-logo.svg:
--------------------------------------------------------------------------------
1 |
2 | React Logo
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/templates/default/introduce/precautions.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | ⚠️ 在使用文档生成工具是,应注意一些事项,避免生成文档过程出现错误。
7 |
8 | 1. 文件与文件夹不能重名。
9 | 2. 顶部菜单通过 `sort` 排序是无效的。
10 | 5. HTML 中写 `
53 |
54 |
55 | ## HTML Demo 预览
56 |
57 | 需要在代码块前后加上一段 ` ` 和 `` 注释即可,代码如下:
58 |
59 | ```
60 |
61 | \```html
62 |
63 | Test Preview HTML Example.
64 |
65 |
68 | \```
69 |
70 | ```
71 |
72 | 下面是效果
73 |
74 |
75 | ```html
76 |
77 | Test Preview HTML Example.
78 |
79 |
82 | ```
83 |
84 |
85 | 目前只预览 `HTML`, 下面为 `LESS` 展示
86 |
87 |
88 | ```less
89 | .wapper {
90 | &::after {
91 | content: '';
92 | display: block;
93 | clear: both;
94 | }
95 | }
96 |
97 | .wapperContent {
98 | padding: 15px 0 0 0;
99 | max-width: 1200px;
100 | margin: 0px auto 0;
101 | }
102 | ```
103 |
104 |
--------------------------------------------------------------------------------
/theme/default/rdoc.logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/templates/default/introduce/guides/custom-menu.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | ## 主菜单定制
7 |
8 | 主菜单的定制,是通过 `建立` 目录来定制的,默认菜单名字是根据目录文件夹名字来显示,下面实例定义了主菜单有三个菜单,顺序分别为 `tutorial`、`doc`、`component`
9 |
10 | ```shell
11 | $ rdoc -d tutorial,doc
12 | ```
13 |
14 | 可以自定义菜单名字,通过在文件夹的跟目录建立 `README.md` 添加配置来设置菜单的名字。
15 |
16 | ```markdown
17 |
20 | ```
21 |
22 | ⚠️ 通过配置菜单对应根目录下的 `README.md` 来改变 `菜单顺序` 和 `是否显示`,[配置参考](#/introduce/api/markdown-config)。
23 |
24 | > sort 菜单顺序
25 | > visible 菜单是否显示 `true` 不显示
26 |
27 | ## Github跳转
28 |
29 | 新建一个目录 `github`,命令配置 `rdoc -d tutorial,doc,github` 将在主菜单上显示,在 `github` 目录下新建 `READEME.md` 文件,添加 Markdown 配置如下:
30 |
31 | > ⚠️ 注意: github 配置项,会增加 `github` 图标
32 | > 如果不想显示`图标`,就将 `github` 指定 `url` 配置。
33 |
34 | ```markdown
35 |
40 | ```
41 |
42 | ## 子菜单定制
43 |
44 | 在某个菜单下面定制二级菜单,默认情况,只需要在该目录创建多个 `.md` 文件,如下目录结构,有四个子菜单`api`、`getting-started`、`guides`、`precautions`。
45 |
46 | > ⚠️ 注意: 文件夹不能跟文件重名
47 |
48 | ```shell
49 | └── introduce
50 | ├── README.md
51 | ├── api
52 | │ ├── README.md
53 | │ └── menu-config.md
54 | ├── getting-started
55 | │ ├── README.md
56 | │ └── site-preparation.md
57 | ├── guides
58 | │ ├── README.md
59 | │ └── menu-sort.md
60 | └── precautions.md
61 | ```
62 |
63 | ## 子菜单菜层级
64 |
65 | 以相同的方式在该目录下面创建目录,并且创建 `.md` 文件,再添加相应的配置即可,如下目录结构,二级菜单将有三层。
66 |
67 | ```shell
68 | └── introduce
69 | ├── README.md
70 | ├── api
71 | │ ├── README.md
72 | │ ├── getting-started
73 | │ │ ├── README.md
74 | │ │ └── site-preparation.md
75 | │ └── menu-config.md
76 | └── precautions.md
77 | ```
78 |
79 | ## 菜单分类
80 |
81 | 子菜单分类是根据目录结构来分类的,假设你新建如下目录结构,配置的命令指向目录 `introduce`,那么你根目录下面的 `README.md` 里面可以配置一级导航的信息内容,二级目录文件夹分别为导航菜单的分类名称。
82 |
83 | 在 `introduce` 目录下面的,每个目录下,面再新建 `README.md` 来配置分类的各种信息,如此循环下去,可以新建一个树形菜单。
84 |
85 | ```shell
86 | └── introduce
87 | ├── README.md
88 | ├── api
89 | │ ├── README.md
90 | │ └── menu-config.md
91 | ├── getting-started
92 | │ ├── README.md
93 | │ └── site-preparation.md
94 | ├── guides
95 | │ ├── README.md
96 | │ └── menu-sort.md
97 | └── precautions.md
98 | ```
99 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | const eslintrc = {
2 | "parser": "babel-eslint",
3 | "extends": "airbnb",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | "es6": true,
8 | "mocha": true,
9 | "jest": true,
10 | "jasmine": true
11 | },
12 | "plugins": [
13 | "react",
14 | "import"
15 | ],
16 | "parserOptions": {
17 | parser: 'babel-eslint',
18 | },
19 | "rules": {
20 | "linebreak-style": 0,
21 | "func-names": 0,
22 | "sort-imports": 0,
23 | "arrow-body-style": 0,
24 | "prefer-destructuring": 0,
25 | "max-len": 0,
26 | "consistent-return": 0,
27 | "comma-dangle": [
28 | "error",
29 | "always-multiline"
30 | ],
31 | "function-paren-newline": 0,
32 | "class-methods-use-this": 0,
33 | "react/sort-comp": 0,
34 | "react/prop-types": 0,
35 | "react/jsx-first-prop-new-line": 0,
36 | "react/require-extension": 0,
37 | "react/jsx-filename-extension": [
38 | 1,
39 | {
40 | "extensions": [
41 | ".js",
42 | ".jsx"
43 | ]
44 | }
45 | ],
46 | "import/extensions": 0,
47 | "import/no-unresolved": 0,
48 | "import/no-extraneous-dependencies": 0,
49 | "import/prefer-default-export": 0,
50 | "jsx-a11y/no-static-element-interactions": 0,
51 | "jsx-a11y/anchor-has-content": 0,
52 | "jsx-a11y/click-events-have-key-events": 0,
53 | "jsx-a11y/anchor-is-valid": 0,
54 | "jsx-a11y/label-has-for": 0,
55 | "jsx-a11y/no-noninteractive-element-interactions": 0,
56 | "jsx-a11y/mouse-events-have-key-events": 0,
57 | "react/no-danger": 0,
58 | "react/jsx-no-bind": 0,
59 | "react/forbid-prop-types": 0,
60 | "react/require-default-props": 0,
61 | "react/no-did-mount-set-state": 0,
62 | "react/no-array-index-key": 0,
63 | "react/no-find-dom-node": 0,
64 | "react/no-unused-state": 0,
65 | "react/no-unused-prop-types": 0,
66 | "react/default-props-match-prop-types": 0,
67 | "react/jsx-curly-spacing": 0,
68 | "react/no-render-return-value": 0,
69 | "object-curly-newline": 0,
70 | "no-param-reassign": 0,
71 | "no-return-assign": 0,
72 | "no-redeclare": 0,
73 | "no-restricted-globals": 0,
74 | "no-restricted-syntax": 0,
75 | "no-underscore-dangle": 0,
76 | "no-unused-expressions": 0
77 | }
78 | }
79 |
80 | if (process.env.NODE_ENV === 'development') {
81 | Object.assign(eslintrc.rules,
82 | {
83 | 'no-console': 0,
84 | 'no-unused-vars': 0,
85 | });
86 | }
87 |
88 | module.exports = eslintrc
89 |
--------------------------------------------------------------------------------
/.bin/rdoc.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const FS = require('fs-extra');
3 | const PATH = require('path');
4 | const program = require('commander');
5 | const color = require('colors-cli/toxic');
6 | const initProject = require('../src/commands/initProject');
7 | const clean = require('../src/commands/clean');
8 | const initCatch = require('../src/utils/initCatch');
9 | const Servers = require('../src/server');
10 | const Build = require('../src/build');
11 | const Publish = require('../src/publish');
12 | const paths = require('../src/conf/path');
13 | const pkg = require('../package.json')
14 |
15 | program
16 | .version(pkg.version, '-v, --version')
17 | .description('Fast static site generator for React.')
18 | .option('-i, init [path]', 'Create an empty website or reinitialize an existing one.')
19 | .option('-d, --doc ', 'Other documents generated.')
20 | .option('-o, --output ', 'Writes the compiled file to the disk directory.', '.rdoc-dist')
21 | .option('-p, --port [number]', 'The port.', 5858)
22 | .option('--host [host]', 'The host.', '0.0.0.0')
23 | .option('-b, --branch ', 'Name of the branch you are pushing to.', 'gh-pages')
24 | .option('--publish [url]', 'Other documents generated.')
25 | .option('--build', 'Creating an optimized production build.')
26 | .option('--clean', 'Delete the .cache folder.')
27 | .on('--help', function () {
28 | console.log('\n Examples:');
29 | console.log();
30 | console.log(' $ rdoc init');
31 | console.log(' $ rdoc init doc-example');
32 | console.log(' $ rdoc -d doc/mm');
33 | console.log(' $ rdoc -d tutorial,doc');
34 | console.log(' $ rdoc -d tutorial,doc --clean --build');
35 | console.log(' $ rdoc -p 2323 -d doc --clean');
36 | console.log(' $ rdoc -h 0.0.0.0 -d doc --clean');
37 | console.log(' $ rdoc --publish https://.git --branch master');
38 | console.log();
39 | })
40 | .parse(process.argv);
41 | // rdoc 工具根目录
42 | // program.rdocPath = PATH.join(__dirname, '../');
43 | // 所有 Markdown 目录
44 | program.markdownPaths = [];
45 | // 网站根目录
46 | program.projectPath = process.cwd();
47 | // 编译输出目录
48 | program.output = PATH.join(program.projectPath, program.output);
49 |
50 | // 网站根目录,指定的所有 Markdown 的目录
51 | if (program.doc) {
52 | program.doc.split(',').forEach((itemPath) => program.markdownPaths.push(PATH.join(program.projectPath, itemPath)));
53 | }
54 |
55 | if (program.clean) clean(program);
56 | if (program.init) return initProject(program);
57 |
58 | // 将生成的代码,push到指定仓库,已经分支。
59 | if (program.publish) {
60 | return Publish(program)
61 | }
62 |
63 | // 没有指定,文档目录
64 | if (program.markdownPaths.length === 0) return console.log(`Please specify the directory with the parameters "-d".`.red)
65 |
66 | let isExists = true;
67 | // 判断指定文件夹是否存
68 | program.markdownPaths.forEach((item) => {
69 | if (!FS.existsSync(item)) {
70 | console.log(`Error: Directory ${item.yellow} does not exist`.red)
71 | isExists = false;
72 | }
73 | });
74 |
75 | if (isExists) {
76 | FS.ensureDirSync(paths.catchDirPath);
77 | initCatch(program, () => {
78 | if (program.build) {
79 | Build(program);
80 | } else {
81 | Servers(program);
82 | }
83 | })
84 | }
85 |
--------------------------------------------------------------------------------
/theme/default/lib/markdown/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import classNames from 'classnames';
4 | import ReactMarkdown from 'react-markdown';
5 | import hljs from 'highlight.js';
6 | import styles from './style/index.less';
7 | import InlineCode from './InlineCode';
8 | import Link from './Link';
9 | import Loading from '../../component/Loading/';
10 |
11 | hljs.configure({
12 | tabReplace: ' ', // 2 spaces
13 | classPrefix: '', // don't append class prefix
14 | });
15 |
16 | const formatPath = path =>
17 | path.replace(/^(\/|\\)/, '')
18 | .replace(/\.md$/, '')
19 | .replace(/\\/g, '/')
20 | .split('/')
21 | .join('___');
22 |
23 | export default class Markdown extends React.Component {
24 | constructor(props) {
25 | super(props);
26 | this.state = {
27 | markdownStr: '',
28 | };
29 | }
30 | componentWillMount() {
31 | this.renderMarkdown();
32 | }
33 | renderMarkdown() {
34 | const { props: { type, relative } } = this.props;
35 | const relativeMd = relative;
36 | if (!relativeMd) return null;
37 | let filename = formatPath(relativeMd);
38 | if (type === 'directory') {
39 | filename = formatPath(relativeMd);
40 | }
41 | import(`__project_root__/.cache/md/${filename}.md`).then((data) => {
42 | this.setState({
43 | markdownStr: data.default || data,
44 | }, () => {
45 | let code = ReactDOM.findDOMNode(this);
46 | code = code.getElementsByTagName('code');
47 | for (let i = 0; i < code.length; i += 1) {
48 | if (code[i].parentNode && code[i].parentNode.tagName === 'PRE') {
49 | hljs.highlightBlock(code[i]);
50 | }
51 | }
52 | });
53 | });
54 | }
55 | render() {
56 | const { mdconf: { title, layout } } = this.props;
57 | const { markdownStr } = this.state;
58 | return (
59 |
60 | {title && layout !== 'IndexLayout' &&
{title} }
61 | {markdownStr ? (
62 | {
72 | if (node.type === 'html') {
73 | // if (//.test(node.value)) return false;
74 | // const scriptValue = node.value.match(/(.*?)<\/script>/ig);
75 | // node.value.replace(/(.*?)<\/script>/, (te) => {
76 | // console.log('te:', te);
77 | // });
78 | }
79 | // 判断 上一个节点是否为
80 | if (node.type === 'code' && parent.children && parent.children.length > 0 && parent.children[index - 1]) {
81 | const parentNode = parent.children[index - 1];
82 | if (parentNode.type === 'html' && //.test(parentNode.value)) {
83 | node.value = `__dome__${node.value}`;
84 | }
85 | }
86 | return node;
87 | }}
88 | />
89 | ) : (
90 |
91 | )}
92 |
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/web/Router.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { HashRouter, withRouter, Route, Switch } from 'react-router-dom';
3 | import lazyload from 'react-dynamic-loadable';
4 | import theme from 'rdoc-theme';
5 | import menuSource from './rdoc.tree.data.json';
6 |
7 | // 判断目录下是否存在 README.md
8 | // 存在返回路由属性,表示是一个路由
9 | function directoryIsRoute(arr, props = false) {
10 | if (!arr || arr.length === 0) return false;
11 | const index = arr.filter(item => item.name === 'README.md' && item.mdconf);
12 | if (index && index.length > 0) props = { ...index[0] };
13 | return props;
14 | }
15 | // 路由数据序列化
16 | function routeData(data, arrayRoute = [], routePath = '/', article) {
17 | data.forEach((item) => {
18 | const routeProps = directoryIsRoute(item.children);
19 | const routePropsCurrent = `${routePath}${item.name}`.replace(/.md$/, '');
20 | if (item.type === 'directory' && routeProps) {
21 | const { mdconf, ...otherItem } = routeProps;
22 | arrayRoute.push({
23 | path: routePropsCurrent,
24 | mdconf: mdconf || {},
25 | props: { ...otherItem },
26 | article: article || item.name,
27 | });
28 | } else {
29 | const { mdconf, ...otherItem } = item;
30 | arrayRoute.push({
31 | path: routePropsCurrent,
32 | mdconf: mdconf || { title: item.name },
33 | props: { ...otherItem },
34 | article: article || item.name,
35 | });
36 | }
37 | if (item.children && item.children.length > 0) {
38 | arrayRoute.concat(routeData(item.children, arrayRoute, `${routePropsCurrent}/`, article || item.name));
39 | }
40 | });
41 | return arrayRoute;
42 | }
43 |
44 |
45 | function menuSourceFormat(data, routePath, article) {
46 | const arr = [];
47 | data.forEach((item) => {
48 | const routePropsCurrent = `${routePath || ''}/${item.name}`.replace(/.md$/, '');
49 | if (item.type === 'directory') {
50 | const getDirReadmeProps = directoryIsRoute(item.children);
51 | if (item.children && item.children.length > 0 && getDirReadmeProps) {
52 | const { sort, title, mdconf, ...otherItem } = getDirReadmeProps;
53 | item.mdconf = mdconf || {};
54 | item.props = otherItem || { isEmpty: true };
55 | item.sort = mdconf.sort ? mdconf.sort : 0;
56 | item.children = menuSourceFormat(item.children, routePropsCurrent, article || item.name);
57 | } else {
58 | item.mdconf = { title: item.name };
59 | item.props = { isEmpty: true };
60 | item.sort = 0;
61 | item.children = [];
62 | }
63 | } else {
64 | item.title = item.mdconf && item.mdconf.title ? item.mdconf.title : item.name.replace(item.extension, '');
65 | item.sort = item.mdconf && item.mdconf.sort ? item.mdconf.sort : 0;
66 | if (!item.mdconf) {
67 | item.props = { isEmpty: true };
68 | }
69 | }
70 | item.routePath = routePropsCurrent;
71 | item.article = article || item.name;
72 | arr.push(item);
73 | });
74 | return arr;
75 | }
76 |
77 | const RoutersContainer = withRouter(({ ...props }) => {
78 | const passProps = {
79 | routeData: routeData(menuSource),
80 | menuSource: menuSourceFormat(menuSource),
81 | ...props,
82 | };
83 | return (
84 |
85 | theme(lazyload, { ...routeProps, ...passProps })} />
86 |
87 | );
88 | });
89 |
90 | export default function RouterRoot() {
91 | return (
92 |
93 |
94 |
95 | );
96 | }
97 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rdoc",
3 | "version": "1.12.0",
4 | "description": "Blazing-fast static site generator for React, Just write Markdown file.",
5 | "homepage": "https://react-doc.github.io",
6 | "bin": {
7 | "rdoc": ".bin/rdoc.js",
8 | "rdoc-cli": ".bin/rdoc.js"
9 | },
10 | "scripts": {
11 | "release": "release-it --src.tagName='v%s'",
12 | "deploy": "node .bin/rdoc.js --publish git@github.com:react-doc/react-doc.github.io.git --branch master",
13 | "start": "node .bin/rdoc.js -d templates/default/home,templates/default/introduce,templates/default/faq,templates/default/about,templates/default/github --clean",
14 | "build": "node .bin/rdoc.js -d templates/default/home,templates/default/introduce,templates/default/faq,templates/default/about,templates/default/github --clean --build"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/jaywcjlove/rdoc.git"
19 | },
20 | "keywords": [
21 | "rdoc",
22 | "react",
23 | "react-doc"
24 | ],
25 | "author": "Kenny Wang",
26 | "license": "MIT",
27 | "dependencies": {
28 | "@babel/cli": "7.2.3",
29 | "@babel/core": "7.3.4",
30 | "@babel/plugin-proposal-class-properties": "7.3.4",
31 | "@babel/plugin-syntax-dynamic-import": "7.2.0",
32 | "@babel/plugin-syntax-object-rest-spread": "7.2.0",
33 | "@babel/plugin-transform-async-to-generator": "7.3.4",
34 | "@babel/plugin-transform-runtime": "7.3.4",
35 | "@babel/polyfill": "7.2.5",
36 | "@babel/preset-env": "7.3.4",
37 | "@babel/preset-react": "7.0.0",
38 | "@babel/runtime": "7.3.4",
39 | "@nuxtjs/friendly-errors-webpack-plugin": "2.0.2",
40 | "babel-eslint": "10.0.1",
41 | "babel-loader": "8.0.5",
42 | "classnames": "2.2.6",
43 | "colors-cli": "1.0.13",
44 | "commander": "2.12.2",
45 | "copy-markdown-image-webpack-plugin": "2.0.0",
46 | "copy-template-dir": "1.3.0",
47 | "create-spare-webpack-plugin": "2.0.0",
48 | "css-loader": "0.28.7",
49 | "detect-port": "1.2.2",
50 | "directory-tree-md": "2.0.7",
51 | "eslint": "4.19.1",
52 | "eslint-config-airbnb": "16.1.0",
53 | "eslint-loader": "2.0.0",
54 | "eslint-plugin-import": "2.11.0",
55 | "eslint-plugin-jsx-a11y": "6.0.3",
56 | "eslint-plugin-react": "7.7.0",
57 | "file-loader": "1.1.11",
58 | "fs-extra": "5.0.0",
59 | "gh-pages": "1.2.0",
60 | "highlight.js": "9.12.0",
61 | "html-webpack-plugin": "3.2.0",
62 | "less": "3.0.2",
63 | "less-loader": "4.1.0",
64 | "loading-cli": "1.0.6",
65 | "local-ip-url": "1.0.1",
66 | "mini-css-extract-plugin": "0.4.0",
67 | "open-browsers": "1.1.1",
68 | "optimize-css-assets-webpack-plugin": "4.0.0",
69 | "postcss-flexbugs-fixes": "3.2.0",
70 | "postcss-loader": "2.0.9",
71 | "raw-content-replace-loader": "1.0.1",
72 | "raw-extend-loader": "1.0.5",
73 | "raw-tree-replace-loader": "1.1.0",
74 | "react": "16.8.4",
75 | "react-document-title": "2.0.3",
76 | "react-dom": "16.8.4",
77 | "react-dynamic-loadable": "1.1.2",
78 | "react-hot-loader": "4.1.1",
79 | "react-markdown": "3.3.0",
80 | "react-router-dom": "4.2.2",
81 | "rimraf": "2.6.2",
82 | "string-replace-loader": "2.1.1",
83 | "style-loader": "0.19.1",
84 | "uglifyjs-webpack-plugin": "2.1.1",
85 | "upath": "1.0.2",
86 | "url-replace-loader": "1.0.0",
87 | "webpack": "4.40.2",
88 | "webpack-dev-middleware": "3.7.1",
89 | "webpack-dev-server": "3.8.1",
90 | "webpack-hot-dev-clients": "1.0.4",
91 | "webpackbar": "4.0.0",
92 | "write": "1.0.3"
93 | },
94 | "devDependencies": {
95 | "release-it": "10.1.0"
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/conf/webpack.config.js:
--------------------------------------------------------------------------------
1 | const PATH = require('path');
2 | const webpack = require('webpack');
3 | const WebpackBar = require('webpackbar');
4 | const UPATH = require('upath');
5 | const paths = require('./path');
6 | const pkg = require('../../package.json');
7 |
8 | const define = { FOOTER: null };
9 | if (paths.rdocConf && paths.rdocConf.footer && typeof paths.rdocConf.footer === 'string') {
10 | define.FOOTER = JSON.stringify(paths.rdocConf.footer);
11 | }
12 |
13 | module.exports = {
14 | entry: {},
15 | output: {
16 | path: paths.appBuildDist,
17 | publicPath: paths.publicPath,
18 | filename: 'js/[name].[hash:8].js',
19 | chunkFilename: 'js/[name].[hash:8].js',
20 | },
21 | resolve: {
22 | alias: {
23 | 'rdoc-theme': UPATH.normalizeSafe(paths.appThemePath),
24 | },
25 | },
26 | module: {
27 | rules: [
28 | {
29 | test: /\.(js|jsx|mjs)$/,
30 | exclude: [/node_modules/, /\.(cache)/, /rdoc-theme-(.*)/],
31 | enforce: 'pre',
32 | use: [
33 | // TODO:禁用require.ensure也不是一种标准的语言特征。
34 | // 我们等待https://github.com/facebookincubator/create-react-app/issues/2176。
35 | // { parser: { requireEnsure: false } },
36 | {
37 | // 首先运行linter。
38 | // 在Babel处理js之前做这一点很重要。
39 | options: {
40 | eslintPath: require.resolve('eslint'),
41 | configFile: require.resolve('../../.eslintrc.js'),
42 | },
43 | loader: require.resolve('eslint-loader'),
44 | },
45 | ],
46 | },
47 | {
48 | // “oneOf”将遍历所有以下加载程序,直到一个符合要求。
49 | // 当没有加载器匹配时,它将返回到加载程序列表末尾的“file”加载器。
50 | oneOf: [
51 | {
52 | test: /\.(svg|png|bmp|jpg|jpeg|gif)$/,
53 | loader: require.resolve('url-replace-loader'),
54 | options: {
55 | limit: 10000,
56 | name: 'img/[name].[hash:8].[ext]',
57 | replace: [
58 | {
59 | test: /rdoc\.logo\.svg$/,
60 | path: paths.logoPath,
61 | },
62 | ],
63 | },
64 | },
65 | {
66 | test: /\.md$/,
67 | use: [
68 | {
69 | loader: require.resolve('raw-content-replace-loader'),
70 | options: {
71 | path: PATH.join(paths.catchDirPath, './md'), // 需要替换的目录
72 | replace: paths.projectPath, // 替换成目标目录
73 | sep: /___/g, // 文件名存储,文件夹+下划线间隔+文件名
74 | },
75 | },
76 | ],
77 | },
78 | // “file-loader”确保这些资源由WebpackDevServer服务。
79 | // 当您导入资源时,您将获得(虚拟)文件名。
80 | // 在生产中,它们将被复制到`build`文件夹。
81 | // 此加载程序不使用“test”,因此它将捕获所有模块
82 | {
83 | // 排除`js`文件以保持“css”加载器工作,因为它注入它的运行时,否则将通过“文件”加载器处理。
84 | // 还可以排除“html”和“json”扩展名,以便它们被webpacks内部加载器处理。
85 | exclude: [/\.js$/, /\.html$/, /\.json$/],
86 | loader: require.resolve('file-loader'),
87 | options: {
88 | name: 'static/[name].[hash:8].[ext]',
89 | },
90 | },
91 | ],
92 | },
93 | ],
94 | },
95 | plugins: [
96 | new WebpackBar({ name: pkg.name }),
97 | new webpack.DefinePlugin({
98 | VERSION: JSON.stringify(pkg.version),
99 | ...define,
100 | }),
101 | ],
102 | node: {
103 | dgram: 'empty',
104 | fs: 'empty',
105 | net: 'empty',
106 | tls: 'empty',
107 | child_process: 'empty',
108 | },
109 | };
110 |
--------------------------------------------------------------------------------
/theme/default/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch, Route } from 'react-router-dom';
3 | import DocumentTitle from 'react-document-title';
4 | import BasicLayout from './layout/BasicLayout';
5 | import IndexLayout from './layout/IndexLayout';
6 | import NoMatch from './component/NoMatch';
7 | import Loading from './component/Loading';
8 |
9 | import './index.less';
10 |
11 | // 获取首页路由参数
12 | // Markdown 配置 layout = 'IndexLayout'
13 | const getIndexProps = (menus = [], attr) => {
14 | menus.forEach((item) => {
15 | if (item && item.mdconf && item.mdconf.layout === 'IndexLayout') {
16 | attr = item;
17 | }
18 | if (!attr && item.children && item.children.length > 0) {
19 | attr = getIndexProps(item.children, attr);
20 | }
21 | });
22 | return attr;
23 | };
24 |
25 | export default function (Lazyload, props) {
26 | let indexRoute = null;
27 |
28 | const LoadableComponent = Lazyload({
29 | component: () => import('./routes/Pages'),
30 | LoadingComponent: Loading,
31 | });
32 |
33 | // 路由加载Component
34 | if (props.routeData && props.routeData.length > 0) {
35 | props.routeData.map((item) => {
36 | item.component = LoadableComponent;
37 | return item;
38 | });
39 | }
40 | // 首页路由
41 | // 获取自定义路由
42 | let indexProps = getIndexProps(props.menuSource) || {};
43 | if (indexProps) {
44 | props.routeData = props.routeData.filter(item => item.mdconf && item.mdconf.layout !== 'IndexLayout');
45 | } else {
46 | // 未定义首页,默认第一个路由当首页
47 | indexProps = props.routeData.find((item, index) => index === 0);
48 | if (indexProps) indexProps.mdconf.layout = 'IndexLayout';
49 | }
50 |
51 | const indexItem = {
52 | path: '/',
53 | mdconf: { ...indexProps.mdconf, layout: 'IndexLayout' },
54 | props: { ...indexProps.props },
55 | article: indexProps.article,
56 | };
57 |
58 | // 首页路由放置路由数组中生成路由
59 | props.routeData.unshift({
60 | ...indexItem,
61 | component: LoadableComponent,
62 | });
63 |
64 | // 获取首页路由
65 | indexRoute = props.routeData.filter(item => item.mdconf && item.mdconf.layout === 'IndexLayout');
66 |
67 | return (
68 |
69 | (
72 |
73 |
74 |
75 | )}
76 | />
77 | {
79 | const { location: { pathname } } = routeProps;
80 | routeProps.indexProps = indexItem;
81 | let curentRoute = props.routeData.filter(item => item.path === pathname);
82 | let title = [];
83 | if (curentRoute.length > 0) {
84 | curentRoute = curentRoute[0];
85 | if (curentRoute.mdconf && curentRoute.mdconf.title && curentRoute.mdconf.layout !== 'IndexLayout') {
86 | title.push(curentRoute.mdconf.title);
87 | }
88 | if (indexItem.mdconf && indexItem.mdconf.title) {
89 | title.push(indexItem.mdconf.title);
90 | }
91 | title = title.length > 1 ? title.join(' - ') : title.join('');
92 | } else {
93 | title = '404';
94 | }
95 | return (
96 |
97 | {pathname === '/' ?
98 | :
99 |
100 | }
101 |
102 | );
103 | }}
104 | />
105 |
106 | );
107 | }
108 |
--------------------------------------------------------------------------------
/templates/default/home/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 |
62 |
63 |
64 |
RDoc
65 |
RDoc 是一个文档生成工具,用于生成文档网站或简单的博客网站。 简单到你只需写 Markdown 文件就可以帮助你生成网站。 同时可以方便的集成到你的项目工程中。
66 |
快速开始
67 |
68 |
69 |
70 |
71 | 在开始之前,推荐先学习 Markdown 语法,并正确安装和配置了 [Node.js](https://nodejs.org) v8.0 或以上。
72 |
73 | 主要用于快速生成文档工具或简单的网站,只需要写Markdown文件既可。
74 |
75 | ```bash
76 | npm install rdoc -g # 安装工具
77 | # /usr/local/bin/rdoc -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
78 | # /usr/local/bin/rdoc-cli -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
79 |
80 | rdoc init my-project # 初始化项目
81 | # 也可以使用 rdoc-cli 命令,跟 rdoc 命令是一样的
82 | # 增加 用 rdoc-cli 命令,目的是解决 Mac 系统自带的 Ruby 命令 rdoc 冲突
83 |
84 | cd my-project && npm start # 进入工程,启动服务
85 | ```
86 |
87 | ### Command
88 |
89 | ```shell
90 | Usage: rdoc [options]
91 |
92 | Fast static site generator for React.
93 |
94 | Options:
95 |
96 | -i, init [path] Create an empty website or reinitialize an existing one.
97 | -d, --doc Other documents generated.
98 | -o, --output Writes the compiled file to the disk directory. (default: .rdoc-dist)
99 | -p, --port [number] The port. (default: 5858)
100 | --host [host] The host. (default: 0.0.0.0)
101 | -b, --branch Name of the branch you are pushing to. (default: gh-pages)
102 | --publish [url] Other documents generated.
103 | --build Creating an optimized production build.
104 | --clean Delete the .cache folder.
105 | -h, --help output usage information
106 |
107 | Examples:
108 |
109 | $ rdoc init
110 | $ rdoc init doc-example
111 | $ rdoc -d doc/mm
112 | $ rdoc -d tutorial,doc
113 | $ rdoc -d tutorial,doc --clean --build
114 | $ rdoc -p 2323 -d doc --clean
115 | $ rdoc --host 0.0.0.0 -d doc --clean
116 | $ rdoc --publish https://.git --branch master
117 | ```
118 |
--------------------------------------------------------------------------------
/src/conf/path.js:
--------------------------------------------------------------------------------
1 | const PATH = require('path');
2 | const FS = require('fs');
3 |
4 | // 确保在项目文件夹中的任何符号都解决了:
5 | const appDirectory = FS.realpathSync(process.cwd());
6 | const toolDirectory = FS.realpathSync(__dirname);
7 | // Markdown 所在目录
8 | const resolveApp = relativePath => PATH.resolve(appDirectory, relativePath);
9 | // rdoc 工具所在目录
10 | const resolveTool = relativePath => PATH.resolve(toolDirectory, relativePath);
11 |
12 | // 获取 rdoc 配置
13 | function getRdocConf() {
14 | const packagePath = resolveApp('./package.json');
15 | let conf = {};
16 | if (FS.existsSync(packagePath)) {
17 | const confPkg = require(packagePath); // eslint-disable-line
18 | conf = confPkg.rdoc;
19 | }
20 | const confPath = resolveApp('./.rdocrc.json');
21 | if (FS.existsSync(confPath)) {
22 | const confRc = require(confPath) // eslint-disable-line
23 | conf = confRc;
24 | }
25 | return conf;
26 | }
27 |
28 | function getConfigFilePath(fileName, type) {
29 | const conf = getRdocConf();
30 | // 这里是读取配置
31 | if (conf && conf[type]) {
32 | // 主题目录加载
33 | if (type === 'theme') {
34 | if (!conf[type]) conf[type] = fileName;
35 | const _path = PATH.resolve(appDirectory, 'theme', conf[type]);
36 | const _NodeModulesPath = PATH.resolve(appDirectory, 'node_modules', conf[type]);
37 | if (FS.existsSync(_path)) {
38 | return FS.realpathSync(_path);
39 | } else if (FS.existsSync(_NodeModulesPath)) {
40 | return FS.realpathSync(_NodeModulesPath);
41 | }
42 | return false;
43 | }
44 | if (/^(favicon|logo)$/.test(type)) {
45 | return PATH.resolve(appDirectory, conf[type]);
46 | }
47 | }
48 | const _filepath = PATH.resolve(appDirectory, fileName);
49 | if (FS.existsSync(_filepath)) {
50 | // 默认根目录下的 favicon|logo
51 | return _filepath;
52 | }
53 | return false;
54 | }
55 |
56 | // Get favicon path
57 | const faviconPath = () => {
58 | const _path = getConfigFilePath('./favicon.ico', 'favicon');
59 | if (_path) return _path;
60 | return resolveTool('../../theme/default/favicon.ico');
61 | };
62 |
63 | // Get logo path
64 | const logoPath = () => {
65 | const _path = getConfigFilePath('./logo.svg', 'logo');
66 | if (_path) return _path;
67 | return false;
68 | };
69 |
70 | // Get theme path
71 | const getThemePath = () => {
72 | const _path = getConfigFilePath('./default', 'theme');
73 | if (_path) return _path;
74 | return resolveTool('../../theme/default');
75 | };
76 |
77 | const modPath = resolveApp('node_modules');
78 | function getExcludeFoldersRegExp() {
79 | if (!FS.existsSync(modPath)) return [];
80 | let regxExc = FS.readdirSync(modPath);
81 | regxExc = regxExc.filter(item => !/rdoc(.*)/.test(item));
82 |
83 | regxExc = regxExc.map((item) => {
84 | let rgxPath = `node_modules${PATH.sep}${item}`;
85 | if (PATH.sep === '\\') {
86 | rgxPath = `node_modules\\${PATH.sep}${item}`;
87 | }
88 | return new RegExp(rgxPath);
89 | });
90 | return regxExc;
91 | }
92 |
93 | module.exports = {
94 | // Markdown 所在目录
95 | rdocConf: getRdocConf(),
96 | appThemePath: getThemePath(),
97 | appPackage: resolveApp('./package.json'),
98 | appNodeModules: resolveApp('node_modules'),
99 | appBuildDist: resolveApp('.rdoc-dist'),
100 | catchDirPath: resolveApp('.cache'),
101 | docTreePath: resolveApp('.cache/.reactdoc.tree.json'),
102 | watchFilePath: resolveApp('.cache/watch-dir.js'),
103 | projectPath: appDirectory,
104 | publicPath: '',
105 | logoPath: logoPath(),
106 | // rdoc 工具所在目录
107 | getExcludeFoldersRegExp: getExcludeFoldersRegExp(),
108 | rdocPackage: resolveTool('../../package.json'),
109 | defaultNodeModules: modPath,
110 | defaultTemplatePath: resolveTool('../../templates/default'),
111 | defaultFaviconPath: faviconPath(),
112 | defaultHTMLPath: resolveTool('../../theme/default/index.html'),
113 | appIndexJs: resolveTool('../web/index.js'),
114 | appDir: resolveTool('../web'),
115 | };
116 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | rdoc
8 | ---
9 |
10 | [](https://gitter.im/j-rdoc/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://github.com/jaywcjlove/rdoc/issues) [](https://github.com/jaywcjlove/rdoc/network) [](https://github.com/jaywcjlove/rdoc/stargazers) [](https://github.com/jaywcjlove/rdoc/releases) [](README.md)
11 |
12 | 基于React的快速静态网站生成器,你只需要写 Markdown 文档即可。访问 [react-doc.github.io](https://react-doc.github.io)网站获取更多信息。
13 |
14 | > 这个文档网站就是一个 [demo](https://react-doc.github.io) 实例。
15 |
16 |
17 |
18 |
19 |
20 | ## 开始
21 |
22 | **rdoc** 使用非常简单,只需将其它作为模块安装并运行即可创建您的网站。
23 |
24 | 让我们开始吧!
25 |
26 | ### 安装
27 |
28 | 安装 `rdoc` 到你系统的全局,您需要在本地开发计算机上使用 `Node >= 8`。 您可以使用 [n](https://github.com/tj/n#installation) 轻松切换不同项目之间的 Node 版本。
29 |
30 |
31 | ```bash
32 | npm install rdoc -g
33 |
34 | # /usr/local/bin/rdoc -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
35 | # /usr/local/bin/rdoc-cli -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
36 | ```
37 |
38 | 增加了 `rdoc-cli` 命令来解决 Mac 集成 `rdoc` 命令冲突。
39 |
40 | 1. 初始化项目
41 |
42 | ```bash
43 | rdoc init my-project # Init project
44 | # 或者
45 | rdoc-cli init my-project
46 | ```
47 |
48 | 2. 运行网站
49 |
50 | ```bash
51 | cd my-project && npm install # 进入目录安装依赖
52 | npm start # 启动服务。
53 | ```
54 |
55 | 3. 编译输出静态HTML资源。
56 |
57 | ```bash
58 | npm run build
59 | ```
60 |
61 | 4. 在 `package.json` 中配置部署 `URL`。
62 |
63 | ```js
64 | {
65 | "scripts": {
66 | "deploy": "rdoc --publish "
67 | ...
68 | },
69 | ...
70 | }
71 | ```
72 |
73 | 5. 部署到 Github `gh-pages` 分支。
74 |
75 | ```bash
76 | npm run deploy
77 | ```
78 |
79 | ### 命令帮助
80 |
81 | ```shell
82 | Usage: rdoc [options]
83 |
84 | Fast static site generator for React.
85 |
86 | Options:
87 |
88 | -i, init [path] 创建一个空的网站或重新初始化一个现有网站。
89 | -d, --doc 生成指定其他文档。
90 | -o, --output 将编译的文件写入磁盘目录。(默认:.rdoc-dist)
91 | -p, --port [number] 端口。(默认: 5858)
92 | --host [host] 主机. (默认: 0.0.0.0)
93 | -b, --branch <分支>您要推送的分支的名称。(默认:gh-pages)
94 | --publish [url] 将生成的代码,push到指定仓库,已经分支。
95 | --build 创建编译的生产版本。
96 | --clean 删除.cache文件夹。
97 | -h, --help 输出使用帮助文档。
98 |
99 | Examples:
100 |
101 | $ rdoc init
102 | $ rdoc init doc-example
103 | $ rdoc -d doc/mm
104 | $ rdoc -d tutorial,doc
105 | $ rdoc -d tutorial,doc --clean --build
106 | $ rdoc -p 2323 -d doc --clean
107 | $ rdoc --host 0.0.0.0 -d doc --clean
108 | $ rdoc --publish https://.git --branch master
109 | ```
110 | ### 开发
111 |
112 | 获取代码,进入目录,运行自动重载构建,:
113 |
114 | ```shell
115 | $ git clone https://github.com/jaywcjlove/rdoc.git
116 | $ cd rdoc # 进入目录
117 | $ npm install # or yarn install
118 | ```
119 |
120 | 要开发,请运行自重载构建:
121 |
122 | ```bash
123 | # 运行应用程序
124 | # 每次代码更改时,自动重新启动应用程序。
125 | # 在开发过程中很有用。
126 | $ npm run start
127 | ```
128 |
129 | 打开浏览器并访问 http://localhost:5858
130 |
131 | ### Folders
132 |
133 | ```bash
134 | .
135 | ├── README.md
136 | ├── .rdoc-dist
137 | ├── package.json
138 | ├── src
139 | │ ├── build.js
140 | │ ├── commands
141 | │ ├── conf
142 | │ ├── publish.js
143 | │ ├── server.js
144 | │ ├── utils
145 | │ └── web
146 | ├── templates
147 | │ └── default # 记录静态文件。
148 | └── theme
149 | └── default
150 | ```
151 |
152 | ### License
153 |
154 | The MIT License (MIT)
155 |
--------------------------------------------------------------------------------
/theme/default/lib/markdown/style/default.less:
--------------------------------------------------------------------------------
1 |
2 | code {
3 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
4 | word-wrap: normal;
5 | }
6 | code:not(.hljs){
7 | padding: 0.2em 0.4em;
8 | margin: 0;
9 | font-size: 85%;
10 | background-color: rgba(27, 31, 35, 0.07);
11 | border-radius: 3px;
12 | }
13 | code.hljs {
14 | padding: 16px;
15 | font-size: 95%;
16 | line-height: 1.5;
17 | display: block;
18 | text-shadow: 0 1px #fff;
19 | }
20 | pre {
21 | max-height: 35em;
22 | position: relative;
23 | overflow: auto;
24 | background-color: #F0F0F0;
25 | border-radius: 3px;
26 | }
27 | pre code {
28 | background: none;
29 | font-size: 1em;
30 | overflow-wrap: normal;
31 | white-space: inherit;
32 | }
33 | ul, ol {
34 | padding-left: 2em;
35 | }
36 | dl {
37 | padding: 0;
38 | dt {
39 | padding: 0;
40 | margin-top: 16px;
41 | font-size: 14px;
42 | font-style: italic;
43 | font-weight: 600;
44 | }
45 | }
46 | li + li {
47 | margin-top: 3px;
48 | }
49 | a {
50 | color: #0366d6;
51 | }
52 | p {
53 | margin-bottom: 16px;
54 | }
55 | blockquote {
56 | margin: 0;
57 | padding: 0 1em;
58 | margin: 16px 0 16px 0;
59 | color: #6a737d;
60 | border-left: 0.25em solid #dfe2e5;
61 | & >:first-child {
62 | margin-top: 0;
63 | }
64 | & >:last-child {
65 | margin-bottom: 0;
66 | }
67 | }
68 | hr {
69 | height: 0.25em;
70 | padding: 0;
71 | margin: 24px 0;
72 | background-color: #e1e4e8;
73 | border: 0;
74 | }
75 |
76 | h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code {
77 | font-size: inherit
78 | }
79 |
80 | h1 {
81 | padding-bottom: 0.3em;
82 | font-size: 2em;
83 | border-bottom: 1px solid #eaecef
84 | }
85 |
86 | h2 {
87 | padding-bottom: 0.3em;
88 | font-size: 1.5em;
89 | border-bottom: 1px solid #eaecef
90 | }
91 |
92 | h3 {
93 | font-size: 1.25em
94 | }
95 |
96 | h4 {
97 | font-size: 1em
98 | }
99 |
100 | h5 {
101 | font-size: 0.875em
102 | }
103 |
104 | h6 {
105 | font-size: 0.85em;
106 | color: #6a737d
107 | }
108 |
109 | table {
110 | border-collapse: collapse;
111 | border-spacing: 0;
112 | width: 100%;
113 | & + table {
114 | margin-top: 16px;
115 | }
116 | }
117 |
118 | table th {
119 | font-weight: 600;
120 | white-space: nowrap;
121 | color: #5c6b77;
122 | background: rgba(0,0,0,.02);
123 | }
124 |
125 | table th,table td {
126 | padding: 8px 13px;
127 | border: 1px solid #dfe2e5;
128 | }
129 |
130 | table tr {
131 | background-color: #fff;
132 | border-top: 1px solid #c6cbd1;
133 | }
134 |
135 | table tr:nth-child(2n) {
136 | background-color: #f6f8fa;
137 | }
138 |
139 | table img {
140 | background-color: transparent;
141 | }
142 |
143 | img {
144 | max-width: 100%;
145 | box-sizing: content-box;
146 | background-color: #fff;
147 | vertical-align: middle;
148 | }
149 |
150 | img[align=right] {
151 | padding-left: 20px;
152 | }
153 |
154 | img[align=left] {
155 | padding-right: 20px;
156 | }
157 |
158 | .comment,.quote{
159 | color:#998;
160 | }
161 | .keyword,.selector-tag,.subst{
162 | color:#333;font-weight:bold;
163 | }
164 | .number,.literal,.variable,.template-variable,.tag .attr{
165 | color:#008080;
166 | }
167 | .string,.doctag{
168 | color:#d14;
169 | }
170 | .title,.section,.selector-id{
171 | color:#900;font-weight:bold;
172 | }
173 | .subst{
174 | font-weight:normal;
175 | }
176 | .type,.class .title{
177 | color:#458;font-weight:bold;
178 | }
179 | .tag,.name,.attribute{
180 | color:#000098;
181 | font-weight:normal;
182 | }
183 | .regexp,.link{
184 | color:#009926;
185 | }
186 | .symbol,.bullet{
187 | color:#990073;
188 | }
189 | .built_in,.builtin-name{
190 | color:#0086b3;
191 | }
192 | .meta{
193 | color:#999;font-weight:bold;
194 | }
195 | .deletion{
196 | background:#fdd;
197 | }
198 | .addition{
199 | background:#dfd;
200 | }
201 | .emphasis{
202 | font-style:italic;
203 | }
204 | .strong{
205 | font-weight:bold;
206 | }
207 |
208 |
--------------------------------------------------------------------------------
/src/conf/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | const autoprefixer = require('autoprefixer');
2 | const webpack = require('webpack');
3 | const PATH = require('path');
4 | const UPATH = require('upath');
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const CreateSpareWebpackPlugin = require('create-spare-webpack-plugin');
7 | const FriendlyErrorsWebpackPlugin = require('@nuxtjs/friendly-errors-webpack-plugin');
8 | const config = require('./webpack.config');
9 | const paths = require('./path');
10 |
11 | module.exports = function (cmd) {
12 | config.mode = 'development';
13 | config.entry = [
14 | require.resolve('react-hot-loader/patch'),
15 | require.resolve('webpack-hot-dev-clients/webpackHotDevClient'),
16 | paths.appIndexJs,
17 | ];
18 | config.module.rules = config.module.rules.map((item) => {
19 | if (item.oneOf) {
20 | const loaders = [];
21 | loaders.push({
22 | // Process JS with Babel.
23 | test: /\.(js|jsx|mjs)$/,
24 | exclude: paths.getExcludeFoldersRegExp.concat(/\.(cache)/),
25 | use: [
26 | {
27 | loader: require.resolve('string-replace-loader'),
28 | options: {
29 | multiple: [
30 | { search: '__project_root__', replace: UPATH.normalizeSafe(paths.projectPath), flags: 'ig' },
31 | ],
32 | },
33 | },
34 | {
35 | loader: require.resolve('babel-loader'),
36 | options: require('../../.babelrc'), // eslint-disable-line
37 | },
38 | ],
39 | });
40 | // https://ilikekillnerds.com/2018/03/disable-webpack-4-native-json-loader/
41 | loaders.push({
42 | test: /rdoc\.tree\.data\.json$/,
43 | // 禁用Webpack 4本身的JSON加载程序
44 | type: 'javascript/auto',
45 | use: [
46 | {
47 | loader: require.resolve('raw-tree-replace-loader'),
48 | options: {
49 | include: /rdoc\.tree\.data\.json$/, // 检查包含的文件名字
50 | directoryTrees: { // 指定目录生成目录树,json
51 | dir: cmd.markdownPaths,
52 | mdconf: true,
53 | extensions: /\.md/,
54 | relativePath: true,
55 | },
56 | },
57 | },
58 | ],
59 | });
60 |
61 | loaders.push({
62 | test: /\.(css|less)$/,
63 | use: [
64 | require.resolve('style-loader'),
65 | {
66 | loader: require.resolve('css-loader'),
67 | options: {
68 | modules: true,
69 | localIdentName: '[name]-[hash:base64:5]',
70 | importLoaders: 1,
71 | },
72 | },
73 | {
74 | loader: require.resolve('postcss-loader'),
75 | options: {
76 | // Necessary for external CSS imports to work
77 | // https://github.com/facebookincubator/create-react-app/issues/2677
78 | ident: 'postcss',
79 | plugins: () => [
80 | require('postcss-flexbugs-fixes'), // eslint-disable-line
81 | autoprefixer({
82 | browsers: [
83 | '>1%',
84 | 'last 4 versions',
85 | 'Firefox ESR',
86 | 'not ie < 9', // React doesn't support IE8 anyway
87 | ],
88 | flexbox: 'no-2009',
89 | }),
90 | ],
91 | },
92 | },
93 | require.resolve('less-loader'),
94 | ],
95 | });
96 |
97 | item.oneOf = loaders.concat(item.oneOf);
98 | }
99 | return item;
100 | });
101 |
102 | config.plugins = config.plugins.concat([
103 | new webpack.HotModuleReplacementPlugin(),
104 | new HtmlWebpackPlugin({
105 | inject: true,
106 | favicon: paths.defaultFaviconPath,
107 | template: paths.defaultHTMLPath,
108 | title: paths.rdocConf && paths.rdocConf.title ? paths.rdocConf.title : 'Rdoc',
109 | }),
110 | // 将模块名称添加到工厂功能,以便它们显示在浏览器分析器中。
111 | // 当接收到热更新信号时,在浏览器console控制台打印更多可读性高的模块名称等信息
112 | new webpack.NamedModulesPlugin(),
113 | new CreateSpareWebpackPlugin({
114 | // 备用文件目录,比对是否存在,不存在生成,根据sep 目录规则生成
115 | path: PATH.join(paths.catchDirPath, './md'),
116 | sep: '___', // 检查目标目录文件,文件名存储,文件夹+下划线间隔+文件名
117 | directoryTrees: { // 索引目录
118 | dir: cmd.markdownPaths,
119 | mdconf: true,
120 | extensions: /\.md$/,
121 | },
122 | }),
123 | new FriendlyErrorsWebpackPlugin({
124 | clearConsole: true,
125 | }),
126 | ]);
127 | return config;
128 | };
129 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | rdoc
8 | ---
9 |
10 | [](https://gitter.im/j-rdoc/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://github.com/jaywcjlove/rdoc/issues) [](https://github.com/jaywcjlove/rdoc/network) [](https://github.com/jaywcjlove/rdoc/stargazers) [](https://github.com/jaywcjlove/rdoc/releases) [](README_zh.md)
11 |
12 | Blazing-fast static site generator for React, Just write Markdown file. Visit the [react-doc.github.io](https://react-doc.github.io) website for more information.
13 |
14 | > The documentation site is also a demo [example](https://react-doc.github.io).
15 |
16 |
17 |
18 |
19 |
20 | ## Getting Started
21 |
22 | It's really easy to get started with **rdoc**. Just install it as a module and run it to create your website.
23 |
24 | Let's get you started!
25 |
26 | ### Install
27 |
28 | Install `rdoc` globally on your system. You’ll need to have Node >= 8 on your local development machine. You can use [n](https://github.com/tj/n#installation) to easily switch Node versions between different projects.
29 |
30 | ```bash
31 | npm install rdoc -g
32 |
33 | # /usr/local/bin/rdoc -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
34 | # /usr/local/bin/rdoc-cli -> /usr/local/lib/node_modules/rdoc/.bin/rdoc.js
35 | ```
36 |
37 | Added `rdoc-cli` command to resolve Mac integration `rdoc` command conflicts.
38 |
39 | 1. Init Project
40 |
41 | ```bash
42 | rdoc init my-project # Init project
43 | # or
44 | rdoc-cli init my-project
45 | ```
46 |
47 | 2. Run website
48 |
49 | ```bash
50 | cd my-project && npm install # Install dependencies.
51 | npm start # Into the directory, start the service.
52 | ```
53 |
54 | 3. Compile output static HTML resources
55 |
56 | ```bash
57 | npm run build
58 | ```
59 |
60 | 4. Configure the deployment URL in `package.json`
61 |
62 | ```js
63 | {
64 | "scripts": {
65 | "deploy": "rdoc --publish "
66 | ...
67 | },
68 | ...
69 | }
70 | ```
71 |
72 | 5. Deploy to Github's `gh-pages` branch
73 |
74 | ```bash
75 | npm run deploy
76 | ```
77 |
78 | ### Command
79 |
80 | ```shell
81 | Usage: rdoc [options]
82 |
83 | Fast static site generator for React.
84 |
85 | Options:
86 |
87 | -i, init [path] Create an empty website or reinitialize an existing one.
88 | -d, --doc Other documents generated.
89 | -o, --output Writes the compiled file to the disk directory. (default: .rdoc-dist)
90 | -p, --port [number] The port. (default: 5858)
91 | --host [host] The host. (default: 0.0.0.0)
92 | -b, --branch Name of the branch you are pushing to. (default: gh-pages)
93 | --publish [url] Other documents generated.
94 | --build Creating an optimized production build.
95 | --clean Delete the .cache folder.
96 | -h, --help output usage information
97 |
98 | Examples:
99 |
100 | $ rdoc init
101 | $ rdoc init doc-example
102 | $ rdoc -d doc/mm
103 | $ rdoc -d tutorial,doc
104 | $ rdoc -d tutorial,doc --clean --build
105 | $ rdoc -p 2323 -d doc --clean
106 | $ rdoc --host 0.0.0.0 -d doc --clean
107 | $ rdoc --publish https://.git --branch master
108 | ```
109 | ### Development
110 |
111 | To develop, run the self-reloading build, Get the code:
112 |
113 | ```shell
114 | $ git clone https://github.com/jaywcjlove/rdoc.git
115 | $ cd rdoc # Into the directory
116 | $ npm install # or yarn install
117 | ```
118 |
119 | To develop, run the self-reloading build:
120 |
121 | ```bash
122 | # Run the app
123 | # Restart the app automatically every time code changes.
124 | # Useful during development.
125 | $ npm run start
126 | ```
127 |
128 | Open your browser and visit http://localhost:5858
129 |
130 | ### Folders
131 |
132 | ```bash
133 | .
134 | ├── README.md
135 | ├── .rdoc-dist
136 | ├── package.json
137 | ├── src
138 | │ ├── build.js
139 | │ ├── commands
140 | │ ├── conf
141 | │ ├── publish.js
142 | │ ├── server.js
143 | │ ├── utils
144 | │ └── web
145 | ├── templates
146 | │ └── default # document the static file.
147 | └── theme
148 | └── default
149 | ```
150 |
151 | ### License
152 |
153 | The MIT License (MIT)
154 |
--------------------------------------------------------------------------------
/theme/default/layout/BasicLayout.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import { Switch, Link, Route, Redirect } from 'react-router-dom';
3 | import classNames from 'classnames';
4 | import styles from './BasicLayout.less';
5 | import Header from '../component/Header';
6 | import Footer from '../component/Footer';
7 | import logo from '../rdoc.logo.svg';
8 |
9 | function getCurrentArticle(routeData, path) {
10 | let article = null;
11 | routeData.forEach((item) => {
12 | if (item.path === path) {
13 | article = item.article;
14 | }
15 | });
16 | return article;
17 | }
18 |
19 | export default class BasicLayout extends PureComponent {
20 | constructor(props) {
21 | super(props);
22 | this.state = {};
23 | }
24 | componentDidUpdate() {
25 | this.scrollToTop();
26 | }
27 | componentDidMount() {
28 | this.scrollToTop();
29 | }
30 | scrollToTop() {
31 | document.body.scrollTop = 0;
32 | document.documentElement.scrollTop = 0;
33 | window.scrollTo(0, 0);
34 | }
35 | renderSubMenuItem(menus) {
36 | const { location: { pathname } } = this.props;
37 | if (menus.length > 1) {
38 | menus = menus.sort((a, b) => {
39 | if (a.sort < b.sort) return -1;
40 | if (a.sort > b.sort) return 1;
41 | return 0;
42 | });
43 | }
44 | return (
45 |
46 | {
47 | menus.map((item, index) => {
48 | if (item.isEmpty) {
49 | return null;
50 | }
51 | if (item.children && item.children.length < 1) return null;
52 | if (item.props && item.props.visible === true) return null;
53 | if (/^README(.*)md$/.test(item.name)) return null;
54 | return (
55 |
56 |
57 | {item && item.props && (item.props.redirect || item.props.isEmpty) ?
{(item.mdconf && item.mdconf.title) || ''}
: (
58 |
59 | {item && item.mdconf.title ? item.mdconf.title : item.name}
60 |
61 | )}
62 |
63 | {item.children && item.children.length > 0 && this.renderSubMenuItem(item.children)}
64 |
65 | );
66 | })
67 | }
68 |
69 | );
70 | }
71 | renderSubMenu(menus) {
72 | const { location: { pathname }, routeData } = this.props;
73 | const article = getCurrentArticle(routeData, pathname);
74 | menus = menus.filter(item => item.article === article);
75 | if (menus.length < 1) return null;
76 | const menusObject = menus[0] && menus[0].children ? menus[0].children : [];
77 | return this.renderSubMenuItem(menusObject);
78 | }
79 | isCurentChildren() {
80 | const { location: { pathname }, menuSource, routeData } = this.props;
81 | const getRoute = routeData.filter(item => pathname === item.path);
82 | const article = getRoute.length > 0 ? getRoute[0].article : null;
83 | const childs = menuSource.filter(item => article === item.article && item.children && item.children.length > 1);
84 | return childs.length > 0;
85 | }
86 | render() {
87 | const { menuSource, routeData, indexProps } = this.props;
88 | const isChild = this.isCurentChildren();
89 | return (
90 |
91 |
92 |
93 | {isChild && (
94 |
{this.renderSubMenu(menuSource)}
95 | )}
96 |
101 |
102 | {routeData.map((item) => {
103 | // 重定向跳转
104 | if (item && item.mdconf && item.mdconf.redirect) {
105 | let redirectPath = `${item.path || ''}/${item.mdconf.redirect}`;
106 | redirectPath = redirectPath.replace(/^\/\//, '/');
107 | return (
108 | } />
109 | );
110 | }
111 | return (
112 | {
116 | const Comp = item.component;
117 | return ;
118 | }}
119 | />
120 | );
121 | })}
122 |
123 |
124 |
125 |
126 |
127 |
128 | );
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/conf/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | const autoprefixer = require('autoprefixer');
2 | const PATH = require('path');
3 | const UPATH = require('upath');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const CreateSpareWebpackPlugin = require('create-spare-webpack-plugin');
6 | const CopyMarkdownImageWebpackPlugin = require('copy-markdown-image-webpack-plugin');
7 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
8 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
9 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
10 | const config = require('./webpack.config');
11 | const paths = require('./path');
12 |
13 | module.exports = function (cmd) {
14 | config.mode = 'production';
15 | config.entry = [paths.appIndexJs];
16 | config.output.filename = 'js/[hash:8].js';
17 | config.output.chunkFilename = 'js/[name].[hash:8].js';
18 | config.module.rules = config.module.rules.map((item) => {
19 | if (item.oneOf) {
20 | const loaders = [];
21 | loaders.push({
22 | // Process JS with Babel.
23 | test: /\.(js|jsx|mjs)$/,
24 | exclude: paths.getExcludeFoldersRegExp.concat(/\.(cache)/),
25 | use: [
26 | {
27 | loader: require.resolve('string-replace-loader'),
28 | options: {
29 | multiple: [
30 | { search: '__project_root__', replace: UPATH.normalizeSafe(paths.projectPath), flags: 'ig' },
31 | ],
32 | },
33 | },
34 | {
35 | loader: require.resolve('babel-loader'),
36 | options: require('../../.babelrc'), // eslint-disable-line
37 | },
38 | ],
39 | });
40 | // https://ilikekillnerds.com/2018/03/disable-webpack-4-native-json-loader/
41 | loaders.push({
42 | test: /rdoc\.tree\.data\.json$/,
43 | // 禁用Webpack 4本身的JSON加载程序
44 | type: 'javascript/auto',
45 | use: [
46 | {
47 | loader: require.resolve('raw-tree-replace-loader'),
48 | options: {
49 | include: /rdoc\.tree\.data\.json$/, // 检查包含的文件名字
50 | directoryTrees: { // 指定目录生成目录树,json
51 | dir: cmd.markdownPaths,
52 | mdconf: true,
53 | extensions: /\.md/,
54 | relativePath: true,
55 | },
56 | },
57 | },
58 | ],
59 | });
60 |
61 | loaders.push({
62 | test: /\.(css|less)$/,
63 | use: [
64 | MiniCssExtractPlugin.loader,
65 | {
66 | loader: require.resolve('css-loader'),
67 | options: {
68 | modules: true,
69 | localIdentName: '[name]-[hash:base64:5]',
70 | importLoaders: 1,
71 | },
72 | },
73 | {
74 | loader: require.resolve('postcss-loader'),
75 | options: {
76 | // Necessary for external CSS imports to work
77 | // https://github.com/facebookincubator/create-react-app/issues/2677
78 | ident: 'postcss',
79 | plugins: () => [
80 | require('postcss-flexbugs-fixes'), // eslint-disable-line
81 | autoprefixer({
82 | browsers: [
83 | '>1%',
84 | 'last 4 versions',
85 | 'Firefox ESR',
86 | 'not ie < 9', // React doesn't support IE8 anyway
87 | ],
88 | flexbox: 'no-2009',
89 | }),
90 | ],
91 | },
92 | },
93 | require.resolve('less-loader'),
94 | ],
95 | });
96 |
97 | item.oneOf = loaders.concat(item.oneOf);
98 | }
99 | return item;
100 | });
101 | config.optimization = {
102 | runtimeChunk: true,
103 | minimizer: [
104 | new UglifyJsPlugin({
105 | cache: true,
106 | parallel: true,
107 | sourceMap: true, // set to true if you want JS source maps
108 | }),
109 | new OptimizeCSSAssetsPlugin({}),
110 | ],
111 | splitChunks: {
112 | minSize: 0,
113 | chunks: 'initial',
114 | cacheGroups: {
115 | commons: {
116 | chunks: 'initial',
117 | minChunks: 2,
118 | maxInitialRequests: 5, // The default limit is too small to showcase the effect
119 | minSize: 2000, // This is example is too small to create commons chunks
120 | },
121 | vendor: {
122 | test: /node_modules/,
123 | chunks: 'initial',
124 | name: 'vendor',
125 | priority: 10,
126 | enforce: true,
127 | },
128 | },
129 | },
130 | };
131 |
132 | config.plugins = config.plugins.concat([
133 | new HtmlWebpackPlugin({
134 | inject: true,
135 | favicon: paths.defaultFaviconPath,
136 | template: paths.defaultHTMLPath,
137 | title: paths.rdocConf && paths.rdocConf.title ? paths.rdocConf.title : 'Rdoc',
138 | minify: {
139 | removeAttributeQuotes: true,
140 | collapseWhitespace: true,
141 | html5: true,
142 | minifyCSS: true,
143 | removeComments: true,
144 | removeEmptyAttributes: true,
145 | },
146 | }),
147 | new CopyMarkdownImageWebpackPlugin({
148 | dir: cmd.markdownPaths,
149 | toDir: config.output.path,
150 | }),
151 | new CreateSpareWebpackPlugin({
152 | // 备用文件目录,比对是否存在,不存在生成,根据sep 目录规则生成
153 | path: PATH.join(paths.catchDirPath, './md'),
154 | sep: '___', // 检查目标目录文件,文件名存储,文件夹+下划线间隔+文件名
155 | directoryTrees: { // 索引目录
156 | dir: cmd.markdownPaths,
157 | mdconf: true,
158 | extensions: /\.md$/,
159 | },
160 | }),
161 | // new webpack.optimize.DedupePlugin(),
162 | new MiniCssExtractPlugin({
163 | // Options similar to the same options in webpackOptions.output
164 | // both options are optional
165 | filename: 'css/[contenthash].css',
166 | chunkFilename: 'css/[id].css',
167 | }),
168 | ]);
169 | return config;
170 | };
171 |
--------------------------------------------------------------------------------
/theme/default/component/Header/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import classNames from 'classnames';
3 | import { Link } from 'react-router-dom';
4 | import PropTypes from 'prop-types';
5 | import styles from './index.less';
6 |
7 | const SVGGithub = (
8 |
9 |
10 |
11 | );
12 |
13 | const isString = val => typeof val === 'string';
14 |
15 | export default class Header extends PureComponent {
16 | renderTopMenu(menuSource, pathname) {
17 | if (menuSource.length > 1) {
18 | menuSource = menuSource.sort((a, b) => {
19 | if (a.sort < b.sort) return -1;
20 | if (a.sort > b.sort) return 1;
21 | return 0;
22 | });
23 | }
24 | return menuSource.map((item, index) => {
25 | if (!item) return null;
26 | if (item.mdconf && item.mdconf.visible === true) return null;
27 |
28 | const url = item.mdconf && (item.mdconf.github || item.mdconf.url);
29 | if (url) {
30 | return (
31 |
32 | {item.mdconf.github && SVGGithub}{item.mdconf.title && {item.mdconf.title} }
33 |
34 | );
35 | }
36 | if (item.props && item.props.isEmpty === true && (item.mdconf && !item.mdconf.redirect)) return null;
37 |
38 | const regx = new RegExp(`^/${item.name}`, 'g');
39 | const isActive = regx.test(pathname);
40 | return (
41 |
42 | {item.mdconf.title || item.name}
43 |
44 | );
45 | });
46 | }
47 | render() {
48 | const { location: { pathname }, menuSource, className, children, logo } = this.props;
49 | const { mdconf } = this.props.indexProps || {};
50 | return (
51 |
52 |
53 |
{logo &&
}
{mdconf.title}
54 | {menuSource &&
{this.renderTopMenu(menuSource, pathname)}
}
55 | {children && children.map((item, index) => {
56 | if (isString(item)) return item;
57 | return React.cloneElement(item, { key: index });
58 | })}
59 |
60 |
61 | );
62 | }
63 | }
64 |
65 | Header.propTypes = {
66 | logo: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
67 | menuSource: PropTypes.array,
68 | };
69 |
70 | Header.defaultProps = {
71 | logo: null,
72 | menuSource: [],
73 | };
74 |
--------------------------------------------------------------------------------
/templates/default/introduce/api/theme-api.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | ## 全局变量
7 |
8 | 全局变量 `__project_root__` 通常用于模板中懒加载 `markdown` 文件,例如:
9 |
10 | > 生成的缓存序列化文件,将被存放到当前目录下的 `.cache/md` 目录中。
11 |
12 | ```js
13 | // 加载高亮库
14 | import hljs from 'highlight.js';
15 |
16 | // filename 处理很重要
17 | // Markdown文件被处理成 `doc___fed___react___component-and-props.md` 这样,
18 | // 路径以下划线间隔避免重复,所以 要获取路径得 通过 props.page.routeData 中获取 relative 路径来处理
19 | const filename = '';
20 | // 加载 Markdown 文件,
21 | import(`__project_root__/.cache/md/${filename}.md`).then((data) => {
22 | this.setState({
23 | markdown: data,
24 | }, () => {
25 | // 找到当前组件根节点,循环code,
26 | // 对code里面的代码进行高亮
27 | let code = ReactDOM.findDOMNode(this);
28 | code = code.getElementsByTagName('code');
29 | for (let i = 0; i < code.length; i += 1) {
30 | if (code[i].parentNode && code[i].parentNode.tagName === 'PRE') {
31 | hljs.highlightBlock(code[i]);
32 | }
33 | }
34 | });
35 | });
36 | ```
37 |
38 | ## Markdown 文件索引
39 |
40 | 那你需要建立一个 `替身` 文件 `rdoc.tree.data.json`,引用替身文件,就可以获取到目录索引内容,这个在编译的时候会自动返回文件索引的 `json`。
41 |
42 | > ⚠️ 替身文件名字,必须取名 `rdoc.tree.data.json`。
43 | > ⚠️ 这个文件是必须建立,引用,这样可以渲染菜单。
44 | > ⚠️ rdoc v1.3.0 以后版本不需要,如果你有同名文件会被替换成,Markdown 文件索引。
45 | > ⚠️ Markdown 文件索引,会在入口函数传入。
46 |
47 | ```js
48 | import menuSource from './rdoc.tree.data.json';
49 | ```
50 |
51 | ## 模板入口
52 |
53 | ```js
54 | import BaseLayout from './layout/BasicLayout';
55 | import Loading from './component/Loading';
56 |
57 | export default function (Lazyload, props) {
58 | if (props.routeData && props.routeData.length > 0) {
59 | props.routeData.map((item) => {
60 | item.component = Lazyload({
61 | component: () => import('./routes/Pages'),
62 | LoadingComponent: Loading,
63 | });
64 | return item;
65 | });
66 | }
67 | return ;
68 | }
69 | ```
70 |
71 | ## 两个入口参数
72 |
73 | `props` 提供路由索引,和 Markdown 文件索引信息。`Lazyload` 为懒加载方法。
74 |
75 | ### Lazyload
76 |
77 | 文档工具包 [react-dynamic-loadable](https://github.com/jaywcjlove/react-dynamic-loadable) 提供的,懒加载方法,下面方法为路由添加 `component` 并传入相应参数。
78 |
79 | ```js
80 | props.routeData.map((item) => {
81 | item.component = Lazyload({
82 | component: () => import('./routes/Pages'),
83 | LoadingComponent: Loading,
84 | });
85 | return item;
86 | });
87 | ```
88 |
89 | ### props
90 |
91 | ```js
92 | {
93 | history: {length: 50, action: "POP", location: {…}, createHref: ƒ, push: ƒ, …},
94 | location: {pathname: "/introduce/api/theme-api", search: "", hash: "", state: undefined},
95 | match: {path: "/", url: "/", params: {…}, isExact: false},
96 | menuSource: [{…}, {…}, {…}, {…}, {…}],
97 | routeData: [{…}, {…}, {…}, {…}, {…}],
98 | staticContext: undefined
99 | }
100 | ```
101 |
102 | #### props.menuSource
103 |
104 | > path 你 Markdown 的全路径
105 | > name 文件夹或者文件的名称
106 | > type 当前节点是一个文件夹还是一个文件`file|directory`
107 | > extension 类型为`file`的后缀
108 |
109 | > **根据文件索引出来的参数**
110 | >
111 | > relative 相对于你指定的路径
112 | > routePath 路由路径
113 | > isEmpty
114 | > size 文件大小
115 | > mdconf 是你在 Markdown中定义的参数
116 |
117 | > **Markdown手动配置的参数**
118 | >
119 | > sort 排序
120 | > title 标题
121 | > visible 是否隐藏菜单
122 |
123 | ```json
124 | [
125 | {
126 | "path": "/Users/mac/doc-example/index",
127 | "name": "index",
128 | "children": [
129 | {
130 | "path": "/Users/mac/doc-example/index/README.md",
131 | "name": "README.md",
132 | "relative": "/index/README.md",
133 | "mdconf": {
134 | "title": "首页",
135 | "layout": "IndexLayout",
136 | "visible": "true",
137 | "logo": "/introduce/assets/react-logo.svg"
138 | },
139 | "isEmpty": false,
140 | "size": 1821,
141 | "extension": ".md",
142 | "type": "file",
143 | "title": "首页",
144 | "sort": 0,
145 | "routePath": "/index/README",
146 | "article": "index"
147 | }
148 | ],
149 | "size": 1821,
150 | "type": "directory",
151 | "mdconf": {
152 | "title": "首页",
153 | "layout": "IndexLayout",
154 | "visible": "true",
155 | "logo": "/introduce/assets/react-logo.svg"
156 | },
157 | "props": {
158 | "path": "/Users/mac/doc-example/index/README.md",
159 | "name": "README.md",
160 | "relative": "/index/README.md",
161 | "isEmpty": false,
162 | "size": 1821,
163 | "extension": ".md",
164 | "type": "file"
165 | },
166 | "sort": 0,
167 | "routePath": "/index",
168 | "article": "index"
169 | }
170 | ]
171 | ```
172 |
173 | #### props.routeData
174 |
175 | > props 文档配置及其信息
176 | > path 路由信息,配合 `React Router` 使用
177 | > relative 路径,从项目的,根目录开始,主要用于读取 Markdown 组合 Markdown 的文件名字
178 |
179 | ```json
180 | [
181 | {
182 | "path": "/introduce/api",
183 | "mdconf": {
184 | "title": "API",
185 | "sort": "3"
186 | },
187 | "props": {
188 | "path": "/Users/mac/doc-example/introduce/api/README.md",
189 | "name": "README.md",
190 | "relative": "/introduce/api/README.md",
191 | "isEmpty": true,
192 | "size": 27,
193 | "extension": ".md",
194 | "type": "file"
195 | },
196 | "article": "introduce",
197 | "title": ""
198 | },{
199 | "path": "/index",
200 | "mdconf": {
201 | "title": "首页",
202 | "layout": "IndexLayout",
203 | "visible": "true",
204 | "logo": "/introduce/assets/react-logo.svg"
205 | },
206 | "props": {
207 | "path": "/Users/mac/doc-example/index/README.md",
208 | "name": "README.md",
209 | "relative": "/index/README.md",
210 | "isEmpty": false,
211 | "size": 1821,
212 | "extension": ".md",
213 | "type": "file"
214 | },
215 | "article": "index",
216 | "title": ""
217 | },
218 | ]
219 | ```
220 |
221 | ## BaseLayout
222 |
223 | 这个是定于的主框架模板,俗称通用布局,主要用于定制头部右边,不常变换的内容,你可以定义多个 `Layout`, 例如你定义 `Markdown` 参数,根据参数加载不用样式的通用布局。
224 |
225 |
226 | ## 默认依赖包
227 |
228 | 工具基础的前端包工具,制作主题需要安装依赖包,提供一个实例 [rdoc-theme-load-react](https://github.com/react-doc/rdoc-theme-load-react)。
229 |
230 | ```bash
231 | {
232 | "classnames": "2.2.5",
233 | "highlight.js": "9.12.0",
234 | "prop-types": "15.6.0",
235 | "react": "16.2.0",
236 | "react-dom": "16.2.0",
237 | "react-markdown": "3.1.3",
238 | "react-router-dom": "4.2.2",
239 | }
240 | ```
241 |
--------------------------------------------------------------------------------
/templates/default/introduce/guides/theme.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | 通过自定义主题来定义网站前端内容。下面定义主题的步骤:
7 |
8 | ## 创建主题
9 |
10 | ```bash
11 | mkdir rdoc-theme-load-react # 创建主题目录
12 | npm init -y # 生成配置文件 package.json
13 | ```
14 |
15 | ⚠️ 注意事项:主题必须以 `rdoc-theme-` 开头,否则会报错。
16 |
17 | 生成 `package.json` 内容:
18 |
19 | ```json
20 | {
21 | "name": "rdoc-theme-load-react",
22 | "version": "1.0.0",
23 | "description": "",
24 | "main": "index.js",
25 | "scripts": {
26 | "test": "echo \"Error: no test specified\" && exit 1"
27 | },
28 | "keywords": [],
29 | "author": "",
30 | "license": "MIT"
31 | }
32 | ```
33 |
34 | ## 添加主题文件
35 |
36 | ```bash
37 | ├── README.md # 说明文档
38 | ├── lib # 主题文件编译后的文件
39 | ├── package.json
40 | └── src # 没有编译的js文件
41 | ```
42 |
43 | 可以将默认主题拷贝到 `src` 目录中,基于[默认主题](https://github.com/jaywcjlove/rdoc/tree/master/theme/default)来改一个新的主题。
44 |
45 | ## 添加编译命令
46 |
47 | 主题文件建立好之后,通过 `babel` 来编译你的主题,将编译后的文件存储到 `lib` 目录中,添加编译命令,通过 `npm run build` 去编译你的代码。
48 |
49 | 安装依赖
50 |
51 | ```shell
52 | npm install --save-dev babel-cli babel-core babel-eslint babel-plugin-syntax-dynamic-import babel-plugin-transform-async-to-generator babel-plugin-transform-class-properties babel-plugin-transform-object-rest-spread babel-plugin-transform-runtime babel-preset-env babel-preset-react
53 | ```
54 |
55 |
56 | ```diff
57 | {
58 | "name": "rdoc-theme-load-react",
59 | "version": "1.0.0",
60 | "description": "",
61 | + "main": "lib/index.js",
62 | - "main": "index.js",
63 | "scripts": {
64 | + "build": "BABEL_ENV=production babel --ignore=src/**/__test__ --plugins transform-runtime src --out-dir lib --copy-files ",
65 | - "test": "echo \"Error: no test specified\" && exit 1"
66 | },
67 | "keywords": [],
68 | "author": "",
69 | + "devDependencies": {
70 | + "babel-cli": "^6.26.0",
71 | + "babel-core": "^6.26.3",
72 | + "babel-eslint": "^8.2.3",
73 | + "babel-plugin-syntax-dynamic-import": "^6.18.0",
74 | + "babel-plugin-transform-async-to-generator": "^6.24.1",
75 | + "babel-plugin-transform-class-properties": "^6.24.1",
76 | + "babel-plugin-transform-object-rest-spread": "^6.26.0",
77 | + "babel-plugin-transform-runtime": "^6.23.0",
78 | + "babel-preset-env": "^1.6.1"
79 | + },
80 | "license": "MIT"
81 | }
82 | ```
83 |
84 | 添加babel配置文件 `.babelrc`。
85 |
86 | ```json
87 | {
88 | "presets": [
89 | "env",
90 | "react"
91 | ],
92 | "plugins": [
93 | "transform-object-rest-spread",
94 | "syntax-dynamic-import",
95 | "transform-async-to-generator",
96 | "transform-class-properties",
97 | "transform-runtime"
98 | ]
99 | }
100 | ```
101 |
102 | 通过运行命令编译主题
103 |
104 | ```bash
105 | npm run build
106 | ```
107 |
108 | ## 添加实时编译命令
109 |
110 | 添加监听模式下开发你的主题,你不能写一句代码,运行一下 `npm run start` 去编译你的代码,要实时编译你的代码,所以你要添加一个实时编译参数。
111 |
112 | ```diff
113 | {
114 | "name": "rdoc-theme-load-react",
115 | "version": "1.0.0",
116 | "description": "",
117 | "main": "lib/index.js",
118 | "scripts": {
119 | "build": "BABEL_ENV=production babel --ignore=src/**/__test__ --plugins transform-runtime src --out-dir lib --copy-files ",
120 | + "dev": "BABEL_ENV=production babel -w --ignore=src/**/__test__ --plugins transform-runtime src --out-dir lib --copy-files ",
121 | + "start": "npm run dev"
122 | },
123 | "keywords": [],
124 | "author": "",
125 | "devDependencies": {
126 | "babel-cli": "^6.26.0",
127 | "babel-core": "^6.26.3",
128 | "babel-plugin-syntax-dynamic-import": "^6.18.0",
129 | "babel-plugin-transform-async-to-generator": "^6.24.1",
130 | "babel-plugin-transform-class-properties": "^6.24.1",
131 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
132 | "babel-plugin-transform-runtime": "^6.23.0",
133 | "babel-preset-env": "^1.6.1"
134 | },
135 | "license": "MIT"
136 | }
137 | ```
138 |
139 | 通过运行命令,实时编译主题
140 |
141 | ```bash
142 | npm run start
143 | ```
144 |
145 | ## 添加代码检测
146 |
147 | 安装代码检测依赖工具
148 |
149 | ```bash
150 | npm install --save-dev eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-watch
151 | ```
152 |
153 | 添加对应的代码检测命令
154 |
155 | ```diff
156 | {
157 | "name": "rdoc-theme-load-react",
158 | "version": "1.0.0",
159 | "description": "",
160 | "main": "lib/index.js",
161 | "scripts": {
162 | "build": "BABEL_ENV=production babel --ignore=src/**/__test__ --plugins transform-runtime src --out-dir lib --copy-files ",
163 | "dev": "BABEL_ENV=production babel -w --ignore=src/**/__test__ --plugins transform-runtime src --out-dir lib --copy-files ",
164 | - "start": "npm run dev"
165 | + "start": "npm run dev & npm run lint:watch",
166 | + "lint": "NODE_ENV=production eslint src",
167 | + "lint:watch": "esw -w src",
168 | + "test": "npm run lint"
169 | },
170 | "keywords": [],
171 | "author": "",
172 | "devDependencies": {
173 | "babel-cli": "^6.26.0",
174 | "babel-core": "^6.26.3",
175 | "babel-plugin-syntax-dynamic-import": "^6.18.0",
176 | "babel-plugin-transform-async-to-generator": "^6.24.1",
177 | "babel-plugin-transform-class-properties": "^6.24.1",
178 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
179 | "babel-plugin-transform-runtime": "^6.23.0",
180 | "babel-preset-env": "^1.6.1",
181 | + "eslint": "^4.19.1",
182 | + "eslint-config-airbnb": "^16.1.0",
183 | + "eslint-plugin-import": "^2.11.0",
184 | + "eslint-plugin-jsx-a11y": "^6.0.3",
185 | + "eslint-plugin-react": "^7.7.0",
186 | + "eslint-watch": "^3.1.4"
187 | },
188 | "license": "MIT"
189 | }
190 | ```
191 |
192 | 添加代码检查 ESLint 的配置文件 `.babelrc`。
193 |
194 | ```json
195 | {
196 | "parser": "babel-eslint",
197 | "extends": "airbnb",
198 | "env": {
199 | "browser": true,
200 | "node": true,
201 | "es6": true,
202 | "mocha": true,
203 | "jest": true,
204 | "jasmine": true
205 | },
206 | "plugins": [
207 | "react",
208 | "import"
209 | ],
210 | "parserOptions": {
211 | "parser": "babel-eslint"
212 | },
213 | "rules": {
214 | "linebreak-style": 0,
215 | "func-names": 0,
216 | "sort-imports": 0,
217 | "arrow-body-style": 0,
218 | "prefer-destructuring": 0,
219 | "max-len": 0,
220 | "consistent-return": 0,
221 | "comma-dangle": [ "error", "always-multiline" ],
222 | "function-paren-newline": 0,
223 | "class-methods-use-this": 0,
224 | "react/sort-comp": 0,
225 | "react/prop-types": 0,
226 | "react/jsx-first-prop-new-line": 0,
227 | "react/require-extension": 0,
228 | "react/jsx-filename-extension": [ 1, { "extensions": [ ".js", ".jsx" ] } ],
229 | "import/extensions": 0,
230 | "import/no-unresolved": 0,
231 | "import/no-extraneous-dependencies": 0,
232 | "import/prefer-default-export": 0,
233 | "jsx-a11y/no-static-element-interactions": 0,
234 | "jsx-a11y/anchor-has-content": 0,
235 | "jsx-a11y/click-events-have-key-events": 0,
236 | "jsx-a11y/anchor-is-valid": 0,
237 | "jsx-a11y/label-has-for": 0,
238 | "jsx-a11y/no-noninteractive-element-interactions": 0,
239 | "jsx-a11y/mouse-events-have-key-events": 0,
240 | "react/no-danger": 0,
241 | "react/jsx-no-bind": 0,
242 | "react/forbid-prop-types": 0,
243 | "react/require-default-props": 0,
244 | "react/no-did-mount-set-state": 0,
245 | "react/no-array-index-key": 0,
246 | "react/no-find-dom-node": 0,
247 | "react/no-unused-state": 0,
248 | "react/no-unused-prop-types": 0,
249 | "react/default-props-match-prop-types": 0,
250 | "react/jsx-curly-spacing": 0,
251 | "react/no-render-return-value": 0,
252 | "object-curly-newline": 0,
253 | "no-param-reassign": 0,
254 | "no-return-assign": 0,
255 | "no-redeclare": 0,
256 | "no-restricted-globals": 0,
257 | "no-restricted-syntax": 0,
258 | "no-underscore-dangle": 0,
259 | "no-unused-expressions": 0
260 | }
261 | }
262 | ```
263 |
264 | ## 开发模式调试主题
265 |
266 | 在你通过上面步骤建立的主题目录下运行命令
267 |
268 | ```bash
269 | # 进入目录
270 | cd rdoc-theme-load-react
271 | # 将 rdoc-theme-load-react 安装到全局目录中
272 | npm link
273 | # /lib/node_modules/rdoc-theme-load-react -> ~/rdoc/rdoc-theme-load-react
274 | ```
275 |
276 | 生成一个 `rdoc` 文档工程
277 |
278 | ```bash
279 | npm install -g rdoc # 全局安装 rdoc 工具
280 | rdoc init dochelp # 生成一个叫 dochelp 的工程
281 | ```
282 |
283 | 安装你自定义的主题 `rdoc-theme-load-react`
284 |
285 | ```bash
286 | npm link rdoc-theme-load-react
287 | ```
288 |
289 | 在 `dochelp` 工程的 `package.json` 中添加配置
290 |
291 | ```diff
292 | {
293 | "name": "dochelp",
294 | "version": "1.0.0",
295 | "description": "Describe rdoc-theme-load-react here",
296 | "private": true,
297 | "scripts": {
298 | "deploy": "rdoc --publish ",
299 | "build": "rdoc -d home,introduce,faq,about,github --clean --build",
300 | "start": "rdoc -d home,introduce,faq,about,github --clean"
301 | },
302 | "keywords": [],
303 | + "rdoc": {
304 | + "theme": "rdoc-theme-load-react"
305 | + },
306 | "dependencies": {
307 | "rdoc": "1.4.x"
308 | },
309 | "author": "",
310 | "license": "MIT"
311 | }
312 | ```
313 |
314 | ## 主题发布到npm
315 |
316 | 如果主题发布到外网,你可以将主题作为一个依赖来使用主题,首先你需要注册一个账号 http://npmjs.org/ ,在命令行中登录你的账号,或者直接在命令行通过 `npm` 命令注册账号。
317 |
318 | ```bash
319 | # 登录 npm 账号
320 | npm login
321 | # 进入主题的根目录
322 | cd rdoc-theme-load-react
323 | # 上传你的主题包,上传记得编译好你的主题哦
324 | npm publish
325 | ```
326 |
--------------------------------------------------------------------------------