逑识

吾生也有涯,而知也无涯,以无涯奉有涯,其易欤?

0%

Markdown Nice:文章排版利器

导语」 你是否也在寻找这样一种写作工具?它需要基于 Markdown,同时它还应兼具文章排版,文章预览以及个性化定制等各种功能,没错,它就是 Markdown Nice,绝对堪称文章排版的利器,可以为你省去绝大部分排版相关工作,让你更加专注于内容本身。另外你还可以通过魔改其源码来实现你独特的个性化需求,快来尝试吧!

Markdown Nice 介绍

Markdown

  1. Markdown 是一种用来写作的轻量级标记语言,它拥有简洁的语法,支持引用,链接,图片以及代码段等常用的写作格式。

  2. 使用 Markdown 进行写作可以让我们更专注于内容本身,而不用花费太多时间和精力去关心诸如文章格式,字体大小等繁杂设置,另外 Markdown 的学习成本极低,基本上稍加学习即可掌握大部分常用的语法。

  3. 但是基于 Markdown 进行写作,方便有余,美观却是不足,而且一些网站本身并不支持 Markdown 格式的写作内容,使得 Markdown 文章的发布与分享有了不小的阻碍。

  4. 使用原生 Markdown 工具(这里为印象笔记)的文章渲染图如下所示:

    Markdown 工具渲染-印象笔记

Markdown Nice

  1. Markdown Nice 顾名思义,就是为了使得 Markdown 的内容更加美观,更加具有平台普适性而产生的排版工具。

  2. 它可以使用多种主题来渲染 Markdown 的内容,给朴实无华的 Markdown 内容带来了诸多色彩,更为重要的是,它支持一键将富文本内容复制到其它平台,大大减少了创作者在各个平台进行内容排版所要花费的人力和时间成本

  3. Markdown Nice 是使用 Markdown 进行写作输出的一个有力补充,给内容创作者带来了诸多方便,更为难得的是,该工具已经开源并托管于 Github ,这也就意味着使用者可以更加自由地进行源码修改以满足自身需求,为 Markdown Nice 的作者点个大赞。

  4. 使用 Markdown Nice 的文章渲染图如下所示:

    Markdown Nice 渲染

通过渲染图的对比,我们可以发现,使用 Markdown Nice 渲染的文章其美观程度明显更胜一筹,你是否已经心动了呢?

那么如何才能使用 Markdown Nice 呢?很简单,只要打开 https://mdnice.com/ 网站,然后将 Markdown 内容拷贝到左侧区域,即可在右侧区域中看到渲染后的内容,接着就可以将渲染后的内容一键拷贝到 Markdown Nice 所支持的各个平台进行发布了。

Markdown Nice 的主界面如下图所示:

Markdown Nice 主界面

Markdown Nice 功能介绍

Markdown Nice 的主要功能是对 Markdown 内容进行美化渲染。访问其官方网站可以看到一篇示例文章,里面详细地介绍了 Markdown Nice 目前所支持的各种基本功能。下面我来对其中一些较为常用的功能进行简要介绍与说明:

图床功能

  1. 图床是进行写作时必不可少的图片存储工具, Markdown Nice 提供了免费的图壳图床以供使用,基本上可以满足在各个平台发布文章的需要。

  2. 不用担心图片持久访问的问题,因为在将文章发布到各个平台之后,图片会直接上传到各平台自己的服务器,文章内的图片链接也会相应改变。也就是说即使图壳图床某天停止服务了,也不影响其它平台上的图片显示。因此可以将图壳图床作为一个图片中转站,它可以有效地减少我们在各个平台分别进行图片上传的繁琐操作,大大提高文章发布的效率。

  3. 当然如果是个人博客使用,最好还是选择一个更为稳定的付费图床,如阿里云、腾讯云以及七牛云(目前有免费额度)等,这样可以更好地进行维护与管理。

  4. 使用付费图床的另一项好处是它们都提供了图片处理的接口,可以很方便地进行图片裁剪,图片瘦身等操作,在内容平台对图片大小有限制时,我们可以方便地调用这些接口对图片进行处理以满足平台要求。更为重要的是它们的图片压缩算法在提供高压缩比的同时还保证了图片的质量,肉眼基本上看不出处理后的图片与原图明显的差别,这是其它一些图片压缩工具所做不到的。

主题功能

  1. Markdown Nice 提供了 10+ 种不同风格的主题来任你选择。可以在 https://mdnice.com/ 页面通过切换文章主题来查看相应的渲染效果,或者在 https://product.mdnice.com/themes/ 直接查看所有主题的预览结果。主题预览网站如下图所示:
    主题预览

  2. 另外对于代码的排版, Markdown Nice 同样提供了多种代码主题来对代码进行高亮显示。同时为了提升代码逼格,它还提供了 MAC 风格的 UI 样式渲染,可以与其他代码主题组合使用。

  3. 如果你不满足于已有的主题样式, Markdown Nice 还为你提供了自定义主题的功能,通过修改 CSS 代码来达到想要的效果,不过前提是你需要有一定的 CSS 基础。

  4. 使用自定义主题可以实现对 Markdown Nice 的渲染内容进行更加精细化地控制,比如标题样式,图片样式以及字体样式等。在设计自定义主题时,可以参考已有主题的实现,借鉴它们的 CSS 样式并在此基础上进行修改,这样会更加高效。

外链转脚注功能

  1. 对于一些平台,如微信公众号,仅支持公众号文章的互相链接,对于外部链接是不支持的。 Markdown Nice 提供了一种将外部超链接转为文章脚注的功能,它会将超链接内容以参考资料的形式显示在文章的末尾。

  2. 外链转脚注功能默认开启,在编写 Markdown 文件时,需要使用带 title 的超链接格式 [content](url "title") 来表示引用才能将其转为脚注,其中 content 为链接的文字, url 为链接地址, title 为内容标题,它会作为名称显示在参考资料中。

  3. 另外,使用该方法还可以自动在 content 处添加上标编号以指明所引用的参考资料。

原生 HTML 支持功能

  1. Markdown 内容有时可能不能满足我们自定义的需求,比如我们想在文章底部加入引导关注的内容,仅依赖 Markdown 语法很难实现,此时就需要借助 HTML 语法来完成。

  2. Markdown Nice 支持原生的 HTML 渲染,可以在定义好 HTML 内容后,直接将该内容拷贝到文章相应的位置即可,进一步满足了个性化定制的需求。

  3. 需要注意的是在使用原生 HTML 时,最好先将其压缩后再加入到 Markdown 内容中,这样可以避免一些潜在的格式问题。比如在 Markdown Nice 中可以正确地渲染,但是拷贝到公众号中渲染格式会出现一些错乱。

  4. 另外,最好使用行内 CSS 样式,避免因全局主题样式的修改而影响了自定义 HTML 的显示。

其它功能

  1. 多平台复制功能:目前 Markdown Nice 仅支持微信公众号,知乎以及掘金三个平台,未来可能会支持更多的平台,有赖于社区成员的共同努力。

  2. 导出 PDF 功能:可以将 Markdown Nice 渲染后的内容保存为 PDF 文件,以供分享以及打印使用。需要注意的是,在导出前最好将预览模式设置为桌面模式,这样保存的 PDF 内容才能更好地适配 A4 页面。

  3. Latex 公式功能:Markdown Nice 可以支持行内公式以及块级公式的渲染,对于喜欢使用 Latex 公式进行内容输出的用户来说是一大福音。

  4. 更多丰富的功能有待你自己去进一步探索!

文章排版

在使用 Markdown Nice 进行文章渲染时,一些排版技巧可以让文章看起来更加美观、更易阅读。下面简要介绍下我个人认为较为实用的一些文章排版技巧,因为大家的偏爱各有不同,所以以下内容仅供参考,Enjoy

字体

  1. 字体大小要适当,正文字体以 16px (font-size: 16px) 为宜,文章标题字体应大于正文字体并适当加粗 (font-weight: bold)。

  2. 正文中字体的颜色不宜过多,一般 1-3 种为宜 (font-color: #000) ,或者选择几种相近的颜色进行搭配。可通过中国传统颜色手册来挑选自己喜欢的主题颜色,本文主题颜色为杏红

  3. 适当使用斜体以表示强调 (*强调的内容*)。

间距

  1. 段落的对齐方式最好选择两端对齐 (text-align: justify),这样会显得比较整齐,不会出现犬牙交错的情况。

  2. 字间距要适当,保持正常状态或 1px 即可 (word-spacing: 0px)。

  3. 行间距不能过宽也不能过窄,一般以 1.75 为宜 (line-height: 1.75)。

  4. 中英文之间最好留出一个空格,阅读体验会更好。

  5. 使用 word-break: break-all 来对行内的单词断句,避免出现行内留白或者某个单词独占一行等情况。

  6. 段落之间最好空出一行,读起来不会显得过于拥挤。

  7. 每段的首行无需缩进,缩进会影响段落的整齐度,而且对于移动端阅读并不友好。

  8. 标题与内容的间距,图片与标题的间距,有序/无序列表的间距要适当,不要过于拥挤,这些都可通过 marginpadding 等样式来进行调整。

图片

  1. 封面图的主要内容要居中,分享时不至于被截断。

  2. 适当地在正文中引入图片以说明相关问题,引导读者阅读。

  3. 将图片进行圆角化处理,显得不那么方正,但也不要过于圆润,以 5px 为宜 (border-radius: 5px)。

  4. 图片的标题要使用小字号的字体,并且将其颜色设置为浅色。

代码与参考资料

  1. 代码要提前在 IDE 中使用特定的规则进行格式化,然后再加入到 Markdown 文章的代码段中,以便于阅读。

  2. 代码段的高度要进行限制,避免代码行数过多时占据大量的阅读空间,可以通过滚动条的方式来呈现。

  3. 参考资料部分的高度同样要进行限制,可以让读者自行在区域内滑动以查看相应的资料,避免占据大量文章篇幅。

  4. 若要实现滚动条效果,首先需要指定块级元素的最大高度 (max-height: 600px),当内容超过此高度时会自动截断,然后再设置元素的溢出属性为滚动 (overflow: scroll) ,以便在内容超出最大高度时显示滚动条。

深色模式适配

  1. 为了在深色模式下获得沉浸式的阅读体验,最好不要使用全文背景图或背景色,它们在深色模式下会显得比较突兀。

  2. 尽量使用 CSS 来实现样式,减少底色图片(引导阅读的通栏图片除外)的使用,这样可以更好地与暗黑模式适配。

  3. 小图标最好使用 png 无底色图片,并且要与全文的主题颜色相搭配,可以通过 iconfont 网站查找与下载相应的图标。

魔改 Markdown Nice

一般情况下, Markdown Nice 提供的功能已经能够满足大部分的排版需要,但在有些方面还是不够智能与自动化。

比如我希望当我写完一篇 Markdown 文章后, Markdown Nice 可以替我做全部的样式排版工作,包括自动编号,自动添加引导关注等操作,这样我就不用手动去逐个添加和修改了,我唯一需要做的就是将渲染后的内容直接拷贝一键发布即可。

而为了实现上述自动化流程,普通的样式设置已经无法完成,此时就需要去修改 Markdown Nice 的源码以满足个性化的需求。

源码解读

在修改 Markdown Nice 的源码之前,我们必须首先对其处理流程有个大概的了解。总体来说, Markdown NiceMarkdown 内容的处理流程可分为如下几步:

  1. 首先,当我们把 Markdown 内容拷贝到页面的左侧之后,它会利用 markdown-it 工具将 Markdown 内容转换为相应的 HTML 内容,如 ## title 会被转为 <h2><span class="prefix"></span><span class="content">title</span><span class="suffix"></span></h2>**content** 会被转换为 <strong>contetn</strong> 等。

  2. 然后它会使用预定义的 CSS 样式(即文章主题)将转化后的 HTML 内容渲染到页面的右侧并呈现给我们。

  3. 接着当我们点击一键复制后,它会利用 juice 工具将 HTML 内容的全局 CSS 样式转为行内 CSS 样式,并将转换后 HTML 内容复制到剪切板。

  4. 最后我们将剪切板的内容黏贴到文章发布平台即可看到最终的渲染效果。

了解了 Markdown Nice 的处理流程之后,当我们需要添加新的功能代码时,就能够很容易地判断应该从哪个部分入手。但仅了解整体的处理流程显然是无法完成修改工作的,我们还需要进一步了解 Markdown Nice 的页面布局与结构,这样才能根据各组件的响应函数来确定最终所要修改代码的实际位置。

Markdown Nice 主要是基于 React 进行编写的,整体是一种模块化的布局方式。该项目 src 目录下的 App.js 是程序的主入口,通过代码中的 render 函数我们可以了解到该页面的整体布局。

页面中的每个模块都是以组件化的形式表示的,比如最上方的导航栏为一个 Navbar 组件,而该导航栏组件又是由各个子组件组成的,如文件组件 (File),主题组件 (Theme) 等。了解了各个组件在代码中位置后,我们就可以通过组件的点击响应函数来按需修改代码以满足定制化的需求了。

另外在代码修改的过程中,我们可以通过 console.log() 函数打印相关信息来辅助我们进行代码调试。

标题自动编号

对于 HTML 格式的内容,我们可以通过设置 H 标签元素的 counter 属性来对实现文章标题的自动编号。这种自动编号的方式在 Markdown Nice 中可以正常显示,但是拷贝到其它平台则不可以,因此需要我们修改代码来实现该功能。

为何拷贝到其它平台就不显示了呢?这与 juice 的工作原理有关,一般而言, counter 属性会用在 ::before 伪元素上,而 ::before 伪元素在 juice 转换的过程中会被转为 <span> 元素,它只保留了元素内容,而失去了计数的功能,所以当我们将内容拷贝到其他平台后只会在相应位置显示 counter 字样而无法显示具体的编号。

为了给标题自动编号,根据上面对 Markdown Nice 处理流程的分析,我们可以考虑从 markdown-it 转换后的 HTML 内容着手来解决该问题。

首先我将转换后的 HTML 内容通过 JS 重新解析为 DOM 树,然后遍历该 DOM 树的所有的子元素来分别给 H1-H6 标签进行编号,这里默认所有的 title 都是以 H 标签进行呈现的,最后将这部分代码放置于主题切换的响应函数中来控制不同主题的编号渲染。示例代码如下所示:

const doc = new DOMParser().parseFromString(html, "text/html");
const inner = doc.body.children;
// H1-H6 init index
const hAarray = [1, 1, 1, 1, 1, 1];
// H1-H6 position in array
const hMap = { H1: 0, H2: 1, H3: 2, H4: 3, H5: 4, H6: 5 };
for (const item of inner) {
const name = item.tagName;
if (name in hMap) {
const num = hAarray[hMap[name]];
const numStr = num < 10 ? "0" + num : num;
const prefix = item.getElementsByClassName["prefix"](0);
if (prefix !== undefined) {
prefix.innerHTML = numStr;
}
hAarray[hMap[name]]++;
for (let i = hMap[name] + 1; i < hAarray.length; i++) {
hAarray[i] = 1;
}
}
}

使用 markdown-it 工具转换后的 HTML 文件中,所有的 H 标签均由三个部分组成,分别为 prefixcontentsuffix 。默认情况下,只有 content 部分有内容,表示标题,其它两个部分都是闲置的,没有内容。因此,在上述代码中,我将生成的编号分配给了 prefix 部分,既利用了闲置资源,又将编号与内容分离开来,以便于分别调整编号和内容的 CSS 样式来满足不同的页面渲染需要。

另外编号的样式也可以根据个人需求来定义,比如二级编号既可以是 01, 02, 03 也可以是 1.1, 1.2, 1.3 等等,利用上述代码按需实现即可。

自动插入 HTML 内容

对于签名以及引导关注这类原生的 HTML 内容,我希望 Markdown Nice 可以直接将其添加渲染的结果中,而无需我手动添加。

为了解决上述需求,同样可以从转化后的 HTML 内容入手,首先将 HTML 内容解析为 DOM 树,然后找出指定元素的位置,并在该位置前/后添加新的 HTML 内容。

比如我想在导语引用的下面加入签名的内容,如下图所示:

导语引用下的签名

那么我需要获取导语引用的位置,然后将签名的 HTML 内容加入到该元素之后即可,注意这里引用是以 blockquote 标签的形式存在的。其代码如下所示:

const { body } = new DOMParser().parseFromString(html, "text/html");
const blockquotes = body.getElementsByTagName("blockquote");
const signNode = blockquotes[0];
if (signNode !== undefined) {
signNode.insertAdjacentHTML("afterend", sign);
}

其它静态 HTML 内容的添加与上述过程类似。比如在文章最后的引导关注内容,可以使用如下代码进行自动添加:

body.insertAdjacentHTML("beforeend", guide);

其中 signguide 都是压缩后的 HTML 内容,它们均以 js 字符串的形式加入到 DOM 树中。

参考资料自定义

Markdown Nice 默认可以将超链接转为脚注,但是有时我只想标明参考资料,而不想将其指定为某个内容的引用。或者文章中多处都引用到了这个资料,我不想将其标记多次,此时就需要一种全局的引用方式,这样我只需将所有的参考资料列出并置于文章末尾即可。

我的做法是先将所有的参考资料放在一起并以超链接的形式给出,让 Markdown Nice 将其转为相应的脚注,然后再将包含那部分超链接的 HTML 内容从整体的 DOM 树中删除,这样既利用了 Markdown Nice 自动转脚注的功能,又不会使得相同的内容重复显示。示例代码如下所示:

if (
referenceNode !== undefined &&
referenceNode.innerHTML.search("参考资料") !== -1
) {
const referenceNextNode = referenceNode.nextElementSibling;
if (referenceNextNode.tagName === "OL") {
referenceNode.remove();
referenceNextNode.remove();
}
}

通过上述魔改过程可以看到,我所有的魔改操作都是围绕转化后的 HTML 展开的。因此如果你也有更深层次自定义的需要,同样可以通过这种方式来完成。另外,由于魔改后的内容并不适用于所有的主题,所以如果你想为该项目提交 pull request ,要注意你的修改内容不会对其它主题的样式产生影响。

VSCode 相关插件

如果你正在使用 VSCode 进行 Markdown 写作以及 HTML 文件编辑,那么下面这些扩展插件可能会对你有很大的帮助。

  1. Markdown All in OneMarkdown 写作利器,可以进行有序列表自动编号,自动添加表格等各种操作,大大简化了我们的 Markdown 写作流程。

  2. markdownlint:用来对 Markdown 文档做格式化检查,以使得文档内容符合 Markdown 语法规范,另外它还可以进行 Markdown 文档的自动格式化操作,免去了手工调整的苦恼。

  3. Pangu-Markdown:是一个对 Markdown 文件中的中英文混排内容进行格式化的插件,比如可以自动在中英文之间添加空格等。

  4. MinifyAll:它是一个对 HTMLCSS 以及 JavaScript 等文件进行压缩的工具。对于自定义的原生 HTML 内容,可以使用该工具压缩后,再加入到 Markdown Nice 中以得到正确的展示。

  5. Draw.io Integration:它是 draw.ioVSCode 中的实现,也就是说你现在可以在 VSCode 中直接画流程图了,该插件基本包含了绝大多数 draw.io 的画图功能,非常方便。

参考资料

  1. 认识与入门 Markdown
  2. Markdown Nice 开源地址
  3. 终于等到你,公众号排版神器
  4. Markdown Nice 浏览器插件
  5. Markdown Nice 主题列表
  6. 中国传统颜色手册
  7. iconfont
  8. markdown-it
  9. juice

欢迎关注我的其它发布渠道