? 这是第 46篇不掺水的原创,想要了解更多,请戳上方蓝色字体:政采云前端团队关注我们吧~

本文首发于政采云前端团队博客:前端文档站点搭建方案

https://www.zoo.team/article/document-site

前言

在《自动化 Web 性能优化分析方案》一文中说到,百策系统性能检测的原理,以及对于检测页面我们最终会生成一份检测报告,如下图所示:

前言

通过检测报告,我们可以清楚地了解到我们的页面在性能方面有哪些不足和有待提高的地方,并且针对每一个扣分项,我们都提供了详细的扣分原因,以及解决方案。

我们的系统是面向前端团队所有的开发同学,因此我们需要将我们的解决方案沉淀下来,群策群力,共同丰富优化性能的知识库,所以我们需要文档站点,一个可以实时编辑,自动部署的文档站点。

目前现有的文档站点方案有 docsify (https://docsify.js.org/#/?id=docsify)、gitbook (http://gitbook.hushuang.me/)、vuepress (https://vuepress.vuejs.org/zh/guide/) 等,也有着相对丰富的插件和主题,但是布局较为单一,灵活性不足。

需求

  • 文档用 Markdown 编写,最终生成 Html
  • 文档可以实时编辑,而不是修改 Html 代码
  • Markdown 文件修改后,文档站点自动更新

方法一:EggJS + marked + highlight.js

  • 将文档以 Markdown 的形式放在 GitLab 中,以便文档的维护
  • 熟悉 Git 的小伙伴知道 GitLab 是可以设置钩子 (Hook) 的,通过设置钩子可以实现当我们提交代码后,服务端知道在哪个分支修改了哪些文件,然后把更新后的文档重新转化成 Html 文件
  • 在设置 GitLab Webhook 时,只需选择 push event 就好,这样 Hook 就只会在 push 的时候触发,一个完整的 push event 返回的数据字段很多,对于我们来说,下面两个字段就足够了

{  ref: ''    // 分支名  commits: [   // 提交内容    {      added: [],  // 新增的文件路径      modified: [],  // 修改的文件路径      removed: []     // 删除的文件路径    }  ],  ...}

整个流程大致如下:

63CCF325-2676-420C-B793-0803B226F8DB.png

模板文件即除了 Markdown 外的文件,譬如布局、样式、脚本等,这些公用文件有变动后需要将整个站点重新构建一遍。

在这个流程中,服务端需要开发两个接口,一个用来响应 GitLab 的 Webhook,另一个是用来进行手动批量生成。

// document.router.tsimport { Application } from "egg";export default (app: Application): void => {  const { controller, router } = app;  // gitlab webhook  router.post("/api/hook", controller.document.hook);  router.get("/api/batchUpdate", controller.document.batchUpdate);};

Webhook

在设置 Webhook 的时候,我们只需选择 push event,这样就会在 push 的时候,才会触发 Hook,为了保证文档的规范,只对 Master 分支的 push event 进行操作。

Webhooks 配置:

image-20191130105149305

代码示例:

const { commits, ref }: { commits: any[]; ref: string } = pushEvent;// 过滤非 master 分支的 pushif (!isMaster(ref)) {  return false;}// 修改(新增)文档列表const updateList: string[] = [];// 删除文档列表const removeList: string[] = [];commits.forEach((item: Commits) => {  const { added, modified, removed } = item;  updateList.push(...added, ...modified);  removeList.push(...removed);});// 过滤重复文件const uniqueUpdateList: string[] = [...new Set(updateList)];const uniqueRemoveList: string[] = [...new Set(removeList)];

在得到要更新的集合 uniqueUpdateList 后,就要将对应的 Markdown 文件内容转为 Html,如何获取到 Git 上的单个文件呢,我们可以从 uniqueUpdateList 得知新增或修改的文件路径,然后我们需要借助 GitLab Open Api 中的 ${gitLabhost}/api/v3/projects/${projectId}/repository/files?file_path=${filePath}&ref=master&private_token=${accessToken} 获取对应文件的内容,完整的返回如下:

{  file_name: "",    // 文件名称  file_path: "",    // 文件路径  size: 700,     // 文件大小  encoding: "base64",     // 编码方式  content: "",     // 文件内容  ref: "master",   // 分支名 ...}

通过这个接口可拿到 base64 编码的文件内容,转换成 uft-8 后就是我们需要的 Markdown 文档了。

new Buffer(content, "base64").toString("utf8");

接下来需要将 Markdown 转换成 Html,Markdown 转 Html 使用的是 marked (https://yarnpkg.com/zh-Hant/package/marked),代码高亮使用的是 highlight.js (https://yarnpkg.com/zh-Hant/package/highlight.js)

import * as marked from "marked";import * as hljs from "highlight.js";marked.setOptions({  // 设置高亮  highlight(code, lang) {    if (lang && hljs.getLanguage(lang)) {      return hljs.highlight(lang, code, true).value;    } else {      return hljs.highlightAuto(code).value;    }  }});const customRender = new marked.Renderer();const htmlStr: string = marked(markdownStr, { renderer: customRender });

全量生成

为了保证使用最新的模板和文档生成 html,每次全量生成之前,都需要从 GitLab 拉取完整的项目,拉取代码使用的是 git-clone (https://yarnpkg.com/zh-Hant/package/git-clone)

gitClone(repo, targetPath, {}, () => {  ...});

接下来就是读取临时文件夹中 Markdown 文件内容,结合页面模板转化为 Html。

页面模板即除了文档内容 Markdown 外的文件,譬如布局、公用头部、左侧菜单、样式、脚本等。

然后将前面生成的正文内容注入到准备好的模板中,这里使用的模板引擎是 Ejs,就可以得到如下页面:

image-20191125211921359

方法二:NestJS + docsify

本着折腾的精神,上述方法是我们组的小伙伴自己实现了 docsify 类似的方案,细节方面的设计着实比不上开源的那些产品,所以我们决定再折腾一次,迁移到了方案二:node.js + docsify。服务端负责处理 Webhooks 来拉取 GitLab 上最新的文档文件,docsify 负责实时编译文档。

docsify 是一个动态生成文档网站的工具。不同于 GitBook、Hexo 的是,它不会在服务端编译时将 md 文件转成 Html 文件,所有转换工作都是在浏览器端执行的。docsify 已经提供了实施编译 md 文件的功能,剩下我们需要实现的部分就是在 GitLab 上的文件有更新时,自动触发服务重新拉取最新的 md 文件。

改造后的流程:

  • 文档贡献者在 GitLab 上编辑源文件
  • 编辑完成保存后触发 GitLab 的 Webhooks
  • 文档服务接收到 Webhooks 请求后拉取最新的文档
  • 用户刷新页面后 docsify 实时把最新的 md 文件转化为 Html

服务端核心代码

// app.controller.tsimport { Controller, Post } from "@nestjs/common";import * as execa from "execa";@Controller()export class AppController {  @Post("hook")  async hook() {    // 执行命令 git pull,拉取最新代码    const { stdout } = await execa("git", ["pull"]);    return stdout;  }}
// main.tsimport { NestFactory } from "@nestjs/core";import { AppModule } from "./app.module";import { join } from "path";import { Logger } from "@nestjs/common";const port = parseInt(process.env.PORT, 10) || 3001;async function bootstrap() {  const app = await NestFactory.create(AppModule);  app.setGlobalPrefix("api");  app.useStaticAssets(join(__dirname, "..", "docs"));  await app.listen(port);  Logger.log(`服务已启动,请访问 http://localhost:${port}`);}bootstrap();

效果图

效果图

点击编辑文档即可进入文档对应的 GitLab 页面进行编辑。

GitLab 编辑

方案对比

方案二和方案一不同的地方就是把 md 文件渲染成 Html 的一步从服务端改到了浏览器端,服务器端只承担接收 Webhook 拉取最新的代码的工作。

fD4H17kx4AkM4dG5.png

总结

以上提供了一个不用 GitLab CI 实现文档站点内容修改后自动更新的思路。一个顺手的文档站点搭好之后,接下来我们就只需要关心如何把 Markdown 写好推送到 GitLab,其它的工作服务器都会帮我们完成。

看完两件事

如果你觉得这篇内容对你挺有启发,我想邀请你帮我两件小事1.点个「在看」,让更多人也能看到这篇内容(喜欢不点在看的,都是耍流氓)2.关注公众号「政采云前端团队」,持续为你推送精选好文

招贤纳士

政采云前端团队(ZooTeam),一个年轻富有激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 50 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员构成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端应用、数据分析及可视化等方向进行技术探索和实战,推动并落地了一系列的内部技术产品,持续探索前端技术体系的新边界。

如果你想改变一直被事折腾,希望开始能折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变既定的节奏,将会是“5 年工作时间 3 年工作经验”;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊… 如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的前端团队的成长历程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 ZooTeam@cai-inc.com

前端md转html添加样式_前端文档站点搭建方案相关推荐

  1. 【前端】【element】el-progress组件使用文档补充——大小调整与数字颜色

    [前端][element]el-progress组件使用文档补充--大小调整与数字颜色 el-progress 调整大小 调整颜色 基础可参考官方文档:Progress 进度条 el-progress ...

  2. 换行样式不要首行缩进_修改文档样式库中的“正文”样式,使得文档中所有正文段落首行缩进2个字符。...

    问答题请在[答题]菜单下选择[进入考生文件夹]命令,并按照题目要求完成下面的操作.注意:以下的文件必须都保存在考生文件夹下.在考生文件夹下打开文档WORD.DOCX.[背景素材]为了更好地介绍公司的服 ...

  3. 计算机毕业设计Java智慧校园系统前端(源码+系统+mysql数据库+lw文档)

    计算机毕业设计Java智慧校园系统前端(源码+系统+mysql数据库+lw文档) 计算机毕业设计Java智慧校园系统前端(源码+系统+mysql数据库+lw文档) 本源码技术栈: 项目架构:B/S架构 ...

  4. 单文档应用程序弹出新对话框_简介——文档

    1.3 文档(Documents) 文档是绘制和编辑结构的工作区域.文档可以包含许多页,也可以只包含一页. 1.3.1 创建文档(Creating Documents) 可以直接使用默认设置创建文档, ...

  5. 10大开源文档管理系统_开源文档的5大趋势

    10大开源文档管理系统 我已经做了很长时间的开源文档. 在过去的十年中,关于创作和出版的态度发生了很多变化. 这些趋势中的一些趋势似乎是周期性的,例如语义标记的流行. 最新趋势使文档更接近于代码,许多 ...

  6. php验证码手册,验证码_专题_帮助文档_Thinkphp手册

    验证码_专题_帮助文档_Think Think/Verify类可以支持验证码的生成和验证功能. 生成验证码 下面是最简单的方式生成验证码: seover" style=" marg ...

  7. api数据接口文档_接口文档示例(Taobao/jd/pinduoduo/开放接口调用)

    api数据接口文档_接口文档示例 本文主要是提供了一个接口文档的范文,内容修订历史.目录.时序图.接口要素描述.接口说明.使用示例.字典.FAQ.  使用MD格式文档(makedown),选择原因,容 ...

  8. java word 超链接到文档内部_Java 添加超链接到 Word 文档方法详解

    在Word文档中,超链接是指在特定文本或者图片中插入的能跳转到其他位置或网页的链接,它也是我们在编辑制作Word文档时广泛使用到的功能之一.今天这篇文章就将为大家演示如何使用Free Spire.Do ...

  9. java中添加文本框_Java 添加、删除Word文档中的文本框

    在Word文档中,文本框是指一种可移动.可调大小的文字或图形容器.使用文本框,能够使文档在内容和形式上更为饱满.本文将通过使用Java编程来演示如何添加.删除Word文档中的文本框. Jar文件获取及 ...

最新文章

  1. android 不重新加载,android – 返回Activity而不重新创建(不调用onCreate())
  2. Java进阶之深入理解JVM类加载机制
  3. LeetCode 79. 单词搜索(回溯DFS)
  4. php-rpm.conf,在新安装的宝塔面板中php无法启动起来
  5. 和当前时间比较_货币的时间价值
  6. Json学习总结(4)——Json基础知识回顾
  7. [20171113]修改表结构删除列相关问题2.txt
  8. python shell常用命令_python 之 shell命令执行
  9. nginx 代理springmvc到二级目录_详解Nginx从入门到实践
  10. 云教务学校管理系统源码
  11. SM2算法全套(基于GMSSL)
  12. 心态-《当下的力量》书中的精髓:了解我们痛苦的根源,学会让自己活在当下,摆脱痛苦。
  13. Untiy 接入 移动MM 详解 转
  14. 生成器和生成器表达方式
  15. [DirectShow] DirectShow的窗口
  16. BackTrack5 Note01
  17. 1100. 校庆 (25 分)
  18. lumia 830 android,微软Lumia 830成功刷入Android 5.0系统
  19. sd卡中的文件夹删除了怎么恢复,SD卡删除的文件如何恢复
  20. Java美团一面_Java开发美团一面面经

热门文章

  1. 去德国做汉语老师,月薪四万
  2. 毕业之后,这些年薪 50w+ 的 90 后程序员都经历了什么?纯水贴
  3. python调用rocketmq的api_rocketmq-python
  4. 腾讯四季度数实经济收入首超游戏达479.58亿元
  5. 支付宝五福活动抢先开始了!原来今年可以提前集
  6. 库克宣布苹果将捐款帮助山西
  7. 特斯拉电动皮卡量产时间还会推迟 内部人士称已被推迟到2023年
  8. 小米宣布造车后,雷军与四位造车界大佬合影照曝光
  9. 广汽埃安总经理古惠南:8分钟快充也不光是电池的问题 ,跟充电桩有关
  10. 完全“撞脸”今日头条,这家店火了!已被今日头条起诉商标侵权...