chaojidan

导航

文章关键字标记方案(内容标记)

有些公司的业务需要把一篇篇文章里面的关键字标记出来,如果不符合的文章就不发布出去,标记文章里面的关键字有多种方案,比如:使用svg进行标记;使用dom进行标记;使用canvas进行标记。

我个人推荐使用Dom进行标记,符合Dom操作的习惯,而且简单易用,易于理解,同时不需要深入了解画图类的技术底层。

几个重要的方法,仅供参考:

 1 mark: function(div, text, processer) {      //搜索的dom节点,关键字,插入的dom节点
 2         return new Promise(function(resolve, reject) {
 3             setTimeout(function() {
 4                 window.focus();
 5 
 6                 let rTemp = document.createRange();
 7                 rTemp.selectNodeContents(div);
 8                 if (rTemp.simpleText().indexOf(text)<0) { // 不包含
 9                     return resolve();
10                 }
11                 let range = null;
12                 search(div, function(e, offset) {
13                     if (e == BREAK_RANGE) {
14                         range = null;
15                         return;
16                     }
17                     rTemp.setStart(e, offset);   //设置文章选区的起始位置
18                     if (!range && rTemp.simpleText().indexOf(text)==0) {
19                         range = document.createRange();
20                         range.setStart(e, offset);
21                     } else if (range) {     //跨标签时,因为range一直有,所以一定会找到跟标记内容相等的终点位置
22                         range.setEnd(e, offset);   
23                         if (range.simpleText()==text) {
24                             let r = processRange(div, range, processer);
25                             range = null;
26                             return r;
27                         }
28                     }
29                 });
30                 document.getSelection().removeAllRanges();
31                 resolve();
32             }, 16);
33         });
34     }
 1 function search(node, doSth) {
 2     let root = node;
 3     function next(node) {
 4         if (node == root) return null;
 5         if (node.nextSibling) {
 6             return node.nextSibling;
 7         }
 8         return next(node.parentNode);
 9     }
10     outer: while (node) {
11         if (node.nodeType==1) {   //元素节点,比如div
12             if (/^(script|style|noscript)$/i.test(node.nodeName)) {
13                 node = next(node);
14             } else if (/^(input|object|audio|video|embed|select)$/i.test(node.nodeName)) {
15                 node = next(node);
16                 doSth(BREAK_RANGE);
17             } else if ($(node).is('.mark-txt')) {
18                 node = next(node);
19                 doSth(BREAK_RANGE);
20             } else if (node.childNodes && node.childNodes.length) {
21                 node = node.childNodes[0];
22             } else {
23                 node = next(node);
24             }
25         } else if (node.nodeType == 8) {   //一个comment节点
26             // 注释节点
27             node = next(node);
28         } else if (node.nodeType == 3) {   //文本节点
29             let s = node.nodeValue;
30             inner: for (let i=0; i<=s.length; i++) {
31                 let end = doSth(node, i);
32                 if (end) {
33                     node = end;
34                     break inner;
35                 }
36             }
37             node = next(node);
38         }
39     }
40 }
 1 function processRange(div, range, processer) {
 2     let s = document.getSelection();
 3     s.removeAllRanges();
 4     s.addRange(range);
 5     document.execCommand('createLink', false, `${vhref}`);
 6     let list = document.querySelectorAll(`a[href="${vhref}"]`);
 7     if (!list.length) return;
 8     list = [].slice.call(list);
 9     list = mergeElement(list);
10     list = list.map(function(oNode) {
11         let childs = [].slice.call(oNode.childNodes);
12         let last = childs[childs.length-1];
13         if (!(oNode.textContent||'').trim() || oNode.querySelector('img')) {
14             while (childs.length && oNode.parentNode) {
15                 oNode.parentNode.insertBefore(childs.shift(), oNode);
16                 oNode.parentNode.removeChild(oNode);
17             }
18             return last;
19         } else {
20             let newNode = processer(childs);
21             oNode.parentNode.replaceChild(newNode, oNode);
22             return newNode;
23         }
24     });
25     return list.pop();
26 }
View Code
 1 function commonParent(a, b) {
 2     if (contains(a, b)) {
 3         return a;
 4     }
 5     if (regBlock.test(window.getComputedStyle(a)['display'])) {
 6         return null;
 7     }
 8     let p = a.parentNode;
 9     while (true) {
10         if (contains(p, b)) {
11             return p;
12         }
13         if (regBlock.test(window.getComputedStyle(p)['display'])) {
14             return null;
15         }
16         p = p.parentNode;
17     }
18 }
19 function unwrap(a, index) {
20     let p = a.parentNode.cloneNode();
21     p.removeAttribute('id');
22     p.innerHTML = '';
23     while (a.childNodes.length) {
24         p.appendChild(a.childNodes[0]);
25     }
26     a.appendChild(p);
27     if (index!=0) {
28         a.parentNode.parentNode.insertBefore(a, a.parentNode);
29     } else {
30         $(a).insertAfter(a.parentNode);
31     }
32 }
33 function importChild(a, b) {
34     while (b.childNodes.length) {
35         a.appendChild(b.childNodes[0]);
36     }
37 }
38 function mergeElement(list) {
39     let n = [];
40     while (list.length>1) {
41         let a = list.shift();
42         let b = list.shift();
43         let p = commonParent(a, b);
44         if (p) {
45             list.unshift(p);
46         } else {
47             n.push(a, b);
48         }
49     }
50     list = n.concat(list);
51     list = list.map(function(node) {
52         let aList = [].slice.call(node.querySelectorAll(`a[href="${vhref}"]`));
53         if (aList.length<1) return node;
54         if (aList.length<2) return aList[0];
55         aList.forEach((a, i)=> {
56             while (a.parentNode != node) {
57                 unwrap(a, i);
58             }
59         });
60         let s = aList[0];
61         let e = aList[aList.length-1];
62         let next = s.nextSibling;
63         console.log('aList:', aList);
64         while (next) {
65             let index = aList.indexOf(next);
66             if (index>-1) {
67                 importChild(s, next);
68                 next.parentNode.removeChild(next);
69                 if (next == e) {
70                     return s;
71                 }
72             } else {
73                 s.appendChild(next);
74             }
75             next = s.nextSibling;
76         }
77         return s;
78     });
79     return list;
80 }
View Code

 

posted on 2025-04-29 10:14  chaojidan  阅读(24)  评论(0)    收藏  举报