公司里前任前端同事做了个笔记功能,3000+行代码纯手写的,改了 mark.js 里的逻辑使其适配

我一直维护着….有一天终于得到了机会重写,就找到了它,一个很牛逼的库。

文档

文档在 github 的 wiki 页面里

安装

import rangy from 'rangy' // rangy-core.js
import 'rangy/lib/rangy-classapplier.js'
import 'rangy/lib/rangy-serializer.js'
import 'rangy/lib/rangy-selectionsaverestore.js'
import 'rangy/lib/rangy-highlighter.js'
import 'rangy/lib/rangy-textrange.js'

// 初始化 Rangy
// 执行了好像才会完全引入,不执行就会缺方法
rangy.init()

使用心得

// 高亮实例
const highlighter = rangy.createHighlighter(null, 'TextRange')

// 填充器实例
const applier1 = rangy.createClassApplier('highlight-orange', {
  elementTagName: 'mark',
  onElementCreate: (markEl, classApplier) => {}
})
const applier2 = rangy.createClassApplier('highlight-red', {
  elementTagName: 'mark',
  onElementCreate: (markEl, classApplier) => {}
})

// 往高亮实例里注册填充器
highlighter.addClassApplier(applier1)
highlighter.addClassApplier(applier2)

// 高亮选区
highlighter.highlightSelection('highlight-orange', {
  containerElementId,
  // 选区冲突时,是否覆盖合并
  exclusive: true
})

/**
 *  获取序列化数据,持久存储
 *  序列化数据当然也可以自己拼出来,后端存 start 和 end,后端返回的数据后拼
 *  格式为:type:TextRange|466$480$4$highlight-red$content_left_wrapper
 *  
 *  466: start
 *  480: end
 *  4: highlight.id,这个值不重要,反序列化时可以随便写
 *  highlight-red: 填充器 className
 *  content_left_wrapper: highlightSelection 时的 containerElementId
 **/
const stringSerialized = highlighter.serialize()

// 根据序列化数据还原高亮
highlighter.deserialize(stringSerialized)

// 获取即将高亮的 start 和 end 位置
// serializedSelection 为数组,如果没有值,则代表没有选区
const serializedSelection = highlighter.converter.serializeSelection(
  rangy.getSelection(),
  document.getElementById(containerElementId)
)
const { start, end } = serializedSelection[ 0 ]