From 4694b3cdb8ab131862f15da760b7222d9562f104 Mon Sep 17 00:00:00 2001 From: Yaohaixiao Date: Tue, 29 Aug 2023 18:23:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20sticky=20=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=EF=BC=8C=E7=AA=97=E5=8F=A3=E8=B0=83=E6=95=B4=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F=EF=BC=8Cchapters=20=E5=AF=BC=E8=88=AA=E6=A0=8F?= =?UTF-8?q?=E9=AB=98=E5=BA=A6=E6=B2=A1=E6=9C=89=E8=87=AA=E9=80=82=E5=BA=94?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E5=A4=A7=E5=B0=8F=E5=8F=98=E5=8C=96=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- anchors.js | 3 +- anchors.min.js | 2 +- anchors.min.js.map | 2 +- api/pug/methods/$off.pug | 4 +- api/pug/properties/section.pug | 2 +- api/pug/script.pug | 42 +++++++------- chapters.js | 9 ++- chapters.min.js | 2 +- chapters.min.js.map | 2 +- docs/fixed.html | 58 +++++++++---------- docs/flex.html | 58 +++++++++---------- docs/index.html | 100 ++++++++++++++++----------------- docs/js/outline.min.js | 2 +- docs/js/outline.min.js.map | 2 +- docs/relative.html | 58 +++++++++---------- docs/sticky.html | 58 +++++++++---------- outline.js | 33 +++++------ outline.min.js | 2 +- outline.min.js.map | 2 +- package.json | 2 +- toolbar.js | 3 +- toolbar.min.js | 2 +- toolbar.min.js.map | 2 +- 23 files changed, 220 insertions(+), 230 deletions(-) diff --git a/anchors.js b/anchors.js index 18d7f656..95c1d268 100644 --- a/anchors.js +++ b/anchors.js @@ -12,7 +12,6 @@ import offsetTop from './utils/dom/offsetTop' import on from './utils/event/on' import off from './utils/event/off' import stop from './utils/event/stop' -import publish from './utils/observer/emit' import paint from './utils/icons/paint' import _updateHeading from './_updateHeading' @@ -173,7 +172,7 @@ class Anchors extends Base { } later(() => { - publish('toolbar:update', { + this.$emit('toolbar:update', { top, min, max diff --git a/anchors.min.js b/anchors.min.js index 93f6774c..5294c0d6 100644 --- a/anchors.min.js +++ b/anchors.min.js @@ -1,2 +1,2 @@ -!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).Anchors=e()}(this,(function(){"use strict";const t=t=>"string"==typeof t,e=(t,e)=>{const r=Object.prototype.hasOwnProperty;return t&&r.call(t,e)},r=t=>Object.prototype.toString.apply(t),s=t=>"function"==typeof t||"[object Function]"===r(t),n=t=>("[object Object]"===r(t)||"object"==typeof t||s(t))&&null!==t,i={},o=t=>e(i,t)&&i[t].length>0,c=(t,e=!0)=>e?o(t):(t=>{let e=o(t),r=t.lastIndexOf(".");for(;!e&&-1!==r;)r=(t=t.substring(0,r)).lastIndexOf("."),e=o(t);return e})(t),l=(t,e,s=!0)=>{const n=t=>{if(!o(t))return!1;i[t].forEach((t=>{const s=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]","[object BigInt64Array]","[object BigUint64Array]"].indexOf(r(e))>-1?e.toString():e;t.callback.call(t.context||t,s)}))},l=()=>{let e=t,r=t.lastIndexOf(".");for(;-1!==r;)e=e.substring(0,r),r=e.lastIndexOf("."),n(e);n(t),n("*")};if(!c(t))return!1;s?setTimeout(l,10):l()},a=(()=>{let t=0;return e=>(t+=1,e?e+"-"+t:"guid-"+t)})(),h=t=>{if(!e(i,t))return!1;delete i[t]},u=(t,e)=>{if(!c(t))return!1;e?(t=>{const e=Object.keys(i);if(!t||e.length<1)return!1;e.forEach((e=>{const r=i[e];let s;r.forEach(((e,n)=>{e.callback!==t&&e.token!==t||(s=e.topic,r.splice(-1,n))})),r.length<1&&h(s)}))})(e):h(t)};class d{constructor(t){this.attrs={},t&&this.initialize(t)}initialize(t){return this.attr(t).render().addListeners(),this}attr(r,s){const i=this.attrs;return t(r)?s&&e(i,r)?(i[r]=s,this):i[r]:n(r)?(o=i,c=r,Object.keys(c).forEach((t=>{e(c,t)&&(o[t]=c[t])})),this):0===arguments.length?i:this;var o,c}render(){return this}destroy(){return this.removeListeners(),this}reload(t){return this.destroy().initialize(this.attr(t)),this}$emit(t,e){return l(t,e),this}$on(t,e){return((t,e,r=null)=>{const n=a();let o="symbol"==typeof t?t.toString():t;s(e)&&(i[o]||(i[o]=[]),i[o].push({topic:o,callback:e,context:r,token:n}))})(t,e,this),this}$off(t,e){return u(t,e),this}addListeners(){return this}removeListeners(){return this}}const p=t=>!!(n(t)&&t.nodeName&&t.tagName&&1===t.nodeType),m=t=>t*t,f=(e=null)=>{let r,s;return e?t(e)?s=document.querySelector(e):p(e)&&(s=e):(r=document.querySelectorAll("html,body"),s=r[0].scrollTop-r[1].scrollTop>=0?r[0]:r[1]),s},y=t=>{let e=t.offsetTop;return null!==t.offsetParent&&(e+=y(t.offsetParent)),e},g=(t,e="")=>{const r=e.replace(/^>/i,"");return!!(e&&r&&t)&&(t.matches?t.matches(r):!!t.msMatchesSelector&&t.msMatchesSelector(r))},b=t=>t.host&&t!==document&&t.host.nodeType?t.host:t.parentNode,v=["focusout","blur","focusin","focus","load","unload","mouseenter","mouseleave"],$=(t,e,r)=>{const s=v.indexOf(e)>-1;r._delegateListener&&delete(r=r._delegateListener)._delegateListener,function(t,e,r){const s=t._listeners;let n=-1;if(s.length<1)return!1;s.forEach(((t,s)=>{const i=t.fn;e===t.type&&(n=s,i===r&&(n=s))})),n>-1&&s.splice(n,1)}(t,e,r),t.removeEventListener(e,r,s)},x=function(e,r,s=!1){const n=t(e)?document.querySelector(e):e,i=n.childNodes,o=((e,r)=>{let s=e._listeners||[];return t(r)&&r&&(s=s.filter((t=>t.type===r))),s})(n,r);o.forEach((t=>{$(n,t.type,t.fn)})),(s||!0===r||1===arguments.length)&&n&&i&&i.forEach((t=>{p(t)&&x(t,r,s)}))},A=(t,e,r)=>{if(!s(r))return x(t,e);$(t,e,r)},E=(t,e,r,s,n,i,o=!1)=>{const c=v.indexOf(r)>-1,l=function(c){const a=function(t){const e=t.target;return(r=e)&&3===r.nodeType?r.parentNode:r;var r}(c),h=((t,e,r,s)=>{const n=r||document;if(!t)return null;do{if(null!=e&&(e.startsWith(">")?t.parentNode===n&&g(t,e):g(t,e))||s&&t===n)return t;if(t===n)break}while(t=b(t))})(a,e,t);let u=i||t;c.delegateTarget=h,!0===i&&(u=n),h&&(!0===o&&A(t,r,l),s.call(u,c,n))};t._listeners||(t._listeners=[]),t._listeners.push({el:t,selector:e,type:r,fn:l,data:n,context:i,capture:c}),s._delegateListener=l,t.addEventListener(r,l,c)},L=t=>Array.isArray?Array.isArray(t):"[object Array]"===r(t),T=['','','','','','','','','',''],M=(e,r="icon")=>t(e)?((t,e="icon")=>{const r=/id="(.*?)"/,s=/^(\w+)-/;return T.find((n=>{const i=r.exec(n)[1];return s.exec(i)[1]===e&&i===("icon"===e?`${e}-${t}`:`${e}-icon-${t}`)}))})(e,r):[...T],z=(e="")=>{const r=document.body;let s=document.querySelector("#outline-icons"),n=[];(e=>{if(!e)return!1;L(e)&&e.length>0?e.forEach((e=>{-1===T.indexOf(e)&&t(e)&&T.push(e)})):t(e)&&T.push(e)})(e),n=M(),s?s.innerHTML=n.join(""):(s=document.createElement("div"),s.innerHTML=``,r.insertBefore(s.firstChild,r.firstChild))},w=e=>!!t(e)&&e.replace(/(^\s+)|(\s+$)/g,""),j=t=>{return!(!n(t)||!(p(t)||(t=>!(!n(t)||"[object NodeList]"!==r(t)))(t)||(e=t,n(e)&&"[object DocumentFragment]"===r(e))||(t=>!(!n(t)||!("[object Text]"===r(t)||t.tagName&&3===t.nodeType)))(t)));var e},S=(t,e,r)=>{let s=t.tagName.toLowerCase();switch(e){case"style":t.style.cssText=r;break;case"value":"input"===s||"textarea"===s?t.value=r:t.setAttribute(e,r);break;case"className":t.className=r;break;default:t.setAttribute(e,r)}},H=e=>{const r=new RegExp("^\\s*(?:<\\?xml[^>]*>\\s*)?(?:<\\!doctype svg[^>]*\\s*(?:\\[?(?:\\s*]*>\\s*)*\\]?)*[^>]*>\\s*)?]*>[^]*<\\/svg>\\s*$\\s*$","i");return t(e)&&r.test(e)},N=(e,r={})=>((e,r={})=>{const s=r.size||0,n=r.color||"",i=r.iconSet||"",o=L(s)?s[0]:s,c=L(s)?s[1]:s,l=s?`width:${o}px;height:${c}px;`:"",a=n?l+`color:${n}`:l,h=document.createElement("i");let u,d="",p="";return t(e)?(H(e)?p=e:(d=i&&"icon"!==i?`xlink:href="#${i}-icon-${e}"`:`xlink:href="#icon-${e}"`,p=``),h.className="outline-icon",h.innerHTML=p,H(e)&&(u=h.querySelector("svg"),u.setAttribute("aria-hidden","true"),u.setAttribute("xmlns","http://www.w3.org/2000/svg"),u.setAttribute("class","outline-icon__svg"),u.setAttribute("width","200"),u.setAttribute("height","200"),u.style.cssText=a),h):null})(e,r),_=(r,s,i)=>{const o=document.createDocumentFragment(),c="outline-heading",l=i.hasAnchor||!0,a=i.isAtStart||!0,h=i.showCode||!1,u=i.chapterCode||"",d=i.anchorURL||"",p=`heading-${s}`,m={id:p,className:a?`${c} ${c}_start`:c,"data-id":s},f=Object.keys(m),y=w(r.innerHTML);let g,b;if(f.forEach((t=>{S(r,t,m[t])})),h&&(r.innerHTML=u+" "+y),!l)return!1;b=N("hash",{iconSet:"outline"}),g=((r,s,i)=>{const o=document.createDocumentFragment(),c=document.createElement(r),l=e=>j(e)||t(e),a=e=>{let r;if(!l(e))return!1;j(e)?r=e:t(e)&&(r=document.createTextNode(e)),o.appendChild(r)};return n(s)?Object.keys(s).forEach((t=>{e(s,t)&&S(c,t,s[t])})):L(s)&&s.every((t=>l(t)))&&s.forEach((t=>{a(t)})),L(i)?i.forEach((t=>{a(t)})):a(i),c.appendChild(o),c})("a",{id:`anchor-${s}`,className:`${c}__anchor anchor-${s}`,href:d||`#${p}`,target:d?"_blank":"self","data-id":s},[b]),o.appendChild(g),r.appendChild(o)},k=(t,e)=>{let r,s=t.className;if(!s||!((t,e)=>{const r=new RegExp("(\\s|^)"+e+"(\\s|$)");let s,n;return!!p(t)&&(s=t.className,!!s&&(n=t.classList,n?.contains?t.classList.contains(e):!!r.exec(s)))})(t,e))return!1;r=t.classList,r?.remove?r.remove(e):(s=w(s.replace(e,"")),t.className=s)},C=(e,r=!0,s=!0)=>{const n="outline-heading",i=e.innerHTML;let o;if(e.innerHTML=i.replace(/^\d+(\.?\d+)*\s?/gi,""),e.removeAttribute("id"),e.removeAttribute("data-id"),k(e,n),!r)return!1;var c;o=e.querySelector(`.${n}__anchor`),s&&k(e,`${n}_start`),c=w(e.className),t(c)&&""===c&&e.removeAttribute("class"),e.removeChild(o)},O=(e,r=!0,n=null)=>{let i=1,o=0,c="";const l=[];return e.forEach(((e,r)=>{const a=e.tagName,h=a.replace(/h/i,"");let u=parseInt(h,10),d=-1;var p;u>i?(o+=1,d=1===o?-1:r-1):u===i||uo?1===u?(o=1,d=-1):d=l[r-1].pid:u<=o&&(1===u?o=1:(o-=i-u,o<=1&&(o=1)),d=1===o?-1:((t,e,r)=>{let s,n,i=t[r-1];for(n=0;n]+(>|$)/g,""):"",s(n)&&(c=n(c)),l.push({id:r,pid:d,level:o,rel:`heading-${r}`,text:c,tagName:a})})),r?(t=>{const e={};return t.forEach((t=>{const r=JSON.stringify((t=>[t.pid])(t));e[r]=e[r]||[],e[r].push(t),t.index=e[r].length,-1===t.pid&&(t.code=String(t.index))})),Object.keys(e).forEach((t=>{e[t].forEach((t=>{const r=e[`[${t.id}]`];if(!r||!L(r))return!1;r.forEach((e=>{e.code=t.code+"."+e.index}))}))})),t})(l):l};class B extends d{constructor(t){super(),this.attrs=B.DEFAULTS,this.$articleElement=null,this.$scrollElement=null,this.$headings=[],this.chapters=[],t&&this.initialize(t)}initialize(e){const r=this.attr("showCode")||!0;let n,i,o,c,l;return this.attr(e),l=this.attr("articleElement"),i=this.attr("scrollElement"),o=this.attr("selector"),n=this.attr("created"),t(l)?c=document.querySelector(l):p(l)&&(c=l),c?(this.$articleElement=c,this.$scrollElement=f(i),this.$headings=[...c.querySelectorAll(o)],this.$headings.length<1||(this.chapters=O(this.$headings,r,this.attr("chapterTextFilter")),s(n)&&n.call(this),this.render().addListeners()),this):this}getChapters(t=!1){const e=this.chapters;return t?((t,e,r)=>{const s={},n=[];return t.forEach(((t,r)=>{s[t[e]]=r,t.children=[]})),t.forEach((e=>{const i=t[s[e[r]]];-1!==e[r]?i.children.push(e):n.push(e)})),n})(e,"id","pid"):e}count(){return this.chapters.length}render(){const t=this.attr("mounted"),e=this.attr("hasAnchor"),r=this.attr("isAtStart"),n=this.attr("showCode"),i=this.attr("anchorURL"),o=this.$headings,c=this.getChapters();return z(),o.forEach(((t,s)=>{const o=c[s].code;_(t,s,{hasAnchor:e,isAtStart:r,showCode:n,chapterCode:o,anchorURL:i})})),s(t)&&t.call(this),this}scrollTo(t,e){return((t,e,r)=>{const n=f(t);let i=n.scrollTop,o=0;const c=e-i,l=n.scrollHeight,a=e-l<=0?e:l,h=t=>(s(r)&&r(t),!1),u=()=>{if(o+=1,c<0){if(i-=m(o),n.scrollTop=i,i<=e)return n.scrollTop=e,h(e)}else if(i+=m(o),n.scrollTop=i,i>=a)return n.scrollTop=a,h(a);requestAnimationFrame(u)};requestAnimationFrame(u)})(this.$scrollElement,t,e),this}destroy(){const t=this.attr("hasAnchor"),e=this.attr("isAtStart"),r=this.attr("beforeDestroy"),n=this.attr("afterDestroy"),i=this.$headings;return s(r)&&r.call(this),this.removeListeners(),i.forEach((r=>{C(r,t,e)})),this.attr(B.DEFAULTS),this.$articleElement=null,this.$scrollElement=null,this.$headings=[],this.chapters=[],s(n)&&n.call(this),this}onAnchorTrigger(t){const e=this.attr("anchorURL"),r=this.attr("afterScroll"),n=this.attr("stickyHeight"),i=t.delegateTarget.parentNode,o=y(i)-(n+10),c=this.$scrollElement,a=c.scrollHeight-c.clientHeight;return this.scrollTo(o,(()=>{s(r)&&r.call(this,"anchor"),((t,e=300)=>{!!s(t)&&setTimeout((()=>{t()}),e)})((()=>{l("toolbar:update",{top:o,min:0,max:a})}))})),e||function(t){t.stopPropagation(),t.preventDefault()}(t),this}addListeners(){const t=this.$articleElement;return E(t,".outline-heading__anchor","click",this.onAnchorTrigger,this,!0),this}removeListeners(){const t=this.$articleElement;return A(t,"click",this.onAnchorTrigger),this}}return B.DEFAULTS={scrollElement:"html,body",articleElement:"#article",selector:"h1,h2,h3,h4,h5,h6",stickyHeight:0,anchorURL:"",hasAnchor:!0,isAtStart:!0,showCode:!1,created:null,mounted:null,afterScroll:null,beforeDestroy:null,afterDestroy:null,chapterTextFilter:null},B})); +!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).Anchors=e()}(this,(function(){"use strict";const t=t=>"string"==typeof t,e=(t,e)=>{const r=Object.prototype.hasOwnProperty;return t&&r.call(t,e)},r=t=>Object.prototype.toString.apply(t),s=t=>"function"==typeof t||"[object Function]"===r(t),n=t=>("[object Object]"===r(t)||"object"==typeof t||s(t))&&null!==t,i={},o=t=>e(i,t)&&i[t].length>0,c=(t,e=!0)=>e?o(t):(t=>{let e=o(t),r=t.lastIndexOf(".");for(;!e&&-1!==r;)r=(t=t.substring(0,r)).lastIndexOf("."),e=o(t);return e})(t),l=(t,e,s=!0)=>{const n=t=>{if(!o(t))return!1;i[t].forEach((t=>{const s=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]","[object BigInt64Array]","[object BigUint64Array]"].indexOf(r(e))>-1?e.toString():e;t.callback.call(t.context||t,s)}))},l=()=>{let e=t,r=t.lastIndexOf(".");for(;-1!==r;)e=e.substring(0,r),r=e.lastIndexOf("."),n(e);n(t),n("*")};if(!c(t))return!1;s?setTimeout(l,10):l()},a=(()=>{let t=0;return e=>(t+=1,e?e+"-"+t:"guid-"+t)})(),h=t=>{if(!e(i,t))return!1;delete i[t]},u=(t,e)=>{if(!c(t))return!1;e?(t=>{const e=Object.keys(i);if(!t||e.length<1)return!1;e.forEach((e=>{const r=i[e];let s;r.forEach(((e,n)=>{e.callback!==t&&e.token!==t||(s=e.topic,r.splice(-1,n))})),r.length<1&&h(s)}))})(e):h(t)};class d{constructor(t){this.attrs={},t&&this.initialize(t)}initialize(t){return this.attr(t).render().addListeners(),this}attr(r,s){const i=this.attrs;return t(r)?s&&e(i,r)?(i[r]=s,this):i[r]:n(r)?(o=i,c=r,Object.keys(c).forEach((t=>{e(c,t)&&(o[t]=c[t])})),this):0===arguments.length?i:this;var o,c}render(){return this}destroy(){return this.removeListeners(),this}reload(t){return this.destroy().initialize(this.attr(t)),this}$emit(t,e){return l(t,e),this}$on(t,e){return((t,e,r=null)=>{const n=a();let o="symbol"==typeof t?t.toString():t;s(e)&&(i[o]||(i[o]=[]),i[o].push({topic:o,callback:e,context:r,token:n}))})(t,e,this),this}$off(t,e){return u(t,e),this}addListeners(){return this}removeListeners(){return this}}const p=t=>!!(n(t)&&t.nodeName&&t.tagName&&1===t.nodeType),m=t=>t*t,f=(e=null)=>{let r,s;return e?t(e)?s=document.querySelector(e):p(e)&&(s=e):(r=document.querySelectorAll("html,body"),s=r[0].scrollTop-r[1].scrollTop>=0?r[0]:r[1]),s},y=t=>{let e=t.offsetTop;return null!==t.offsetParent&&(e+=y(t.offsetParent)),e},g=(t,e="")=>{const r=e.replace(/^>/i,"");return!!(e&&r&&t)&&(t.matches?t.matches(r):!!t.msMatchesSelector&&t.msMatchesSelector(r))},b=t=>t.host&&t!==document&&t.host.nodeType?t.host:t.parentNode,v=["focusout","blur","focusin","focus","load","unload","mouseenter","mouseleave"],$=(t,e,r)=>{const s=v.indexOf(e)>-1;r._delegateListener&&delete(r=r._delegateListener)._delegateListener,function(t,e,r){const s=t._listeners;let n=-1;if(s.length<1)return!1;s.forEach(((t,s)=>{const i=t.fn;e===t.type&&(n=s,i===r&&(n=s))})),n>-1&&s.splice(n,1)}(t,e,r),t.removeEventListener(e,r,s)},x=function(e,r,s=!1){const n=t(e)?document.querySelector(e):e,i=n.childNodes,o=((e,r)=>{let s=e._listeners||[];return t(r)&&r&&(s=s.filter((t=>t.type===r))),s})(n,r);o.forEach((t=>{$(n,t.type,t.fn)})),(s||!0===r||1===arguments.length)&&n&&i&&i.forEach((t=>{p(t)&&x(t,r,s)}))},A=(t,e,r)=>{if(!s(r))return x(t,e);$(t,e,r)},E=(t,e,r,s,n,i,o=!1)=>{const c=v.indexOf(r)>-1,l=function(c){const a=function(t){const e=t.target;return(r=e)&&3===r.nodeType?r.parentNode:r;var r}(c),h=((t,e,r,s)=>{const n=r||document;if(!t)return null;do{if(null!=e&&(e.startsWith(">")?t.parentNode===n&&g(t,e):g(t,e))||s&&t===n)return t;if(t===n)break}while(t=b(t))})(a,e,t);let u=i||t;c.delegateTarget=h,!0===i&&(u=n),h&&(!0===o&&A(t,r,l),s.call(u,c,n))};t._listeners||(t._listeners=[]),t._listeners.push({el:t,selector:e,type:r,fn:l,data:n,context:i,capture:c}),s._delegateListener=l,t.addEventListener(r,l,c)},L=t=>Array.isArray?Array.isArray(t):"[object Array]"===r(t),T=['','','','','','','','','',''],M=(e,r="icon")=>t(e)?((t,e="icon")=>{const r=/id="(.*?)"/,s=/^(\w+)-/;return T.find((n=>{const i=r.exec(n)[1];return s.exec(i)[1]===e&&i===("icon"===e?`${e}-${t}`:`${e}-icon-${t}`)}))})(e,r):[...T],z=(e="")=>{const r=document.body;let s=document.querySelector("#outline-icons"),n=[];(e=>{if(!e)return!1;L(e)&&e.length>0?e.forEach((e=>{-1===T.indexOf(e)&&t(e)&&T.push(e)})):t(e)&&T.push(e)})(e),n=M(),s?s.innerHTML=n.join(""):(s=document.createElement("div"),s.innerHTML=``,r.insertBefore(s.firstChild,r.firstChild))},w=e=>!!t(e)&&e.replace(/(^\s+)|(\s+$)/g,""),j=t=>{return!(!n(t)||!(p(t)||(t=>!(!n(t)||"[object NodeList]"!==r(t)))(t)||(e=t,n(e)&&"[object DocumentFragment]"===r(e))||(t=>!(!n(t)||!("[object Text]"===r(t)||t.tagName&&3===t.nodeType)))(t)));var e},S=(t,e,r)=>{let s=t.tagName.toLowerCase();switch(e){case"style":t.style.cssText=r;break;case"value":"input"===s||"textarea"===s?t.value=r:t.setAttribute(e,r);break;case"className":t.className=r;break;default:t.setAttribute(e,r)}},H=e=>{const r=new RegExp("^\\s*(?:<\\?xml[^>]*>\\s*)?(?:<\\!doctype svg[^>]*\\s*(?:\\[?(?:\\s*]*>\\s*)*\\]?)*[^>]*>\\s*)?]*>[^]*<\\/svg>\\s*$\\s*$","i");return t(e)&&r.test(e)},N=(e,r={})=>((e,r={})=>{const s=r.size||0,n=r.color||"",i=r.iconSet||"",o=L(s)?s[0]:s,c=L(s)?s[1]:s,l=s?`width:${o}px;height:${c}px;`:"",a=n?l+`color:${n}`:l,h=document.createElement("i");let u,d="",p="";return t(e)?(H(e)?p=e:(d=i&&"icon"!==i?`xlink:href="#${i}-icon-${e}"`:`xlink:href="#icon-${e}"`,p=``),h.className="outline-icon",h.innerHTML=p,H(e)&&(u=h.querySelector("svg"),u.setAttribute("aria-hidden","true"),u.setAttribute("xmlns","http://www.w3.org/2000/svg"),u.setAttribute("class","outline-icon__svg"),u.setAttribute("width","200"),u.setAttribute("height","200"),u.style.cssText=a),h):null})(e,r),_=(r,s,i)=>{const o=document.createDocumentFragment(),c="outline-heading",l=i.hasAnchor||!0,a=i.isAtStart||!0,h=i.showCode||!1,u=i.chapterCode||"",d=i.anchorURL||"",p=`heading-${s}`,m={id:p,className:a?`${c} ${c}_start`:c,"data-id":s},f=Object.keys(m),y=w(r.innerHTML);let g,b;if(f.forEach((t=>{S(r,t,m[t])})),h&&(r.innerHTML=u+" "+y),!l)return!1;b=N("hash",{iconSet:"outline"}),g=((r,s,i)=>{const o=document.createDocumentFragment(),c=document.createElement(r),l=e=>j(e)||t(e),a=e=>{let r;if(!l(e))return!1;j(e)?r=e:t(e)&&(r=document.createTextNode(e)),o.appendChild(r)};return n(s)?Object.keys(s).forEach((t=>{e(s,t)&&S(c,t,s[t])})):L(s)&&s.every((t=>l(t)))&&s.forEach((t=>{a(t)})),L(i)?i.forEach((t=>{a(t)})):a(i),c.appendChild(o),c})("a",{id:`anchor-${s}`,className:`${c}__anchor anchor-${s}`,href:d||`#${p}`,target:d?"_blank":"self","data-id":s},[b]),o.appendChild(g),r.appendChild(o)},k=(t,e)=>{let r,s=t.className;if(!s||!((t,e)=>{const r=new RegExp("(\\s|^)"+e+"(\\s|$)");let s,n;return!!p(t)&&(s=t.className,!!s&&(n=t.classList,n?.contains?t.classList.contains(e):!!r.exec(s)))})(t,e))return!1;r=t.classList,r?.remove?r.remove(e):(s=w(s.replace(e,"")),t.className=s)},C=(e,r=!0,s=!0)=>{const n="outline-heading",i=e.innerHTML;let o;if(e.innerHTML=i.replace(/^\d+(\.?\d+)*\s?/gi,""),e.removeAttribute("id"),e.removeAttribute("data-id"),k(e,n),!r)return!1;var c;o=e.querySelector(`.${n}__anchor`),s&&k(e,`${n}_start`),c=w(e.className),t(c)&&""===c&&e.removeAttribute("class"),e.removeChild(o)},O=(e,r=!0,n=null)=>{let i=1,o=0,c="";const l=[];return e.forEach(((e,r)=>{const a=e.tagName,h=a.replace(/h/i,"");let u=parseInt(h,10),d=-1;var p;u>i?(o+=1,d=1===o?-1:r-1):u===i||uo?1===u?(o=1,d=-1):d=l[r-1].pid:u<=o&&(1===u?o=1:(o-=i-u,o<=1&&(o=1)),d=1===o?-1:((t,e,r)=>{let s,n,i=t[r-1];for(n=0;n]+(>|$)/g,""):"",s(n)&&(c=n(c)),l.push({id:r,pid:d,level:o,rel:`heading-${r}`,text:c,tagName:a})})),r?(t=>{const e={};return t.forEach((t=>{const r=JSON.stringify((t=>[t.pid])(t));e[r]=e[r]||[],e[r].push(t),t.index=e[r].length,-1===t.pid&&(t.code=String(t.index))})),Object.keys(e).forEach((t=>{e[t].forEach((t=>{const r=e[`[${t.id}]`];if(!r||!L(r))return!1;r.forEach((e=>{e.code=t.code+"."+e.index}))}))})),t})(l):l};class B extends d{constructor(t){super(),this.attrs=B.DEFAULTS,this.$articleElement=null,this.$scrollElement=null,this.$headings=[],this.chapters=[],t&&this.initialize(t)}initialize(e){const r=this.attr("showCode")||!0;let n,i,o,c,l;return this.attr(e),l=this.attr("articleElement"),i=this.attr("scrollElement"),o=this.attr("selector"),n=this.attr("created"),t(l)?c=document.querySelector(l):p(l)&&(c=l),c?(this.$articleElement=c,this.$scrollElement=f(i),this.$headings=[...c.querySelectorAll(o)],this.$headings.length<1||(this.chapters=O(this.$headings,r,this.attr("chapterTextFilter")),s(n)&&n.call(this),this.render().addListeners()),this):this}getChapters(t=!1){const e=this.chapters;return t?((t,e,r)=>{const s={},n=[];return t.forEach(((t,r)=>{s[t[e]]=r,t.children=[]})),t.forEach((e=>{const i=t[s[e[r]]];-1!==e[r]?i.children.push(e):n.push(e)})),n})(e,"id","pid"):e}count(){return this.chapters.length}render(){const t=this.attr("mounted"),e=this.attr("hasAnchor"),r=this.attr("isAtStart"),n=this.attr("showCode"),i=this.attr("anchorURL"),o=this.$headings,c=this.getChapters();return z(),o.forEach(((t,s)=>{const o=c[s].code;_(t,s,{hasAnchor:e,isAtStart:r,showCode:n,chapterCode:o,anchorURL:i})})),s(t)&&t.call(this),this}scrollTo(t,e){return((t,e,r)=>{const n=f(t);let i=n.scrollTop,o=0;const c=e-i,l=n.scrollHeight,a=e-l<=0?e:l,h=t=>(s(r)&&r(t),!1),u=()=>{if(o+=1,c<0){if(i-=m(o),n.scrollTop=i,i<=e)return n.scrollTop=e,h(e)}else if(i+=m(o),n.scrollTop=i,i>=a)return n.scrollTop=a,h(a);requestAnimationFrame(u)};requestAnimationFrame(u)})(this.$scrollElement,t,e),this}destroy(){const t=this.attr("hasAnchor"),e=this.attr("isAtStart"),r=this.attr("beforeDestroy"),n=this.attr("afterDestroy"),i=this.$headings;return s(r)&&r.call(this),this.removeListeners(),i.forEach((r=>{C(r,t,e)})),this.attr(B.DEFAULTS),this.$articleElement=null,this.$scrollElement=null,this.$headings=[],this.chapters=[],s(n)&&n.call(this),this}onAnchorTrigger(t){const e=this.attr("anchorURL"),r=this.attr("afterScroll"),n=this.attr("stickyHeight"),i=t.delegateTarget.parentNode,o=y(i)-(n+10),c=this.$scrollElement,l=c.scrollHeight-c.clientHeight;return this.scrollTo(o,(()=>{s(r)&&r.call(this,"anchor"),((t,e=300)=>{!!s(t)&&setTimeout((()=>{t()}),e)})((()=>{this.$emit("toolbar:update",{top:o,min:0,max:l})}))})),e||function(t){t.stopPropagation(),t.preventDefault()}(t),this}addListeners(){const t=this.$articleElement;return E(t,".outline-heading__anchor","click",this.onAnchorTrigger,this,!0),this}removeListeners(){const t=this.$articleElement;return A(t,"click",this.onAnchorTrigger),this}}return B.DEFAULTS={scrollElement:"html,body",articleElement:"#article",selector:"h1,h2,h3,h4,h5,h6",stickyHeight:0,anchorURL:"",hasAnchor:!0,isAtStart:!0,showCode:!1,created:null,mounted:null,afterScroll:null,beforeDestroy:null,afterDestroy:null,chapterTextFilter:null},B})); //# sourceMappingURL=anchors.min.js.map diff --git a/anchors.min.js.map b/anchors.min.js.map index 0cbe97aa..1a7492ea 100644 --- a/anchors.min.js.map +++ b/anchors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"anchors.min.js","sources":["utils/types/isString.js","utils/lang/hasOwn.js","utils/lang/toString.js","utils/types/isFunction.js","utils/types/isObject.js","utils/observer/_subscribers.js","utils/observer/_hasDirectSubscribersFor.js","utils/observer/has.js","utils/observer/_hasSubscribers.js","utils/observer/emit.js","utils/types/isTypedArray.js","utils/lang/guid.js","utils/observer/_removeSubscriber.js","utils/observer/off.js","utils/observer/_removeSubscriberByToken.js","base.js","utils/lang/extend.js","utils/observer/on.js","utils/types/isElement.js","utils/lang/easeInQuad.js","utils/dom/_getScrollElement.js","utils/dom/offsetTop.js","utils/dom/matches.js","utils/dom/getParentOrHost.js","utils/event/enum.js","utils/event/_off.js","utils/event/_delete.js","utils/event/purgeElement.js","utils/event/getListeners.js","utils/event/off.js","utils/event/on.js","utils/event/getTarget.js","utils/dom/resolveTextNode.js","utils/dom/closest.js","utils/types/isArray.js","utils/icons/symbols.js","utils/icons/defaults.js","utils/icons/getSymbols.js","utils/icons/getSymbol.js","utils/icons/paint.js","utils/icons/add.js","utils/lang/trim.js","utils/types/isDOM.js","utils/types/isHTMLCollection.js","utils/types/isFragment.js","utils/types/isTextNode.js","utils/dom/setAttribute.js","utils/types/isSVG.js","utils/icons/icon.js","utils/icons/createElement.js","_updateHeading.js","utils/dom/createElement.js","utils/dom/removeClass.js","utils/dom/hasClass.js","_resetHeading.js","utils/types/isEmpty.js","getChapters.js","utils/lang/stripTags.js","_getChapterParentIdByDiffer.js","_getChaptersWithCode.js","anchors.js","utils/lang/toTree.js","utils/dom/scrollTo.js","utils/lang/later.js","utils/event/stop.js"],"sourcesContent":["/**\n * 检测数据是否为 String 类型\n * ========================================================================\n * @method isArray\n * @param {*} str\n * @returns {boolean}\n */\nconst isString = (str) => {\n return typeof str === 'string'\n}\n\nexport default isString\n","/**\n * 检测对象自身属性中是否具有指定的属性。\n * ========================================================================\n * @method hasOwn\n * @param {Object} obj - (必须)检测的目标对象\n * @param {String} prop - (必须)属性名\n * @returns {Boolean}\n */\nconst hasOwn = (obj, prop) => {\n const hasOwnProperty = Object.prototype.hasOwnProperty\n return obj && hasOwnProperty.call(obj, prop)\n}\n\nexport default hasOwn\n","/**\n * Object 对象原型上的 toString 方法\n * ========================================================================\n * @method toString\n * @param {*} val\n * @returns {string}\n */\nconst toString = (val) => {\n return Object.prototype.toString.apply(val)\n}\n\nexport default toString\n","import toString from '../lang/toString'\n\n/**\n * 检测测试数据是否为 Function 类型\n * ========================================================================\n * @method isFunction\n * @param {*} val - (必须)待检测的数据\n * @returns {boolean} 'val' 是 Function 类型返回 true,否则返回 false\n */\nconst isFunction = (val) => {\n return typeof val === 'function' || toString(val) === '[object Function]'\n}\n\nexport default isFunction\n","import toString from '../lang/toString'\nimport isFunction from './isFunction'\n\n/**\n * 检测数据是否为 Object 类型\n * ========================================================================\n * @method isObject\n * @param {*} o\n * @returns {boolean}\n */\nconst isObject = (o) => {\n return (\n (toString(o) === '[object Object]' ||\n typeof o === 'object' ||\n isFunction(o)) &&\n o !== null\n )\n}\n\nexport default isObject\n","/**\n * 存储订阅者(主题和处理器的)私有对象\n * ========================================================================\n * @type {{}}\n * @private\n */\nconst _subscribers = {}\n\nexport default _subscribers\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 判断是否存在与给定 topic 完全匹配的订阅者信息\n * ========================================================================\n * @method _hasDirectSubscribersFor\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasDirectSubscribersFor = (topic) => {\n return hasOwn(_subscribers, topic) && _subscribers[topic].length > 0\n}\n\nexport default _hasDirectSubscribersFor\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\nimport _hasSubscribers from './_hasSubscribers'\n\n/**\n * 判断是否存在包含 topic 指定的订阅者信息\n * ========================================================================\n * @method has\n * @param {String} topic - (必须)主题名称\n * @param {Boolean} [isDirect] - (可选)是否为直接的主题,默认值:true\n * @returns {Boolean}\n */\nconst has = (topic, isDirect = true) => {\n return isDirect ? _hasDirectSubscribersFor(topic) : _hasSubscribers(topic)\n}\n\nexport default has\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * 判断是否存在包含给定 topic 相关的订阅者信息\n * ========================================================================\n * @method _hasSubscribers\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasSubscribers = (topic) => {\n let found = _hasDirectSubscribersFor(topic)\n let position = topic.lastIndexOf('.')\n\n while (!found && position !== -1) {\n topic = topic.substring(0, position)\n position = topic.lastIndexOf('.')\n found = _hasDirectSubscribersFor(topic)\n }\n\n return found\n}\n\nexport default _hasSubscribers\n","import isTypedArray from '../types/isTypedArray'\nimport _subscribers from './_subscribers'\nimport has from './has'\nimport _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * (异步)发布订阅主题信息\n * ========================================================================\n * 主题默认是异步发布的。确保在消费者处理主题时,主题的发起者不会被阻止。\n * ========================================================================\n * @method emit\n * @param {String} topic - (必须)主题名称\n * @param {Object} [data] - (可选)数据对象\n * @param {Boolean} [async] - (可选) 是否异步发布\n */\nconst emit = (topic, data, async = true) => {\n const execute = (topic) => {\n if (!_hasDirectSubscribersFor(topic)) {\n return false\n }\n\n _subscribers[topic].forEach((subscriber) => {\n // 针对 mqtt 消息服务返回的 Uint8Array 类似的 typed arrays 格式的数据\n // 采用 toString() 方法转化为普通(JSON)字符串\n const message = isTypedArray(data) ? data.toString() : data\n\n subscriber.callback.call(subscriber.context || subscriber, message)\n })\n }\n const deliver = () => {\n let subscriber = topic\n let position = topic.lastIndexOf('.')\n\n while (position !== -1) {\n subscriber = subscriber.substring(0, position)\n position = subscriber.lastIndexOf('.')\n\n execute(subscriber)\n }\n\n // 执行 topic 对应的处理器\n execute(topic)\n // 执行特殊 topic:'*'(监听全部消息的发布)\n execute('*')\n }\n\n if (!has(topic)) {\n return false\n }\n\n if (async) {\n setTimeout(deliver, 10)\n } else {\n deliver()\n }\n}\n\nexport default emit\n","import toString from '../lang/toString'\n/**\n * 判断检测数据是否为 Typed Arrays 类型的数据\n * ========================================================================\n * @param {*} val\n * @returns {boolean}\n */\nconst isTypedArray = (val) => {\n const TYPES = [\n '[object Int8Array]',\n '[object Uint8Array]',\n '[object Uint8ClampedArray]',\n '[object Int16Array]',\n '[object Uint16Array]',\n '[object Int32Array]',\n '[object Uint32Array]',\n '[object Float32Array]',\n '[object Float64Array]',\n '[object BigInt64Array]',\n '[object BigUint64Array]'\n ]\n\n return TYPES.indexOf(toString(val)) > -1\n}\n\nexport default isTypedArray\n","/**\n * 生成唯一 id 字符串的函数\n * ========================================================================\n * @method guid\n * @param {String} [prefix] - 生成 id 的前缀字符串\n * @return {String} 返回一个表示唯一 id 的字符串\n */\nconst guid = (() => {\n let uuid = 0\n\n return (prefix) => {\n uuid += 1\n\n return prefix ? prefix + '-' + uuid : 'guid-' + uuid\n }\n})()\n\nexport default guid\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 删除与给定 topic 相同的订阅者信息\n * ========================================================================\n * @method _removeSubscriber\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _removeSubscriber = (topic) => {\n if (!hasOwn(_subscribers, topic)) {\n return false\n }\n\n delete _subscribers[topic]\n}\n\nexport default _removeSubscriber\n","import has from './has'\nimport _removeSubscriber from './_removeSubscriber'\nimport _removeSubscriberByToken from './_removeSubscriberByToken'\n\n/**\n * 取消订阅主题\n * ========================================================================\n * @method off\n * @param {String} topic - (必须)订阅的主题\n * @param {Function|String} [token] - (可选)订阅主题的处理器函数或者唯一 Id 值\n */\nconst off = (topic, token) => {\n if (!has(topic)) {\n return false\n }\n\n if (token) {\n _removeSubscriberByToken(token)\n } else {\n _removeSubscriber(topic)\n }\n}\n\nexport default off\n","import _subscribers from './_subscribers'\nimport _removeSubscriber from './_removeSubscriber'\n\n/**\n * 通过订阅者 token 值删除订阅者信息\n * ========================================================================\n * @method _removeSubscriberByToken\n * @param {String} token - 订阅者 token 字符串\n * @returns {boolean}\n * @private\n */\nconst _removeSubscriberByToken = (token) => {\n const keys = Object.keys(_subscribers)\n let index = -1\n\n if (!token || keys.length < 1) {\n return false\n }\n\n keys.forEach((subject) => {\n const subscriber = _subscribers[subject]\n let topic\n\n subscriber.forEach((execution, j) => {\n if (execution.callback === token || execution.token === token) {\n topic = execution.topic\n subscriber.splice(index, j)\n }\n })\n\n /* istanbul ignore else */\n if (subscriber.length < 1) {\n _removeSubscriber(topic)\n }\n })\n}\n\nexport default _removeSubscriberByToken\n","import isString from './utils/types/isString'\r\nimport hasOwn from './utils/lang/hasOwn'\r\nimport isObject from './utils/types/isObject'\r\nimport extend from './utils/lang/extend'\r\nimport publish from './utils/observer/emit'\r\nimport subscribe from './utils/observer/on'\r\nimport unsubscribe from './utils/observer/off'\r\n\r\nclass Base {\r\n constructor(options) {\r\n this.attrs = {}\r\n\r\n if (options) {\r\n this.initialize(options)\r\n }\r\n }\r\n\r\n initialize(options) {\r\n this.attr(options).render().addListeners()\r\n return this\r\n }\r\n\r\n attr(prop, value) {\r\n const attrs = this.attrs\r\n\r\n if (isString(prop)) {\r\n // 只能扩展 attrs 中已有的属性\r\n if (value && hasOwn(attrs, prop)) {\r\n // 更新单个配置信息\r\n attrs[prop] = value\r\n return this\r\n }\r\n\r\n // 只传递 prop 参数,则返回对应的属性值\r\n return attrs[prop]\r\n } else if (isObject(prop)) {\r\n // 批量更新配置信息\r\n extend(attrs, prop)\r\n\r\n return this\r\n } else if (arguments.length === 0) {\r\n // 不传递参数,直接返回整个\r\n return attrs\r\n }\r\n\r\n return this\r\n }\r\n\r\n render() {\r\n return this\r\n }\r\n\r\n destroy() {\r\n this.removeListeners()\r\n return this\r\n }\r\n\r\n reload(options) {\r\n this.destroy().initialize(this.attr(options))\r\n return this\r\n }\r\n\r\n $emit(event, data) {\r\n publish(event, data)\r\n return this\r\n }\r\n\r\n $on(event, callback) {\r\n subscribe(event, callback, this)\r\n return this\r\n }\r\n\r\n $off(event, callback) {\r\n unsubscribe(event, callback)\r\n return this\r\n }\r\n\r\n addListeners() {\r\n return this\r\n }\r\n\r\n removeListeners() {\r\n return this\r\n }\r\n}\r\n\r\nexport default Base\r\n","import hasOwn from './hasOwn'\n\n/**\n * 扩展对象\n * ========================================================================\n * @method extend\n * @param {Object} origin\n * @param {Object} source\n */\nconst extend = (origin, source) => {\n const keys = Object.keys(source)\n\n keys.forEach((prop) => {\n if (hasOwn(source, prop)) {\n origin[prop] = source[prop]\n }\n })\n}\n\nexport default extend\n","import _subscribers from './_subscribers'\nimport isFunction from '../types/isFunction'\nimport guid from '../lang/guid'\n\n/**\n * 订阅主题,并给出处理器函数\n * ========================================================================\n * @method on\n * @param {String} topic - (必须)主题名称\n * @param {Function} handler - (必须)主题的处理器函数\n * @param {Object} [context] - (可选)指定 this 执行上下文\n * @return {String} - 唯一的 token 字符串,例如:'guid-1'。\n */\nconst on = (topic, handler, context = null) => {\n const token = guid()\n let subject = typeof topic === 'symbol' ? topic.toString() : topic\n\n if (!isFunction(handler)) {\n return ''\n }\n\n /* istanbul ignore else */\n if (!_subscribers[subject]) {\n _subscribers[subject] = []\n }\n\n _subscribers[subject].push({\n topic: subject,\n callback: handler,\n context,\n token\n })\n\n return token\n}\n\nexport default on\n","import isObject from './isObject'\n\n/**\n * 检测数据是否为 HTMLElement DOM 节点\n * ========================================================================\n * @method isElement\n * @param {*} o\n * @returns {boolean}\n */\nconst isElement = (o) => {\n return !!(isObject(o) && o.nodeName && o.tagName && o.nodeType === 1)\n}\n\nexport default isElement\n","/**\n * 返回给定值的平方值\n * ========================================================================\n * @method easeInQuad\n * @param {Number} x\n * @returns {number}\n */\nconst easeInQuad = (x) => {\n return x * x\n}\n\nexport default easeInQuad\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\n\n/**\n * 通过给的 scrollElement 参数,获取滚动 DOM 元素\n * ========================================================================\n * @method _getScrollElement\n * @param {String|HTMLElement} scrollElement\n * @returns {Element}\n * @private\n */\nconst _getScrollElement = (scrollElement = null) => {\n let $rootElements\n let $scrollElement\n\n if (!scrollElement) {\n $rootElements = document.querySelectorAll('html,body')\n $scrollElement =\n $rootElements[0].scrollTop - $rootElements[1].scrollTop >= 0\n ? $rootElements[0]\n : $rootElements[1]\n } else {\n if (isString(scrollElement)) {\n $scrollElement = document.querySelector(scrollElement)\n } else if (isElement(scrollElement)) {\n $scrollElement = scrollElement\n }\n }\n\n return $scrollElement\n}\n\nexport default _getScrollElement\n","/**\n * 获取 DOM 节点相对于窗口的 left (纵坐标)值\n * ========================================================================\n * @method offsetTop\n * @param {HTMLElement} el - DOM 节点\n * @returns {Number}\n */\nconst offsetTop = (el) => {\n let top = el.offsetTop\n\n if (el.offsetParent !== null) {\n top += offsetTop(el.offsetParent)\n }\n\n return top\n}\n\nexport default offsetTop\n","/**\n * 获取 options 节点下匹配 selector 选择器的 DOM 节点\n * ========================================================================\n * Element.matches() 方法可以用来判断 DOM 元素是否与给定的选择器匹配,事件代理判断是\n * 否触发绑定的代理事件回调函数,关键就是使用 Element.matches() 辨别当前事件触发的目\n * 标 DOM 元素是否为事件代理所期望触发的目标。\n * ========================================================================\n * @method matches\n * @see https://developer.mozilla.org/en-US/docs/web/api/element/matches\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)匹配 DOM 元素的选择器\n * @returns {Boolean}\n */\nconst matches = (el, selector = '') => {\n const sel = selector.replace(/^>/i, '')\n\n if (!selector || !sel || !el) {\n return false\n }\n\n /* istanbul ignore else */\n if (el.matches) {\n return el.matches(sel)\n } else if (el.msMatchesSelector) {\n return el.msMatchesSelector(sel)\n } else {\n return false\n }\n}\n\nexport default matches\n","/**\n * 获取 DOM 元素的父节点\n * ========================================================================\n * @method getParentOrHost\n * @param {*|HTMLElement} el - (必须)要获取父节点的 DOM 元素\n * @returns {*|HTMLElement}\n */\nconst getParentOrHost = (el) => {\n return el.host && el !== document && el.host.nodeType\n ? el.host\n : el.parentNode\n}\n\nexport default getParentOrHost\n","export const CAPTURE_EVENTS = [\n 'focusout',\n 'blur',\n 'focusin',\n 'focus',\n 'load',\n 'unload',\n 'mouseenter',\n 'mouseleave'\n]\n","import { CAPTURE_EVENTS } from './enum'\nimport _delete from './_delete'\n\n/**\n * (私有方法)取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method _off\n * @param {HTMLElement} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} fn - (必须)事件处理器回调函数\n * @private\n */\nconst _off = (el, type, fn) => {\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n /* istanbul ignore else */\n if (fn._delegateListener) {\n fn = fn._delegateListener\n delete fn._delegateListener\n }\n\n // 移除缓存的 _listeners 数据\n _delete(el, type, fn)\n\n el.removeEventListener(type, fn, capture)\n}\n\nexport default _off\n","/**\n * 删除 DOM 元素缓存的 _listeners 数据\n * ========================================================================\n * @method _delete\n * @param {HTMLElement} el - 要删除 listener 的 DOM 元素\n * @param {String} type - 事件类型(名称)\n * @param {Function} [fn] - 事件处理器回调函数\n */\nconst _delete = function (el, type, fn) {\n const listeners = el._listeners\n let index = -1\n\n if (listeners.length < 1) {\n return false\n }\n\n // 移除缓存的 _listeners 数据\n listeners.forEach((listener, i) => {\n const handler = listener.fn\n\n if (type === listener.type) {\n index = i\n\n if (handler === fn) {\n index = i\n }\n }\n })\n\n /* istanbul ignore else */\n if (index > -1) {\n listeners.splice(index, 1)\n }\n}\n\nexport default _delete\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\nimport getListeners from './getListeners'\nimport _off from './_off'\n\n/**\n * 销毁(type 类型的)代理事件绑定\n * ========================================================================\n * 1. 设置了事件类型 type,则销毁指定类型的事件绑定,否则清除所有代理事件绑定\n * 2. recurse 设置为 true,递归销毁子节点全部事件绑定\n * ========================================================================\n * @method purgeElement\n * @param {HTMLElement|String} el - (必须)DOM 元素或者其选择器\n * @param {String|Boolean} type - (必须)事件类型\n * @param {Boolean} [recurse] - (可选)是否递归销毁子节点所有事件绑定\n */\nconst purgeElement = function (el, type, recurse = false) {\n const $element = isString(el) ? document.querySelector(el) : el\n const $children = $element.childNodes\n const listeners = getListeners($element, type)\n\n listeners.forEach((listener) => {\n _off($element, listener.type, listener.fn)\n })\n\n if (\n (recurse || type === true || arguments.length === 1) &&\n $element &&\n $children\n ) {\n $children.forEach(($child) => {\n if (isElement($child)) {\n purgeElement($child, type, recurse)\n }\n })\n }\n}\n\nexport default purgeElement\n","import isString from '../types/isString'\n\n/**\n * 获取 DOM 元素(type 事件类型)事件绑定信息\n * ========================================================================\n * 如果设置了事件类型 type, 则返回指定类型的事件绑定信息,否则返回所有事件绑定信息\n * ========================================================================\n * @methods getListeners\n * @param {HTMLElement} el - (必须)要获取事件绑定信息的 DOM 元素\n * @param {String} [type] - (可选)事件类型\n * @returns {Array} - 已绑定的事件信息\n */\nconst getListeners = (el, type) => {\n let listeners = el._listeners || []\n\n if (isString(type) && type) {\n listeners = listeners.filter((listener) => {\n return listener.type === type\n })\n }\n\n return listeners\n}\n\nexport default getListeners\n","import purgeElement from './purgeElement'\nimport isFunction from '../types/isFunction'\nimport _off from './_off'\n\n/**\n * 取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method off\n * @param {HTMLElement|Object} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} [fn] - (可选)事件处理器回调函数\n */\nconst off = (el, type, fn) => {\n // 如果不设置 fn 参数,默认清除 el 元素上绑定的所有事件处理器\n if (!isFunction(fn)) {\n return purgeElement(el, type)\n }\n\n _off(el, type, fn)\n}\n\nexport default off\n","import closest from '../dom/closest'\nimport off from './off'\nimport getTarget from './getTarget'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定代理事件\n * ========================================================================\n * @method on\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String} selector - (必须)事件代理目标 DOM 元素的选择器\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (可选) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst on = (el, selector, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n const listener = function (evt) {\n const target = getTarget(evt)\n // 通过 Element.matches 方法获得点击的目标元素\n const delegateTarget = closest(target, selector, el)\n let overrideContext = context || el\n\n evt.delegateTarget = delegateTarget\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n /* istanbul ignore else */\n if (delegateTarget) {\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n selector,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default on\n","import resolveTextNode from '../dom/resolveTextNode'\n\n/**\n * 返回触发事件的 target DOM 元素\n * ========================================================================\n * @method getTarget\n * @param {Event} evt - Event 对象\n * @return {HTMLElement} - Event 对象的 target DOM 元素\n */\nconst getTarget = function (evt) {\n const target = evt.target\n\n return resolveTextNode(target)\n}\n\nexport default getTarget\n","/**\n * 在某些情况下,某些浏览器(例如:Safari 浏览器)会返回实际的目标元素内部的文本节点。\n * resolveTextNode() 方法则会返回实际的目标节点。\n * ========================================================================\n * @method resolveTextNode\n * @param {HTMLElement|Text} el - 要解析的节点\n * @return {*|HTMLElement} - 实际的目标 DOM 节点\n */\nconst resolveTextNode = function (el) {\n if (el && el.nodeType === 3) {\n return el.parentNode\n }\n\n return el\n}\n\nexport default resolveTextNode\n","import matches from './matches'\nimport getParentOrHost from './getParentOrHost'\n\n/**\n * 获取 options 元素父元素最近的包含 selector 选择器的元素\n * ========================================================================\n * @method closest\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)DOM 元素的选择其\n * @param {HTMLElement} [ctx] - (必须)比对的 DOM 元素\n * @param {Boolean} [includeCTX] - (必须)是否包含 context DOM 元素\n * @returns {null|HTMLElement} - 返回最接近的 DOM 元素\n */\nconst closest = (el, selector, ctx, includeCTX) => {\n const context = ctx || document\n\n if (!el) {\n return null\n }\n\n do {\n /* istanbul ignore else */\n if (\n (selector != null &&\n (selector.startsWith('>')\n ? el.parentNode === context && matches(el, selector)\n : matches(el, selector))) ||\n (includeCTX && el === context)\n ) {\n return el\n }\n\n /* istanbul ignore else */\n if (el === context) {\n break\n }\n\n /* jshint boss:true */\n } while ((el = getParentOrHost(el)))\n}\n\nexport default closest\n","import toString from '../lang/toString'\n\n/**\n * 检测数据是否为 Array 类型\n * ========================================================================\n * @method isArray\n * @param {*} o\n * @returns {boolean}\n */\nconst isArray = (o) => {\n if (Array.isArray) {\n return Array.isArray(o)\n } else {\n return toString(o) === '[object Array]'\n }\n}\n\nexport default isArray\n","import DEFAULTS from './defaults'\n\nconst SYMBOLS = [...DEFAULTS]\n\nexport default SYMBOLS\n","const DEFAULTS = [\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n ''\n]\n\nexport default DEFAULTS\n","import isString from '../types/isString'\nimport getSymbol from './getSymbol'\nimport SYMBOLS from './symbols'\n\n/**\n *\n * @method getSymbols\n * @param {String} [name]\n * @param {String} [iconSet]\n * @returns {string[]|*}\n */\nconst getSymbols = (name, iconSet = 'icon') => {\n if (isString(name)) {\n return getSymbol(name, iconSet)\n }\n\n return [...SYMBOLS]\n}\n\nexport default getSymbols\n","import SYMBOLS from './symbols'\n\n/**\n * @method getSymbol\n * @param {String} name\n * @param {String} [iconSet]\n * @returns {String}\n */\nconst getSymbol = (name, iconSet = 'icon') => {\n const patternName = /id=\"(.*?)\"/\n const patternSet = /^(\\w+)-/\n const symbols = SYMBOLS\n\n return symbols.find((symbol) => {\n const names = patternName.exec(symbol)\n const fullName = names[1]\n const sets = patternSet.exec(fullName)\n const setName = sets[1]\n const iconName =\n iconSet === 'icon' ? `${iconSet}-${name}` : `${iconSet}-icon-${name}`\n\n return setName === iconSet && fullName === iconName\n })\n}\n\nexport default getSymbol\n","import add from './add'\nimport getSymbols from './getSymbols'\n\n/**\n * 绘制 SVG 图标集\n * ========================================================================\n * @method paint\n * @param {String|Array} symbol\n */\nconst paint = (symbol = '') => {\n const $body = document.body\n let $icons = document.querySelector('#outline-icons')\n let symbols = []\n\n add(symbol)\n symbols = getSymbols()\n\n if ($icons) {\n $icons.innerHTML = symbols.join('')\n } else {\n $icons = document.createElement('div')\n $icons.innerHTML =\n ``\n $body.insertBefore($icons.firstChild, $body.firstChild)\n }\n}\n\nexport default paint\n","import isArray from '../types/isArray'\nimport isString from '../types/isString'\nimport SYMBOLS from './symbols'\n\n/**\n * @method add\n * @param {Array|String} symbols\n * @return {Boolean}\n */\nconst add = (symbols) => {\n if (!symbols) {\n return false\n }\n\n if (isArray(symbols) && symbols.length > 0) {\n symbols.forEach((symbol) => {\n /* istanbul ignore else */\n if (SYMBOLS.indexOf(symbol) === -1 && isString(symbol)) {\n SYMBOLS.push(symbol)\n }\n })\n } else {\n /* istanbul ignore else */\n if (isString(symbols)) {\n SYMBOLS.push(symbols)\n }\n }\n}\n\nexport default add\n","import isString from '../types/isString'\n\n/**\n * 清楚字符串起始位置所有的空格\n * ========================================================================\n * @method trim\n * @param {string} str\n * @returns {string|Boolean}\n */\nconst trim = (str) => {\n if (!isString(str)) {\n return false\n }\n return str.replace(/(^\\s+)|(\\s+$)/g, '')\n}\n\nexport default trim\n","import isObject from './isObject'\r\nimport isElement from './isElement'\r\nimport isHTMLCollection from './isHTMLCollection'\r\nimport isFragment from './isFragment'\r\nimport isTextNode from './isTextNode'\r\n\r\nconst isDOM = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (isElement(el) || isHTMLCollection(el) || isFragment(el) || isTextNode(el))\r\n )\r\n}\r\n\r\nexport default isDOM\r\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isHTMLCollection = (el) => {\r\n return !!(isObject(el) && toString(el) === '[object NodeList]')\r\n}\r\n\r\nexport default isHTMLCollection\r\n","import toString from '../lang/toString'\nimport isObject from './isObject'\n\nconst isFragment = (fragment) => {\n return !!(\n isObject(fragment) && toString(fragment) === '[object DocumentFragment]'\n )\n}\n\nexport default isFragment\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isTextNode = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (toString(el) === '[object Text]' || (el.tagName && el.nodeType === 3))\r\n )\r\n}\r\n\r\nexport default isTextNode\r\n","/**\n * 给 DOM 节点设置属性/值\n * ========================================================================\n * @method setAttribute\n * @param {HTMLElement} el - DOM 节点\n * @param {String} attr - 属性名称\n * @param {String|Number|Boolean} value - 属性值\n */\nconst setAttribute = (el, attr, value) => {\n let tagName = el.tagName.toLowerCase()\n\n switch (attr) {\n case 'style':\n el.style.cssText = value\n break\n case 'value':\n if (tagName === 'input' || tagName === 'textarea') {\n el.value = value\n } else {\n el.setAttribute(attr, value)\n }\n break\n case 'className':\n el.className = value\n break\n default:\n el.setAttribute(attr, value)\n break\n }\n}\n\nexport default setAttribute\n","import isString from './isString'\n\nconst isSVG = (str) => {\n const declaration = '(?:<\\\\?xml[^>]*>\\\\s*)?'\n const doctype =\n '(?:<\\\\!doctype svg[^>]*\\\\s*(?:\\\\[?(?:\\\\s*]*>\\\\s*)*\\\\]?)*[^>]*>\\\\s*)?'\n const content = ']*>[^]*<\\\\/svg>\\\\s*$'\n const svg = `^\\\\s*${declaration}${doctype}${content}\\\\s*$`\n const pattern = new RegExp(svg, 'i')\n\n return isString(str) && pattern.test(str)\n}\n\nexport default isSVG\n","import createElement from './createElement'\n\n/**\n * 创建 SVG 图标 DOM 元素\n * ========================================================================\n * @method icon\n * @alias createElement\n * @see createElement\n * @param {String} name\n * @param {Object} [options]\n * @param {Number|Array} [options.size]\n * @param {String} [options.color]\n * @param {String} [options.iconSet]\n * @returns {HTMLElement}\n */\nconst icon = (name, options = {}) => {\n return createElement(name, options)\n}\n\nexport default icon\n","import isArray from '../types/isArray'\nimport isString from '../types/isString'\nimport isSVG from '../types/isSVG'\n\n/**\n * 创建 SVG 图标 DOM 元素\n * ========================================================================\n * @method createElement\n * @param {String} name\n * @param {Object} [options]\n * @param {Number|Array} [options.size]\n * @param {String} [options.color]\n * @param {String} [options.iconSet]\n * @returns {HTMLElement}\n */\nconst createElement = (name, options = {}) => {\n const size = options.size || 0\n const color = options.color || ''\n const iconSet = options.iconSet || ''\n const width = isArray(size) ? size[0] : size\n const height = isArray(size) ? size[1] : size\n const defaultRules = size ? `width:${width}px;height:${height}px;` : ''\n const cssRules = color ? defaultRules + `color:${color}` : defaultRules\n const $icon = document.createElement('i')\n let binds = ''\n let svg = ''\n let $svg\n\n if (!isString(name)) {\n return null\n }\n\n if (isSVG(name)) {\n svg = name\n } else {\n binds =\n iconSet && iconSet !== 'icon'\n ? `xlink:href=\"#${iconSet}-icon-${name}\"`\n : `xlink:href=\"#icon-${name}\"`\n svg =\n `` +\n `` +\n ``\n }\n\n $icon.className = 'outline-icon'\n $icon.innerHTML = svg\n\n if (isSVG(name)) {\n $svg = $icon.querySelector('svg')\n $svg.setAttribute('aria-hidden', 'true')\n $svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n $svg.setAttribute('class', 'outline-icon__svg')\n $svg.setAttribute('width', '200')\n $svg.setAttribute('height', '200')\n $svg.style.cssText = cssRules\n }\n\n return $icon\n}\n\nexport default createElement\n","import trim from './utils/lang/trim'\nimport createElement from './utils/dom/createElement'\nimport setAttribute from './utils/dom/setAttribute'\n\nimport icon from './utils/icons/icon'\n\nconst _updateHeading = ($heading, i, options) => {\n const $fragment = document.createDocumentFragment()\n const CLS_HEADING = 'outline-heading'\n const hasAnchor = options.hasAnchor || true\n const isAtStart = options.isAtStart || true\n const showCode = options.showCode || false\n const chapterCode = options.chapterCode || ''\n const anchorURL = options.anchorURL || ''\n const headingId = `heading-${i}`\n const attrs = {\n id: headingId,\n className: isAtStart ? `${CLS_HEADING} ${CLS_HEADING}_start` : CLS_HEADING,\n 'data-id': i\n }\n const keys = Object.keys(attrs)\n const text = trim($heading.innerHTML)\n let $anchor\n let $icon\n\n keys.forEach((prop) => {\n setAttribute($heading, prop, attrs[prop])\n })\n\n if (showCode) {\n $heading.innerHTML = chapterCode + ' ' + text\n }\n\n if (!hasAnchor) {\n return false\n }\n\n $icon = icon('hash', { iconSet: 'outline' })\n $anchor = createElement(\n 'a',\n {\n id: `anchor-${i}`,\n className: `${CLS_HEADING}__anchor anchor-${i}`,\n href: anchorURL || `#${headingId}`,\n target: anchorURL ? '_blank' : 'self',\n 'data-id': i\n },\n [$icon]\n )\n $fragment.appendChild($anchor)\n $heading.appendChild($fragment)\n}\n\nexport default _updateHeading\n","import hasOwn from '../lang/hasOwn'\nimport isObject from '../types/isObject'\nimport isString from '../types/isString'\nimport isArray from '../types/isArray'\nimport isDOM from '../types/isDOM'\nimport setAttribute from './setAttribute'\n\n/**\n * 创建 DOM 节点,并添加属性和子节点\n * ========================================================================\n * @method createElement\n * @param {String} tagName - 标签名称\n * @param {Object|Array} attrs - 属性对象或者子节点\n * @param {Array} [children] - 子节点数组\n * @returns {HTMLElement}\n */\nconst createElement = (tagName, attrs, children) => {\n const $fragment = document.createDocumentFragment()\n const $el = document.createElement(tagName)\n const isValidChild = (child) => {\n return isDOM(child) || isString(child)\n }\n const append = (child) => {\n let $child\n\n if (!isValidChild(child)) {\n return false\n }\n\n if (isDOM(child)) {\n $child = child\n } else if (isString(child)) {\n $child = document.createTextNode(child)\n }\n\n $fragment.appendChild($child)\n }\n\n if (isObject(attrs)) {\n Object.keys(attrs).forEach((attr) => {\n if (hasOwn(attrs, attr)) {\n setAttribute($el, attr, attrs[attr])\n }\n })\n } else if (isArray(attrs) && attrs.every((attr) => isValidChild(attr))) {\n attrs.forEach((child) => {\n append(child)\n })\n }\n\n if (isArray(children)) {\n children.forEach((child) => {\n append(child)\n })\n } else {\n append(children)\n }\n\n $el.appendChild($fragment)\n\n return $el\n}\n\nexport default createElement\n","import trim from '../lang/trim'\nimport hasClass from './hasClass'\n\n/**\n * 移除 DOM 节点的 className 样式\n * ========================================================================\n * @method removeClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst removeClass = (el, className) => {\n let allClass = el.className\n let classList\n\n if (!allClass || !hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.remove) {\n classList.remove(className)\n } else {\n allClass = trim(allClass.replace(className, ''))\n el.className = allClass\n }\n}\n\nexport default removeClass\n","import isElement from '../types/isElement'\n/**\n * 检测 DOM 节点是否包含名为 className 的样式\n * ========================================================================\n * @method hasClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst hasClass = (el, className) => {\n const pattern = new RegExp('(\\\\s|^)' + className + '(\\\\s|$)')\n let allClass\n let classList\n\n if (!isElement(el)) {\n return false\n }\n\n allClass = el.className\n\n if (!allClass) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.contains) {\n return el.classList.contains(className)\n }\n\n return !!pattern.exec(allClass)\n}\n\nexport default hasClass\n","import removeClass from './utils/dom/removeClass'\nimport isEmpty from './utils/types/isEmpty'\nimport trim from './utils/lang/trim'\n\nconst _resetHeading = ($heading, hasAnchor = true, isAtStart = true) => {\n const CLS_HEADING = 'outline-heading'\n const text = $heading.innerHTML\n const pattern = /^\\d+(\\.?\\d+)*\\s?/gi\n let $anchor\n\n $heading.innerHTML = text.replace(pattern, '')\n $heading.removeAttribute('id')\n $heading.removeAttribute('data-id')\n\n removeClass($heading, CLS_HEADING)\n\n if (!hasAnchor) {\n return false\n }\n\n $anchor = $heading.querySelector(`.${CLS_HEADING}__anchor`)\n\n if (isAtStart) {\n removeClass($heading, `${CLS_HEADING}_start`)\n }\n\n if (isEmpty(trim($heading.className))) {\n $heading.removeAttribute('class')\n }\n\n $heading.removeChild($anchor)\n}\n\nexport default _resetHeading\n","import isString from './isString'\n/**\n * 检测数据是否为空字符串\n * ========================================================================\n * @method isEmpty\n * @param {String} str\n * @returns {boolean}\n */\nconst isEmpty = (str) => {\n return isString(str) && str === ''\n}\n\nexport default isEmpty\n","import trim from './utils/lang/trim'\nimport stripTags from './utils/lang/stripTags'\nimport isFunction from './utils/types/isFunction'\n\nimport _getChapterParentIdByDiffer from './_getChapterParentIdByDiffer'\nimport _getChaptersWithCode from './_getChaptersWithCode'\n\n/**\n * 根据文章中的 h1~h6 标签,自动分析返回文章章节数据\n * ========================================================================\n * @method getChapters\n * @param {Array} headings\n * @param {Boolean} [showCode]\n * @param {Function} [chapterTextFilter]\n * @return {*|*[]}\n */\nconst getChapters = (headings, showCode = true, chapterTextFilter = null) => {\n let previous = 1\n let level = 0\n let text = ''\n const chapters = []\n\n headings.forEach((heading, i) => {\n const tagName = heading.tagName\n const headingLevel = tagName.replace(/h/i, '')\n let current = parseInt(headingLevel, 10)\n let pid = -1\n\n // 场景1:当前标题是前一个标题的子标题\n // 当前标题的(标题标签)序号 > 前一个标题的序号:两个相连的标题是父标题 -> 子标题关系;\n // h2 (前一个标题)\n // h3 (当前标题)\n if (current > previous) {\n level += 1\n\n // 第一层级的 pid 是 -1\n if (level === 1) {\n pid = -1\n } else {\n pid = i - 1\n }\n }\n // 场景2:当前标题和前一个标题层级相同\n // 当前标题的(标题标签)序号 = 前一个标题的序号\n // h2 (前一个标题)\n // h2 (当前标题)\n // 当前标题的(标题标签)序号 < 前一个标题的序号,并且当前标题序号 > 当前的级别\n // h2\n // h4 (前一个标题)\n // h3 (当前标题:这种情况我们还是任务 h3 是 h2 的下一级章节)\n else if (current === previous || (current < previous && current > level)) {\n // H1 的层级肯定是 1\n if (current === 1) {\n level = 1\n pid = -1\n } else {\n pid = chapters[i - 1].pid\n }\n }\n // 场景3:当前标题比前一个标题层级高\n else if (current <= level) {\n // H1 的层级肯定是 1\n if (current === 1) {\n level = 1\n } else {\n level = level - (previous - current)\n\n if (level <= 1) {\n level = 1\n }\n }\n\n // 第一级的标题\n if (level === 1) {\n pid = -1\n } else {\n // 通过当前标题和前一个标题之间的等级差,获得当前标题的父标题ID\n pid = _getChapterParentIdByDiffer(chapters, previous - current, i)\n }\n }\n\n previous = current\n\n text = stripTags(trim(heading.innerHTML))\n\n if (isFunction(chapterTextFilter)) {\n text = chapterTextFilter(text)\n }\n\n chapters.push({\n id: i,\n pid: pid,\n level: level,\n rel: `heading-${i}`,\n text,\n tagName\n })\n })\n\n return showCode ? _getChaptersWithCode(chapters) : chapters\n}\n\nexport default getChapters\n","import isString from '../types/isString'\n\n/**\n * 过滤所有 HTML 标签\n * ========================================================================\n * @method stripTags\n * @param {string} str\n * @returns {string}\n */\nconst stripTags = (str) => {\n if (!isString(str)) {\n return ''\n }\n return str.replace(/<\\/?[^>]+(>|$)/g, '')\n}\n\nexport default stripTags\n","const _getChapterParentIdByDiffer = (chapters, differ, index) => {\n let previous = chapters[index - 1]\n let pid\n let i\n\n for (i = 0; i < differ; i += 1) {\n pid = previous.pid\n previous = chapters[pid]\n }\n\n pid = previous.pid\n\n return pid\n}\n\nexport default _getChapterParentIdByDiffer\n","import isArray from './utils/types/isArray'\n\nconst _getChaptersWithCode = (chapters) => {\n const groups = {}\n const cb = (o) => {\n return [o.pid]\n }\n\n chapters.forEach((o) => {\n const group = JSON.stringify(cb(o))\n\n groups[group] = groups[group] || []\n groups[group].push(o)\n\n o.index = groups[group].length\n if (o.pid === -1) {\n o.code = String(o.index)\n }\n })\n\n Object.keys(groups).forEach((group) => {\n groups[group].forEach((c) => {\n const subjects = groups[`[${c.id}]`]\n if (!subjects || !isArray(subjects)) {\n return false\n }\n subjects.forEach((o) => {\n o.code = c.code + '.' + o.index\n })\n })\n })\n\n return chapters\n}\n\nexport default _getChaptersWithCode\n","import Base from './base'\n\n// 在文章的标题生成 anchor 链接\nimport isString from './utils/types/isString'\nimport isFunction from './utils/types/isFunction'\nimport isElement from './utils/types/isElement'\nimport toTree from './utils/lang/toTree'\nimport later from './utils/lang/later'\nimport scrollTo from './utils/dom/scrollTo'\nimport _getScrollElement from './utils/dom/_getScrollElement'\nimport offsetTop from './utils/dom/offsetTop'\nimport on from './utils/event/on'\nimport off from './utils/event/off'\nimport stop from './utils/event/stop'\nimport publish from './utils/observer/emit'\nimport paint from './utils/icons/paint'\n\nimport _updateHeading from './_updateHeading'\nimport _resetHeading from './_resetHeading'\nimport getChapters from './getChapters'\n\nclass Anchors extends Base {\n constructor(options) {\n super()\n\n this.attrs = Anchors.DEFAULTS\n this.$articleElement = null\n this.$scrollElement = null\n this.$headings = []\n\n this.chapters = []\n\n if (options) {\n this.initialize(options)\n }\n }\n\n initialize(options) {\n const showCode = this.attr('showCode') || true\n let created\n let scrollElement\n let selector\n let $articleElement\n let articleElement\n\n this.attr(options)\n articleElement = this.attr('articleElement')\n scrollElement = this.attr('scrollElement')\n selector = this.attr('selector')\n created = this.attr('created')\n\n if (isString(articleElement)) {\n $articleElement = document.querySelector(articleElement)\n } else if (isElement(articleElement)) {\n $articleElement = articleElement\n }\n\n if (!$articleElement) {\n return this\n }\n\n this.$articleElement = $articleElement\n this.$scrollElement = _getScrollElement(scrollElement)\n this.$headings = [...$articleElement.querySelectorAll(selector)]\n\n if (this.$headings.length < 1) {\n return this\n }\n\n this.chapters = getChapters(\n this.$headings,\n showCode,\n this.attr('chapterTextFilter')\n )\n\n if (isFunction(created)) {\n created.call(this)\n }\n\n this.render().addListeners()\n\n return this\n }\n\n getChapters(isTreeStructured = false) {\n const chapters = this.chapters\n return isTreeStructured ? toTree(chapters, 'id', 'pid') : chapters\n }\n\n count() {\n return this.chapters.length\n }\n\n render() {\n const mounted = this.attr('mounted')\n const hasAnchor = this.attr('hasAnchor')\n const isAtStart = this.attr('isAtStart')\n const showCode = this.attr('showCode')\n const anchorURL = this.attr('anchorURL')\n const $headings = this.$headings\n const chapters = this.getChapters()\n\n paint()\n\n $headings.forEach(($heading, i) => {\n const chapterCode = chapters[i].code\n _updateHeading($heading, i, {\n hasAnchor,\n isAtStart,\n showCode,\n chapterCode,\n anchorURL\n })\n })\n\n if (isFunction(mounted)) {\n mounted.call(this)\n }\n\n return this\n }\n\n scrollTo(top, after) {\n const el = this.$scrollElement\n\n scrollTo(el, top, after)\n\n return this\n }\n\n destroy() {\n const hasAnchor = this.attr('hasAnchor')\n const isAtStart = this.attr('isAtStart')\n const beforeDestroy = this.attr('beforeDestroy')\n const afterDestroy = this.attr('afterDestroy')\n const $headings = this.$headings\n\n if (isFunction(beforeDestroy)) {\n beforeDestroy.call(this)\n }\n\n this.removeListeners()\n $headings.forEach(($heading) => {\n _resetHeading($heading, hasAnchor, isAtStart)\n })\n\n this.attr(Anchors.DEFAULTS)\n this.$articleElement = null\n this.$scrollElement = null\n this.$headings = []\n this.chapters = []\n\n if (isFunction(afterDestroy)) {\n afterDestroy.call(this)\n }\n\n return this\n }\n\n onAnchorTrigger(evt) {\n const anchorURL = this.attr('anchorURL')\n const afterScroll = this.attr('afterScroll')\n const stickyHeight = this.attr('stickyHeight')\n const $anchor = evt.delegateTarget\n const $heading = $anchor.parentNode\n const top = offsetTop($heading) - (stickyHeight + 10)\n const $scrollElement = this.$scrollElement\n const min = 0\n const max = $scrollElement.scrollHeight - $scrollElement.clientHeight\n const after = () => {\n if (isFunction(afterScroll)) {\n afterScroll.call(this, 'anchor')\n }\n\n later(() => {\n publish('toolbar:update', {\n top,\n min,\n max\n })\n })\n }\n\n this.scrollTo(top, after)\n\n if (!anchorURL) {\n stop(evt)\n }\n\n return this\n }\n\n addListeners() {\n const $articleElement = this.$articleElement\n\n on(\n $articleElement,\n '.outline-heading__anchor',\n 'click',\n this.onAnchorTrigger,\n this,\n true\n )\n\n return this\n }\n\n removeListeners() {\n const $articleElement = this.$articleElement\n\n off($articleElement, 'click', this.onAnchorTrigger)\n\n return this\n }\n}\n\nAnchors.DEFAULTS = {\n scrollElement: 'html,body',\n articleElement: '#article',\n selector: 'h1,h2,h3,h4,h5,h6',\n stickyHeight: 0,\n anchorURL: '',\n hasAnchor: true,\n isAtStart: true,\n showCode: false,\n created: null,\n mounted: null,\n afterScroll: null,\n beforeDestroy: null,\n afterDestroy: null,\n chapterTextFilter: null\n}\n\nexport default Anchors\n","const toTree = (list, nodeKey, parentKey) => {\r\n const map = {}\r\n const roots = []\r\n\r\n list.forEach((item, i) => {\r\n // initialize the map\r\n map[item[nodeKey]] = i\r\n // initialize the children\r\n item.children = []\r\n })\r\n\r\n list.forEach((item) => {\r\n const node = list[map[item[parentKey]]]\r\n\r\n if (item[parentKey] !== -1) {\r\n // if you have dangling branches check that map[node.parentId] exists\r\n node.children.push(item)\r\n } else {\r\n roots.push(item)\r\n }\r\n })\r\n\r\n return roots\r\n}\r\n\r\nexport default toTree\r\n","import easeInQuad from '../lang/easeInQuad'\nimport isFunction from '../types/isFunction'\nimport _getScrollElement from './_getScrollElement'\n\n/**\n * 指定 rootElement DOM 节点滚动到指定 top 位置\n * ========================================================================\n * @method scrollTo\n * @param {HTMLElement|Object} [scrollElement] - (必须)要滚动的 DOM 节点\n * @param {Number} top - (必须)滚动的 scrollTop 数值\n * @param {Function} [afterStop] - (可选)滚动完成的回调函数\n */\nconst scrollTo = (scrollElement, top, afterStop) => {\n const $scrollElement = _getScrollElement(scrollElement)\n let scrollTop = $scrollElement.scrollTop\n let step = 0\n const distance = top - scrollTop\n const MAX_HEIGHT = $scrollElement.scrollHeight\n const MAX_TOP = top - MAX_HEIGHT <= 0 ? top : MAX_HEIGHT\n const stop = (top) => {\n if (isFunction(afterStop)) {\n afterStop(top)\n }\n\n return false\n }\n const play = () => {\n step += 1\n\n // 向上滚动\n if (distance < 0) {\n scrollTop -= easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop <= top) {\n $scrollElement.scrollTop = top\n return stop(top)\n }\n } else {\n scrollTop += easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop >= MAX_TOP) {\n $scrollElement.scrollTop = MAX_TOP\n return stop(MAX_TOP)\n }\n }\n\n requestAnimationFrame(play)\n }\n\n requestAnimationFrame(play)\n}\n\nexport default scrollTo\n","import isFunction from '../types/isFunction'\n\n/**\n * later - 延迟执行方法\n * ========================================================================\n * @method later\n * @param {Function} fn\n * @param {Number} [delay]\n * @returns {number|boolean}\n */\nconst later = (fn, delay = 300) => {\n if (!isFunction(fn)) {\n return false\n }\n\n return setTimeout(() => {\n fn()\n }, delay)\n}\n\nexport default later\n","/**\n * 停止事件(阻止默认行为和阻止事件的捕获或冒泡)\n * ========================================================================\n * @method stop\n * @param {Event} evt - 事件对象\n *\n * @example\n *
\n * Service\n * Help\n *
\n *\n * const $nav = document.querySelector('#nav')\n * const $service = document.querySelector('.anchor')\n *\n * on($nav, 'click', function(evt) {\n * console.log('你点击了导航栏')\n * })\n *\n * on($anchor, 'click', function(evt) {\n * console.log('tagName', this.tagName)\n *\n * // 工作台输出:'a'\n * // 不会触发事件冒泡,输出:'你点击了导航栏'\n * // 也不会切换到 href 属性的页面,阻止了点击链接的默认行为\n * stopEvent(evt)\n * })\n */\nconst stop = function (evt) {\n evt.stopPropagation()\n evt.preventDefault()\n}\n\nexport default stop\n"],"names":["isString","str","hasOwn","obj","prop","hasOwnProperty","Object","prototype","call","toString","val","apply","isFunction","isObject","o","_subscribers","_hasDirectSubscribersFor","topic","length","has","isDirect","found","position","lastIndexOf","substring","_hasSubscribers","emit","data","async","execute","forEach","subscriber","message","indexOf","callback","context","deliver","setTimeout","guid","uuid","prefix","_removeSubscriber","off","token","keys","subject","execution","j","splice","_removeSubscriberByToken","Base","constructor","options","this","attrs","initialize","attr","render","addListeners","value","origin","source","arguments","destroy","removeListeners","reload","$emit","event","publish","$on","handler","push","subscribe","$off","unsubscribe","isElement","nodeName","tagName","nodeType","easeInQuad","x","_getScrollElement","scrollElement","$rootElements","$scrollElement","document","querySelector","querySelectorAll","scrollTop","offsetTop","el","top","offsetParent","matches","selector","sel","replace","msMatchesSelector","getParentOrHost","host","parentNode","CAPTURE_EVENTS","_off","type","fn","capture","_delegateListener","listeners","_listeners","index","listener","i","_delete","removeEventListener","purgeElement","recurse","$element","$children","childNodes","filter","getListeners","$child","on","once","evt","target","getTarget","delegateTarget","ctx","includeCTX","startsWith","closest","overrideContext","addEventListener","isArray","Array","SYMBOLS","getSymbols","name","iconSet","patternName","patternSet","find","symbol","fullName","exec","iconName","getSymbol","paint","$body","body","$icons","symbols","add","innerHTML","join","createElement","insertBefore","firstChild","trim","isDOM","isHTMLCollection","fragment","isTextNode","setAttribute","toLowerCase","style","cssText","className","isSVG","pattern","RegExp","test","icon","size","color","width","height","defaultRules","cssRules","$icon","$svg","binds","svg","_updateHeading","$heading","$fragment","createDocumentFragment","CLS_HEADING","hasAnchor","isAtStart","showCode","chapterCode","anchorURL","headingId","id","text","$anchor","children","$el","isValidChild","child","append","createTextNode","appendChild","every","href","removeClass","classList","allClass","contains","hasClass","remove","_resetHeading","removeAttribute","removeChild","getChapters","headings","chapterTextFilter","previous","level","chapters","heading","headingLevel","current","parseInt","pid","differ","_getChapterParentIdByDiffer","rel","groups","group","JSON","stringify","cb","code","String","c","subjects","_getChaptersWithCode","Anchors","super","DEFAULTS","$articleElement","$headings","created","articleElement","isTreeStructured","list","nodeKey","parentKey","map","roots","item","node","toTree","count","mounted","scrollTo","after","afterStop","step","distance","MAX_HEIGHT","scrollHeight","MAX_TOP","stop","play","requestAnimationFrame","beforeDestroy","afterDestroy","onAnchorTrigger","afterScroll","stickyHeight","max","clientHeight","delay","later","min","stopPropagation","preventDefault"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"anchors.min.js","sources":["utils/types/isString.js","utils/lang/hasOwn.js","utils/lang/toString.js","utils/types/isFunction.js","utils/types/isObject.js","utils/observer/_subscribers.js","utils/observer/_hasDirectSubscribersFor.js","utils/observer/has.js","utils/observer/_hasSubscribers.js","utils/observer/emit.js","utils/types/isTypedArray.js","utils/lang/guid.js","utils/observer/_removeSubscriber.js","utils/observer/off.js","utils/observer/_removeSubscriberByToken.js","base.js","utils/lang/extend.js","utils/observer/on.js","utils/types/isElement.js","utils/lang/easeInQuad.js","utils/dom/_getScrollElement.js","utils/dom/offsetTop.js","utils/dom/matches.js","utils/dom/getParentOrHost.js","utils/event/enum.js","utils/event/_off.js","utils/event/_delete.js","utils/event/purgeElement.js","utils/event/getListeners.js","utils/event/off.js","utils/event/on.js","utils/event/getTarget.js","utils/dom/resolveTextNode.js","utils/dom/closest.js","utils/types/isArray.js","utils/icons/symbols.js","utils/icons/defaults.js","utils/icons/getSymbols.js","utils/icons/getSymbol.js","utils/icons/paint.js","utils/icons/add.js","utils/lang/trim.js","utils/types/isDOM.js","utils/types/isHTMLCollection.js","utils/types/isFragment.js","utils/types/isTextNode.js","utils/dom/setAttribute.js","utils/types/isSVG.js","utils/icons/icon.js","utils/icons/createElement.js","_updateHeading.js","utils/dom/createElement.js","utils/dom/removeClass.js","utils/dom/hasClass.js","_resetHeading.js","utils/types/isEmpty.js","getChapters.js","utils/lang/stripTags.js","_getChapterParentIdByDiffer.js","_getChaptersWithCode.js","anchors.js","utils/lang/toTree.js","utils/dom/scrollTo.js","utils/lang/later.js","utils/event/stop.js"],"sourcesContent":["/**\n * 检测数据是否为 String 类型\n * ========================================================================\n * @method isArray\n * @param {*} str\n * @returns {boolean}\n */\nconst isString = (str) => {\n return typeof str === 'string'\n}\n\nexport default isString\n","/**\n * 检测对象自身属性中是否具有指定的属性。\n * ========================================================================\n * @method hasOwn\n * @param {Object} obj - (必须)检测的目标对象\n * @param {String} prop - (必须)属性名\n * @returns {Boolean}\n */\nconst hasOwn = (obj, prop) => {\n const hasOwnProperty = Object.prototype.hasOwnProperty\n return obj && hasOwnProperty.call(obj, prop)\n}\n\nexport default hasOwn\n","/**\n * Object 对象原型上的 toString 方法\n * ========================================================================\n * @method toString\n * @param {*} val\n * @returns {string}\n */\nconst toString = (val) => {\n return Object.prototype.toString.apply(val)\n}\n\nexport default toString\n","import toString from '../lang/toString'\n\n/**\n * 检测测试数据是否为 Function 类型\n * ========================================================================\n * @method isFunction\n * @param {*} val - (必须)待检测的数据\n * @returns {boolean} 'val' 是 Function 类型返回 true,否则返回 false\n */\nconst isFunction = (val) => {\n return typeof val === 'function' || toString(val) === '[object Function]'\n}\n\nexport default isFunction\n","import toString from '../lang/toString'\nimport isFunction from './isFunction'\n\n/**\n * 检测数据是否为 Object 类型\n * ========================================================================\n * @method isObject\n * @param {*} o\n * @returns {boolean}\n */\nconst isObject = (o) => {\n return (\n (toString(o) === '[object Object]' ||\n typeof o === 'object' ||\n isFunction(o)) &&\n o !== null\n )\n}\n\nexport default isObject\n","/**\n * 存储订阅者(主题和处理器的)私有对象\n * ========================================================================\n * @type {{}}\n * @private\n */\nconst _subscribers = {}\n\nexport default _subscribers\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 判断是否存在与给定 topic 完全匹配的订阅者信息\n * ========================================================================\n * @method _hasDirectSubscribersFor\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasDirectSubscribersFor = (topic) => {\n return hasOwn(_subscribers, topic) && _subscribers[topic].length > 0\n}\n\nexport default _hasDirectSubscribersFor\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\nimport _hasSubscribers from './_hasSubscribers'\n\n/**\n * 判断是否存在包含 topic 指定的订阅者信息\n * ========================================================================\n * @method has\n * @param {String} topic - (必须)主题名称\n * @param {Boolean} [isDirect] - (可选)是否为直接的主题,默认值:true\n * @returns {Boolean}\n */\nconst has = (topic, isDirect = true) => {\n return isDirect ? _hasDirectSubscribersFor(topic) : _hasSubscribers(topic)\n}\n\nexport default has\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * 判断是否存在包含给定 topic 相关的订阅者信息\n * ========================================================================\n * @method _hasSubscribers\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasSubscribers = (topic) => {\n let found = _hasDirectSubscribersFor(topic)\n let position = topic.lastIndexOf('.')\n\n while (!found && position !== -1) {\n topic = topic.substring(0, position)\n position = topic.lastIndexOf('.')\n found = _hasDirectSubscribersFor(topic)\n }\n\n return found\n}\n\nexport default _hasSubscribers\n","import isTypedArray from '../types/isTypedArray'\nimport _subscribers from './_subscribers'\nimport has from './has'\nimport _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * (异步)发布订阅主题信息\n * ========================================================================\n * 主题默认是异步发布的。确保在消费者处理主题时,主题的发起者不会被阻止。\n * ========================================================================\n * @method emit\n * @param {String} topic - (必须)主题名称\n * @param {Object} [data] - (可选)数据对象\n * @param {Boolean} [async] - (可选) 是否异步发布\n */\nconst emit = (topic, data, async = true) => {\n const execute = (topic) => {\n if (!_hasDirectSubscribersFor(topic)) {\n return false\n }\n\n _subscribers[topic].forEach((subscriber) => {\n // 针对 mqtt 消息服务返回的 Uint8Array 类似的 typed arrays 格式的数据\n // 采用 toString() 方法转化为普通(JSON)字符串\n const message = isTypedArray(data) ? data.toString() : data\n\n subscriber.callback.call(subscriber.context || subscriber, message)\n })\n }\n const deliver = () => {\n let subscriber = topic\n let position = topic.lastIndexOf('.')\n\n while (position !== -1) {\n subscriber = subscriber.substring(0, position)\n position = subscriber.lastIndexOf('.')\n\n execute(subscriber)\n }\n\n // 执行 topic 对应的处理器\n execute(topic)\n // 执行特殊 topic:'*'(监听全部消息的发布)\n execute('*')\n }\n\n if (!has(topic)) {\n return false\n }\n\n if (async) {\n setTimeout(deliver, 10)\n } else {\n deliver()\n }\n}\n\nexport default emit\n","import toString from '../lang/toString'\n/**\n * 判断检测数据是否为 Typed Arrays 类型的数据\n * ========================================================================\n * @param {*} val\n * @returns {boolean}\n */\nconst isTypedArray = (val) => {\n const TYPES = [\n '[object Int8Array]',\n '[object Uint8Array]',\n '[object Uint8ClampedArray]',\n '[object Int16Array]',\n '[object Uint16Array]',\n '[object Int32Array]',\n '[object Uint32Array]',\n '[object Float32Array]',\n '[object Float64Array]',\n '[object BigInt64Array]',\n '[object BigUint64Array]'\n ]\n\n return TYPES.indexOf(toString(val)) > -1\n}\n\nexport default isTypedArray\n","/**\n * 生成唯一 id 字符串的函数\n * ========================================================================\n * @method guid\n * @param {String} [prefix] - 生成 id 的前缀字符串\n * @return {String} 返回一个表示唯一 id 的字符串\n */\nconst guid = (() => {\n let uuid = 0\n\n return (prefix) => {\n uuid += 1\n\n return prefix ? prefix + '-' + uuid : 'guid-' + uuid\n }\n})()\n\nexport default guid\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 删除与给定 topic 相同的订阅者信息\n * ========================================================================\n * @method _removeSubscriber\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _removeSubscriber = (topic) => {\n if (!hasOwn(_subscribers, topic)) {\n return false\n }\n\n delete _subscribers[topic]\n}\n\nexport default _removeSubscriber\n","import has from './has'\nimport _removeSubscriber from './_removeSubscriber'\nimport _removeSubscriberByToken from './_removeSubscriberByToken'\n\n/**\n * 取消订阅主题\n * ========================================================================\n * @method off\n * @param {String} topic - (必须)订阅的主题\n * @param {Function|String} [token] - (可选)订阅主题的处理器函数或者唯一 Id 值\n */\nconst off = (topic, token) => {\n if (!has(topic)) {\n return false\n }\n\n if (token) {\n _removeSubscriberByToken(token)\n } else {\n _removeSubscriber(topic)\n }\n}\n\nexport default off\n","import _subscribers from './_subscribers'\nimport _removeSubscriber from './_removeSubscriber'\n\n/**\n * 通过订阅者 token 值删除订阅者信息\n * ========================================================================\n * @method _removeSubscriberByToken\n * @param {String} token - 订阅者 token 字符串\n * @returns {boolean}\n * @private\n */\nconst _removeSubscriberByToken = (token) => {\n const keys = Object.keys(_subscribers)\n let index = -1\n\n if (!token || keys.length < 1) {\n return false\n }\n\n keys.forEach((subject) => {\n const subscriber = _subscribers[subject]\n let topic\n\n subscriber.forEach((execution, j) => {\n if (execution.callback === token || execution.token === token) {\n topic = execution.topic\n subscriber.splice(index, j)\n }\n })\n\n /* istanbul ignore else */\n if (subscriber.length < 1) {\n _removeSubscriber(topic)\n }\n })\n}\n\nexport default _removeSubscriberByToken\n","import isString from './utils/types/isString'\r\nimport hasOwn from './utils/lang/hasOwn'\r\nimport isObject from './utils/types/isObject'\r\nimport extend from './utils/lang/extend'\r\nimport publish from './utils/observer/emit'\r\nimport subscribe from './utils/observer/on'\r\nimport unsubscribe from './utils/observer/off'\r\n\r\nclass Base {\r\n constructor(options) {\r\n this.attrs = {}\r\n\r\n if (options) {\r\n this.initialize(options)\r\n }\r\n }\r\n\r\n initialize(options) {\r\n this.attr(options).render().addListeners()\r\n return this\r\n }\r\n\r\n attr(prop, value) {\r\n const attrs = this.attrs\r\n\r\n if (isString(prop)) {\r\n // 只能扩展 attrs 中已有的属性\r\n if (value && hasOwn(attrs, prop)) {\r\n // 更新单个配置信息\r\n attrs[prop] = value\r\n return this\r\n }\r\n\r\n // 只传递 prop 参数,则返回对应的属性值\r\n return attrs[prop]\r\n } else if (isObject(prop)) {\r\n // 批量更新配置信息\r\n extend(attrs, prop)\r\n\r\n return this\r\n } else if (arguments.length === 0) {\r\n // 不传递参数,直接返回整个\r\n return attrs\r\n }\r\n\r\n return this\r\n }\r\n\r\n render() {\r\n return this\r\n }\r\n\r\n destroy() {\r\n this.removeListeners()\r\n return this\r\n }\r\n\r\n reload(options) {\r\n this.destroy().initialize(this.attr(options))\r\n return this\r\n }\r\n\r\n $emit(event, data) {\r\n publish(event, data)\r\n return this\r\n }\r\n\r\n $on(event, callback) {\r\n subscribe(event, callback, this)\r\n return this\r\n }\r\n\r\n $off(event, callback) {\r\n unsubscribe(event, callback)\r\n return this\r\n }\r\n\r\n addListeners() {\r\n return this\r\n }\r\n\r\n removeListeners() {\r\n return this\r\n }\r\n}\r\n\r\nexport default Base\r\n","import hasOwn from './hasOwn'\n\n/**\n * 扩展对象\n * ========================================================================\n * @method extend\n * @param {Object} origin\n * @param {Object} source\n */\nconst extend = (origin, source) => {\n const keys = Object.keys(source)\n\n keys.forEach((prop) => {\n if (hasOwn(source, prop)) {\n origin[prop] = source[prop]\n }\n })\n}\n\nexport default extend\n","import _subscribers from './_subscribers'\nimport isFunction from '../types/isFunction'\nimport guid from '../lang/guid'\n\n/**\n * 订阅主题,并给出处理器函数\n * ========================================================================\n * @method on\n * @param {String} topic - (必须)主题名称\n * @param {Function} handler - (必须)主题的处理器函数\n * @param {Object} [context] - (可选)指定 this 执行上下文\n * @return {String} - 唯一的 token 字符串,例如:'guid-1'。\n */\nconst on = (topic, handler, context = null) => {\n const token = guid()\n let subject = typeof topic === 'symbol' ? topic.toString() : topic\n\n if (!isFunction(handler)) {\n return ''\n }\n\n /* istanbul ignore else */\n if (!_subscribers[subject]) {\n _subscribers[subject] = []\n }\n\n _subscribers[subject].push({\n topic: subject,\n callback: handler,\n context,\n token\n })\n\n return token\n}\n\nexport default on\n","import isObject from './isObject'\n\n/**\n * 检测数据是否为 HTMLElement DOM 节点\n * ========================================================================\n * @method isElement\n * @param {*} o\n * @returns {boolean}\n */\nconst isElement = (o) => {\n return !!(isObject(o) && o.nodeName && o.tagName && o.nodeType === 1)\n}\n\nexport default isElement\n","/**\n * 返回给定值的平方值\n * ========================================================================\n * @method easeInQuad\n * @param {Number} x\n * @returns {number}\n */\nconst easeInQuad = (x) => {\n return x * x\n}\n\nexport default easeInQuad\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\n\n/**\n * 通过给的 scrollElement 参数,获取滚动 DOM 元素\n * ========================================================================\n * @method _getScrollElement\n * @param {String|HTMLElement} scrollElement\n * @returns {Element}\n * @private\n */\nconst _getScrollElement = (scrollElement = null) => {\n let $rootElements\n let $scrollElement\n\n if (!scrollElement) {\n $rootElements = document.querySelectorAll('html,body')\n $scrollElement =\n $rootElements[0].scrollTop - $rootElements[1].scrollTop >= 0\n ? $rootElements[0]\n : $rootElements[1]\n } else {\n if (isString(scrollElement)) {\n $scrollElement = document.querySelector(scrollElement)\n } else if (isElement(scrollElement)) {\n $scrollElement = scrollElement\n }\n }\n\n return $scrollElement\n}\n\nexport default _getScrollElement\n","/**\n * 获取 DOM 节点相对于窗口的 left (纵坐标)值\n * ========================================================================\n * @method offsetTop\n * @param {HTMLElement} el - DOM 节点\n * @returns {Number}\n */\nconst offsetTop = (el) => {\n let top = el.offsetTop\n\n if (el.offsetParent !== null) {\n top += offsetTop(el.offsetParent)\n }\n\n return top\n}\n\nexport default offsetTop\n","/**\n * 获取 options 节点下匹配 selector 选择器的 DOM 节点\n * ========================================================================\n * Element.matches() 方法可以用来判断 DOM 元素是否与给定的选择器匹配,事件代理判断是\n * 否触发绑定的代理事件回调函数,关键就是使用 Element.matches() 辨别当前事件触发的目\n * 标 DOM 元素是否为事件代理所期望触发的目标。\n * ========================================================================\n * @method matches\n * @see https://developer.mozilla.org/en-US/docs/web/api/element/matches\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)匹配 DOM 元素的选择器\n * @returns {Boolean}\n */\nconst matches = (el, selector = '') => {\n const sel = selector.replace(/^>/i, '')\n\n if (!selector || !sel || !el) {\n return false\n }\n\n /* istanbul ignore else */\n if (el.matches) {\n return el.matches(sel)\n } else if (el.msMatchesSelector) {\n return el.msMatchesSelector(sel)\n } else {\n return false\n }\n}\n\nexport default matches\n","/**\n * 获取 DOM 元素的父节点\n * ========================================================================\n * @method getParentOrHost\n * @param {*|HTMLElement} el - (必须)要获取父节点的 DOM 元素\n * @returns {*|HTMLElement}\n */\nconst getParentOrHost = (el) => {\n return el.host && el !== document && el.host.nodeType\n ? el.host\n : el.parentNode\n}\n\nexport default getParentOrHost\n","export const CAPTURE_EVENTS = [\n 'focusout',\n 'blur',\n 'focusin',\n 'focus',\n 'load',\n 'unload',\n 'mouseenter',\n 'mouseleave'\n]\n","import { CAPTURE_EVENTS } from './enum'\nimport _delete from './_delete'\n\n/**\n * (私有方法)取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method _off\n * @param {HTMLElement} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} fn - (必须)事件处理器回调函数\n * @private\n */\nconst _off = (el, type, fn) => {\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n /* istanbul ignore else */\n if (fn._delegateListener) {\n fn = fn._delegateListener\n delete fn._delegateListener\n }\n\n // 移除缓存的 _listeners 数据\n _delete(el, type, fn)\n\n el.removeEventListener(type, fn, capture)\n}\n\nexport default _off\n","/**\n * 删除 DOM 元素缓存的 _listeners 数据\n * ========================================================================\n * @method _delete\n * @param {HTMLElement} el - 要删除 listener 的 DOM 元素\n * @param {String} type - 事件类型(名称)\n * @param {Function} [fn] - 事件处理器回调函数\n */\nconst _delete = function (el, type, fn) {\n const listeners = el._listeners\n let index = -1\n\n if (listeners.length < 1) {\n return false\n }\n\n // 移除缓存的 _listeners 数据\n listeners.forEach((listener, i) => {\n const handler = listener.fn\n\n if (type === listener.type) {\n index = i\n\n if (handler === fn) {\n index = i\n }\n }\n })\n\n /* istanbul ignore else */\n if (index > -1) {\n listeners.splice(index, 1)\n }\n}\n\nexport default _delete\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\nimport getListeners from './getListeners'\nimport _off from './_off'\n\n/**\n * 销毁(type 类型的)代理事件绑定\n * ========================================================================\n * 1. 设置了事件类型 type,则销毁指定类型的事件绑定,否则清除所有代理事件绑定\n * 2. recurse 设置为 true,递归销毁子节点全部事件绑定\n * ========================================================================\n * @method purgeElement\n * @param {HTMLElement|String} el - (必须)DOM 元素或者其选择器\n * @param {String|Boolean} type - (必须)事件类型\n * @param {Boolean} [recurse] - (可选)是否递归销毁子节点所有事件绑定\n */\nconst purgeElement = function (el, type, recurse = false) {\n const $element = isString(el) ? document.querySelector(el) : el\n const $children = $element.childNodes\n const listeners = getListeners($element, type)\n\n listeners.forEach((listener) => {\n _off($element, listener.type, listener.fn)\n })\n\n if (\n (recurse || type === true || arguments.length === 1) &&\n $element &&\n $children\n ) {\n $children.forEach(($child) => {\n if (isElement($child)) {\n purgeElement($child, type, recurse)\n }\n })\n }\n}\n\nexport default purgeElement\n","import isString from '../types/isString'\n\n/**\n * 获取 DOM 元素(type 事件类型)事件绑定信息\n * ========================================================================\n * 如果设置了事件类型 type, 则返回指定类型的事件绑定信息,否则返回所有事件绑定信息\n * ========================================================================\n * @methods getListeners\n * @param {HTMLElement} el - (必须)要获取事件绑定信息的 DOM 元素\n * @param {String} [type] - (可选)事件类型\n * @returns {Array} - 已绑定的事件信息\n */\nconst getListeners = (el, type) => {\n let listeners = el._listeners || []\n\n if (isString(type) && type) {\n listeners = listeners.filter((listener) => {\n return listener.type === type\n })\n }\n\n return listeners\n}\n\nexport default getListeners\n","import purgeElement from './purgeElement'\nimport isFunction from '../types/isFunction'\nimport _off from './_off'\n\n/**\n * 取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method off\n * @param {HTMLElement|Object} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} [fn] - (可选)事件处理器回调函数\n */\nconst off = (el, type, fn) => {\n // 如果不设置 fn 参数,默认清除 el 元素上绑定的所有事件处理器\n if (!isFunction(fn)) {\n return purgeElement(el, type)\n }\n\n _off(el, type, fn)\n}\n\nexport default off\n","import closest from '../dom/closest'\nimport off from './off'\nimport getTarget from './getTarget'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定代理事件\n * ========================================================================\n * @method on\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String} selector - (必须)事件代理目标 DOM 元素的选择器\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (可选) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst on = (el, selector, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n const listener = function (evt) {\n const target = getTarget(evt)\n // 通过 Element.matches 方法获得点击的目标元素\n const delegateTarget = closest(target, selector, el)\n let overrideContext = context || el\n\n evt.delegateTarget = delegateTarget\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n /* istanbul ignore else */\n if (delegateTarget) {\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n selector,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default on\n","import resolveTextNode from '../dom/resolveTextNode'\n\n/**\n * 返回触发事件的 target DOM 元素\n * ========================================================================\n * @method getTarget\n * @param {Event} evt - Event 对象\n * @return {HTMLElement} - Event 对象的 target DOM 元素\n */\nconst getTarget = function (evt) {\n const target = evt.target\n\n return resolveTextNode(target)\n}\n\nexport default getTarget\n","/**\n * 在某些情况下,某些浏览器(例如:Safari 浏览器)会返回实际的目标元素内部的文本节点。\n * resolveTextNode() 方法则会返回实际的目标节点。\n * ========================================================================\n * @method resolveTextNode\n * @param {HTMLElement|Text} el - 要解析的节点\n * @return {*|HTMLElement} - 实际的目标 DOM 节点\n */\nconst resolveTextNode = function (el) {\n if (el && el.nodeType === 3) {\n return el.parentNode\n }\n\n return el\n}\n\nexport default resolveTextNode\n","import matches from './matches'\nimport getParentOrHost from './getParentOrHost'\n\n/**\n * 获取 options 元素父元素最近的包含 selector 选择器的元素\n * ========================================================================\n * @method closest\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)DOM 元素的选择其\n * @param {HTMLElement} [ctx] - (必须)比对的 DOM 元素\n * @param {Boolean} [includeCTX] - (必须)是否包含 context DOM 元素\n * @returns {null|HTMLElement} - 返回最接近的 DOM 元素\n */\nconst closest = (el, selector, ctx, includeCTX) => {\n const context = ctx || document\n\n if (!el) {\n return null\n }\n\n do {\n /* istanbul ignore else */\n if (\n (selector != null &&\n (selector.startsWith('>')\n ? el.parentNode === context && matches(el, selector)\n : matches(el, selector))) ||\n (includeCTX && el === context)\n ) {\n return el\n }\n\n /* istanbul ignore else */\n if (el === context) {\n break\n }\n\n /* jshint boss:true */\n } while ((el = getParentOrHost(el)))\n}\n\nexport default closest\n","import toString from '../lang/toString'\n\n/**\n * 检测数据是否为 Array 类型\n * ========================================================================\n * @method isArray\n * @param {*} o\n * @returns {boolean}\n */\nconst isArray = (o) => {\n if (Array.isArray) {\n return Array.isArray(o)\n } else {\n return toString(o) === '[object Array]'\n }\n}\n\nexport default isArray\n","import DEFAULTS from './defaults'\n\nconst SYMBOLS = [...DEFAULTS]\n\nexport default SYMBOLS\n","const DEFAULTS = [\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n '',\n ''\n]\n\nexport default DEFAULTS\n","import isString from '../types/isString'\nimport getSymbol from './getSymbol'\nimport SYMBOLS from './symbols'\n\n/**\n *\n * @method getSymbols\n * @param {String} [name]\n * @param {String} [iconSet]\n * @returns {string[]|*}\n */\nconst getSymbols = (name, iconSet = 'icon') => {\n if (isString(name)) {\n return getSymbol(name, iconSet)\n }\n\n return [...SYMBOLS]\n}\n\nexport default getSymbols\n","import SYMBOLS from './symbols'\n\n/**\n * @method getSymbol\n * @param {String} name\n * @param {String} [iconSet]\n * @returns {String}\n */\nconst getSymbol = (name, iconSet = 'icon') => {\n const patternName = /id=\"(.*?)\"/\n const patternSet = /^(\\w+)-/\n const symbols = SYMBOLS\n\n return symbols.find((symbol) => {\n const names = patternName.exec(symbol)\n const fullName = names[1]\n const sets = patternSet.exec(fullName)\n const setName = sets[1]\n const iconName =\n iconSet === 'icon' ? `${iconSet}-${name}` : `${iconSet}-icon-${name}`\n\n return setName === iconSet && fullName === iconName\n })\n}\n\nexport default getSymbol\n","import add from './add'\nimport getSymbols from './getSymbols'\n\n/**\n * 绘制 SVG 图标集\n * ========================================================================\n * @method paint\n * @param {String|Array} symbol\n */\nconst paint = (symbol = '') => {\n const $body = document.body\n let $icons = document.querySelector('#outline-icons')\n let symbols = []\n\n add(symbol)\n symbols = getSymbols()\n\n if ($icons) {\n $icons.innerHTML = symbols.join('')\n } else {\n $icons = document.createElement('div')\n $icons.innerHTML =\n ``\n $body.insertBefore($icons.firstChild, $body.firstChild)\n }\n}\n\nexport default paint\n","import isArray from '../types/isArray'\nimport isString from '../types/isString'\nimport SYMBOLS from './symbols'\n\n/**\n * @method add\n * @param {Array|String} symbols\n * @return {Boolean}\n */\nconst add = (symbols) => {\n if (!symbols) {\n return false\n }\n\n if (isArray(symbols) && symbols.length > 0) {\n symbols.forEach((symbol) => {\n /* istanbul ignore else */\n if (SYMBOLS.indexOf(symbol) === -1 && isString(symbol)) {\n SYMBOLS.push(symbol)\n }\n })\n } else {\n /* istanbul ignore else */\n if (isString(symbols)) {\n SYMBOLS.push(symbols)\n }\n }\n}\n\nexport default add\n","import isString from '../types/isString'\n\n/**\n * 清楚字符串起始位置所有的空格\n * ========================================================================\n * @method trim\n * @param {string} str\n * @returns {string|Boolean}\n */\nconst trim = (str) => {\n if (!isString(str)) {\n return false\n }\n return str.replace(/(^\\s+)|(\\s+$)/g, '')\n}\n\nexport default trim\n","import isObject from './isObject'\r\nimport isElement from './isElement'\r\nimport isHTMLCollection from './isHTMLCollection'\r\nimport isFragment from './isFragment'\r\nimport isTextNode from './isTextNode'\r\n\r\nconst isDOM = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (isElement(el) || isHTMLCollection(el) || isFragment(el) || isTextNode(el))\r\n )\r\n}\r\n\r\nexport default isDOM\r\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isHTMLCollection = (el) => {\r\n return !!(isObject(el) && toString(el) === '[object NodeList]')\r\n}\r\n\r\nexport default isHTMLCollection\r\n","import toString from '../lang/toString'\nimport isObject from './isObject'\n\nconst isFragment = (fragment) => {\n return !!(\n isObject(fragment) && toString(fragment) === '[object DocumentFragment]'\n )\n}\n\nexport default isFragment\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isTextNode = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (toString(el) === '[object Text]' || (el.tagName && el.nodeType === 3))\r\n )\r\n}\r\n\r\nexport default isTextNode\r\n","/**\n * 给 DOM 节点设置属性/值\n * ========================================================================\n * @method setAttribute\n * @param {HTMLElement} el - DOM 节点\n * @param {String} attr - 属性名称\n * @param {String|Number|Boolean} value - 属性值\n */\nconst setAttribute = (el, attr, value) => {\n let tagName = el.tagName.toLowerCase()\n\n switch (attr) {\n case 'style':\n el.style.cssText = value\n break\n case 'value':\n if (tagName === 'input' || tagName === 'textarea') {\n el.value = value\n } else {\n el.setAttribute(attr, value)\n }\n break\n case 'className':\n el.className = value\n break\n default:\n el.setAttribute(attr, value)\n break\n }\n}\n\nexport default setAttribute\n","import isString from './isString'\n\nconst isSVG = (str) => {\n const declaration = '(?:<\\\\?xml[^>]*>\\\\s*)?'\n const doctype =\n '(?:<\\\\!doctype svg[^>]*\\\\s*(?:\\\\[?(?:\\\\s*]*>\\\\s*)*\\\\]?)*[^>]*>\\\\s*)?'\n const content = ']*>[^]*<\\\\/svg>\\\\s*$'\n const svg = `^\\\\s*${declaration}${doctype}${content}\\\\s*$`\n const pattern = new RegExp(svg, 'i')\n\n return isString(str) && pattern.test(str)\n}\n\nexport default isSVG\n","import createElement from './createElement'\n\n/**\n * 创建 SVG 图标 DOM 元素\n * ========================================================================\n * @method icon\n * @alias createElement\n * @see createElement\n * @param {String} name\n * @param {Object} [options]\n * @param {Number|Array} [options.size]\n * @param {String} [options.color]\n * @param {String} [options.iconSet]\n * @returns {HTMLElement}\n */\nconst icon = (name, options = {}) => {\n return createElement(name, options)\n}\n\nexport default icon\n","import isArray from '../types/isArray'\nimport isString from '../types/isString'\nimport isSVG from '../types/isSVG'\n\n/**\n * 创建 SVG 图标 DOM 元素\n * ========================================================================\n * @method createElement\n * @param {String} name\n * @param {Object} [options]\n * @param {Number|Array} [options.size]\n * @param {String} [options.color]\n * @param {String} [options.iconSet]\n * @returns {HTMLElement}\n */\nconst createElement = (name, options = {}) => {\n const size = options.size || 0\n const color = options.color || ''\n const iconSet = options.iconSet || ''\n const width = isArray(size) ? size[0] : size\n const height = isArray(size) ? size[1] : size\n const defaultRules = size ? `width:${width}px;height:${height}px;` : ''\n const cssRules = color ? defaultRules + `color:${color}` : defaultRules\n const $icon = document.createElement('i')\n let binds = ''\n let svg = ''\n let $svg\n\n if (!isString(name)) {\n return null\n }\n\n if (isSVG(name)) {\n svg = name\n } else {\n binds =\n iconSet && iconSet !== 'icon'\n ? `xlink:href=\"#${iconSet}-icon-${name}\"`\n : `xlink:href=\"#icon-${name}\"`\n svg =\n `` +\n `` +\n ``\n }\n\n $icon.className = 'outline-icon'\n $icon.innerHTML = svg\n\n if (isSVG(name)) {\n $svg = $icon.querySelector('svg')\n $svg.setAttribute('aria-hidden', 'true')\n $svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n $svg.setAttribute('class', 'outline-icon__svg')\n $svg.setAttribute('width', '200')\n $svg.setAttribute('height', '200')\n $svg.style.cssText = cssRules\n }\n\n return $icon\n}\n\nexport default createElement\n","import trim from './utils/lang/trim'\nimport createElement from './utils/dom/createElement'\nimport setAttribute from './utils/dom/setAttribute'\n\nimport icon from './utils/icons/icon'\n\nconst _updateHeading = ($heading, i, options) => {\n const $fragment = document.createDocumentFragment()\n const CLS_HEADING = 'outline-heading'\n const hasAnchor = options.hasAnchor || true\n const isAtStart = options.isAtStart || true\n const showCode = options.showCode || false\n const chapterCode = options.chapterCode || ''\n const anchorURL = options.anchorURL || ''\n const headingId = `heading-${i}`\n const attrs = {\n id: headingId,\n className: isAtStart ? `${CLS_HEADING} ${CLS_HEADING}_start` : CLS_HEADING,\n 'data-id': i\n }\n const keys = Object.keys(attrs)\n const text = trim($heading.innerHTML)\n let $anchor\n let $icon\n\n keys.forEach((prop) => {\n setAttribute($heading, prop, attrs[prop])\n })\n\n if (showCode) {\n $heading.innerHTML = chapterCode + ' ' + text\n }\n\n if (!hasAnchor) {\n return false\n }\n\n $icon = icon('hash', { iconSet: 'outline' })\n $anchor = createElement(\n 'a',\n {\n id: `anchor-${i}`,\n className: `${CLS_HEADING}__anchor anchor-${i}`,\n href: anchorURL || `#${headingId}`,\n target: anchorURL ? '_blank' : 'self',\n 'data-id': i\n },\n [$icon]\n )\n $fragment.appendChild($anchor)\n $heading.appendChild($fragment)\n}\n\nexport default _updateHeading\n","import hasOwn from '../lang/hasOwn'\nimport isObject from '../types/isObject'\nimport isString from '../types/isString'\nimport isArray from '../types/isArray'\nimport isDOM from '../types/isDOM'\nimport setAttribute from './setAttribute'\n\n/**\n * 创建 DOM 节点,并添加属性和子节点\n * ========================================================================\n * @method createElement\n * @param {String} tagName - 标签名称\n * @param {Object|Array} attrs - 属性对象或者子节点\n * @param {Array} [children] - 子节点数组\n * @returns {HTMLElement}\n */\nconst createElement = (tagName, attrs, children) => {\n const $fragment = document.createDocumentFragment()\n const $el = document.createElement(tagName)\n const isValidChild = (child) => {\n return isDOM(child) || isString(child)\n }\n const append = (child) => {\n let $child\n\n if (!isValidChild(child)) {\n return false\n }\n\n if (isDOM(child)) {\n $child = child\n } else if (isString(child)) {\n $child = document.createTextNode(child)\n }\n\n $fragment.appendChild($child)\n }\n\n if (isObject(attrs)) {\n Object.keys(attrs).forEach((attr) => {\n if (hasOwn(attrs, attr)) {\n setAttribute($el, attr, attrs[attr])\n }\n })\n } else if (isArray(attrs) && attrs.every((attr) => isValidChild(attr))) {\n attrs.forEach((child) => {\n append(child)\n })\n }\n\n if (isArray(children)) {\n children.forEach((child) => {\n append(child)\n })\n } else {\n append(children)\n }\n\n $el.appendChild($fragment)\n\n return $el\n}\n\nexport default createElement\n","import trim from '../lang/trim'\nimport hasClass from './hasClass'\n\n/**\n * 移除 DOM 节点的 className 样式\n * ========================================================================\n * @method removeClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst removeClass = (el, className) => {\n let allClass = el.className\n let classList\n\n if (!allClass || !hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.remove) {\n classList.remove(className)\n } else {\n allClass = trim(allClass.replace(className, ''))\n el.className = allClass\n }\n}\n\nexport default removeClass\n","import isElement from '../types/isElement'\n/**\n * 检测 DOM 节点是否包含名为 className 的样式\n * ========================================================================\n * @method hasClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst hasClass = (el, className) => {\n const pattern = new RegExp('(\\\\s|^)' + className + '(\\\\s|$)')\n let allClass\n let classList\n\n if (!isElement(el)) {\n return false\n }\n\n allClass = el.className\n\n if (!allClass) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.contains) {\n return el.classList.contains(className)\n }\n\n return !!pattern.exec(allClass)\n}\n\nexport default hasClass\n","import removeClass from './utils/dom/removeClass'\nimport isEmpty from './utils/types/isEmpty'\nimport trim from './utils/lang/trim'\n\nconst _resetHeading = ($heading, hasAnchor = true, isAtStart = true) => {\n const CLS_HEADING = 'outline-heading'\n const text = $heading.innerHTML\n const pattern = /^\\d+(\\.?\\d+)*\\s?/gi\n let $anchor\n\n $heading.innerHTML = text.replace(pattern, '')\n $heading.removeAttribute('id')\n $heading.removeAttribute('data-id')\n\n removeClass($heading, CLS_HEADING)\n\n if (!hasAnchor) {\n return false\n }\n\n $anchor = $heading.querySelector(`.${CLS_HEADING}__anchor`)\n\n if (isAtStart) {\n removeClass($heading, `${CLS_HEADING}_start`)\n }\n\n if (isEmpty(trim($heading.className))) {\n $heading.removeAttribute('class')\n }\n\n $heading.removeChild($anchor)\n}\n\nexport default _resetHeading\n","import isString from './isString'\n/**\n * 检测数据是否为空字符串\n * ========================================================================\n * @method isEmpty\n * @param {String} str\n * @returns {boolean}\n */\nconst isEmpty = (str) => {\n return isString(str) && str === ''\n}\n\nexport default isEmpty\n","import trim from './utils/lang/trim'\nimport stripTags from './utils/lang/stripTags'\nimport isFunction from './utils/types/isFunction'\n\nimport _getChapterParentIdByDiffer from './_getChapterParentIdByDiffer'\nimport _getChaptersWithCode from './_getChaptersWithCode'\n\n/**\n * 根据文章中的 h1~h6 标签,自动分析返回文章章节数据\n * ========================================================================\n * @method getChapters\n * @param {Array} headings\n * @param {Boolean} [showCode]\n * @param {Function} [chapterTextFilter]\n * @return {*|*[]}\n */\nconst getChapters = (headings, showCode = true, chapterTextFilter = null) => {\n let previous = 1\n let level = 0\n let text = ''\n const chapters = []\n\n headings.forEach((heading, i) => {\n const tagName = heading.tagName\n const headingLevel = tagName.replace(/h/i, '')\n let current = parseInt(headingLevel, 10)\n let pid = -1\n\n // 场景1:当前标题是前一个标题的子标题\n // 当前标题的(标题标签)序号 > 前一个标题的序号:两个相连的标题是父标题 -> 子标题关系;\n // h2 (前一个标题)\n // h3 (当前标题)\n if (current > previous) {\n level += 1\n\n // 第一层级的 pid 是 -1\n if (level === 1) {\n pid = -1\n } else {\n pid = i - 1\n }\n }\n // 场景2:当前标题和前一个标题层级相同\n // 当前标题的(标题标签)序号 = 前一个标题的序号\n // h2 (前一个标题)\n // h2 (当前标题)\n // 当前标题的(标题标签)序号 < 前一个标题的序号,并且当前标题序号 > 当前的级别\n // h2\n // h4 (前一个标题)\n // h3 (当前标题:这种情况我们还是任务 h3 是 h2 的下一级章节)\n else if (current === previous || (current < previous && current > level)) {\n // H1 的层级肯定是 1\n if (current === 1) {\n level = 1\n pid = -1\n } else {\n pid = chapters[i - 1].pid\n }\n }\n // 场景3:当前标题比前一个标题层级高\n else if (current <= level) {\n // H1 的层级肯定是 1\n if (current === 1) {\n level = 1\n } else {\n level = level - (previous - current)\n\n if (level <= 1) {\n level = 1\n }\n }\n\n // 第一级的标题\n if (level === 1) {\n pid = -1\n } else {\n // 通过当前标题和前一个标题之间的等级差,获得当前标题的父标题ID\n pid = _getChapterParentIdByDiffer(chapters, previous - current, i)\n }\n }\n\n previous = current\n\n text = stripTags(trim(heading.innerHTML))\n\n if (isFunction(chapterTextFilter)) {\n text = chapterTextFilter(text)\n }\n\n chapters.push({\n id: i,\n pid: pid,\n level: level,\n rel: `heading-${i}`,\n text,\n tagName\n })\n })\n\n return showCode ? _getChaptersWithCode(chapters) : chapters\n}\n\nexport default getChapters\n","import isString from '../types/isString'\n\n/**\n * 过滤所有 HTML 标签\n * ========================================================================\n * @method stripTags\n * @param {string} str\n * @returns {string}\n */\nconst stripTags = (str) => {\n if (!isString(str)) {\n return ''\n }\n return str.replace(/<\\/?[^>]+(>|$)/g, '')\n}\n\nexport default stripTags\n","const _getChapterParentIdByDiffer = (chapters, differ, index) => {\n let previous = chapters[index - 1]\n let pid\n let i\n\n for (i = 0; i < differ; i += 1) {\n pid = previous.pid\n previous = chapters[pid]\n }\n\n pid = previous.pid\n\n return pid\n}\n\nexport default _getChapterParentIdByDiffer\n","import isArray from './utils/types/isArray'\n\nconst _getChaptersWithCode = (chapters) => {\n const groups = {}\n const cb = (o) => {\n return [o.pid]\n }\n\n chapters.forEach((o) => {\n const group = JSON.stringify(cb(o))\n\n groups[group] = groups[group] || []\n groups[group].push(o)\n\n o.index = groups[group].length\n if (o.pid === -1) {\n o.code = String(o.index)\n }\n })\n\n Object.keys(groups).forEach((group) => {\n groups[group].forEach((c) => {\n const subjects = groups[`[${c.id}]`]\n if (!subjects || !isArray(subjects)) {\n return false\n }\n subjects.forEach((o) => {\n o.code = c.code + '.' + o.index\n })\n })\n })\n\n return chapters\n}\n\nexport default _getChaptersWithCode\n","import Base from './base'\n\n// 在文章的标题生成 anchor 链接\nimport isString from './utils/types/isString'\nimport isFunction from './utils/types/isFunction'\nimport isElement from './utils/types/isElement'\nimport toTree from './utils/lang/toTree'\nimport later from './utils/lang/later'\nimport scrollTo from './utils/dom/scrollTo'\nimport _getScrollElement from './utils/dom/_getScrollElement'\nimport offsetTop from './utils/dom/offsetTop'\nimport on from './utils/event/on'\nimport off from './utils/event/off'\nimport stop from './utils/event/stop'\nimport paint from './utils/icons/paint'\n\nimport _updateHeading from './_updateHeading'\nimport _resetHeading from './_resetHeading'\nimport getChapters from './getChapters'\n\nclass Anchors extends Base {\n constructor(options) {\n super()\n\n this.attrs = Anchors.DEFAULTS\n this.$articleElement = null\n this.$scrollElement = null\n this.$headings = []\n\n this.chapters = []\n\n if (options) {\n this.initialize(options)\n }\n }\n\n initialize(options) {\n const showCode = this.attr('showCode') || true\n let created\n let scrollElement\n let selector\n let $articleElement\n let articleElement\n\n this.attr(options)\n articleElement = this.attr('articleElement')\n scrollElement = this.attr('scrollElement')\n selector = this.attr('selector')\n created = this.attr('created')\n\n if (isString(articleElement)) {\n $articleElement = document.querySelector(articleElement)\n } else if (isElement(articleElement)) {\n $articleElement = articleElement\n }\n\n if (!$articleElement) {\n return this\n }\n\n this.$articleElement = $articleElement\n this.$scrollElement = _getScrollElement(scrollElement)\n this.$headings = [...$articleElement.querySelectorAll(selector)]\n\n if (this.$headings.length < 1) {\n return this\n }\n\n this.chapters = getChapters(\n this.$headings,\n showCode,\n this.attr('chapterTextFilter')\n )\n\n if (isFunction(created)) {\n created.call(this)\n }\n\n this.render().addListeners()\n\n return this\n }\n\n getChapters(isTreeStructured = false) {\n const chapters = this.chapters\n return isTreeStructured ? toTree(chapters, 'id', 'pid') : chapters\n }\n\n count() {\n return this.chapters.length\n }\n\n render() {\n const mounted = this.attr('mounted')\n const hasAnchor = this.attr('hasAnchor')\n const isAtStart = this.attr('isAtStart')\n const showCode = this.attr('showCode')\n const anchorURL = this.attr('anchorURL')\n const $headings = this.$headings\n const chapters = this.getChapters()\n\n paint()\n\n $headings.forEach(($heading, i) => {\n const chapterCode = chapters[i].code\n _updateHeading($heading, i, {\n hasAnchor,\n isAtStart,\n showCode,\n chapterCode,\n anchorURL\n })\n })\n\n if (isFunction(mounted)) {\n mounted.call(this)\n }\n\n return this\n }\n\n scrollTo(top, after) {\n const el = this.$scrollElement\n\n scrollTo(el, top, after)\n\n return this\n }\n\n destroy() {\n const hasAnchor = this.attr('hasAnchor')\n const isAtStart = this.attr('isAtStart')\n const beforeDestroy = this.attr('beforeDestroy')\n const afterDestroy = this.attr('afterDestroy')\n const $headings = this.$headings\n\n if (isFunction(beforeDestroy)) {\n beforeDestroy.call(this)\n }\n\n this.removeListeners()\n $headings.forEach(($heading) => {\n _resetHeading($heading, hasAnchor, isAtStart)\n })\n\n this.attr(Anchors.DEFAULTS)\n this.$articleElement = null\n this.$scrollElement = null\n this.$headings = []\n this.chapters = []\n\n if (isFunction(afterDestroy)) {\n afterDestroy.call(this)\n }\n\n return this\n }\n\n onAnchorTrigger(evt) {\n const anchorURL = this.attr('anchorURL')\n const afterScroll = this.attr('afterScroll')\n const stickyHeight = this.attr('stickyHeight')\n const $anchor = evt.delegateTarget\n const $heading = $anchor.parentNode\n const top = offsetTop($heading) - (stickyHeight + 10)\n const $scrollElement = this.$scrollElement\n const min = 0\n const max = $scrollElement.scrollHeight - $scrollElement.clientHeight\n const after = () => {\n if (isFunction(afterScroll)) {\n afterScroll.call(this, 'anchor')\n }\n\n later(() => {\n this.$emit('toolbar:update', {\n top,\n min,\n max\n })\n })\n }\n\n this.scrollTo(top, after)\n\n if (!anchorURL) {\n stop(evt)\n }\n\n return this\n }\n\n addListeners() {\n const $articleElement = this.$articleElement\n\n on(\n $articleElement,\n '.outline-heading__anchor',\n 'click',\n this.onAnchorTrigger,\n this,\n true\n )\n\n return this\n }\n\n removeListeners() {\n const $articleElement = this.$articleElement\n\n off($articleElement, 'click', this.onAnchorTrigger)\n\n return this\n }\n}\n\nAnchors.DEFAULTS = {\n scrollElement: 'html,body',\n articleElement: '#article',\n selector: 'h1,h2,h3,h4,h5,h6',\n stickyHeight: 0,\n anchorURL: '',\n hasAnchor: true,\n isAtStart: true,\n showCode: false,\n created: null,\n mounted: null,\n afterScroll: null,\n beforeDestroy: null,\n afterDestroy: null,\n chapterTextFilter: null\n}\n\nexport default Anchors\n","const toTree = (list, nodeKey, parentKey) => {\r\n const map = {}\r\n const roots = []\r\n\r\n list.forEach((item, i) => {\r\n // initialize the map\r\n map[item[nodeKey]] = i\r\n // initialize the children\r\n item.children = []\r\n })\r\n\r\n list.forEach((item) => {\r\n const node = list[map[item[parentKey]]]\r\n\r\n if (item[parentKey] !== -1) {\r\n // if you have dangling branches check that map[node.parentId] exists\r\n node.children.push(item)\r\n } else {\r\n roots.push(item)\r\n }\r\n })\r\n\r\n return roots\r\n}\r\n\r\nexport default toTree\r\n","import easeInQuad from '../lang/easeInQuad'\nimport isFunction from '../types/isFunction'\nimport _getScrollElement from './_getScrollElement'\n\n/**\n * 指定 rootElement DOM 节点滚动到指定 top 位置\n * ========================================================================\n * @method scrollTo\n * @param {HTMLElement|Object} [scrollElement] - (必须)要滚动的 DOM 节点\n * @param {Number} top - (必须)滚动的 scrollTop 数值\n * @param {Function} [afterStop] - (可选)滚动完成的回调函数\n */\nconst scrollTo = (scrollElement, top, afterStop) => {\n const $scrollElement = _getScrollElement(scrollElement)\n let scrollTop = $scrollElement.scrollTop\n let step = 0\n const distance = top - scrollTop\n const MAX_HEIGHT = $scrollElement.scrollHeight\n const MAX_TOP = top - MAX_HEIGHT <= 0 ? top : MAX_HEIGHT\n const stop = (top) => {\n if (isFunction(afterStop)) {\n afterStop(top)\n }\n\n return false\n }\n const play = () => {\n step += 1\n\n // 向上滚动\n if (distance < 0) {\n scrollTop -= easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop <= top) {\n $scrollElement.scrollTop = top\n return stop(top)\n }\n } else {\n scrollTop += easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop >= MAX_TOP) {\n $scrollElement.scrollTop = MAX_TOP\n return stop(MAX_TOP)\n }\n }\n\n requestAnimationFrame(play)\n }\n\n requestAnimationFrame(play)\n}\n\nexport default scrollTo\n","import isFunction from '../types/isFunction'\n\n/**\n * later - 延迟执行方法\n * ========================================================================\n * @method later\n * @param {Function} fn\n * @param {Number} [delay]\n * @returns {number|boolean}\n */\nconst later = (fn, delay = 300) => {\n if (!isFunction(fn)) {\n return false\n }\n\n return setTimeout(() => {\n fn()\n }, delay)\n}\n\nexport default later\n","/**\n * 停止事件(阻止默认行为和阻止事件的捕获或冒泡)\n * ========================================================================\n * @method stop\n * @param {Event} evt - 事件对象\n *\n * @example\n *
\n * Service\n * Help\n *
\n *\n * const $nav = document.querySelector('#nav')\n * const $service = document.querySelector('.anchor')\n *\n * on($nav, 'click', function(evt) {\n * console.log('你点击了导航栏')\n * })\n *\n * on($anchor, 'click', function(evt) {\n * console.log('tagName', this.tagName)\n *\n * // 工作台输出:'a'\n * // 不会触发事件冒泡,输出:'你点击了导航栏'\n * // 也不会切换到 href 属性的页面,阻止了点击链接的默认行为\n * stopEvent(evt)\n * })\n */\nconst stop = function (evt) {\n evt.stopPropagation()\n evt.preventDefault()\n}\n\nexport default stop\n"],"names":["isString","str","hasOwn","obj","prop","hasOwnProperty","Object","prototype","call","toString","val","apply","isFunction","isObject","o","_subscribers","_hasDirectSubscribersFor","topic","length","has","isDirect","found","position","lastIndexOf","substring","_hasSubscribers","emit","data","async","execute","forEach","subscriber","message","indexOf","callback","context","deliver","setTimeout","guid","uuid","prefix","_removeSubscriber","off","token","keys","subject","execution","j","splice","_removeSubscriberByToken","Base","constructor","options","this","attrs","initialize","attr","render","addListeners","value","origin","source","arguments","destroy","removeListeners","reload","$emit","event","publish","$on","handler","push","subscribe","$off","unsubscribe","isElement","nodeName","tagName","nodeType","easeInQuad","x","_getScrollElement","scrollElement","$rootElements","$scrollElement","document","querySelector","querySelectorAll","scrollTop","offsetTop","el","top","offsetParent","matches","selector","sel","replace","msMatchesSelector","getParentOrHost","host","parentNode","CAPTURE_EVENTS","_off","type","fn","capture","_delegateListener","listeners","_listeners","index","listener","i","_delete","removeEventListener","purgeElement","recurse","$element","$children","childNodes","filter","getListeners","$child","on","once","evt","target","getTarget","delegateTarget","ctx","includeCTX","startsWith","closest","overrideContext","addEventListener","isArray","Array","SYMBOLS","getSymbols","name","iconSet","patternName","patternSet","find","symbol","fullName","exec","iconName","getSymbol","paint","$body","body","$icons","symbols","add","innerHTML","join","createElement","insertBefore","firstChild","trim","isDOM","isHTMLCollection","fragment","isTextNode","setAttribute","toLowerCase","style","cssText","className","isSVG","pattern","RegExp","test","icon","size","color","width","height","defaultRules","cssRules","$icon","$svg","binds","svg","_updateHeading","$heading","$fragment","createDocumentFragment","CLS_HEADING","hasAnchor","isAtStart","showCode","chapterCode","anchorURL","headingId","id","text","$anchor","children","$el","isValidChild","child","append","createTextNode","appendChild","every","href","removeClass","classList","allClass","contains","hasClass","remove","_resetHeading","removeAttribute","removeChild","getChapters","headings","chapterTextFilter","previous","level","chapters","heading","headingLevel","current","parseInt","pid","differ","_getChapterParentIdByDiffer","rel","groups","group","JSON","stringify","cb","code","String","c","subjects","_getChaptersWithCode","Anchors","super","DEFAULTS","$articleElement","$headings","created","articleElement","isTreeStructured","list","nodeKey","parentKey","map","roots","item","node","toTree","count","mounted","scrollTo","after","afterStop","step","distance","MAX_HEIGHT","scrollHeight","MAX_TOP","stop","play","requestAnimationFrame","beforeDestroy","afterDestroy","onAnchorTrigger","afterScroll","stickyHeight","max","clientHeight","delay","later","min","stopPropagation","preventDefault"],"mappings":"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"} \ No newline at end of file diff --git a/api/pug/methods/$off.pug b/api/pug/methods/$off.pug index 747dbcf2..8b378362 100644 --- a/api/pug/methods/$off.pug +++ b/api/pug/methods/$off.pug @@ -34,10 +34,10 @@ section.section console.log('handler:', msg) } - outline.$on('created', handler) + outline.$on('created') // 取消订阅 author 主题 - outline.$off('created', handler) + outline.$off('created') // 不会有任何反应,因为已经取消订阅了 outline.$emit('created') diff --git a/api/pug/properties/section.pug b/api/pug/properties/section.pug index fb4d154e..36c13b98 100644 --- a/api/pug/properties/section.pug +++ b/api/pug/properties/section.pug @@ -3,10 +3,10 @@ section.section h2.section__title Properties div.section__content p outline.js 重构后,对外放 4 个重要的属性:anchors、drawer、chapters 和 toolbar。它们都是独立的对象实例,提供了 outline.js 所有的能力(属性和方法)。 - include DEFAULTS include attrs include buttons include anchors include chapters include drawer include toolbar + include DEFAULTS diff --git a/api/pug/script.pug b/api/pug/script.pug index 0e767fbc..96f09dd4 100644 --- a/api/pug/script.pug +++ b/api/pug/script.pug @@ -1,25 +1,23 @@ script(src="js/outline.min.js") script. - (function(){ - const defaults = Outline.DEFAULTS - let outline + const defaults = Outline.DEFAULTS + let outline - defaults.selector = 'h2,h3' - defaults.title = false - defaults.showCode = false - defaults.position = 'sticky' - defaults.parentElement = '#aside' - defaults.scrollElement = '#main' - defaults.articleElement = '#article' - defaults.git = 'https://github.com/yaohaixiao/outline.js' - defaults.tags = 'https://github.com/yaohaixiao/outline.js/tags' - defaults.issues = 'https://github.com/yaohaixiao/outline.js/issues' - defaults.print = { - element: '#article', - title: document.querySelector('.main__h1') - } - defaults.chapterTextFilter = (text) => { - return text.replace(/\s*\(.*?\)/, '()') - } - outline = new Outline(Outline.DEFAULTS) - })() + defaults.selector = 'h2,h3' + defaults.title = false + defaults.showCode = false + defaults.position = 'sticky' + defaults.parentElement = '#aside' + defaults.scrollElement = '#main' + defaults.articleElement = '#article' + defaults.git = 'https://github.com/yaohaixiao/outline.js' + defaults.tags = 'https://github.com/yaohaixiao/outline.js/tags' + defaults.issues = 'https://github.com/yaohaixiao/outline.js/issues' + defaults.print = { + element: '#article', + title: document.querySelector('.main__h1') + } + defaults.chapterTextFilter = (text) => { + return text.replace(/\s*\(.*?\)/, '()') + } + outline = new Outline(Outline.DEFAULTS) diff --git a/chapters.js b/chapters.js index 093630ae..bf1d6217 100644 --- a/chapters.js +++ b/chapters.js @@ -16,7 +16,6 @@ import removeClass from './utils/dom/removeClass' import offsetTop from './utils/dom/offsetTop' import getStyle from './utils/dom/getStyle' import setProperty from './utils/dom/setProperty' -import publish from './utils/observer/emit' import cloneDeep from './utils/lang/cloneDeep' import _getScrollElement from './utils/dom/_getScrollElement' @@ -511,7 +510,7 @@ class Chapters extends Base { later(() => { this.playing = false - publish('toolbar:update', { + this.$emit('toolbar:update', { top, min, max @@ -552,7 +551,7 @@ class Chapters extends Base { this.sticky() } - publish('toolbar:update', { + this.$emit('toolbar:update', { top, min, max @@ -587,7 +586,7 @@ class Chapters extends Base { on($el, '.outline-chapters__anchor', 'click', this.onSelect, this, true) at($element, 'scroll', this.onScroll, this, true) if (this.isSticky()) { - at($element, 'resize', this.onResize, this, true) + at(window, 'resize', this.onResize, this, true) } return this @@ -608,7 +607,7 @@ class Chapters extends Base { off($element, 'scroll', this.onScroll) if (this.isSticky()) { - at($element, 'resize', this.onResize) + at(window, 'resize', this.onResize) } if (this.Observer) { diff --git a/chapters.min.js b/chapters.min.js index a32bca3f..2bc9ab85 100644 --- a/chapters.min.js +++ b/chapters.min.js @@ -1,2 +1,2 @@ -!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).Chapters=e()}(this,(function(){"use strict";const t=t=>"string"==typeof t,e=(t,e)=>{const s=Object.prototype.hasOwnProperty;return t&&s.call(t,e)},s=t=>Object.prototype.toString.apply(t),i=t=>"function"==typeof t||"[object Function]"===s(t),r=t=>("[object Object]"===s(t)||"object"==typeof t||i(t))&&null!==t,l={},n=t=>e(l,t)&&l[t].length>0,o=(t,e=!0)=>e?n(t):(t=>{let e=n(t),s=t.lastIndexOf(".");for(;!e&&-1!==s;)s=(t=t.substring(0,s)).lastIndexOf("."),e=n(t);return e})(t),a=(t,e,i=!0)=>{const r=t=>{if(!n(t))return!1;l[t].forEach((t=>{const i=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]","[object BigInt64Array]","[object BigUint64Array]"].indexOf(s(e))>-1?e.toString():e;t.callback.call(t.context||t,i)}))},a=()=>{let e=t,s=t.lastIndexOf(".");for(;-1!==s;)e=e.substring(0,s),s=e.lastIndexOf("."),r(e);r(t),r("*")};if(!o(t))return!1;i?setTimeout(a,10):a()},c=(()=>{let t=0;return e=>(t+=1,e?e+"-"+t:"guid-"+t)})(),h=t=>{if(!e(l,t))return!1;delete l[t]},u=(t,e)=>{if(!o(t))return!1;e?(t=>{const e=Object.keys(l);if(!t||e.length<1)return!1;e.forEach((e=>{const s=l[e];let i;s.forEach(((e,r)=>{e.callback!==t&&e.token!==t||(i=e.topic,s.splice(-1,r))})),s.length<1&&h(i)}))})(e):h(t)};class d{constructor(t){this.attrs={},t&&this.initialize(t)}initialize(t){return this.attr(t).render().addListeners(),this}attr(s,i){const l=this.attrs;return t(s)?i&&e(l,s)?(l[s]=i,this):l[s]:r(s)?(n=l,o=s,Object.keys(o).forEach((t=>{e(o,t)&&(n[t]=o[t])})),this):0===arguments.length?l:this;var n,o}render(){return this}destroy(){return this.removeListeners(),this}reload(t){return this.destroy().initialize(this.attr(t)),this}$emit(t,e){return a(t,e),this}$on(t,e){return((t,e,s=null)=>{const r=c();let n="symbol"==typeof t?t.toString():t;i(e)&&(l[n]||(l[n]=[]),l[n].push({topic:n,callback:e,context:s,token:r}))})(t,e,this),this}$off(t,e){return u(t,e),this}addListeners(){return this}removeListeners(){return this}}const p=t=>!!(r(t)&&t.nodeName&&t.tagName&&1===t.nodeType),m=(t,e=300)=>!!i(t)&&setTimeout((()=>{t()}),e),f=["focusout","blur","focusin","focus","load","unload","mouseenter","mouseleave"],y=(t,e,s)=>{const i=f.indexOf(e)>-1;s._delegateListener&&delete(s=s._delegateListener)._delegateListener,function(t,e,s){const i=t._listeners;let r=-1;if(i.length<1)return!1;i.forEach(((t,i)=>{const l=t.fn;e===t.type&&(r=i,l===s&&(r=i))})),r>-1&&i.splice(r,1)}(t,e,s),t.removeEventListener(e,s,i)},g=function(e,s,i=!1){const r=t(e)?document.querySelector(e):e,l=r.childNodes,n=((e,s)=>{let i=e._listeners||[];return t(s)&&s&&(i=i.filter((t=>t.type===s))),i})(r,s);n.forEach((t=>{y(r,t.type,t.fn)})),(i||!0===s||1===arguments.length)&&r&&l&&l.forEach((t=>{p(t)&&g(t,s,i)}))},b=(t,e,s)=>{if(!i(s))return g(t,e);y(t,e,s)},$=(t,e,s,r,l,n=!1)=>{const o=f.indexOf(e)>-1,a=function(i){let o=l||t;!0===l&&(o=r),!0===n&&b(t,e,a),s.call(o,i,r)};if(!i(s))return!1;t._listeners||(t._listeners=[]),t._listeners.push({el:t,type:e,fn:a,data:r,context:l,capture:o}),s._delegateListener=a,t.addEventListener(e,a,o)},T=(t,e="")=>{const s=e.replace(/^>/i,"");return!!(e&&s&&t)&&(t.matches?t.matches(s):!!t.msMatchesSelector&&t.msMatchesSelector(s))},v=t=>t.host&&t!==document&&t.host.nodeType?t.host:t.parentNode,_=(t,e,s,i,r,l,n=!1)=>{const o=f.indexOf(s)>-1,a=function(o){const c=function(t){const e=t.target;return(s=e)&&3===s.nodeType?s.parentNode:s;var s}(o),h=((t,e,s,i)=>{const r=s||document;if(!t)return null;do{if(null!=e&&(e.startsWith(">")?t.parentNode===r&&T(t,e):T(t,e))||i&&t===r)return t;if(t===r)break}while(t=v(t))})(c,e,t);let u=l||t;o.delegateTarget=h,!0===l&&(u=r),h&&(!0===n&&b(t,s,a),i.call(u,o,r))};t._listeners||(t._listeners=[]),t._listeners.push({el:t,selector:e,type:s,fn:a,data:r,context:l,capture:o}),i._delegateListener=a,t.addEventListener(s,a,o)},E=t=>Array.isArray?Array.isArray(t):"[object Array]"===s(t),x=t=>{return!(!r(t)||!(p(t)||(t=>!(!r(t)||"[object NodeList]"!==s(t)))(t)||(e=t,r(e)&&"[object DocumentFragment]"===s(e))||(t=>!(!r(t)||!("[object Text]"===s(t)||t.tagName&&3===t.nodeType)))(t)));var e},S=(s,i,l)=>{const n=document.createDocumentFragment(),o=document.createElement(s),a=e=>x(e)||t(e),c=e=>{let s;if(!a(e))return!1;x(e)?s=e:t(e)&&(s=document.createTextNode(e)),n.appendChild(s)};return r(i)?Object.keys(i).forEach((t=>{e(i,t)&&((t,e,s)=>{let i=t.tagName.toLowerCase();switch(e){case"style":t.style.cssText=s;break;case"value":"input"===i||"textarea"===i?t.value=s:t.setAttribute(e,s);break;case"className":t.className=s;break;default:t.setAttribute(e,s)}})(o,t,i[t])})):E(i)&&i.every((t=>a(t)))&&i.forEach((t=>{c(t)})),E(l)?l.forEach((t=>{c(t)})):c(l),o.appendChild(n),o},k=t=>t*t,j=(e=null)=>{let s,i;return e?t(e)?i=document.querySelector(e):p(e)&&(i=e):(s=document.querySelectorAll("html,body"),i=s[0].scrollTop-s[1].scrollTop>=0?s[0]:s[1]),i},A=(t,e)=>{const s=new RegExp("(\\s|^)"+e+"(\\s|$)");let i,r;return!!p(t)&&(i=t.className,!!i&&(r=t.classList,r?.contains?t.classList.contains(e):!!s.exec(i)))},N=(t,e)=>{let s,i;if(A(t,e))return!1;s=t.classList,s?.add?s.add(e):(i=t.className,i+=i.length>0?" "+e:e,t.className=i)},O=(e,s)=>{let i,r=e.className;if(!r||!A(e,s))return!1;var l;i=e.classList,i?.remove?i.remove(s):(l=r.replace(s,""),r=!!t(l)&&l.replace(/(^\s+)|(\s+$)/g,""),e.className=r)},L=t=>{let e=t.offsetTop;return null!==t.offsetParent&&(e+=L(t.offsetParent)),e},C=(t,e)=>getComputedStyle(t)[e],w=(t,e)=>{document.documentElement.style.setProperty(t,e)},I=t=>{let e;return null===t?null:(e=Object.assign({},t),Object.keys(e).forEach((s=>e[s]="object"==typeof t[s]?I(t[s]):t[s])),E(t)?(e.length=t.length,Array.from(e)):e)};class z extends d{constructor(t){super(),this.attrs=I(z.DEFAULTS),this.$el=null,this.$title=null,this.$main=null,this.$list=null,this.$placeholder=null,this.$parentElement=null,this.$scrollElement=null,this.chapters=[],this.closed=!1,this.active=0,this.offsetTop=0,this.offsetWidth=0,this.$active=null,this.scrollTimer=null,this.resizeTimer=null,this.playing=!1,this.Observer=null,t&&this.initialize(t)}initialize(e){let s,r,l,n;return this.attr(e),s=this.attr("created"),r=this.attr("parentElement"),l=this.attr("scrollElement"),t(r)?n=document.querySelector(r):p(r)&&(n=r),this.$parentElement=n,this.$scrollElement=j(l),this.chapters=this.attr("chapters"),this.closed=this.attr("closed"),this.active=this.attr("active"),i(s)&&s.call(this),this.chapters.length<1||(this.render().addListeners(),this.$active=document.querySelector(`#chapter-${this.active}`)),this}isClosed(){return this.closed}isSticky(){return"sticky"===this.attr("position")}isFixed(){return"fixed"===this.attr("position")}isInside(){return this.isFixed()||this.isSticky()}isOutside(){return!this.isInside()}_paintEdge(){const t=document.createDocumentFragment(),e=this.attr("title"),s=this.attr("customClass"),i=this.$parentElement,r=[];let l,n,o,a,c=null;return i?(this.isInside()&&e&&(c=S("h2",{className:"outline-chapters__title"},[e]),this.$title=c,r.push(c)),o=S("ul",{className:"outline-chapters__list"},[""]),this.$list=o,a=S("div",{className:"outline-chapters__placeholder"},[""]),this.$placeholder=a,n=S("div",{className:"outline-chapters__main"},[o,a]),this.$main=n,r.push(n),l=S("nav",{id:"outline-chapters",className:"outline-chapters outline-chapters_hidden"},r),this.$el=l,this.isSticky()&&(this.calculateStickyHeight(),N(l,"outline-chapters_sticky")),s&&N(l,s),t.appendChild(l),i.appendChild(t),this):this}render(){const t=this.attr("showCode"),e=this.attr("mounted"),s=this.$parentElement,r=this.chapters;let l,n;return!s||r.length<1||(this._paintEdge(),l=this.$el,n=this.$list,((t,e,s=!1)=>{const i=t=>document.querySelector(`#${t}`);e.forEach((e=>{const r=e.pid,l=e.id,n=e.rel,o=S("span",{className:"outline-chapters__text"},[e.text]),a=S("a",{id:`chapter__anchor-${l}`,className:"outline-chapters__anchor",href:"#"+n,rel:n,"data-id":l},[o]);let c,h,u,d;s&&(c=S("span",{className:"outline-chapters__code","data-id":l},[e.code]),a.insertBefore(c,a.firstChild)),h=S("li",{id:`chapter-${l}`,className:"outline-chapters__item","data-id":l},[a]),-1===r?t.appendChild(h):(d=i(`chapter-${r}`),u=i(`subject-${r}`),u?u.appendChild(h):(u=S("ul",{id:"subject-"+r,className:"outline-chapters__subject"},[h]),d.appendChild(u)))}))})(n,r,t),O(l,"outline-chapters_hidden"),this.positionPlaceholder(this.active),this.offsetTop=L(l),this.offsetWidth=l.offsetWidth,this.isFixed()&&(this.sticky(),w("--outline-chapters-width",`${this.offsetWidth}px`)),i(e)&&e.call(this),this.onObserver()),this}positionPlaceholder(t){const e=this.$main,s=this.$list,i=this.$placeholder,r=s.querySelector(".outline-chapters__anchor"),l=parseInt(C(e,"padding-top"),10),n=parseInt(C(e,"border-top-width"),10),o=parseInt(C(s,"padding-top"),10),a=parseInt(C(s,"margin-top"),10),c=parseInt(C(s,"border-top-width"),10);let h,u=r.offsetHeight,d=0;return l&&(d+=l),o&&(d+=o),a&&(d+=a),n&&(d+=n),c&&(d+=c),h=u*t,i.style.cssText=`transform: translateY(${d+h}px);height:${u}px;`,this}highlight(t){const e=this.$el.querySelector(`#chapter__anchor-${t}`),s="outline-chapters_active";return e?(this.$active&&O(this.$active,s),this.active=parseInt(e.getAttribute("data-id"),10),this.$active=e,N(this.$active,s),this.positionPlaceholder(this.active),this):this}sticky(){const t=this.attr("afterSticky"),e="outline-chapters_fixed",s=this.$el,r=this.offsetTop,l=this.$scrollElement.scrollTop;let n;return this.isFixed()?(n=l>=r,n?N(s,e):O(s,e),i(t)&&t.call(this,this.isClosed(),n),this):this}calculateStickyHeight(){const t=document.documentElement,e=Math.max(t.clientHeight||0,window.innerHeight||0);return w("--outline-sticky-height",`${e}px`),this}scrollTo(t,e){return((t,e,s)=>{const r=j(t);let l=r.scrollTop,n=0;const o=e-l,a=r.scrollHeight,c=e-a<=0?e:a,h=t=>(i(s)&&s(t),!1),u=()=>{if(n+=1,o<0){if(l-=k(n),r.scrollTop=l,l<=e)return r.scrollTop=e,h(e)}else if(l+=k(n),r.scrollTop=l,l>=c)return r.scrollTop=c,h(c);requestAnimationFrame(u)};requestAnimationFrame(u)})(this.$scrollElement,t,e),this}show(){const t="outline-chapters_folded",e="outline-chapters_hidden",s=this.attr("afterOpened"),r=this.$el,l=this.$parentElement;return this.isInside()?(O(l,e),O(r,e),m((()=>{O(l,t),O(r,t)}),30)):O(r,e),this.closed=!1,i(s)&&s.call(this),this}hide(){const t="outline-chapters_folded",e="outline-chapters_hidden",s=this.attr("afterClosed"),r=this.$el,l=this.$parentElement;return this.isInside()?(N(l,t),N(r,t),m((()=>{N(l,e),N(r,e)}))):N(r,e),this.closed=!0,i(s)&&s.call(this),this}toggle(){const t=this.attr("afterToggle"),e=this.offsetTop,s=this.$scrollElement.scrollTop;let r;return this.isClosed()?this.show():this.hide(),i(t)&&m((()=>{r=s>=e,t.call(this,this.isClosed(),r)})),this}destroy(){const t=this.attr("beforeDestroy"),e=this.attr("afterDestroy");return i(t)&&t.call(this),this.removeListeners(),this.$parentElement.removeChild(this.$el),this.attr(z.DEFAULTS),this.$el=null,this.$title=null,this.$main=null,this.$list=null,this.$placeholder=null,this.$parentElement=null,this.$scrollElement=null,this.chapters=[],this.active=0,this.offsetTop=0,this.$active=null,this.closed=!1,this.scrollTimer&&(clearTimeout(this.scrollTimer),this.scrollTimer=null),this.resizeTimer&&(clearTimeout(this.resizeTimer),this.resizeTimer=null),i(e)&&e.call(this),this.Observer&&(this.Observer=null),this}onObserver(){const t=this.attr("selector");let e=null;return this.Observer=((t,e={})=>{const s=e.root||null,r=e.selector||".outline-heading",l=e.context||null,n={rootMargin:e.rootMargin||"0px 0px -90% 0px"},o=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&i(t)&&t.call(l||e.target,e.target)}))}),n),a=p(s)?s:document;return s&&(n.root=s),a.querySelectorAll(r).forEach((t=>{o.observe(t)})),o})((t=>{const s=t.getAttribute("data-id");if(this.playing)return!1;e&&clearTimeout(e),e=m((()=>{this.highlight(s)}),100)}),{selector:t,context:this}),this}onSelect(t){const e=this.attr("stickyHeight"),s=t.delegateTarget,r=s.getAttribute("data-id"),l=s.href.split("#")[1],n=document.querySelector(`#${l}`),o=L(n)-(e+10),c=this.$scrollElement.scrollHeight,h=this.attr("afterScroll"),u=()=>{i(h)&&h.call(this,"chapter"),m((()=>{this.playing=!1,a("toolbar:update",{top:o,min:0,max:c})}))};return this.playing=!0,this.isFixed()?(this.sticky(),m((()=>{this.scrollTo(o,u),this.highlight(r)}),10)):(this.scrollTo(o,u),this.highlight(r)),function(t){t.stopPropagation(),t.preventDefault()}(t),this}onScroll(){const t=this.$scrollElement;return this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=m((()=>{const e=t.scrollTop,s=t.scrollHeight-t.clientHeight;this.isFixed()&&this.sticky(),a("toolbar:update",{top:e,min:0,max:s})}),100),this}onResize(){return this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=m((()=>{this.calculateStickyHeight()})),this}addListeners(){const t=this.$el,e=this.$scrollElement,s=e.tagName.toLowerCase();let i=e;return"html"!==s&&"body"!==s||(i=window),_(t,".outline-chapters__anchor","click",this.onSelect,this,!0),$(i,"scroll",this.onScroll,this,!0),this.isSticky()&&$(i,"resize",this.onResize,this,!0),this}removeListeners(){const t=this.attr("selector"),e=this.$el,s=this.$scrollElement,i=s.tagName.toLowerCase();let r=s;return"html"!==i&&"body"!==i||(r=window),b(e,"click",this.onSelect),b(r,"scroll",this.onScroll),this.isSticky()&&$(r,"resize",this.onResize),this.Observer&&document.querySelectorAll(t).forEach((t=>{this.Observer.unobserve(t)})),this}}return z.DEFAULTS={parentElement:"",scrollElement:"",selector:".outline-heading",active:0,closed:!1,showCode:!0,position:"relative",stickyHeight:0,chapters:[],created:null,mounted:null,afterClosed:null,afterOpened:null,afterScroll:null,beforeDestroy:null,afterDestroy:null,afterSticky:null},z})); +!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).Chapters=e()}(this,(function(){"use strict";const t=t=>"string"==typeof t,e=(t,e)=>{const s=Object.prototype.hasOwnProperty;return t&&s.call(t,e)},s=t=>Object.prototype.toString.apply(t),i=t=>"function"==typeof t||"[object Function]"===s(t),r=t=>("[object Object]"===s(t)||"object"==typeof t||i(t))&&null!==t,l={},n=t=>e(l,t)&&l[t].length>0,o=(t,e=!0)=>e?n(t):(t=>{let e=n(t),s=t.lastIndexOf(".");for(;!e&&-1!==s;)s=(t=t.substring(0,s)).lastIndexOf("."),e=n(t);return e})(t),a=(t,e,i=!0)=>{const r=t=>{if(!n(t))return!1;l[t].forEach((t=>{const i=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]","[object BigInt64Array]","[object BigUint64Array]"].indexOf(s(e))>-1?e.toString():e;t.callback.call(t.context||t,i)}))},a=()=>{let e=t,s=t.lastIndexOf(".");for(;-1!==s;)e=e.substring(0,s),s=e.lastIndexOf("."),r(e);r(t),r("*")};if(!o(t))return!1;i?setTimeout(a,10):a()},c=(()=>{let t=0;return e=>(t+=1,e?e+"-"+t:"guid-"+t)})(),h=t=>{if(!e(l,t))return!1;delete l[t]},u=(t,e)=>{if(!o(t))return!1;e?(t=>{const e=Object.keys(l);if(!t||e.length<1)return!1;e.forEach((e=>{const s=l[e];let i;s.forEach(((e,r)=>{e.callback!==t&&e.token!==t||(i=e.topic,s.splice(-1,r))})),s.length<1&&h(i)}))})(e):h(t)};class d{constructor(t){this.attrs={},t&&this.initialize(t)}initialize(t){return this.attr(t).render().addListeners(),this}attr(s,i){const l=this.attrs;return t(s)?i&&e(l,s)?(l[s]=i,this):l[s]:r(s)?(n=l,o=s,Object.keys(o).forEach((t=>{e(o,t)&&(n[t]=o[t])})),this):0===arguments.length?l:this;var n,o}render(){return this}destroy(){return this.removeListeners(),this}reload(t){return this.destroy().initialize(this.attr(t)),this}$emit(t,e){return a(t,e),this}$on(t,e){return((t,e,s=null)=>{const r=c();let n="symbol"==typeof t?t.toString():t;i(e)&&(l[n]||(l[n]=[]),l[n].push({topic:n,callback:e,context:s,token:r}))})(t,e,this),this}$off(t,e){return u(t,e),this}addListeners(){return this}removeListeners(){return this}}const p=t=>!!(r(t)&&t.nodeName&&t.tagName&&1===t.nodeType),m=(t,e=300)=>!!i(t)&&setTimeout((()=>{t()}),e),f=["focusout","blur","focusin","focus","load","unload","mouseenter","mouseleave"],y=(t,e,s)=>{const i=f.indexOf(e)>-1;s._delegateListener&&delete(s=s._delegateListener)._delegateListener,function(t,e,s){const i=t._listeners;let r=-1;if(i.length<1)return!1;i.forEach(((t,i)=>{const l=t.fn;e===t.type&&(r=i,l===s&&(r=i))})),r>-1&&i.splice(r,1)}(t,e,s),t.removeEventListener(e,s,i)},g=function(e,s,i=!1){const r=t(e)?document.querySelector(e):e,l=r.childNodes,n=((e,s)=>{let i=e._listeners||[];return t(s)&&s&&(i=i.filter((t=>t.type===s))),i})(r,s);n.forEach((t=>{y(r,t.type,t.fn)})),(i||!0===s||1===arguments.length)&&r&&l&&l.forEach((t=>{p(t)&&g(t,s,i)}))},$=(t,e,s)=>{if(!i(s))return g(t,e);y(t,e,s)},b=(t,e,s,r,l,n=!1)=>{const o=f.indexOf(e)>-1,a=function(i){let o=l||t;!0===l&&(o=r),!0===n&&$(t,e,a),s.call(o,i,r)};if(!i(s))return!1;t._listeners||(t._listeners=[]),t._listeners.push({el:t,type:e,fn:a,data:r,context:l,capture:o}),s._delegateListener=a,t.addEventListener(e,a,o)},T=(t,e="")=>{const s=e.replace(/^>/i,"");return!!(e&&s&&t)&&(t.matches?t.matches(s):!!t.msMatchesSelector&&t.msMatchesSelector(s))},v=t=>t.host&&t!==document&&t.host.nodeType?t.host:t.parentNode,_=(t,e,s,i,r,l,n=!1)=>{const o=f.indexOf(s)>-1,a=function(o){const c=function(t){const e=t.target;return(s=e)&&3===s.nodeType?s.parentNode:s;var s}(o),h=((t,e,s,i)=>{const r=s||document;if(!t)return null;do{if(null!=e&&(e.startsWith(">")?t.parentNode===r&&T(t,e):T(t,e))||i&&t===r)return t;if(t===r)break}while(t=v(t))})(c,e,t);let u=l||t;o.delegateTarget=h,!0===l&&(u=r),h&&(!0===n&&$(t,s,a),i.call(u,o,r))};t._listeners||(t._listeners=[]),t._listeners.push({el:t,selector:e,type:s,fn:a,data:r,context:l,capture:o}),i._delegateListener=a,t.addEventListener(s,a,o)},E=t=>Array.isArray?Array.isArray(t):"[object Array]"===s(t),x=t=>{return!(!r(t)||!(p(t)||(t=>!(!r(t)||"[object NodeList]"!==s(t)))(t)||(e=t,r(e)&&"[object DocumentFragment]"===s(e))||(t=>!(!r(t)||!("[object Text]"===s(t)||t.tagName&&3===t.nodeType)))(t)));var e},S=(s,i,l)=>{const n=document.createDocumentFragment(),o=document.createElement(s),a=e=>x(e)||t(e),c=e=>{let s;if(!a(e))return!1;x(e)?s=e:t(e)&&(s=document.createTextNode(e)),n.appendChild(s)};return r(i)?Object.keys(i).forEach((t=>{e(i,t)&&((t,e,s)=>{let i=t.tagName.toLowerCase();switch(e){case"style":t.style.cssText=s;break;case"value":"input"===i||"textarea"===i?t.value=s:t.setAttribute(e,s);break;case"className":t.className=s;break;default:t.setAttribute(e,s)}})(o,t,i[t])})):E(i)&&i.every((t=>a(t)))&&i.forEach((t=>{c(t)})),E(l)?l.forEach((t=>{c(t)})):c(l),o.appendChild(n),o},k=t=>t*t,j=(e=null)=>{let s,i;return e?t(e)?i=document.querySelector(e):p(e)&&(i=e):(s=document.querySelectorAll("html,body"),i=s[0].scrollTop-s[1].scrollTop>=0?s[0]:s[1]),i},A=(t,e)=>{const s=new RegExp("(\\s|^)"+e+"(\\s|$)");let i,r;return!!p(t)&&(i=t.className,!!i&&(r=t.classList,r?.contains?t.classList.contains(e):!!s.exec(i)))},N=(t,e)=>{let s,i;if(A(t,e))return!1;s=t.classList,s?.add?s.add(e):(i=t.className,i+=i.length>0?" "+e:e,t.className=i)},O=(e,s)=>{let i,r=e.className;if(!r||!A(e,s))return!1;var l;i=e.classList,i?.remove?i.remove(s):(l=r.replace(s,""),r=!!t(l)&&l.replace(/(^\s+)|(\s+$)/g,""),e.className=r)},L=t=>{let e=t.offsetTop;return null!==t.offsetParent&&(e+=L(t.offsetParent)),e},w=(t,e)=>getComputedStyle(t)[e],C=(t,e)=>{document.documentElement.style.setProperty(t,e)},I=t=>{let e;return null===t?null:(e=Object.assign({},t),Object.keys(e).forEach((s=>e[s]="object"==typeof t[s]?I(t[s]):t[s])),E(t)?(e.length=t.length,Array.from(e)):e)};class z extends d{constructor(t){super(),this.attrs=I(z.DEFAULTS),this.$el=null,this.$title=null,this.$main=null,this.$list=null,this.$placeholder=null,this.$parentElement=null,this.$scrollElement=null,this.chapters=[],this.closed=!1,this.active=0,this.offsetTop=0,this.offsetWidth=0,this.$active=null,this.scrollTimer=null,this.resizeTimer=null,this.playing=!1,this.Observer=null,t&&this.initialize(t)}initialize(e){let s,r,l,n;return this.attr(e),s=this.attr("created"),r=this.attr("parentElement"),l=this.attr("scrollElement"),t(r)?n=document.querySelector(r):p(r)&&(n=r),this.$parentElement=n,this.$scrollElement=j(l),this.chapters=this.attr("chapters"),this.closed=this.attr("closed"),this.active=this.attr("active"),i(s)&&s.call(this),this.chapters.length<1||(this.render().addListeners(),this.$active=document.querySelector(`#chapter-${this.active}`)),this}isClosed(){return this.closed}isSticky(){return"sticky"===this.attr("position")}isFixed(){return"fixed"===this.attr("position")}isInside(){return this.isFixed()||this.isSticky()}isOutside(){return!this.isInside()}_paintEdge(){const t=document.createDocumentFragment(),e=this.attr("title"),s=this.attr("customClass"),i=this.$parentElement,r=[];let l,n,o,a,c=null;return i?(this.isInside()&&e&&(c=S("h2",{className:"outline-chapters__title"},[e]),this.$title=c,r.push(c)),o=S("ul",{className:"outline-chapters__list"},[""]),this.$list=o,a=S("div",{className:"outline-chapters__placeholder"},[""]),this.$placeholder=a,n=S("div",{className:"outline-chapters__main"},[o,a]),this.$main=n,r.push(n),l=S("nav",{id:"outline-chapters",className:"outline-chapters outline-chapters_hidden"},r),this.$el=l,this.isSticky()&&(this.calculateStickyHeight(),N(l,"outline-chapters_sticky")),s&&N(l,s),t.appendChild(l),i.appendChild(t),this):this}render(){const t=this.attr("showCode"),e=this.attr("mounted"),s=this.$parentElement,r=this.chapters;let l,n;return!s||r.length<1||(this._paintEdge(),l=this.$el,n=this.$list,((t,e,s=!1)=>{const i=t=>document.querySelector(`#${t}`);e.forEach((e=>{const r=e.pid,l=e.id,n=e.rel,o=S("span",{className:"outline-chapters__text"},[e.text]),a=S("a",{id:`chapter__anchor-${l}`,className:"outline-chapters__anchor",href:"#"+n,rel:n,"data-id":l},[o]);let c,h,u,d;s&&(c=S("span",{className:"outline-chapters__code","data-id":l},[e.code]),a.insertBefore(c,a.firstChild)),h=S("li",{id:`chapter-${l}`,className:"outline-chapters__item","data-id":l},[a]),-1===r?t.appendChild(h):(d=i(`chapter-${r}`),u=i(`subject-${r}`),u?u.appendChild(h):(u=S("ul",{id:"subject-"+r,className:"outline-chapters__subject"},[h]),d.appendChild(u)))}))})(n,r,t),O(l,"outline-chapters_hidden"),this.positionPlaceholder(this.active),this.offsetTop=L(l),this.offsetWidth=l.offsetWidth,this.isFixed()&&(this.sticky(),C("--outline-chapters-width",`${this.offsetWidth}px`)),i(e)&&e.call(this),this.onObserver()),this}positionPlaceholder(t){const e=this.$main,s=this.$list,i=this.$placeholder,r=s.querySelector(".outline-chapters__anchor"),l=parseInt(w(e,"padding-top"),10),n=parseInt(w(e,"border-top-width"),10),o=parseInt(w(s,"padding-top"),10),a=parseInt(w(s,"margin-top"),10),c=parseInt(w(s,"border-top-width"),10);let h,u=r.offsetHeight,d=0;return l&&(d+=l),o&&(d+=o),a&&(d+=a),n&&(d+=n),c&&(d+=c),h=u*t,i.style.cssText=`transform: translateY(${d+h}px);height:${u}px;`,this}highlight(t){const e=this.$el.querySelector(`#chapter__anchor-${t}`),s="outline-chapters_active";return e?(this.$active&&O(this.$active,s),this.active=parseInt(e.getAttribute("data-id"),10),this.$active=e,N(this.$active,s),this.positionPlaceholder(this.active),this):this}sticky(){const t=this.attr("afterSticky"),e="outline-chapters_fixed",s=this.$el,r=this.offsetTop,l=this.$scrollElement.scrollTop;let n;return this.isFixed()?(n=l>=r,n?N(s,e):O(s,e),i(t)&&t.call(this,this.isClosed(),n),this):this}calculateStickyHeight(){const t=document.documentElement,e=Math.max(t.clientHeight||0,window.innerHeight||0);return C("--outline-sticky-height",`${e}px`),this}scrollTo(t,e){return((t,e,s)=>{const r=j(t);let l=r.scrollTop,n=0;const o=e-l,a=r.scrollHeight,c=e-a<=0?e:a,h=t=>(i(s)&&s(t),!1),u=()=>{if(n+=1,o<0){if(l-=k(n),r.scrollTop=l,l<=e)return r.scrollTop=e,h(e)}else if(l+=k(n),r.scrollTop=l,l>=c)return r.scrollTop=c,h(c);requestAnimationFrame(u)};requestAnimationFrame(u)})(this.$scrollElement,t,e),this}show(){const t="outline-chapters_folded",e="outline-chapters_hidden",s=this.attr("afterOpened"),r=this.$el,l=this.$parentElement;return this.isInside()?(O(l,e),O(r,e),m((()=>{O(l,t),O(r,t)}),30)):O(r,e),this.closed=!1,i(s)&&s.call(this),this}hide(){const t="outline-chapters_folded",e="outline-chapters_hidden",s=this.attr("afterClosed"),r=this.$el,l=this.$parentElement;return this.isInside()?(N(l,t),N(r,t),m((()=>{N(l,e),N(r,e)}))):N(r,e),this.closed=!0,i(s)&&s.call(this),this}toggle(){const t=this.attr("afterToggle"),e=this.offsetTop,s=this.$scrollElement.scrollTop;let r;return this.isClosed()?this.show():this.hide(),i(t)&&m((()=>{r=s>=e,t.call(this,this.isClosed(),r)})),this}destroy(){const t=this.attr("beforeDestroy"),e=this.attr("afterDestroy");return i(t)&&t.call(this),this.removeListeners(),this.$parentElement.removeChild(this.$el),this.attr(z.DEFAULTS),this.$el=null,this.$title=null,this.$main=null,this.$list=null,this.$placeholder=null,this.$parentElement=null,this.$scrollElement=null,this.chapters=[],this.active=0,this.offsetTop=0,this.$active=null,this.closed=!1,this.scrollTimer&&(clearTimeout(this.scrollTimer),this.scrollTimer=null),this.resizeTimer&&(clearTimeout(this.resizeTimer),this.resizeTimer=null),i(e)&&e.call(this),this.Observer&&(this.Observer=null),this}onObserver(){const t=this.attr("selector");let e=null;return this.Observer=((t,e={})=>{const s=e.root||null,r=e.selector||".outline-heading",l=e.context||null,n={rootMargin:e.rootMargin||"0px 0px -90% 0px"},o=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&i(t)&&t.call(l||e.target,e.target)}))}),n),a=p(s)?s:document;return s&&(n.root=s),a.querySelectorAll(r).forEach((t=>{o.observe(t)})),o})((t=>{const s=t.getAttribute("data-id");if(this.playing)return!1;e&&clearTimeout(e),e=m((()=>{this.highlight(s)}),100)}),{selector:t,context:this}),this}onSelect(t){const e=this.attr("stickyHeight"),s=t.delegateTarget,r=s.getAttribute("data-id"),l=s.href.split("#")[1],n=document.querySelector(`#${l}`),o=L(n)-(e+10),a=this.$scrollElement.scrollHeight,c=this.attr("afterScroll"),h=()=>{i(c)&&c.call(this,"chapter"),m((()=>{this.playing=!1,this.$emit("toolbar:update",{top:o,min:0,max:a})}))};return this.playing=!0,this.isFixed()?(this.sticky(),m((()=>{this.scrollTo(o,h),this.highlight(r)}),10)):(this.scrollTo(o,h),this.highlight(r)),function(t){t.stopPropagation(),t.preventDefault()}(t),this}onScroll(){const t=this.$scrollElement;return this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=m((()=>{const e=t.scrollTop,s=t.scrollHeight-t.clientHeight;this.isFixed()&&this.sticky(),this.$emit("toolbar:update",{top:e,min:0,max:s})}),100),this}onResize(){return this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=m((()=>{this.calculateStickyHeight()})),this}addListeners(){const t=this.$el,e=this.$scrollElement,s=e.tagName.toLowerCase();let i=e;return"html"!==s&&"body"!==s||(i=window),_(t,".outline-chapters__anchor","click",this.onSelect,this,!0),b(i,"scroll",this.onScroll,this,!0),this.isSticky()&&b(window,"resize",this.onResize,this,!0),this}removeListeners(){const t=this.attr("selector"),e=this.$el,s=this.$scrollElement,i=s.tagName.toLowerCase();let r=s;return"html"!==i&&"body"!==i||(r=window),$(e,"click",this.onSelect),$(r,"scroll",this.onScroll),this.isSticky()&&b(window,"resize",this.onResize),this.Observer&&document.querySelectorAll(t).forEach((t=>{this.Observer.unobserve(t)})),this}}return z.DEFAULTS={parentElement:"",scrollElement:"",selector:".outline-heading",active:0,closed:!1,showCode:!0,position:"relative",stickyHeight:0,chapters:[],created:null,mounted:null,afterClosed:null,afterOpened:null,afterScroll:null,beforeDestroy:null,afterDestroy:null,afterSticky:null},z})); //# sourceMappingURL=chapters.min.js.map diff --git a/chapters.min.js.map b/chapters.min.js.map index 8a093f32..15aff11d 100644 --- a/chapters.min.js.map +++ b/chapters.min.js.map @@ -1 +1 @@ -{"version":3,"file":"chapters.min.js","sources":["utils/types/isString.js","utils/lang/hasOwn.js","utils/lang/toString.js","utils/types/isFunction.js","utils/types/isObject.js","utils/observer/_subscribers.js","utils/observer/_hasDirectSubscribersFor.js","utils/observer/has.js","utils/observer/_hasSubscribers.js","utils/observer/emit.js","utils/types/isTypedArray.js","utils/lang/guid.js","utils/observer/_removeSubscriber.js","utils/observer/off.js","utils/observer/_removeSubscriberByToken.js","base.js","utils/lang/extend.js","utils/observer/on.js","utils/types/isElement.js","utils/lang/later.js","utils/event/enum.js","utils/event/_off.js","utils/event/_delete.js","utils/event/purgeElement.js","utils/event/getListeners.js","utils/event/off.js","utils/event/at.js","utils/dom/matches.js","utils/dom/getParentOrHost.js","utils/event/on.js","utils/event/getTarget.js","utils/dom/resolveTextNode.js","utils/dom/closest.js","utils/types/isArray.js","utils/types/isDOM.js","utils/types/isHTMLCollection.js","utils/types/isFragment.js","utils/types/isTextNode.js","utils/dom/createElement.js","utils/dom/setAttribute.js","utils/lang/easeInQuad.js","utils/dom/_getScrollElement.js","utils/dom/hasClass.js","utils/dom/addClass.js","utils/dom/removeClass.js","utils/lang/trim.js","utils/dom/offsetTop.js","utils/dom/getStyle.js","utils/dom/setProperty.js","utils/lang/cloneDeep.js","chapters.js","_paintChapters.js","utils/dom/scrollTo.js","utils/dom/intersection.js","utils/event/stop.js"],"sourcesContent":["/**\n * 检测数据是否为 String 类型\n * ========================================================================\n * @method isArray\n * @param {*} str\n * @returns {boolean}\n */\nconst isString = (str) => {\n return typeof str === 'string'\n}\n\nexport default isString\n","/**\n * 检测对象自身属性中是否具有指定的属性。\n * ========================================================================\n * @method hasOwn\n * @param {Object} obj - (必须)检测的目标对象\n * @param {String} prop - (必须)属性名\n * @returns {Boolean}\n */\nconst hasOwn = (obj, prop) => {\n const hasOwnProperty = Object.prototype.hasOwnProperty\n return obj && hasOwnProperty.call(obj, prop)\n}\n\nexport default hasOwn\n","/**\n * Object 对象原型上的 toString 方法\n * ========================================================================\n * @method toString\n * @param {*} val\n * @returns {string}\n */\nconst toString = (val) => {\n return Object.prototype.toString.apply(val)\n}\n\nexport default toString\n","import toString from '../lang/toString'\n\n/**\n * 检测测试数据是否为 Function 类型\n * ========================================================================\n * @method isFunction\n * @param {*} val - (必须)待检测的数据\n * @returns {boolean} 'val' 是 Function 类型返回 true,否则返回 false\n */\nconst isFunction = (val) => {\n return typeof val === 'function' || toString(val) === '[object Function]'\n}\n\nexport default isFunction\n","import toString from '../lang/toString'\nimport isFunction from './isFunction'\n\n/**\n * 检测数据是否为 Object 类型\n * ========================================================================\n * @method isObject\n * @param {*} o\n * @returns {boolean}\n */\nconst isObject = (o) => {\n return (\n (toString(o) === '[object Object]' ||\n typeof o === 'object' ||\n isFunction(o)) &&\n o !== null\n )\n}\n\nexport default isObject\n","/**\n * 存储订阅者(主题和处理器的)私有对象\n * ========================================================================\n * @type {{}}\n * @private\n */\nconst _subscribers = {}\n\nexport default _subscribers\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 判断是否存在与给定 topic 完全匹配的订阅者信息\n * ========================================================================\n * @method _hasDirectSubscribersFor\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasDirectSubscribersFor = (topic) => {\n return hasOwn(_subscribers, topic) && _subscribers[topic].length > 0\n}\n\nexport default _hasDirectSubscribersFor\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\nimport _hasSubscribers from './_hasSubscribers'\n\n/**\n * 判断是否存在包含 topic 指定的订阅者信息\n * ========================================================================\n * @method has\n * @param {String} topic - (必须)主题名称\n * @param {Boolean} [isDirect] - (可选)是否为直接的主题,默认值:true\n * @returns {Boolean}\n */\nconst has = (topic, isDirect = true) => {\n return isDirect ? _hasDirectSubscribersFor(topic) : _hasSubscribers(topic)\n}\n\nexport default has\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * 判断是否存在包含给定 topic 相关的订阅者信息\n * ========================================================================\n * @method _hasSubscribers\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasSubscribers = (topic) => {\n let found = _hasDirectSubscribersFor(topic)\n let position = topic.lastIndexOf('.')\n\n while (!found && position !== -1) {\n topic = topic.substring(0, position)\n position = topic.lastIndexOf('.')\n found = _hasDirectSubscribersFor(topic)\n }\n\n return found\n}\n\nexport default _hasSubscribers\n","import isTypedArray from '../types/isTypedArray'\nimport _subscribers from './_subscribers'\nimport has from './has'\nimport _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * (异步)发布订阅主题信息\n * ========================================================================\n * 主题默认是异步发布的。确保在消费者处理主题时,主题的发起者不会被阻止。\n * ========================================================================\n * @method emit\n * @param {String} topic - (必须)主题名称\n * @param {Object} [data] - (可选)数据对象\n * @param {Boolean} [async] - (可选) 是否异步发布\n */\nconst emit = (topic, data, async = true) => {\n const execute = (topic) => {\n if (!_hasDirectSubscribersFor(topic)) {\n return false\n }\n\n _subscribers[topic].forEach((subscriber) => {\n // 针对 mqtt 消息服务返回的 Uint8Array 类似的 typed arrays 格式的数据\n // 采用 toString() 方法转化为普通(JSON)字符串\n const message = isTypedArray(data) ? data.toString() : data\n\n subscriber.callback.call(subscriber.context || subscriber, message)\n })\n }\n const deliver = () => {\n let subscriber = topic\n let position = topic.lastIndexOf('.')\n\n while (position !== -1) {\n subscriber = subscriber.substring(0, position)\n position = subscriber.lastIndexOf('.')\n\n execute(subscriber)\n }\n\n // 执行 topic 对应的处理器\n execute(topic)\n // 执行特殊 topic:'*'(监听全部消息的发布)\n execute('*')\n }\n\n if (!has(topic)) {\n return false\n }\n\n if (async) {\n setTimeout(deliver, 10)\n } else {\n deliver()\n }\n}\n\nexport default emit\n","import toString from '../lang/toString'\n/**\n * 判断检测数据是否为 Typed Arrays 类型的数据\n * ========================================================================\n * @param {*} val\n * @returns {boolean}\n */\nconst isTypedArray = (val) => {\n const TYPES = [\n '[object Int8Array]',\n '[object Uint8Array]',\n '[object Uint8ClampedArray]',\n '[object Int16Array]',\n '[object Uint16Array]',\n '[object Int32Array]',\n '[object Uint32Array]',\n '[object Float32Array]',\n '[object Float64Array]',\n '[object BigInt64Array]',\n '[object BigUint64Array]'\n ]\n\n return TYPES.indexOf(toString(val)) > -1\n}\n\nexport default isTypedArray\n","/**\n * 生成唯一 id 字符串的函数\n * ========================================================================\n * @method guid\n * @param {String} [prefix] - 生成 id 的前缀字符串\n * @return {String} 返回一个表示唯一 id 的字符串\n */\nconst guid = (() => {\n let uuid = 0\n\n return (prefix) => {\n uuid += 1\n\n return prefix ? prefix + '-' + uuid : 'guid-' + uuid\n }\n})()\n\nexport default guid\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 删除与给定 topic 相同的订阅者信息\n * ========================================================================\n * @method _removeSubscriber\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _removeSubscriber = (topic) => {\n if (!hasOwn(_subscribers, topic)) {\n return false\n }\n\n delete _subscribers[topic]\n}\n\nexport default _removeSubscriber\n","import has from './has'\nimport _removeSubscriber from './_removeSubscriber'\nimport _removeSubscriberByToken from './_removeSubscriberByToken'\n\n/**\n * 取消订阅主题\n * ========================================================================\n * @method off\n * @param {String} topic - (必须)订阅的主题\n * @param {Function|String} [token] - (可选)订阅主题的处理器函数或者唯一 Id 值\n */\nconst off = (topic, token) => {\n if (!has(topic)) {\n return false\n }\n\n if (token) {\n _removeSubscriberByToken(token)\n } else {\n _removeSubscriber(topic)\n }\n}\n\nexport default off\n","import _subscribers from './_subscribers'\nimport _removeSubscriber from './_removeSubscriber'\n\n/**\n * 通过订阅者 token 值删除订阅者信息\n * ========================================================================\n * @method _removeSubscriberByToken\n * @param {String} token - 订阅者 token 字符串\n * @returns {boolean}\n * @private\n */\nconst _removeSubscriberByToken = (token) => {\n const keys = Object.keys(_subscribers)\n let index = -1\n\n if (!token || keys.length < 1) {\n return false\n }\n\n keys.forEach((subject) => {\n const subscriber = _subscribers[subject]\n let topic\n\n subscriber.forEach((execution, j) => {\n if (execution.callback === token || execution.token === token) {\n topic = execution.topic\n subscriber.splice(index, j)\n }\n })\n\n /* istanbul ignore else */\n if (subscriber.length < 1) {\n _removeSubscriber(topic)\n }\n })\n}\n\nexport default _removeSubscriberByToken\n","import isString from './utils/types/isString'\r\nimport hasOwn from './utils/lang/hasOwn'\r\nimport isObject from './utils/types/isObject'\r\nimport extend from './utils/lang/extend'\r\nimport publish from './utils/observer/emit'\r\nimport subscribe from './utils/observer/on'\r\nimport unsubscribe from './utils/observer/off'\r\n\r\nclass Base {\r\n constructor(options) {\r\n this.attrs = {}\r\n\r\n if (options) {\r\n this.initialize(options)\r\n }\r\n }\r\n\r\n initialize(options) {\r\n this.attr(options).render().addListeners()\r\n return this\r\n }\r\n\r\n attr(prop, value) {\r\n const attrs = this.attrs\r\n\r\n if (isString(prop)) {\r\n // 只能扩展 attrs 中已有的属性\r\n if (value && hasOwn(attrs, prop)) {\r\n // 更新单个配置信息\r\n attrs[prop] = value\r\n return this\r\n }\r\n\r\n // 只传递 prop 参数,则返回对应的属性值\r\n return attrs[prop]\r\n } else if (isObject(prop)) {\r\n // 批量更新配置信息\r\n extend(attrs, prop)\r\n\r\n return this\r\n } else if (arguments.length === 0) {\r\n // 不传递参数,直接返回整个\r\n return attrs\r\n }\r\n\r\n return this\r\n }\r\n\r\n render() {\r\n return this\r\n }\r\n\r\n destroy() {\r\n this.removeListeners()\r\n return this\r\n }\r\n\r\n reload(options) {\r\n this.destroy().initialize(this.attr(options))\r\n return this\r\n }\r\n\r\n $emit(event, data) {\r\n publish(event, data)\r\n return this\r\n }\r\n\r\n $on(event, callback) {\r\n subscribe(event, callback, this)\r\n return this\r\n }\r\n\r\n $off(event, callback) {\r\n unsubscribe(event, callback)\r\n return this\r\n }\r\n\r\n addListeners() {\r\n return this\r\n }\r\n\r\n removeListeners() {\r\n return this\r\n }\r\n}\r\n\r\nexport default Base\r\n","import hasOwn from './hasOwn'\n\n/**\n * 扩展对象\n * ========================================================================\n * @method extend\n * @param {Object} origin\n * @param {Object} source\n */\nconst extend = (origin, source) => {\n const keys = Object.keys(source)\n\n keys.forEach((prop) => {\n if (hasOwn(source, prop)) {\n origin[prop] = source[prop]\n }\n })\n}\n\nexport default extend\n","import _subscribers from './_subscribers'\nimport isFunction from '../types/isFunction'\nimport guid from '../lang/guid'\n\n/**\n * 订阅主题,并给出处理器函数\n * ========================================================================\n * @method on\n * @param {String} topic - (必须)主题名称\n * @param {Function} handler - (必须)主题的处理器函数\n * @param {Object} [context] - (可选)指定 this 执行上下文\n * @return {String} - 唯一的 token 字符串,例如:'guid-1'。\n */\nconst on = (topic, handler, context = null) => {\n const token = guid()\n let subject = typeof topic === 'symbol' ? topic.toString() : topic\n\n if (!isFunction(handler)) {\n return ''\n }\n\n /* istanbul ignore else */\n if (!_subscribers[subject]) {\n _subscribers[subject] = []\n }\n\n _subscribers[subject].push({\n topic: subject,\n callback: handler,\n context,\n token\n })\n\n return token\n}\n\nexport default on\n","import isObject from './isObject'\n\n/**\n * 检测数据是否为 HTMLElement DOM 节点\n * ========================================================================\n * @method isElement\n * @param {*} o\n * @returns {boolean}\n */\nconst isElement = (o) => {\n return !!(isObject(o) && o.nodeName && o.tagName && o.nodeType === 1)\n}\n\nexport default isElement\n","import isFunction from '../types/isFunction'\n\n/**\n * later - 延迟执行方法\n * ========================================================================\n * @method later\n * @param {Function} fn\n * @param {Number} [delay]\n * @returns {number|boolean}\n */\nconst later = (fn, delay = 300) => {\n if (!isFunction(fn)) {\n return false\n }\n\n return setTimeout(() => {\n fn()\n }, delay)\n}\n\nexport default later\n","export const CAPTURE_EVENTS = [\n 'focusout',\n 'blur',\n 'focusin',\n 'focus',\n 'load',\n 'unload',\n 'mouseenter',\n 'mouseleave'\n]\n","import { CAPTURE_EVENTS } from './enum'\nimport _delete from './_delete'\n\n/**\n * (私有方法)取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method _off\n * @param {HTMLElement} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} fn - (必须)事件处理器回调函数\n * @private\n */\nconst _off = (el, type, fn) => {\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n /* istanbul ignore else */\n if (fn._delegateListener) {\n fn = fn._delegateListener\n delete fn._delegateListener\n }\n\n // 移除缓存的 _listeners 数据\n _delete(el, type, fn)\n\n el.removeEventListener(type, fn, capture)\n}\n\nexport default _off\n","/**\n * 删除 DOM 元素缓存的 _listeners 数据\n * ========================================================================\n * @method _delete\n * @param {HTMLElement} el - 要删除 listener 的 DOM 元素\n * @param {String} type - 事件类型(名称)\n * @param {Function} [fn] - 事件处理器回调函数\n */\nconst _delete = function (el, type, fn) {\n const listeners = el._listeners\n let index = -1\n\n if (listeners.length < 1) {\n return false\n }\n\n // 移除缓存的 _listeners 数据\n listeners.forEach((listener, i) => {\n const handler = listener.fn\n\n if (type === listener.type) {\n index = i\n\n if (handler === fn) {\n index = i\n }\n }\n })\n\n /* istanbul ignore else */\n if (index > -1) {\n listeners.splice(index, 1)\n }\n}\n\nexport default _delete\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\nimport getListeners from './getListeners'\nimport _off from './_off'\n\n/**\n * 销毁(type 类型的)代理事件绑定\n * ========================================================================\n * 1. 设置了事件类型 type,则销毁指定类型的事件绑定,否则清除所有代理事件绑定\n * 2. recurse 设置为 true,递归销毁子节点全部事件绑定\n * ========================================================================\n * @method purgeElement\n * @param {HTMLElement|String} el - (必须)DOM 元素或者其选择器\n * @param {String|Boolean} type - (必须)事件类型\n * @param {Boolean} [recurse] - (可选)是否递归销毁子节点所有事件绑定\n */\nconst purgeElement = function (el, type, recurse = false) {\n const $element = isString(el) ? document.querySelector(el) : el\n const $children = $element.childNodes\n const listeners = getListeners($element, type)\n\n listeners.forEach((listener) => {\n _off($element, listener.type, listener.fn)\n })\n\n if (\n (recurse || type === true || arguments.length === 1) &&\n $element &&\n $children\n ) {\n $children.forEach(($child) => {\n if (isElement($child)) {\n purgeElement($child, type, recurse)\n }\n })\n }\n}\n\nexport default purgeElement\n","import isString from '../types/isString'\n\n/**\n * 获取 DOM 元素(type 事件类型)事件绑定信息\n * ========================================================================\n * 如果设置了事件类型 type, 则返回指定类型的事件绑定信息,否则返回所有事件绑定信息\n * ========================================================================\n * @methods getListeners\n * @param {HTMLElement} el - (必须)要获取事件绑定信息的 DOM 元素\n * @param {String} [type] - (可选)事件类型\n * @returns {Array} - 已绑定的事件信息\n */\nconst getListeners = (el, type) => {\n let listeners = el._listeners || []\n\n if (isString(type) && type) {\n listeners = listeners.filter((listener) => {\n return listener.type === type\n })\n }\n\n return listeners\n}\n\nexport default getListeners\n","import purgeElement from './purgeElement'\nimport isFunction from '../types/isFunction'\nimport _off from './_off'\n\n/**\n * 取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method off\n * @param {HTMLElement|Object} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} [fn] - (可选)事件处理器回调函数\n */\nconst off = (el, type, fn) => {\n // 如果不设置 fn 参数,默认清除 el 元素上绑定的所有事件处理器\n if (!isFunction(fn)) {\n return purgeElement(el, type)\n }\n\n _off(el, type, fn)\n}\n\nexport default off\n","import isFunction from '../types/isFunction'\nimport off from './off'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定事件\n * ========================================================================\n * @method at\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (必须) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst at = (el, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n const listener = function (evt) {\n let overrideContext = context || el\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n\n if (!isFunction(fn)) {\n return false\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default at\n","/**\n * 获取 options 节点下匹配 selector 选择器的 DOM 节点\n * ========================================================================\n * Element.matches() 方法可以用来判断 DOM 元素是否与给定的选择器匹配,事件代理判断是\n * 否触发绑定的代理事件回调函数,关键就是使用 Element.matches() 辨别当前事件触发的目\n * 标 DOM 元素是否为事件代理所期望触发的目标。\n * ========================================================================\n * @method matches\n * @see https://developer.mozilla.org/en-US/docs/web/api/element/matches\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)匹配 DOM 元素的选择器\n * @returns {Boolean}\n */\nconst matches = (el, selector = '') => {\n const sel = selector.replace(/^>/i, '')\n\n if (!selector || !sel || !el) {\n return false\n }\n\n /* istanbul ignore else */\n if (el.matches) {\n return el.matches(sel)\n } else if (el.msMatchesSelector) {\n return el.msMatchesSelector(sel)\n } else {\n return false\n }\n}\n\nexport default matches\n","/**\n * 获取 DOM 元素的父节点\n * ========================================================================\n * @method getParentOrHost\n * @param {*|HTMLElement} el - (必须)要获取父节点的 DOM 元素\n * @returns {*|HTMLElement}\n */\nconst getParentOrHost = (el) => {\n return el.host && el !== document && el.host.nodeType\n ? el.host\n : el.parentNode\n}\n\nexport default getParentOrHost\n","import closest from '../dom/closest'\nimport off from './off'\nimport getTarget from './getTarget'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定代理事件\n * ========================================================================\n * @method on\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String} selector - (必须)事件代理目标 DOM 元素的选择器\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (可选) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst on = (el, selector, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n const listener = function (evt) {\n const target = getTarget(evt)\n // 通过 Element.matches 方法获得点击的目标元素\n const delegateTarget = closest(target, selector, el)\n let overrideContext = context || el\n\n evt.delegateTarget = delegateTarget\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n /* istanbul ignore else */\n if (delegateTarget) {\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n selector,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default on\n","import resolveTextNode from '../dom/resolveTextNode'\n\n/**\n * 返回触发事件的 target DOM 元素\n * ========================================================================\n * @method getTarget\n * @param {Event} evt - Event 对象\n * @return {HTMLElement} - Event 对象的 target DOM 元素\n */\nconst getTarget = function (evt) {\n const target = evt.target\n\n return resolveTextNode(target)\n}\n\nexport default getTarget\n","/**\n * 在某些情况下,某些浏览器(例如:Safari 浏览器)会返回实际的目标元素内部的文本节点。\n * resolveTextNode() 方法则会返回实际的目标节点。\n * ========================================================================\n * @method resolveTextNode\n * @param {HTMLElement|Text} el - 要解析的节点\n * @return {*|HTMLElement} - 实际的目标 DOM 节点\n */\nconst resolveTextNode = function (el) {\n if (el && el.nodeType === 3) {\n return el.parentNode\n }\n\n return el\n}\n\nexport default resolveTextNode\n","import matches from './matches'\nimport getParentOrHost from './getParentOrHost'\n\n/**\n * 获取 options 元素父元素最近的包含 selector 选择器的元素\n * ========================================================================\n * @method closest\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)DOM 元素的选择其\n * @param {HTMLElement} [ctx] - (必须)比对的 DOM 元素\n * @param {Boolean} [includeCTX] - (必须)是否包含 context DOM 元素\n * @returns {null|HTMLElement} - 返回最接近的 DOM 元素\n */\nconst closest = (el, selector, ctx, includeCTX) => {\n const context = ctx || document\n\n if (!el) {\n return null\n }\n\n do {\n /* istanbul ignore else */\n if (\n (selector != null &&\n (selector.startsWith('>')\n ? el.parentNode === context && matches(el, selector)\n : matches(el, selector))) ||\n (includeCTX && el === context)\n ) {\n return el\n }\n\n /* istanbul ignore else */\n if (el === context) {\n break\n }\n\n /* jshint boss:true */\n } while ((el = getParentOrHost(el)))\n}\n\nexport default closest\n","import toString from '../lang/toString'\n\n/**\n * 检测数据是否为 Array 类型\n * ========================================================================\n * @method isArray\n * @param {*} o\n * @returns {boolean}\n */\nconst isArray = (o) => {\n if (Array.isArray) {\n return Array.isArray(o)\n } else {\n return toString(o) === '[object Array]'\n }\n}\n\nexport default isArray\n","import isObject from './isObject'\r\nimport isElement from './isElement'\r\nimport isHTMLCollection from './isHTMLCollection'\r\nimport isFragment from './isFragment'\r\nimport isTextNode from './isTextNode'\r\n\r\nconst isDOM = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (isElement(el) || isHTMLCollection(el) || isFragment(el) || isTextNode(el))\r\n )\r\n}\r\n\r\nexport default isDOM\r\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isHTMLCollection = (el) => {\r\n return !!(isObject(el) && toString(el) === '[object NodeList]')\r\n}\r\n\r\nexport default isHTMLCollection\r\n","import toString from '../lang/toString'\nimport isObject from './isObject'\n\nconst isFragment = (fragment) => {\n return !!(\n isObject(fragment) && toString(fragment) === '[object DocumentFragment]'\n )\n}\n\nexport default isFragment\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isTextNode = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (toString(el) === '[object Text]' || (el.tagName && el.nodeType === 3))\r\n )\r\n}\r\n\r\nexport default isTextNode\r\n","import hasOwn from '../lang/hasOwn'\nimport isObject from '../types/isObject'\nimport isString from '../types/isString'\nimport isArray from '../types/isArray'\nimport isDOM from '../types/isDOM'\nimport setAttribute from './setAttribute'\n\n/**\n * 创建 DOM 节点,并添加属性和子节点\n * ========================================================================\n * @method createElement\n * @param {String} tagName - 标签名称\n * @param {Object|Array} attrs - 属性对象或者子节点\n * @param {Array} [children] - 子节点数组\n * @returns {HTMLElement}\n */\nconst createElement = (tagName, attrs, children) => {\n const $fragment = document.createDocumentFragment()\n const $el = document.createElement(tagName)\n const isValidChild = (child) => {\n return isDOM(child) || isString(child)\n }\n const append = (child) => {\n let $child\n\n if (!isValidChild(child)) {\n return false\n }\n\n if (isDOM(child)) {\n $child = child\n } else if (isString(child)) {\n $child = document.createTextNode(child)\n }\n\n $fragment.appendChild($child)\n }\n\n if (isObject(attrs)) {\n Object.keys(attrs).forEach((attr) => {\n if (hasOwn(attrs, attr)) {\n setAttribute($el, attr, attrs[attr])\n }\n })\n } else if (isArray(attrs) && attrs.every((attr) => isValidChild(attr))) {\n attrs.forEach((child) => {\n append(child)\n })\n }\n\n if (isArray(children)) {\n children.forEach((child) => {\n append(child)\n })\n } else {\n append(children)\n }\n\n $el.appendChild($fragment)\n\n return $el\n}\n\nexport default createElement\n","/**\n * 给 DOM 节点设置属性/值\n * ========================================================================\n * @method setAttribute\n * @param {HTMLElement} el - DOM 节点\n * @param {String} attr - 属性名称\n * @param {String|Number|Boolean} value - 属性值\n */\nconst setAttribute = (el, attr, value) => {\n let tagName = el.tagName.toLowerCase()\n\n switch (attr) {\n case 'style':\n el.style.cssText = value\n break\n case 'value':\n if (tagName === 'input' || tagName === 'textarea') {\n el.value = value\n } else {\n el.setAttribute(attr, value)\n }\n break\n case 'className':\n el.className = value\n break\n default:\n el.setAttribute(attr, value)\n break\n }\n}\n\nexport default setAttribute\n","/**\n * 返回给定值的平方值\n * ========================================================================\n * @method easeInQuad\n * @param {Number} x\n * @returns {number}\n */\nconst easeInQuad = (x) => {\n return x * x\n}\n\nexport default easeInQuad\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\n\n/**\n * 通过给的 scrollElement 参数,获取滚动 DOM 元素\n * ========================================================================\n * @method _getScrollElement\n * @param {String|HTMLElement} scrollElement\n * @returns {Element}\n * @private\n */\nconst _getScrollElement = (scrollElement = null) => {\n let $rootElements\n let $scrollElement\n\n if (!scrollElement) {\n $rootElements = document.querySelectorAll('html,body')\n $scrollElement =\n $rootElements[0].scrollTop - $rootElements[1].scrollTop >= 0\n ? $rootElements[0]\n : $rootElements[1]\n } else {\n if (isString(scrollElement)) {\n $scrollElement = document.querySelector(scrollElement)\n } else if (isElement(scrollElement)) {\n $scrollElement = scrollElement\n }\n }\n\n return $scrollElement\n}\n\nexport default _getScrollElement\n","import isElement from '../types/isElement'\n/**\n * 检测 DOM 节点是否包含名为 className 的样式\n * ========================================================================\n * @method hasClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst hasClass = (el, className) => {\n const pattern = new RegExp('(\\\\s|^)' + className + '(\\\\s|$)')\n let allClass\n let classList\n\n if (!isElement(el)) {\n return false\n }\n\n allClass = el.className\n\n if (!allClass) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.contains) {\n return el.classList.contains(className)\n }\n\n return !!pattern.exec(allClass)\n}\n\nexport default hasClass\n","import hasClass from './hasClass'\n\n/**\n * 给 DOM 节点添加名为 className 的样式\n * ========================================================================\n * @method addClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst addClass = (el, className) => {\n let classList\n let allClass\n\n if (hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.add) {\n classList.add(className)\n } else {\n allClass = el.className\n allClass += allClass.length > 0 ? ' ' + className : className\n el.className = allClass\n }\n}\n\nexport default addClass\n","import trim from '../lang/trim'\nimport hasClass from './hasClass'\n\n/**\n * 移除 DOM 节点的 className 样式\n * ========================================================================\n * @method removeClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst removeClass = (el, className) => {\n let allClass = el.className\n let classList\n\n if (!allClass || !hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.remove) {\n classList.remove(className)\n } else {\n allClass = trim(allClass.replace(className, ''))\n el.className = allClass\n }\n}\n\nexport default removeClass\n","import isString from '../types/isString'\n\n/**\n * 清楚字符串起始位置所有的空格\n * ========================================================================\n * @method trim\n * @param {string} str\n * @returns {string|Boolean}\n */\nconst trim = (str) => {\n if (!isString(str)) {\n return false\n }\n return str.replace(/(^\\s+)|(\\s+$)/g, '')\n}\n\nexport default trim\n","/**\n * 获取 DOM 节点相对于窗口的 left (纵坐标)值\n * ========================================================================\n * @method offsetTop\n * @param {HTMLElement} el - DOM 节点\n * @returns {Number}\n */\nconst offsetTop = (el) => {\n let top = el.offsetTop\n\n if (el.offsetParent !== null) {\n top += offsetTop(el.offsetParent)\n }\n\n return top\n}\n\nexport default offsetTop\n","/**\r\n * 获取HTML元素的某个CSS样式值\r\n * ====================================================\r\n * @param el\r\n * @param ruleName\r\n * @returns {*}\r\n */\r\nconst getStyle = (el, ruleName) => {\r\n return getComputedStyle(el)[ruleName]\r\n}\r\n\r\nexport default getStyle\r\n","const setProperty = (prop, value) => {\r\n const documentElement = document.documentElement\r\n documentElement.style.setProperty(prop, value)\r\n}\r\n\r\nexport default setProperty\r\n","import isArray from '../types/isArray'\r\n\r\n/**\r\n * 深拷贝对象函数\r\n * ========================================================================\r\n * @methods cloneDeep\r\n * @param {Object} obj - 深拷贝的对象\r\n * @returns {Array|Object|*}\r\n *\r\n * @example\r\n * const arr = cloneDeep([2,3,4,6])\r\n * => [2,3,4,6]\r\n */\r\nconst cloneDeep = (obj) => {\r\n let clone\r\n\r\n if (obj === null) {\r\n return null\r\n }\r\n\r\n clone = Object.assign({}, obj)\r\n\r\n Object.keys(clone).forEach((key) => {\r\n return (clone[key] =\r\n typeof obj[key] === 'object' ? cloneDeep(obj[key]) : obj[key])\r\n })\r\n\r\n if (isArray(obj)) {\r\n clone.length = obj.length\r\n\r\n return Array.from(clone)\r\n }\r\n\r\n return clone\r\n}\r\n\r\nexport default cloneDeep\r\n","import Base from './base'\n\nimport isString from './utils/types/isString'\nimport isFunction from './utils/types/isFunction'\nimport isElement from './utils/types/isElement'\nimport later from './utils/lang/later'\nimport at from './utils/event/at'\nimport on from './utils/event/on'\nimport off from './utils/event/off'\nimport stop from './utils/event/stop'\nimport createElement from './utils/dom/createElement'\nimport scrollTo from './utils/dom/scrollTo'\nimport addClass from './utils/dom/addClass'\nimport intersection from './utils/dom/intersection'\nimport removeClass from './utils/dom/removeClass'\nimport offsetTop from './utils/dom/offsetTop'\nimport getStyle from './utils/dom/getStyle'\nimport setProperty from './utils/dom/setProperty'\nimport publish from './utils/observer/emit'\nimport cloneDeep from './utils/lang/cloneDeep'\n\nimport _getScrollElement from './utils/dom/_getScrollElement'\nimport _paintChapters from './_paintChapters'\n\nclass Chapters extends Base {\n constructor(options) {\n super()\n\n this.attrs = cloneDeep(Chapters.DEFAULTS)\n this.$el = null\n this.$title = null\n this.$main = null\n this.$list = null\n this.$placeholder = null\n this.$parentElement = null\n this.$scrollElement = null\n this.chapters = []\n this.closed = false\n this.active = 0\n this.offsetTop = 0\n this.offsetWidth = 0\n this.$active = null\n this.scrollTimer = null\n this.resizeTimer = null\n this.playing = false\n this.Observer = null\n\n if (options) {\n this.initialize(options)\n }\n }\n\n initialize(options) {\n let created\n let parentElement\n let scrollElement\n let $parent\n\n this.attr(options)\n created = this.attr('created')\n parentElement = this.attr('parentElement')\n scrollElement = this.attr('scrollElement')\n\n if (isString(parentElement)) {\n $parent = document.querySelector(parentElement)\n } else if (isElement(parentElement)) {\n $parent = parentElement\n }\n this.$parentElement = $parent\n this.$scrollElement = _getScrollElement(scrollElement)\n\n this.chapters = this.attr('chapters')\n this.closed = this.attr('closed')\n this.active = this.attr('active')\n\n if (isFunction(created)) {\n created.call(this)\n }\n\n if (this.chapters.length < 1) {\n return this\n }\n\n this.render().addListeners()\n\n this.$active = document.querySelector(`#chapter-${this.active}`)\n\n return this\n }\n\n isClosed() {\n return this.closed\n }\n\n isSticky() {\n const position = this.attr('position')\n return position === 'sticky'\n }\n\n isFixed() {\n const position = this.attr('position')\n return position === 'fixed'\n }\n\n isInside() {\n return this.isFixed() || this.isSticky()\n }\n\n isOutside() {\n return !this.isInside()\n }\n\n _paintEdge() {\n const $fragment = document.createDocumentFragment()\n const STICKY = 'outline-chapters_sticky'\n const HIDDEN = 'outline-chapters_hidden'\n const title = this.attr('title')\n const customClass = this.attr('customClass')\n const $parentElement = this.$parentElement\n const contents = []\n let $title = null\n let $el\n let $main\n let $list\n let $placeholder\n\n if (!$parentElement) {\n return this\n }\n\n if (this.isInside() && title) {\n $title = createElement(\n 'h2',\n {\n className: 'outline-chapters__title'\n },\n [title]\n )\n this.$title = $title\n contents.push($title)\n }\n\n $list = createElement(\n 'ul',\n {\n // 为优化性能,添加了 _fixed 和 _hidden\n // fixed 为了让 $list 脱离流布局\n // hidden 让 $list 不可见\n className: `outline-chapters__list`\n },\n ['']\n )\n this.$list = $list\n\n $placeholder = createElement(\n 'div',\n {\n className: 'outline-chapters__placeholder'\n },\n ['']\n )\n this.$placeholder = $placeholder\n\n $main = createElement(\n 'div',\n {\n className: 'outline-chapters__main'\n },\n [$list, $placeholder]\n )\n this.$main = $main\n contents.push($main)\n\n $el = createElement(\n 'nav',\n {\n id: 'outline-chapters',\n className: `outline-chapters ${HIDDEN}`\n },\n contents\n )\n this.$el = $el\n\n if (this.isSticky()) {\n this.calculateStickyHeight()\n addClass($el, STICKY)\n }\n\n if (customClass) {\n addClass($el, customClass)\n }\n $fragment.appendChild($el)\n $parentElement.appendChild($fragment)\n\n return this\n }\n\n render() {\n const HIDDEN = 'outline-chapters_hidden'\n const showCode = this.attr('showCode')\n const mounted = this.attr('mounted')\n const $parentElement = this.$parentElement\n const chapters = this.chapters\n let $el\n let $list\n\n if (!$parentElement || chapters.length < 1) {\n return this\n }\n\n this._paintEdge()\n\n $el = this.$el\n $list = this.$list\n _paintChapters($list, chapters, showCode)\n removeClass($el, HIDDEN)\n this.positionPlaceholder(this.active)\n\n this.offsetTop = offsetTop($el)\n this.offsetWidth = $el.offsetWidth\n\n if (this.isFixed()) {\n this.sticky()\n setProperty('--outline-chapters-width', `${this.offsetWidth}px`)\n }\n\n if (isFunction(mounted)) {\n mounted.call(this)\n }\n\n this.onObserver()\n\n return this\n }\n\n positionPlaceholder(index) {\n const $main = this.$main\n const $list = this.$list\n const $placeholder = this.$placeholder\n const $anchor = $list.querySelector('.outline-chapters__anchor')\n const mainPaddingTop = parseInt(getStyle($main, 'padding-top'), 10)\n const mainBorderTop = parseInt(getStyle($main, 'border-top-width'), 10)\n const placeholderPaddingTop = parseInt(getStyle($list, 'padding-top'), 10)\n const placeholderMarginTop = parseInt(getStyle($list, 'margin-top'), 10)\n const placeholderBorderTop = parseInt(\n getStyle($list, 'border-top-width'),\n 10\n )\n let height = $anchor.offsetHeight\n let offsetTop = 0\n let top\n\n if (mainPaddingTop) {\n offsetTop += mainPaddingTop\n }\n\n if (placeholderPaddingTop) {\n offsetTop += placeholderPaddingTop\n }\n\n if (placeholderMarginTop) {\n offsetTop += placeholderMarginTop\n }\n\n if (mainBorderTop) {\n offsetTop += mainBorderTop\n }\n\n if (placeholderBorderTop) {\n offsetTop += placeholderBorderTop\n }\n\n top = height * index\n // top:calc(${offsetTop}px + ${top}px);\n $placeholder.style.cssText = `transform: translateY(${\n offsetTop + top\n }px);height:${height}px;`\n\n return this\n }\n\n highlight(id) {\n const $anchor = this.$el.querySelector(`#chapter__anchor-${id}`)\n const HIGHLIGHT = 'outline-chapters_active'\n\n if (!$anchor) {\n return this\n }\n\n if (this.$active) {\n removeClass(this.$active, HIGHLIGHT)\n }\n\n this.active = parseInt($anchor.getAttribute('data-id'), 10)\n this.$active = $anchor\n addClass(this.$active, HIGHLIGHT)\n\n this.positionPlaceholder(this.active)\n\n return this\n }\n\n sticky() {\n const afterSticky = this.attr('afterSticky')\n const FIXED = 'outline-chapters_fixed'\n const $el = this.$el\n const top = this.offsetTop\n const scrollTop = this.$scrollElement.scrollTop\n let isStickying\n\n if (!this.isFixed()) {\n return this\n }\n\n isStickying = scrollTop >= top\n\n if (isStickying) {\n addClass($el, FIXED)\n } else {\n removeClass($el, FIXED)\n }\n\n if (isFunction(afterSticky)) {\n afterSticky.call(this, this.isClosed(), isStickying)\n }\n\n return this\n }\n\n calculateStickyHeight() {\n const documentElement = document.documentElement\n const height = Math.max(\n documentElement.clientHeight || 0,\n window.innerHeight || 0\n )\n setProperty('--outline-sticky-height', `${height}px`)\n return this\n }\n\n scrollTo(top, after) {\n const el = this.$scrollElement\n\n scrollTo(el, top, after)\n\n return this\n }\n\n show() {\n const FOLDED = 'outline-chapters_folded'\n const HIDDEN = 'outline-chapters_hidden'\n const opened = this.attr('afterOpened')\n const $el = this.$el\n const $parent = this.$parentElement\n\n if (this.isInside()) {\n removeClass($parent, HIDDEN)\n removeClass($el, HIDDEN)\n later(() => {\n removeClass($parent, FOLDED)\n removeClass($el, FOLDED)\n }, 30)\n } else {\n removeClass($el, HIDDEN)\n }\n this.closed = false\n\n if (isFunction(opened)) {\n opened.call(this)\n }\n\n return this\n }\n\n hide() {\n const FOLDED = 'outline-chapters_folded'\n const HIDDEN = 'outline-chapters_hidden'\n const closed = this.attr('afterClosed')\n const $el = this.$el\n const $parent = this.$parentElement\n\n if (this.isInside()) {\n addClass($parent, FOLDED)\n addClass($el, FOLDED)\n later(() => {\n addClass($parent, HIDDEN)\n addClass($el, HIDDEN)\n })\n } else {\n addClass($el, HIDDEN)\n }\n this.closed = true\n\n if (isFunction(closed)) {\n closed.call(this)\n }\n\n return this\n }\n\n toggle() {\n const afterToggle = this.attr('afterToggle')\n const top = this.offsetTop\n const scrollTop = this.$scrollElement.scrollTop\n let isStickying\n\n if (this.isClosed()) {\n this.show()\n } else {\n this.hide()\n }\n\n if (isFunction(afterToggle)) {\n later(() => {\n isStickying = scrollTop >= top\n afterToggle.call(this, this.isClosed(), isStickying)\n })\n }\n\n return this\n }\n\n destroy() {\n const beforeDestroy = this.attr('beforeDestroy')\n const afterDestroy = this.attr('afterDestroy')\n\n if (isFunction(beforeDestroy)) {\n beforeDestroy.call(this)\n }\n\n this.removeListeners()\n this.$parentElement.removeChild(this.$el)\n\n this.attr(Chapters.DEFAULTS)\n this.$el = null\n this.$title = null\n this.$main = null\n this.$list = null\n this.$placeholder = null\n this.$parentElement = null\n this.$scrollElement = null\n this.chapters = []\n this.active = 0\n this.offsetTop = 0\n this.$active = null\n this.closed = false\n\n if (this.scrollTimer) {\n clearTimeout(this.scrollTimer)\n this.scrollTimer = null\n }\n\n if (this.resizeTimer) {\n clearTimeout(this.resizeTimer)\n this.resizeTimer = null\n }\n\n if (isFunction(afterDestroy)) {\n afterDestroy.call(this)\n }\n\n if (this.Observer) {\n this.Observer = null\n }\n\n return this\n }\n\n onObserver() {\n const selector = this.attr('selector')\n let timer = null\n\n this.Observer = intersection(\n ($heading) => {\n const id = $heading.getAttribute('data-id')\n\n if (this.playing) {\n return false\n }\n\n if (timer) {\n clearTimeout(timer)\n }\n\n timer = later(() => {\n this.highlight(id)\n }, 100)\n },\n {\n selector,\n context: this\n }\n )\n\n return this\n }\n\n onSelect(evt) {\n const stickyHeight = this.attr('stickyHeight')\n const $anchor = evt.delegateTarget\n const id = $anchor.getAttribute('data-id')\n const headingId = $anchor.href.split('#')[1]\n const $heading = document.querySelector(`#${headingId}`)\n const top = offsetTop($heading) - (stickyHeight + 10)\n const min = 0\n const max = this.$scrollElement.scrollHeight\n const afterScroll = this.attr('afterScroll')\n const after = () => {\n if (isFunction(afterScroll)) {\n afterScroll.call(this, 'chapter')\n }\n\n later(() => {\n this.playing = false\n publish('toolbar:update', {\n top,\n min,\n max\n })\n })\n }\n\n this.playing = true\n if (this.isFixed()) {\n this.sticky()\n later(() => {\n this.scrollTo(top, after)\n this.highlight(id)\n }, 10)\n } else {\n this.scrollTo(top, after)\n this.highlight(id)\n }\n\n stop(evt)\n\n return this\n }\n\n onScroll() {\n const $scrollElement = this.$scrollElement\n\n if (this.scrollTimer) {\n clearTimeout(this.scrollTimer)\n }\n\n this.scrollTimer = later(() => {\n const top = $scrollElement.scrollTop\n const min = 0\n const max = $scrollElement.scrollHeight - $scrollElement.clientHeight\n\n if (this.isFixed()) {\n this.sticky()\n }\n\n publish('toolbar:update', {\n top,\n min,\n max\n })\n }, 100)\n\n return this\n }\n\n onResize() {\n if (this.resizeTimer) {\n clearTimeout(this.resizeTimer)\n }\n\n this.resizeTimer = later(() => {\n this.calculateStickyHeight()\n })\n\n return this\n }\n\n addListeners() {\n const $el = this.$el\n const $scrollElement = this.$scrollElement\n const tagName = $scrollElement.tagName.toLowerCase()\n let $element = $scrollElement\n\n if (tagName === 'html' || tagName === 'body') {\n $element = window\n }\n\n on($el, '.outline-chapters__anchor', 'click', this.onSelect, this, true)\n at($element, 'scroll', this.onScroll, this, true)\n if (this.isSticky()) {\n at($element, 'resize', this.onResize, this, true)\n }\n\n return this\n }\n\n removeListeners() {\n const selector = this.attr('selector')\n const $el = this.$el\n const $scrollElement = this.$scrollElement\n const tagName = $scrollElement.tagName.toLowerCase()\n let $element = $scrollElement\n\n if (tagName === 'html' || tagName === 'body') {\n $element = window\n }\n\n off($el, 'click', this.onSelect)\n off($element, 'scroll', this.onScroll)\n\n if (this.isSticky()) {\n at($element, 'resize', this.onResize)\n }\n\n if (this.Observer) {\n document.querySelectorAll(selector).forEach((section) => {\n this.Observer.unobserve(section)\n })\n }\n\n return this\n }\n}\n\nChapters.DEFAULTS = {\n parentElement: '',\n scrollElement: '',\n selector: '.outline-heading',\n active: 0,\n closed: false,\n showCode: true,\n position: 'relative',\n stickyHeight: 0,\n chapters: [],\n created: null,\n mounted: null,\n afterClosed: null,\n afterOpened: null,\n afterScroll: null,\n beforeDestroy: null,\n afterDestroy: null,\n afterSticky: null\n}\n\nexport default Chapters\n","import createElement from './utils/dom/createElement'\n\nconst _paintChapters = ($list, chapters, showCode = false) => {\n const byId = (id) => document.querySelector(`#${id}`)\n\n chapters.forEach((chapter) => {\n const pid = chapter.pid\n const id = chapter.id\n const rel = chapter.rel\n const $text = createElement(\n 'span',\n {\n className: 'outline-chapters__text'\n },\n [chapter.text]\n )\n const $link = createElement(\n 'a',\n {\n id: `chapter__anchor-${id}`,\n className: 'outline-chapters__anchor',\n href: '#' + rel,\n rel: rel,\n 'data-id': id\n },\n [$text]\n )\n let $code\n let $li\n let $ul\n let $parent\n\n if (showCode) {\n $code = createElement(\n 'span',\n {\n className: 'outline-chapters__code',\n 'data-id': id\n },\n [chapter.code]\n )\n\n $link.insertBefore($code, $link.firstChild)\n }\n\n $li = createElement(\n 'li',\n {\n id: `chapter-${id}`,\n className: 'outline-chapters__item',\n 'data-id': id\n },\n [$link]\n )\n\n if (pid === -1) {\n $list.appendChild($li)\n } else {\n $parent = byId(`chapter-${pid}`)\n $ul = byId(`subject-${pid}`)\n\n if (!$ul) {\n $ul = createElement(\n 'ul',\n {\n id: 'subject-' + pid,\n className: 'outline-chapters__subject'\n },\n [$li]\n )\n\n $parent.appendChild($ul)\n } else {\n $ul.appendChild($li)\n }\n }\n })\n}\n\nexport default _paintChapters\n","import easeInQuad from '../lang/easeInQuad'\nimport isFunction from '../types/isFunction'\nimport _getScrollElement from './_getScrollElement'\n\n/**\n * 指定 rootElement DOM 节点滚动到指定 top 位置\n * ========================================================================\n * @method scrollTo\n * @param {HTMLElement|Object} [scrollElement] - (必须)要滚动的 DOM 节点\n * @param {Number} top - (必须)滚动的 scrollTop 数值\n * @param {Function} [afterStop] - (可选)滚动完成的回调函数\n */\nconst scrollTo = (scrollElement, top, afterStop) => {\n const $scrollElement = _getScrollElement(scrollElement)\n let scrollTop = $scrollElement.scrollTop\n let step = 0\n const distance = top - scrollTop\n const MAX_HEIGHT = $scrollElement.scrollHeight\n const MAX_TOP = top - MAX_HEIGHT <= 0 ? top : MAX_HEIGHT\n const stop = (top) => {\n if (isFunction(afterStop)) {\n afterStop(top)\n }\n\n return false\n }\n const play = () => {\n step += 1\n\n // 向上滚动\n if (distance < 0) {\n scrollTop -= easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop <= top) {\n $scrollElement.scrollTop = top\n return stop(top)\n }\n } else {\n scrollTop += easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop >= MAX_TOP) {\n $scrollElement.scrollTop = MAX_TOP\n return stop(MAX_TOP)\n }\n }\n\n requestAnimationFrame(play)\n }\n\n requestAnimationFrame(play)\n}\n\nexport default scrollTo\n","import isFunction from '../types/isFunction'\nimport isElement from '../types/isElement'\n\n/**\n * 通用的 IntersectionObserver 观察者处理器\n * ========================================================================\n * @method intersection\n * @param {Function} fn\n * @param {Object} [props]\n * @param {Object|HTMLElement} [props.root]\n * @param {String} [props.selector]\n * @param {Object} [props.context]\n * @param {String} [props.attr]\n * @param {String} [props.rootMargin]\n */\nconst intersection = (fn, props = {}) => {\n const root = props.root || null\n const selector = props.selector || '.outline-heading'\n const context = props.context || null\n const rootMargin = props.rootMargin || '0px 0px -90% 0px'\n const options = {\n rootMargin: rootMargin\n }\n const Observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.intersectionRatio > 0) {\n if (isFunction(fn)) {\n fn.call(context || entry.target, entry.target)\n }\n }\n })\n }, options)\n const $root = isElement(root) ? root : document\n\n if (root) {\n options.root = root\n }\n\n $root.querySelectorAll(selector).forEach((section) => {\n Observer.observe(section)\n })\n\n return Observer\n}\n\nexport default intersection\n","/**\n * 停止事件(阻止默认行为和阻止事件的捕获或冒泡)\n * ========================================================================\n * @method stop\n * @param {Event} evt - 事件对象\n *\n * @example\n *
\n * Service\n * Help\n *
\n *\n * const $nav = document.querySelector('#nav')\n * const $service = document.querySelector('.anchor')\n *\n * on($nav, 'click', function(evt) {\n * console.log('你点击了导航栏')\n * })\n *\n * on($anchor, 'click', function(evt) {\n * console.log('tagName', this.tagName)\n *\n * // 工作台输出:'a'\n * // 不会触发事件冒泡,输出:'你点击了导航栏'\n * // 也不会切换到 href 属性的页面,阻止了点击链接的默认行为\n * stopEvent(evt)\n * })\n */\nconst stop = function (evt) {\n evt.stopPropagation()\n evt.preventDefault()\n}\n\nexport default stop\n"],"names":["isString","str","hasOwn","obj","prop","hasOwnProperty","Object","prototype","call","toString","val","apply","isFunction","isObject","o","_subscribers","_hasDirectSubscribersFor","topic","length","has","isDirect","found","position","lastIndexOf","substring","_hasSubscribers","emit","data","async","execute","forEach","subscriber","message","indexOf","callback","context","deliver","setTimeout","guid","uuid","prefix","_removeSubscriber","off","token","keys","subject","execution","j","splice","_removeSubscriberByToken","Base","constructor","options","this","attrs","initialize","attr","render","addListeners","value","origin","source","arguments","destroy","removeListeners","reload","$emit","event","publish","$on","handler","push","subscribe","$off","unsubscribe","isElement","nodeName","tagName","nodeType","later","fn","delay","CAPTURE_EVENTS","_off","el","type","capture","_delegateListener","listeners","_listeners","index","listener","i","_delete","removeEventListener","purgeElement","recurse","$element","document","querySelector","$children","childNodes","filter","getListeners","$child","at","once","evt","overrideContext","addEventListener","matches","selector","sel","replace","msMatchesSelector","getParentOrHost","host","parentNode","on","target","getTarget","delegateTarget","ctx","includeCTX","startsWith","closest","isArray","Array","isDOM","isHTMLCollection","fragment","isTextNode","createElement","children","$fragment","createDocumentFragment","$el","isValidChild","child","append","createTextNode","appendChild","toLowerCase","style","cssText","setAttribute","className","every","easeInQuad","x","_getScrollElement","scrollElement","$rootElements","$scrollElement","querySelectorAll","scrollTop","hasClass","pattern","RegExp","allClass","classList","contains","exec","addClass","add","removeClass","remove","offsetTop","top","offsetParent","getStyle","ruleName","getComputedStyle","setProperty","documentElement","cloneDeep","clone","assign","key","from","Chapters","super","DEFAULTS","$title","$main","$list","$placeholder","$parentElement","chapters","closed","active","offsetWidth","$active","scrollTimer","resizeTimer","playing","Observer","created","parentElement","$parent","isClosed","isSticky","isFixed","isInside","isOutside","_paintEdge","title","customClass","contents","id","calculateStickyHeight","showCode","mounted","byId","chapter","pid","rel","$text","text","$link","href","$code","$li","$ul","code","insertBefore","firstChild","_paintChapters","positionPlaceholder","sticky","onObserver","$anchor","mainPaddingTop","parseInt","mainBorderTop","placeholderPaddingTop","placeholderMarginTop","placeholderBorderTop","height","offsetHeight","highlight","HIGHLIGHT","getAttribute","afterSticky","FIXED","isStickying","Math","max","clientHeight","window","innerHeight","scrollTo","after","afterStop","step","distance","MAX_HEIGHT","scrollHeight","MAX_TOP","stop","play","requestAnimationFrame","show","FOLDED","HIDDEN","opened","hide","toggle","afterToggle","beforeDestroy","afterDestroy","removeChild","clearTimeout","timer","props","root","rootMargin","IntersectionObserver","entries","entry","intersectionRatio","$root","section","observe","intersection","$heading","onSelect","stickyHeight","headingId","split","afterScroll","min","stopPropagation","preventDefault","onScroll","onResize","unobserve","afterClosed","afterOpened"],"mappings":"yOAOA,MAAMA,EAAYC,GACM,iBAARA,ECAVC,EAAS,CAACC,EAAKC,KACnB,MAAMC,EAAiBC,OAAOC,UAAUF,eACxC,OAAOF,GAAOE,EAAeG,KAAKL,EAAKC,EAAI,ECHvCK,EAAYC,GACTJ,OAAOC,UAAUE,SAASE,MAAMD,GCCnCE,EAAcF,GACI,mBAARA,GAAwC,sBAAlBD,EAASC,GCAzCG,EAAYC,IAEG,oBAAhBL,EAASK,IACK,iBAANA,GACPF,EAAWE,KACP,OAANA,ECTEC,EAAe,CAAA,ECIfC,EAA4BC,GACzBf,EAAOa,EAAcE,IAAUF,EAAaE,GAAOC,OAAS,ECA/DC,EAAM,CAACF,EAAOG,GAAW,IACtBA,EAAWJ,EAAyBC,GCHrB,CAACA,IACvB,IAAII,EAAQL,EAAyBC,GACjCK,EAAWL,EAAMM,YAAY,KAEjC,MAAQF,IAAuB,IAAdC,GAEfA,GADAL,EAAQA,EAAMO,UAAU,EAAGF,IACVC,YAAY,KAC7BF,EAAQL,EAAyBC,GAGnC,OAAOI,GDP6CI,CAAgBR,GEGhES,EAAO,CAACT,EAAOU,EAAMC,GAAQ,KACjC,MAAMC,EAAWZ,IACf,IAAKD,EAAyBC,GAC5B,OAAO,EAGTF,EAAaE,GAAOa,SAASC,IAG3B,MAAMC,EChBI,CACZ,qBACA,sBACA,6BACA,sBACA,uBACA,sBACA,uBACA,wBACA,wBACA,yBACA,2BAGWC,QAAQxB,EDEYkB,KCFM,EDEEA,EAAKlB,WAAakB,EAEvDI,EAAWG,SAAS1B,KAAKuB,EAAWI,SAAWJ,EAAYC,EAAQ,GACnE,EAEEI,EAAU,KACd,IAAIL,EAAad,EACbK,EAAWL,EAAMM,YAAY,KAEjC,MAAqB,IAAdD,GACLS,EAAaA,EAAWP,UAAU,EAAGF,GACrCA,EAAWS,EAAWR,YAAY,KAElCM,EAAQE,GAIVF,EAAQZ,GAERY,EAAQ,IAAI,EAGd,IAAKV,EAAIF,GACP,OAAO,EAGLW,EACFS,WAAWD,EAAS,IAEpBA,GACD,EE/CGE,EAAO,MACX,IAAIC,EAAO,EAEX,OAAQC,IACND,GAAQ,EAEDC,EAASA,EAAS,IAAMD,EAAO,QAAUA,EAEnD,EARY,GCGPE,EAAqBxB,IACzB,IAAKf,EAAOa,EAAcE,GACxB,OAAO,SAGFF,EAAaE,EAAM,ECJtByB,EAAM,CAACzB,EAAO0B,KAClB,IAAKxB,EAAIF,GACP,OAAO,EAGL0B,ECL2B,CAACA,IAChC,MAAMC,EAAOtC,OAAOsC,KAAK7B,GAGzB,IAAK4B,GAASC,EAAK1B,OAAS,EAC1B,OAAO,EAGT0B,EAAKd,SAASe,IACZ,MAAMd,EAAahB,EAAa8B,GAChC,IAAI5B,EAEJc,EAAWD,SAAQ,CAACgB,EAAWC,KACzBD,EAAUZ,WAAaS,GAASG,EAAUH,QAAUA,IACtD1B,EAAQ6B,EAAU7B,MAClBc,EAAWiB,QAbL,EAamBD,GAC1B,IAIChB,EAAWb,OAAS,GACtBuB,EAAkBxB,EACnB,GACD,EDjBAgC,CAAyBN,GAEzBF,EAAkBxB,EACnB,EEZH,MAAMiC,EACJC,YAAYC,GACVC,KAAKC,MAAQ,CAAE,EAEXF,GACFC,KAAKE,WAAWH,EAEnB,CAEDG,WAAWH,GAET,OADAC,KAAKG,KAAKJ,GAASK,SAASC,eACrBL,IACR,CAEDG,KAAKpD,EAAMuD,GACT,MAAML,EAAQD,KAAKC,MAEnB,OAAItD,EAASI,GAEPuD,GAASzD,EAAOoD,EAAOlD,IAEzBkD,EAAMlD,GAAQuD,EACPN,MAIFC,EAAMlD,GACJS,EAAST,IC1BRwD,ED4BHN,EC5BWO,ED4BJzD,EC3BLE,OAAOsC,KAAKiB,GAEpB/B,SAAS1B,IACRF,EAAO2D,EAAQzD,KACjBwD,EAAOxD,GAAQyD,EAAOzD,GACvB,IDwBQiD,MACuB,IAArBS,UAAU5C,OAEZoC,EAGFD,KCpCI,IAACO,EAAQC,CDqCrB,CAEDJ,SACE,OAAOJ,IACR,CAEDU,UAEE,OADAV,KAAKW,kBACEX,IACR,CAEDY,OAAOb,GAEL,OADAC,KAAKU,UAAUR,WAAWF,KAAKG,KAAKJ,IAC7BC,IACR,CAEDa,MAAMC,EAAOxC,GAEX,OADAyC,EAAQD,EAAOxC,GACR0B,IACR,CAEDgB,IAAIF,EAAOjC,GAET,MExDO,EAACjB,EAAOqD,EAASnC,EAAU,QACpC,MAAMQ,EAAQL,IACd,IAAIO,EAA2B,iBAAV5B,EAAqBA,EAAMR,WAAaQ,EAExDL,EAAW0D,KAKXvD,EAAa8B,KAChB9B,EAAa8B,GAAW,IAG1B9B,EAAa8B,GAAS0B,KAAK,CACzBtD,MAAO4B,EACPX,SAAUoC,EACVnC,UACAQ,UAGKA,EFmCL6B,CAAUL,EAAOjC,EAAUmB,MACpBA,IACR,CAEDoB,KAAKN,EAAOjC,GAEV,OADAwC,EAAYP,EAAOjC,GACZmB,IACR,CAEDK,eACE,OAAOL,IACR,CAEDW,kBACE,OAAOX,IACR,EG1EH,MAAMsB,EAAa7D,MACPD,EAASC,IAAMA,EAAE8D,UAAY9D,EAAE+D,SAA0B,IAAf/D,EAAEgE,UCAlDC,EAAQ,CAACC,EAAIC,EAAQ,QACpBrE,EAAWoE,IAIT3C,YAAW,KAChB2C,GAAI,GACHC,GCjBQC,EAAiB,CAC5B,WACA,OACA,UACA,QACA,OACA,SACA,aACA,cCMIC,EAAO,CAACC,EAAIC,EAAML,KACtB,MAAMM,EAAUJ,EAAejD,QAAQoD,IAAS,EAG5CL,EAAGO,0BACLP,EAAKA,EAAGO,mBACEA,kBCZE,SAAUH,EAAIC,EAAML,GAClC,MAAMQ,EAAYJ,EAAGK,WACrB,IAAIC,GAAS,EAEb,GAAIF,EAAUtE,OAAS,EACrB,OAAO,EAITsE,EAAU1D,SAAQ,CAAC6D,EAAUC,KAC3B,MAAMtB,EAAUqB,EAASX,GAErBK,IAASM,EAASN,OACpBK,EAAQE,EAEJtB,IAAYU,IACdU,EAAQE,GAEX,IAICF,GAAS,GACXF,EAAUxC,OAAO0C,EAAO,EAE5B,CDTEG,CAAQT,EAAIC,EAAML,GAElBI,EAAGU,oBAAoBT,EAAML,EAAIM,EAAQ,EEVrCS,EAAe,SAAUX,EAAIC,EAAMW,GAAU,GACjD,MAAMC,EAAWjG,EAASoF,GAAMc,SAASC,cAAcf,GAAMA,EACvDgB,EAAYH,EAASI,WACrBb,ECPa,EAACJ,EAAIC,KACxB,IAAIG,EAAYJ,EAAGK,YAAc,GAQjC,OANIzF,EAASqF,IAASA,IACpBG,EAAYA,EAAUc,QAAQX,GACrBA,EAASN,OAASA,KAItBG,GDFWe,CAAaN,EAAUZ,GAEzCG,EAAU1D,SAAS6D,IACjBR,EAAKc,EAAUN,EAASN,KAAMM,EAASX,GAAG,KAIzCgB,IAAoB,IAATX,GAAsC,IAArBvB,UAAU5C,SACvC+E,GACAG,GAEAA,EAAUtE,SAAS0E,IACb7B,EAAU6B,IACZT,EAAaS,EAAQnB,EAAMW,EAC5B,GAGP,EEtBMtD,EAAM,CAAC0C,EAAIC,EAAML,KAErB,IAAKpE,EAAWoE,GACd,OAAOe,EAAaX,EAAIC,GAG1BF,EAAKC,EAAIC,EAAML,EAAG,ECHdyB,EAAK,CAACrB,EAAIC,EAAML,EAAIrD,EAAMQ,EAASuE,GAAO,KAE9C,MAAMpB,EAAUJ,EAAejD,QAAQoD,IAAS,EAC1CM,EAAW,SAAUgB,GACzB,IAAIC,EAAkBzE,GAAWiD,GAIjB,IAAZjD,IACFyE,EAAkBjF,IAKP,IAAT+E,GACFhE,EAAI0C,EAAIC,EAAMM,GAGhBX,EAAGxE,KAAKoG,EAAiBD,EAAKhF,EAC/B,EAED,IAAKf,EAAWoE,GACd,OAAO,EAGJI,EAAGK,aACNL,EAAGK,WAAa,IAIlBL,EAAGK,WAAWlB,KAAK,CACjBa,KACAC,OACAL,GAAIW,EACJhE,OACAQ,UACAmD,YAIFN,EAAGO,kBAAoBI,EAEvBP,EAAGyB,iBAAiBxB,EAAMM,EAAUL,EAAQ,EC9CxCwB,EAAU,CAAC1B,EAAI2B,EAAW,MAC9B,MAAMC,EAAMD,EAASE,QAAQ,MAAO,IAEpC,SAAKF,GAAaC,GAAQ5B,KAKtBA,EAAG0B,QACE1B,EAAG0B,QAAQE,KACT5B,EAAG8B,mBACL9B,EAAG8B,kBAAkBF,GAG7B,ECpBGG,EAAmB/B,GAChBA,EAAGgC,MAAQhC,IAAOc,UAAYd,EAAGgC,KAAKtC,SACzCM,EAAGgC,KACHhC,EAAGiC,WCSHC,EAAK,CAAClC,EAAI2B,EAAU1B,EAAML,EAAIrD,EAAMQ,EAASuE,GAAO,KAExD,MAAMpB,EAAUJ,EAAejD,QAAQoD,IAAS,EAE1CM,EAAW,SAAUgB,GACzB,MAAMY,ECfQ,SAAUZ,GAC1B,MAAMY,EAASZ,EAAIY,OAEnB,OCJgCnC,EDITmC,ICHG,IAAhBnC,EAAGN,SACJM,EAAGiC,WAGLjC,EALe,IAAUA,CDKlC,CDWmBoC,CAAUb,GAEnBc,EGbM,EAACrC,EAAI2B,EAAUW,EAAKC,KAClC,MAAMxF,EAAUuF,GAAOxB,SAEvB,IAAKd,EACH,OAAO,KAGT,EAAG,CAED,GACe,MAAZ2B,IACEA,EAASa,WAAW,KACjBxC,EAAGiC,aAAelF,GAAW2E,EAAQ1B,EAAI2B,GACzCD,EAAQ1B,EAAI2B,KACjBY,GAAcvC,IAAOjD,EAEtB,OAAOiD,EAIT,GAAIA,IAAOjD,EACT,KAIN,OAAYiD,EAAK+B,EAAgB/B,GAAK,EHZXyC,CAAQN,EAAQR,EAAU3B,GACjD,IAAIwB,EAAkBzE,GAAWiD,EAEjCuB,EAAIc,eAAiBA,GAIL,IAAZtF,IACFyE,EAAkBjF,GAIhB8F,KAGW,IAATf,GACFhE,EAAI0C,EAAIC,EAAMM,GAGhBX,EAAGxE,KAAKoG,EAAiBD,EAAKhF,GAEjC,EAEIyD,EAAGK,aACNL,EAAGK,WAAa,IAIlBL,EAAGK,WAAWlB,KAAK,CACjBa,KACA2B,WACA1B,OACAL,GAAIW,EACJhE,OACAQ,UACAmD,YAIFN,EAAGO,kBAAoBI,EAEvBP,EAAGyB,iBAAiBxB,EAAMM,EAAUL,EAAQ,EI1DxCwC,EAAWhH,GACXiH,MAAMD,QACDC,MAAMD,QAAQhH,GAEE,mBAAhBL,EAASK,GCPdkH,EAAS5C,IACb,SACEvE,EAASuE,MACRT,EAAUS,ICNU,CAACA,MACdvE,EAASuE,IAAwB,sBAAjB3E,EAAS2E,IDKf6C,CAAiB7C,KENnB8C,EFMqC9C,EEJrDvE,EAASqH,IAAoC,8BAAvBzH,EAASyH,KCFhB,CAAC9C,MAEhBvE,EAASuE,MACS,kBAAjB3E,EAAS2E,IAA4BA,EAAGP,SAA2B,IAAhBO,EAAGN,WHGKqD,CAAW/C,KENxD,IAAC8C,CFOjB,EIMGE,EAAgB,CAACvD,EAASvB,EAAO+E,KACrC,MAAMC,EAAYpC,SAASqC,yBACrBC,EAAMtC,SAASkC,cAAcvD,GAC7B4D,EAAgBC,GACbV,EAAMU,IAAU1I,EAAS0I,GAE5BC,EAAUD,IACd,IAAIlC,EAEJ,IAAKiC,EAAaC,GAChB,OAAO,EAGLV,EAAMU,GACRlC,EAASkC,EACA1I,EAAS0I,KAClBlC,EAASN,SAAS0C,eAAeF,IAGnCJ,EAAUO,YAAYrC,EAAO,EAyB/B,OAtBI3F,EAASyC,GACXhD,OAAOsC,KAAKU,GAAOxB,SAAS0B,IACtBtD,EAAOoD,EAAOE,IChCH,EAAC4B,EAAI5B,EAAMG,KAC9B,IAAIkB,EAAUO,EAAGP,QAAQiE,cAEzB,OAAQtF,GACN,IAAK,QACH4B,EAAG2D,MAAMC,QAAUrF,EACnB,MACF,IAAK,QACa,UAAZkB,GAAmC,aAAZA,EACzBO,EAAGzB,MAAQA,EAEXyB,EAAG6D,aAAazF,EAAMG,GAExB,MACF,IAAK,YACHyB,EAAG8D,UAAYvF,EACf,MACF,QACEyB,EAAG6D,aAAazF,EAAMG,GAEzB,EDaKsF,CAAaT,EAAKhF,EAAMF,EAAME,GAC/B,IAEMsE,EAAQxE,IAAUA,EAAM6F,OAAO3F,GAASiF,EAAajF,MAC9DF,EAAMxB,SAAS4G,IACbC,EAAOD,EAAM,IAIbZ,EAAQO,GACVA,EAASvG,SAAS4G,IAChBC,EAAOD,EAAM,IAGfC,EAAON,GAGTG,EAAIK,YAAYP,GAETE,GErDHY,EAAcC,GACXA,EAAIA,ECGPC,EAAoB,CAACC,EAAgB,QACzC,IAAIC,EACAC,EAgBJ,OAdKF,EAOCvJ,EAASuJ,GACXE,EAAiBvD,SAASC,cAAcoD,GAC/B5E,EAAU4E,KACnBE,EAAiBF,IATnBC,EAAgBtD,SAASwD,iBAAiB,aAC1CD,EACED,EAAc,GAAGG,UAAYH,EAAc,GAAGG,WAAa,EACvDH,EAAc,GACdA,EAAc,IASfC,GCpBHG,EAAW,CAACxE,EAAI8D,KACpB,MAAMW,EAAU,IAAIC,OAAO,UAAYZ,EAAY,WACnD,IAAIa,EACAC,EAEJ,QAAKrF,EAAUS,KAIf2E,EAAW3E,EAAG8D,YAETa,IAILC,EAAY5E,EAAG4E,UAEXA,GAAWC,SACN7E,EAAG4E,UAAUC,SAASf,KAGtBW,EAAQK,KAAKH,IAAQ,ECpB1BI,EAAW,CAAC/E,EAAI8D,KACpB,IAAIc,EACAD,EAEJ,GAAIH,EAASxE,EAAI8D,GACf,OAAO,EAGTc,EAAY5E,EAAG4E,UAEXA,GAAWI,IACbJ,EAAUI,IAAIlB,IAEda,EAAW3E,EAAG8D,UACda,GAAYA,EAAS7I,OAAS,EAAI,IAAMgI,EAAYA,EACpD9D,EAAG8D,UAAYa,EAChB,ECfGM,EAAc,CAACjF,EAAI8D,KACvB,IACIc,EADAD,EAAW3E,EAAG8D,UAGlB,IAAKa,IAAaH,EAASxE,EAAI8D,GAC7B,OAAO,ECPE,IAACjJ,EDUZ+J,EAAY5E,EAAG4E,UAEXA,GAAWM,OACbN,EAAUM,OAAOpB,ICbPjJ,EDeM8J,EAAS9C,QAAQiC,EAAW,IAA5Ca,ICdG/J,EAASC,IAGPA,EAAIgH,QAAQ,iBAAkB,IDYnC7B,EAAG8D,UAAYa,EAChB,EEnBGQ,EAAanF,IACjB,IAAIoF,EAAMpF,EAAGmF,UAMb,OAJwB,OAApBnF,EAAGqF,eACLD,GAAOD,EAAUnF,EAAGqF,eAGfD,GCPHE,EAAW,CAACtF,EAAIuF,IACbC,iBAAiBxF,GAAIuF,GCRxBE,EAAc,CAACzK,EAAMuD,KACDuC,SAAS4E,gBACjB/B,MAAM8B,YAAYzK,EAAMuD,EAAM,ECW1CoH,EAAa5K,IACjB,IAAI6K,EAEJ,OAAY,OAAR7K,EACK,MAGT6K,EAAQ1K,OAAO2K,OAAO,CAAA,EAAI9K,GAE1BG,OAAOsC,KAAKoI,GAAOlJ,SAASoJ,GAClBF,EAAME,GACQ,iBAAb/K,EAAI+K,GAAoBH,EAAU5K,EAAI+K,IAAQ/K,EAAI+K,KAGzDpD,EAAQ3H,IACV6K,EAAM9J,OAASf,EAAIe,OAEZ6G,MAAMoD,KAAKH,IAGbA,ICTT,MAAMI,UAAiBlI,EACrBC,YAAYC,GACViI,QAEAhI,KAAKC,MAAQyH,EAAUK,EAASE,UAChCjI,KAAKmF,IAAM,KACXnF,KAAKkI,OAAS,KACdlI,KAAKmI,MAAQ,KACbnI,KAAKoI,MAAQ,KACbpI,KAAKqI,aAAe,KACpBrI,KAAKsI,eAAiB,KACtBtI,KAAKoG,eAAiB,KACtBpG,KAAKuI,SAAW,GAChBvI,KAAKwI,QAAS,EACdxI,KAAKyI,OAAS,EACdzI,KAAKkH,UAAY,EACjBlH,KAAK0I,YAAc,EACnB1I,KAAK2I,QAAU,KACf3I,KAAK4I,YAAc,KACnB5I,KAAK6I,YAAc,KACnB7I,KAAK8I,SAAU,EACf9I,KAAK+I,SAAW,KAEZhJ,GACFC,KAAKE,WAAWH,EAEnB,CAEDG,WAAWH,GACT,IAAIiJ,EACAC,EACA/C,EACAgD,EAuBJ,OArBAlJ,KAAKG,KAAKJ,GACViJ,EAAUhJ,KAAKG,KAAK,WACpB8I,EAAgBjJ,KAAKG,KAAK,iBAC1B+F,EAAgBlG,KAAKG,KAAK,iBAEtBxD,EAASsM,GACXC,EAAUrG,SAASC,cAAcmG,GACxB3H,EAAU2H,KACnBC,EAAUD,GAEZjJ,KAAKsI,eAAiBY,EACtBlJ,KAAKoG,eAAiBH,EAAkBC,GAExClG,KAAKuI,SAAWvI,KAAKG,KAAK,YAC1BH,KAAKwI,OAASxI,KAAKG,KAAK,UACxBH,KAAKyI,OAASzI,KAAKG,KAAK,UAEpB5C,EAAWyL,IACbA,EAAQ7L,KAAK6C,MAGXA,KAAKuI,SAAS1K,OAAS,IAI3BmC,KAAKI,SAASC,eAEdL,KAAK2I,QAAU9F,SAASC,cAAc,YAAY9C,KAAKyI,WAL9CzI,IAQV,CAEDmJ,WACE,OAAOnJ,KAAKwI,MACb,CAEDY,WAEE,MAAoB,WADHpJ,KAAKG,KAAK,WAE5B,CAEDkJ,UAEE,MAAoB,UADHrJ,KAAKG,KAAK,WAE5B,CAEDmJ,WACE,OAAOtJ,KAAKqJ,WAAarJ,KAAKoJ,UAC/B,CAEDG,YACE,OAAQvJ,KAAKsJ,UACd,CAEDE,aACE,MAAMvE,EAAYpC,SAASqC,yBAGrBuE,EAAQzJ,KAAKG,KAAK,SAClBuJ,EAAc1J,KAAKG,KAAK,eACxBmI,EAAiBtI,KAAKsI,eACtBqB,EAAW,GACjB,IACIxE,EACAgD,EACAC,EACAC,EAJAH,EAAS,KAMb,OAAKI,GAIDtI,KAAKsJ,YAAcG,IACrBvB,EAASnD,EACP,KACA,CACEc,UAAW,2BAEb,CAAC4D,IAEHzJ,KAAKkI,OAASA,EACdyB,EAASzI,KAAKgH,IAGhBE,EAAQrD,EACN,KACA,CAIEc,UAAW,0BAEb,CAAC,KAEH7F,KAAKoI,MAAQA,EAEbC,EAAetD,EACb,MACA,CACEc,UAAW,iCAEb,CAAC,KAEH7F,KAAKqI,aAAeA,EAEpBF,EAAQpD,EACN,MACA,CACEc,UAAW,0BAEb,CAACuC,EAAOC,IAEVrI,KAAKmI,MAAQA,EACbwB,EAASzI,KAAKiH,GAEdhD,EAAMJ,EACJ,MACA,CACE6E,GAAI,mBACJ/D,UAAW,4CAEb8D,GAEF3J,KAAKmF,IAAMA,EAEPnF,KAAKoJ,aACPpJ,KAAK6J,wBACL/C,EAAS3B,EAvEI,4BA0EXuE,GACF5C,EAAS3B,EAAKuE,GAEhBzE,EAAUO,YAAYL,GACtBmD,EAAe9C,YAAYP,GAEpBjF,MAnEEA,IAoEV,CAEDI,SACE,MACM0J,EAAW9J,KAAKG,KAAK,YACrB4J,EAAU/J,KAAKG,KAAK,WACpBmI,EAAiBtI,KAAKsI,eACtBC,EAAWvI,KAAKuI,SACtB,IAAIpD,EACAiD,EAEJ,OAAKE,GAAkBC,EAAS1K,OAAS,IAIzCmC,KAAKwJ,aAELrE,EAAMnF,KAAKmF,IACXiD,EAAQpI,KAAKoI,MCnNM,EAACA,EAAOG,EAAUuB,GAAW,KAClD,MAAME,EAAQJ,GAAO/G,SAASC,cAAc,IAAI8G,KAEhDrB,EAAS9J,SAASwL,IAChB,MAAMC,EAAMD,EAAQC,IACdN,EAAKK,EAAQL,GACbO,EAAMF,EAAQE,IACdC,EAAQrF,EACZ,OACA,CACEc,UAAW,0BAEb,CAACoE,EAAQI,OAELC,EAAQvF,EACZ,IACA,CACE6E,GAAI,mBAAmBA,IACvB/D,UAAW,2BACX0E,KAAM,IAAMJ,EACZA,IAAKA,EACL,UAAWP,GAEb,CAACQ,IAEH,IAAII,EACAC,EACAC,EACAxB,EAEAY,IACFU,EAAQzF,EACN,OACA,CACEc,UAAW,yBACX,UAAW+D,GAEb,CAACK,EAAQU,OAGXL,EAAMM,aAAaJ,EAAOF,EAAMO,aAGlCJ,EAAM1F,EACJ,KACA,CACE6E,GAAI,WAAWA,IACf/D,UAAW,yBACX,UAAW+D,GAEb,CAACU,KAGU,IAATJ,EACF9B,EAAM5C,YAAYiF,IAElBvB,EAAUc,EAAK,WAAWE,KAC1BQ,EAAMV,EAAK,WAAWE,KAEjBQ,EAYHA,EAAIlF,YAAYiF,IAXhBC,EAAM3F,EACJ,KACA,CACE6E,GAAI,WAAaM,EACjBrE,UAAW,6BAEb,CAAC4E,IAGHvB,EAAQ1D,YAAYkF,IAIvB,GACD,ED0IAI,CAAe1C,EAAOG,EAAUuB,GAChC9C,EAAY7B,EAjBG,2BAkBfnF,KAAK+K,oBAAoB/K,KAAKyI,QAE9BzI,KAAKkH,UAAYA,EAAU/B,GAC3BnF,KAAK0I,YAAcvD,EAAIuD,YAEnB1I,KAAKqJ,YACPrJ,KAAKgL,SACLxD,EAAY,2BAA4B,GAAGxH,KAAK0I,kBAG9CnL,EAAWwM,IACbA,EAAQ5M,KAAK6C,MAGfA,KAAKiL,cAvBIjL,IA0BV,CAED+K,oBAAoB1I,GAClB,MAAM8F,EAAQnI,KAAKmI,MACbC,EAAQpI,KAAKoI,MACbC,EAAerI,KAAKqI,aACpB6C,EAAU9C,EAAMtF,cAAc,6BAC9BqI,EAAiBC,SAAS/D,EAASc,EAAO,eAAgB,IAC1DkD,EAAgBD,SAAS/D,EAASc,EAAO,oBAAqB,IAC9DmD,EAAwBF,SAAS/D,EAASe,EAAO,eAAgB,IACjEmD,EAAuBH,SAAS/D,EAASe,EAAO,cAAe,IAC/DoD,EAAuBJ,SAC3B/D,EAASe,EAAO,oBAChB,IAEF,IAEIjB,EAFAsE,EAASP,EAAQQ,aACjBxE,EAAY,EA6BhB,OA1BIiE,IACFjE,GAAaiE,GAGXG,IACFpE,GAAaoE,GAGXC,IACFrE,GAAaqE,GAGXF,IACFnE,GAAamE,GAGXG,IACFtE,GAAasE,GAGfrE,EAAMsE,EAASpJ,EAEfgG,EAAa3C,MAAMC,QAAU,yBAC3BuB,EAAYC,eACAsE,OAEPzL,IACR,CAED2L,UAAU/B,GACR,MAAMsB,EAAUlL,KAAKmF,IAAIrC,cAAc,oBAAoB8G,KACrDgC,EAAY,0BAElB,OAAKV,GAIDlL,KAAK2I,SACP3B,EAAYhH,KAAK2I,QAASiD,GAG5B5L,KAAKyI,OAAS2C,SAASF,EAAQW,aAAa,WAAY,IACxD7L,KAAK2I,QAAUuC,EACfpE,EAAS9G,KAAK2I,QAASiD,GAEvB5L,KAAK+K,oBAAoB/K,KAAKyI,QAEvBzI,MAbEA,IAcV,CAEDgL,SACE,MAAMc,EAAc9L,KAAKG,KAAK,eACxB4L,EAAQ,yBACR5G,EAAMnF,KAAKmF,IACXgC,EAAMnH,KAAKkH,UACXZ,EAAYtG,KAAKoG,eAAeE,UACtC,IAAI0F,EAEJ,OAAKhM,KAAKqJ,WAIV2C,EAAc1F,GAAaa,EAEvB6E,EACFlF,EAAS3B,EAAK4G,GAEd/E,EAAY7B,EAAK4G,GAGfxO,EAAWuO,IACbA,EAAY3O,KAAK6C,KAAMA,KAAKmJ,WAAY6C,GAGnChM,MAfEA,IAgBV,CAED6J,wBACE,MAAMpC,EAAkB5E,SAAS4E,gBAC3BgE,EAASQ,KAAKC,IAClBzE,EAAgB0E,cAAgB,EAChCC,OAAOC,aAAe,GAGxB,OADA7E,EAAY,0BAA2B,GAAGiE,OACnCzL,IACR,CAEDsM,SAASnF,EAAKoF,GAKZ,ME5Ua,EAACrG,EAAeiB,EAAKqF,KACpC,MAAMpG,EAAiBH,EAAkBC,GACzC,IAAII,EAAYF,EAAeE,UAC3BmG,EAAO,EACX,MAAMC,EAAWvF,EAAMb,EACjBqG,EAAavG,EAAewG,aAC5BC,EAAU1F,EAAMwF,GAAc,EAAIxF,EAAMwF,EACxCG,EAAQ3F,IACR5J,EAAWiP,IACbA,EAAUrF,IAGL,GAEH4F,EAAO,KAIX,GAHAN,GAAQ,EAGJC,EAAW,GAIb,GAHApG,GAAaP,EAAW0G,GACxBrG,EAAeE,UAAYA,EAEvBA,GAAaa,EAEf,OADAf,EAAeE,UAAYa,EACpB2F,EAAK3F,QAMd,GAHAb,GAAaP,EAAW0G,GACxBrG,EAAeE,UAAYA,EAEvBA,GAAauG,EAEf,OADAzG,EAAeE,UAAYuG,EACpBC,EAAKD,GAIhBG,sBAAsBD,EAAK,EAG7BC,sBAAsBD,EAAK,EFmSzBT,CAFWtM,KAAKoG,eAEHe,EAAKoF,GAEXvM,IACR,CAEDiN,OACE,MAAMC,EAAS,0BACTC,EAAS,0BACTC,EAASpN,KAAKG,KAAK,eACnBgF,EAAMnF,KAAKmF,IACX+D,EAAUlJ,KAAKsI,eAkBrB,OAhBItI,KAAKsJ,YACPtC,EAAYkC,EAASiE,GACrBnG,EAAY7B,EAAKgI,GACjBzL,GAAM,KACJsF,EAAYkC,EAASgE,GACrBlG,EAAY7B,EAAK+H,EAAO,GACvB,KAEHlG,EAAY7B,EAAKgI,GAEnBnN,KAAKwI,QAAS,EAEVjL,EAAW6P,IACbA,EAAOjQ,KAAK6C,MAGPA,IACR,CAEDqN,OACE,MAAMH,EAAS,0BACTC,EAAS,0BACT3E,EAASxI,KAAKG,KAAK,eACnBgF,EAAMnF,KAAKmF,IACX+D,EAAUlJ,KAAKsI,eAkBrB,OAhBItI,KAAKsJ,YACPxC,EAASoC,EAASgE,GAClBpG,EAAS3B,EAAK+H,GACdxL,GAAM,KACJoF,EAASoC,EAASiE,GAClBrG,EAAS3B,EAAKgI,EAAO,KAGvBrG,EAAS3B,EAAKgI,GAEhBnN,KAAKwI,QAAS,EAEVjL,EAAWiL,IACbA,EAAOrL,KAAK6C,MAGPA,IACR,CAEDsN,SACE,MAAMC,EAAcvN,KAAKG,KAAK,eACxBgH,EAAMnH,KAAKkH,UACXZ,EAAYtG,KAAKoG,eAAeE,UACtC,IAAI0F,EAeJ,OAbIhM,KAAKmJ,WACPnJ,KAAKiN,OAELjN,KAAKqN,OAGH9P,EAAWgQ,IACb7L,GAAM,KACJsK,EAAc1F,GAAaa,EAC3BoG,EAAYpQ,KAAK6C,KAAMA,KAAKmJ,WAAY6C,EAAY,IAIjDhM,IACR,CAEDU,UACE,MAAM8M,EAAgBxN,KAAKG,KAAK,iBAC1BsN,EAAezN,KAAKG,KAAK,gBAyC/B,OAvCI5C,EAAWiQ,IACbA,EAAcrQ,KAAK6C,MAGrBA,KAAKW,kBACLX,KAAKsI,eAAeoF,YAAY1N,KAAKmF,KAErCnF,KAAKG,KAAK4H,EAASE,UACnBjI,KAAKmF,IAAM,KACXnF,KAAKkI,OAAS,KACdlI,KAAKmI,MAAQ,KACbnI,KAAKoI,MAAQ,KACbpI,KAAKqI,aAAe,KACpBrI,KAAKsI,eAAiB,KACtBtI,KAAKoG,eAAiB,KACtBpG,KAAKuI,SAAW,GAChBvI,KAAKyI,OAAS,EACdzI,KAAKkH,UAAY,EACjBlH,KAAK2I,QAAU,KACf3I,KAAKwI,QAAS,EAEVxI,KAAK4I,cACP+E,aAAa3N,KAAK4I,aAClB5I,KAAK4I,YAAc,MAGjB5I,KAAK6I,cACP8E,aAAa3N,KAAK6I,aAClB7I,KAAK6I,YAAc,MAGjBtL,EAAWkQ,IACbA,EAAatQ,KAAK6C,MAGhBA,KAAK+I,WACP/I,KAAK+I,SAAW,MAGX/I,IACR,CAEDiL,aACE,MAAMvH,EAAW1D,KAAKG,KAAK,YAC3B,IAAIyN,EAAQ,KAwBZ,OAtBA5N,KAAK+I,SGxcY,EAACpH,EAAIkM,EAAQ,MAChC,MAAMC,EAAOD,EAAMC,MAAQ,KACrBpK,EAAWmK,EAAMnK,UAAY,mBAC7B5E,EAAU+O,EAAM/O,SAAW,KAE3BiB,EAAU,CACdgO,WAFiBF,EAAME,YAAc,oBAIjChF,EAAW,IAAIiF,sBAAsBC,IACzCA,EAAQxP,SAASyP,IACXA,EAAMC,kBAAoB,GACxB5Q,EAAWoE,IACbA,EAAGxE,KAAK2B,GAAWoP,EAAMhK,OAAQgK,EAAMhK,OAE1C,GACD,GACDnE,GACGqO,EAAQ9M,EAAUwM,GAAQA,EAAOjL,SAUvC,OARIiL,IACF/N,EAAQ+N,KAAOA,GAGjBM,EAAM/H,iBAAiB3C,GAAUjF,SAAS4P,IACxCtF,EAASuF,QAAQD,EAAQ,IAGpBtF,GH6aWwF,EACbC,IACC,MAAM5E,EAAK4E,EAAS3C,aAAa,WAEjC,GAAI7L,KAAK8I,QACP,OAAO,EAGL8E,GACFD,aAAaC,GAGfA,EAAQlM,GAAM,KACZ1B,KAAK2L,UAAU/B,EAAG,GACjB,IAAI,GAET,CACElG,WACA5E,QAASkB,OAINA,IACR,CAEDyO,SAASnL,GACP,MAAMoL,EAAe1O,KAAKG,KAAK,gBACzB+K,EAAU5H,EAAIc,eACdwF,EAAKsB,EAAQW,aAAa,WAC1B8C,EAAYzD,EAAQX,KAAKqE,MAAM,KAAK,GACpCJ,EAAW3L,SAASC,cAAc,IAAI6L,KACtCxH,EAAMD,EAAUsH,IAAaE,EAAe,IAE5CxC,EAAMlM,KAAKoG,eAAewG,aAC1BiC,EAAc7O,KAAKG,KAAK,eACxBoM,EAAQ,KACRhP,EAAWsR,IACbA,EAAY1R,KAAK6C,KAAM,WAGzB0B,GAAM,KACJ1B,KAAK8I,SAAU,EACf/H,EAAQ,iBAAkB,CACxBoG,MACA2H,IAZM,EAaN5C,OACA,GACF,EAiBJ,OAdAlM,KAAK8I,SAAU,EACX9I,KAAKqJ,WACPrJ,KAAKgL,SACLtJ,GAAM,KACJ1B,KAAKsM,SAASnF,EAAKoF,GACnBvM,KAAK2L,UAAU/B,EAAG,GACjB,MAEH5J,KAAKsM,SAASnF,EAAKoF,GACnBvM,KAAK2L,UAAU/B,IItfR,SAAUtG,GACrBA,EAAIyL,kBACJzL,EAAI0L,gBACN,CJsfIlC,CAAKxJ,GAEEtD,IACR,CAEDiP,WACE,MAAM7I,EAAiBpG,KAAKoG,eAsB5B,OApBIpG,KAAK4I,aACP+E,aAAa3N,KAAK4I,aAGpB5I,KAAK4I,YAAclH,GAAM,KACvB,MAAMyF,EAAMf,EAAeE,UAErB4F,EAAM9F,EAAewG,aAAexG,EAAe+F,aAErDnM,KAAKqJ,WACPrJ,KAAKgL,SAGPjK,EAAQ,iBAAkB,CACxBoG,MACA2H,IATU,EAUV5C,OACA,GACD,KAEIlM,IACR,CAEDkP,WASE,OARIlP,KAAK6I,aACP8E,aAAa3N,KAAK6I,aAGpB7I,KAAK6I,YAAcnH,GAAM,KACvB1B,KAAK6J,uBAAuB,IAGvB7J,IACR,CAEDK,eACE,MAAM8E,EAAMnF,KAAKmF,IACXiB,EAAiBpG,KAAKoG,eACtB5E,EAAU4E,EAAe5E,QAAQiE,cACvC,IAAI7C,EAAWwD,EAYf,MAVgB,SAAZ5E,GAAkC,SAAZA,IACxBoB,EAAWwJ,QAGbnI,EAAGkB,EAAK,4BAA6B,QAASnF,KAAKyO,SAAUzO,MAAM,GACnEoD,EAAGR,EAAU,SAAU5C,KAAKiP,SAAUjP,MAAM,GACxCA,KAAKoJ,YACPhG,EAAGR,EAAU,SAAU5C,KAAKkP,SAAUlP,MAAM,GAGvCA,IACR,CAEDW,kBACE,MAAM+C,EAAW1D,KAAKG,KAAK,YACrBgF,EAAMnF,KAAKmF,IACXiB,EAAiBpG,KAAKoG,eACtB5E,EAAU4E,EAAe5E,QAAQiE,cACvC,IAAI7C,EAAWwD,EAmBf,MAjBgB,SAAZ5E,GAAkC,SAAZA,IACxBoB,EAAWwJ,QAGb/M,EAAI8F,EAAK,QAASnF,KAAKyO,UACvBpP,EAAIuD,EAAU,SAAU5C,KAAKiP,UAEzBjP,KAAKoJ,YACPhG,EAAGR,EAAU,SAAU5C,KAAKkP,UAG1BlP,KAAK+I,UACPlG,SAASwD,iBAAiB3C,GAAUjF,SAAS4P,IAC3CrO,KAAK+I,SAASoG,UAAUd,EAAQ,IAI7BrO,IACR,SAGH+H,EAASE,SAAW,CAClBgB,cAAe,GACf/C,cAAe,GACfxC,SAAU,mBACV+E,OAAQ,EACRD,QAAQ,EACRsB,UAAU,EACV7L,SAAU,WACVyQ,aAAc,EACdnG,SAAU,GACVS,QAAS,KACTe,QAAS,KACTqF,YAAa,KACbC,YAAa,KACbR,YAAa,KACbrB,cAAe,KACfC,aAAc,KACd3B,YAAa"} \ No newline at end of file +{"version":3,"file":"chapters.min.js","sources":["utils/types/isString.js","utils/lang/hasOwn.js","utils/lang/toString.js","utils/types/isFunction.js","utils/types/isObject.js","utils/observer/_subscribers.js","utils/observer/_hasDirectSubscribersFor.js","utils/observer/has.js","utils/observer/_hasSubscribers.js","utils/observer/emit.js","utils/types/isTypedArray.js","utils/lang/guid.js","utils/observer/_removeSubscriber.js","utils/observer/off.js","utils/observer/_removeSubscriberByToken.js","base.js","utils/lang/extend.js","utils/observer/on.js","utils/types/isElement.js","utils/lang/later.js","utils/event/enum.js","utils/event/_off.js","utils/event/_delete.js","utils/event/purgeElement.js","utils/event/getListeners.js","utils/event/off.js","utils/event/at.js","utils/dom/matches.js","utils/dom/getParentOrHost.js","utils/event/on.js","utils/event/getTarget.js","utils/dom/resolveTextNode.js","utils/dom/closest.js","utils/types/isArray.js","utils/types/isDOM.js","utils/types/isHTMLCollection.js","utils/types/isFragment.js","utils/types/isTextNode.js","utils/dom/createElement.js","utils/dom/setAttribute.js","utils/lang/easeInQuad.js","utils/dom/_getScrollElement.js","utils/dom/hasClass.js","utils/dom/addClass.js","utils/dom/removeClass.js","utils/lang/trim.js","utils/dom/offsetTop.js","utils/dom/getStyle.js","utils/dom/setProperty.js","utils/lang/cloneDeep.js","chapters.js","_paintChapters.js","utils/dom/scrollTo.js","utils/dom/intersection.js","utils/event/stop.js"],"sourcesContent":["/**\n * 检测数据是否为 String 类型\n * ========================================================================\n * @method isArray\n * @param {*} str\n * @returns {boolean}\n */\nconst isString = (str) => {\n return typeof str === 'string'\n}\n\nexport default isString\n","/**\n * 检测对象自身属性中是否具有指定的属性。\n * ========================================================================\n * @method hasOwn\n * @param {Object} obj - (必须)检测的目标对象\n * @param {String} prop - (必须)属性名\n * @returns {Boolean}\n */\nconst hasOwn = (obj, prop) => {\n const hasOwnProperty = Object.prototype.hasOwnProperty\n return obj && hasOwnProperty.call(obj, prop)\n}\n\nexport default hasOwn\n","/**\n * Object 对象原型上的 toString 方法\n * ========================================================================\n * @method toString\n * @param {*} val\n * @returns {string}\n */\nconst toString = (val) => {\n return Object.prototype.toString.apply(val)\n}\n\nexport default toString\n","import toString from '../lang/toString'\n\n/**\n * 检测测试数据是否为 Function 类型\n * ========================================================================\n * @method isFunction\n * @param {*} val - (必须)待检测的数据\n * @returns {boolean} 'val' 是 Function 类型返回 true,否则返回 false\n */\nconst isFunction = (val) => {\n return typeof val === 'function' || toString(val) === '[object Function]'\n}\n\nexport default isFunction\n","import toString from '../lang/toString'\nimport isFunction from './isFunction'\n\n/**\n * 检测数据是否为 Object 类型\n * ========================================================================\n * @method isObject\n * @param {*} o\n * @returns {boolean}\n */\nconst isObject = (o) => {\n return (\n (toString(o) === '[object Object]' ||\n typeof o === 'object' ||\n isFunction(o)) &&\n o !== null\n )\n}\n\nexport default isObject\n","/**\n * 存储订阅者(主题和处理器的)私有对象\n * ========================================================================\n * @type {{}}\n * @private\n */\nconst _subscribers = {}\n\nexport default _subscribers\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 判断是否存在与给定 topic 完全匹配的订阅者信息\n * ========================================================================\n * @method _hasDirectSubscribersFor\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasDirectSubscribersFor = (topic) => {\n return hasOwn(_subscribers, topic) && _subscribers[topic].length > 0\n}\n\nexport default _hasDirectSubscribersFor\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\nimport _hasSubscribers from './_hasSubscribers'\n\n/**\n * 判断是否存在包含 topic 指定的订阅者信息\n * ========================================================================\n * @method has\n * @param {String} topic - (必须)主题名称\n * @param {Boolean} [isDirect] - (可选)是否为直接的主题,默认值:true\n * @returns {Boolean}\n */\nconst has = (topic, isDirect = true) => {\n return isDirect ? _hasDirectSubscribersFor(topic) : _hasSubscribers(topic)\n}\n\nexport default has\n","import _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * 判断是否存在包含给定 topic 相关的订阅者信息\n * ========================================================================\n * @method _hasSubscribers\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _hasSubscribers = (topic) => {\n let found = _hasDirectSubscribersFor(topic)\n let position = topic.lastIndexOf('.')\n\n while (!found && position !== -1) {\n topic = topic.substring(0, position)\n position = topic.lastIndexOf('.')\n found = _hasDirectSubscribersFor(topic)\n }\n\n return found\n}\n\nexport default _hasSubscribers\n","import isTypedArray from '../types/isTypedArray'\nimport _subscribers from './_subscribers'\nimport has from './has'\nimport _hasDirectSubscribersFor from './_hasDirectSubscribersFor'\n\n/**\n * (异步)发布订阅主题信息\n * ========================================================================\n * 主题默认是异步发布的。确保在消费者处理主题时,主题的发起者不会被阻止。\n * ========================================================================\n * @method emit\n * @param {String} topic - (必须)主题名称\n * @param {Object} [data] - (可选)数据对象\n * @param {Boolean} [async] - (可选) 是否异步发布\n */\nconst emit = (topic, data, async = true) => {\n const execute = (topic) => {\n if (!_hasDirectSubscribersFor(topic)) {\n return false\n }\n\n _subscribers[topic].forEach((subscriber) => {\n // 针对 mqtt 消息服务返回的 Uint8Array 类似的 typed arrays 格式的数据\n // 采用 toString() 方法转化为普通(JSON)字符串\n const message = isTypedArray(data) ? data.toString() : data\n\n subscriber.callback.call(subscriber.context || subscriber, message)\n })\n }\n const deliver = () => {\n let subscriber = topic\n let position = topic.lastIndexOf('.')\n\n while (position !== -1) {\n subscriber = subscriber.substring(0, position)\n position = subscriber.lastIndexOf('.')\n\n execute(subscriber)\n }\n\n // 执行 topic 对应的处理器\n execute(topic)\n // 执行特殊 topic:'*'(监听全部消息的发布)\n execute('*')\n }\n\n if (!has(topic)) {\n return false\n }\n\n if (async) {\n setTimeout(deliver, 10)\n } else {\n deliver()\n }\n}\n\nexport default emit\n","import toString from '../lang/toString'\n/**\n * 判断检测数据是否为 Typed Arrays 类型的数据\n * ========================================================================\n * @param {*} val\n * @returns {boolean}\n */\nconst isTypedArray = (val) => {\n const TYPES = [\n '[object Int8Array]',\n '[object Uint8Array]',\n '[object Uint8ClampedArray]',\n '[object Int16Array]',\n '[object Uint16Array]',\n '[object Int32Array]',\n '[object Uint32Array]',\n '[object Float32Array]',\n '[object Float64Array]',\n '[object BigInt64Array]',\n '[object BigUint64Array]'\n ]\n\n return TYPES.indexOf(toString(val)) > -1\n}\n\nexport default isTypedArray\n","/**\n * 生成唯一 id 字符串的函数\n * ========================================================================\n * @method guid\n * @param {String} [prefix] - 生成 id 的前缀字符串\n * @return {String} 返回一个表示唯一 id 的字符串\n */\nconst guid = (() => {\n let uuid = 0\n\n return (prefix) => {\n uuid += 1\n\n return prefix ? prefix + '-' + uuid : 'guid-' + uuid\n }\n})()\n\nexport default guid\n","import _subscribers from './_subscribers'\nimport hasOwn from '../lang/hasOwn'\n\n/**\n * 删除与给定 topic 相同的订阅者信息\n * ========================================================================\n * @method _removeSubscriber\n * @param {String} topic - (必须)订阅主题字符串\n * @returns {Boolean}\n */\nconst _removeSubscriber = (topic) => {\n if (!hasOwn(_subscribers, topic)) {\n return false\n }\n\n delete _subscribers[topic]\n}\n\nexport default _removeSubscriber\n","import has from './has'\nimport _removeSubscriber from './_removeSubscriber'\nimport _removeSubscriberByToken from './_removeSubscriberByToken'\n\n/**\n * 取消订阅主题\n * ========================================================================\n * @method off\n * @param {String} topic - (必须)订阅的主题\n * @param {Function|String} [token] - (可选)订阅主题的处理器函数或者唯一 Id 值\n */\nconst off = (topic, token) => {\n if (!has(topic)) {\n return false\n }\n\n if (token) {\n _removeSubscriberByToken(token)\n } else {\n _removeSubscriber(topic)\n }\n}\n\nexport default off\n","import _subscribers from './_subscribers'\nimport _removeSubscriber from './_removeSubscriber'\n\n/**\n * 通过订阅者 token 值删除订阅者信息\n * ========================================================================\n * @method _removeSubscriberByToken\n * @param {String} token - 订阅者 token 字符串\n * @returns {boolean}\n * @private\n */\nconst _removeSubscriberByToken = (token) => {\n const keys = Object.keys(_subscribers)\n let index = -1\n\n if (!token || keys.length < 1) {\n return false\n }\n\n keys.forEach((subject) => {\n const subscriber = _subscribers[subject]\n let topic\n\n subscriber.forEach((execution, j) => {\n if (execution.callback === token || execution.token === token) {\n topic = execution.topic\n subscriber.splice(index, j)\n }\n })\n\n /* istanbul ignore else */\n if (subscriber.length < 1) {\n _removeSubscriber(topic)\n }\n })\n}\n\nexport default _removeSubscriberByToken\n","import isString from './utils/types/isString'\r\nimport hasOwn from './utils/lang/hasOwn'\r\nimport isObject from './utils/types/isObject'\r\nimport extend from './utils/lang/extend'\r\nimport publish from './utils/observer/emit'\r\nimport subscribe from './utils/observer/on'\r\nimport unsubscribe from './utils/observer/off'\r\n\r\nclass Base {\r\n constructor(options) {\r\n this.attrs = {}\r\n\r\n if (options) {\r\n this.initialize(options)\r\n }\r\n }\r\n\r\n initialize(options) {\r\n this.attr(options).render().addListeners()\r\n return this\r\n }\r\n\r\n attr(prop, value) {\r\n const attrs = this.attrs\r\n\r\n if (isString(prop)) {\r\n // 只能扩展 attrs 中已有的属性\r\n if (value && hasOwn(attrs, prop)) {\r\n // 更新单个配置信息\r\n attrs[prop] = value\r\n return this\r\n }\r\n\r\n // 只传递 prop 参数,则返回对应的属性值\r\n return attrs[prop]\r\n } else if (isObject(prop)) {\r\n // 批量更新配置信息\r\n extend(attrs, prop)\r\n\r\n return this\r\n } else if (arguments.length === 0) {\r\n // 不传递参数,直接返回整个\r\n return attrs\r\n }\r\n\r\n return this\r\n }\r\n\r\n render() {\r\n return this\r\n }\r\n\r\n destroy() {\r\n this.removeListeners()\r\n return this\r\n }\r\n\r\n reload(options) {\r\n this.destroy().initialize(this.attr(options))\r\n return this\r\n }\r\n\r\n $emit(event, data) {\r\n publish(event, data)\r\n return this\r\n }\r\n\r\n $on(event, callback) {\r\n subscribe(event, callback, this)\r\n return this\r\n }\r\n\r\n $off(event, callback) {\r\n unsubscribe(event, callback)\r\n return this\r\n }\r\n\r\n addListeners() {\r\n return this\r\n }\r\n\r\n removeListeners() {\r\n return this\r\n }\r\n}\r\n\r\nexport default Base\r\n","import hasOwn from './hasOwn'\n\n/**\n * 扩展对象\n * ========================================================================\n * @method extend\n * @param {Object} origin\n * @param {Object} source\n */\nconst extend = (origin, source) => {\n const keys = Object.keys(source)\n\n keys.forEach((prop) => {\n if (hasOwn(source, prop)) {\n origin[prop] = source[prop]\n }\n })\n}\n\nexport default extend\n","import _subscribers from './_subscribers'\nimport isFunction from '../types/isFunction'\nimport guid from '../lang/guid'\n\n/**\n * 订阅主题,并给出处理器函数\n * ========================================================================\n * @method on\n * @param {String} topic - (必须)主题名称\n * @param {Function} handler - (必须)主题的处理器函数\n * @param {Object} [context] - (可选)指定 this 执行上下文\n * @return {String} - 唯一的 token 字符串,例如:'guid-1'。\n */\nconst on = (topic, handler, context = null) => {\n const token = guid()\n let subject = typeof topic === 'symbol' ? topic.toString() : topic\n\n if (!isFunction(handler)) {\n return ''\n }\n\n /* istanbul ignore else */\n if (!_subscribers[subject]) {\n _subscribers[subject] = []\n }\n\n _subscribers[subject].push({\n topic: subject,\n callback: handler,\n context,\n token\n })\n\n return token\n}\n\nexport default on\n","import isObject from './isObject'\n\n/**\n * 检测数据是否为 HTMLElement DOM 节点\n * ========================================================================\n * @method isElement\n * @param {*} o\n * @returns {boolean}\n */\nconst isElement = (o) => {\n return !!(isObject(o) && o.nodeName && o.tagName && o.nodeType === 1)\n}\n\nexport default isElement\n","import isFunction from '../types/isFunction'\n\n/**\n * later - 延迟执行方法\n * ========================================================================\n * @method later\n * @param {Function} fn\n * @param {Number} [delay]\n * @returns {number|boolean}\n */\nconst later = (fn, delay = 300) => {\n if (!isFunction(fn)) {\n return false\n }\n\n return setTimeout(() => {\n fn()\n }, delay)\n}\n\nexport default later\n","export const CAPTURE_EVENTS = [\n 'focusout',\n 'blur',\n 'focusin',\n 'focus',\n 'load',\n 'unload',\n 'mouseenter',\n 'mouseleave'\n]\n","import { CAPTURE_EVENTS } from './enum'\nimport _delete from './_delete'\n\n/**\n * (私有方法)取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method _off\n * @param {HTMLElement} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} fn - (必须)事件处理器回调函数\n * @private\n */\nconst _off = (el, type, fn) => {\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n /* istanbul ignore else */\n if (fn._delegateListener) {\n fn = fn._delegateListener\n delete fn._delegateListener\n }\n\n // 移除缓存的 _listeners 数据\n _delete(el, type, fn)\n\n el.removeEventListener(type, fn, capture)\n}\n\nexport default _off\n","/**\n * 删除 DOM 元素缓存的 _listeners 数据\n * ========================================================================\n * @method _delete\n * @param {HTMLElement} el - 要删除 listener 的 DOM 元素\n * @param {String} type - 事件类型(名称)\n * @param {Function} [fn] - 事件处理器回调函数\n */\nconst _delete = function (el, type, fn) {\n const listeners = el._listeners\n let index = -1\n\n if (listeners.length < 1) {\n return false\n }\n\n // 移除缓存的 _listeners 数据\n listeners.forEach((listener, i) => {\n const handler = listener.fn\n\n if (type === listener.type) {\n index = i\n\n if (handler === fn) {\n index = i\n }\n }\n })\n\n /* istanbul ignore else */\n if (index > -1) {\n listeners.splice(index, 1)\n }\n}\n\nexport default _delete\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\nimport getListeners from './getListeners'\nimport _off from './_off'\n\n/**\n * 销毁(type 类型的)代理事件绑定\n * ========================================================================\n * 1. 设置了事件类型 type,则销毁指定类型的事件绑定,否则清除所有代理事件绑定\n * 2. recurse 设置为 true,递归销毁子节点全部事件绑定\n * ========================================================================\n * @method purgeElement\n * @param {HTMLElement|String} el - (必须)DOM 元素或者其选择器\n * @param {String|Boolean} type - (必须)事件类型\n * @param {Boolean} [recurse] - (可选)是否递归销毁子节点所有事件绑定\n */\nconst purgeElement = function (el, type, recurse = false) {\n const $element = isString(el) ? document.querySelector(el) : el\n const $children = $element.childNodes\n const listeners = getListeners($element, type)\n\n listeners.forEach((listener) => {\n _off($element, listener.type, listener.fn)\n })\n\n if (\n (recurse || type === true || arguments.length === 1) &&\n $element &&\n $children\n ) {\n $children.forEach(($child) => {\n if (isElement($child)) {\n purgeElement($child, type, recurse)\n }\n })\n }\n}\n\nexport default purgeElement\n","import isString from '../types/isString'\n\n/**\n * 获取 DOM 元素(type 事件类型)事件绑定信息\n * ========================================================================\n * 如果设置了事件类型 type, 则返回指定类型的事件绑定信息,否则返回所有事件绑定信息\n * ========================================================================\n * @methods getListeners\n * @param {HTMLElement} el - (必须)要获取事件绑定信息的 DOM 元素\n * @param {String} [type] - (可选)事件类型\n * @returns {Array} - 已绑定的事件信息\n */\nconst getListeners = (el, type) => {\n let listeners = el._listeners || []\n\n if (isString(type) && type) {\n listeners = listeners.filter((listener) => {\n return listener.type === type\n })\n }\n\n return listeners\n}\n\nexport default getListeners\n","import purgeElement from './purgeElement'\nimport isFunction from '../types/isFunction'\nimport _off from './_off'\n\n/**\n * 取消 type 类型的代理事件绑定\n * ========================================================================\n * 如果没有设置 handler,则销毁 this.$options 绑定的所有符合 type 事件类型的事件绑定\n * ========================================================================\n * @method off\n * @param {HTMLElement|Object} el - (必须)取消事件绑定的 DOM 元素\n * @param {String} type - (必须)事件类型\n * @param {Function} [fn] - (可选)事件处理器回调函数\n */\nconst off = (el, type, fn) => {\n // 如果不设置 fn 参数,默认清除 el 元素上绑定的所有事件处理器\n if (!isFunction(fn)) {\n return purgeElement(el, type)\n }\n\n _off(el, type, fn)\n}\n\nexport default off\n","import isFunction from '../types/isFunction'\nimport off from './off'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定事件\n * ========================================================================\n * @method at\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (必须) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst at = (el, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n const listener = function (evt) {\n let overrideContext = context || el\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n\n if (!isFunction(fn)) {\n return false\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default at\n","/**\n * 获取 options 节点下匹配 selector 选择器的 DOM 节点\n * ========================================================================\n * Element.matches() 方法可以用来判断 DOM 元素是否与给定的选择器匹配,事件代理判断是\n * 否触发绑定的代理事件回调函数,关键就是使用 Element.matches() 辨别当前事件触发的目\n * 标 DOM 元素是否为事件代理所期望触发的目标。\n * ========================================================================\n * @method matches\n * @see https://developer.mozilla.org/en-US/docs/web/api/element/matches\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)匹配 DOM 元素的选择器\n * @returns {Boolean}\n */\nconst matches = (el, selector = '') => {\n const sel = selector.replace(/^>/i, '')\n\n if (!selector || !sel || !el) {\n return false\n }\n\n /* istanbul ignore else */\n if (el.matches) {\n return el.matches(sel)\n } else if (el.msMatchesSelector) {\n return el.msMatchesSelector(sel)\n } else {\n return false\n }\n}\n\nexport default matches\n","/**\n * 获取 DOM 元素的父节点\n * ========================================================================\n * @method getParentOrHost\n * @param {*|HTMLElement} el - (必须)要获取父节点的 DOM 元素\n * @returns {*|HTMLElement}\n */\nconst getParentOrHost = (el) => {\n return el.host && el !== document && el.host.nodeType\n ? el.host\n : el.parentNode\n}\n\nexport default getParentOrHost\n","import closest from '../dom/closest'\nimport off from './off'\nimport getTarget from './getTarget'\n\nimport { CAPTURE_EVENTS } from './enum'\n\n/**\n * 绑定代理事件\n * ========================================================================\n * @method on\n * @param {HTMLElement|String|Object} el - (必须)绑定代理事件的 DOM 节点\n * @param {String} selector - (必须)事件代理目标 DOM 元素的选择器\n * @param {String|Function} type - (必须)事件类型或者事件处理器回调函数\n * @param {Function|Object} fn - (可选) 事件处理器回调函数或者传递给事件处理器回调函数的数据对象\n * @param {Object|Boolean} [data] - (可选)传递给事件处理器回调函数的数据对象或者事件处理器回调函数的 this 上下文指向,\n * @param {Object|Boolean} [context] - (可选)事件处理器回调函数的 this 上下文指向,或者是否仅触发一次\n * 当设置为 true 时,则事件处理器回调函数的 this 上下文指向为 data 对象\n * @param {Boolean} once - (可选)是否仅触发一次\n */\nconst on = (el, selector, type, fn, data, context, once = false) => {\n // CAPTURE_EVENTS 中的特殊事件,采用事件捕获模型\n const capture = CAPTURE_EVENTS.indexOf(type) > -1\n\n const listener = function (evt) {\n const target = getTarget(evt)\n // 通过 Element.matches 方法获得点击的目标元素\n const delegateTarget = closest(target, selector, el)\n let overrideContext = context || el\n\n evt.delegateTarget = delegateTarget\n\n // 当设置为 true 时,则事件处理器回调函数的\n // this 上下文指向为 data 对象\n if (context === true) {\n overrideContext = data\n }\n\n /* istanbul ignore else */\n if (delegateTarget) {\n // 仅触发一次\n /* istanbul ignore else */\n if (once === true) {\n off(el, type, listener)\n }\n\n fn.call(overrideContext, evt, data)\n }\n }\n\n if (!el._listeners) {\n el._listeners = []\n }\n\n // 缓存 options 元素绑定的事件处理器\n el._listeners.push({\n el,\n selector,\n type,\n fn: listener,\n data,\n context,\n capture\n })\n\n // 缓存包装后的事件处理器\n fn._delegateListener = listener\n\n el.addEventListener(type, listener, capture)\n}\n\nexport default on\n","import resolveTextNode from '../dom/resolveTextNode'\n\n/**\n * 返回触发事件的 target DOM 元素\n * ========================================================================\n * @method getTarget\n * @param {Event} evt - Event 对象\n * @return {HTMLElement} - Event 对象的 target DOM 元素\n */\nconst getTarget = function (evt) {\n const target = evt.target\n\n return resolveTextNode(target)\n}\n\nexport default getTarget\n","/**\n * 在某些情况下,某些浏览器(例如:Safari 浏览器)会返回实际的目标元素内部的文本节点。\n * resolveTextNode() 方法则会返回实际的目标节点。\n * ========================================================================\n * @method resolveTextNode\n * @param {HTMLElement|Text} el - 要解析的节点\n * @return {*|HTMLElement} - 实际的目标 DOM 节点\n */\nconst resolveTextNode = function (el) {\n if (el && el.nodeType === 3) {\n return el.parentNode\n }\n\n return el\n}\n\nexport default resolveTextNode\n","import matches from './matches'\nimport getParentOrHost from './getParentOrHost'\n\n/**\n * 获取 options 元素父元素最近的包含 selector 选择器的元素\n * ========================================================================\n * @method closest\n * @param {HTMLElement} el - (必须)DOM 元素\n * @param {String} selector - (必须)DOM 元素的选择其\n * @param {HTMLElement} [ctx] - (必须)比对的 DOM 元素\n * @param {Boolean} [includeCTX] - (必须)是否包含 context DOM 元素\n * @returns {null|HTMLElement} - 返回最接近的 DOM 元素\n */\nconst closest = (el, selector, ctx, includeCTX) => {\n const context = ctx || document\n\n if (!el) {\n return null\n }\n\n do {\n /* istanbul ignore else */\n if (\n (selector != null &&\n (selector.startsWith('>')\n ? el.parentNode === context && matches(el, selector)\n : matches(el, selector))) ||\n (includeCTX && el === context)\n ) {\n return el\n }\n\n /* istanbul ignore else */\n if (el === context) {\n break\n }\n\n /* jshint boss:true */\n } while ((el = getParentOrHost(el)))\n}\n\nexport default closest\n","import toString from '../lang/toString'\n\n/**\n * 检测数据是否为 Array 类型\n * ========================================================================\n * @method isArray\n * @param {*} o\n * @returns {boolean}\n */\nconst isArray = (o) => {\n if (Array.isArray) {\n return Array.isArray(o)\n } else {\n return toString(o) === '[object Array]'\n }\n}\n\nexport default isArray\n","import isObject from './isObject'\r\nimport isElement from './isElement'\r\nimport isHTMLCollection from './isHTMLCollection'\r\nimport isFragment from './isFragment'\r\nimport isTextNode from './isTextNode'\r\n\r\nconst isDOM = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (isElement(el) || isHTMLCollection(el) || isFragment(el) || isTextNode(el))\r\n )\r\n}\r\n\r\nexport default isDOM\r\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isHTMLCollection = (el) => {\r\n return !!(isObject(el) && toString(el) === '[object NodeList]')\r\n}\r\n\r\nexport default isHTMLCollection\r\n","import toString from '../lang/toString'\nimport isObject from './isObject'\n\nconst isFragment = (fragment) => {\n return !!(\n isObject(fragment) && toString(fragment) === '[object DocumentFragment]'\n )\n}\n\nexport default isFragment\n","import toString from '../lang/toString'\r\nimport isObject from './isObject'\r\n\r\nconst isTextNode = (el) => {\r\n return !!(\r\n isObject(el) &&\r\n (toString(el) === '[object Text]' || (el.tagName && el.nodeType === 3))\r\n )\r\n}\r\n\r\nexport default isTextNode\r\n","import hasOwn from '../lang/hasOwn'\nimport isObject from '../types/isObject'\nimport isString from '../types/isString'\nimport isArray from '../types/isArray'\nimport isDOM from '../types/isDOM'\nimport setAttribute from './setAttribute'\n\n/**\n * 创建 DOM 节点,并添加属性和子节点\n * ========================================================================\n * @method createElement\n * @param {String} tagName - 标签名称\n * @param {Object|Array} attrs - 属性对象或者子节点\n * @param {Array} [children] - 子节点数组\n * @returns {HTMLElement}\n */\nconst createElement = (tagName, attrs, children) => {\n const $fragment = document.createDocumentFragment()\n const $el = document.createElement(tagName)\n const isValidChild = (child) => {\n return isDOM(child) || isString(child)\n }\n const append = (child) => {\n let $child\n\n if (!isValidChild(child)) {\n return false\n }\n\n if (isDOM(child)) {\n $child = child\n } else if (isString(child)) {\n $child = document.createTextNode(child)\n }\n\n $fragment.appendChild($child)\n }\n\n if (isObject(attrs)) {\n Object.keys(attrs).forEach((attr) => {\n if (hasOwn(attrs, attr)) {\n setAttribute($el, attr, attrs[attr])\n }\n })\n } else if (isArray(attrs) && attrs.every((attr) => isValidChild(attr))) {\n attrs.forEach((child) => {\n append(child)\n })\n }\n\n if (isArray(children)) {\n children.forEach((child) => {\n append(child)\n })\n } else {\n append(children)\n }\n\n $el.appendChild($fragment)\n\n return $el\n}\n\nexport default createElement\n","/**\n * 给 DOM 节点设置属性/值\n * ========================================================================\n * @method setAttribute\n * @param {HTMLElement} el - DOM 节点\n * @param {String} attr - 属性名称\n * @param {String|Number|Boolean} value - 属性值\n */\nconst setAttribute = (el, attr, value) => {\n let tagName = el.tagName.toLowerCase()\n\n switch (attr) {\n case 'style':\n el.style.cssText = value\n break\n case 'value':\n if (tagName === 'input' || tagName === 'textarea') {\n el.value = value\n } else {\n el.setAttribute(attr, value)\n }\n break\n case 'className':\n el.className = value\n break\n default:\n el.setAttribute(attr, value)\n break\n }\n}\n\nexport default setAttribute\n","/**\n * 返回给定值的平方值\n * ========================================================================\n * @method easeInQuad\n * @param {Number} x\n * @returns {number}\n */\nconst easeInQuad = (x) => {\n return x * x\n}\n\nexport default easeInQuad\n","import isString from '../types/isString'\nimport isElement from '../types/isElement'\n\n/**\n * 通过给的 scrollElement 参数,获取滚动 DOM 元素\n * ========================================================================\n * @method _getScrollElement\n * @param {String|HTMLElement} scrollElement\n * @returns {Element}\n * @private\n */\nconst _getScrollElement = (scrollElement = null) => {\n let $rootElements\n let $scrollElement\n\n if (!scrollElement) {\n $rootElements = document.querySelectorAll('html,body')\n $scrollElement =\n $rootElements[0].scrollTop - $rootElements[1].scrollTop >= 0\n ? $rootElements[0]\n : $rootElements[1]\n } else {\n if (isString(scrollElement)) {\n $scrollElement = document.querySelector(scrollElement)\n } else if (isElement(scrollElement)) {\n $scrollElement = scrollElement\n }\n }\n\n return $scrollElement\n}\n\nexport default _getScrollElement\n","import isElement from '../types/isElement'\n/**\n * 检测 DOM 节点是否包含名为 className 的样式\n * ========================================================================\n * @method hasClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst hasClass = (el, className) => {\n const pattern = new RegExp('(\\\\s|^)' + className + '(\\\\s|$)')\n let allClass\n let classList\n\n if (!isElement(el)) {\n return false\n }\n\n allClass = el.className\n\n if (!allClass) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.contains) {\n return el.classList.contains(className)\n }\n\n return !!pattern.exec(allClass)\n}\n\nexport default hasClass\n","import hasClass from './hasClass'\n\n/**\n * 给 DOM 节点添加名为 className 的样式\n * ========================================================================\n * @method addClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst addClass = (el, className) => {\n let classList\n let allClass\n\n if (hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.add) {\n classList.add(className)\n } else {\n allClass = el.className\n allClass += allClass.length > 0 ? ' ' + className : className\n el.className = allClass\n }\n}\n\nexport default addClass\n","import trim from '../lang/trim'\nimport hasClass from './hasClass'\n\n/**\n * 移除 DOM 节点的 className 样式\n * ========================================================================\n * @method removeClass\n * @param {HTMLElement} el - DOM 节点\n * @param {String} className - 样式名称\n * @returns {Boolean}\n */\nconst removeClass = (el, className) => {\n let allClass = el.className\n let classList\n\n if (!allClass || !hasClass(el, className)) {\n return false\n }\n\n classList = el.classList\n\n if (classList?.remove) {\n classList.remove(className)\n } else {\n allClass = trim(allClass.replace(className, ''))\n el.className = allClass\n }\n}\n\nexport default removeClass\n","import isString from '../types/isString'\n\n/**\n * 清楚字符串起始位置所有的空格\n * ========================================================================\n * @method trim\n * @param {string} str\n * @returns {string|Boolean}\n */\nconst trim = (str) => {\n if (!isString(str)) {\n return false\n }\n return str.replace(/(^\\s+)|(\\s+$)/g, '')\n}\n\nexport default trim\n","/**\n * 获取 DOM 节点相对于窗口的 left (纵坐标)值\n * ========================================================================\n * @method offsetTop\n * @param {HTMLElement} el - DOM 节点\n * @returns {Number}\n */\nconst offsetTop = (el) => {\n let top = el.offsetTop\n\n if (el.offsetParent !== null) {\n top += offsetTop(el.offsetParent)\n }\n\n return top\n}\n\nexport default offsetTop\n","/**\r\n * 获取HTML元素的某个CSS样式值\r\n * ====================================================\r\n * @param el\r\n * @param ruleName\r\n * @returns {*}\r\n */\r\nconst getStyle = (el, ruleName) => {\r\n return getComputedStyle(el)[ruleName]\r\n}\r\n\r\nexport default getStyle\r\n","const setProperty = (prop, value) => {\r\n const documentElement = document.documentElement\r\n documentElement.style.setProperty(prop, value)\r\n}\r\n\r\nexport default setProperty\r\n","import isArray from '../types/isArray'\r\n\r\n/**\r\n * 深拷贝对象函数\r\n * ========================================================================\r\n * @methods cloneDeep\r\n * @param {Object} obj - 深拷贝的对象\r\n * @returns {Array|Object|*}\r\n *\r\n * @example\r\n * const arr = cloneDeep([2,3,4,6])\r\n * => [2,3,4,6]\r\n */\r\nconst cloneDeep = (obj) => {\r\n let clone\r\n\r\n if (obj === null) {\r\n return null\r\n }\r\n\r\n clone = Object.assign({}, obj)\r\n\r\n Object.keys(clone).forEach((key) => {\r\n return (clone[key] =\r\n typeof obj[key] === 'object' ? cloneDeep(obj[key]) : obj[key])\r\n })\r\n\r\n if (isArray(obj)) {\r\n clone.length = obj.length\r\n\r\n return Array.from(clone)\r\n }\r\n\r\n return clone\r\n}\r\n\r\nexport default cloneDeep\r\n","import Base from './base'\n\nimport isString from './utils/types/isString'\nimport isFunction from './utils/types/isFunction'\nimport isElement from './utils/types/isElement'\nimport later from './utils/lang/later'\nimport at from './utils/event/at'\nimport on from './utils/event/on'\nimport off from './utils/event/off'\nimport stop from './utils/event/stop'\nimport createElement from './utils/dom/createElement'\nimport scrollTo from './utils/dom/scrollTo'\nimport addClass from './utils/dom/addClass'\nimport intersection from './utils/dom/intersection'\nimport removeClass from './utils/dom/removeClass'\nimport offsetTop from './utils/dom/offsetTop'\nimport getStyle from './utils/dom/getStyle'\nimport setProperty from './utils/dom/setProperty'\nimport cloneDeep from './utils/lang/cloneDeep'\n\nimport _getScrollElement from './utils/dom/_getScrollElement'\nimport _paintChapters from './_paintChapters'\n\nclass Chapters extends Base {\n constructor(options) {\n super()\n\n this.attrs = cloneDeep(Chapters.DEFAULTS)\n this.$el = null\n this.$title = null\n this.$main = null\n this.$list = null\n this.$placeholder = null\n this.$parentElement = null\n this.$scrollElement = null\n this.chapters = []\n this.closed = false\n this.active = 0\n this.offsetTop = 0\n this.offsetWidth = 0\n this.$active = null\n this.scrollTimer = null\n this.resizeTimer = null\n this.playing = false\n this.Observer = null\n\n if (options) {\n this.initialize(options)\n }\n }\n\n initialize(options) {\n let created\n let parentElement\n let scrollElement\n let $parent\n\n this.attr(options)\n created = this.attr('created')\n parentElement = this.attr('parentElement')\n scrollElement = this.attr('scrollElement')\n\n if (isString(parentElement)) {\n $parent = document.querySelector(parentElement)\n } else if (isElement(parentElement)) {\n $parent = parentElement\n }\n this.$parentElement = $parent\n this.$scrollElement = _getScrollElement(scrollElement)\n\n this.chapters = this.attr('chapters')\n this.closed = this.attr('closed')\n this.active = this.attr('active')\n\n if (isFunction(created)) {\n created.call(this)\n }\n\n if (this.chapters.length < 1) {\n return this\n }\n\n this.render().addListeners()\n\n this.$active = document.querySelector(`#chapter-${this.active}`)\n\n return this\n }\n\n isClosed() {\n return this.closed\n }\n\n isSticky() {\n const position = this.attr('position')\n return position === 'sticky'\n }\n\n isFixed() {\n const position = this.attr('position')\n return position === 'fixed'\n }\n\n isInside() {\n return this.isFixed() || this.isSticky()\n }\n\n isOutside() {\n return !this.isInside()\n }\n\n _paintEdge() {\n const $fragment = document.createDocumentFragment()\n const STICKY = 'outline-chapters_sticky'\n const HIDDEN = 'outline-chapters_hidden'\n const title = this.attr('title')\n const customClass = this.attr('customClass')\n const $parentElement = this.$parentElement\n const contents = []\n let $title = null\n let $el\n let $main\n let $list\n let $placeholder\n\n if (!$parentElement) {\n return this\n }\n\n if (this.isInside() && title) {\n $title = createElement(\n 'h2',\n {\n className: 'outline-chapters__title'\n },\n [title]\n )\n this.$title = $title\n contents.push($title)\n }\n\n $list = createElement(\n 'ul',\n {\n // 为优化性能,添加了 _fixed 和 _hidden\n // fixed 为了让 $list 脱离流布局\n // hidden 让 $list 不可见\n className: `outline-chapters__list`\n },\n ['']\n )\n this.$list = $list\n\n $placeholder = createElement(\n 'div',\n {\n className: 'outline-chapters__placeholder'\n },\n ['']\n )\n this.$placeholder = $placeholder\n\n $main = createElement(\n 'div',\n {\n className: 'outline-chapters__main'\n },\n [$list, $placeholder]\n )\n this.$main = $main\n contents.push($main)\n\n $el = createElement(\n 'nav',\n {\n id: 'outline-chapters',\n className: `outline-chapters ${HIDDEN}`\n },\n contents\n )\n this.$el = $el\n\n if (this.isSticky()) {\n this.calculateStickyHeight()\n addClass($el, STICKY)\n }\n\n if (customClass) {\n addClass($el, customClass)\n }\n $fragment.appendChild($el)\n $parentElement.appendChild($fragment)\n\n return this\n }\n\n render() {\n const HIDDEN = 'outline-chapters_hidden'\n const showCode = this.attr('showCode')\n const mounted = this.attr('mounted')\n const $parentElement = this.$parentElement\n const chapters = this.chapters\n let $el\n let $list\n\n if (!$parentElement || chapters.length < 1) {\n return this\n }\n\n this._paintEdge()\n\n $el = this.$el\n $list = this.$list\n _paintChapters($list, chapters, showCode)\n removeClass($el, HIDDEN)\n this.positionPlaceholder(this.active)\n\n this.offsetTop = offsetTop($el)\n this.offsetWidth = $el.offsetWidth\n\n if (this.isFixed()) {\n this.sticky()\n setProperty('--outline-chapters-width', `${this.offsetWidth}px`)\n }\n\n if (isFunction(mounted)) {\n mounted.call(this)\n }\n\n this.onObserver()\n\n return this\n }\n\n positionPlaceholder(index) {\n const $main = this.$main\n const $list = this.$list\n const $placeholder = this.$placeholder\n const $anchor = $list.querySelector('.outline-chapters__anchor')\n const mainPaddingTop = parseInt(getStyle($main, 'padding-top'), 10)\n const mainBorderTop = parseInt(getStyle($main, 'border-top-width'), 10)\n const placeholderPaddingTop = parseInt(getStyle($list, 'padding-top'), 10)\n const placeholderMarginTop = parseInt(getStyle($list, 'margin-top'), 10)\n const placeholderBorderTop = parseInt(\n getStyle($list, 'border-top-width'),\n 10\n )\n let height = $anchor.offsetHeight\n let offsetTop = 0\n let top\n\n if (mainPaddingTop) {\n offsetTop += mainPaddingTop\n }\n\n if (placeholderPaddingTop) {\n offsetTop += placeholderPaddingTop\n }\n\n if (placeholderMarginTop) {\n offsetTop += placeholderMarginTop\n }\n\n if (mainBorderTop) {\n offsetTop += mainBorderTop\n }\n\n if (placeholderBorderTop) {\n offsetTop += placeholderBorderTop\n }\n\n top = height * index\n // top:calc(${offsetTop}px + ${top}px);\n $placeholder.style.cssText = `transform: translateY(${\n offsetTop + top\n }px);height:${height}px;`\n\n return this\n }\n\n highlight(id) {\n const $anchor = this.$el.querySelector(`#chapter__anchor-${id}`)\n const HIGHLIGHT = 'outline-chapters_active'\n\n if (!$anchor) {\n return this\n }\n\n if (this.$active) {\n removeClass(this.$active, HIGHLIGHT)\n }\n\n this.active = parseInt($anchor.getAttribute('data-id'), 10)\n this.$active = $anchor\n addClass(this.$active, HIGHLIGHT)\n\n this.positionPlaceholder(this.active)\n\n return this\n }\n\n sticky() {\n const afterSticky = this.attr('afterSticky')\n const FIXED = 'outline-chapters_fixed'\n const $el = this.$el\n const top = this.offsetTop\n const scrollTop = this.$scrollElement.scrollTop\n let isStickying\n\n if (!this.isFixed()) {\n return this\n }\n\n isStickying = scrollTop >= top\n\n if (isStickying) {\n addClass($el, FIXED)\n } else {\n removeClass($el, FIXED)\n }\n\n if (isFunction(afterSticky)) {\n afterSticky.call(this, this.isClosed(), isStickying)\n }\n\n return this\n }\n\n calculateStickyHeight() {\n const documentElement = document.documentElement\n const height = Math.max(\n documentElement.clientHeight || 0,\n window.innerHeight || 0\n )\n setProperty('--outline-sticky-height', `${height}px`)\n return this\n }\n\n scrollTo(top, after) {\n const el = this.$scrollElement\n\n scrollTo(el, top, after)\n\n return this\n }\n\n show() {\n const FOLDED = 'outline-chapters_folded'\n const HIDDEN = 'outline-chapters_hidden'\n const opened = this.attr('afterOpened')\n const $el = this.$el\n const $parent = this.$parentElement\n\n if (this.isInside()) {\n removeClass($parent, HIDDEN)\n removeClass($el, HIDDEN)\n later(() => {\n removeClass($parent, FOLDED)\n removeClass($el, FOLDED)\n }, 30)\n } else {\n removeClass($el, HIDDEN)\n }\n this.closed = false\n\n if (isFunction(opened)) {\n opened.call(this)\n }\n\n return this\n }\n\n hide() {\n const FOLDED = 'outline-chapters_folded'\n const HIDDEN = 'outline-chapters_hidden'\n const closed = this.attr('afterClosed')\n const $el = this.$el\n const $parent = this.$parentElement\n\n if (this.isInside()) {\n addClass($parent, FOLDED)\n addClass($el, FOLDED)\n later(() => {\n addClass($parent, HIDDEN)\n addClass($el, HIDDEN)\n })\n } else {\n addClass($el, HIDDEN)\n }\n this.closed = true\n\n if (isFunction(closed)) {\n closed.call(this)\n }\n\n return this\n }\n\n toggle() {\n const afterToggle = this.attr('afterToggle')\n const top = this.offsetTop\n const scrollTop = this.$scrollElement.scrollTop\n let isStickying\n\n if (this.isClosed()) {\n this.show()\n } else {\n this.hide()\n }\n\n if (isFunction(afterToggle)) {\n later(() => {\n isStickying = scrollTop >= top\n afterToggle.call(this, this.isClosed(), isStickying)\n })\n }\n\n return this\n }\n\n destroy() {\n const beforeDestroy = this.attr('beforeDestroy')\n const afterDestroy = this.attr('afterDestroy')\n\n if (isFunction(beforeDestroy)) {\n beforeDestroy.call(this)\n }\n\n this.removeListeners()\n this.$parentElement.removeChild(this.$el)\n\n this.attr(Chapters.DEFAULTS)\n this.$el = null\n this.$title = null\n this.$main = null\n this.$list = null\n this.$placeholder = null\n this.$parentElement = null\n this.$scrollElement = null\n this.chapters = []\n this.active = 0\n this.offsetTop = 0\n this.$active = null\n this.closed = false\n\n if (this.scrollTimer) {\n clearTimeout(this.scrollTimer)\n this.scrollTimer = null\n }\n\n if (this.resizeTimer) {\n clearTimeout(this.resizeTimer)\n this.resizeTimer = null\n }\n\n if (isFunction(afterDestroy)) {\n afterDestroy.call(this)\n }\n\n if (this.Observer) {\n this.Observer = null\n }\n\n return this\n }\n\n onObserver() {\n const selector = this.attr('selector')\n let timer = null\n\n this.Observer = intersection(\n ($heading) => {\n const id = $heading.getAttribute('data-id')\n\n if (this.playing) {\n return false\n }\n\n if (timer) {\n clearTimeout(timer)\n }\n\n timer = later(() => {\n this.highlight(id)\n }, 100)\n },\n {\n selector,\n context: this\n }\n )\n\n return this\n }\n\n onSelect(evt) {\n const stickyHeight = this.attr('stickyHeight')\n const $anchor = evt.delegateTarget\n const id = $anchor.getAttribute('data-id')\n const headingId = $anchor.href.split('#')[1]\n const $heading = document.querySelector(`#${headingId}`)\n const top = offsetTop($heading) - (stickyHeight + 10)\n const min = 0\n const max = this.$scrollElement.scrollHeight\n const afterScroll = this.attr('afterScroll')\n const after = () => {\n if (isFunction(afterScroll)) {\n afterScroll.call(this, 'chapter')\n }\n\n later(() => {\n this.playing = false\n this.$emit('toolbar:update', {\n top,\n min,\n max\n })\n })\n }\n\n this.playing = true\n if (this.isFixed()) {\n this.sticky()\n later(() => {\n this.scrollTo(top, after)\n this.highlight(id)\n }, 10)\n } else {\n this.scrollTo(top, after)\n this.highlight(id)\n }\n\n stop(evt)\n\n return this\n }\n\n onScroll() {\n const $scrollElement = this.$scrollElement\n\n if (this.scrollTimer) {\n clearTimeout(this.scrollTimer)\n }\n\n this.scrollTimer = later(() => {\n const top = $scrollElement.scrollTop\n const min = 0\n const max = $scrollElement.scrollHeight - $scrollElement.clientHeight\n\n if (this.isFixed()) {\n this.sticky()\n }\n\n this.$emit('toolbar:update', {\n top,\n min,\n max\n })\n }, 100)\n\n return this\n }\n\n onResize() {\n if (this.resizeTimer) {\n clearTimeout(this.resizeTimer)\n }\n\n this.resizeTimer = later(() => {\n this.calculateStickyHeight()\n })\n\n return this\n }\n\n addListeners() {\n const $el = this.$el\n const $scrollElement = this.$scrollElement\n const tagName = $scrollElement.tagName.toLowerCase()\n let $element = $scrollElement\n\n if (tagName === 'html' || tagName === 'body') {\n $element = window\n }\n\n on($el, '.outline-chapters__anchor', 'click', this.onSelect, this, true)\n at($element, 'scroll', this.onScroll, this, true)\n if (this.isSticky()) {\n at(window, 'resize', this.onResize, this, true)\n }\n\n return this\n }\n\n removeListeners() {\n const selector = this.attr('selector')\n const $el = this.$el\n const $scrollElement = this.$scrollElement\n const tagName = $scrollElement.tagName.toLowerCase()\n let $element = $scrollElement\n\n if (tagName === 'html' || tagName === 'body') {\n $element = window\n }\n\n off($el, 'click', this.onSelect)\n off($element, 'scroll', this.onScroll)\n\n if (this.isSticky()) {\n at(window, 'resize', this.onResize)\n }\n\n if (this.Observer) {\n document.querySelectorAll(selector).forEach((section) => {\n this.Observer.unobserve(section)\n })\n }\n\n return this\n }\n}\n\nChapters.DEFAULTS = {\n parentElement: '',\n scrollElement: '',\n selector: '.outline-heading',\n active: 0,\n closed: false,\n showCode: true,\n position: 'relative',\n stickyHeight: 0,\n chapters: [],\n created: null,\n mounted: null,\n afterClosed: null,\n afterOpened: null,\n afterScroll: null,\n beforeDestroy: null,\n afterDestroy: null,\n afterSticky: null\n}\n\nexport default Chapters\n","import createElement from './utils/dom/createElement'\n\nconst _paintChapters = ($list, chapters, showCode = false) => {\n const byId = (id) => document.querySelector(`#${id}`)\n\n chapters.forEach((chapter) => {\n const pid = chapter.pid\n const id = chapter.id\n const rel = chapter.rel\n const $text = createElement(\n 'span',\n {\n className: 'outline-chapters__text'\n },\n [chapter.text]\n )\n const $link = createElement(\n 'a',\n {\n id: `chapter__anchor-${id}`,\n className: 'outline-chapters__anchor',\n href: '#' + rel,\n rel: rel,\n 'data-id': id\n },\n [$text]\n )\n let $code\n let $li\n let $ul\n let $parent\n\n if (showCode) {\n $code = createElement(\n 'span',\n {\n className: 'outline-chapters__code',\n 'data-id': id\n },\n [chapter.code]\n )\n\n $link.insertBefore($code, $link.firstChild)\n }\n\n $li = createElement(\n 'li',\n {\n id: `chapter-${id}`,\n className: 'outline-chapters__item',\n 'data-id': id\n },\n [$link]\n )\n\n if (pid === -1) {\n $list.appendChild($li)\n } else {\n $parent = byId(`chapter-${pid}`)\n $ul = byId(`subject-${pid}`)\n\n if (!$ul) {\n $ul = createElement(\n 'ul',\n {\n id: 'subject-' + pid,\n className: 'outline-chapters__subject'\n },\n [$li]\n )\n\n $parent.appendChild($ul)\n } else {\n $ul.appendChild($li)\n }\n }\n })\n}\n\nexport default _paintChapters\n","import easeInQuad from '../lang/easeInQuad'\nimport isFunction from '../types/isFunction'\nimport _getScrollElement from './_getScrollElement'\n\n/**\n * 指定 rootElement DOM 节点滚动到指定 top 位置\n * ========================================================================\n * @method scrollTo\n * @param {HTMLElement|Object} [scrollElement] - (必须)要滚动的 DOM 节点\n * @param {Number} top - (必须)滚动的 scrollTop 数值\n * @param {Function} [afterStop] - (可选)滚动完成的回调函数\n */\nconst scrollTo = (scrollElement, top, afterStop) => {\n const $scrollElement = _getScrollElement(scrollElement)\n let scrollTop = $scrollElement.scrollTop\n let step = 0\n const distance = top - scrollTop\n const MAX_HEIGHT = $scrollElement.scrollHeight\n const MAX_TOP = top - MAX_HEIGHT <= 0 ? top : MAX_HEIGHT\n const stop = (top) => {\n if (isFunction(afterStop)) {\n afterStop(top)\n }\n\n return false\n }\n const play = () => {\n step += 1\n\n // 向上滚动\n if (distance < 0) {\n scrollTop -= easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop <= top) {\n $scrollElement.scrollTop = top\n return stop(top)\n }\n } else {\n scrollTop += easeInQuad(step)\n $scrollElement.scrollTop = scrollTop\n\n if (scrollTop >= MAX_TOP) {\n $scrollElement.scrollTop = MAX_TOP\n return stop(MAX_TOP)\n }\n }\n\n requestAnimationFrame(play)\n }\n\n requestAnimationFrame(play)\n}\n\nexport default scrollTo\n","import isFunction from '../types/isFunction'\nimport isElement from '../types/isElement'\n\n/**\n * 通用的 IntersectionObserver 观察者处理器\n * ========================================================================\n * @method intersection\n * @param {Function} fn\n * @param {Object} [props]\n * @param {Object|HTMLElement} [props.root]\n * @param {String} [props.selector]\n * @param {Object} [props.context]\n * @param {String} [props.attr]\n * @param {String} [props.rootMargin]\n */\nconst intersection = (fn, props = {}) => {\n const root = props.root || null\n const selector = props.selector || '.outline-heading'\n const context = props.context || null\n const rootMargin = props.rootMargin || '0px 0px -90% 0px'\n const options = {\n rootMargin: rootMargin\n }\n const Observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.intersectionRatio > 0) {\n if (isFunction(fn)) {\n fn.call(context || entry.target, entry.target)\n }\n }\n })\n }, options)\n const $root = isElement(root) ? root : document\n\n if (root) {\n options.root = root\n }\n\n $root.querySelectorAll(selector).forEach((section) => {\n Observer.observe(section)\n })\n\n return Observer\n}\n\nexport default intersection\n","/**\n * 停止事件(阻止默认行为和阻止事件的捕获或冒泡)\n * ========================================================================\n * @method stop\n * @param {Event} evt - 事件对象\n *\n * @example\n *
\n * Service\n * Help\n *
\n *\n * const $nav = document.querySelector('#nav')\n * const $service = document.querySelector('.anchor')\n *\n * on($nav, 'click', function(evt) {\n * console.log('你点击了导航栏')\n * })\n *\n * on($anchor, 'click', function(evt) {\n * console.log('tagName', this.tagName)\n *\n * // 工作台输出:'a'\n * // 不会触发事件冒泡,输出:'你点击了导航栏'\n * // 也不会切换到 href 属性的页面,阻止了点击链接的默认行为\n * stopEvent(evt)\n * })\n */\nconst stop = function (evt) {\n evt.stopPropagation()\n evt.preventDefault()\n}\n\nexport default stop\n"],"names":["isString","str","hasOwn","obj","prop","hasOwnProperty","Object","prototype","call","toString","val","apply","isFunction","isObject","o","_subscribers","_hasDirectSubscribersFor","topic","length","has","isDirect","found","position","lastIndexOf","substring","_hasSubscribers","emit","data","async","execute","forEach","subscriber","message","indexOf","callback","context","deliver","setTimeout","guid","uuid","prefix","_removeSubscriber","off","token","keys","subject","execution","j","splice","_removeSubscriberByToken","Base","constructor","options","this","attrs","initialize","attr","render","addListeners","value","origin","source","arguments","destroy","removeListeners","reload","$emit","event","publish","$on","handler","push","subscribe","$off","unsubscribe","isElement","nodeName","tagName","nodeType","later","fn","delay","CAPTURE_EVENTS","_off","el","type","capture","_delegateListener","listeners","_listeners","index","listener","i","_delete","removeEventListener","purgeElement","recurse","$element","document","querySelector","$children","childNodes","filter","getListeners","$child","at","once","evt","overrideContext","addEventListener","matches","selector","sel","replace","msMatchesSelector","getParentOrHost","host","parentNode","on","target","getTarget","delegateTarget","ctx","includeCTX","startsWith","closest","isArray","Array","isDOM","isHTMLCollection","fragment","isTextNode","createElement","children","$fragment","createDocumentFragment","$el","isValidChild","child","append","createTextNode","appendChild","toLowerCase","style","cssText","setAttribute","className","every","easeInQuad","x","_getScrollElement","scrollElement","$rootElements","$scrollElement","querySelectorAll","scrollTop","hasClass","pattern","RegExp","allClass","classList","contains","exec","addClass","add","removeClass","remove","offsetTop","top","offsetParent","getStyle","ruleName","getComputedStyle","setProperty","documentElement","cloneDeep","clone","assign","key","from","Chapters","super","DEFAULTS","$title","$main","$list","$placeholder","$parentElement","chapters","closed","active","offsetWidth","$active","scrollTimer","resizeTimer","playing","Observer","created","parentElement","$parent","isClosed","isSticky","isFixed","isInside","isOutside","_paintEdge","title","customClass","contents","id","calculateStickyHeight","showCode","mounted","byId","chapter","pid","rel","$text","text","$link","href","$code","$li","$ul","code","insertBefore","firstChild","_paintChapters","positionPlaceholder","sticky","onObserver","$anchor","mainPaddingTop","parseInt","mainBorderTop","placeholderPaddingTop","placeholderMarginTop","placeholderBorderTop","height","offsetHeight","highlight","HIGHLIGHT","getAttribute","afterSticky","FIXED","isStickying","Math","max","clientHeight","window","innerHeight","scrollTo","after","afterStop","step","distance","MAX_HEIGHT","scrollHeight","MAX_TOP","stop","play","requestAnimationFrame","show","FOLDED","HIDDEN","opened","hide","toggle","afterToggle","beforeDestroy","afterDestroy","removeChild","clearTimeout","timer","props","root","rootMargin","IntersectionObserver","entries","entry","intersectionRatio","$root","section","observe","intersection","$heading","onSelect","stickyHeight","headingId","split","afterScroll","min","stopPropagation","preventDefault","onScroll","onResize","unobserve","afterClosed","afterOpened"],"mappings":"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"} \ No newline at end of file diff --git a/docs/fixed.html b/docs/fixed.html index 6b79e096..a370b856 100644 --- a/docs/fixed.html +++ b/docs/fixed.html @@ -313,32 +313,7 @@ defaults.chapterTextFilter = (text) => { return text.replace(/\(.*?\)/, '()') } -outline = new Outline(Outline.DEFAULTS)

Properties

outline.js 重构后,对外放 4 个重要的属性:anchors、drawer、chapters 和 toolbar。它们都是独立的对象实例,提供了 outline.js 所有的能力(属性和方法)。

Outline.DEFAULTS

Description

Type:
Object

静态属性,存储的是 Outline 对象默认配置选项:

Outline.DEFAULTS = {
-  articleElement: '#article',
-  selector: 'h2,h3,h4,h5,h6',
-  title: '目录',
-  scrollElement: 'html,body',
-  position: 'relative',
-  parentElement: '#aside',
-  placement: 'rtl',
-  showCode: true,
-  anchorURL: '',
-  stickyHeight: 0,
-  homepage: '',
-  git: '',
-  tags: '',
-  issues: '',
-  tools: [],
-  print: {
-    element: '',
-    title: ''
-  },
-  customClass: '',
-  afterSticky: null,
-  afterToggle: null,
-  afterScroll: null,
-  chapterTextFilter: null
-}

attrs

Description

Type:
Object

存储的是 Outline 对象当前使用中的配置选项:

说明:建议使用 attr(prop) 方法来获取属性,避免直接调用属性。

// 设置默认配置项
+outline = new Outline(Outline.DEFAULTS)

Properties

outline.js 重构后,对外放 4 个重要的属性:anchors、drawer、chapters 和 toolbar。它们都是独立的对象实例,提供了 outline.js 所有的能力(属性和方法)。

attrs

Description

Type:
Object

存储的是 Outline 对象当前使用中的配置选项:

说明:建议使用 attr(prop) 方法来获取属性,避免直接调用属性。

// 设置默认配置项
 const outline = new Outline(Outline.DEFAULTS)
 
 // 查看全部配置信息
@@ -756,7 +731,32 @@
 
 Drawer.zIndex = 2000
 
-export default Toolbar

Methods

outline.js 的提供的方法如下:

attr([prop, value])

Description

attr() 方法用来设置或者获取初始化时配置的 attrs 信息的。

Parameters

prop
Type:
String|HTMLElement

(可选)options 中的属性名称或者要配置的 attrs 信息。

value
Type:
Any

(可选)要设置的 prop 属性的值

  • 不传递任何参数:返回完整的 attrs 配置信息;
  • 仅传递 prop:
    • String: 返回 attrs 配型信息中与 prop 对应的值;
    • Object: 用来设置 attrs 配置信息;
  • 同时传递 prop 和 value 参数:设置 attrs 配置信息中的某个属性值;

Returns

Type:
Any

配置信息 attrs 的属性值或者 Outline 对象。

const outline = new Outline({
+export default Toolbar

Outline.DEFAULTS

Description

Type:
Object

静态属性,存储的是 Outline 对象默认配置选项:

Outline.DEFAULTS = {
+  articleElement: '#article',
+  selector: 'h2,h3,h4,h5,h6',
+  title: '目录',
+  scrollElement: 'html,body',
+  position: 'relative',
+  parentElement: '#aside',
+  placement: 'rtl',
+  showCode: true,
+  anchorURL: '',
+  stickyHeight: 0,
+  homepage: '',
+  git: '',
+  tags: '',
+  issues: '',
+  tools: [],
+  print: {
+    element: '',
+    title: ''
+  },
+  customClass: '',
+  afterSticky: null,
+  afterToggle: null,
+  afterScroll: null,
+  chapterTextFilter: null
+}

Methods

outline.js 的提供的方法如下:

attr([prop, value])

Description

attr() 方法用来设置或者获取初始化时配置的 attrs 信息的。

Parameters

prop
Type:
String|HTMLElement

(可选)options 中的属性名称或者要配置的 attrs 信息。

value
Type:
Any

(可选)要设置的 prop 属性的值

  • 不传递任何参数:返回完整的 attrs 配置信息;
  • 仅传递 prop:
    • String: 返回 attrs 配型信息中与 prop 对应的值;
    • Object: 用来设置 attrs 配置信息;
  • 同时传递 prop 和 value 参数:设置 attrs 配置信息中的某个属性值;

Returns

Type:
Any

配置信息 attrs 的属性值或者 Outline 对象。

const outline = new Outline({
    article: '#article',
    title: 'Outline v2.0.0'
 })
@@ -1019,10 +1019,10 @@
   console.log('handler:', msg)
 }
 
-outline.$on('created', handler)
+outline.$on('created')
 
 // 取消订阅 author 主题
-outline.$off('created', handler)
+outline.$off('created')
 
 // 不会有任何反应,因为已经取消订阅了
 outline.$emit('created')

License

JavaScript Code Licensed under MIT License.

API Documentation Licensed under CC BY 3.0