自己动手开发更好用的markdown编辑器-07(扩展语法)
2015-05-20 13:37
756 查看
这里文章都是从个人的github博客直接复制过来的,排版可能有点乱. 原始地址 http://benq.im/2015/05/19/hexomd-07/
文章目录
1. 准备工作
2. 目录语法
3. emojis表情语法
3.1. 准备表情素材
3.2. 实现功能
4. 编辑器语法高亮
5. 总结
6. 附件
上一篇我们实现了
在前面的6篇中,我们基本没做什么创造,都只是像玩乐高那样把零件拼接成我们想要的东西.
今天这篇将对
以及改造
对于不想看如何实现的朋友,直接下载v0.6.0.2,然后点击右上角的更新按钮更新到最新版即可.
将我们fork的版本clone到本地,打开lib/marked.js.所有代码都在这个文件里.
修改
修改
修改
修改
最后是修改
这样目录语法就完成了,没几行代码,效果如图(预览的样式比较丑,这系列的某一篇会专门优化预览样式):
我将这里所有表情上传一份到我的七牛空间里,这样访问会快一些.
修改
为
最后,在
完成!这个功能比目录功能更加简单
我们直接简单粗暴的修改lib/codemirror/mode/markdown/markdown.js.
增加toc和emoji的正则:
在
这样就搞定了,编辑器会为匹配到的代码加上相应的class
有了,class,就可以在样式修改自定义语法的高亮显示了,比如我现在用的样式文件mdn-like
打开这个样式文件,加上样式:
现在这些语法在编辑器里有独特的高亮效果了:
增加语法关键词的匹配正则.
在
在
接下来的计划:
导出pdf,html文件.
美化预览样式.
项目地址
文章目录
1. 准备工作
2. 目录语法
3. emojis表情语法
3.1. 准备表情素材
3.2. 实现功能
4. 编辑器语法高亮
5. 总结
6. 附件
上一篇我们实现了
自动更新的功能.
在前面的6篇中,我们基本没做什么创造,都只是像玩乐高那样把零件拼接成我们想要的东西.
今天这篇将对
marked进行简单扩展, 增加我们的markdown编辑器支持的语法,实现
目录,
emojis表情两种新语法.
以及改造
codemirror,实现我们自定义语法的编辑器高亮显示(这个本来是要放到下一篇,但是刚刚做完后发现内容很短,所以就又合并到这篇里来了).
对于不想看如何实现的朋友,直接下载v0.6.0.2,然后点击右上角的更新按钮更新到最新版即可.
准备工作
首先打开marked,Fork一份到自己仓库. 对marked的改造都将基于我们的这个fork版本.目录语法
功能描述: 自动提取所有H标签,形成目录树,在解析markdown文本时,如果遇到[TOC]标签则自动将其替换为目录.
将我们fork的版本clone到本地,打开lib/marked.js.所有代码都在这个文件里.
修改
inline.gfm,增加目录语法匹配正则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * GFM Inline Grammar */ inline.gfm = merge({}, inline.normal, { escape: replace(inline.escape)('])', '~|])')(), url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, del: /^~~(?=\S)([\s\S]*?\S)~~/, toc: /\s*\[TOC\]/, text: replace(inline.text) (']|', '~]|') ('|', '|https?://|') () }); |
Renderer,增加
toc和
tocItem两个方法,用于生成目录标签:
1 2 3 4 5 6 7 8 9 10 | Renderer.prototype.toc = function (items) { var html = '<div id="toc" class="toc"><ul class="toc-tree">'; html += items; html += '</ul></div>'; return html; } Renderer.prototype.tocItem = function (id, level, text) { return '<li class="toc-item toc-level-' + level + '"><a class="toc-link" href="#' + id + '"><span class="toc-number"></span> <span class="toc-text">' + text + '</span></a></li>'; }; |
Renderer的
heading方法,为其赋予id作为点击目录项的锚点
1 2 3 4 5 6 7 8 9 | Renderer.prototype.heading = function(text, level, raw) { var escapedText = text.toLowerCase(); return '<h' + level + '><a name="' + escapedText + '" class="anchor" href="#' + escapedText + '"><span class="header-link"></span></a>' + text + '</h' + level + '>'; }; |
Parser.prototype.parse,在解析时预生成好目录标签备用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * Parse Loop */ Parser.prototype.parse = function (src) { var me = this, tocItems = ''; //预生成好目录标签 src.forEach(function (token) { if (token.type == 'heading') { id = token.text.toLowerCase(); tocItems += me.renderer.tocItem(id, token.depth, token.text); } }); this.inline = new InlineLexer(src.links, this.options, this.renderer); this.inline.tocHTML = me.renderer.toc(tocItems); this.tokens = src.reverse(); var out = ''; while (this.next()) { out += this.tok(); } return out; }; |
InlineLexer,在匹配到
[TOC]时将其替换为完整的目录标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * Lexing/Compiling */ InlineLexer.prototype.output = function(src) { var out = '' , link , text , href , cap; while (src) { //toc语法 if (cap = this.rules.toc.exec(src)) { src = src.substring(cap[0].length); out += this.tocHTML; continue; } ... } |
emojis表情语法
准备表情素材
我将要实现的emoji表情库基于http://www.emoji-cheat-sheet.com/这个项目,大家可以通过这个页面查看所有表情的命名.
我将这里所有表情上传一份到我的七牛空间里,这样访问会快一些.
实现功能
emojis语法的实现跟目录类似.
修改
inline.gfm,增加emojis语法匹配正则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * GFM Inline Grammar */ inline.gfm = merge({}, inline.normal, { escape: replace(inline.escape)('])', '~|])')(), url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, del: /^~~(?=\S)([\s\S]*?\S)~~/, emoji: /^:([A-Za-z0-9_\-\+]+?):/, toc: /\s*\[TOC\]/, text: replace(inline.text) (']|', ':~]|') ('|', '|https?://|') () }); |
Renderer增加
emoji方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Renderer.prototype.emoji = function (emoji) { //图片使用自己的七牛空间 return '<img src="' + 'http://7xj6bw.com1.z0.glb.clouddn.com/' + encodeURIComponent(emoji) + '.png"' + ' alt=":' + escape(emoji) + ':"' + ' title=":' + escape(emoji) + ':"' + ' class="emoji" align="absmiddle" height="20" width="20">'; }; |
InlineLexer里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * Lexing/Compiling */ InlineLexer.prototype.output = function(src) { var out = '' , link , text , href , cap; while (src) { ... // emoji (gfm) if (cap = this.rules.emoji.exec(src)) { src = src.substring(cap[0].length); out += this.renderer.emoji(cap[1]); continue; } ... } |
编辑器语法高亮
这里就不再去fork codemirror这个项目了,有兴趣的可以去fork,修改完后提交给官方.我们直接简单粗暴的修改lib/codemirror/mode/markdown/markdown.js.
增加toc和emoji的正则:
1 2 3 4 5 6 7 8 9 10 | ... , toc = 'toc' , emoji = 'emoji' .. .. var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/ , ulRE = /^[*\-+]\s+/ , olRE = /^[0-9]+\.\s+/ , taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE , atxHeaderRE = /^#+/ , tocRE = /\[TOC\]/ , emojiRE = /^:([A-Za-z0-9_\-\+]+?):/ .. |
blockNormal方法里为匹配到的标签返回独立的class:
1 2 3 4 5 6 7 | ... } else if(match = stream.match(tocRE)){ return toc; } else if(match = stream.match(emojiRE)){ return emoji; } ... |
有了,class,就可以在样式修改自定义语法的高亮显示了,比如我现在用的样式文件mdn-like
打开这个样式文件,加上样式:
1 2 3 4 5 6 | .cm-toc{ background:#ccc; } .cm-emoji{ color:#F7A21B; } |
总结
通过两个自定义语法的实现,我们可以总结出自定义语法的一般步骤:增加语法关键词的匹配正则.
在
Renderer里增加相应的标签生成方法.
在
InlineLexer里处理匹配到的语法.
接下来的计划:
导出pdf,html文件.
美化预览样式.
附件
v0.6.0.2项目地址
相关文章推荐
- 自己动手开发更好用的markdown编辑器-05(粘贴上传图片)
- 自己动手开发更好用的markdown编辑器-04(实时预览)
- 自己动手开发更好用的markdown编辑器-06(自动更新)
- 自己动手制作更好用的markdown编辑器-02
- 自己动手制作更好用的markdown编辑器-03
- 自己动手制作更好用的markdown编辑器-01
- atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结
- atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结
- CSDN-markdown编辑器语法
- SAP 开发陷阱一箩筐(07)——新版编辑器中的查找功能哪去了
- 自己动手开发智能聊天机器人完全指南(附完整源码)
- 自己动手打造嵌入式Linux软硬件开发环境
- 自己动手用C扩展PHP(三)
- markdown编辑器语法——文字颜色、大小、字体与背景色的设置(转)
- 自己动手开发jQuery插件全面解析 jquery插件开发方法(这个写的还可以,但不够细致)
- 自己动手开发emlog插件
- 由浅入深:自己动手开发模板引擎——置换型模板引擎(二)
- 自己动手用C扩展PHP(三)
- 自己动手“数据恢复编程、数据恢复软件开发”- NTFS扫描恢复通用库
- 自己动手开发一个Xcode插件