使用docsify+markdown+vditor构建gitlab pages文档库
前几天策划写了一个word文档来整理补充一些内容,当时就比较感慨,如果是Web文档就好了,可以超链接过去,也不必东一个文档,西一个文档的查找。
确实如此,工作这么久,各个公司的策划案都是使用的Word文档的形式给别的部门,策划写起来是方便了,但是其他岗位的人要看文档来制作就比较麻烦了,比如程序,一个项目中可能会有几十甚至几百个文档,这些文档之间的内容可能会有相互关联,使用WORD文档,可能过段时间,策划自己都不知道放哪个文档了,于是就出了各种整理文档,补充文档。
使用Web来管理文档是好,但要让策划直接编写网页制作策划案,我想应该基本上没人响应。那就只能迂回一点,平常写博客这类的文档,使用最多的就是Markdown了,而且目前使用Markdown格式作为各种网络文档也是非常常见的,比如github、gitlab、CSDN、各种笔记类APP等等。
有了使用Web来管理策划案的想法后,就着手查资料开干。 查下来目前比较常见的工具有:
笔者之前写过一篇 《使用jekyll写博客》,就是介绍的使用jekyll来编写 github的博客。 jekyll使用的ruby语言来构建静态网页,要使用这个工具,搭建语言环境比较麻烦,笔者在MacOS上为了使用jekyll,记得卡在了ruby的版本上,要求高版本,但OS又支持不了高版本,就此作罢,只能Windows上用用。
其它工具就不一一介绍了,都做了超链接,感兴趣的读者可以自行点开了解。今天要介绍是主角是Docsify,它与Docute一起成为与其它工具不一样的选择。
Docsify与Docute都是基于 Vue,且它们都是完全的运行时驱动,不会生成静态html,因此对 SEO 不够友好。如果你并不关注 SEO,同时也不想安装大量依赖,它们将是非常好的选择!在公司内部做策划文档的管理,不需要SEO,所以使用运行时驱动的Docsify或者Docute是完全可以的。之所以选择Docsify,一是因为最先发现它,二是它比Docute小,插件这些也比较丰富。
下面就介绍一下如何使用docsify构建gitlab Pages上的文档库。
一、开启gitlab pages
编辑/etc/gitlab/gitlab.rb,设置pages_external_url为自定义的域名,并且设置gitlab_pages[‘enable’]为true,如果要打开访问控制,则需要设置gitlab_pages[‘access_control’]为true,如下所示:
1################################################################################
2## GitLab Pages
3##! Docs: https://docs.gitlab.com/ee/pages/administration.html
4################################################################################
5
6##! Define to enable GitLab Pages
7pages_external_url "http://pages.io/"
8gitlab_pages['enable'] = true
9
10##! Pages access control
11gitlab_pages['access_control'] = true
设置好后运行下面的命令生效:
1gitlab-ctl reconfigure
二、gitlab网站设置
1. 访问控制
如果需要访问控制,则需要: 在“菜单”=>“管理员”=>“设置”=>“偏好设置”中展开Pages选项,勾选
- 要求用户证明自定义域名的所有权
- 禁止公开访问 Pages 站点
如下图所示:
最大页面大小默认为100M,可以根据实际情况调整。设置完成后记得执行“保存修改”。
2. 项目设置
在开启Pages后,项目设置,通用里会根据项目可见性自动设置Pages的可见性,并且项目设置里会看到Pages栏,如下图所示:
此时还没有任何可用页面。
三、编写网页
使用docsify+markdown文件来构建网页,只需要编写一个index.html即可。其它的就是根据docsify规则 编写markdown文件。
本地编写markdown文件建议使用VSCode+Office Viewer(Markdown Editor)插件,Office Viewer(Markdown Editor)插件使用了 vditor markdown编辑器,不得不说该编辑器非常强大。
如果想在本地编写好后,预览网页,满意后,再发布到gitlab pages。则需要在本地安装相应的环境。先安装 node.js,再根据 官方文档创建相应的项目。
具体如何编写这里就不再赘述了,可以看 官方文档。官方文档给出了一个插件列表 awesome-docsify,里面有很多插件,可以丰富docsify。
这里主要介绍一下官网上没有的或者需要注意的东西。
docsify内置的 Markdown 解析器是 marked,对markdown的支持有限,像数学公式,mermaid图这些都不支持,官网上对 markdown的配置所提甚少,只提供了mermaid图的配置,数学公式没有提及。
下面结合 awesome-docsify中提供的插件,介绍一下几种常用的额外功能配置:
1. mermaid图
直接使用插件 docsify-mermaid;
1 <!--mermaid图支持-->
2 <script src="//unpkg.com/mermaid/dist/mermaid.js"></script>
3 <script src="//unpkg.com/docsify-mermaid@latest/dist/docsify-mermaid.js"></script>
4 <script>
5 mermaid.initialize({ startOnLoad: true });
6 </script>
2. plantuml图
直接使用插件 docsify-plantuml 或者插件 docsify-puml
1<script>
2 window.$docsify = {
3 plantuml: {
4 skin: "classic",
5 },
6 }
7</script>
8<!--plantuml图支持-->
9<script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
3.数学公式
数学公式,这里需要提一下,markdown中的数学公式有几种格式,不同的平台支持的写法也不一致。 常见的markdown数学公式有以下几种写法:
- 以$加`开头,并以反序结尾的行内公式(gitlab支持,vditor会多显示一对单引号)
- 以$开头和结尾的行内公式(gitlab不支持,vditor支持)
- 以$$开头和结尾的块公式(gitlab不支持,vditor支持)
- 以math块标识的块公式(gitlab支持,vditor支持)
有一个插件 docsify-katex 支持使用katex输出数学公式,但是试用了一下,没达到预期。docsify有一个 issues提到怎样支持数学公式,但不尽如意。
笔者通过查资料和自己的修改得出如下配置:
1<script>
2 window.$docsify = {
3 plugins: [
4 function (hook) {
5 // 支持$和$$
6 hook.doneEach(function () {
7 if (typeof MathJax !== "undefined") {
8 MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
9 }
10 });
11 // 支持$``$
12 hook.beforeEach(function (content) {
13 return content.replace(/\$`.*`\$/g, function (a) {
14 return a.replace("`", "").replace("`", "");
15 });
16 });
17 // 支持```math```块
18 hook.beforeEach(function (content) {
19 return content.replace("\r\n","\n");
20 });
21 hook.beforeEach(function (content) {
22 return content.replace("\r","\n");
23 });
24 hook.beforeEach(function (content) {
25 c = content.replace(
26 /```math\n[^`]*\n```/g,
27 function (a) {
28 return a
29 .replace("```math", "\$\$\$\$")
30 .replace("```", "\$\$\$\$");
31 }
32 );
33 return c
34 });
35 },
36 ],
37 }
38</script>
39
40<script type="text/x-mathjax-config">
41 MathJax.Hub.Config({
42 tex2jax: {
43 inlineMath: [['$','$'], ['\\(','\\)']],
44 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
45 processClass: 'math',
46 processEscapes: true
47 },
48 TeX: {
49 equationNumbers: { autoNumber: ['AMS'], useLabelIds: true },
50 extensions: ['extpfeil.js', 'mediawiki-texvc.js'],
51 Macros: {bm: "\\boldsymbol"}
52 },
53 'HTML-CSS': { linebreaks: { automatic: true } },
54 'preview-HTML': { linebreaks: { automatic: true } },
55 SVG: { linebreaks: { automatic: true } }
56 });
57</script>
58
59<!--MathJax数学公式支持-->
60<script src="//cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
下图为数学公式示例输出:
四、预览网页
预览网页只需要在项目所在目录的命令行运行:
1docsify serve
五、发布到gitlab pages
1. 编写.gitlab-ci.yml
为了让gitlab pages能正常显示网页,需要使用到gitlab的CI/CD功能,在项目根目录创建一个.gitlab-ci.yml文件,也可以在gitlab网站上新建,选择.gitlab-ci.yml模板,应用html模板。
或者把生成的内容复制到本地建。
1pages:
2 stage: deploy
3 script:
4 - mkdir .public
5 - cp -r * .public
6 - mv .public public
7 artifacts:
8 paths:
9 - public
10 rules:
11 - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
这样每次提交更改后,gitlab都会自动更新页面。 成功后就可以在项目设置的Pages下看到网页的访问地址了:
2. 修改hosts
由于前面在配置gitlab.rb时pages_external_url是随便配置的,为了能正常访问,需要将之映射到gitlab所在的ip,修改C:\Windows\System32\drivers\etc\hosts,添加映射:
1192.168.1.6 docs.pages.io
2192.168.1.6 projects.pages.io
docs.pages.io是平常访问用到的域名,其中的docs是gitlab中项目所在的组或者用户 projects.pages.io是访问控制授权时需要用到的域名。
六、附index.html源码
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <title>Document</title>
6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
7 <meta name="description" content="Description" />
8 <meta
9 name="viewport"
10 content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
11 />
12 <link
13 rel="stylesheet"
14 href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css"
15 />
16 </head>
17
18 <body>
19 <div id="app"></div>
20 <script>
21 window.$docsify = {
22 loadNavbar: true,
23 loadSidebar: true,
24 loadSidebar: "summary.md",
25 autoHeader: true,
26 subMaxLevel: 3,
27 auto2top: true,
28 name: "主页",
29 homepage: 'index.md',
30 basePath: 'docs',
31 repo: "http://192.168.1.6/",
32
33 pagination: {
34 previousText: "上一篇",
35 nextText: "下一篇",
36 crossChapter: true,
37 crossChapterText: false,
38 },
39
40 count: {
41 countable: true,
42 fontsize: "0.9em",
43 color: "rgb(90,90,90)",
44 language: "chinese",
45 },
46
47 search: {
48 maxAge: 864, // 过期时间,单位毫秒,默认一天
49 placeholder: "搜索",
50 noData: "找不到结果",
51 namespace: "文档",
52 },
53
54 plantuml: {
55 skin: "classic",
56 },
57
58 timeUpdater: {
59 text: ">最后更新时间: {docsify-updated}",
60 formatUpdated: "{YYYY}/{MM}/{DD} {HH}:{mm}",
61 },
62
63 plugins: [
64 function (hook) {
65 // 支持$$
66 hook.doneEach(function () {
67 if (typeof MathJax !== "undefined") {
68 MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
69 }
70 });
71 // 支持$``$
72 hook.beforeEach(function (content) {
73 return content.replace(/\$`.*`\$/g, function (a) {
74 return a.replace("`", "").replace("`", "");
75 });
76 });
77 // 支持```math```块
78 hook.beforeEach(function (content) {
79 return content.replace("\r\n","\n");
80 });
81 hook.beforeEach(function (content) {
82 return content.replace("\r","\n");
83 });
84 hook.beforeEach(function (content) {
85 c = content.replace(
86 /```math\n[^`]*\n```/g,
87 function (a) {
88 return a
89 .replace("```math", "\$\$\$\$")
90 .replace("```", "\$\$\$\$");
91 }
92 );
93 return c
94 });
95 },
96 ],
97 };
98 </script>
99 <script type="text/x-mathjax-config">
100 MathJax.Hub.Config({
101 tex2jax: {
102 inlineMath: [['$','$'], ['\\(','\\)']],
103 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
104 processClass: 'math',
105 processEscapes: true
106 },
107 TeX: {
108 equationNumbers: { autoNumber: ['AMS'], useLabelIds: true },
109 extensions: ['extpfeil.js', 'mediawiki-texvc.js'],
110 Macros: {bm: "\\boldsymbol"}
111 },
112 'preview-HTML': { linebreaks: { automatic: true } },
113 SVG: { linebreaks: { automatic: true } }
114 });
115 </script>
116 <!-- Docsify v4 -->
117 <script src="//cdn.jsdelivr.net/npm/docsify"></script>
118
119 <!--MathJax数学公式支持-->
120 <script src="//cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
121
122 <!--plantuml图支持-->
123 <script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
124
125 <!--mermaid图支持-->
126 <script src="//unpkg.com/mermaid/dist/mermaid.js"></script>
127 <script src="//unpkg.com/docsify-mermaid@latest/dist/docsify-mermaid.js"></script>
128
129 <!--字数统计-->
130 <script src="//unpkg.com/docsify-count/dist/countable.js"></script>
131
132 <!-- emoji表情支持 -->
133 <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script>
134 <!-- 搜索功能支持 -->
135 <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
136 <!--在所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码-->
137 <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
138 <!-- 图片放大缩小支持 -->
139 <script src="//unpkg.com/docsify/lib/plugins/zoom-image.min.js"></script>
140 <!--分页支持-->
141 <script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
142 <!-- 更新时间支持 -->
143 <script src="https://cdn.jsdelivr.net/npm/docsify-updated@1/src/time-updater.min.js"></script>
144
145 <!--语法高亮-->
146 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
147 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-c.min.js"></script>
148 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-cpp.min.js"></script>
149 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-csharp.min.js"></script>
150 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-go.min.js"></script>
151 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-go-module.min.js"></script>
152 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-cmake.min.js"></script>
153 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-lua.min.js"></script>
154 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-mermaid.min.js"></script>
155 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-protobuf.min.js"></script>
156 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-docker.min.js"></script>
157 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-java.min.js"></script>
158 </body>
159</html>
其实我们可以直接使用vditor来渲染,这样就能与VSCode中的表现完全一致(都是使用的vditor),但是docsify的其它插件就用不了了,同时图片的URL生成也有问题,显示不了本地图片。记录一下配置:
1 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vditor/dist/index.css" />
2 <script src="https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js"></script>
3 <script>
4 window.$docsify = {
5 plugins: [
6 function (hook) {
7 hook.beforeEach(function (content) {
8 // 获取内容输出的节点
9 const previewElement = document.getElementById('main')
10 Vditor.preview(previewElement, content, {
11 markdown: {
12 toc: true,
13 // 使用vditor来渲染Markdown最好不使用history模式,否则可能引起路由错误
14 // linkBase这个设置对Hash路由方式非常重要
15 linkBase: '#',
16 },
17 speech: {
18 enable: true,
19 },
20 math: {
21 // VSCode的Office Viewer(Markdown Editor)插件使用的是'KaTeX'引擎,
22 // 这里与之保持一致,当然也可以使用'MathJax'引擎
23 engine: 'KaTeX',
24 //engine: 'MathJax',
25 },
26 })
27 })
28 }
29 ]
30 }
31 </script>
经过多番研究,使用docsify插件,配置出了比Vditor更强大的配置,支持
- LaTex数学公式
- mermaid图
- dot图
- plantuml图
- graphviz图
- mindmap图
- echarts图表
- charty图表
记录一下: index.html:
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <title>文档库</title>
6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
7 <meta name="description" content="Description" />
8 <meta
9 name="viewport"
10 content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
11 />
12 <link
13 rel="stylesheet"
14 href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css"
15 />
16 <!-- 支持 LaTex 语言 -->
17 <link
18 rel="stylesheet"
19 href="//cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css"
20 />
21
22 <link
23 rel="stylesheet"
24 href="//cdn.jsdelivr.net/npm/docsify-dark-mode@latest/dist/style.min.css"
25 />
26
27 <link
28 rel="stylesheet"
29 href="https://unpkg.com/docsify-toc@1.0.0/dist/toc.css"
30 />
31 </head>
32
33 <body>
34 <!-- markmap is based on d3, so must load those files first. -->
35 <script src="//unpkg.com/d3@3/d3.min.js"></script>
36 <script src="//unpkg.com/markmap@0.6.1/lib/d3-flextree.js"></script>
37 <script src="//unpkg.com/markmap@0.6.1/lib/view.mindmap.js"></script>
38 <link
39 rel="stylesheet"
40 href="//unpkg.com/markmap@0.6.1/style/view.mindmap.css"
41 />
42
43 <div id="app">拼命加载中……</div>
44
45 <script>
46 window.$docsify = {
47 loadNavbar: true,
48 loadNavbar: "navbar.md",
49 loadSidebar: true,
50 loadSidebar: "sidebar.md",
51 loadFooter: true,
52 loadFooter: "footer.md",
53 autoHeader: true,
54 subMaxLevel: 3,
55 auto2top: true,
56 mergeNavbar: true,
57 topMargin: 0,
58 name: "文档库",
59 //repo: "http://127.0.0.1/",
60
61 //themeColor: "#42b983",
62 tabs: { persist: true, theme: "material" },
63
64 // 图表
65 charty: {
66 theme: "#EE5599",
67 mode: "light",
68 },
69
70 toc: {
71 scope: ".markdown-section",
72 headings: "h1, h2, h3",
73 title: "大纲",
74 },
75
76 copyCode: {
77 buttonText: "复制到剪贴板",
78 errorText: "错误",
79 successText: "已复制",
80 },
81
82 // 文本高亮
83 "flexible-alerts": {
84 style: "flat",
85 note: {
86 label: "信息",
87 },
88 tip: {
89 label: "提示",
90 },
91 warning: {
92 label: "警告",
93 },
94 attention: {
95 label: "注意",
96 },
97 },
98
99 pagination: {
100 previousText: "上一篇",
101 nextText: "下一篇",
102 crossChapter: true,
103 crossChapterText: false,
104 },
105
106 count: {
107 countable: true,
108 fontsize: "0.9em",
109 color: "rgb(90,90,90)",
110 language: "chinese",
111 },
112
113 search: {
114 maxAge: 180000, // 过期时间,单位毫秒,默认3分钟
115 placeholder: "搜索",
116 noData: "找不到结果",
117 namespace: "文档",
118 },
119
120 plantuml: {
121 skin: "classic",
122 renderSvgAsObject: true,
123 },
124
125 mindmap: {
126 markmap: {
127 preset: "colorful", // or default
128 linkShape: "diagonal", // or bracket
129 },
130 },
131
132 timeUpdater: {
133 text: ">最后更新时间: {docsify-updated}",
134 formatUpdated: "{YYYY}/{MM}/{DD} {HH}:{mm}",
135 },
136
137 markdown: {
138 renderer: {
139 code: function (code, lang, base = null) {
140 if (lang === "dot") {
141 return '<div class="viz">' + Viz(code, "SVG") + "</div>";
142 }
143
144 var pdf_renderer = function (code, lang, verify) {
145 function unique_id_generator() {
146 function rand_gen() {
147 return Math.floor((Math.random() + 1) * 65536)
148 .toString(16)
149 .substring(1);
150 }
151 return (
152 rand_gen() +
153 rand_gen() +
154 "-" +
155 rand_gen() +
156 "-" +
157 rand_gen() +
158 "-" +
159 rand_gen() +
160 "-" +
161 rand_gen() +
162 rand_gen() +
163 rand_gen()
164 );
165 }
166 if (
167 lang &&
168 !lang.localeCompare("pdf", "en", { sensitivity: "base" })
169 ) {
170 if (verify) {
171 return true;
172 } else {
173 var divId =
174 "markdown_code_pdf_container_" +
175 unique_id_generator().toString();
176 var container_list = new Array();
177 if (localStorage.getItem("pdf_container_list")) {
178 container_list = JSON.parse(
179 localStorage.getItem("pdf_container_list")
180 );
181 }
182 container_list.push({ pdf_location: code, div_id: divId });
183 localStorage.setItem(
184 "pdf_container_list",
185 JSON.stringify(container_list)
186 );
187 return (
188 '<div style="margin-top:' +
189 PDF_MARGIN_TOP +
190 "; margin-bottom:" +
191 PDF_MARGIN_BOTTOM +
192 ';" id="' +
193 divId +
194 '">' +
195 '<a href="' +
196 code +
197 '"> Link </a> to ' +
198 code +
199 "</div>"
200 );
201 }
202 }
203 return false;
204 };
205
206 if (pdf_renderer(code, lang, true)) {
207 return pdf_renderer(code, lang, false);
208 }
209
210 return base ? base : this.origin.code.apply(this, arguments);
211 },
212 },
213 },
214 };
215 </script>
216
217 <!-- Docsify -->
218 <script src="https://cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
219
220 <script src="//cdn.jsdelivr.net/npm/docsify-dark-mode@latest/dist/index.min.js"></script>
221 <script src="//unpkg.com/docsify-toc@1.0.0/dist/toc.js"></script>
222
223 <!-- charty -->
224 <script src="//cdn.jsdelivr.net/npm/@markbattistella/docsify-charty@latest"></script>
225 <link
226 rel="stylesheet"
227 href="//cdn.jsdelivr.net/npm/@markbattistella/docsify-charty@latest/dist/docsify-charty.min.css"
228 />
229
230 <!-- docsify: tabs -->
231 <script src="//cdn.jsdelivr.net/npm/docsify-tabs@1"></script>
232
233 <!-- 脑图 -->
234 <script src="//unpkg.com/docsify-mindmap/dist/docsify-mindmap.min.js"></script>
235
236 <!--plantuml图支持-->
237 <script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
238
239 <!-- 支持 DOT 语言 -->
240 <script src="https://cdn.jsdelivr.net/gh/wugenqiang/NoteBook@master/plugin/viz.js"></script>
241 <!-- 支持 LaTex 语言 -->
242 <script src="//cdn.jsdelivr.net/npm/docsify-katex@latest/dist/docsify-katex.js"></script>
243
244 <!--mermaid支持-->
245 <script src="//unpkg.com/mermaid/dist/mermaid.js"></script>
246 <script src="//unpkg.com/docsify-mermaid@latest/dist/docsify-mermaid.js"></script>
247
248 <!--graphviz支持-->
249 <script src="//unpkg.com/@hpcc-js/wasm/dist/index.min.js"></script>
250 <script src="//unpkg.com/docsify-graphviz@latest/dist/docsify-graphviz.js"></script>
251
252 <!-- alerts -->
253 <script src="https://unpkg.com/docsify-plugin-flexible-alerts"></script>
254
255 <!-- echarts -->
256 <script src="//cdn.jsdelivr.net/npm/echarts@latest/dist/echarts.min.js"></script>
257 <script src="//cdn.jsdelivr.net/npm/docsify-echarts-plugin/lib/index.min.js"></script>
258
259 <!-- 添加 PDF 页面展示功能 -->
260 <script src="//cdnjs.cloudflare.com/ajax/libs/pdfobject/2.1.1/pdfobject.min.js"></script>
261 <script src="//unpkg.com/docsify-pdf-embed-plugin/src/docsify-pdf-embed.js"></script>
262
263 <!-- emoji表情支持 -->
264 <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script>
265 <!-- 搜索功能支持 -->
266 <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
267 <!--在所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码-->
268 <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
269 <!-- 图片放大缩小支持 -->
270 <script src="//unpkg.com/docsify/lib/plugins/zoom-image.min.js"></script>
271 <!--分页支持-->
272 <script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
273 <!-- 更新时间支持 -->
274 <script src="//cdn.jsdelivr.net/npm/docsify-updated@1/src/time-updater.min.js"></script>
275 <!--字数统计-->
276 <script src="//unpkg.com/docsify-count/dist/countable.min.js"></script>
277
278 <!-- footer -->
279 <script src="//cdn.jsdelivr.net/npm/@alertbox/docsify-footer/dist/docsify-footer.min.js"></script>
280
281 <!--语法高亮-->
282 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
283 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-c.min.js"></script>
284 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-cpp.min.js"></script>
285 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-csharp.min.js"></script>
286 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-go.min.js"></script>
287 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-go-module.min.js"></script>
288 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-cmake.min.js"></script>
289 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-lua.min.js"></script>
290 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-mermaid.min.js"></script>
291 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-protobuf.min.js"></script>
292 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-docker.min.js"></script>
293 <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-java.min.js"></script>
294
295 <!-- 实现离线化 -->
296 <script>
297 if (typeof navigator.serviceWorker !== "undefined") {
298 navigator.serviceWorker.register("assets/docsify-sw.js");
299 }
300 </script>
301 </body>
302</html>
其中的docsify-sw.js为:
1/* ===========================================================
2 * docsify sw.js
3 * ===========================================================
4 * Copyright 2016 @huxpro
5 * Licensed under Apache 2.0
6 * Register service worker.
7 * ========================================================== */
8
9const RUNTIME = 'docsify'
10const HOSTNAME_WHITELIST = [
11 self.location.hostname,
12 'fonts.gstatic.com',
13 'fonts.googleapis.com',
14 'cdn.jsdelivr.net'
15]
16
17// The Util Function to hack URLs of intercepted requests
18const getFixedUrl = (req) => {
19 var now = Date.now()
20 var url = new URL(req.url)
21
22 // 1. fixed http URL
23 // Just keep syncing with location.protocol
24 // fetch(httpURL) belongs to active mixed content.
25 // And fetch(httpRequest) is not supported yet.
26 url.protocol = self.location.protocol
27
28 // 2. add query for caching-busting.
29 // Github Pages served with Cache-Control: max-age=600
30 // max-age on mutable content is error-prone, with SW life of bugs can even extend.
31 // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
32 // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
33 if (url.hostname === self.location.hostname) {
34 url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
35 }
36 return url.href
37}
38
39/**
40 * @Lifecycle Activate
41 * New one activated when old isnt being used.
42 *
43 * waitUntil(): activating ====> activated
44 */
45self.addEventListener('activate', event => {
46 event.waitUntil(self.clients.claim())
47})
48
49/**
50 * @Functional Fetch
51 * All network requests are being intercepted here.
52 *
53 * void respondWith(Promise<Response> r)
54 */
55self.addEventListener('fetch', event => {
56 // Skip some of cross-origin requests, like those for Google Analytics.
57 if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
58 // Stale-while-revalidate
59 // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
60 // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
61 const cached = caches.match(event.request)
62 const fixedUrl = getFixedUrl(event.request)
63 const fetched = fetch(fixedUrl, { cache: 'no-store' })
64 const fetchedCopy = fetched.then(resp => resp.clone())
65
66 // Call respondWith() with whatever we get first.
67 // If the fetch fails (e.g disconnected), wait for the cache.
68 // If there’s nothing in cache, wait for the fetch.
69 // If neither yields a response, return offline pages.
70 event.respondWith(
71 Promise.race([fetched.catch(_ => cached), cached])
72 .then(resp => resp || fetched)
73 .catch(_ => { /* eat any errors */ })
74 )
75
76 // Update the cache with the version we fetched (only for ok status)
77 event.waitUntil(
78 Promise.all([fetchedCopy, caches.open(RUNTIME)])
79 .then(([response, cache]) => response.ok && cache.put(event.request, response))
80 .catch(_ => { /* eat any errors */ })
81 )
82 }
83})
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2022/2022-02-22-使用docsify+markdown+vditor构建gitlab-pages文档库/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。