移动端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

132 lines
3.9 KiB

// 标识必须独一无二 - 标识是为了使用insertText插入标识文本后,查找到标识所在delta位置的索引
export const linkFlag = '#-*=*-*=*-*=*@-link超链接标识link-@*=*-*=*-*=*-#'
export function addLink(editorCtx, attr, callback) {
// 先插入一段文本内容
editorCtx.insertText({
text: linkFlag
})
// 获取全文delta内容
editorCtx.getContents({
success(res) {
let options = res.delta.ops
const findex = options.findIndex(item => {
return item.insert && typeof item.insert !== 'object' && item.insert?.indexOf(linkFlag) !== -1
})
// 根据标识查找到插入的位置
if (findex > -1) {
const findOption = options[findex]
const findAttributes = findOption.attributes
// 将该findOption分成三部分:前内容 要插入的link 后内容
const [prefix, suffix] = findOption.insert.split(linkFlag);
const handleOps = []
// 前内容
if (prefix) {
const prefixOps = findAttributes ? {
insert: prefix,
attributes: findAttributes
} : {
insert: prefix
}
handleOps.push(prefixOps)
}
// 插入的link
const linkOps = {
insert: attr.text,
attributes: {
link: attr.href,
textDecoration: attr.textDecoration || 'none', // 下划线
color: attr.color || '#007aff'
}
}
handleOps.push(linkOps)
// 后内容
if (suffix) {
const suffixOps = findAttributes ? {
insert: suffix,
attributes: findAttributes
} : {
insert: suffix
}
handleOps.push(suffixOps)
}
// 删除原options[findex]并在findex位置插入上述三个ops
options.splice(findex, 1);
options.splice(findex, 0, ...handleOps);
// 最后重新初始化内容,注意该方法会导致光标重置到最开始位置
editorCtx.setContents({
delta: {
ops: options
}
})
// 所以最后建议使富文本光标失焦,让用户手动聚焦光标
editorCtx.blur()
// 后续回调操作
if (callback) callback()
}
}
})
}
/**
* 将含有特殊图片形式视频的富文本转换成正常视频的富文本
* @param {String} html 要进行处理的富文本字符串
* @returns {String} 返回处理结果
*/
export function handleHtmlWithVideo(html) {
// 正则表达式用于匹配img标签中带有alt属性且alt属性值为视频链接的模式
const regex = /<img\s+src="[^"]*"\s+alt="([^"]*)"[^>]*>/g
// 使用replace方法和一个函数回调来替换匹配到的内容
return html.replace(regex, (match, videoUrl) => {
// 替换为video标签,并添加controls属性以便用户可以控制播放
return `<video width="80%" controls><source src="${videoUrl}" type="video/mp4"></video>`
})
}
/**
* 将img标签中内联style属性中的宽高样式提取出标签width与height属性
* @param {Object} html 要处理的富文本字符串
* @returns {Object} 返回处理结果
*/
export function convertImgStylesToAttributes(html) {
return html.replace(/<img\s+([^>]+)\s*>/g, function(match, attributes) {
// 分割属性
const attrs = attributes.split(/\s+/);
// 找到style属性的位置
const styleIndex = attrs.findIndex(attr => attr.startsWith('style='));
if (styleIndex === -1) return match; // 如果没有找到style属性,则返回原样
// 提取style属性值
const styleAttr = attrs.splice(styleIndex, 1)[0];
const style = styleAttr.match(/"([^"]*)"/)[1];
// 解析 style 属性
const styleObj = {};
style.split(';').forEach(function(part) {
if (part) {
const [name, value] = part.split(':');
styleObj[name.trim()] = value.trim();
}
});
// 创建新的 img 标签
let newTag = '<img';
if (styleObj.width) {
newTag += ` width="${styleObj.width}"`;
}
if (styleObj.height) {
newTag += ` height="${styleObj.height}"`;
}
// 添加原有的属性,包括修改过的style属性
newTag += ` ${styleAttr} ${attrs.join(' ')}`;
// 关闭 img 标签
newTag += '>';
return newTag;
});
}