目录

前言:我的编程成果

编程中遇到的挑战

为什么要做这个编辑器?

最后:我的的想法


前言:我的编程成果

目前在写作的世界里,已有许多优秀精致的 Markdown 编辑器横空出世,比如大名鼎鼎的 Ulyless、Bear、MarkEditor、MWeb、Typora 等等。

然而作为一个编程新手,你可能想要尝试做一个完全属于自己、适合自己的 Markdown 编辑器。

随心所欲、私人定制的背后总是有着无数的坑,你必须跳下去。😂

在花费了一周的时间之后,我终于创造了我的 「Markdown 编辑器 01 版」。在这个过程中,我不断地经历着编程的错误百出以及需求的失败与变更,希望通过我的介绍可以帮助你了解这个过程。其中实现的功能:

  • Markdown 预览
  • 代码高亮
  • 设置 CSS 属性
  • 输入 CSS 语句
  • 响应式布局
  • 本地存储
  • 生成 PDF

当然也有最终没有实现而被替换的功能:

  • 选择 CSS 模板❎
  • 生成图片❎
自制 Markdown 编辑器

编程中遇到的挑战

以下部分,正文就开始了。

Markdown 预览

如果利用原生 JavaScript 语言,可能需要不断进行 # hello world <h1>hello world</h1>```my  code``` <pre><code>my code</code><pre>之类的替换。为了减少这个重复的过程,利用现有轮子,我使用了 marked.js 这个成熟的库,帮助我简化代码。

html_area.innerHTML = marked( markdownArea.value,  { sanitize: true } )

代码高亮

当大家使用那些已经商业化的编辑器时,它们均内置了代码高亮这个功能。然而它并不是原生 Markdown 就具备的。在自制 Markdown 编辑器中,即使你已经在第一行说明了代码语言类型,它依然无法起效,代码仍然默认为黑色。

```javascript
console.log( [ 'a', 'b', 'c' ] )
```

有一个最简单的方法,就是直接在 CSS 中宣称代码的颜色。请注意观察下图右侧代码的颜色。⚠️

code { color: red; }
代码颜色为红色

然而,它只是通过颜色区别设置将代码部分与正文文字分开,并未实现我们真正需要的代码高亮。

我的解决办法是导入 highlight.js这个代码高亮库及其配套的 CSS 库。由于 HTML 其实是动态生成的,所以必须设置相应的事件监听器,保证其高亮的代码部分可以及时刷新、更新。

 html_area.querySelectorAll( 'code' ).forEach( ( block ) => {                
    hljs.highlightBlock( block );           
 });

最后看实现的效果,是不是还不错?

实现代码高亮功能

设置 CSS 属性

在大多数 Markdown 编辑器的设置部分,用户可以自动调整一些基础样式,比如字体、行高等等。当任意改变一个滑动条时,文章内容的样式改变会即刻生效。

Bear 设置 - 编辑器

如果没有设计 CSS ,那么整个页面基本就是黑白两色了。

无 CSS 样式绑定的 Markdown 预览
有 CSS 样式绑定的 Markdown 预览

要如何实现多样化的CSS 属性定制呢?

首先你需要利用 CSS3的变量功能,设置一些基础的可调节变量,如paddingweightheightfont-sizecolorbackground-color等。在设置这边变量的同时,也要设定它们的默认值哦。更重要的,将它们与相应的 input 联系在一起。

:root { 
--padding : 10px;           
 --width : 100%;          
--font-size : 16px;            
--color: #336699;  
}
<input  type="number" name="padding"  value="10" data-sizing="px">

最后一步,就是利用 JavaScript 将这些改变生效1 。

function handelControl() {            
    const suffix = this.dataset.sizing || '';            
    document.documentElement.style.setProperty( `--${ this.name }`,  this.value + suffix );           
}
inputs.forEach( input => input.addEventListener( 'change', handelControl ))

输入 CSS 语句

为什么我没有选择导入 CSS文件呢?当然是由于这个需求我实现不了啊😡。我只能退而求其次了,让用户可以输入自己的 CSS 语句,或者复制粘贴也可以啊。
我来简单说一下我在导入文件这个过程中遇到的困难。
input 导入文件 -> 获取文件地址 ->  插入到 link ->  CSS 文件生效
多么完美顺利的流程啊,然而我失败了。
input 导入文件 -> 获取文件地址 ❌

为什么呢?原来是因为为了阻止恶意软件猜测文件路径,路径字符串以C:\fakepath\为前缀2 没有真实路径,我怎么让用户导入CSS 文件呢?所以,就让用户直接在文本输入框输入 CSS语句吧。

稍等,我有两个灵感冒出来了。
💡 可以让用户输入一个CSS 文件的网络链接啊,这样就可以插入到 <link>
💡 或者设计几套 CSS 文件,用户使用时把它们的相对路径插入到 <link>

响应式设计

在平板、甚至电脑屏幕上,我选择了三列式的设计,从左到右分别是设置区域、Markdown 区域、HTML 区域。这样可以最大限度地利用宽屏空间。

然而,在手机页面,我选择了自上而下的三行式布局,这很明显是因为手机屏幕宽度不够。另外,大多数人在手机上的操作为上下滑动。这样也是符合了用户交互的原则吧。

 @media  screen and (max-width: 500px) {            
    div#app {                
        display: grid;                
        grid-template-rows: repeat(3,1fr);            
    }        
}    

本地存储

由于这个「自制 Markdown 编辑器」本质上只是一个 HTML 文件,为了方便测试过程,保存 CSS 语句、Markdown 语句等,我设置了本地存储功能。因此在下次加载过程中,不需要重新输入内容,大大提高开发效率,或者说提高了用户满意度。毕竟,好不容易设计的 CSS 我可不想一下子没了。😉

localStorage 本地存储

生成 PDF

为什么我没有生成图片呢?因为我没有找到一个合适的方法将创建的 HTML 生成图片。所以我只能另辟蹊径,利用window.print()功能生成一份 PDF。

print 选项

看起来不错吧。但这功能背后也有很多挑战。这可一点也不容易啊,30行 JavaScript 代码,花费了我2天的时间,还是靠我的灵机一动呢🌟

  • 新建一个窗口文档(难度⬆️,灵机一动⬆️⬆️)
  • 导入其 HTML内容
  • 导入动态滑动条的 CSS 变量属性(难度⬆️,灵机一动⬆️⬆️⬆️)
  • 导入已输入的 CSS 语句
  • 创建导入 highlight.js 代码高亮


为什么要做这个编辑器

如果有编程新手练习 Vue 前端框架。那么就会有一个学习案例:简易 Markdown 编辑器。这个案例很简单,只用到了几行 Vue 语句。

Vue 学习案例

如果大家尝试过 Text2Image这款软件,它的主要功能是:将输入的 Markdown 文件最终转换成图片保存。对我而言要实现这个比较困难,开发者主要利用 Python、jinja 进行编程。

Text2Image操作界面

所以作为一个折衷的想法,我尽自己所能,用前端三剑客 HTML、CSS、Javascript 完成了部分编程需求。


最后:我的想法

说实话,编程比我想象的更加困难,但是有了目标,有了方向,完成第一步总比永远没有出发好太多,也厉害太多。所以争取做一个厉害的人吧!👑