富文本实现格式化,格式化的时候保留图文、文字换行、样式。html
有一个需求,粘贴的时候格式化富文本内容,可是保留图文、文字换行、样式。node
一开始我作的时候是所有格式化,也就是粘贴的时候拿到html(怎么拿到百度下就有了,通常你们也都是对别人的富文本进行改造。),而后转DOM,而后getInnerText.大功告成。这时候产品说,保留图文和换行哦。nginx
因而修改下。web
这个比较简单,看下就好了。跨域
不作解析。 (核心代码就这些) bash
虽然比较简单,可是也有几个地方须要注意的是服务器
main.js微信
const error_img_url = 'https://hongqiaojiaoyu.oss-cn-shenzhen.aliyuncs.com/huazhang/imgs/error.png'
const Koa = require('koa');
const app = new Koa();
const get_url_buffer = require('./js/get_url_buffer')
const port = 3024
// 响应
app.use(async (ctx, next) => {
const path = ctx.request.path
console.log(path)
if(path.match(/^\/_proxy\/.*/)){
var body = await new Promise(function(resolve, reject) {
get_url_buffer(
(path.match(/(?:(?<=\/_proxy\/)).*/) || [error_img_url])[0],
(body) => {
resolve(body)
},
(uri) => {
console.log(uri)
}
)
})
ctx.set("Access-Control-Allow-Origin", "*")
ctx.status = 200
ctx.type = 'jpg'
ctx.length = Buffer.byteLength(body)
ctx.body = body
}
});
app.listen(port);
console.log(`启动完成 端口${port}`)
复制代码
get_url_buffer.jsapp
var http = require('http')
var https = require('https')
const url = require('url')
/**
* 获取图片buffer
* @param {*} _url 要转换的地址
* @param {*} success 成功 success(buffer)
* @param {*} fail 失败 fail(uri)
*/
var get_url_buffer = (_url, success, fail) => {
var uri = url.parse(_url)
// console.log(uri)
console.log(_url)
var option = {
...uri,
method: 'GET',
}
var handle_cb = (res) => {
if(res.statusCode === 301){
const url = res.headers['location']
console.log('重定向', url)
get_url_buffer(url, success, fail)
return
}
var img = []
var size = 0
res.on("data", (chunk) => {
img.push(chunk)
size += chunk.length
})
res.on("end", () => {
// console.log(size)
const buffer = Buffer.concat(img, size)
success(buffer)
})
}
if(uri.protocol === 'https:'){
return https.request(option, handle_cb).end()
}
if(uri.protocol === 'http:'){
return http.request(option, handle_cb).end()
}
console.log('协议异常', uri)
fail(uri)
}
module.exports = get_url_buffer
复制代码
到这里,咱们实现了第一个功能dom
可是这时候需求添加了一条,以下
这时候咱们很差下手,咱们须要作一个抉择
若是已经有必定修改这时候换富文本不太合适,只能去抄别人富文本的或者去找插件。
可是我遇到了以下两个问题,因此仍是决定本身来
slate-paste-html-plugin
,可是用起来一堆报错,就放弃了1: 要去掉垃圾代码,咱们就须要重组html格式
2: 去掉html可是样式不会影响
3: 要计算出换行
这个不太好说,我画了一张图
左侧那个是dom树,右侧是修改规则 (可是这个是理想状态,实际获取到的代码不会这么理想,稍后再说怎么解决)
有了思路,就能够实现了
咱们须要先递归获取每个节点,若是是最后一个,那么就计算。 (嗯,很完美
but, 刚刚不是说了,有些不是很符合理想,好比长这样
<p>
我是文字
<span>我也是</span>
</p>
复制代码
按照思路,咱们不该该拿这样的dom
因此须要先转下, 代码以下,相信大家能够看懂。
补全span
/** * 补全span * @param {*} html html片断 */
function tag_full(html){
const tag = 'span'
const reg1 = /(?<=\<(?:\/\w|\w).*>)([^<|>]*)(?=<\w.*>)/g
const reg2 = /(?<=\<(?:\/\w).*>)([^<|>]*)(?=<\/\w.*>)/g
const replace_value = (_, p1) => (p1.replace(/\s|\S|t|r/, '') == '' ? '' : `<${tag}>${p1}</${tag}>`)
return html.replace(reg1, replace_value).replace(reg2, replace_value)
}
复制代码
转完以后,咱们拿最后的节点,可是咱们还缺乏红色路径。
可是,红色路径怎么拿,看起来有点复杂,咱们先拿到当前节点路径再说,就让其余的事情随风吧。
递归获取节点
function traverse_tree(node, path){
if (!node) return
if (node.children && node.children.length > 0) {
for (let i = 0; i < node.children.length; i++) {
let next_node = node.children[i]
traverse_tree(next_node, [...path, {node: node, index: i}])
}
}else{
// 其余代码...
}
}
复制代码
经过递归,咱们遍历的时候顺手拿下节点路径和每一个路径下面的节点。
拿到以后,咱们和上面一个node节点(这里指的是最后节点)计算分叉位置, 代码以下
获取分叉点
/** * 获取分叉点 * @param {*} old_path [number] * @param {*} path [number] */
function get_path_diff_index(old_path, path){
let index = 0
let k = 0
for(let item of path){
old_path[k] === item && index++
k++
}
return index
}
复制代码
而后计算什么类型就能够了。
这时候,咱们就能够再对img、等标签处理了,还有样式。
样式代码送上
设置样式
/** * 根据style设置style * @param {*} node node节点 * @param {<filter_styles>} styles ['bold'] */
function set_style(node, filter_styles){
let style = {}
for(let item of filter_styles){
switch(item){
case 'bold': {
let key = 'font-weight'
let value = get_style(node, key)
value >= 600 && (style[key] = item)
break
}
case 'color': {
let value = get_style(node, item)
console.log(node, value)
style[item] = value
break
}
}
... 其余
}
return style
}
复制代码
而后
合并HTML
/**
* 合并html
* @param {*} html_arr
*/
function merge_html(html_arr){
function get_style_string(style){
let style_string = ''
for(let key in style){
style_string += `${key}:${style[key]};`
}
return style_string ? ` style="${style_string}"` : ''
}
const res = html_arr
.map(e =>
e.tag === 'img' ? `<p><img src="${e.src}" class="userChoosImg" style="max-width:100%;display: inline-block;" /></p>` :
block_element_tags.includes(e.tag) ?
// 忽略空白文本
(e.text === '' ? '' :
`<${e.tag}${get_style_string(e.style)}>${e.text}</${e.tag}>`) :
``
)
.join('')
console.log('html_format_res: ', res)
return res
}
复制代码
而后再循环判断img,把img合并处理,既然走以前的处理图片方法便可。
点个赞再走呗
--完--