1const TAG_TYPES = { 2 self_close_tag: 'self_close_tag', //èªéåæ ç¾ 3 open_tag: 'open_tag', // èµ·å§æ ç¾ 4 close_tag: 'close_tag' //éåæ ç¾ 5} 6 7const TAG_CLASS = { 8 tag: 'tag', //æ ç¾ç±»å 9 text: 'text' //ææ¬ç±»å 10} 11 12/** 13 * å建æ ç¾å®¹å¨å¯¹è±¡ 14 * @param {string} str 15 * @returns {{key, content, tagClass, parentKey, tagType?, tagName?, pairKey?}} 16 */ 17function createTag(str) { 18 const tag = {} 19 if (/^[<](meta|link|br|hr|img|input\b.*\/?)|([a-z0-9_-]+.*?\/)[>]$/is.test(str)) { 20 tag.tagClass = TAG_CLASS.tag 21 tag.tagType = TAG_TYPES.self_close_tag 22 tag.tagName = (/(?<=<)[a-z0-9_-]+\b/is.exec(str))?.[0].toUpperCase() || '' 23 } else if (/^<\/[a-z0-9_-]+[^>]*>$/is.test(str)) { 24 tag.tagClass = TAG_CLASS.tag 25 tag.tagType = TAG_TYPES.close_tag 26 tag.tagName = (/(?<=<\/)[a-z0-9_-]+\b/is.exec(str))?.[0].toUpperCase() || '' 27 } else if (/^<\w+.*>$/is.test(str)) { 28 tag.tagClass = TAG_CLASS.tag 29 tag.tagType = TAG_TYPES.open_tag 30 tag.tagName = (/(?<=<)[a-z0-9_-]+\b/is.exec(str))?.[0].toUpperCase() || '' 31 } else { 32 tag.tagClass = TAG_CLASS.text 33 } 34 tag.content = str 35 return tag 36} 37 38/** 39 * æ ç¾é 对 40 */ 41function matchTagPairs(tags) { 42 const stack = [] 43 for (let i = 0; i < tags.length; i++) { 44 let tag = tags[i] 45 const len = stack.length 46 let parent = null 47 if (tag.tagType === TAG_TYPES.close_tag) { 48 parent = stack[len - 2] 49 } else { 50 parent = stack[len - 1] 51 } 52 tag.parentKey = parent ? parent.key : '' 53 if (tag.tagClass !== TAG_CLASS.tag) { 54 continue 55 } 56 if (tag.tagType === TAG_TYPES.open_tag) { 57 stack.push(tag) 58 } else if (tag.tagType === TAG_TYPES.close_tag) { 59 const openTag = stack.pop() 60 if (openTag) { 61 // todo æ ç¾æ°éä¸å¹é & æ ç¾å±æ§ä¸åµå¥æ ç¾ exp: <input alt="<p>something</p>"> 62 openTag.pairKey = tag.key 63 tag.pairKey = openTag.key 64 } 65 } else if (tag.tagType === TAG_TYPES.self_close_tag) { 66 tag.pairKey = tag.key 67 } 68 } 69} 70 71/** 72 * å¹é ä¸ç«¯éèçæ ç¾ 73 */ 74function matchHides(tag, hides = ['hide-pc', 'hide-pad', 'hide-phone']) { 75 // ^(?=.*hide-pc)(?=.*hide-pad)(?=.*hide-phone).*$ 76 const reg = new RegExp('^' + hides.map(hide => `(?=.*${hide})`).join('') + '.*$', 'i') 77 return tag.tagClass === TAG_CLASS.tag 78 && (tag.tagType === TAG_TYPES.open_tag || tag.tagType === TAG_TYPES.self_close_tag) 79 && reg.test(tag.content) 80} 81 82/** 83 * æ¸ çä¸ç«¯éèHTML 84 */ 85function doPruneHiddenHtml(tpl, hides = ['hide-pc', 'hide-pad', 'hide-phone']) { 86 let arr = tpl.replace(/\s*\n\s*/gis, ' ') 87 .replace(/<\w+:\w+>[^<>]*?<\/w+:\w+>/gis, '') // æ¸ çéhtmlæ ç¾ï¼wordææ¡£å¼å ¥çå¼å¸¸æ ç¾<o:p></o:p> 88 .replace(/^\s*|\s*$/gis, '') 89 .split(/(?<=[<][a-z\/_-][^>]*[>])[\b]?|[\b]?(?=[<][a-z\/_-][^>]*[>])/gis) 90 .filter(s => !/^\s*$/gis.test(s)) 91 let tags = arr.map((str, idx) => { 92 let tag = createTag(str) 93 tag.key = (`${tag.tagClass}:${idx}`).toLowerCase() 94 return tag 95 }) 96 97 matchTagPairs(tags) 98 99 if (hides.length) { 100 let hideIndex = tags.findIndex(tag => matchHides(tag, hides)) 101 while (hideIndex > -1) { 102 let hide = tags[hideIndex] 103 let closeIndex = tags.findIndex(tag => tag.key === hide.pairKey) 104 tags.splice(hideIndex, closeIndex - hideIndex + 1) 105 hideIndex = tags.findIndex(tag => matchHides(tag)) 106 } 107 } 108 109 return tags.reduce((prev, node) => `${prev}${node.content}`, '') 110} 111 112/** 113 * wrap catch exception 114 * @param tpl 115 * @param hides 116 * @returns {*} 117 */ 118function pruneHiddenHtml(tpl, hides = ['hide-pc', 'hide-pad', 'hide-phone']) { 119 try { 120 return doPruneHiddenHtml(tpl, hides) 121 } catch (e) { 122 console.error(e) 123 return tpl 124 } 125} 126 127export { 128 pruneHiddenHtml 129}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.