@ohos-ports/advanced-mark.js 3.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -0
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/jquery.mark.d.ts +235 -0
- package/dist/jquery.mark.es6.d.ts +235 -0
- package/dist/jquery.mark.es6.js +1281 -0
- package/dist/jquery.mark.es6.min.js +8 -0
- package/dist/jquery.mark.js +1681 -0
- package/dist/jquery.mark.min.js +8 -0
- package/dist/mark.d.ts +210 -0
- package/dist/mark.es6.d.ts +210 -0
- package/dist/mark.es6.js +1284 -0
- package/dist/mark.es6.min.js +8 -0
- package/dist/mark.js +1682 -0
- package/dist/mark.min.js +8 -0
- package/package.json +72 -0
- package/src/jquery.js +24 -0
- package/src/jquery_es6.js +23 -0
- package/src/lib/domiterator.js +419 -0
- package/src/lib/mark.js +1817 -0
- package/src/lib/regexpcreator.js +397 -0
- package/src/types/jquery.mark.d.ts +235 -0
- package/src/types/mark.d.ts +210 -0
- package/src/vanilla.js +25 -0
package/dist/mark.min.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*!***************************************************
|
|
2
|
+
* advanced-mark.js v3.0.0
|
|
3
|
+
* https://github.com/angezid/advanced-mark.js
|
|
4
|
+
* MIT licensed
|
|
5
|
+
* Copyright (c) 2022–2026, angezid
|
|
6
|
+
* Based on 'mark.js', license https://git.io/vwTVl
|
|
7
|
+
*****************************************************/
|
|
8
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Mark=e()}(this,(function(){"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,(o=r.key,i=void 0,"symbol"==typeof(i=function(t,e){if("object"!=typeof t||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var r=n.call(t,e||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(o,"string"))?i:String(i)),r)}var o,i}function r(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t}function o(){return o=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},o.apply(this,arguments)}var i=function(){function t(n,r){e(this,t),this.ctx=n,this.opt=r,this.map=new Map}return r(t,[{key:"getContexts",value:function(){var t=this.ctx,e=this.opt.window,n=!1;if(!t)return[];Array.isArray(t)?n=!0:"string"==typeof t?t=e.document.querySelectorAll(t):void 0===t.length&&(t=[t]);for(var r=[],o=function(e){r.includes(t[e])||r.some((function(n){return n.contains(t[e])}))||r.push(t[e])},i=0;i<t.length;i++)o(i);return n&&r.sort((function(t,n){return(t.compareDocumentPosition(n)&e.Node.DOCUMENT_POSITION_FOLLOWING)>0?-1:1})),r}},{key:"getIframeContents",value:function(t,e,n){try{var r=t.contentWindow.document;r&&(this.map.set(t,"ready"),e({iframe:t,context:r}))}catch(e){n({iframe:t,error:e})}}},{key:"observeIframeLoad",value:function(t,e,n){var r=this;if(!this.map.has(t)){var o=null,i=function i(){clearTimeout(o),t.removeEventListener("load",i),r.getIframeContents(t,e,n)};t.addEventListener("load",i),this.map.set(t,!0),o=setTimeout(i,this.opt.iframesTimeout)}}},{key:"onIframeReady",value:function(t,e,n){var r="about:blank",o=t.getAttribute("src"),i=t.contentWindow;try{"complete"!==i.document.readyState||o&&o.trim()!==r&&i.location.href===r?this.observeIframeLoad(t,e,n):this.getIframeContents(t,e,n)}catch(t){n(t)}}},{key:"waitForIframes",value:function(t,e){var n,r,o=this,i=this.opt.shadowDOM,a=0,s=0,c=function t(e){for(var a=o.createIterator(e,o.opt.window.NodeFilter.SHOW_ELEMENT);r=a.nextNode();)o.isIframe(r)&&!o.map.has(r)&&(n.push(r),s++),i&&r.shadowRoot&&"open"===r.shadowRoot.mode&&t(r.shadowRoot)};!function t(r){n=[],r.iframe&&"about:blank"===r.context.location.href||(c(r.context),r.iframe||n.length)?n.length?n.forEach((function(n){o.onIframeReady(n,(function(e){a++,t(e)}),(function(t){o.opt.debug&&console.log(t.error||t),++a===s&&e()}))})):a===s&&e():e()}({context:t})}},{key:"createIterator",value:function(t,e){var n=this.opt.window;return n.document.createNodeIterator(t,e,(function(){return n.NodeFilter.FILTER_ACCEPT}),!1)}},{key:"addRemoveStyle",value:function(t,e,n){if(!n||e){var r=t.querySelector("style[data-markjs]");n?(r||((r=this.opt.window.document.createElement("style")).setAttribute("data-markjs","true"),t.appendChild(r)),r.textContent=e):r&&t.removeChild(r)}}},{key:"isIframe",value:function(e){return"IFRAME"===e.tagName&&!t.matches(e,this.opt.exclude)}},{key:"iterateThroughNodes",value:function(t,e,n,r,o){var i=this,a=this.opt.window.NodeFilter,s=this.opt.shadowDOM,c=this.opt.iframes;if(c||s){var u=(e&a.SHOW_ELEMENT)>0,h=(e&a.SHOW_TEXT)>0;!function t(o){for(var l,f=i.createIterator(o,e|a.SHOW_ELEMENT);o=f.nextNode();)if(1===o.nodeType){if(u&&n(o)&&r(o),c&&i.isIframe(o)&&"ready"===i.map.get(o)){var d=o.contentWindow.document;d&&(i.opt.highlight&&h&&o.contentWindow.CSS.highlights.set(i.opt.highlightName,i.opt.highlight),i.addRemoveStyle(d.head,c.style,h),t(d))}s&&(l=o.shadowRoot)&&"open"===l.mode&&(i.addRemoveStyle(l,s.style,h),t(l))}else h&&3===o.nodeType&&n(o)&&r(o)}(t)}else for(var l,f=this.createIterator(t,e);l=f.nextNode();)n(l)&&r(l);o()}},{key:"forEachNode",value:function(t,e,n){var r=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},i=this.getContexts(),a=i.length;a||o();var s=function(){i.forEach((function(i){r.iterateThroughNodes(i,t,n,e,(function(){--a<=0&&o()}))}))};if(this.opt.iframes){var c=a;i.forEach((function(t){r.waitForIframes(t,(function(){--c<=0&&s()}))}))}else s()}}],[{key:"matches",value:function(t,e){if(!e||!e.length)return!1;var n="string"==typeof e?[e]:e,r=t.matches;return r&&n.some((function(e){return r.call(t,e)}))}}]),t}(),a=function(){function t(n){e(this,t),this.opt=o({},{diacritics:!0,synonyms:{},accuracy:"partially",caseSensitive:!1,ignoreJoiners:!1,ignorePunctuation:[],wildcards:"disabled"},n)}return r(t,[{key:"chars",get:function(){var t=this;return this._chars||(this._chars=[],["aàáảãạăằắẳẵặâầấẩẫậäåāą","cçćč","dđď","eèéẻẽẹêềếểễệëěēę","iìíỉĩịîïī","lł","nñňń","oòóỏõọôồốổỗộơởỡớờợöøōő","rř","sšśșş","tťțţ","uùúủũụưừứửữựûüůūű","yýỳỷỹỵÿ","zžżź"].forEach((function(e){t._chars.push(e,e.toUpperCase())}))),this._chars}},{key:"create",value:function(t){var e=this,n="g".concat(this.opt.caseSensitive?"":"i");t=t.map((function(t){return"("+e.createPattern(t,n)+")"}));var r=this.createAccuracy(t.join("|"));return new RegExp("".concat(r.lookbehind,"(").concat(r.pattern,")").concat(r.lookahead),n)}},{key:"createPattern",value:function(t,e){t=this.checkWildcardsEscape(t),t=this.createSynonyms(t,e);var n=this.getJoinersPunctuation();return n&&(t=this.setupIgnoreJoiners(t)),this.opt.diacritics&&(t=this.createDiacritics(t)),t=t.replace(/\s+/g,"[\\s]+"),n&&(t=this.createJoiners(t,n)),"disabled"!==this.opt.wildcards&&(t=this.createWildcards(t)),t}},{key:"escape",value:function(t){return t.replace(/[[\]/{}()*+?.\\^$|]/g,"\\$&")}},{key:"preprocess",value:function(t){return t&&t.length?this.distinct("string"==typeof t?t.split(""):t).join("").replace(/[-^\]\\]/g,"\\$&"):""}},{key:"distinct",value:function(t){var e=[];return t.forEach((function(t){t.trim()&&!e.includes(t)&&e.push(t)})),e}},{key:"createSynonyms",value:function(t,e){var n=this,r=this.opt.synonyms;for(var o in r)if(r.hasOwnProperty(o)){var i=Array.isArray(r[o])?r[o]:[r[o]];if(i.unshift(o),(i=this.distinct(i)).length>1){i.sort((function(t,e){return e.length-t.length}));var a=(i=i.map((function(t){return n.checkWildcardsEscape(t)}))).map((function(t){return n.escape(t)})).join("|");t=t.replace(new RegExp(a,e),"(?:".concat(i.join("|"),")"))}}return t}},{key:"checkWildcardsEscape",value:function(t){return"disabled"!==this.opt.wildcards&&(t=t.replace(/(\\.)+|[?*]/g,(function(t,e){return e?t:"?"===t?"":""})).replace(/\\(?=[?*\x01\x02])/g,"")),this.escape(t)}},{key:"createWildcards",value:function(t){var e="withSpaces"===this.opt.wildcards,n=this.opt.blockElementsBoundary,r="[^".concat(e&&n?"":"","]*?");return t.replace(/\x01/g,e?"[^]?":"\\S?").replace(/\x02/g,e?r:"\\S*")}},{key:"setupIgnoreJoiners",value:function(t){return t.replace(/((?:\\\\)+|\x02|\(\?:|\|)|\\?(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|.)(?=([|)\x02]|$)|.)/g,(function(t,e,n){return e||void 0!==n?t:t+"\0"}))}},{key:"createJoiners",value:function(t,e){return t.split(/\x00+/).join("[".concat(e,"]*"))}},{key:"getJoinersPunctuation",value:function(){var t=this.preprocess(this.opt.ignorePunctuation),e=t||"";return this.opt.ignoreJoiners&&(e+="\\u00ad\\u200b\\u200c\\u200d"),e}},{key:"createDiacritics",value:function(t){var e=this,n=this.chars;return t.split("").map((function(t){for(var r=0;r<n.length;r+=2){var o=n[r].includes(t);if(e.opt.caseSensitive){if(o)return"["+n[r]+"]";if(n[r+1].includes(t))return"["+n[r+1]+"]"}else if(o||n[r+1].includes(t))return"["+n[r]+n[r+1]+"]"}return t})).join("")}},{key:"createAccuracy",value:function(t){var e,n=this.opt.accuracy,r="()",o=t,i="";if("partially"!==n)if("string"!=typeof n&&(e=this.preprocess(n.limiters),n=n.value),"exactly"===n){var a=e?"[\\s"+e+"]":"\\s";r="(^|".concat(a,")"),i="(?=$|".concat(a,")")}else{var s=e||"!-/:-@[-`{-~¡¿",c="[^\\s".concat(s,"]*");o="(?:".concat(t,")"),"complementary"===n?o=c+o+c:"startsWith"===n&&(r="(^|[\\s".concat(s,"])"),o=o.split(/\[\\s\]\+/).join(c+"[\\s]+")+c)}return{lookbehind:r,pattern:o,lookahead:i}}}]),t}(),s=function(){function n(t){e(this,n),this.ctx=t,this.nodeNames=["script","style","title","head","html"]}return r(n,[{key:"opt",get:function(){return this._opt},set:function(t){if(!(t&&t.window&&t.window.document)&&"undefined"==typeof window)throw new Error("Mark.js: please provide a window object as an option.");var e=t&&t.window||window,n=t&&t.highlight&&t.highlight instanceof Highlight;this._opt=o({},{window:e,element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,staticRanges:!0,rangeAcrossElements:!0,acrossElements:!1,ignoreGroups:0,each:function(){},noMatch:function(){},filter:function(){return!0},done:function(){},debug:!1,log:e.console},t),this._opt.element||(this._opt.element="mark"),this.filter=e.NodeFilter,this.empty=e.document.createTextNode(""),this._opt.highlightName||(this._opt.highlightName="advanced-markjs"),n?this.rangeArray=[]:this._opt.highlight=null}},{key:"iterator",get:function(){return new i(this.ctx,this.opt)}},{key:"log",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug";if(this.opt.debug){var r=this.opt.log;"object"===t(r)&&"function"==typeof r[n]&&r[n]("mark.js: ".concat(e))}}},{key:"report",value:function(t){var e=this;t.forEach((function(t){e.log("".concat(t.text," ").concat(JSON.stringify(t.obj)),t.level||"debug"),t.skip||e.opt.noMatch(t.obj)}))}},{key:"getSeachTerms",value:function(t){var e="string"==typeof t?[t]:t,n=this.opt.separateWordSearch,r=[],o={},i=function(t){t.split(/ +/).forEach((function(t){return a(t)}))},a=function(t){t.trim()&&!r.includes(t)&&(r.push(t),o[t]=0)};return e.forEach((function(t){n?"preserveTerms"===n?t.split(/"("*[^"]+"*)"/).forEach((function(t,e){e%2>0?a(t):i(t)})):i(t):a(t)})),r.sort((function(t,e){return e.length-t.length})),{terms:r,termStats:o}}},{key:"isNumeric",value:function(t){return Number(parseFloat(t))==t}},{key:"checkRanges",value:function(t,e,n,r){var o=this,i="error",a=t.filter((function(t){return!!(o.isNumeric(t.start)&&o.isNumeric(t.length)&&(t.start=parseInt(t.start),t.length=parseInt(t.length),t.start>=n&&t.start<r&&t.length>0))||(e.push({text:"Invalid range: ",obj:t,level:i}),!1)})).sort((function(t,e){return t.start-e.start}));if(this.opt.wrapAllRanges)return a;var s,c=0;return a.filter((function(t){return s=t.start+t.length,t.start>=c?(c=s,!0):(e.push({text:(s<c?"Nest":"Overlapp")+"ing range: ",obj:t,level:i}),!1)}))}},{key:"setType",value:function(t,e){var n=Array.isArray(e.tagNames)&&e.tagNames.length;if(n&&e.tagNames.forEach((function(e){return t[e.toLowerCase()]=2})),!n||e.extend)for(var r in t)t[r]=2;t.br=3}},{key:"getTextNodesAcross",value:function(t){var e,n,r,o=this,i={div:1,p:1,li:1,td:1,tr:1,th:1,ul:1,ol:1,dd:1,dl:1,dt:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,blockquote:1,figcaption:1,figure:1,pre:1,table:1,thead:1,tbody:1,tfoot:1,input:1,img:1,nav:1,details:1,label:1,form:1,select:1,menu:1,br:3,menuitem:1,main:1,section:1,article:1,aside:1,picture:1,output:1,button:1,header:1,footer:1,address:1,area:1,canvas:1,map:1,fieldset:1,textarea:1,track:1,video:1,audio:1,body:1,iframe:1,meter:1,object:1,svg:1},a=[],s=this.opt.blockElementsBoundary,c=s?2:1,u="";s&&(this.setType(i,s),s.char&&(u=s.char.charAt(0)));var h={text:"",regex:/\s/,tags:i,boundary:s,str:"",ch:u};this.iterator.forEachNode(this.filter.SHOW_ELEMENT|this.filter.SHOW_TEXT,(function(t){r&&a.push(o.getNodeInfo(r,t,n,h)),n=null,r=t}),(function(t){return 1===t.nodeType?(3===(e=i[t.nodeName.toLowerCase()])&&(h.str+="\n"),n&&e!==c||(n=e),!1):!o.excluded(t.parentNode)}),(function(){r&&a.push(o.getNodeInfo(r,null,n,h)),t({text:h.text,nodes:a,lastIndex:0})}))}},{key:"getNodeInfo",value:function(t,e,n,r){var o=r.text.length,i=r.ch,a=0,s=r.str,c=t.textContent;if(e){var u=r.regex.test(e.textContent[0]),h=u&&r.regex.test(c[c.length-1]);if(r.boundary||!h){var l=n;if(!n)for(var f=t.parentNode;f;){if(n=r.tags[f.nodeName.toLowerCase()]){l=!(f===e.parentNode||f.contains(e));break}f=f.parentNode}l&&(h?2===n&&(s+=h?i:u?" "+i:i+" "):s+=1===n?" ":2===n?" "+i+" ":"")}}return s&&(c+=s,a=s.length,r.str=""),r.text+=c,this.createInfo(t,o,r.text.length-a,a)}},{key:"getRangesTextNodes",value:function(t,e){var n,r=this,o=[],i=/\n/g,a=[0],s=this.filter.SHOW_TEXT|(e?this.filter.SHOW_ELEMENT:0),c="",u=0;this.iterator.forEachNode(s,(function(t){if(e)for(;null!==(n=i.exec(t.textContent));)a.push(u+n.index);c+=t.textContent,o.push({start:u,end:u=c.length,offset:0,node:t})}),(function(t){return e&&1===t.nodeType?("br"===t.tagName.toLowerCase()&&a.push(u),!1):!r.excluded(t.parentNode)}),(function(){var n={text:c,nodes:o,lastIndex:0};e&&(a.push(u),n.newLines=a),t(n)}))}},{key:"getTextNodes",value:function(t){var e=this,n=[],r=0;this.iterator.forEachNode(this.filter.SHOW_TEXT,(function(t){n.push({node:t,start:r}),r+=t.textContent.length}),(function(t){return!e.excluded(t.parentNode)}),(function(){t({nodes:n,lastIndex:0})}))}},{key:"excluded",value:function(t){return this.nodeNames.includes(t.nodeName.toLowerCase())||i.matches(t,this.opt.exclude)}},{key:"wrapRangeInsert",value:function(t,e,n,r,o,i){var a=r===e.node.textContent.length,s=e.end,c=1,u=r,h=e.node;0!==n?(h=h.splitText(n),u=r-n,c=a?2:3):a&&(c=0);var l=a?this.empty:h.splitText(u),f=this.createElement(h),d=f.childNodes[0],p=this.createInfo(l,0===c||2===c?s:e.start+r,s,e.offset);if(0===c)return e.node=d,{mark:f,nodeInfo:p,increment:0};var g=this.createInfo(d,1===c?e.start:o,e.start+r,0);return 1===c?t.nodes.splice(i,1,g,p):(2===c?t.nodes.splice(i+1,0,g):t.nodes.splice(i+1,0,g,p),e.end=o,e.offset=0),{mark:f,nodeInfo:p,increment:c<3?1:2}}},{key:"createInfo",value:function(t,e,n,r){return{node:t,start:e,end:n,offset:r}}},{key:"wrapRange",value:function(t,e,n,r){var o,i=t.node;if(this.rangeArray)this.createRange(i,e,i,n,t.start+e,r),o=i;else{var a=n===i.textContent.length,s=n;0!==e&&(i=i.splitText(e),s=n-e),o=a?this.empty:i.splitText(s),r(this.createElement(i))}return o}},{key:"createRange",value:function(t,e,n,r,o,i){var a;this.opt.staticRanges?a=new StaticRange({startContainer:t,startOffset:e,endContainer:n,endOffset:r}):((a=new Range).setStart(t,e),a.setEnd(n,r)),a.absoluteOffset=o,i(a,!0),a&&this.rangeArray.push(a)}},{key:"createElement",value:function(t){var e=this.opt.window.document.createElement(this.opt.element);return e.setAttribute("data-markjs","true"),this.opt.className&&e.setAttribute("class",this.opt.className),e.textContent=t.textContent,t.parentNode.replaceChild(e,t),e}},{key:"wrapRangeAcross",value:function(t,e,n,r,o){var i,a,s=t.lastIndex,c=!0,u=[],h=this.opt.wrapAllRanges,l=!!this.opt.highlight,f=l&&this.opt.rangeAcrossElements;if(h)for(;s>0&&t.nodes[s].start>e;)s--;for(;s<t.nodes.length;s++)if(s+1===t.nodes.length||t.nodes[s+1].start>e){var d=t.nodes[s];if(f)u.push(d.node);else if(!r(d.node))break;var p=e-d.start;if(a=(n>d.end?d.end:n)-d.start,p>=0&&a>p){if(f)c&&(i=[d.node,p,d.start+p]);else if(!l&&h){var g=this.wrapRangeInsert(t,d,p,a,e,s);d=g.nodeInfo,o(g.mark,c)}else d.node=this.wrapRange(d,p,a,(function(t){o(t,c)})),l||(d.start+=a);c=!1}if(!(n>d.end)){i&&r(u)&&this.createRange(i[0],i[1],d.node,a,i[2],o);break}e=d.end+d.offset}t.lastIndex=s}},{key:"wrapGroups",value:function(t,e,n,r,o){for(var i,a,s=0,c=0,u=0,h=this.opt.highlight,l=!1,f=0;++u<e.length;)(i=e[u])&&(a=e.indices[u][0])>=s&&(f=e.indices[u][1],r(t.node,i,u)&&(t.node=this.wrapRange(t,a-c,f-c,(function(t){o(t)})),f>s&&(s=f),h||(c=f),l=!0));l?h||(n.lastIndex=0):0===e[0].length&&this.setLastIndex(n,f)}},{key:"wrapGroupsAcross",value:function(t,e,n,r,o){for(var i,a,s,c=0,u=0,h=0;++u<e.length;)(a=e[u])&&(i=e.indices[u][0],(this.opt.wrapAllRanges||i>=c)&&(h=e.indices[u][1],s=!1,this.wrapRangeAcross(t,i,h,(function(t){return r(t,a,u)}),(function(t,e){s=!0,o(t,e)})),s&&h>c&&(c=h)));0===e[0].length&&this.setLastIndex(n,h)}},{key:"setLastIndex",value:function(t,e){var n=t.lastIndex;t.lastIndex=e>n?e:e>0?n+1:1/0}},{key:"processGroups",value:function(t,e,n,r,o,i){var a,s,c,u=this,h=n.count;this.getTextNodes((function(e){e.nodes.every((function(e){for(;null!==(a=t.exec(e.node.textContent))&&(n.match=a,s=c=!0,u.wrapGroups(e,a,t,(function(t,e,o){return n.matchStart=s,n.groupIndex=o,s=!1,r(t,e,n)}),(function(t){c&&h++,n.count=h,n.matchStart=c,c=!1,o(t,n)})),!n.abort););return!n.abort})),i(h)}))}},{key:"processGroupsAcross",value:function(t,e,n,r,o,i){var a,s,c,u=this,h=n.count;this.getTextNodesAcross((function(e){for(;null!==(a=t.exec(e.text))&&(n.match=a,s=c=!0,u.wrapGroupsAcross(e,a,t,(function(t,e,o){return n.groupStart=void 0,n.matchStart=s,n.groupIndex=o,s=!1,r(t,e,n)}),(function(t,e){c&&h++,n.count=h,n.matchStart=c,n.groupStart=e,o(t,n),c=!1})),!n.abort););i(h)}))}},{key:"processMatches",value:function(t,e,n,r,o,i){var a,s,c=this,u=0===e?0:e+1,h=n.count;this.getTextNodes((function(e){e.nodes.every((function(e){for(;null!==(a=t.exec(e.node.textContent));)if(""!==(s=a[u])){if(n.match=a,r(e.node,s,n)){for(var i=0,l=a.index;++i<u;)a[i]&&(l+=a[i].length);if(e.node=c.wrapRange(e,l,l+s.length,(function(t){n.count=++h,o(t,n)})),c.opt.highlight||(t.lastIndex=0),n.abort)break}}else t.lastIndex++;return!n.abort})),i(h)}))}},{key:"processMatchesAcross",value:function(t,e,n,r,o,i){var a,s,c,u=this,h=0===e?0:e+1,l=n.count;this.getTextNodesAcross((function(e){for(;null!==(a=t.exec(e.text));)if(""!==(s=a[h])){n.match=a,c=!0;for(var f=0,d=a.index;++f<h;)a[f]&&(d+=a[f].length);if(u.wrapRangeAcross(e,d,d+s.length,(function(t){return n.matchStart=c,c=!1,r(t,s,n)}),(function(t,e){e&&l++,n.count=l,n.matchStart=e,o(t,n)})),n.abort)break}else t.lastIndex++;i(l)}))}},{key:"processRanges",value:function(t,e,n,r){var o=this,i=this.opt.markLines,a=[],s=[],c="warn",u=0;this.getRangesTextNodes((function(h){var l=i?h.newLines.length:h.text.length,f=o.checkRanges(t,a,i?1:0,l);f.forEach((function(t,r){var f=t.start,d=f+t.length;d>l&&(a.push({text:"Range was limited to: ".concat(l),obj:t,skip:!0,level:c}),d=l),i&&(f=h.newLines[f-1],"\n"===h.text[f]&&f++,d=h.newLines[d-1]);var p=h.text.slice(f,d);p.trim()?o.wrapRangeAcross(h,f,d,(function(n){return e(n,t,p,r)}),(function(e,r){r&&u++,n(e,t,{matchStart:r,count:u})})):(a.push({text:"Skipping whitespace only range: ",obj:t,level:c}),s.push(t))})),o.log("Valid ranges: ".concat(JSON.stringify(f.filter((function(t){return!s.includes(t)}))))),r(u,a)}),i)}},{key:"unwrapMatches",value:function(t){var e=t.parentNode,n=t.firstChild;if(1===t.childNodes.length)if(3===n.nodeType){var r=t.previousSibling,o=t.nextSibling;if(r&&3===r.nodeType)o&&3===o.nodeType?(r.nodeValue+=n.nodeValue+o.nodeValue,e.removeChild(o)):r.nodeValue+=n.nodeValue;else{if(!o||3!==o.nodeType)return void e.replaceChild(t.firstChild,t);o.nodeValue=n.nodeValue+o.nodeValue}e.removeChild(t)}else e.replaceChild(t.firstChild,t);else{if(n){for(var i=this.opt.window.document.createDocumentFragment();t.firstChild;)i.appendChild(t.removeChild(t.firstChild));e.replaceChild(i,t)}else e.removeChild(t);e.normalize()}}},{key:"markRegExp",value:function(t,e){var n=this;this.opt=e;var r=0,o=0,i=this.opt.acrossElements,a="processMatches";if(this.opt.separateGroups){if(!t.hasIndices)throw new Error("Mark.js: RegExp must have a `d` flag");a=i?"processGroupsAcross":"processGroups"}else i&&(a="processMatchesAcross");if(!t.global&&!t.sticky){var s=t.toString().split("/");t=new RegExp(t.source,"g"+s[s.length-1]),this.log("RegExp is recompiled - it must have a `g` flag","warn")}this.log('RegExp "'.concat(t,'"')),this[a](t,this.opt.ignoreGroups,{count:0,abort:!1},(function(t,e,r){return n.opt.filter(t,e,o,r)}),(function(t,e){o=e.count,r++,n.opt.each(t,e)}),(function(e){0===e&&n.opt.noMatch(t),n.registerHighlight(),n.opt.done(r,e)}))}},{key:"mark",value:function(t,e){var n=this;this.opt=e;var r=this.getSeachTerms(t),o=r.terms,i=r.termStats;if(o.length){var a,s=0,c=0,u=0,h=this.opt.acrossElements,l=h?"processMatchesAcross":"processMatches",f=this.getRegExps(o),d={count:0,abort:!1};!function t(e){var r=e.regex,o=e.regTerms;n.log("RegExp ".concat(r)),n[l](r,1,d,(function(t,e,r){return h&&!r.matchStart||(a=n.getCurrentTerm(r.match,o)),n.opt.filter(t,a,u,i[a],r)}),(function(t,e){c++,u=e.count,h&&!e.matchStart||(i[a]+=1),n.opt.each(t,e)}),(function(e){var r=o.filter((function(t){return 0===i[t]}));r.length&&n.opt.noMatch(r),!d.abort&&++s<f.length?t(f[s]):(n.registerHighlight(),n.opt.done(c,e,i))}))}(f[0])}else this.opt.done(0,0,i)}},{key:"getCurrentTerm",value:function(t,e){for(var n=t.length;--n>2;)if(t[n])return e[n-3];return" "}},{key:"getRegExps",value:function(t){var e,n=new a(this.opt),r=this.opt.combineBy||this.opt.combinePatterns,o=t.length,i=[],s=100;r===1/0?s=o:!isNaN(+r)&&(e=parseInt(r))>0&&(s=e);for(var c=0;c<o;c+=s){var u=t.slice(c,Math.min(c+s,o));i.push({regex:n.create(u),regTerms:u})}return i}},{key:"markRanges",value:function(t,e){var n=this;if(this.opt=e,Array.isArray(t)){var r=0;this.processRanges(t,(function(t,e,r,o){return n.opt.filter(t,e,r,o)}),(function(t,e,o){r++,n.opt.each(t,e,o)}),(function(t,e){n.report(e),n.registerHighlight(),n.opt.done(r,t)}))}else this.report([{text:"markRanges() accept an array of objects: ",obj:t,level:"error"}]),this.opt.done(0,0)}},{key:"unmark",value:function(t){var e=this;this.opt=t;var n=CSS.highlights,r=this.opt.exclude&&this.opt.exclude.length;if(n){var o,a=this.opt.highlightName;"string"==typeof a&&(a=[a]),a.forEach((function(t){(o=n.get(t))&&o.size&&(n.delete(t),r?o.forEach((function(t){var n=t.startContainer;3===n.nodeType&&(n=n.parentNode),e.excluded(n)||o.delete(t)})):o.clear(),o.size&&n.set(t,o))}))}if(this.opt.highlight)this.opt.done();else{var s=this.opt.element+"[data-markjs]";this.opt.className&&(s+=".".concat(this.opt.className)),this.log('Removal selector "'.concat(s,'"')),this.iterator.forEachNode(this.filter.SHOW_ELEMENT,(function(t){e.unwrapMatches(t)}),(function(t){return i.matches(t,s)&&!(r&&e.excluded(t))}),this.opt.done)}}},{key:"registerHighlight",value:function(){var t=this,e=this.opt.highlight;if(e){var n=this.opt.highlightName,r=CSS.highlights;this.rangeArray.length&&(r.delete(n),e.size&&(e.forEach((function(e){t.rangeArray.push(e)})),e.clear()),this.rangeArray.sort((function(t,e){return t.absoluteOffset-e.absoluteOffset})),this.rangeArray.forEach((function(t){e.add(t)})),this.rangeArray=[]),e.size&&r.set(n,e)}}}]),n}();return function(t){var e=this,n=new s(t);return this.mark=function(t,r){return n.mark(t,r),e},this.markRegExp=function(t,r){return n.markRegExp(t,r),e},this.markRanges=function(t,r){return n.markRanges(t,r),e},this.unmark=function(t){return n.unmark(t),e},this.getVersion=function(){return"3.0.0"},this}}));
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ohos-ports/advanced-mark.js",
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"highlight",
|
|
6
|
+
"highlight-text",
|
|
7
|
+
"highlight-words",
|
|
8
|
+
"highlight-lines",
|
|
9
|
+
"search",
|
|
10
|
+
"jsdom",
|
|
11
|
+
"jquery",
|
|
12
|
+
"javascript",
|
|
13
|
+
"advanced-mark.js",
|
|
14
|
+
"mark.js"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "angezid",
|
|
19
|
+
"url": "https://github.com/angezid"
|
|
20
|
+
},
|
|
21
|
+
"description": "A fast JavaScript library to highlight any text on a browser page. It has support for CSS Custom Highlight API and virtual DOMs like JSDOM.",
|
|
22
|
+
"main": "dist/mark.js",
|
|
23
|
+
"types": "dist/mark.es6.d.ts",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/ohos-ports/ohos-ports.git",
|
|
27
|
+
"directory": "ports/advanced-mark.js/3.0.0"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/angezid/advanced-mark.js/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/angezid/advanced-mark.js",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"eslint": "eslint src/ test/",
|
|
35
|
+
"karma": "karma start build/karma.config.js",
|
|
36
|
+
"copy-files": "node scripts/copy-types-files.js",
|
|
37
|
+
"build-performance": "node scripts/build-performance.js",
|
|
38
|
+
"test-jsdom": "node jsdom-tests/test.js",
|
|
39
|
+
"jsdoc": "jsdoc src/lib/ -d build/doc -R README.md -P package.json -r",
|
|
40
|
+
"compile": "rollup -c build/rollup.config.js",
|
|
41
|
+
"build": "npm run test && npm run copy-files && npm run build-performance && npm run jsdoc",
|
|
42
|
+
"dev": "nodemon --exec \"npm run eslint && npm run compile\" --watch src/ --watch test/ -e js,html",
|
|
43
|
+
"test": "npm run eslint && npm run compile && npm run karma && npm run test-jsdom"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@babel/core": "^7.26.10",
|
|
47
|
+
"@babel/plugin-transform-object-assign": "^7.22.5",
|
|
48
|
+
"@babel/preset-env": "^7.26.9",
|
|
49
|
+
"@metahub/karma-jasmine-jquery": "^4.0.1",
|
|
50
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
51
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
52
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
53
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
54
|
+
"eslint": "8.56.0",
|
|
55
|
+
"eslint-plugin-jasmine-jquery": "^1.0.0",
|
|
56
|
+
"jasmine-core": "^4.5.0",
|
|
57
|
+
"jquery": "^3.2.1",
|
|
58
|
+
"jsdoc": "^4.0.0",
|
|
59
|
+
"jsdom": "^26.1.0",
|
|
60
|
+
"karma": "^6.4.4",
|
|
61
|
+
"karma-chrome-launcher": "^3.2.0",
|
|
62
|
+
"karma-cli": "^2.0.0",
|
|
63
|
+
"karma-coverage": "^2.1.1",
|
|
64
|
+
"karma-jasmine": "^5.1.0",
|
|
65
|
+
"karma-spec-reporter": "^0.0.36",
|
|
66
|
+
"karma-summary-reporter": "^4.0.1",
|
|
67
|
+
"puppeteer": "^25.6.0-beta.0",
|
|
68
|
+
"rollup": "^4.62.2-beta.0",
|
|
69
|
+
"rollup-plugin-cleanup": "^3.2.1",
|
|
70
|
+
"rollup-plugin-version-injector": "^1.3.3"
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/jquery.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Mark from './lib/mark';
|
|
2
|
+
import $ from 'jquery';
|
|
3
|
+
|
|
4
|
+
$.fn.mark = function(sv, opt) {
|
|
5
|
+
new Mark(this.get()).mark(sv, opt);
|
|
6
|
+
return this;
|
|
7
|
+
};
|
|
8
|
+
$.fn.markRegExp = function(regexp, opt) {
|
|
9
|
+
new Mark(this.get()).markRegExp(regexp, opt);
|
|
10
|
+
return this;
|
|
11
|
+
};
|
|
12
|
+
$.fn.markRanges = function(ranges, opt) {
|
|
13
|
+
new Mark(this.get()).markRanges(ranges, opt);
|
|
14
|
+
return this;
|
|
15
|
+
};
|
|
16
|
+
$.fn.unmark = function(opt) {
|
|
17
|
+
new Mark(this.get()).unmark(opt);
|
|
18
|
+
return this;
|
|
19
|
+
};
|
|
20
|
+
$.fn.getVersion = function() {
|
|
21
|
+
return '[VI]{version}[/VI]';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default $;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Mark from './lib/mark';
|
|
2
|
+
|
|
3
|
+
$.fn.mark = function(sv, opt) {
|
|
4
|
+
new Mark(this.get()).mark(sv, opt);
|
|
5
|
+
return this;
|
|
6
|
+
};
|
|
7
|
+
$.fn.markRegExp = function(regexp, opt) {
|
|
8
|
+
new Mark(this.get()).markRegExp(regexp, opt);
|
|
9
|
+
return this;
|
|
10
|
+
};
|
|
11
|
+
$.fn.markRanges = function(ranges, opt) {
|
|
12
|
+
new Mark(this.get()).markRanges(ranges, opt);
|
|
13
|
+
return this;
|
|
14
|
+
};
|
|
15
|
+
$.fn.unmark = function(opt) {
|
|
16
|
+
new Mark(this.get()).unmark(opt);
|
|
17
|
+
return this;
|
|
18
|
+
};
|
|
19
|
+
$.fn.getVersion = function() {
|
|
20
|
+
return '[VI]{version}[/VI]';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default $;
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A NodeIterator with iframes support and a method to check if an element is
|
|
3
|
+
* matching a specified selector
|
|
4
|
+
* @example
|
|
5
|
+
* const iterator = new DOMIterator("selector", opt);
|
|
6
|
+
* iterator.forEachNode(NodeFilter.SHOW_TEXT, node => { // each
|
|
7
|
+
* console.log(node);
|
|
8
|
+
* }, node => { // filter
|
|
9
|
+
* return !DOMIterator.matches(node.parentNode, ".ignore");
|
|
10
|
+
* }, () => { // done
|
|
11
|
+
* console.log("DONE");
|
|
12
|
+
* });
|
|
13
|
+
*/
|
|
14
|
+
class DOMIterator {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM
|
|
18
|
+
* element, an array of DOM elements, a NodeList or a selector
|
|
19
|
+
* @param {object} opt - Options object
|
|
20
|
+
*/
|
|
21
|
+
constructor(ctx, opt) {
|
|
22
|
+
/**
|
|
23
|
+
* The context of the instance. Either a DOM element, an array of DOM
|
|
24
|
+
* elements, a NodeList or a selector
|
|
25
|
+
* @type {HTMLElement|HTMLElement[]|NodeList|string}
|
|
26
|
+
* @access protected
|
|
27
|
+
*/
|
|
28
|
+
this.ctx = ctx;
|
|
29
|
+
/**
|
|
30
|
+
* The object containing Mark options
|
|
31
|
+
* @type {object}
|
|
32
|
+
* @access protected
|
|
33
|
+
*/
|
|
34
|
+
this.opt = opt;
|
|
35
|
+
/**
|
|
36
|
+
* The map to truck iframes states
|
|
37
|
+
* @type {Map}
|
|
38
|
+
* @access protected
|
|
39
|
+
*/
|
|
40
|
+
this.map = new Map();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Checks if the specified DOM element matches the selector
|
|
45
|
+
* @param {HTMLElement} element - The DOM element
|
|
46
|
+
* @param {string|string[]} selector - The selector or an array with
|
|
47
|
+
* selectors
|
|
48
|
+
* @return {boolean}
|
|
49
|
+
* @access public
|
|
50
|
+
*/
|
|
51
|
+
static matches(element, selector) {
|
|
52
|
+
if ( !selector || !selector.length) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
const selectors = typeof selector === 'string' ? [selector] : selector,
|
|
56
|
+
fn = element.matches;
|
|
57
|
+
return fn && selectors.some(sel => fn.call(element, sel));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns all contexts filtered by duplicates or nested elements
|
|
62
|
+
* @return {HTMLElement[]} - An array containing DOM contexts
|
|
63
|
+
* @access protected
|
|
64
|
+
*/
|
|
65
|
+
getContexts() {
|
|
66
|
+
let ctx = this.ctx,
|
|
67
|
+
win = this.opt.window,
|
|
68
|
+
sort = false;
|
|
69
|
+
|
|
70
|
+
if ( !ctx) return [];
|
|
71
|
+
|
|
72
|
+
if (Array.isArray(ctx)) {
|
|
73
|
+
sort = true;
|
|
74
|
+
} else if (typeof ctx === 'string') {
|
|
75
|
+
ctx = win.document.querySelectorAll(ctx);
|
|
76
|
+
} else if (typeof ctx.length === 'undefined') {
|
|
77
|
+
ctx = [ctx];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// filters out duplicate/nested elements
|
|
81
|
+
const array = [];
|
|
82
|
+
for (let i = 0; i < ctx.length; i++) {
|
|
83
|
+
if ( !array.includes(ctx[i]) && !array.some(node => node.contains(ctx[i]))) {
|
|
84
|
+
array.push(ctx[i]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// elements in the custom array can be in any order
|
|
88
|
+
// sorts elements by the DOM order
|
|
89
|
+
if (sort) {
|
|
90
|
+
array.sort((a, b) => {
|
|
91
|
+
return (a.compareDocumentPosition(b) & win.Node.DOCUMENT_POSITION_FOLLOWING) > 0 ? -1 : 1;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return array;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @callback DOMIterator~getIframeContentsSuccessCallback
|
|
99
|
+
* @param {HTMLDocument} contents - The contentDocument of the iframe
|
|
100
|
+
*/
|
|
101
|
+
/**
|
|
102
|
+
* Calls the success callback function with the iframe document. If it can't
|
|
103
|
+
* be accessed it calls the error callback function
|
|
104
|
+
* @param {HTMLElement} ifr - The iframe DOM element
|
|
105
|
+
* @param {DOMIterator~getIframeContentsSuccessCallback} successFn
|
|
106
|
+
* @param {function} [errorFn]
|
|
107
|
+
* @access protected
|
|
108
|
+
*/
|
|
109
|
+
getIframeContents(iframe, successFn, errorFn) {
|
|
110
|
+
try {
|
|
111
|
+
const doc = iframe.contentWindow.document;
|
|
112
|
+
if (doc) {
|
|
113
|
+
this.map.set(iframe, 'ready');
|
|
114
|
+
successFn({ iframe: iframe, context: doc });
|
|
115
|
+
}
|
|
116
|
+
} catch (e) {
|
|
117
|
+
errorFn({ iframe: iframe, error: e });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Observes the onload event of an iframe and calls the success callback or
|
|
123
|
+
* the error callback if the iframe is inaccessible. If the event isn't
|
|
124
|
+
* fired within the specified {@link DOMIterator#iframesTimeout}, then it'll
|
|
125
|
+
* call the error callback too
|
|
126
|
+
* @param {HTMLElement} ifr - The iframe DOM element
|
|
127
|
+
* @param {DOMIterator~getIframeContentsSuccessCallback} successFn
|
|
128
|
+
* @param {function} errorFn
|
|
129
|
+
* @access protected
|
|
130
|
+
*/
|
|
131
|
+
observeIframeLoad(ifr, successFn, errorFn) {
|
|
132
|
+
// an event listener is already added to the iframe
|
|
133
|
+
if (this.map.has(ifr)) return;
|
|
134
|
+
|
|
135
|
+
let id = null;
|
|
136
|
+
|
|
137
|
+
const listener = () => {
|
|
138
|
+
clearTimeout(id);
|
|
139
|
+
ifr.removeEventListener('load', listener);
|
|
140
|
+
this.getIframeContents(ifr, successFn, errorFn);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
ifr.addEventListener('load', listener);
|
|
144
|
+
this.map.set(ifr, true);
|
|
145
|
+
id = setTimeout(listener, this.opt.iframesTimeout);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Callback when the iframe is ready
|
|
150
|
+
* @callback DOMIterator~onIframeReadySuccessCallback
|
|
151
|
+
* @param {HTMLDocument} contents - The contentDocument of the iframe
|
|
152
|
+
*/
|
|
153
|
+
/**
|
|
154
|
+
* Callback if the iframe can't be accessed
|
|
155
|
+
* @callback DOMIterator~onIframeReadyErrorCallback
|
|
156
|
+
*/
|
|
157
|
+
/**
|
|
158
|
+
* Calls the callback if the specified iframe is ready for DOM access
|
|
159
|
+
* @param {HTMLElement} ifr - The iframe DOM element
|
|
160
|
+
* @param {DOMIterator~onIframeReadySuccessCallback} successFn - Success
|
|
161
|
+
* callback
|
|
162
|
+
* @param {DOMIterator~onIframeReadyErrorCallback} errorFn - Error callback
|
|
163
|
+
* @see {@link http://stackoverflow.com/a/36155560/3894981} for
|
|
164
|
+
* background information
|
|
165
|
+
* @access protected
|
|
166
|
+
*/
|
|
167
|
+
onIframeReady(ifr, successFn, errorFn) {
|
|
168
|
+
const bl = 'about:blank',
|
|
169
|
+
src = ifr.getAttribute('src'),
|
|
170
|
+
win = ifr.contentWindow;
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
if (win.document.readyState !== 'complete' || src && src.trim() !== bl && win.location.href === bl) {
|
|
174
|
+
this.observeIframeLoad(ifr, successFn, errorFn);
|
|
175
|
+
} else {
|
|
176
|
+
this.getIframeContents(ifr, successFn, errorFn);
|
|
177
|
+
}
|
|
178
|
+
} catch (e) { // accessing document failed
|
|
179
|
+
errorFn(e);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Callback when all context iframes are ready for DOM access
|
|
185
|
+
* @callback DOMIterator~waitForIframesDoneCallback
|
|
186
|
+
*/
|
|
187
|
+
/**
|
|
188
|
+
* Iterates over all context iframes and calls the done callback when all of them
|
|
189
|
+
* are ready for DOM access (including nested ones)
|
|
190
|
+
* @param {HTMLElement} ctx - The context DOM element
|
|
191
|
+
* @param {DOMIterator~waitForIframesDoneCallback} done - Done callback
|
|
192
|
+
*/
|
|
193
|
+
waitForIframes(ctx, doneCb) {
|
|
194
|
+
const shadow = this.opt.shadowDOM;
|
|
195
|
+
let count = 0,
|
|
196
|
+
iframes = 0,
|
|
197
|
+
array,
|
|
198
|
+
node;
|
|
199
|
+
|
|
200
|
+
const collect = context => {
|
|
201
|
+
const iterator = this.createIterator(context, this.opt.window.NodeFilter.SHOW_ELEMENT);
|
|
202
|
+
|
|
203
|
+
while ((node = iterator.nextNode())) {
|
|
204
|
+
if (this.isIframe(node) && !this.map.has(node)) {
|
|
205
|
+
array.push(node);
|
|
206
|
+
iframes++;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (shadow && node.shadowRoot && node.shadowRoot.mode === 'open') {
|
|
210
|
+
collect(node.shadowRoot);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const loop = (obj) => {
|
|
216
|
+
array = [];
|
|
217
|
+
|
|
218
|
+
if ( !obj.iframe || obj.context.location.href !== 'about:blank') {
|
|
219
|
+
collect(obj.context);
|
|
220
|
+
|
|
221
|
+
if ( !obj.iframe && !array.length) {
|
|
222
|
+
doneCb();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (array.length) {
|
|
228
|
+
array.forEach(iframe => {
|
|
229
|
+
this.onIframeReady(iframe, obj => { // success
|
|
230
|
+
count++;
|
|
231
|
+
loop(obj);
|
|
232
|
+
}, obj => { // error
|
|
233
|
+
if (this.opt.debug) {
|
|
234
|
+
console.log(obj.error || obj);
|
|
235
|
+
}
|
|
236
|
+
if (++count === iframes) doneCb();
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
} else if (count === iframes) {
|
|
240
|
+
doneCb();
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
loop({ context: ctx });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Creates a NodeIterator on the specified context
|
|
249
|
+
* @see {@link https://developer.mozilla.org/en/docs/Web/API/NodeIterator}
|
|
250
|
+
* @param {HTMLElement} ctx - The context DOM element
|
|
251
|
+
* @param {DOMIterator~whatToShow} whatToShow
|
|
252
|
+
* @return {NodeIterator}
|
|
253
|
+
* @access protected
|
|
254
|
+
*/
|
|
255
|
+
createIterator(ctx, whatToShow) {
|
|
256
|
+
const win = this.opt.window;
|
|
257
|
+
return win.document.createNodeIterator(ctx, whatToShow, () => win.NodeFilter.FILTER_ACCEPT, false);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Adds custom style to shadow root when marking, removes when unmark
|
|
262
|
+
* There is no possibility to check whether a shadow root has any matches though
|
|
263
|
+
* @param {HTMLElement} node - The shadow root node
|
|
264
|
+
* @param {HTMLElement} style - The custom style element
|
|
265
|
+
* @param {boolean} add - A boolean indicating add or remove a style element
|
|
266
|
+
*/
|
|
267
|
+
addRemoveStyle(root, style, add) {
|
|
268
|
+
if (add && !style) return;
|
|
269
|
+
|
|
270
|
+
let elem = root.querySelector('style[data-markjs]');
|
|
271
|
+
|
|
272
|
+
if (add) {
|
|
273
|
+
if ( !elem) {
|
|
274
|
+
elem = this.opt.window.document.createElement('style');
|
|
275
|
+
elem.setAttribute('data-markjs', 'true');
|
|
276
|
+
root.appendChild(elem);
|
|
277
|
+
}
|
|
278
|
+
elem.textContent = style;
|
|
279
|
+
|
|
280
|
+
} else if (elem) {
|
|
281
|
+
root.removeChild(elem);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Checks if the DOM element is an iframe and is not excluded from search
|
|
287
|
+
* @param {HTMLElement} element - The DOM element
|
|
288
|
+
* @return {boolean}
|
|
289
|
+
*/
|
|
290
|
+
isIframe(node) {
|
|
291
|
+
return node.tagName === 'IFRAME' && !DOMIterator.matches(node, this.opt.exclude);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Iterates through all nodes, including shadow DOM nodes, in the specified context
|
|
296
|
+
* @param {HTMLElement} ctx - The context
|
|
297
|
+
* @param {DOMIterator~whatToShow} whatToShow
|
|
298
|
+
* @param {DOMIterator~filterCb} filterCb - Filter callback
|
|
299
|
+
* @param {DOMIterator~forEachNodeCallback} eachCb - Each callback
|
|
300
|
+
* @param {DOMIterator~forEachNodeEndCallback} doneCb - End callback
|
|
301
|
+
* @access protected
|
|
302
|
+
*/
|
|
303
|
+
iterateThroughNodes(ctx, whatToShow, filterCb, eachCb, doneCb) {
|
|
304
|
+
const filter = this.opt.window.NodeFilter,
|
|
305
|
+
shadow = this.opt.shadowDOM,
|
|
306
|
+
iframe = this.opt.iframes;
|
|
307
|
+
|
|
308
|
+
if (iframe || shadow) {
|
|
309
|
+
const showElement = (whatToShow & filter.SHOW_ELEMENT) > 0,
|
|
310
|
+
showText = (whatToShow & filter.SHOW_TEXT) > 0;
|
|
311
|
+
|
|
312
|
+
const traverse = node => {
|
|
313
|
+
let iterator = this.createIterator(node, whatToShow | filter.SHOW_ELEMENT),
|
|
314
|
+
root;
|
|
315
|
+
|
|
316
|
+
while ((node = iterator.nextNode())) {
|
|
317
|
+
if (node.nodeType === 1) { // element
|
|
318
|
+
if (showElement && filterCb(node)) {
|
|
319
|
+
eachCb(node);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (iframe && this.isIframe(node) && this.map.get(node) === 'ready') {
|
|
323
|
+
const doc = node.contentWindow.document;
|
|
324
|
+
if (doc) {
|
|
325
|
+
if (this.opt.highlight && showText) {
|
|
326
|
+
node.contentWindow.CSS.highlights.set(this.opt.highlightName, this.opt.highlight);
|
|
327
|
+
}
|
|
328
|
+
this.addRemoveStyle(doc.head, iframe.style, showText);
|
|
329
|
+
traverse(doc);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// there is no possibility to filter a whole shadow DOM, because the 'DOMIterator.matches()'
|
|
333
|
+
// is not working neither for 'shadowRoot' no for the element itself
|
|
334
|
+
if (shadow && (root = node.shadowRoot) && root.mode === 'open') {
|
|
335
|
+
this.addRemoveStyle(root, shadow.style, showText);
|
|
336
|
+
traverse(root);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
} else if (showText && node.nodeType === 3 && filterCb(node)) { // text node
|
|
340
|
+
eachCb(node);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
traverse(ctx);
|
|
346
|
+
|
|
347
|
+
} else {
|
|
348
|
+
const iterator = this.createIterator(ctx, whatToShow);
|
|
349
|
+
let node;
|
|
350
|
+
|
|
351
|
+
while ((node = iterator.nextNode())) {
|
|
352
|
+
if (filterCb(node)) {
|
|
353
|
+
eachCb(node);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
doneCb();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @typedef DOMIterator~whatToShow
|
|
363
|
+
* @see {@link http://tinyurl.com/zfqqkx2}
|
|
364
|
+
* @type {number}
|
|
365
|
+
*/
|
|
366
|
+
/**
|
|
367
|
+
* Callback to filter nodes. Can return either true to accept node or false to reject node.
|
|
368
|
+
* @see {@link http://tinyurl.com/zdczmm2}
|
|
369
|
+
* @callback DOMIterator~filterCb
|
|
370
|
+
* @param {Text|HTMLElement} node - The node to filter
|
|
371
|
+
*/
|
|
372
|
+
/**
|
|
373
|
+
* Callback for each node
|
|
374
|
+
* @callback DOMIterator~forEachNodeCallback
|
|
375
|
+
* @param {Text|HTMLElement} node - The node node to process
|
|
376
|
+
*/
|
|
377
|
+
/**
|
|
378
|
+
* Callback if all contexts were handled
|
|
379
|
+
* @callback DOMIterator~forEachNodeEndCallback
|
|
380
|
+
*/
|
|
381
|
+
/**
|
|
382
|
+
* Iterates over all contexts
|
|
383
|
+
* @param {DOMIterator~whatToShow} whatToShow
|
|
384
|
+
* @param {DOMIterator~forEachNodeCallback} each - Each callback
|
|
385
|
+
* @param {DOMIterator~filterCb} filter - Filter callback
|
|
386
|
+
* @param {DOMIterator~forEachNodeEndCallback} done - End callback
|
|
387
|
+
* @access public
|
|
388
|
+
*/
|
|
389
|
+
forEachNode(whatToShow, each, filter, done = () => {}) {
|
|
390
|
+
const contexts = this.getContexts();
|
|
391
|
+
let open = contexts.length;
|
|
392
|
+
|
|
393
|
+
if ( !open) done();
|
|
394
|
+
|
|
395
|
+
const ready = () => {
|
|
396
|
+
contexts.forEach(ctx => {
|
|
397
|
+
this.iterateThroughNodes(ctx, whatToShow, filter, each, () => {
|
|
398
|
+
if (--open <= 0) done(); // calls end when all contexts were handled
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
if (this.opt.iframes) {
|
|
404
|
+
let count = open;
|
|
405
|
+
|
|
406
|
+
// waits for all iframes to be ready for DOM access or timeout
|
|
407
|
+
contexts.forEach(ctx => {
|
|
408
|
+
this.waitForIframes(ctx, () => {
|
|
409
|
+
if (--count <= 0) ready();
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
} else {
|
|
414
|
+
ready();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export default DOMIterator;
|