Pages入口:
僅作為了解學習
官方例子:
第一頁:
vuepress有自己的目錄格式
第二頁:
gitbook有自己的格式
GitBook 3.2.3入門

GitBook目錄結構
基本結構如下:
├── book.json
├── README.md
├── SUMMARY.md
├── chapter-1/
| ├── README.md
| └── something.md
└── chapter-2/
├── README.md
└── something.md
book.json:全局配置數據 (可選)
README.md:介紹電子書(必須)
SUMMARY.md:目錄 (可選)
GLOSSARY.md:詞匯、術語列表(可選)
- SUMMARY.md格式
基本格式為:* [描述](文件路徑或者http超鏈接)。文件路徑是相對於SUMMARY.md所在的目錄的。
支持多級目錄,每級目錄多縮進4個空格。例如:
* [介紹](README.md)
* [概述](index.md)
* [接口](api.md)
* [注意事項](note.md)
直接簡單粗暴的使用上:(項目用的是下面這種方式)


book.json文件

{ "title": "項目技術特點", "author": "王雲鵬", "language": "zh-hans", "ignores": [ "node_modules", "**/resources" ] }
.gitlab-ci.yml文件,直接創建,需要SUMMARY.md

default: tags: - docker - company # requiring the environment of NodeJS 10 image: node:10 # add 'node_modules' to cache for speeding up builds cache: paths: - node_modules/ # Node modules and dependencies before_script: - npm install gitbook-cli -g # install gitbook - gitbook fetch 3.2.3 # fetch final stable version - gitbook install # add any requested plugins in book.json # the 'pages' job will deploy and build your site to the 'public' path pages: stage: deploy script: # - node generateSummary.js - gitbook build . public # build to public path artifacts: paths: - public expire_in: 1 week only: - master # this job will affect only the 'master' branch
.gitlab-ci.yml文件,用自己創建的鏡像實現,不需要寫SUMMAY.md

default: tags: - docker - company # requiring the environment of NodeJS 10 image: nexus3:8089/wangyp/gitbook:1.0.1 test: stage: test script: - gitbook build . public # build to public path only: - branches # this job will affect every branch except 'master' except: - master # the 'pages' job will deploy and build your site to the 'public' path pages: stage: deploy script: - book sm - gitbook build . public # build to public path artifacts: paths: - public expire_in: 1 day only: - master # this job will affect only the 'master' branch
generateSummary.js文件

const IGNORE_FILES = [ /* gitignore style */ 'SUMMARY.md', ]; const DEFAULT_README_TITLE = 'Introduction'; //////////////////////////////////////////////// const fs = require('fs'); const path = require('path'); const isNotIgnored = (() => { const ignoredPatterns = fs.readFileSync('./.gitignore', 'utf8') .split('\n') .map(f => f.trim()) .filter(f => f.length > 0) .filter(f => f[0] !== '#') .concat(IGNORE_FILES) .map(f => new RegExp(f.replace(/\*/g, '(.*?)'))); return (f) => { if(!(f instanceof File)) throw "Error: expecting File"; return ignoredPatterns.reduce((bool, p) => bool && !p.test(f.path, true)); }; })(); const indent = (s, n=4) => { const spaces = (new Array(n + 1)).join(' '); return spaces + s.replace(/\n/g, '\n' + spaces); }; class File{ constructor(path){ this.path = path; } get filename(){ return this.path.substring(this.path.lastIndexOf('/') + 1); } get name(){ const p = this.filename; if(p.lastIndexOf('.') === -1) return p; return p.substring(0, p.lastIndexOf('.')); } get prettyname(){ const capitalize = (s) => { if(s.length === 0) return ''; return [s[0].toUpperCase(), ...s.substring(1).toLowerCase()].join(''); }; const sepWords = (p) => p.replace(/[-_]/g, ' '); return capitalize(sepWords(this.name)); } get ext(){ return this.path.substring(this.path.lastIndexOf('.')); } } class Dir extends File{ ls(){ const isVisible = (f) => f[0] !== '.'; return fs.readdirSync(this.path) .filter(isVisible) .map((f) => path.join(this.path, f)) .map(p => new (fs.statSync(p).isDirectory()? Dir: File)(p)); } lsdirs(){ return this.ls().filter(f => f instanceof Dir); } } class Root extends Dir{ /* directories are viewed as Parts * files are Articles */ ls(){ return super.ls() .filter(isNotIgnored) .map(f => new (f instanceof Dir? Part: Article)(f.path)) .filter(f => f instanceof Article? f.ext === '.md': f); } getHeader(){ return `# Summary`; } articlesSummary(){ return this.ls() .filter(f => f instanceof Article) .map(f => f.toSummary()) .join('\n'); } directoriesSummary(){ return this.lsdirs() .map(part => part.toSummary()) .join('\n'); } getSummary(){ const artSum = this.articlesSummary() const dirsSum = this.directoriesSummary(); return [artSum, dirsSum].filter(s => s.trim() !== '').join('\n\n'); } toSummary(){ return this.getHeader() + '\n' + this.getSummary() + '\n'; } } class Part extends Root{ /* directories are viewed as Chapters * files are Articles */ ls(){ return super.ls() .map(f => f instanceof Part? new Chapter(f.path): f) } getHeader(){ return `## ${this.prettyname}`; } } class Chapter extends Part{ ls(){ return super.ls().filter(f => f.filename !== 'README.md'); } getHeader(){ const readme_path = path.join(this.path, 'README.md'); return `* [${this.prettyname}](${readme_path})` } getSummary(){ return indent(super.getSummary()); } } class Article extends File{ get prettyname(){ const original_prettyname = super.prettyname; if(original_prettyname !== 'Readme') return original_prettyname; return DEFAULT_README_TITLE; } toSummary(){ return `* [${this.prettyname}](${this.path})`; } } const summary = new Root('.').toSummary(); fs.writeFileSync('SUMMARY.md', summary);
本地安裝node環境,直接直接運行:
node generateSummary.js
也能生成Summary。
提交代碼之后,gitlab-ci也可以自動生成gitbook。
然后windows系統里設置hosts文件,瀏覽器訪問
192.168.0.82 root.gitlab-server