index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // 标识必须独一无二 - 标识是为了使用insertText插入标识文本后,查找到标识所在delta位置的索引
  2. export const linkFlag = '#-*=*-*=*-*=*@-link超链接标识link-@*=*-*=*-*=*-#'
  3. export function addLink(editorCtx, attr, callback) {
  4. // 先插入一段文本内容
  5. editorCtx.insertText({
  6. text: linkFlag
  7. })
  8. // 获取全文delta内容
  9. editorCtx.getContents({
  10. success(res) {
  11. let options = res.delta.ops
  12. const findex = options.findIndex(item => {
  13. return item.insert && typeof item.insert !== 'object' && item.insert?.indexOf(linkFlag) !== -1
  14. })
  15. // 根据标识查找到插入的位置
  16. if (findex > -1) {
  17. const findOption = options[findex]
  18. const findAttributes = findOption.attributes
  19. // 将该findOption分成三部分:前内容 要插入的link 后内容
  20. const [prefix, suffix] = findOption.insert.split(linkFlag);
  21. const handleOps = []
  22. // 前内容
  23. if (prefix) {
  24. const prefixOps = findAttributes ? {
  25. insert: prefix,
  26. attributes: findAttributes
  27. } : {
  28. insert: prefix
  29. }
  30. handleOps.push(prefixOps)
  31. }
  32. // 插入的link
  33. const linkOps = {
  34. insert: attr.text,
  35. attributes: {
  36. link: attr.href,
  37. textDecoration: attr.textDecoration || 'none', // 下划线
  38. color: attr.color || '#007aff'
  39. }
  40. }
  41. handleOps.push(linkOps)
  42. // 后内容
  43. if (suffix) {
  44. const suffixOps = findAttributes ? {
  45. insert: suffix,
  46. attributes: findAttributes
  47. } : {
  48. insert: suffix
  49. }
  50. handleOps.push(suffixOps)
  51. }
  52. // 删除原options[findex]并在findex位置插入上述三个ops
  53. options.splice(findex, 1);
  54. options.splice(findex, 0, ...handleOps);
  55. // 最后重新初始化内容,注意该方法会导致光标重置到最开始位置
  56. editorCtx.setContents({
  57. delta: {
  58. ops: options
  59. }
  60. })
  61. // 所以最后建议使富文本光标失焦,让用户手动聚焦光标
  62. editorCtx.blur()
  63. // 后续回调操作
  64. if (callback) callback()
  65. }
  66. }
  67. })
  68. }
  69. /**
  70. * 将含有特殊图片形式视频的富文本转换成正常视频的富文本
  71. * @param {String} html 要进行处理的富文本字符串
  72. * @returns {String} 返回处理结果
  73. */
  74. export function handleHtmlWithVideo(html) {
  75. // 正则表达式用于匹配img标签中带有alt属性且alt属性值为视频链接的模式
  76. const regex = /<img\s+src="[^"]*"\s+alt="([^"]*)"[^>]*>/g
  77. // 使用replace方法和一个函数回调来替换匹配到的内容
  78. return html.replace(regex, (match, videoUrl) => {
  79. // 替换为video标签,并添加controls属性以便用户可以控制播放
  80. return `<video width="80%" controls><source src="${videoUrl}" type="video/mp4"></video>`
  81. })
  82. }
  83. /**
  84. * 将img标签中内联style属性中的宽高样式提取出标签width与height属性
  85. * @param {Object} html 要处理的富文本字符串
  86. * @returns {Object} 返回处理结果
  87. */
  88. export function convertImgStylesToAttributes(html) {
  89. return html.replace(/<img\s+([^>]+)\s*>/g, function(match, attributes) {
  90. // 分割属性
  91. const attrs = attributes.split(/\s+/);
  92. // 找到style属性的位置
  93. const styleIndex = attrs.findIndex(attr => attr.startsWith('style='));
  94. if (styleIndex === -1) return match; // 如果没有找到style属性,则返回原样
  95. // 提取style属性值
  96. const styleAttr = attrs.splice(styleIndex, 1)[0];
  97. const style = styleAttr.match(/"([^"]*)"/)[1];
  98. // 解析 style 属性
  99. const styleObj = {};
  100. style.split(';').forEach(function(part) {
  101. if (part) {
  102. const [name, value] = part.split(':');
  103. styleObj[name.trim()] = value.trim();
  104. }
  105. });
  106. // 创建新的 img 标签
  107. let newTag = '<img';
  108. if (styleObj.width) {
  109. newTag += ` width="${styleObj.width}"`;
  110. }
  111. if (styleObj.height) {
  112. newTag += ` height="${styleObj.height}"`;
  113. }
  114. // 添加原有的属性,包括修改过的style属性
  115. newTag += ` ${styleAttr} ${attrs.join(' ')}`;
  116. // 关闭 img 标签
  117. newTag += '>';
  118. return newTag;
  119. });
  120. }