code-mirror块高亮
之前用code-mirror些了个便签, 最近又开始想复习找工作, 用起来还差点意思.
markdown比较适合写作, 用在”便签”系统, 在需要”给列表打钩”来表示完成状态的时候就没招了.
而我这复习列表正是需要给列表标注状态.
这里记录实现思路, 再结合上次存放图片的功能聊聊对decoration的认识.
需求和思路
与存放图片功能的类似, 希望选中一段文本, 快捷键操作让他改变背景颜色, 并且产生对应的标签语法, 因为毕竟在markdown环境中.
于是需求就拆分成了2个:
快捷键给选中的文本增加标签, 我这里暂定的是这样的标签:
#(数字)#(内容)$$
其中数字表示颜色序号.(这里我直接使用了标签的9个颜色主题, 他们是被仔细选过与文字颜色对比和谐的, 也已经处理过黑暗模式)
给有对应标签语法的文字背景样式.
实现
实现这2个功能都是通过extension.
keybinding
先来说keybinding, 我希望 cmd + 数字1~9 来触发, 但cm的keybinding只能指定按键, 于是就直接绑定9个按键.
1 | [1, 2, 3, 4, 5, 6, 7, 8, 9].map(i => getKeyBinding(i)) |
在getKeyBinding()
方法里返回一个KeyBinding
对象.
1 | const getKeyBinding: (i: number) => KeyBinding = (i) => { |
- 通过api获取到选中的文本
content
. - 判断文本
content
的情况, 对content
进行处理. - 通过api把修改的
content
插入会文本.
修改content
的情况分为这3种:
- 正则不命中, 则是普通文本, 那就在文本两侧加上标记.
- 通过正则取出”标记数字”如果和目标数字相同, 则取消标记.
- 如果和目标数字不同, 则把数字修改为目标数字.
通过标记语法修改背景颜色
插件的入口和插入图片的入口是一样的:
1 | const bgRenderer = ViewPlugin.fromClass(class { |
这是控制在初始化和更新的时候重新渲染decoration.
下面是decoration的主体部分:
1 | const createBgDecro = (view: EditorView) => { |
createBgDecro()
接受EditorView
参数, 获取当前文档内容, 返回一个decoration.
这里的decoration和extension一样, 可以返回数组, cm在处理的时候会先flatten.
RangeSetBuilder()
的作用就是最后返回[decoration, decoration, decoration], 上次做显示图片功能的时候就是直接返回的.
文档对decoration的介绍解释了不能直接操作dom, 是无效的, 要通过decoration来改变样式或者增加一些表现.
decoration类是继承于rangeValue类的, 所以decoration必须会有range信息, 再根据不同的decoration类型有一些额外的属性.
decoration的类型都是由decoration的静态方法创建的. 我们这里用到了mark
, 是给指定的range加上一些attr.
之前显示图片功能用到的是widget
, 因为图片需要增加dom, 光修改样式不够.
加载
我们把2个写好的extension加载到配置里就完成了.
1 | export const blockbg = [bgRenderer, keymap.of([1, 2, 3, 4, 5, 6, 7, 8, 9].map(i => getKeyBinding(i)))] |
1 | let startState = EditorState.create({ |
(本文完)
如果你可以 点击这个链接打赏我5毛,对我的鼓励比500块还多很多
本文遵循 cc协议
你可以在注明出处和非商用的前提下任意复制及演绎