如何快速实现 markdown 转 HTML 文档?
我想要在 Github 上开一个主题博客,我希望通过 Markdown 语法写作,然后生成 HTML 并附带自定义样式显示在网页上。
我找到了 gulp-markdown 这个库,看起来符合我的需求场景。然而这个库有一个问题,他只能将 Markdown 语法书写的文字转换为 HTML 标签,但并不能自动添加 doctype 文档声明,这就意味着生成的 HTML 文档并不合法。
# 标题
我是正文。
会被编译为
<h1>标题</h1>
<p>我是正文</p>
而不是
<!doctype html>
<html>
<head>
<title>XXX<title>
</head>
<body>
<h1>标题</h1>
<p>我是正文</p>
</body>
</html>
这就很尴尬了,我不知道这个库的作者为什么要这么设计这个库,我觉得它应该有一个配置参数可以自动添加 HTML 文档声明等信息,于是我去查找其文档(注意,它的文档只能翻墙才能看),然而呵呵并没有。
这就很尴尬了,怎么办呢?首先我想到的是,使用其他类似 HTML 模版的库来组合实现我想要的效果,然而搜了一圈发现,并没有合适的。因为这类库都需要首先在 HTML 文档中使用其模版语法标记 HTML 要插入的位置,然后在声明要插入的内容。可是我们并没有 HTML 模版,套路不同。
所以这个思路行不通,接下来我想到的方案是:
- 写一个 Gulp 插件解决这个问题;
- 这个问题肯定不是我第一次遇见,我先查查别人的解决方案;
懒惰是第一生产力,我当然先选择方案二,果不其然,全网看下来,貌似只有一个台湾小哥想到了一个解决方案,大体的思路是使用大陆前端娱乐圈知名人士方方老师写的一个 gulp-html-extend 库,实现一种类模版语言的 HTML 混入。为了实现这一点,你需要在每个 Markdown 文档里写下模版语言语法,类似这样:
<!-- @ @master = ../../layout/master.html-->
<!-- @ @block = content-->
# 我是标题
我是正文
<!-- @ @close-->
额,很显然这个解决方案并不优雅。为什么我要在每次开心书写 Markdown 的时候先写这堆奇怪的注释啊。我拒绝。
那么我们又回到了最初的起点,那个残酷的方案一又萦绕在我心头,要写一个 Gulp 插件吗?不!我的懒惰不允许我就在这里放弃!
当你不知所措的时候,不妨回到最初的起点,思考问题的本质是什么,这通常会激发我的灵感。这次我也这么做了,果不其然有所收获。
让我们一起想想,我实际要做的无非就是把由 gulp-markdown 生成的 HTML 标签插入到一个这样的「壳子」里:
<!doctype html>
<html>
<head>
<title>XXX<title>
</head>
<body>
<!-- 在这里插入 -->
</body>
</html>
所以我只需要在每个生成的 HTML 文件的头尾插入这些字符:
<!doctype html>
<html>
<head>
<title>XXX<title>
</head>
<body>
和这些字符:
</body>
</html>
就行了,所以问题转变为一个文件字符串拼接的问题,我很快就找到了 gulp-header 这个库,它能实现我们在每个文件头部插入字符的需求,而根据「对称就是美」定理,当然会有一个 gulp-footer 库来解决我们后半部分的需求,这样我们的问题就被完美解决了!
但是,老实讲这样的方案还是不够优雅,因为我们给文件前后插入太多字符了,我写代码习惯遵照 make it simple and stupid 的原则,因此对这个方案并不满意,我希望只插入最少的字符解决这个问题,因此接下来的问题就是:最少能插入多少字符保障 HTML 文档的规范性?
进过一番资料的查找,我发现,原来 <html>,<head> 和 <body> 标签都是可以省略的!只要一个 HTML 文档具备 <!doctype html> 文档声明和 <title> 标签,对于现代浏览器而言,就是一个合法合规的 HTML 文档!浏览器会自动生成 <html>,<head> 和 <body> 标签,并且把第一个不能放入 <head> 标签的标签和随后的标签都插入 <body> 标签中。没想到浏览器这么智能吧,我也没想到。
现在真相大白,解决这个问题的方案就很简单了,我们就只用在生成的 HTML 文档中添加最少的字符,这是我的 gulpfile.js 的配置:
const gulp = require('gulp')
const markdown = require('gulp-markdown')
const header = require('gulp-header')
gulp.task('default', () =>
gulp
.src('blog/**/*.md')
.pipe(header('<!doctype html><title>Blog</title>\n\r'))
.pipe(
markdown({
headerIds: false,
}),
)
.pipe(gulp.dest('html')),
)
搞定!
总结
通过这一番调研,我找到了解决 Markdown 生成规范的 HTML 文档的一种比较优雅的解决方案,并在调研过程中学到了关于 HTML 文档必备标签的相关知识,可谓是获益匪浅。希望阅读这篇文章的你也能够有所收获。
最后我再啰嗦两句,可能有人会问,为什么不搞个浏览器同步渲染,所见即所得,同步编辑岂不是更加炫酷,这个其实我有想过,最终决定不搞这个的理由是我觉得既然使用了 Markdown 语法,我的目的就是专心写作,我并不想因为要看到样式而分心,因此我在编辑器中只管我要写什么,当我写好 CSS 后,我就对内容如何呈现已经心中有数了,因此我认为「所见即所得」的功能没什么用。当然,如果你还是想要添加,相信对你而言也不是什么难事,毕竟方法之前的那位台湾小哥已经给出了。
如何快速实现 markdown 转 HTML 文档?的更多相关文章
- 无需编译、快速生成 Vue 风格的文档网站
无需编译.快速生成 Vue 风格的文档网站 https://docsify.js.org/#/#coverpage https://github.com/QingWei-Li/docsify/
- Markdown写接口文档,自动添加TOC
上回说到,用Impress.js代替PPT来做项目展示.这回换Markdown来做接口文档好了.(不敢说代替Word,只能说个人感觉更为方便)当然,还要辅之以Git,来方便版本管理. Markdown ...
- Sublime Text 3安装Package Control快速建立html5和xhtml文档
Sublime Text 3安装Package Control快速建立html5和xhtml文档 先关闭Sublime text 3:第1步:下载sublime_package_control-mas ...
- 使用 flow.ci 快速发布你的项目文档
软件研发的协作过程中,文档是必不可少的一环,有需求文档.接口文档.使用文档等等.当开始写文档时,首先会遇到两个问题: team members 之间如何协作? 文档 OK 后如何分发,去哪里看?如何更 ...
- 基于 Markdown 编写接口文档
最近公司开发项目需要前后端分离,这样话就设计到后端接口设计.复杂功能需要提供各种各样的接口供前端调用,因此编写API文档非常有必要了 网上查了很多资料,发现基于Markdown编写文档是一种比较流行而 ...
- 使用Spec Markdown 编写手册文档
Spec Markdown 是一个基于markdown 的文档编写工具,安装简单,可以让我们编写出专业的文档 参考项目 https://github.com/rongfengliang/spec-md ...
- 使用 VS Code + Markdown 编写 PDF 文档
背景介绍 作为一个技术人员,基本都需要编写技术相关文档,而且大部分技术人员都应该掌握 markdown 这个技能,使用 markdown 来编写并生成 PDF 文档将会是一个不错的体验,以下就介绍下如 ...
- Hi,给他介绍一款markdown的帮助文档生成器
当今大多数的团队都实现了前.后端分支.前端与后端的沟通都是通过接口来实现的(一般情况下都是webapi接口).这种情况你肯定需要一个接口查询的帮助文档,这个当然用swagger都可以实现.但做为前端开 ...
- Solr.NET快速入门(九)【二进制文档上传】【完】
二进制文档上传 SolrNet支持Solr"提取"功能(a.k.a. Solr"Cell")从二进制文档格式(如Word,PDF等)索引数据. 这里有一个简单的 ...
随机推荐
- rabbitmq - java client lib一二事
由于不可抗因素, 需要给对接方撸一个client的demo.基于比较老的jdk. 所幸找到了这里:http://www.rabbitmq.com/releases/rabbitmq-java-clie ...
- poj 2826
太自闭了...明明很水的说... 有三种为0的情况.一种是有水平,一种是没交点. 第三种有点难想啊.就是下面那个板子被上面的挡住了,,雨水进不去... 关键是我翻了翻discuss找到了这种数据,,但 ...
- 牛客练习赛39D
n,m<=5e4; 首先操作2用并查集就行了.题解说的好啊! 考虑操作一,连的两个点如果同色,直接合并,然后这个颜色的联通块-1,然后合并bitset,就是或一下.bitset维护的是相连的异色 ...
- PentestBox在win10里打不开工具
PentestBox详细安装过程:http://www.cnblogs.com/ESHLkangi/p/8336398.html 在使用PentestBox的时候出现了打不开工具的问题,最后看到一个老 ...
- vue里v-for下的key的作用
将v-for的元素赋予唯一的key属性,则会打破‘就地复用原则’: 这个就地复用原则是指 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确 ...
- Background removal with deep learning
[原文链接] Background removal with deep learning This post describes our work and research on the gree ...
- VS2013 Ctrl+Shift+F 没反应
快捷键设定与搜狗输入法中文繁体切换冲突,搜狗输入法管理设置中关掉就好.
- 我也来----xia bi bi 一下----微信小程序
工作刚到一阶段 就看了看微信小程序 自己做了个小dome 主要是为了让我女朋友能够学习做菜! 然而悲催的发现我根本没有App ID 不说快了 直接上图 个人感觉开发起来还是很简单的. 对着AP ...
- [No0000198]swagger api一键导入postman
在用postman进行接口测试时,对于参数较多的接口时第一次添加接口参数是比较繁琐的,可利用swagger一键导入api接口,事例如下: 1.获取swagger地址 2.打开postman,点击imp ...
- hive on spark配置
1.安装java.maven.scala.hadoop.mysql.hive 略 2.编译spark ./make-distribution.sh --name "hadoop2-witho ...