@public-ui/hydrate 2.2.23 → 2.2.24-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +988 -756
  2. package/dist/index.mjs +988 -756
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -229,7 +229,7 @@ var HYDRATED_STYLE_ID = "sty-id";
229
229
  var HYDRATE_CHILD_ID = "c-id";
230
230
  var SLOT_FB_CSS = "slot-fb{display:contents}slot-fb[hidden]{display:none}";
231
231
  var XLINK_NS = "http://www.w3.org/1999/xlink";
232
- var h$1 = (nodeName, vnodeData, ...children) => {
232
+ var h = (nodeName, vnodeData, ...children) => {
233
233
  let child = null;
234
234
  let key = null;
235
235
  let slotName = null;
@@ -331,7 +331,7 @@ var convertToPrivate = (node) => {
331
331
  if (node.vname) {
332
332
  vnodeData.name = node.vname;
333
333
  }
334
- return h$1(node.vtag, vnodeData, ...node.vchildren || []);
334
+ return h(node.vtag, vnodeData, ...node.vchildren || []);
335
335
  }
336
336
  const vnode = newVNode(node.vtag, node.vtext);
337
337
  vnode.$attrs$ = node.vattrs;
@@ -1166,7 +1166,7 @@ var renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => {
1166
1166
  const hostElm = hostRef.$hostElement$;
1167
1167
  const cmpMeta = hostRef.$cmpMeta$;
1168
1168
  const oldVNode = hostRef.$vnode$ || newVNode(null, null);
1169
- const rootVnode = isHost(renderFnResults) ? renderFnResults : h$1(null, null, renderFnResults);
1169
+ const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
1170
1170
  hostTagName = hostElm.tagName;
1171
1171
  if (cmpMeta.$attrsToReflect$) {
1172
1172
  rootVnode.$attrs$ = rootVnode.$attrs$ || {};
@@ -1890,14 +1890,14 @@ var hAsync = (nodeName, vnodeData, ...children) => {
1890
1890
  const flatChildren = children.flat(Infinity);
1891
1891
  if (flatChildren.some((child) => child instanceof Promise)) {
1892
1892
  return Promise.all(flatChildren).then((resolvedChildren) => {
1893
- return h$1(nodeName, vnodeData, ...resolvedChildren);
1893
+ return h(nodeName, vnodeData, ...resolvedChildren);
1894
1894
  }).catch((err2) => {
1895
- return h$1(nodeName, vnodeData);
1895
+ return h(nodeName, vnodeData);
1896
1896
  });
1897
1897
  }
1898
- return h$1(nodeName, vnodeData, ...flatChildren);
1898
+ return h(nodeName, vnodeData, ...flatChildren);
1899
1899
  }
1900
- return h$1(nodeName, vnodeData);
1900
+ return h(nodeName, vnodeData);
1901
1901
  };
1902
1902
  function proxyHostElement(elm, cmpMeta) {
1903
1903
  if (typeof elm.componentOnReady !== "function") {
@@ -2658,9 +2658,9 @@ var loglevel = {exports: {}};
2658
2658
  }));
2659
2659
  }(loglevel));
2660
2660
 
2661
- var h = loglevel.exports;
2661
+ var f = loglevel.exports;
2662
2662
 
2663
- const j=(t,e)=>s=>s(t,e),F=(t,e)=>s=>s(t,e,{append:!1}),Y=()=>{const t=typeof process<"u"&&process.env?process.env:{},e=t.NODE_ENV==="test",s="VITEST"in t,o="JEST_WORKER_ID"in t,a="PLAYWRIGHT_TEST_BASE_URL"in t,r=t.CI==="true",i=t.TEST==="true"||t.IS_TEST==="true",c=typeof navigator<"u"&&navigator.webdriver===!0,y=typeof navigator<"u"&&/playwright|puppeteer|webdriver|selenium|testcafe/i.test(navigator.userAgent);return e||s||o||a||r||i||c||y},n$1={A11yUi:{CSS_STYLE_CACHE:new Map,IS_TEST_ENVIRONMENT:Y(),PERFORMANCE_MEASURES:new Map,STYLING_TASK_QUEUE:new Map,THEMES:new Map,showAverageTimes:()=>{const t={};for(const[s,o]of n$1.A11yUi.PERFORMANCE_MEASURES.entries())t[s]=[o.totalTime/o.count,o.count];const e=Object.entries(t).sort((s,o)=>o[1][0]-s[1][0]);return console.table(Object.fromEntries(e.map(([s,[o,a]])=>[s,{"avg (ms)":parseFloat(o.toFixed(2)),count:a}]))),t}}};let f=!1;const k=/^[a-z][a-z0-9]{1,}(-[a-z0-9]+)?$/,G=t=>typeof t=="string"&&k.test(t),S=t=>{if(!G(t))throw new Error(`[Theming] The theme identifier "${typeof t=="string"?t:""}" (Type: ${typeof t}) is not valid. Please use only follow this pattern: /^[a-z][a-z0-9]{1,}(-[a-z0-9]+)?$/`)},A=t=>t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\s*([{},;])\s*/g,"$1").replace(/:\s+/g,":").replace(/\s+/g," ").replace(/;\}/g,"}").trim(),x=(t,e,s,o)=>T(t,e,s,o),T=(t,e,s,o)=>{o=o??{},o.append=o.append??!1,S(t),!f&&(f=!0,h.warn(`[Theming] The theme process is locked. This means that the theme "${t}" should not be patched.
2663
+ const k=(e,t)=>s=>s(e,t),G=(e,t,s)=>o=>o(e,t,{append:!1},s),x=()=>{const e=typeof process<"u"&&process.env?process.env:{},t=e.NODE_ENV==="test",s="VITEST"in e,o="JEST_WORKER_ID"in e,a="PLAYWRIGHT_TEST_BASE_URL"in e,r=e.CI==="true",i=e.TEST==="true"||e.IS_TEST==="true",c=typeof navigator<"u"&&navigator.webdriver===!0,m=typeof navigator<"u"&&/playwright|puppeteer|webdriver|selenium|testcafe/i.test(navigator.userAgent);return t||s||o||a||r||i||c||m},n$1={A11yUi:{CSS_STYLE_CACHE:new Map,FEATURES:{},IS_TEST_ENVIRONMENT:x(),PERFORMANCE_MEASURES:new Map,STYLING_TASK_QUEUE:new Map,THEMES:new Map,THEME_FEATURES:{},showAverageTimes:()=>{const e={};for(const[s,o]of n$1.A11yUi.PERFORMANCE_MEASURES.entries())e[s]=[o.totalTime/o.count,o.count];const t=Object.entries(e).sort((s,o)=>o[1][0]-s[1][0]);return console.table(Object.fromEntries(t.map(([s,[o,a]])=>[s,{"avg (ms)":parseFloat(o.toFixed(2)),count:a}]))),e}}};let u$1=!1;const K=/^[a-z][a-z0-9]{1,}(-[a-z0-9]+)?$/,B=e=>typeof e=="string"&&K.test(e),U=e=>{if(!B(e))throw new Error(`[Theming] The theme identifier "${typeof e=="string"?e:""}" (Type: ${typeof e}) is not valid. Please use only follow this pattern: /^[a-z][a-z0-9]{1,}(-[a-z0-9]+)?$/`)},b=e=>e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\s*([{},;])\s*/g,"$1").replace(/:\s+/g,":").replace(/\s+/g," ").replace(/;\}/g,"}").trim(),D=(e,t,s,o)=>p(e,t,s,o),p=(e,t,s,o)=>{o=o??{},o.append=o.append??!1,U(e),!u$1&&(u$1=!0,f.warn(`[Theming] The theme process is locked. This means that the theme "${e}" should not be patched.
2664
2664
 
2665
2665
  import { register } from 'adopted-style-sheets';
2666
2666
  import { defineCustomElements } from '...';
@@ -2670,94 +2670,94 @@ const j=(t,e)=>s=>s(t,e),F=(t,e)=>s=>s(t,e,{append:!1}),Y=()=>{const t=typeof pr
2670
2670
  .then(() => {
2671
2671
  // run your app or website
2672
2672
  })
2673
- .catch(console.warn);`));let a=n$1.A11yUi.THEMES.get(t);if(a||(a=new Map,n$1.A11yUi.THEMES.set(t,a)),o.append&&a.has(e)){const r=a.get(e);a.set(e,A(`${r}${s}`));}else a.set(e,A(s));},K=(t,e,s,o)=>g(t,e,s,o),g=(t,e,s,o)=>(S(t),typeof e=="object"&&e!==null&&Object.getOwnPropertyNames(e).forEach(a=>{const r=e[a],i=a.toLowerCase(),c=typeof o?.transformTagName=="function"&&!["GLOBAL","PROPERTIES"].includes(a)?o.transformTagName(i):a;typeof r=="string"&&r.length>0&&T(t,c.toUpperCase(),r,s);}),t);const v=new Set,N=new Map,X=/--[^;]+/g,Z$1=/:/,ee=typeof MutationObserver<"u";let R=()=>{};const te=(t,e)=>{let s=e.match(X);if(Array.isArray(s)){s=s.filter(a=>Z$1.test(a));const o=document.createElement("style");o.innerHTML=`.${t} {${s.join(";")}}`,document.querySelector("head")?.appendChild(o);}v.add(t);},d=(t,e)=>{const s=n$1.A11yUi.THEMES.get(t);if(s instanceof Map){const o=s.get(e);if(o!==void 0)return o}return ""},se=t=>{const e=t.firstChild;if(!(!(e instanceof HTMLStyleElement)||e.dataset.themingFallback!==void 0))for(const s of Array.from(t.childNodes))if(s instanceof HTMLStyleElement&&s.tagName==="STYLE"&&s.dataset.themingFallback===void 0)t.removeChild(s);else break},oe=(t,e)=>{try{if(n$1.A11yUi.Theme?.mode==="ssr")throw new Error("SSR");const s=e.filter(o=>typeof o=="string"&&o.length>0).map(o=>{let a=N.get(o);return a||(a=new CSSStyleSheet,a.replaceSync(o),N.set(o,a)),a});t.adoptedStyleSheets=s;}catch{for(let o=e.length-1;o>=0;o--){const a=e[o];if(typeof a!="string"||a.length===0)continue;const r=e.length-1-o,i=document.createElement("style");switch(i.dataset.themingFallback="",r){case 4:i.dataset.themingBaseA11y="";break;case 3:i.dataset.themingBaseGlobal="";break;case 2:i.dataset.themingBaseComponent="";break;case 1:i.dataset.themingCustomGlobal="";break;case 0:i.dataset.themingCustomComponent="";break;default:i.dataset.themingUnknown="";break}i.innerHTML=a,t.insertBefore(i,t.firstChild);}}},ae=(t,e,s)=>{if(s===!1||s?.mode!=="before"&&s?.mode!=="after")return;const o=Array.from(t.childNodes).filter(r=>r instanceof HTMLStyleElement&&r.tagName==="STYLE");let a;try{a=Array.from(t.adoptedStyleSheets);}catch{a=[];}if(!(o.length===0&&a.length===0))if(s.mode==="before"){const r=[...a.map(i=>Array.from(i.cssRules).map(c=>c.cssText).join("")),...o.map(i=>i.innerHTML)];e.unshift(...r);}else o.forEach(r=>e.push(r.innerHTML)),a.forEach(r=>e.push(Array.from(r.cssRules).map(i=>i.cssText).join("")));},ne=(t,e,s)=>{const o=e.name||"default";let a;try{if(t.shadowRoot===null)throw new Error("ShadowRoot is null");a=t.shadowRoot;}catch{a=t;}const r=n$1.A11yUi.CSS_STYLE_CACHE.get(o)?.get(t.tagName);if(r)_(t,a,r,s);else {const i=d(o,"PROPERTIES"),c=d(o,"GLOBAL"),y=d(o,t.tagName);v.has(o)===!1&&te(o,c);const u=[i,c,y];if(ae(a,u,e.encroachCss),e.cache===!0){let m=n$1.A11yUi.CSS_STYLE_CACHE.get(o);m||(m=new Map,n$1.A11yUi.CSS_STYLE_CACHE.set(o,m)),m.set(t.tagName,u);}_(t,a,u,s);}},_=(t,e,s,o)=>{const a=n$1.A11yUi.Theme?.loglevel==="debug",r=a?performance.now():0;if(se(e),oe(e,s),me(t),requestAnimationFrame(o),a){const i=performance.now()-r,c=n$1.A11yUi.PERFORMANCE_MEASURES.get(t.tagName);c?(c.count+=1,c.totalTime+=i):n$1.A11yUi.PERFORMANCE_MEASURES.set(t.tagName,{count:1,totalTime:i});}},O=t=>{const e=n$1.A11yUi.STYLING_TASK_QUEUE.get(t);if(e){const{resetCss:s,themeDetails:o}=e;ne(t,o,s);}};const ce={attributes:!0,attributeFilter:[],childList:!1,subtree:!1},I=ee?new MutationObserver((t,e)=>{const s=[];for(const o of t){const a=o.target;a.classList.contains("hydrated")&&n$1.A11yUi.STYLING_TASK_QUEUE.has(a)&&(O(a),s.push(a));}for(const o of s)e.observe(o,ce);}):null;I&&(R=()=>{});const me=t=>{n$1.A11yUi.STYLING_TASK_QUEUE.delete(t),R();};class fe{Prefix;Key;Tag;createTheme=(e,s)=>F(e,s);createTranslation=(e,s)=>j(e,s);constructor(e,s,o){this.Prefix=e,this.Key=Object.getOwnPropertyNames(s),this.Tag=Object.getOwnPropertyNames(o);}}
2673
+ .catch(console.warn);`));let a=n$1.A11yUi.THEMES.get(e);if(a||(a=new Map,n$1.A11yUi.THEMES.set(e,a)),o.append&&a.has(t)){const r=a.get(t);a.set(t,b(`${r}${s}`));}else a.set(t,b(s));},z=(e,t,s,o)=>g(e,t,s,o),g=(e,t,s,o)=>(U(e),typeof t=="object"&&t!==null&&Object.getOwnPropertyNames(t).forEach(a=>{const r=t[a],i=a.toLowerCase(),c=typeof o?.transformTagName=="function"&&!["GLOBAL","PROPERTIES"].includes(a)?o.transformTagName(i):a;typeof r=="string"&&r.length>0&&p(e,c.toUpperCase(),r,s);}),e);const _=new Set,L=new Map,oe=/--[^;]+/g,ae=/:/,ne=typeof MutationObserver<"u";let H=()=>{};const re=(e,t)=>{let s=t.match(oe);if(Array.isArray(s)){s=s.filter(a=>ae.test(a));const o=document.createElement("style");o.innerHTML=`.${e} {${s.join(";")}}`,document.querySelector("head")?.appendChild(o);}_.add(e);},T=(e,t)=>{const s=n$1.A11yUi.THEMES.get(e);if(s instanceof Map){const o=s.get(t);if(o!==void 0)return o}return ""},ie=e=>{const t=e.firstChild;if(!(!(t instanceof HTMLStyleElement)||t.dataset.themingFallback!==void 0))for(const s of Array.from(e.childNodes))if(s instanceof HTMLStyleElement&&s.tagName==="STYLE"&&s.dataset.themingFallback===void 0)e.removeChild(s);else break},ce=(e,t)=>{try{if(n$1.A11yUi.Theme?.mode==="ssr")throw new Error("SSR");const s=t.filter(o=>typeof o=="string"&&o.length>0).map(o=>{let a=L.get(o);return a||(a=new CSSStyleSheet,a.replaceSync(o),L.set(o,a)),a});e.adoptedStyleSheets=s;}catch{for(let o=t.length-1;o>=0;o--){const a=t[o];if(typeof a!="string"||a.length===0)continue;const r=t.length-1-o,i=document.createElement("style");switch(i.dataset.themingFallback="",r){case 4:i.dataset.themingBaseA11y="";break;case 3:i.dataset.themingBaseGlobal="";break;case 2:i.dataset.themingBaseComponent="";break;case 1:i.dataset.themingCustomGlobal="";break;case 0:i.dataset.themingCustomComponent="";break;default:i.dataset.themingUnknown="";break}i.innerHTML=a,e.insertBefore(i,e.firstChild);}}},le=(e,t,s)=>{if(s===!1||s?.mode!=="before"&&s?.mode!=="after")return;const o=Array.from(e.childNodes).filter(r=>r instanceof HTMLStyleElement&&r.tagName==="STYLE");let a;try{a=Array.from(e.adoptedStyleSheets);}catch{a=[];}if(!(o.length===0&&a.length===0))if(s.mode==="before"){const r=[...a.map(i=>Array.from(i.cssRules).map(c=>c.cssText).join("")),...o.map(i=>i.innerHTML)];t.unshift(...r);}else o.forEach(r=>t.push(r.innerHTML)),a.forEach(r=>t.push(Array.from(r.cssRules).map(i=>i.cssText).join("")));},me=(e,t,s)=>{const o=t.name||"default";let a;try{if(e.shadowRoot===null)throw new Error("ShadowRoot is null");a=e.shadowRoot;}catch{a=e;}const r=n$1.A11yUi.CSS_STYLE_CACHE.get(o)?.get(e.tagName);if(r)O(e,a,r,s);else {const i=T(o,"PROPERTIES"),c=T(o,"GLOBAL"),m=T(o,e.tagName);_.has(o)===!1&&re(o,c);const d=[i,c,m];if(le(a,d,t.encroachCss),t.cache===!0){let h=n$1.A11yUi.CSS_STYLE_CACHE.get(o);h||(h=new Map,n$1.A11yUi.CSS_STYLE_CACHE.set(o,h)),h.set(e.tagName,d);}O(e,a,d,s);}},O=(e,t,s,o)=>{const a=n$1.A11yUi.Theme?.loglevel==="debug",r=a?performance.now():0;if(ie(t),ce(t,s),Te(e),requestAnimationFrame(o),a){const i=performance.now()-r,c=n$1.A11yUi.PERFORMANCE_MEASURES.get(e.tagName);c?(c.count+=1,c.totalTime+=i):n$1.A11yUi.PERFORMANCE_MEASURES.set(e.tagName,{count:1,totalTime:i});}},I=e=>{const t=n$1.A11yUi.STYLING_TASK_QUEUE.get(e);if(t){const{resetCss:s,themeDetails:o}=t;me(e,o,s);}};const ue={attributes:!0,attributeFilter:[],childList:!1,subtree:!1},P$1=ne?new MutationObserver((e,t)=>{const s=[];for(const o of e){const a=o.target;a.classList.contains("hydrated")&&n$1.A11yUi.STYLING_TASK_QUEUE.has(a)&&(I(a),s.push(a));}for(const o of s)t.observe(o,ue);}):null;P$1&&(H=()=>{});const Te=e=>{n$1.A11yUi.STYLING_TASK_QUEUE.delete(e),H();};class Ee{Prefix;Key;Tag;createTheme=(t,s,o)=>G(t,s,o);createTranslation=(t,s)=>k(t,s);constructor(t,s,o){this.Prefix=t,this.Key=Object.getOwnPropertyNames(s),this.Tag=Object.getOwnPropertyNames(o);}}
2674
2674
 
2675
2675
  var KeyEnum;
2676
2676
  (function (KeyEnum) {
2677
- KeyEnum[KeyEnum["error"] = 0] = "error";
2678
- KeyEnum[KeyEnum["warning"] = 1] = "warning";
2679
- KeyEnum[KeyEnum["info"] = 2] = "info";
2680
- KeyEnum[KeyEnum["success"] = 3] = "success";
2681
- KeyEnum[KeyEnum["message"] = 4] = "message";
2682
- KeyEnum[KeyEnum["close"] = 5] = "close";
2683
- KeyEnum[KeyEnum["form-description"] = 6] = "form-description";
2684
- KeyEnum[KeyEnum["of"] = 7] = "of";
2685
- KeyEnum[KeyEnum["characters"] = 8] = "characters";
2686
- KeyEnum[KeyEnum["new"] = 9] = "new";
2687
- KeyEnum[KeyEnum["no-entries"] = 10] = "no-entries";
2688
- KeyEnum[KeyEnum["change-order"] = 11] = "change-order";
2689
- KeyEnum[KeyEnum["action-running"] = 12] = "action-running";
2690
- KeyEnum[KeyEnum["action-done"] = 13] = "action-done";
2691
- KeyEnum[KeyEnum["page-first"] = 14] = "page-first";
2692
- KeyEnum[KeyEnum["page-back"] = 15] = "page-back";
2693
- KeyEnum[KeyEnum["page-next"] = 16] = "page-next";
2694
- KeyEnum[KeyEnum["page-last"] = 17] = "page-last";
2695
- KeyEnum[KeyEnum["entries-per-site"] = 18] = "entries-per-site";
2696
- KeyEnum[KeyEnum["page-current"] = 19] = "page-current";
2697
- KeyEnum[KeyEnum["page-selected"] = 20] = "page-selected";
2698
- KeyEnum[KeyEnum["page-per-site"] = 21] = "page-per-site";
2699
- KeyEnum[KeyEnum["logo-description"] = 22] = "logo-description";
2700
- KeyEnum[KeyEnum["open-link-in-tab"] = 23] = "open-link-in-tab";
2701
- KeyEnum[KeyEnum["kolibri-logo"] = 24] = "kolibri-logo";
2677
+ KeyEnum["error"] = "error";
2678
+ KeyEnum["warning"] = "warning";
2679
+ KeyEnum["info"] = "info";
2680
+ KeyEnum["success"] = "success";
2681
+ KeyEnum["message"] = "message";
2682
+ KeyEnum["close"] = "close";
2683
+ KeyEnum["form-description"] = "form-description";
2684
+ KeyEnum["of"] = "of";
2685
+ KeyEnum["characters"] = "characters";
2686
+ KeyEnum["new"] = "new";
2687
+ KeyEnum["no-entries"] = "no-entries";
2688
+ KeyEnum["change-order"] = "change-order";
2689
+ KeyEnum["action-running"] = "action-running";
2690
+ KeyEnum["action-done"] = "action-done";
2691
+ KeyEnum["page-first"] = "page-first";
2692
+ KeyEnum["page-back"] = "page-back";
2693
+ KeyEnum["page-next"] = "page-next";
2694
+ KeyEnum["page-last"] = "page-last";
2695
+ KeyEnum["entries-per-site"] = "entries-per-site";
2696
+ KeyEnum["page-current"] = "page-current";
2697
+ KeyEnum["page-selected"] = "page-selected";
2698
+ KeyEnum["page-per-site"] = "page-per-site";
2699
+ KeyEnum["logo-description"] = "logo-description";
2700
+ KeyEnum["open-link-in-tab"] = "open-link-in-tab";
2701
+ KeyEnum["kolibri-logo"] = "kolibri-logo";
2702
2702
  })(KeyEnum || (KeyEnum = {}));
2703
2703
 
2704
2704
  var TagEnum;
2705
2705
  (function (TagEnum) {
2706
- TagEnum[TagEnum["abbr"] = 0] = "abbr";
2707
- TagEnum[TagEnum["accordion"] = 1] = "accordion";
2708
- TagEnum[TagEnum["alert"] = 2] = "alert";
2709
- TagEnum[TagEnum["avatar"] = 3] = "avatar";
2710
- TagEnum[TagEnum["badge"] = 4] = "badge";
2711
- TagEnum[TagEnum["breadcrumb"] = 5] = "breadcrumb";
2712
- TagEnum[TagEnum["button"] = 6] = "button";
2713
- TagEnum[TagEnum["button-group"] = 7] = "button-group";
2714
- TagEnum[TagEnum["button-link"] = 8] = "button-link";
2715
- TagEnum[TagEnum["card"] = 9] = "card";
2716
- TagEnum[TagEnum["combobox"] = 10] = "combobox";
2717
- TagEnum[TagEnum["details"] = 11] = "details";
2718
- TagEnum[TagEnum["drawer"] = 12] = "drawer";
2719
- TagEnum[TagEnum["form"] = 13] = "form";
2720
- TagEnum[TagEnum["heading"] = 14] = "heading";
2721
- TagEnum[TagEnum["icon"] = 15] = "icon";
2722
- TagEnum[TagEnum["image"] = 16] = "image";
2723
- TagEnum[TagEnum["indented-text"] = 17] = "indented-text";
2724
- TagEnum[TagEnum["input-checkbox"] = 18] = "input-checkbox";
2725
- TagEnum[TagEnum["input-color"] = 19] = "input-color";
2726
- TagEnum[TagEnum["input-date"] = 20] = "input-date";
2727
- TagEnum[TagEnum["input-email"] = 21] = "input-email";
2728
- TagEnum[TagEnum["input-file"] = 22] = "input-file";
2729
- TagEnum[TagEnum["input-number"] = 23] = "input-number";
2730
- TagEnum[TagEnum["input-password"] = 24] = "input-password";
2731
- TagEnum[TagEnum["input-radio"] = 25] = "input-radio";
2732
- TagEnum[TagEnum["input-range"] = 26] = "input-range";
2733
- TagEnum[TagEnum["input-text"] = 27] = "input-text";
2734
- TagEnum[TagEnum["kolibri"] = 28] = "kolibri";
2735
- TagEnum[TagEnum["link"] = 29] = "link";
2736
- TagEnum[TagEnum["link-button"] = 30] = "link-button";
2737
- TagEnum[TagEnum["link-group"] = 31] = "link-group";
2738
- TagEnum[TagEnum["logo"] = 32] = "logo";
2739
- TagEnum[TagEnum["modal"] = 33] = "modal";
2740
- TagEnum[TagEnum["nav"] = 34] = "nav";
2741
- TagEnum[TagEnum["pagination"] = 35] = "pagination";
2742
- TagEnum[TagEnum["popover-button"] = 36] = "popover-button";
2743
- TagEnum[TagEnum["progress"] = 37] = "progress";
2744
- TagEnum[TagEnum["quote"] = 38] = "quote";
2745
- TagEnum[TagEnum["select"] = 39] = "select";
2746
- TagEnum[TagEnum["single-select"] = 40] = "single-select";
2747
- TagEnum[TagEnum["skip-nav"] = 41] = "skip-nav";
2748
- TagEnum[TagEnum["spin"] = 42] = "spin";
2749
- TagEnum[TagEnum["split-button"] = 43] = "split-button";
2750
- TagEnum[TagEnum["symbol"] = 44] = "symbol";
2751
- TagEnum[TagEnum["table"] = 45] = "table";
2752
- TagEnum[TagEnum["table-stateful"] = 46] = "table-stateful";
2753
- TagEnum[TagEnum["table-stateless"] = 47] = "table-stateless";
2754
- TagEnum[TagEnum["tabs"] = 48] = "tabs";
2755
- TagEnum[TagEnum["textarea"] = 49] = "textarea";
2756
- TagEnum[TagEnum["toast-container"] = 50] = "toast-container";
2757
- TagEnum[TagEnum["toolbar"] = 51] = "toolbar";
2758
- TagEnum[TagEnum["tooltip"] = 52] = "tooltip";
2759
- TagEnum[TagEnum["tree"] = 53] = "tree";
2760
- TagEnum[TagEnum["tree-item"] = 54] = "tree-item";
2706
+ TagEnum["abbr"] = "abbr";
2707
+ TagEnum["accordion"] = "accordion";
2708
+ TagEnum["alert"] = "alert";
2709
+ TagEnum["avatar"] = "avatar";
2710
+ TagEnum["badge"] = "badge";
2711
+ TagEnum["breadcrumb"] = "breadcrumb";
2712
+ TagEnum["button"] = "button";
2713
+ TagEnum["button-group"] = "button-group";
2714
+ TagEnum["button-link"] = "button-link";
2715
+ TagEnum["card"] = "card";
2716
+ TagEnum["combobox"] = "combobox";
2717
+ TagEnum["details"] = "details";
2718
+ TagEnum["drawer"] = "drawer";
2719
+ TagEnum["form"] = "form";
2720
+ TagEnum["heading"] = "heading";
2721
+ TagEnum["icon"] = "icon";
2722
+ TagEnum["image"] = "image";
2723
+ TagEnum["indented-text"] = "indented-text";
2724
+ TagEnum["input-checkbox"] = "input-checkbox";
2725
+ TagEnum["input-color"] = "input-color";
2726
+ TagEnum["input-date"] = "input-date";
2727
+ TagEnum["input-email"] = "input-email";
2728
+ TagEnum["input-file"] = "input-file";
2729
+ TagEnum["input-number"] = "input-number";
2730
+ TagEnum["input-password"] = "input-password";
2731
+ TagEnum["input-radio"] = "input-radio";
2732
+ TagEnum["input-range"] = "input-range";
2733
+ TagEnum["input-text"] = "input-text";
2734
+ TagEnum["kolibri"] = "kolibri";
2735
+ TagEnum["link"] = "link";
2736
+ TagEnum["link-button"] = "link-button";
2737
+ TagEnum["link-group"] = "link-group";
2738
+ TagEnum["logo"] = "logo";
2739
+ TagEnum["modal"] = "modal";
2740
+ TagEnum["nav"] = "nav";
2741
+ TagEnum["pagination"] = "pagination";
2742
+ TagEnum["popover-button"] = "popover-button";
2743
+ TagEnum["progress"] = "progress";
2744
+ TagEnum["quote"] = "quote";
2745
+ TagEnum["select"] = "select";
2746
+ TagEnum["single-select"] = "single-select";
2747
+ TagEnum["skip-nav"] = "skip-nav";
2748
+ TagEnum["spin"] = "spin";
2749
+ TagEnum["split-button"] = "split-button";
2750
+ TagEnum["symbol"] = "symbol";
2751
+ TagEnum["table"] = "table";
2752
+ TagEnum["table-stateful"] = "table-stateful";
2753
+ TagEnum["table-stateless"] = "table-stateless";
2754
+ TagEnum["tabs"] = "tabs";
2755
+ TagEnum["textarea"] = "textarea";
2756
+ TagEnum["toast-container"] = "toast-container";
2757
+ TagEnum["toolbar"] = "toolbar";
2758
+ TagEnum["tooltip"] = "tooltip";
2759
+ TagEnum["tree"] = "tree";
2760
+ TagEnum["tree-item"] = "tree-item";
2761
2761
  })(TagEnum || (TagEnum = {}));
2762
2762
 
2763
2763
  const alertTypeOptions = ['default', 'info', 'success', 'warning', 'error'];
@@ -3802,9 +3802,9 @@ const koliBriQuerySelector = (selector, node) => querySelector(selector, node ||
3802
3802
  const koliBriQuerySelectorAll = (selector, node) => querySelectorAll(selector, node || getDocument());
3803
3803
  class KoliBriDevHelper {
3804
3804
  }
3805
- KoliBriDevHelper.getCssStyle = d;
3806
- KoliBriDevHelper.patchTheme = K;
3807
- KoliBriDevHelper.patchThemeTag = x;
3805
+ KoliBriDevHelper.getCssStyle = T;
3806
+ KoliBriDevHelper.patchTheme = z;
3807
+ KoliBriDevHelper.patchThemeTag = D;
3808
3808
  KoliBriDevHelper.querySelector = koliBriQuerySelector;
3809
3809
  KoliBriDevHelper.querySelectorAll = koliBriQuerySelectorAll;
3810
3810
  KoliBriDevHelper.stringifyJson = stringifyJson;
@@ -4501,7 +4501,7 @@ var KoliBriProgressVariantEnum;
4501
4501
  KoliBriProgressVariantEnum["cycle"] = "cycle";
4502
4502
  })(KoliBriProgressVariantEnum || (KoliBriProgressVariantEnum = {}));
4503
4503
 
4504
- new fe('kol', KeyEnum, TagEnum);
4504
+ new Ee('kol', KeyEnum, TagEnum);
4505
4505
 
4506
4506
  let nonce = () => Math.floor(Math.random() * 16777215).toString(16);
4507
4507
  if (processEnv === 'test') {
@@ -12373,12 +12373,12 @@ function getOppositePlacement(placement) {
12373
12373
  return oppositeSideMap[side] + placement.slice(side.length);
12374
12374
  }
12375
12375
  function expandPaddingObject(padding) {
12376
+ var _padding$top, _padding$right, _padding$bottom, _padding$left;
12376
12377
  return {
12377
- top: 0,
12378
- right: 0,
12379
- bottom: 0,
12380
- left: 0,
12381
- ...padding
12378
+ top: (_padding$top = padding.top) != null ? _padding$top : 0,
12379
+ right: (_padding$right = padding.right) != null ? _padding$right : 0,
12380
+ bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0,
12381
+ left: (_padding$left = padding.left) != null ? _padding$left : 0
12382
12382
  };
12383
12383
  }
12384
12384
  function getPaddingObject(padding) {
@@ -12453,13 +12453,9 @@ function computeCoordsFromPlacement(_ref, placement, rtl) {
12453
12453
  y: reference.y
12454
12454
  };
12455
12455
  }
12456
- switch (getAlignment(placement)) {
12457
- case 'start':
12458
- coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
12459
- break;
12460
- case 'end':
12461
- coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
12462
- break;
12456
+ const alignment = getAlignment(placement);
12457
+ if (alignment) {
12458
+ coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);
12463
12459
  }
12464
12460
  return coords;
12465
12461
  }
@@ -12508,10 +12504,7 @@ async function detectOverflow(state, options) {
12508
12504
  height: rects.floating.height
12509
12505
  } : rects.reference;
12510
12506
  const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
12511
- const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
12512
- x: 1,
12513
- y: 1
12514
- } : {
12507
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
12515
12508
  x: 1,
12516
12509
  y: 1
12517
12510
  };
@@ -12684,17 +12677,16 @@ const arrow$1 = options => ({
12684
12677
 
12685
12678
  // Make sure the arrow doesn't overflow the floating element if the center
12686
12679
  // point is outside the floating element's bounds.
12687
- const min$1 = minPadding;
12688
12680
  const max = clientSize - arrowDimensions[length] - maxPadding;
12689
12681
  const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
12690
- const offset = clamp(min$1, center, max);
12682
+ const offset = clamp(minPadding, center, max);
12691
12683
 
12692
12684
  // If the reference is small enough that the arrow's padding causes it to
12693
12685
  // to point to nothing for an aligned placement, adjust the offset of the
12694
12686
  // floating element itself. To ensure `shift()` continues to take action,
12695
12687
  // a single reset is performed when this is true.
12696
- const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
12697
- const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
12688
+ const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < minPadding ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
12689
+ const alignmentOffset = shouldAddOffset ? center < minPadding ? center - minPadding : center - max : 0;
12698
12690
  return {
12699
12691
  [axis]: coords[axis] + alignmentOffset,
12700
12692
  data: {
@@ -12748,13 +12740,11 @@ const autoPlacement = function (options) {
12748
12740
  ...detectOverflowOptions
12749
12741
  } = evaluate(options, state);
12750
12742
  const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;
12751
- const overflow = await platform.detectOverflow(state, detectOverflowOptions);
12752
12743
  const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;
12753
12744
  const currentPlacement = placements$1[currentIndex];
12754
12745
  if (currentPlacement == null) {
12755
12746
  return {};
12756
12747
  }
12757
- const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
12758
12748
 
12759
12749
  // Make `computeCoords` start from the right place.
12760
12750
  if (placement !== currentPlacement) {
@@ -12764,6 +12754,8 @@ const autoPlacement = function (options) {
12764
12754
  }
12765
12755
  };
12766
12756
  }
12757
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
12758
+ const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
12767
12759
  const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];
12768
12760
  const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {
12769
12761
  placement: currentPlacement,
@@ -13070,12 +13062,19 @@ const inline$1 = function (options) {
13070
13062
  y
13071
13063
  } = evaluate(options, state);
13072
13064
  const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);
13065
+
13066
+ // No rects (e.g. a hidden or detached reference, or a collapsed range) —
13067
+ // keep the existing reference rect rather than resetting to an invalid
13068
+ // one with non-finite values.
13069
+ if (!nativeClientRects.length) {
13070
+ return {};
13071
+ }
13073
13072
  const clientRects = getRectsByLine(nativeClientRects);
13074
13073
  const fallback = rectToClientRect(getBoundingRect(nativeClientRects));
13075
13074
  const paddingObject = getPaddingObject(padding);
13076
13075
  function getBoundingClientRect() {
13077
13076
  // There are two rects and they are disjoined.
13078
- if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {
13077
+ if (clientRects.length === 2 && (clientRects[0].left > clientRects[1].right || clientRects[1].left > clientRects[0].right) && x != null && y != null) {
13079
13078
  // Find the first rect in which the point is fully inside.
13080
13079
  return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;
13081
13080
  }
@@ -13090,18 +13089,12 @@ const inline$1 = function (options) {
13090
13089
  const bottom = lastRect.bottom;
13091
13090
  const left = isTop ? firstRect.left : lastRect.left;
13092
13091
  const right = isTop ? firstRect.right : lastRect.right;
13093
- const width = right - left;
13094
- const height = bottom - top;
13095
- return {
13096
- top,
13097
- bottom,
13098
- left,
13099
- right,
13100
- width,
13101
- height,
13092
+ return rectToClientRect({
13102
13093
  x: left,
13103
- y: top
13104
- };
13094
+ y: top,
13095
+ width: right - left,
13096
+ height: bottom - top
13097
+ });
13105
13098
  }
13106
13099
  const isLeftSide = getSide(placement) === 'left';
13107
13100
  const maxRight = max(...clientRects.map(rect => rect.right));
@@ -13109,20 +13102,12 @@ const inline$1 = function (options) {
13109
13102
  const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);
13110
13103
  const top = measureRects[0].top;
13111
13104
  const bottom = measureRects[measureRects.length - 1].bottom;
13112
- const left = minLeft;
13113
- const right = maxRight;
13114
- const width = right - left;
13115
- const height = bottom - top;
13116
- return {
13117
- top,
13118
- bottom,
13119
- left,
13120
- right,
13121
- width,
13122
- height,
13123
- x: left,
13124
- y: top
13125
- };
13105
+ return rectToClientRect({
13106
+ x: minLeft,
13107
+ y: top,
13108
+ width: maxRight - minLeft,
13109
+ height: bottom - top
13110
+ });
13126
13111
  }
13127
13112
  return fallback;
13128
13113
  }
@@ -13272,23 +13257,16 @@ const shift$1 = function (options) {
13272
13257
  y
13273
13258
  };
13274
13259
  const overflow = await platform.detectOverflow(state, detectOverflowOptions);
13275
- const crossAxis = getSideAxis(getSide(placement));
13260
+ const crossAxis = getSideAxis(placement);
13276
13261
  const mainAxis = getOppositeAxis(crossAxis);
13277
13262
  let mainAxisCoord = coords[mainAxis];
13278
13263
  let crossAxisCoord = coords[crossAxis];
13264
+ const clampCoord = (axis, coord) => clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);
13279
13265
  if (checkMainAxis) {
13280
- const minSide = mainAxis === 'y' ? 'top' : 'left';
13281
- const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
13282
- const min = mainAxisCoord + overflow[minSide];
13283
- const max = mainAxisCoord - overflow[maxSide];
13284
- mainAxisCoord = clamp(min, mainAxisCoord, max);
13266
+ mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);
13285
13267
  }
13286
13268
  if (checkCrossAxis) {
13287
- const minSide = crossAxis === 'y' ? 'top' : 'left';
13288
- const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
13289
- const min = crossAxisCoord + overflow[minSide];
13290
- const max = crossAxisCoord - overflow[maxSide];
13291
- crossAxisCoord = clamp(min, crossAxisCoord, max);
13269
+ crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);
13292
13270
  }
13293
13271
  const limitedCoords = limiter.fn({
13294
13272
  ...state,
@@ -13319,6 +13297,7 @@ const limitShift = function (options) {
13319
13297
  return {
13320
13298
  options,
13321
13299
  fn(state) {
13300
+ var _rawOffset$mainAxis, _rawOffset$crossAxis;
13322
13301
  const {
13323
13302
  x,
13324
13303
  y,
@@ -13344,9 +13323,8 @@ const limitShift = function (options) {
13344
13323
  mainAxis: rawOffset,
13345
13324
  crossAxis: 0
13346
13325
  } : {
13347
- mainAxis: 0,
13348
- crossAxis: 0,
13349
- ...rawOffset
13326
+ mainAxis: (_rawOffset$mainAxis = rawOffset.mainAxis) != null ? _rawOffset$mainAxis : 0,
13327
+ crossAxis: (_rawOffset$crossAxis = rawOffset.crossAxis) != null ? _rawOffset$crossAxis : 0
13350
13328
  };
13351
13329
  if (checkMainAxis) {
13352
13330
  const len = mainAxis === 'y' ? 'height' : 'width';
@@ -13378,6 +13356,12 @@ const limitShift = function (options) {
13378
13356
  };
13379
13357
  };
13380
13358
 
13359
+ // Method syntax keeps callback parameters bivariant, but expressing the
13360
+ // explicit `| undefined` required by `exactOptionalPropertyTypes` needs
13361
+ // property syntax, which is contravariant under `strictFunctionTypes`.
13362
+ // Extracting the function from a method position restores that bivariance so
13363
+ // consumers can still assign callbacks with narrower parameter types.
13364
+
13381
13365
  /**
13382
13366
  * Provides data that allows you to change the size of the floating element —
13383
13367
  * for instance, prevent it from overflowing the clipping boundary or match the
@@ -13392,7 +13376,6 @@ const size = function (options) {
13392
13376
  name: 'size',
13393
13377
  options,
13394
13378
  async fn(state) {
13395
- var _state$middlewareData, _state$middlewareData2;
13396
13379
  const {
13397
13380
  placement,
13398
13381
  rects,
@@ -13424,24 +13407,21 @@ const size = function (options) {
13424
13407
  const maximumClippingWidth = width - overflow.left - overflow.right;
13425
13408
  const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
13426
13409
  const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
13427
- const noShift = !state.middlewareData.shift;
13410
+ const shiftData = state.middlewareData.shift;
13411
+ const noShift = !shiftData;
13428
13412
  let availableHeight = overflowAvailableHeight;
13429
13413
  let availableWidth = overflowAvailableWidth;
13430
- if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
13414
+ if (shiftData != null && shiftData.enabled.x) {
13431
13415
  availableWidth = maximumClippingWidth;
13432
13416
  }
13433
- if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
13417
+ if (shiftData != null && shiftData.enabled.y) {
13434
13418
  availableHeight = maximumClippingHeight;
13435
13419
  }
13436
13420
  if (noShift && !alignment) {
13437
- const xMin = max(overflow.left, 0);
13438
- const xMax = max(overflow.right, 0);
13439
- const yMin = max(overflow.top, 0);
13440
- const yMax = max(overflow.bottom, 0);
13441
13421
  if (isYAxis) {
13442
- availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
13422
+ availableWidth = width - 2 * max(overflow.left, overflow.right);
13443
13423
  } else {
13444
- availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
13424
+ availableHeight = height - 2 * max(overflow.top, overflow.bottom);
13445
13425
  }
13446
13426
  }
13447
13427
  await apply({
@@ -13597,7 +13577,7 @@ function getParentNode(node) {
13597
13577
  function getNearestOverflowAncestor(node) {
13598
13578
  const parentNode = getParentNode(node);
13599
13579
  if (isLastTraversableNode(parentNode)) {
13600
- return node.ownerDocument ? node.ownerDocument.body : node.body;
13580
+ return (node.ownerDocument || node).body;
13601
13581
  }
13602
13582
  if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
13603
13583
  return parentNode;
@@ -13694,10 +13674,7 @@ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
13694
13674
  if (isFixed === void 0) {
13695
13675
  isFixed = false;
13696
13676
  }
13697
- if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
13698
- return false;
13699
- }
13700
- return isFixed;
13677
+ return !!floatingOffsetParent && isFixed && floatingOffsetParent === getWindow(element);
13701
13678
  }
13702
13679
 
13703
13680
  function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
@@ -13724,12 +13701,12 @@ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetPar
13724
13701
  let y = (clientRect.top + visualOffsets.y) / scale.y;
13725
13702
  let width = clientRect.width / scale.x;
13726
13703
  let height = clientRect.height / scale.y;
13727
- if (domElement) {
13704
+ if (domElement && offsetParent) {
13728
13705
  const win = getWindow(domElement);
13729
- const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
13706
+ const offsetWin = isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
13730
13707
  let currentWin = win;
13731
13708
  let currentIFrame = getFrameElement(currentWin);
13732
- while (currentIFrame && offsetParent && offsetWin !== currentWin) {
13709
+ while (currentIFrame && offsetWin !== currentWin) {
13733
13710
  const iframeScale = getScale(currentIFrame);
13734
13711
  const iframeRect = currentIFrame.getBoundingClientRect();
13735
13712
  const css = getComputedStyle$1(currentIFrame);
@@ -13793,7 +13770,7 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
13793
13770
  let scale = createCoords(1);
13794
13771
  const offsets = createCoords(0);
13795
13772
  const isOffsetParentAnElement = isHTMLElement(offsetParent);
13796
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
13773
+ if (isOffsetParentAnElement || !isFixed) {
13797
13774
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
13798
13775
  scroll = getNodeScroll(offsetParent);
13799
13776
  }
@@ -13814,18 +13791,17 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
13814
13791
  }
13815
13792
 
13816
13793
  function getClientRects(element) {
13817
- return Array.from(element.getClientRects());
13794
+ return element.getClientRects ? Array.from(element.getClientRects()) : [];
13818
13795
  }
13819
13796
 
13820
13797
  // Gets the entire size of the scrollable document area, even extending outside
13821
13798
  // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
13822
- function getDocumentRect(element) {
13823
- const html = getDocumentElement(element);
13824
- const scroll = getNodeScroll(element);
13825
- const body = element.ownerDocument.body;
13799
+ function getDocumentRect(html) {
13800
+ const scroll = getNodeScroll(html);
13801
+ const body = html.ownerDocument.body;
13826
13802
  const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
13827
13803
  const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
13828
- let x = -scroll.scrollLeft + getWindowScrollBarX(element);
13804
+ let x = -scroll.scrollLeft + getWindowScrollBarX(html);
13829
13805
  const y = -scroll.scrollTop;
13830
13806
  if (getComputedStyle$1(body).direction === 'rtl') {
13831
13807
  x += max(html.clientWidth, body.clientWidth) - width;
@@ -13842,7 +13818,11 @@ function getDocumentRect(element) {
13842
13818
  // calculation is affected by unusual styles.
13843
13819
  // Most scrollbars leave 15-18px of space.
13844
13820
  const SCROLLBAR_MAX = 25;
13845
- function getViewportRect(element, strategy) {
13821
+ function getViewportRect(element, strategy, rootBoundary) {
13822
+ if (rootBoundary === void 0) {
13823
+ rootBoundary = 'viewport';
13824
+ }
13825
+ const isLayoutViewport = rootBoundary === 'layoutViewport';
13846
13826
  const win = getWindow(element);
13847
13827
  const html = getDocumentElement(element);
13848
13828
  const visualViewport = win.visualViewport;
@@ -13851,31 +13831,42 @@ function getViewportRect(element, strategy) {
13851
13831
  let x = 0;
13852
13832
  let y = 0;
13853
13833
  if (visualViewport) {
13854
- width = visualViewport.width;
13855
- height = visualViewport.height;
13856
- const visualViewportBased = isWebKit();
13857
- if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
13858
- x = visualViewport.offsetLeft;
13859
- y = visualViewport.offsetTop;
13834
+ // Client coordinates are relative to the layout viewport, except in
13835
+ // WebKit with an `absolute` strategy, where they are relative to the
13836
+ // visual viewport.
13837
+ const layoutRelativeClientCoords = !isWebKit() || strategy === 'fixed';
13838
+ if (isLayoutViewport) {
13839
+ if (!layoutRelativeClientCoords) {
13840
+ x = -visualViewport.offsetLeft;
13841
+ y = -visualViewport.offsetTop;
13842
+ }
13843
+ } else {
13844
+ width = visualViewport.width;
13845
+ height = visualViewport.height;
13846
+ if (layoutRelativeClientCoords) {
13847
+ x = visualViewport.offsetLeft;
13848
+ y = visualViewport.offsetTop;
13849
+ }
13860
13850
  }
13861
13851
  }
13862
13852
  const windowScrollbarX = getWindowScrollBarX(html);
13863
- // <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the
13864
- // visual width of the <html> but this is not considered in the size
13865
- // of `html.clientWidth`.
13853
+ // `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks
13854
+ // the visual width but isn't reflected in `html.clientWidth`, so subtract it.
13855
+ // Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also
13856
+ // reserves an empty inline-start gutter that clips nothing, so exclude just
13857
+ // the one scrollbar-side gutter — halve the measured (two-gutter) total. A
13858
+ // left-side scrollbar (`windowScrollbarX > 0`) is already handled by
13859
+ // `getHTMLOffset`/`visualViewport.width`; skip it here.
13866
13860
  if (windowScrollbarX <= 0) {
13867
13861
  const doc = html.ownerDocument;
13868
13862
  const body = doc.body;
13869
13863
  const bodyStyles = getComputedStyle(body);
13870
13864
  const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
13871
- const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
13872
- if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
13873
- width -= clippingStableScrollbarWidth;
13865
+ const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
13866
+ const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;
13867
+ if (gutter <= SCROLLBAR_MAX) {
13868
+ width -= gutter;
13874
13869
  }
13875
- } else if (windowScrollbarX <= SCROLLBAR_MAX) {
13876
- // If the <body> scrollbar is on the left, the width needs to be extended
13877
- // by the scrollbar amount so there isn't extra space on the right.
13878
- width += windowScrollbarX;
13879
13870
  }
13880
13871
  return {
13881
13872
  width,
@@ -13890,7 +13881,7 @@ function getInnerBoundingClientRect(element, strategy) {
13890
13881
  const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
13891
13882
  const top = clientRect.top + element.clientTop;
13892
13883
  const left = clientRect.left + element.clientLeft;
13893
- const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
13884
+ const scale = getScale(element);
13894
13885
  const width = element.clientWidth * scale.x;
13895
13886
  const height = element.clientHeight * scale.y;
13896
13887
  const x = left * scale.x;
@@ -13904,8 +13895,8 @@ function getInnerBoundingClientRect(element, strategy) {
13904
13895
  }
13905
13896
  function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
13906
13897
  let rect;
13907
- if (clippingAncestor === 'viewport') {
13908
- rect = getViewportRect(element, strategy);
13898
+ if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {
13899
+ rect = getViewportRect(element, strategy, clippingAncestor);
13909
13900
  } else if (clippingAncestor === 'document') {
13910
13901
  rect = getDocumentRect(getDocumentElement(element));
13911
13902
  } else if (isElement(clippingAncestor)) {
@@ -13921,13 +13912,6 @@ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy)
13921
13912
  }
13922
13913
  return rectToClientRect(rect);
13923
13914
  }
13924
- function hasFixedPositionAncestor(element, stopNode) {
13925
- const parentNode = getParentNode(element);
13926
- if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
13927
- return false;
13928
- }
13929
- return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
13930
- }
13931
13915
 
13932
13916
  // A "clipping ancestor" is an `overflow` element with the characteristic of
13933
13917
  // clipping (or hiding) child elements. This returns all clipping ancestors
@@ -13938,7 +13922,7 @@ function getClippingElementAncestors(element, cache) {
13938
13922
  return cachedResult;
13939
13923
  }
13940
13924
  let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
13941
- let currentContainingBlockComputedStyle = null;
13925
+ let lastKeptComputedStyle = null;
13942
13926
  const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
13943
13927
  let currentNode = elementIsFixed ? getParentNode(element) : element;
13944
13928
 
@@ -13946,16 +13930,20 @@ function getClippingElementAncestors(element, cache) {
13946
13930
  while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
13947
13931
  const computedStyle = getComputedStyle$1(currentNode);
13948
13932
  const currentNodeIsContaining = isContainingBlock(currentNode);
13949
- if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
13950
- currentContainingBlockComputedStyle = null;
13951
- }
13952
- const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === 'absolute' || currentContainingBlockComputedStyle.position === 'fixed') || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
13933
+ // Position of the containing block chain below the current node. A fixed
13934
+ // element whose containing block hasn't been found yet is a fixed chain.
13935
+ const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';
13936
+
13937
+ // A non-containing ancestor does not clip the element when the chain
13938
+ // below it escapes it: a fixed chain escapes all ancestors up to the
13939
+ // next containing block, an absolute chain escapes static ancestors.
13940
+ const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');
13953
13941
  if (shouldDropCurrentNode) {
13954
13942
  // Drop non-containing blocks.
13955
13943
  result = result.filter(ancestor => ancestor !== currentNode);
13956
13944
  } else {
13957
- // Record last containing block for next iteration.
13958
- currentContainingBlockComputedStyle = computedStyle;
13945
+ // The kept node carries the chain position for the next iteration.
13946
+ lastKeptComputedStyle = computedStyle;
13959
13947
  }
13960
13948
  currentNode = getParentNode(currentNode);
13961
13949
  }
@@ -14015,13 +14003,7 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
14015
14003
  scrollTop: 0
14016
14004
  };
14017
14005
  const offsets = createCoords(0);
14018
-
14019
- // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
14020
- // Firefox with layout.scrollbar.side = 3 in about:config to test this.
14021
- function setLeftRTLScrollbarOffset() {
14022
- offsets.x = getWindowScrollBarX(documentElement);
14023
- }
14024
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
14006
+ if (isOffsetParentAnElement || !isFixed) {
14025
14007
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
14026
14008
  scroll = getNodeScroll(offsetParent);
14027
14009
  }
@@ -14029,12 +14011,13 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
14029
14011
  const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
14030
14012
  offsets.x = offsetRect.x + offsetParent.clientLeft;
14031
14013
  offsets.y = offsetRect.y + offsetParent.clientTop;
14032
- } else if (documentElement) {
14033
- setLeftRTLScrollbarOffset();
14034
14014
  }
14035
14015
  }
14036
- if (isFixed && !isOffsetParentAnElement && documentElement) {
14037
- setLeftRTLScrollbarOffset();
14016
+
14017
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
14018
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
14019
+ if (!isOffsetParentAnElement && documentElement) {
14020
+ offsets.x = getWindowScrollBarX(documentElement);
14038
14021
  }
14039
14022
  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
14040
14023
  const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
@@ -14134,7 +14117,7 @@ function rectsAreEqual(a, b) {
14134
14117
  }
14135
14118
 
14136
14119
  // https://samthor.au/2021/observing-dom/
14137
- function observeMove(element, onMove) {
14120
+ function observeMove(element, onMove, ancestorResize) {
14138
14121
  let io = null;
14139
14122
  let timeoutId;
14140
14123
  const root = getDocumentElement(element);
@@ -14177,13 +14160,22 @@ function observeMove(element, onMove) {
14177
14160
  let isFirstUpdate = true;
14178
14161
  function handleObserve(entries) {
14179
14162
  const ratio = entries[0].intersectionRatio;
14163
+
14164
+ // The entry is a snapshot, so the reference may have moved since the
14165
+ // intersection was computed (under performance constraints, or between
14166
+ // consecutive frames of a multi-frame layout shift). The reported ratio
14167
+ // and the observed area are stale in that case and cannot be trusted to
14168
+ // detect subsequent movement, so refresh regardless of the ratio.
14169
+ if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
14170
+ return refresh();
14171
+ }
14180
14172
  if (ratio !== threshold) {
14181
14173
  if (!isFirstUpdate) {
14182
14174
  return refresh();
14183
14175
  }
14184
14176
  if (!ratio) {
14185
- // If the reference is clipped, the ratio is 0. Throttle the refresh
14186
- // to prevent an infinite loop of updates.
14177
+ // If the reference is clipped in place, the ratio is 0. Throttle
14178
+ // the refresh to prevent an infinite loop of updates.
14187
14179
  timeoutId = setTimeout(() => {
14188
14180
  refresh(false, 1e-7);
14189
14181
  }, 1000);
@@ -14191,16 +14183,6 @@ function observeMove(element, onMove) {
14191
14183
  refresh(false, ratio);
14192
14184
  }
14193
14185
  }
14194
- if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
14195
- // It's possible that even though the ratio is reported as 1, the
14196
- // element is not actually fully within the IntersectionObserver's root
14197
- // area anymore. This can happen under performance constraints. This may
14198
- // be a bug in the browser's IntersectionObserver implementation. To
14199
- // work around this, we compare the element's bounding rect now with
14200
- // what it was at the time we created the IntersectionObserver. If they
14201
- // are not equal then the element moved, so we refresh.
14202
- refresh();
14203
- }
14204
14186
  isFirstUpdate = false;
14205
14187
  }
14206
14188
 
@@ -14217,8 +14199,18 @@ function observeMove(element, onMove) {
14217
14199
  }
14218
14200
  io.observe(element);
14219
14201
  }
14202
+ const win = getWindow(element);
14203
+ // The window is a resize ancestor, so when `ancestorResize` is enabled its
14204
+ // listener already runs the update on resize. Here we only need to rebuild
14205
+ // the `IntersectionObserver` for the new root size, skipping a redundant
14206
+ // update. When `ancestorResize` is disabled, this becomes the sole update.
14207
+ const handleResize = () => refresh(ancestorResize);
14208
+ win.addEventListener('resize', handleResize);
14220
14209
  refresh(true);
14221
- return cleanup;
14210
+ return () => {
14211
+ win.removeEventListener('resize', handleResize);
14212
+ cleanup();
14213
+ };
14222
14214
  }
14223
14215
 
14224
14216
  /**
@@ -14243,12 +14235,10 @@ function autoUpdate(reference, floating, update, options) {
14243
14235
  const referenceEl = unwrapElement(reference);
14244
14236
  const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];
14245
14237
  ancestors.forEach(ancestor => {
14246
- ancestorScroll && ancestor.addEventListener('scroll', update, {
14247
- passive: true
14248
- });
14238
+ ancestorScroll && ancestor.addEventListener('scroll', update);
14249
14239
  ancestorResize && ancestor.addEventListener('resize', update);
14250
14240
  });
14251
- const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
14241
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;
14252
14242
  let reobserveFrame = -1;
14253
14243
  let resizeObserver = null;
14254
14244
  if (elementResize) {
@@ -14377,11 +14367,9 @@ const computePosition = (reference, floating, options) => {
14377
14367
  // multiple lifecycle resets re-use the same result. It only lives for a
14378
14368
  // single call. If other functions become expensive, we can add them as well.
14379
14369
  const cache = new Map();
14380
- const mergedOptions = {
14381
- platform,
14382
- ...options
14383
- };
14370
+ const mergedOptions = options != null ? options : {};
14384
14371
  const platformWithCache = {
14372
+ ...platform,
14385
14373
  ...mergedOptions.platform,
14386
14374
  _c: cache
14387
14375
  };
@@ -17039,6 +17027,15 @@ getDecoder(xmlDecodeTree);
17039
17027
  function decodeHTML(str, mode = DecodingMode.Legacy) {
17040
17028
  return htmlDecoder(str, mode);
17041
17029
  }
17030
+ /**
17031
+ * Decodes an HTML string, requiring all entities to be terminated by a semicolon.
17032
+ *
17033
+ * @param str The string to decode.
17034
+ * @returns The decoded string.
17035
+ */
17036
+ function decodeHTMLStrict(str) {
17037
+ return htmlDecoder(str, DecodingMode.Strict);
17038
+ }
17042
17039
 
17043
17040
  // Utilities
17044
17041
 
@@ -17079,7 +17076,6 @@ function arrayReplaceAt (src, pos, newElements) {
17079
17076
  }
17080
17077
 
17081
17078
  function isValidEntityCode (c) {
17082
- /* eslint no-bitwise:0 */
17083
17079
  // broken sequence
17084
17080
  if (c >= 0xD800 && c <= 0xDFFF) { return false }
17085
17081
  // never used
@@ -17107,8 +17103,8 @@ function fromCodePoint (c) {
17107
17103
  return String.fromCharCode(c)
17108
17104
  }
17109
17105
 
17110
- const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
17111
- const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
17106
+ const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
17107
+ const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
17112
17108
  const UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');
17113
17109
 
17114
17110
  const DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i;
@@ -17134,12 +17130,6 @@ function replaceEntityPattern (match, name) {
17134
17130
  return match
17135
17131
  }
17136
17132
 
17137
- /* function replaceEntities(str) {
17138
- if (str.indexOf('&') < 0) { return str; }
17139
-
17140
- return str.replace(ENTITY_RE, replaceEntityPattern);
17141
- } */
17142
-
17143
17133
  function unescapeMd (str) {
17144
17134
  if (str.indexOf('\\') < 0) { return str }
17145
17135
  return str.replace(UNESCAPE_MD_RE, '$1')
@@ -17209,13 +17199,15 @@ function isWhiteSpace (code) {
17209
17199
  return false
17210
17200
  }
17211
17201
 
17212
- /* eslint-disable max-len */
17213
-
17214
17202
  // Currently without astral characters support.
17215
17203
  function isPunctChar (ch) {
17216
17204
  return P.test(ch) || regex.test(ch)
17217
17205
  }
17218
17206
 
17207
+ function isPunctCharCode (code) {
17208
+ return isPunctChar(fromCodePoint(code))
17209
+ }
17210
+
17219
17211
  // Markdown ASCII punctuation characters.
17220
17212
  //
17221
17213
  // !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
@@ -17277,6 +17269,7 @@ function normalizeReference (str) {
17277
17269
  // (remove this when node v10 is no longer supported).
17278
17270
  //
17279
17271
  if ('ẞ'.toLowerCase() === 'Ṿ') {
17272
+ /* c8 ignore next 2 */
17280
17273
  str = str.replace(/ẞ/g, 'ß');
17281
17274
  }
17282
17275
 
@@ -17315,6 +17308,28 @@ function normalizeReference (str) {
17315
17308
  return str.toLowerCase().toUpperCase()
17316
17309
  }
17317
17310
 
17311
+ function isAsciiTrimmable (c) {
17312
+ return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d
17313
+ }
17314
+
17315
+ // "Light" .trim() for blocks (headers, paragraphs), where unicode spaces
17316
+ // should be preserved.
17317
+ function asciiTrim (str) {
17318
+ let start = 0;
17319
+ for (; start < str.length; start++) {
17320
+ if (!isAsciiTrimmable(str.charCodeAt(start))) {
17321
+ break
17322
+ }
17323
+ }
17324
+ let end = str.length - 1;
17325
+ for (; end >= start; end--) {
17326
+ if (!isAsciiTrimmable(str.charCodeAt(end))) {
17327
+ break
17328
+ }
17329
+ }
17330
+ return str.slice(start, end + 1)
17331
+ }
17332
+
17318
17333
  // Re-export libraries commonly used in both markdown-it and its plugins,
17319
17334
  // so plugins won't have to depend on them explicitly, which reduces their
17320
17335
  // bundled size (e.g. a browser build).
@@ -17337,8 +17352,10 @@ var utils = /*#__PURE__*/Object.freeze({
17337
17352
  isWhiteSpace: isWhiteSpace,
17338
17353
  isMdAsciiPunct: isMdAsciiPunct,
17339
17354
  isPunctChar: isPunctChar,
17355
+ isPunctCharCode: isPunctCharCode,
17340
17356
  escapeRE: escapeRE$1,
17341
- normalizeReference: normalizeReference
17357
+ normalizeReference: normalizeReference,
17358
+ asciiTrim: asciiTrim
17342
17359
  });
17343
17360
 
17344
17361
  // Parse link label
@@ -17439,7 +17456,7 @@ function parseLinkDestination (str, start, max) {
17439
17456
  if (code < 0x20 || code === 0x7F) { break }
17440
17457
 
17441
17458
  if (code === 0x5C /* \ */ && pos + 1 < max) {
17442
- if (str.charCodeAt(pos + 1) === 0x20) { break }
17459
+ if (str.charCodeAt(pos + 1) === 0x20) { pos++; continue }
17443
17460
  pos += 2;
17444
17461
  continue
17445
17462
  }
@@ -17552,7 +17569,7 @@ const default_rules = {};
17552
17569
  default_rules.code_inline = function (tokens, idx, options, env, slf) {
17553
17570
  const token = tokens[idx];
17554
17571
 
17555
- return '<code' + slf.renderAttrs(token) + '>' +
17572
+ return '<code' + slf.renderAttrs(token) + '>' +
17556
17573
  escapeHtml(token.content) +
17557
17574
  '</code>'
17558
17575
  };
@@ -17560,7 +17577,7 @@ default_rules.code_inline = function (tokens, idx, options, env, slf) {
17560
17577
  default_rules.code_block = function (tokens, idx, options, env, slf) {
17561
17578
  const token = tokens[idx];
17562
17579
 
17563
- return '<pre' + slf.renderAttrs(token) + '><code>' +
17580
+ return '<pre' + slf.renderAttrs(token) + '><code>' +
17564
17581
  escapeHtml(tokens[idx].content) +
17565
17582
  '</code></pre>\n'
17566
17583
  };
@@ -18213,28 +18230,28 @@ function Token (type, tag, nesting) {
18213
18230
  *
18214
18231
  * Type of the token (string, e.g. "paragraph_open")
18215
18232
  **/
18216
- this.type = type;
18233
+ this.type = type;
18217
18234
 
18218
18235
  /**
18219
18236
  * Token#tag -> String
18220
18237
  *
18221
18238
  * html tag name, e.g. "p"
18222
18239
  **/
18223
- this.tag = tag;
18240
+ this.tag = tag;
18224
18241
 
18225
18242
  /**
18226
18243
  * Token#attrs -> Array
18227
18244
  *
18228
18245
  * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
18229
18246
  **/
18230
- this.attrs = null;
18247
+ this.attrs = null;
18231
18248
 
18232
18249
  /**
18233
18250
  * Token#map -> Array
18234
18251
  *
18235
18252
  * Source map info. Format: `[ line_begin, line_end ]`
18236
18253
  **/
18237
- this.map = null;
18254
+ this.map = null;
18238
18255
 
18239
18256
  /**
18240
18257
  * Token#nesting -> Number
@@ -18245,14 +18262,14 @@ function Token (type, tag, nesting) {
18245
18262
  * - `0` means the tag is self-closing
18246
18263
  * - `-1` means the tag is closing
18247
18264
  **/
18248
- this.nesting = nesting;
18265
+ this.nesting = nesting;
18249
18266
 
18250
18267
  /**
18251
18268
  * Token#level -> Number
18252
18269
  *
18253
18270
  * nesting level, the same as `state.level`
18254
18271
  **/
18255
- this.level = 0;
18272
+ this.level = 0;
18256
18273
 
18257
18274
  /**
18258
18275
  * Token#children -> Array
@@ -18267,14 +18284,14 @@ function Token (type, tag, nesting) {
18267
18284
  * In a case of self-closing tag (code, html, fence, etc.),
18268
18285
  * it has contents of this tag.
18269
18286
  **/
18270
- this.content = '';
18287
+ this.content = '';
18271
18288
 
18272
18289
  /**
18273
18290
  * Token#markup -> String
18274
18291
  *
18275
18292
  * '*' or '_' for emphasis, fence string for fence, etc.
18276
18293
  **/
18277
- this.markup = '';
18294
+ this.markup = '';
18278
18295
 
18279
18296
  /**
18280
18297
  * Token#info -> String
@@ -18285,14 +18302,14 @@ function Token (type, tag, nesting) {
18285
18302
  * - The value "auto" for autolink "link_open" and "link_close" tokens
18286
18303
  * - The string value of the item marker for ordered-list "list_item_open" tokens
18287
18304
  **/
18288
- this.info = '';
18305
+ this.info = '';
18289
18306
 
18290
18307
  /**
18291
18308
  * Token#meta -> Object
18292
18309
  *
18293
18310
  * A place for plugins to store an arbitrary data
18294
18311
  **/
18295
- this.meta = null;
18312
+ this.meta = null;
18296
18313
 
18297
18314
  /**
18298
18315
  * Token#block -> Boolean
@@ -18300,7 +18317,7 @@ function Token (type, tag, nesting) {
18300
18317
  * True for block-level tokens, false for inline tokens.
18301
18318
  * Used in renderer to calculate line breaks
18302
18319
  **/
18303
- this.block = false;
18320
+ this.block = false;
18304
18321
 
18305
18322
  /**
18306
18323
  * Token#hidden -> Boolean
@@ -18308,7 +18325,7 @@ function Token (type, tag, nesting) {
18308
18325
  * If it's true, ignore this element when rendering. Used for tight lists
18309
18326
  * to hide paragraphs.
18310
18327
  **/
18311
- this.hidden = false;
18328
+ this.hidden = false;
18312
18329
  }
18313
18330
 
18314
18331
  /**
@@ -18402,8 +18419,8 @@ StateCore.prototype.Token = Token;
18402
18419
  // Normalize input string
18403
18420
 
18404
18421
  // https://spec.commonmark.org/0.29/#line-ending
18405
- const NEWLINES_RE = /\r\n?|\n/g;
18406
- const NULL_RE = /\0/g;
18422
+ const NEWLINES_RE = /\r\n?|\n/g;
18423
+ const NULL_RE = /\0/g;
18407
18424
 
18408
18425
  function normalize (state) {
18409
18426
  let str;
@@ -18421,9 +18438,9 @@ function block (state) {
18421
18438
  let token;
18422
18439
 
18423
18440
  if (state.inlineMode) {
18424
- token = new state.Token('inline', '', 0);
18425
- token.content = state.src;
18426
- token.map = [0, 1];
18441
+ token = new state.Token('inline', '', 0);
18442
+ token.content = state.src;
18443
+ token.map = [0, 1];
18427
18444
  token.children = [];
18428
18445
  state.tokens.push(token);
18429
18446
  } else {
@@ -18444,6 +18461,9 @@ function inline (state) {
18444
18461
  }
18445
18462
 
18446
18463
  // Replace link-like texts with link nodes.
18464
+ //
18465
+ // Currently restricted by `md.validateLink()` to http/https/ftp
18466
+ //
18447
18467
 
18448
18468
  function isLinkOpen$1 (str) {
18449
18469
  return /^<a[>\s]/i.test(str)
@@ -18463,7 +18483,8 @@ function linkify$1 (state) {
18463
18483
  continue
18464
18484
  }
18465
18485
 
18466
- let tokens = blockTokens[j].children;
18486
+ const tokens = blockTokens[j].children;
18487
+ const replacements = [];
18467
18488
 
18468
18489
  let htmlLinkLevel = 0;
18469
18490
 
@@ -18533,43 +18554,70 @@ function linkify$1 (state) {
18533
18554
  const pos = links[ln].index;
18534
18555
 
18535
18556
  if (pos > lastPos) {
18536
- const token = new state.Token('text', '', 0);
18557
+ const token = new state.Token('text', '', 0);
18537
18558
  token.content = text.slice(lastPos, pos);
18538
- token.level = level;
18559
+ token.level = level;
18539
18560
  nodes.push(token);
18540
18561
  }
18541
18562
 
18542
- const token_o = new state.Token('link_open', 'a', 1);
18543
- token_o.attrs = [['href', fullUrl]];
18544
- token_o.level = level++;
18545
- token_o.markup = 'linkify';
18546
- token_o.info = 'auto';
18563
+ const token_o = new state.Token('link_open', 'a', 1);
18564
+ token_o.attrs = [['href', fullUrl]];
18565
+ token_o.level = level++;
18566
+ token_o.markup = 'linkify';
18567
+ token_o.info = 'auto';
18547
18568
  nodes.push(token_o);
18548
18569
 
18549
- const token_t = new state.Token('text', '', 0);
18570
+ const token_t = new state.Token('text', '', 0);
18550
18571
  token_t.content = urlText;
18551
- token_t.level = level;
18572
+ token_t.level = level;
18552
18573
  nodes.push(token_t);
18553
18574
 
18554
- const token_c = new state.Token('link_close', 'a', -1);
18555
- token_c.level = --level;
18556
- token_c.markup = 'linkify';
18557
- token_c.info = 'auto';
18575
+ const token_c = new state.Token('link_close', 'a', -1);
18576
+ token_c.level = --level;
18577
+ token_c.markup = 'linkify';
18578
+ token_c.info = 'auto';
18558
18579
  nodes.push(token_c);
18559
18580
 
18560
18581
  lastPos = links[ln].lastIndex;
18561
18582
  }
18562
18583
  if (lastPos < text.length) {
18563
- const token = new state.Token('text', '', 0);
18584
+ const token = new state.Token('text', '', 0);
18564
18585
  token.content = text.slice(lastPos);
18565
- token.level = level;
18586
+ token.level = level;
18566
18587
  nodes.push(token);
18567
18588
  }
18568
18589
 
18569
- // replace current node
18570
- blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
18590
+ replacements.push({ index: i, nodes });
18571
18591
  }
18572
18592
  }
18593
+
18594
+ if (replacements.length > 0) {
18595
+ let newTokensLength = tokens.length;
18596
+ for (const replacement of replacements) {
18597
+ newTokensLength += replacement.nodes.length - 1;
18598
+ }
18599
+
18600
+ const newTokens = new Array(newTokensLength);
18601
+ let replacementIndex = 0;
18602
+ let newTokenIndex = 0;
18603
+
18604
+ replacements.reverse();
18605
+
18606
+ for (let i = 0; i < tokens.length; i++) {
18607
+ const replacement = replacements[replacementIndex];
18608
+
18609
+ if (replacement?.index === i) {
18610
+ for (const node of replacement.nodes) {
18611
+ newTokens[newTokenIndex++] = node;
18612
+ }
18613
+ replacementIndex++;
18614
+ } else {
18615
+ newTokens[newTokenIndex++] = tokens[i];
18616
+ }
18617
+ }
18618
+
18619
+ blockTokens[j].children = newTokens;
18620
+ }
18573
18621
  }
18574
18622
  }
18575
18623
 
@@ -18680,15 +18728,52 @@ function replace (state) {
18680
18728
  const QUOTE_TEST_RE = /['"]/;
18681
18729
  const QUOTE_RE = /['"]/g;
18682
18730
  const APOSTROPHE = '\u2019'; /* ’ */
18731
+ // Caps memory on malicious input
18732
+ const MAX_OPENERS = 1000;
18733
+
18734
+ function truncateStack (stack, heads, length) {
18735
+ while (stack.length > length) {
18736
+ const item = stack.pop();
18737
+ if (item.isSingleQuote) {
18738
+ heads.single = item.prevSameQuoteIdx;
18739
+ } else {
18740
+ heads.double = item.prevSameQuoteIdx;
18741
+ }
18742
+ }
18743
+ }
18744
+
18745
+ function addReplacement (replacements, tokenIdx, pos, ch) {
18746
+ if (!replacements[tokenIdx]) {
18747
+ replacements[tokenIdx] = [];
18748
+ }
18683
18749
 
18684
- function replaceAt (str, index, ch) {
18685
- return str.slice(0, index) + ch + str.slice(index + 1)
18750
+ replacements[tokenIdx].push({ pos, ch });
18751
+ }
18752
+
18753
+ function applyReplacements (str, replacements) {
18754
+ let result = '';
18755
+ let lastPos = 0;
18756
+
18757
+ replacements.sort((a, b) => a.pos - b.pos);
18758
+
18759
+ for (let i = 0; i < replacements.length; i++) {
18760
+ const replacement = replacements[i];
18761
+
18762
+ result += str.slice(lastPos, replacement.pos) + replacement.ch;
18763
+ lastPos = replacement.pos + 1;
18764
+ }
18765
+
18766
+ return result + str.slice(lastPos)
18686
18767
  }
18687
18768
 
18688
18769
  function process_inlines (tokens, state) {
18689
18770
  let j;
18690
18771
 
18691
18772
  const stack = [];
18773
+ // stack indexes of topmost openers of each type (-1 if none)
18774
+ const heads = { single: -1, double: -1 };
18775
+ // token index -> list of replacements in the original token content
18776
+ const replacements = {};
18692
18777
 
18693
18778
  for (let i = 0; i < tokens.length; i++) {
18694
18779
  const token = tokens[i];
@@ -18698,13 +18783,13 @@ function process_inlines (tokens, state) {
18698
18783
  for (j = stack.length - 1; j >= 0; j--) {
18699
18784
  if (stack[j].level <= thisLevel) { break }
18700
18785
  }
18701
- stack.length = j + 1;
18786
+ truncateStack(stack, heads, j + 1);
18702
18787
 
18703
18788
  if (token.type !== 'text') { continue }
18704
18789
 
18705
- let text = token.content;
18790
+ const text = token.content;
18706
18791
  let pos = 0;
18707
- let max = text.length;
18792
+ const max = text.length;
18708
18793
 
18709
18794
  /* eslint no-labels:0,block-scoped-var:0 */
18710
18795
  OUTER:
@@ -18752,8 +18837,8 @@ function process_inlines (tokens, state) {
18752
18837
  }
18753
18838
  }
18754
18839
 
18755
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
18756
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
18840
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
18841
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
18757
18842
 
18758
18843
  const isLastWhiteSpace = isWhiteSpace(lastChar);
18759
18844
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -18796,60 +18881,60 @@ function process_inlines (tokens, state) {
18796
18881
  if (!canOpen && !canClose) {
18797
18882
  // middle of word
18798
18883
  if (isSingle) {
18799
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
18884
+ addReplacement(replacements, i, t.index, APOSTROPHE);
18800
18885
  }
18801
18886
  continue
18802
18887
  }
18803
18888
 
18804
18889
  if (canClose) {
18805
- // this could be a closing quote, rewind the stack to get a match
18806
- for (j = stack.length - 1; j >= 0; j--) {
18807
- let item = stack[j];
18808
- if (stack[j].level < thisLevel) { break }
18809
- if (item.single === isSingle && stack[j].level === thisLevel) {
18810
- item = stack[j];
18811
-
18812
- let openQuote;
18813
- let closeQuote;
18814
- if (isSingle) {
18815
- openQuote = state.md.options.quotes[2];
18816
- closeQuote = state.md.options.quotes[3];
18817
- } else {
18818
- openQuote = state.md.options.quotes[0];
18819
- closeQuote = state.md.options.quotes[1];
18820
- }
18821
-
18822
- // replace token.content *before* tokens[item.token].content,
18823
- // because, if they are pointing at the same token, replaceAt
18824
- // could mess up indices when quote length != 1
18825
- token.content = replaceAt(token.content, t.index, closeQuote);
18826
- tokens[item.token].content = replaceAt(
18827
- tokens[item.token].content, item.pos, openQuote);
18828
-
18829
- pos += closeQuote.length - 1;
18830
- if (item.token === i) { pos += openQuote.length - 1; }
18890
+ // Stack levels never decrease, so an opener of this type below
18891
+ // the current level means there is no match
18892
+ j = isSingle ? heads.single : heads.double;
18893
+ if (j >= 0 && stack[j].level === thisLevel) {
18894
+ const item = stack[j];
18895
+
18896
+ let openQuote;
18897
+ let closeQuote;
18898
+ if (isSingle) {
18899
+ openQuote = state.md.options.quotes[2];
18900
+ closeQuote = state.md.options.quotes[3];
18901
+ } else {
18902
+ openQuote = state.md.options.quotes[0];
18903
+ closeQuote = state.md.options.quotes[1];
18904
+ }
18831
18905
 
18832
- text = token.content;
18833
- max = text.length;
18906
+ addReplacement(replacements, i, t.index, closeQuote);
18907
+ addReplacement(replacements, item.tokenIdx, item.contentPos, openQuote);
18834
18908
 
18835
- stack.length = j;
18836
- continue OUTER
18837
- }
18909
+ truncateStack(stack, heads, j);
18910
+ continue OUTER
18838
18911
  }
18839
18912
  }
18840
18913
 
18841
18914
  if (canOpen) {
18915
+ if (stack.length >= MAX_OPENERS) { return }
18842
18916
  stack.push({
18843
- token: i,
18844
- pos: t.index,
18845
- single: isSingle,
18846
- level: thisLevel
18917
+ tokenIdx: i,
18918
+ contentPos: t.index,
18919
+ isSingleQuote: isSingle,
18920
+ level: thisLevel,
18921
+ // stack index of the previous opener of the same quote type, -1 if none
18922
+ prevSameQuoteIdx: isSingle ? heads.single : heads.double
18847
18923
  });
18924
+ if (isSingle) {
18925
+ heads.single = stack.length - 1;
18926
+ } else {
18927
+ heads.double = stack.length - 1;
18928
+ }
18848
18929
  } else if (canClose && isSingle) {
18849
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
18930
+ addReplacement(replacements, i, t.index, APOSTROPHE);
18850
18931
  }
18851
18932
  }
18852
18933
  }
18934
+
18935
+ Object.keys(replacements).forEach(function (tokenIdx) {
18936
+ tokens[tokenIdx].content = applyReplacements(tokens[tokenIdx].content, replacements[tokenIdx]);
18937
+ });
18853
18938
  }
18854
18939
 
18855
18940
  function smartquotes (state) {
@@ -18918,15 +19003,15 @@ function text_join (state) {
18918
19003
  **/
18919
19004
 
18920
19005
  const _rules$2 = [
18921
- ['normalize', normalize],
18922
- ['block', block],
18923
- ['inline', inline],
18924
- ['linkify', linkify$1],
18925
- ['replacements', replace],
18926
- ['smartquotes', smartquotes],
19006
+ ['normalize', normalize],
19007
+ ['block', block],
19008
+ ['inline', inline],
19009
+ ['linkify', linkify$1],
19010
+ ['replacements', replace],
19011
+ ['smartquotes', smartquotes],
18927
19012
  // `text_join` finds `text_special` tokens (for escape sequences)
18928
19013
  // and joins them with the rest of the text
18929
- ['text_join', text_join]
19014
+ ['text_join', text_join]
18930
19015
  ];
18931
19016
 
18932
19017
  /**
@@ -18966,7 +19051,7 @@ function StateBlock (src, md, env, tokens) {
18966
19051
  this.src = src;
18967
19052
 
18968
19053
  // link to parser instance
18969
- this.md = md;
19054
+ this.md = md;
18970
19055
 
18971
19056
  this.env = env;
18972
19057
 
@@ -18997,11 +19082,11 @@ function StateBlock (src, md, env, tokens) {
18997
19082
 
18998
19083
  // required block content indent (for example, if we are
18999
19084
  // inside a list, it would be positioned after list marker)
19000
- this.blkIndent = 0;
19001
- this.line = 0; // line index in src
19002
- this.lineMax = 0; // lines count
19003
- this.tight = false; // loose/tight mode for lists
19004
- this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
19085
+ this.blkIndent = 0;
19086
+ this.line = 0; // line index in src
19087
+ this.lineMax = 0; // lines count
19088
+ this.tight = false; // loose/tight mode for lists
19089
+ this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
19005
19090
  this.listIndent = -1; // indent of the current list block (-1 if there isn't any)
19006
19091
 
19007
19092
  // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'
@@ -19327,11 +19412,11 @@ function table (state, startLine, endLine, silent) {
19327
19412
  for (let i = 0; i < columns.length; i++) {
19328
19413
  const token_ho = state.push('th_open', 'th', 1);
19329
19414
  if (aligns[i]) {
19330
- token_ho.attrs = [['style', 'text-align:' + aligns[i]]];
19415
+ token_ho.attrs = [['style', 'text-align:' + aligns[i]]];
19331
19416
  }
19332
19417
 
19333
19418
  const token_il = state.push('inline', '', 0);
19334
- token_il.content = columns[i].trim();
19419
+ token_il.content = columns[i].trim();
19335
19420
  token_il.children = [];
19336
19421
 
19337
19422
  state.push('th_close', 'th', -1);
@@ -19378,11 +19463,11 @@ function table (state, startLine, endLine, silent) {
19378
19463
  for (let i = 0; i < columnCount; i++) {
19379
19464
  const token_tdo = state.push('td_open', 'td', 1);
19380
19465
  if (aligns[i]) {
19381
- token_tdo.attrs = [['style', 'text-align:' + aligns[i]]];
19466
+ token_tdo.attrs = [['style', 'text-align:' + aligns[i]]];
19382
19467
  }
19383
19468
 
19384
19469
  const token_il = state.push('inline', '', 0);
19385
- token_il.content = columns[i] ? columns[i].trim() : '';
19470
+ token_il.content = columns[i] ? columns[i].trim() : '';
19386
19471
  token_il.children = [];
19387
19472
 
19388
19473
  state.push('td_close', 'td', -1);
@@ -19427,9 +19512,9 @@ function code (state, startLine, endLine/*, silent */) {
19427
19512
 
19428
19513
  state.line = last;
19429
19514
 
19430
- const token = state.push('code_block', 'code', 0);
19515
+ const token = state.push('code_block', 'code', 0);
19431
19516
  token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n';
19432
- token.map = [startLine, state.line];
19517
+ token.map = [startLine, state.line];
19433
19518
 
19434
19519
  return true
19435
19520
  }
@@ -19520,11 +19605,11 @@ function fence (state, startLine, endLine, silent) {
19520
19605
 
19521
19606
  state.line = nextLine + (haveEndMarker ? 1 : 0);
19522
19607
 
19523
- const token = state.push('fence', 'code', 0);
19524
- token.info = params;
19608
+ const token = state.push('fence', 'code', 0);
19609
+ token.info = params;
19525
19610
  token.content = state.getLines(startLine + 1, nextLine, len, true);
19526
- token.markup = markup;
19527
- token.map = [startLine, state.line];
19611
+ token.markup = markup;
19612
+ token.map = [startLine, state.line];
19528
19613
 
19529
19614
  return true
19530
19615
  }
@@ -19547,10 +19632,10 @@ function blockquote (state, startLine, endLine, silent) {
19547
19632
  // so no point trying to find the end of it in silent mode
19548
19633
  if (silent) { return true }
19549
19634
 
19550
- const oldBMarks = [];
19635
+ const oldBMarks = [];
19551
19636
  const oldBSCount = [];
19552
- const oldSCount = [];
19553
- const oldTShift = [];
19637
+ const oldSCount = [];
19638
+ const oldTShift = [];
19554
19639
 
19555
19640
  const terminatorRules = state.md.block.ruler.getRules('blockquote');
19556
19641
 
@@ -19710,14 +19795,14 @@ function blockquote (state, startLine, endLine, silent) {
19710
19795
  const oldIndent = state.blkIndent;
19711
19796
  state.blkIndent = 0;
19712
19797
 
19713
- const token_o = state.push('blockquote_open', 'blockquote', 1);
19798
+ const token_o = state.push('blockquote_open', 'blockquote', 1);
19714
19799
  token_o.markup = '>';
19715
19800
  const lines = [startLine, 0];
19716
- token_o.map = lines;
19801
+ token_o.map = lines;
19717
19802
 
19718
19803
  state.md.block.tokenize(state, startLine, nextLine);
19719
19804
 
19720
- const token_c = state.push('blockquote_close', 'blockquote', -1);
19805
+ const token_c = state.push('blockquote_close', 'blockquote', -1);
19721
19806
  token_c.markup = '>';
19722
19807
 
19723
19808
  state.lineMax = oldLineMax;
@@ -19769,8 +19854,8 @@ function hr (state, startLine, endLine, silent) {
19769
19854
 
19770
19855
  state.line = startLine + 1;
19771
19856
 
19772
- const token = state.push('hr', 'hr', 0);
19773
- token.map = [startLine, state.line];
19857
+ const token = state.push('hr', 'hr', 0);
19858
+ token.map = [startLine, state.line];
19774
19859
  token.markup = Array(cnt + 1).join(String.fromCharCode(marker));
19775
19860
 
19776
19861
  return true
@@ -19932,16 +20017,16 @@ function list (state, startLine, endLine, silent) {
19932
20017
  const listTokIdx = state.tokens.length;
19933
20018
 
19934
20019
  if (isOrdered) {
19935
- token = state.push('ordered_list_open', 'ol', 1);
20020
+ token = state.push('ordered_list_open', 'ol', 1);
19936
20021
  if (markerValue !== 1) {
19937
20022
  token.attrs = [['start', markerValue]];
19938
20023
  }
19939
20024
  } else {
19940
- token = state.push('bullet_list_open', 'ul', 1);
20025
+ token = state.push('bullet_list_open', 'ul', 1);
19941
20026
  }
19942
20027
 
19943
20028
  const listLines = [nextLine, 0];
19944
- token.map = listLines;
20029
+ token.map = listLines;
19945
20030
  token.markup = String.fromCharCode(markerCharCode);
19946
20031
 
19947
20032
  //
@@ -19994,10 +20079,10 @@ function list (state, startLine, endLine, silent) {
19994
20079
  const indent = initial + indentAfterMarker;
19995
20080
 
19996
20081
  // Run subparser & write tokens
19997
- token = state.push('list_item_open', 'li', 1);
20082
+ token = state.push('list_item_open', 'li', 1);
19998
20083
  token.markup = String.fromCharCode(markerCharCode);
19999
20084
  const itemLines = [nextLine, 0];
20000
- token.map = itemLines;
20085
+ token.map = itemLines;
20001
20086
  if (isOrdered) {
20002
20087
  token.info = state.src.slice(start, posAfterMarker - 1);
20003
20088
  }
@@ -20046,7 +20131,7 @@ function list (state, startLine, endLine, silent) {
20046
20131
  state.sCount[nextLine] = oldSCount;
20047
20132
  state.tight = oldTight;
20048
20133
 
20049
- token = state.push('list_item_close', 'li', -1);
20134
+ token = state.push('list_item_close', 'li', -1);
20050
20135
  token.markup = String.fromCharCode(markerCharCode);
20051
20136
 
20052
20137
  nextLine = state.line;
@@ -20106,114 +20191,141 @@ function list (state, startLine, endLine, silent) {
20106
20191
  return true
20107
20192
  }
20108
20193
 
20109
- function reference (state, startLine, _endLine, silent) {
20110
- let pos = state.bMarks[startLine] + state.tShift[startLine];
20111
- let max = state.eMarks[startLine];
20112
- let nextLine = startLine + 1;
20113
-
20114
- // if it's indented more than 3 spaces, it should be a code block
20115
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20194
+ // CommonMark limits reference labels to 999 Unicode code points.
20195
+ const MAX_LABEL_LENGTH = 999;
20116
20196
 
20117
- if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false }
20197
+ function countCodePoints (str) {
20198
+ let length = str.length;
20118
20199
 
20119
- function getNextLine (nextLine) {
20120
- const endLine = state.lineMax;
20200
+ for (let i = 0; i < str.length - 1; i++) {
20201
+ const high = str.charCodeAt(i);
20202
+ if (high < 0xD800 || high > 0xDBFF) { continue }
20121
20203
 
20122
- if (nextLine >= endLine || state.isEmpty(nextLine)) {
20123
- // empty line or end of input
20124
- return null
20204
+ const low = str.charCodeAt(i + 1);
20205
+ if (low >= 0xDC00 && low <= 0xDFFF) {
20206
+ length--;
20207
+ i++;
20125
20208
  }
20209
+ }
20126
20210
 
20127
- let isContinuation = false;
20211
+ return length
20212
+ }
20128
20213
 
20129
- // this would be a code block normally, but after paragraph
20130
- // it's considered a lazy continuation regardless of what's there
20131
- if (state.sCount[nextLine] - state.blkIndent > 3) { isContinuation = true; }
20214
+ // Exclusive end offset of the line, after its newline if present
20215
+ function lineEnd (state, line) {
20216
+ return Math.min(state.eMarks[line] + 1, state.src.length)
20217
+ }
20132
20218
 
20133
- // quirk for blockquotes, this line should already be checked by that rule
20134
- if (state.sCount[nextLine] < 0) { isContinuation = true; }
20135
-
20136
- if (!isContinuation) {
20137
- const terminatorRules = state.md.block.ruler.getRules('reference');
20138
- const oldParentType = state.parentType;
20139
- state.parentType = 'reference';
20140
-
20141
- // Some tags can terminate paragraph without empty line.
20142
- let terminate = false;
20143
- for (let i = 0, l = terminatorRules.length; i < l; i++) {
20144
- if (terminatorRules[i](state, nextLine, endLine, true)) {
20145
- terminate = true;
20146
- break
20147
- }
20148
- }
20219
+ // Returns -1 if the reference can't continue on this line
20220
+ function getNextLinePos (state, nextLine) {
20221
+ const endLine = state.lineMax;
20222
+
20223
+ if (nextLine >= endLine || state.isEmpty(nextLine)) {
20224
+ // empty line or end of input
20225
+ return -1
20226
+ }
20227
+
20228
+ let isContinuation = false;
20149
20229
 
20150
- state.parentType = oldParentType;
20151
- if (terminate) {
20152
- // terminated by another block
20153
- return null
20230
+ // this would be a code block normally, but after paragraph
20231
+ // it's considered a lazy continuation regardless of what's there
20232
+ if (state.sCount[nextLine] - state.blkIndent > 3) { isContinuation = true; }
20233
+
20234
+ // quirk for blockquotes, this line should already be checked by that rule
20235
+ if (state.sCount[nextLine] < 0) { isContinuation = true; }
20236
+
20237
+ if (!isContinuation) {
20238
+ const terminatorRules = state.md.block.ruler.getRules('reference');
20239
+ const oldParentType = state.parentType;
20240
+ state.parentType = 'reference';
20241
+
20242
+ // Some tags can terminate paragraph without empty line.
20243
+ let terminate = false;
20244
+ for (let i = 0, l = terminatorRules.length; i < l; i++) {
20245
+ if (terminatorRules[i](state, nextLine, endLine, true)) {
20246
+ terminate = true;
20247
+ break
20154
20248
  }
20155
20249
  }
20156
20250
 
20157
- const pos = state.bMarks[nextLine] + state.tShift[nextLine];
20158
- const max = state.eMarks[nextLine];
20159
-
20160
- // max + 1 explicitly includes the newline
20161
- return state.src.slice(pos, max + 1)
20251
+ state.parentType = oldParentType;
20252
+ if (terminate) {
20253
+ // terminated by another block
20254
+ return -1
20255
+ }
20162
20256
  }
20163
20257
 
20164
- let str = state.src.slice(pos, max + 1);
20258
+ return state.bMarks[nextLine] + state.tShift[nextLine]
20259
+ }
20260
+
20261
+ function reference (state, startLine, _endLine, silent) {
20262
+ const src = state.src;
20263
+ let pos = state.bMarks[startLine] + state.tShift[startLine];
20264
+ let nextLine = startLine + 1;
20165
20265
 
20166
- max = str.length;
20266
+ // if it's indented more than 3 spaces, it should be a code block
20267
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20268
+
20269
+ if (src.charCodeAt(pos) !== 0x5B/* [ */) { return false }
20270
+
20271
+ // Scan the source directly: indexing a string after each appended line
20272
+ // can make V8 copy the accumulated prefix on every continuation.
20273
+ let max = lineEnd(state, startLine);
20274
+
20275
+ let rawLabel = '';
20167
20276
  let labelEnd = -1;
20277
+ let segmentStart = ++pos;
20168
20278
 
20169
- for (pos = 1; pos < max; pos++) {
20170
- const ch = str.charCodeAt(pos);
20171
- if (ch === 0x5B /* [ */) {
20172
- return false
20173
- } else if (ch === 0x5D /* ] */) {
20279
+ while (pos < max) {
20280
+ if (rawLabel.length + pos - segmentStart > MAX_LABEL_LENGTH * 2) { return false }
20281
+
20282
+ let ch = src.charCodeAt(pos);
20283
+ if (ch === 0x5B /* [ */) { return false }
20284
+ if (ch === 0x5D /* ] */) {
20174
20285
  labelEnd = pos;
20175
20286
  break
20176
- } else if (ch === 0x0A /* \n */) {
20177
- const lineContent = getNextLine(nextLine);
20178
- if (lineContent !== null) {
20179
- str += lineContent;
20180
- max = str.length;
20181
- nextLine++;
20182
- }
20183
- } else if (ch === 0x5C /* \ */) {
20184
- pos++;
20185
- if (pos < max && str.charCodeAt(pos) === 0x0A) {
20186
- const lineContent = getNextLine(nextLine);
20187
- if (lineContent !== null) {
20188
- str += lineContent;
20189
- max = str.length;
20190
- nextLine++;
20191
- }
20192
- }
20193
20287
  }
20288
+ if (ch === 0x5C /* \ */) { ch = src.charCodeAt(++pos); }
20289
+
20290
+ if (ch === 0x0A /* \n */ && pos < max) {
20291
+ const nextPos = getNextLinePos(state, nextLine);
20292
+ if (nextPos < 0) { return false }
20293
+ rawLabel += src.slice(segmentStart, max);
20294
+ pos = segmentStart = nextPos;
20295
+ max = lineEnd(state, nextLine++);
20296
+ continue
20297
+ }
20298
+ pos++;
20194
20299
  }
20195
20300
 
20196
- if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
20301
+ if (labelEnd < 0 || src.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
20302
+
20303
+ rawLabel += src.slice(segmentStart, labelEnd);
20304
+
20305
+ if (rawLabel.length > MAX_LABEL_LENGTH && countCodePoints(rawLabel) > MAX_LABEL_LENGTH) {
20306
+ return false
20307
+ }
20197
20308
 
20198
20309
  // [label]: destination 'title'
20199
20310
  // ^^^ skip optional whitespace here
20200
- for (pos = labelEnd + 2; pos < max; pos++) {
20201
- const ch = str.charCodeAt(pos);
20311
+ pos = labelEnd + 2;
20312
+ while (pos < max) {
20313
+ const ch = src.charCodeAt(pos);
20202
20314
  if (ch === 0x0A) {
20203
- const lineContent = getNextLine(nextLine);
20204
- if (lineContent !== null) {
20205
- str += lineContent;
20206
- max = str.length;
20207
- nextLine++;
20208
- }
20209
- } else if (isSpace(ch)) ; else {
20315
+ const nextPos = getNextLinePos(state, nextLine);
20316
+ if (nextPos < 0) { break }
20317
+ pos = nextPos;
20318
+ max = lineEnd(state, nextLine++);
20319
+ } else if (isSpace(ch)) {
20320
+ pos++;
20321
+ } else {
20210
20322
  break
20211
20323
  }
20212
20324
  }
20213
20325
 
20214
20326
  // [label]: destination 'title'
20215
20327
  // ^^^^^^^^^^^ parse this
20216
- const destRes = state.md.helpers.parseLinkDestination(str, pos, max);
20328
+ const destRes = state.md.helpers.parseLinkDestination(src, pos, max);
20217
20329
  if (!destRes.ok) { return false }
20218
20330
 
20219
20331
  const href = state.md.normalizeLink(destRes.str);
@@ -20223,76 +20335,77 @@ function reference (state, startLine, _endLine, silent) {
20223
20335
 
20224
20336
  // save cursor state, we could require to rollback later
20225
20337
  const destEndPos = pos;
20338
+ const destEndMax = max;
20226
20339
  const destEndLineNo = nextLine;
20227
20340
 
20228
20341
  // [label]: destination 'title'
20229
20342
  // ^^^ skipping those spaces
20230
- const start = pos;
20231
- for (; pos < max; pos++) {
20232
- const ch = str.charCodeAt(pos);
20343
+ while (pos < max) {
20344
+ const ch = src.charCodeAt(pos);
20233
20345
  if (ch === 0x0A) {
20234
- const lineContent = getNextLine(nextLine);
20235
- if (lineContent !== null) {
20236
- str += lineContent;
20237
- max = str.length;
20238
- nextLine++;
20239
- }
20240
- } else if (isSpace(ch)) ; else {
20346
+ const nextPos = getNextLinePos(state, nextLine);
20347
+ if (nextPos < 0) { break }
20348
+ pos = nextPos;
20349
+ max = lineEnd(state, nextLine++);
20350
+ } else if (isSpace(ch)) {
20351
+ pos++;
20352
+ } else {
20241
20353
  break
20242
20354
  }
20243
20355
  }
20244
20356
 
20245
20357
  // [label]: destination 'title'
20246
20358
  // ^^^^^^^ parse this
20247
- let titleRes = state.md.helpers.parseLinkTitle(str, pos, max);
20359
+ const titleStart = pos;
20360
+ let titleRes = state.md.helpers.parseLinkTitle(src, pos, max);
20248
20361
  while (titleRes.can_continue) {
20249
- const lineContent = getNextLine(nextLine);
20250
- if (lineContent === null) break
20251
- str += lineContent;
20252
- pos = max;
20253
- max = str.length;
20254
- nextLine++;
20255
- titleRes = state.md.helpers.parseLinkTitle(str, pos, max, titleRes);
20362
+ const nextPos = getNextLinePos(state, nextLine);
20363
+ if (nextPos < 0) break
20364
+ pos = nextPos;
20365
+ max = lineEnd(state, nextLine++);
20366
+ titleRes = state.md.helpers.parseLinkTitle(src, pos, max, titleRes);
20256
20367
  }
20257
20368
  let title;
20258
20369
 
20259
- if (pos < max && start !== pos && titleRes.ok) {
20370
+ if (titleStart !== destEndPos && titleRes.ok) {
20260
20371
  title = titleRes.str;
20261
20372
  pos = titleRes.pos;
20262
20373
  } else {
20263
20374
  title = '';
20264
20375
  pos = destEndPos;
20376
+ max = destEndMax;
20265
20377
  nextLine = destEndLineNo;
20266
20378
  }
20267
20379
 
20268
20380
  // skip trailing spaces until the rest of the line
20269
20381
  while (pos < max) {
20270
- const ch = str.charCodeAt(pos);
20382
+ const ch = src.charCodeAt(pos);
20271
20383
  if (!isSpace(ch)) { break }
20272
20384
  pos++;
20273
20385
  }
20274
20386
 
20275
- if (pos < max && str.charCodeAt(pos) !== 0x0A) {
20387
+ if (pos < max && src.charCodeAt(pos) !== 0x0A) {
20276
20388
  if (title) {
20277
20389
  // garbage at the end of the line after title,
20278
20390
  // but it could still be a valid reference if we roll back
20279
20391
  title = '';
20280
20392
  pos = destEndPos;
20393
+ max = destEndMax;
20281
20394
  nextLine = destEndLineNo;
20282
20395
  while (pos < max) {
20283
- const ch = str.charCodeAt(pos);
20396
+ const ch = src.charCodeAt(pos);
20284
20397
  if (!isSpace(ch)) { break }
20285
20398
  pos++;
20286
20399
  }
20287
20400
  }
20288
20401
  }
20289
20402
 
20290
- if (pos < max && str.charCodeAt(pos) !== 0x0A) {
20403
+ if (pos < max && src.charCodeAt(pos) !== 0x0A) {
20291
20404
  // garbage at the end of the line
20292
20405
  return false
20293
20406
  }
20294
20407
 
20295
- const label = normalizeReference(str.slice(1, labelEnd));
20408
+ const label = normalizeReference(rawLabel);
20296
20409
  if (!label) {
20297
20410
  // CommonMark 0.20 disallows empty labels
20298
20411
  return false
@@ -20383,26 +20496,19 @@ var block_names = [
20383
20496
 
20384
20497
  // Regexps to match html elements
20385
20498
 
20386
- const attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
20499
+ const attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
20387
20500
 
20388
- const unquoted = '[^"\'=<>`\\x00-\\x20]+';
20501
+ const unquoted = '[^"\'=<>`\\x00-\\x20]+';
20389
20502
  const single_quoted = "'[^']*'";
20390
20503
  const double_quoted = '"[^"]*"';
20391
20504
 
20392
- const attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
20393
-
20394
- const attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
20505
+ const attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
20395
20506
 
20396
- const open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
20507
+ const attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
20397
20508
 
20398
- const close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
20399
- const comment = '<!---?>|<!--(?:[^-]|-[^-]|--[^>])*-->';
20400
- const processing = '<[?][\\s\\S]*?[?]>';
20401
- const declaration = '<![A-Za-z][^>]*>';
20402
- const cdata = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>';
20509
+ const open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
20403
20510
 
20404
- const HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
20405
- '|' + processing + '|' + declaration + '|' + cdata + ')');
20511
+ const close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
20406
20512
  const HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');
20407
20513
 
20408
20514
  // HTML block
@@ -20412,12 +20518,12 @@ const HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag +
20412
20518
  //
20413
20519
  const HTML_SEQUENCES = [
20414
20520
  [/^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true],
20415
- [/^<!--/, /-->/, true],
20416
- [/^<\?/, /\?>/, true],
20417
- [/^<![A-Z]/, />/, true],
20521
+ [/^<!--/, /-->/, true],
20522
+ [/^<\?/, /\?>/, true],
20523
+ [/^<![A-Za-z]/, />/, true],
20418
20524
  [/^<!\[CDATA\[/, /\]\]>/, true],
20419
20525
  [new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
20420
- [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
20526
+ [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
20421
20527
  ];
20422
20528
 
20423
20529
  function html_block (state, startLine, endLine, silent) {
@@ -20446,11 +20552,22 @@ function html_block (state, startLine, endLine, silent) {
20446
20552
 
20447
20553
  let nextLine = startLine + 1;
20448
20554
 
20555
+ // Block types 6 and 7 (the only ones whose end condition is a blank line)
20556
+ // have `/^$/` as their closing regexp. For all other types (1-5, e.g.
20557
+ // `<!--` comments), a blank line is regular content and must not terminate
20558
+ // the block - it ends only when its closing sequence is found.
20559
+ const endsOnBlankLine = HTML_SEQUENCES[i][1].test('');
20560
+
20449
20561
  // If we are here - we detected HTML block.
20450
20562
  // Let's roll down till block end.
20451
20563
  if (!HTML_SEQUENCES[i][1].test(lineText)) {
20452
20564
  for (; nextLine < endLine; nextLine++) {
20453
- if (state.sCount[nextLine] < state.blkIndent) { break }
20565
+ if (state.sCount[nextLine] < state.blkIndent) {
20566
+ // An outdented blank line shouldn't end a block that doesn't end on a
20567
+ // blank line (e.g. a `<!--` comment inside a list item). Such blocks
20568
+ // must continue until their closing sequence regardless of indent.
20569
+ if (endsOnBlankLine || !state.isEmpty(nextLine)) { break }
20570
+ }
20454
20571
 
20455
20572
  pos = state.bMarks[nextLine] + state.tShift[nextLine];
20456
20573
  max = state.eMarks[nextLine];
@@ -20465,8 +20582,8 @@ function html_block (state, startLine, endLine, silent) {
20465
20582
 
20466
20583
  state.line = nextLine;
20467
20584
 
20468
- const token = state.push('html_block', '', 0);
20469
- token.map = [startLine, nextLine];
20585
+ const token = state.push('html_block', '', 0);
20586
+ token.map = [startLine, nextLine];
20470
20587
  token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
20471
20588
 
20472
20589
  return true
@@ -20481,7 +20598,7 @@ function heading (state, startLine, endLine, silent) {
20481
20598
  // if it's indented more than 3 spaces, it should be a code block
20482
20599
  if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20483
20600
 
20484
- let ch = state.src.charCodeAt(pos);
20601
+ let ch = state.src.charCodeAt(pos);
20485
20602
 
20486
20603
  if (ch !== 0x23/* # */ || pos >= max) { return false }
20487
20604
 
@@ -20507,16 +20624,16 @@ function heading (state, startLine, endLine, silent) {
20507
20624
 
20508
20625
  state.line = startLine + 1;
20509
20626
 
20510
- const token_o = state.push('heading_open', 'h' + String(level), 1);
20627
+ const token_o = state.push('heading_open', 'h' + String(level), 1);
20511
20628
  token_o.markup = '########'.slice(0, level);
20512
- token_o.map = [startLine, state.line];
20629
+ token_o.map = [startLine, state.line];
20513
20630
 
20514
- const token_i = state.push('inline', '', 0);
20515
- token_i.content = state.src.slice(pos, max).trim();
20516
- token_i.map = [startLine, state.line];
20631
+ const token_i = state.push('inline', '', 0);
20632
+ token_i.content = asciiTrim(state.src.slice(pos, max));
20633
+ token_i.map = [startLine, state.line];
20517
20634
  token_i.children = [];
20518
20635
 
20519
- const token_c = state.push('heading_close', 'h' + String(level), -1);
20636
+ const token_c = state.push('heading_close', 'h' + String(level), -1);
20520
20637
  token_c.markup = '########'.slice(0, level);
20521
20638
 
20522
20639
  return true
@@ -20581,24 +20698,25 @@ function lheading (state, startLine, endLine/*, silent */) {
20581
20698
 
20582
20699
  if (!level) {
20583
20700
  // Didn't find valid underline
20701
+ state.parentType = oldParentType;
20584
20702
  return false
20585
20703
  }
20586
20704
 
20587
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
20705
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
20588
20706
 
20589
20707
  state.line = nextLine + 1;
20590
20708
 
20591
- const token_o = state.push('heading_open', 'h' + String(level), 1);
20592
- token_o.markup = String.fromCharCode(marker);
20593
- token_o.map = [startLine, state.line];
20709
+ const token_o = state.push('heading_open', 'h' + String(level), 1);
20710
+ token_o.markup = String.fromCharCode(marker);
20711
+ token_o.map = [startLine, state.line];
20594
20712
 
20595
- const token_i = state.push('inline', '', 0);
20596
- token_i.content = content;
20597
- token_i.map = [startLine, state.line - 1];
20713
+ const token_i = state.push('inline', '', 0);
20714
+ token_i.content = content;
20715
+ token_i.map = [startLine, state.line - 1];
20598
20716
  token_i.children = [];
20599
20717
 
20600
- const token_c = state.push('heading_close', 'h' + String(level), -1);
20601
- token_c.markup = String.fromCharCode(marker);
20718
+ const token_c = state.push('heading_close', 'h' + String(level), -1);
20719
+ token_c.markup = String.fromCharCode(marker);
20602
20720
 
20603
20721
  state.parentType = oldParentType;
20604
20722
 
@@ -20633,16 +20751,16 @@ function paragraph (state, startLine, endLine) {
20633
20751
  if (terminate) { break }
20634
20752
  }
20635
20753
 
20636
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
20754
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
20637
20755
 
20638
20756
  state.line = nextLine;
20639
20757
 
20640
- const token_o = state.push('paragraph_open', 'p', 1);
20641
- token_o.map = [startLine, state.line];
20758
+ const token_o = state.push('paragraph_open', 'p', 1);
20759
+ token_o.map = [startLine, state.line];
20642
20760
 
20643
- const token_i = state.push('inline', '', 0);
20644
- token_i.content = content;
20645
- token_i.map = [startLine, state.line];
20761
+ const token_i = state.push('inline', '', 0);
20762
+ token_i.content = content;
20763
+ token_i.map = [startLine, state.line];
20646
20764
  token_i.children = [];
20647
20765
 
20648
20766
  state.push('paragraph_close', 'p', -1);
@@ -20661,17 +20779,17 @@ function paragraph (state, startLine, endLine) {
20661
20779
  const _rules$1 = [
20662
20780
  // First 2 params - rule name & source. Secondary array - list of rules,
20663
20781
  // which can be terminated by this one.
20664
- ['table', table, ['paragraph', 'reference']],
20665
- ['code', code],
20666
- ['fence', fence, ['paragraph', 'reference', 'blockquote', 'list']],
20782
+ ['table', table, ['paragraph', 'reference']],
20783
+ ['code', code],
20784
+ ['fence', fence, ['paragraph', 'reference', 'blockquote', 'list']],
20667
20785
  ['blockquote', blockquote, ['paragraph', 'reference', 'blockquote', 'list']],
20668
- ['hr', hr, ['paragraph', 'reference', 'blockquote', 'list']],
20669
- ['list', list, ['paragraph', 'reference', 'blockquote']],
20670
- ['reference', reference],
20786
+ ['hr', hr, ['paragraph', 'reference', 'blockquote', 'list']],
20787
+ ['list', list, ['paragraph', 'reference', 'blockquote']],
20788
+ ['reference', reference],
20671
20789
  ['html_block', html_block, ['paragraph', 'reference', 'blockquote']],
20672
- ['heading', heading, ['paragraph', 'reference', 'blockquote']],
20673
- ['lheading', lheading],
20674
- ['paragraph', paragraph]
20790
+ ['heading', heading, ['paragraph', 'reference', 'blockquote']],
20791
+ ['lheading', lheading],
20792
+ ['paragraph', paragraph]
20675
20793
  ];
20676
20794
 
20677
20795
  /**
@@ -20799,6 +20917,10 @@ function StateInline (src, md, env, outTokens) {
20799
20917
  this.backticks = {};
20800
20918
  this.backticksScanned = false;
20801
20919
 
20920
+ // Set when html comment / PI / declaration / CDATA has no terminator,
20921
+ // to skip further scans of these constructs
20922
+ this.skipHtmlSpecial = false;
20923
+
20802
20924
  // Counter used to disable inline linkify-it execution
20803
20925
  // inside <a> and markdown links
20804
20926
  this.linkLevel = 0;
@@ -20858,8 +20980,30 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20858
20980
  const max = this.posMax;
20859
20981
  const marker = this.src.charCodeAt(start);
20860
20982
 
20861
- // treat beginning of the line as a whitespace
20862
- const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
20983
+ // Astral characters below are combined manually, because .codePointAt()
20984
+ // does not guarantee numeric type output. And we don't wish JIT cache issues.
20985
+ // The broken surrogate pairs are evaluated as U+FFFD to prevent possible
20986
+ // crashes.
20987
+
20988
+ let lastChar;
20989
+ if (start === 0) {
20990
+ // treat beginning of the line as a whitespace
20991
+ lastChar = 0x20;
20992
+ } else if (start === 1) {
20993
+ lastChar = this.src.charCodeAt(0);
20994
+ if ((lastChar & 0xF800) === 0xD800) { lastChar = 0xFFFD; }
20995
+ } else {
20996
+ lastChar = this.src.charCodeAt(start - 1);
20997
+ if ((lastChar & 0xFC00) === 0xDC00) {
20998
+ // low surrogate => add high one, replace broken pair with U+FFFD
20999
+ const highSurr = this.src.charCodeAt(start - 2);
21000
+ lastChar = (highSurr & 0xFC00) === 0xD800
21001
+ ? 0x10000 + ((highSurr - 0xD800) << 10) + (lastChar - 0xDC00)
21002
+ : 0xFFFD;
21003
+ } else if ((lastChar & 0xFC00) === 0xD800) {
21004
+ lastChar = 0xFFFD;
21005
+ }
21006
+ }
20863
21007
 
20864
21008
  let pos = start;
20865
21009
  while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
@@ -20867,10 +21011,19 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20867
21011
  const count = pos - start;
20868
21012
 
20869
21013
  // treat end of the line as a whitespace
20870
- const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
21014
+ let nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
21015
+ if ((nextChar & 0xFC00) === 0xD800) {
21016
+ // high surrogate => add low one, replace broken pair with U+FFFD
21017
+ const lowSurr = this.src.charCodeAt(pos + 1);
21018
+ nextChar = (lowSurr & 0xFC00) === 0xDC00
21019
+ ? 0x10000 + ((nextChar - 0xD800) << 10) + (lowSurr - 0xDC00)
21020
+ : 0xFFFD;
21021
+ } else if ((nextChar & 0xFC00) === 0xDC00) {
21022
+ nextChar = 0xFFFD;
21023
+ }
20871
21024
 
20872
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
20873
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
21025
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
21026
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
20874
21027
 
20875
21028
  const isLastWhiteSpace = isWhiteSpace(lastChar);
20876
21029
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -20880,8 +21033,8 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20880
21033
  const right_flanking =
20881
21034
  !isLastWhiteSpace && (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar);
20882
21035
 
20883
- const can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar);
20884
- const can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar);
21036
+ const can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar);
21037
+ const can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar);
20885
21038
 
20886
21039
  return { can_open, can_close, length: count }
20887
21040
  };
@@ -20976,10 +21129,20 @@ module.exports = function text(state, silent) {
20976
21129
  return true;
20977
21130
  }; */
20978
21131
 
20979
- // Process links like https://example.org/
21132
+ // Early process links like https://example.org/ to have priority
21133
+ // over emphasis, etc.
20980
21134
 
20981
21135
  // RFC3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
20982
- const SCHEME_RE = /(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$/i;
21136
+ function isAsciiAlpha (code) {
21137
+ return (code >= 0x41 && code <= 0x5A) || (code >= 0x61 && code <= 0x7A)
21138
+ }
21139
+
21140
+ function isSchemeChar (code) {
21141
+ return (code >= 0x41 && code <= 0x5A) ||
21142
+ (code >= 0x61 && code <= 0x7A) ||
21143
+ (code >= 0x30 && code <= 0x39) ||
21144
+ code === 0x2B || code === 0x2D || code === 0x2E
21145
+ }
20983
21146
 
20984
21147
  function linkify (state, silent) {
20985
21148
  if (!state.md.options.linkify) return false
@@ -20993,19 +21156,27 @@ function linkify (state, silent) {
20993
21156
  if (state.src.charCodeAt(pos + 1) !== 0x2F/* / */) return false
20994
21157
  if (state.src.charCodeAt(pos + 2) !== 0x2F/* / */) return false
20995
21158
 
20996
- const match = state.pending.match(SCHEME_RE);
20997
- if (!match) return false
21159
+ // Search backwards for the scheme, but no more than 10 characters, the length
21160
+ // of the pending string, or the length of the source prefix.
21161
+ // Use state.src instead of state.pending because it is faster to access.
21162
+ const protoMin = pos - Math.min(10, state.pending.length, pos);
21163
+ let protoStart = pos;
21164
+ while (protoStart > protoMin && isSchemeChar(state.src.charCodeAt(protoStart - 1))) {
21165
+ protoStart--;
21166
+ }
21167
+
21168
+ if (protoStart === pos || !isAsciiAlpha(state.src.charCodeAt(protoStart))) return false
20998
21169
 
20999
- const proto = match[1];
21170
+ const protoLength = pos - protoStart;
21000
21171
 
21001
- const link = state.md.linkify.matchAtStart(state.src.slice(pos - proto.length));
21172
+ const link = state.md.linkify.matchAtStart(state.src.slice(protoStart));
21002
21173
  if (!link) return false
21003
21174
 
21004
21175
  let url = link.url;
21005
21176
 
21006
21177
  // invalid link, but still detected by linkify somehow;
21007
21178
  // need to check to prevent infinite loop below
21008
- if (url.length <= proto.length) return false
21179
+ if (url.length <= protoLength) return false
21009
21180
 
21010
21181
  // disallow '*' at the end of the link (conflicts with emphasis)
21011
21182
  // do manual backsearch to avoid perf issues with regex /\*+$/ on "****...****a".
@@ -21021,7 +21192,7 @@ function linkify (state, silent) {
21021
21192
  if (!state.md.validateLink(fullUrl)) return false
21022
21193
 
21023
21194
  if (!silent) {
21024
- state.pending = state.pending.slice(0, -proto.length);
21195
+ state.pending = state.pending.slice(0, -protoLength);
21025
21196
 
21026
21197
  const token_o = state.push('link_open', 'a', 1);
21027
21198
  token_o.attrs = [['href', fullUrl]];
@@ -21036,7 +21207,7 @@ function linkify (state, silent) {
21036
21207
  token_c.info = 'auto';
21037
21208
  }
21038
21209
 
21039
- state.pos += url.length - proto.length;
21210
+ state.pos += url.length - protoLength;
21040
21211
  return true
21041
21212
  }
21042
21213
 
@@ -21119,6 +21290,20 @@ function escape (state, silent) {
21119
21290
  return true
21120
21291
  }
21121
21292
 
21293
+ // '\' before a space is a literal backslash. Don't consume the space, so a
21294
+ // trailing two-space hard line break is still detected by the newline rule.
21295
+ if (ch1 === 0x20) {
21296
+ if (!silent) {
21297
+ const token = state.push('text_special', '', 0);
21298
+ token.content = '\\';
21299
+ token.markup = '\\';
21300
+ token.info = 'escape';
21301
+ }
21302
+
21303
+ state.pos = pos;
21304
+ return true
21305
+ }
21306
+
21122
21307
  let escapedStr = state.src[pos];
21123
21308
 
21124
21309
  if (ch1 >= 0xD800 && ch1 <= 0xDBFF && pos + 1 < max) {
@@ -21142,7 +21327,7 @@ function escape (state, silent) {
21142
21327
  }
21143
21328
 
21144
21329
  token.markup = origStr;
21145
- token.info = 'escape';
21330
+ token.info = 'escape';
21146
21331
  }
21147
21332
 
21148
21333
  state.pos = pos + 1;
@@ -21232,13 +21417,13 @@ function strikethrough_tokenize (state, silent) {
21232
21417
  let token;
21233
21418
 
21234
21419
  if (len % 2) {
21235
- token = state.push('text', '', 0);
21420
+ token = state.push('text', '', 0);
21236
21421
  token.content = ch;
21237
21422
  len--;
21238
21423
  }
21239
21424
 
21240
21425
  for (let i = 0; i < len; i += 2) {
21241
- token = state.push('text', '', 0);
21426
+ token = state.push('text', '', 0);
21242
21427
  token.content = ch + ch;
21243
21428
 
21244
21429
  state.delimiters.push({
@@ -21274,18 +21459,18 @@ function postProcess$1 (state, delimiters) {
21274
21459
 
21275
21460
  const endDelim = delimiters[startDelim.end];
21276
21461
 
21277
- token = state.tokens[startDelim.token];
21278
- token.type = 's_open';
21279
- token.tag = 's';
21462
+ token = state.tokens[startDelim.token];
21463
+ token.type = 's_open';
21464
+ token.tag = 's';
21280
21465
  token.nesting = 1;
21281
- token.markup = '~~';
21466
+ token.markup = '~~';
21282
21467
  token.content = '';
21283
21468
 
21284
- token = state.tokens[endDelim.token];
21285
- token.type = 's_close';
21286
- token.tag = 's';
21469
+ token = state.tokens[endDelim.token];
21470
+ token.type = 's_close';
21471
+ token.tag = 's';
21287
21472
  token.nesting = -1;
21288
- token.markup = '~~';
21473
+ token.markup = '~~';
21289
21474
  token.content = '';
21290
21475
 
21291
21476
  if (state.tokens[endDelim.token - 1].type === 'text' &&
@@ -21420,18 +21605,18 @@ function postProcess (state, delimiters) {
21420
21605
 
21421
21606
  const ch = String.fromCharCode(startDelim.marker);
21422
21607
 
21423
- const token_o = state.tokens[startDelim.token];
21424
- token_o.type = isStrong ? 'strong_open' : 'em_open';
21425
- token_o.tag = isStrong ? 'strong' : 'em';
21608
+ const token_o = state.tokens[startDelim.token];
21609
+ token_o.type = isStrong ? 'strong_open' : 'em_open';
21610
+ token_o.tag = isStrong ? 'strong' : 'em';
21426
21611
  token_o.nesting = 1;
21427
- token_o.markup = isStrong ? ch + ch : ch;
21612
+ token_o.markup = isStrong ? ch + ch : ch;
21428
21613
  token_o.content = '';
21429
21614
 
21430
- const token_c = state.tokens[endDelim.token];
21431
- token_c.type = isStrong ? 'strong_close' : 'em_close';
21432
- token_c.tag = isStrong ? 'strong' : 'em';
21615
+ const token_c = state.tokens[endDelim.token];
21616
+ token_c.type = isStrong ? 'strong_close' : 'em_close';
21617
+ token_c.tag = isStrong ? 'strong' : 'em';
21433
21618
  token_c.nesting = -1;
21434
- token_c.markup = isStrong ? ch + ch : ch;
21619
+ token_c.markup = isStrong ? ch + ch : ch;
21435
21620
  token_c.content = '';
21436
21621
 
21437
21622
  if (isStrong) {
@@ -21583,7 +21768,7 @@ function link (state, silent) {
21583
21768
 
21584
21769
  const token_o = state.push('link_open', 'a', 1);
21585
21770
  const attrs = [['href', href]];
21586
- token_o.attrs = attrs;
21771
+ token_o.attrs = attrs;
21587
21772
  if (title) {
21588
21773
  attrs.push(['title', title]);
21589
21774
  }
@@ -21740,7 +21925,7 @@ function image (state, silent) {
21740
21925
  // Process autolinks '<protocol:...>'
21741
21926
 
21742
21927
  /* eslint max-len:0 */
21743
- const EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/;
21928
+ const EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/;
21744
21929
  /* eslint-disable-next-line no-control-regex */
21745
21930
  const AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;
21746
21931
 
@@ -21768,17 +21953,17 @@ function autolink (state, silent) {
21768
21953
  if (!state.md.validateLink(fullUrl)) { return false }
21769
21954
 
21770
21955
  if (!silent) {
21771
- const token_o = state.push('link_open', 'a', 1);
21772
- token_o.attrs = [['href', fullUrl]];
21773
- token_o.markup = 'autolink';
21774
- token_o.info = 'auto';
21956
+ const token_o = state.push('link_open', 'a', 1);
21957
+ token_o.attrs = [['href', fullUrl]];
21958
+ token_o.markup = 'autolink';
21959
+ token_o.info = 'auto';
21775
21960
 
21776
- const token_t = state.push('text', '', 0);
21961
+ const token_t = state.push('text', '', 0);
21777
21962
  token_t.content = state.md.normalizeLinkText(url);
21778
21963
 
21779
- const token_c = state.push('link_close', 'a', -1);
21780
- token_c.markup = 'autolink';
21781
- token_c.info = 'auto';
21964
+ const token_c = state.push('link_close', 'a', -1);
21965
+ token_c.markup = 'autolink';
21966
+ token_c.info = 'auto';
21782
21967
  }
21783
21968
 
21784
21969
  state.pos += url.length + 2;
@@ -21790,17 +21975,17 @@ function autolink (state, silent) {
21790
21975
  if (!state.md.validateLink(fullUrl)) { return false }
21791
21976
 
21792
21977
  if (!silent) {
21793
- const token_o = state.push('link_open', 'a', 1);
21794
- token_o.attrs = [['href', fullUrl]];
21795
- token_o.markup = 'autolink';
21796
- token_o.info = 'auto';
21978
+ const token_o = state.push('link_open', 'a', 1);
21979
+ token_o.attrs = [['href', fullUrl]];
21980
+ token_o.markup = 'autolink';
21981
+ token_o.info = 'auto';
21797
21982
 
21798
- const token_t = state.push('text', '', 0);
21983
+ const token_t = state.push('text', '', 0);
21799
21984
  token_t.content = state.md.normalizeLinkText(url);
21800
21985
 
21801
- const token_c = state.push('link_close', 'a', -1);
21802
- token_c.markup = 'autolink';
21803
- token_c.info = 'auto';
21986
+ const token_c = state.push('link_close', 'a', -1);
21987
+ token_c.markup = 'autolink';
21988
+ token_c.info = 'auto';
21804
21989
  }
21805
21990
 
21806
21991
  state.pos += url.length + 2;
@@ -21825,6 +22010,43 @@ function isLetter (ch) {
21825
22010
  return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */)
21826
22011
  }
21827
22012
 
22013
+ // Comment, processing instruction, declaration or CDATA: fixed opener,
22014
+ // then everything up to the first terminator. Returns end position or -1.
22015
+ function scanSpecial (state, pos) {
22016
+ const src = state.src;
22017
+ let start;
22018
+ let terminator;
22019
+
22020
+ if (src.startsWith('<!--', pos)) {
22021
+ if (src.startsWith('>', pos + 4)) { return pos + 5 }
22022
+ if (src.startsWith('->', pos + 4)) { return pos + 6 }
22023
+ start = pos + 4;
22024
+ terminator = '-->';
22025
+ } else if (src.startsWith('<![CDATA[', pos)) {
22026
+ start = pos + 9;
22027
+ terminator = ']]>';
22028
+ } else if (src.charCodeAt(pos + 1) === 0x3F/* ? */) {
22029
+ start = pos + 2;
22030
+ terminator = '?>';
22031
+ } else if (isLetter(src.charCodeAt(pos + 2))) {
22032
+ start = pos + 3;
22033
+ terminator = '>';
22034
+ } else {
22035
+ return -1
22036
+ }
22037
+
22038
+ if (state.skipHtmlSpecial) { return -1 }
22039
+
22040
+ const end = src.indexOf(terminator, start);
22041
+ if (end < 0) {
22042
+ // One flag for all constructs to keep code simple. Valid constructs after
22043
+ // an unclosed one in the same paragraph become text, that's acceptable.
22044
+ state.skipHtmlSpecial = true;
22045
+ return -1
22046
+ }
22047
+ return end + terminator.length
22048
+ }
22049
+
21828
22050
  function html_inline (state, silent) {
21829
22051
  if (!state.md.options.html) { return false }
21830
22052
 
@@ -21836,33 +22058,35 @@ function html_inline (state, silent) {
21836
22058
  return false
21837
22059
  }
21838
22060
 
21839
- // Quick fail on second char
22061
+ let end;
21840
22062
  const ch = state.src.charCodeAt(pos + 1);
21841
- if (ch !== 0x21/* ! */ &&
21842
- ch !== 0x3F/* ? */ &&
21843
- ch !== 0x2F/* / */ &&
21844
- !isLetter(ch)) {
22063
+
22064
+ if (ch === 0x21/* ! */ || ch === 0x3F/* ? */) {
22065
+ end = scanSpecial(state, pos);
22066
+ } else if (ch === 0x2F/* / */ || isLetter(ch)) {
22067
+ const match = state.src.slice(pos).match(HTML_OPEN_CLOSE_TAG_RE);
22068
+ end = match ? pos + match[0].length : -1;
22069
+ } else {
21845
22070
  return false
21846
22071
  }
21847
22072
 
21848
- const match = state.src.slice(pos).match(HTML_TAG_RE);
21849
- if (!match) { return false }
22073
+ if (end < 0) { return false }
21850
22074
 
21851
22075
  if (!silent) {
21852
22076
  const token = state.push('html_inline', '', 0);
21853
- token.content = match[0];
22077
+ token.content = state.src.slice(pos, end);
21854
22078
 
21855
- if (isLinkOpen(token.content)) state.linkLevel++;
22079
+ if (isLinkOpen(token.content)) state.linkLevel++;
21856
22080
  if (isLinkClose(token.content)) state.linkLevel--;
21857
22081
  }
21858
- state.pos += match[0].length;
22082
+ state.pos = end;
21859
22083
  return true
21860
22084
  }
21861
22085
 
21862
22086
  // Process html entity - &#123;, &#xAF;, &quot;, ...
21863
22087
 
21864
22088
  const DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;
21865
- const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
22089
+ const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
21866
22090
 
21867
22091
  function entity (state, silent) {
21868
22092
  const pos = state.pos;
@@ -21880,10 +22104,10 @@ function entity (state, silent) {
21880
22104
  if (!silent) {
21881
22105
  const code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);
21882
22106
 
21883
- const token = state.push('text_special', '', 0);
22107
+ const token = state.push('text_special', '', 0);
21884
22108
  token.content = isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);
21885
- token.markup = match[0];
21886
- token.info = 'entity';
22109
+ token.markup = match[0];
22110
+ token.info = 'entity';
21887
22111
  }
21888
22112
  state.pos += match[0].length;
21889
22113
  return true
@@ -21891,13 +22115,13 @@ function entity (state, silent) {
21891
22115
  } else {
21892
22116
  const match = state.src.slice(pos).match(NAMED_RE);
21893
22117
  if (match) {
21894
- const decoded = decodeHTML(match[0]);
22118
+ const decoded = decodeHTMLStrict(match[0]);
21895
22119
  if (decoded !== match[0]) {
21896
22120
  if (!silent) {
21897
- const token = state.push('text_special', '', 0);
22121
+ const token = state.push('text_special', '', 0);
21898
22122
  token.content = decoded;
21899
- token.markup = match[0];
21900
- token.info = 'entity';
22123
+ token.markup = match[0];
22124
+ token.info = 'entity';
21901
22125
  }
21902
22126
  state.pos += match[0].length;
21903
22127
  return true
@@ -21995,8 +22219,8 @@ function processDelimiters (delimiters) {
21995
22219
  jumps[closerIdx] = closerIdx - openerIdx + lastJump;
21996
22220
  jumps[openerIdx] = lastJump;
21997
22221
 
21998
- closer.open = false;
21999
- opener.end = closerIdx;
22222
+ closer.open = false;
22223
+ opener.end = closerIdx;
22000
22224
  opener.close = false;
22001
22225
  newMinOpenerIdx = -1;
22002
22226
  // treat next token as start of run,
@@ -22081,18 +22305,18 @@ function fragments_join (state) {
22081
22305
  // Parser rules
22082
22306
 
22083
22307
  const _rules = [
22084
- ['text', text],
22085
- ['linkify', linkify],
22086
- ['newline', newline],
22087
- ['escape', escape],
22088
- ['backticks', backtick],
22089
- ['strikethrough', r_strikethrough.tokenize],
22090
- ['emphasis', r_emphasis.tokenize],
22091
- ['link', link],
22092
- ['image', image],
22093
- ['autolink', autolink],
22094
- ['html_inline', html_inline],
22095
- ['entity', entity]
22308
+ ['text', text],
22309
+ ['linkify', linkify],
22310
+ ['newline', newline],
22311
+ ['escape', escape],
22312
+ ['backticks', backtick],
22313
+ ['strikethrough', r_strikethrough.tokenize],
22314
+ ['emphasis', r_emphasis.tokenize],
22315
+ ['link', link],
22316
+ ['image', image],
22317
+ ['autolink', autolink],
22318
+ ['html_inline', html_inline],
22319
+ ['entity', entity]
22096
22320
  ];
22097
22321
 
22098
22322
  // `rule2` ruleset was created specifically for emphasis/strikethrough
@@ -22101,12 +22325,12 @@ const _rules = [
22101
22325
  // Don't use this for anything except pairs (plugins working with `balance_pairs`).
22102
22326
  //
22103
22327
  const _rules2 = [
22104
- ['balance_pairs', link_pairs],
22105
- ['strikethrough', r_strikethrough.postProcess],
22106
- ['emphasis', r_emphasis.postProcess],
22328
+ ['balance_pairs', link_pairs],
22329
+ ['strikethrough', r_strikethrough.postProcess],
22330
+ ['emphasis', r_emphasis.postProcess],
22107
22331
  // rules for pairs separate '**' into its own text tokens, which may be left unused,
22108
22332
  // rule below merges unused segments back with the rest of the text
22109
- ['fragments_join', fragments_join]
22333
+ ['fragments_join', fragments_join]
22110
22334
  ];
22111
22335
 
22112
22336
  /**
@@ -22271,7 +22495,7 @@ function reFactory (opts) {
22271
22495
  // All possible word characters (everything without punctuation, spaces & controls)
22272
22496
  // Defined via punctuation & spaces to save space
22273
22497
  // Should be something like \p{\L\N\S\M} (\w but without `_`)
22274
- re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';
22498
+ re.src_pseudo_letter = `(?:(?!${text_separators}|${re.src_ZPCc})${re.src_Any})`;
22275
22499
  // The same as abothe but without [0-9]
22276
22500
  // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';
22277
22501
 
@@ -22280,7 +22504,9 @@ function reFactory (opts) {
22280
22504
  '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
22281
22505
 
22282
22506
  // Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch.
22283
- re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\[\\]()]).)+@)?';
22507
+ // Length is capped to exclude possible rescans till the end and avoid O(n^2)
22508
+ // DoS. No standard limit, just take something reasonable.
22509
+ re.src_auth = `(?:(?:(?!${re.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`;
22284
22510
 
22285
22511
  re.src_port =
22286
22512
 
@@ -22288,23 +22514,23 @@ function reFactory (opts) {
22288
22514
 
22289
22515
  re.src_host_terminator =
22290
22516
 
22291
- '(?=$|' + text_separators + '|' + re.src_ZPCc + ')' +
22292
- '(?!' + (opts['---'] ? '-(?!--)|' : '-|') + '_|:\\d|\\.-|\\.(?!$|' + re.src_ZPCc + '))';
22517
+ `(?=$|${text_separators}|${re.src_ZPCc})` +
22518
+ `(?!${opts['---'] ? '-(?!--)|' : '-|'}_|:\\d|\\.-|\\.(?!$|${re.src_ZPCc}))`;
22293
22519
 
22294
22520
  re.src_path =
22295
22521
 
22296
22522
  '(?:' +
22297
22523
  '[/?#]' +
22298
22524
  '(?:' +
22299
- '(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\]{}.,"\'?!\\-;]).|' +
22300
- '\\[(?:(?!' + re.src_ZCc + '|\\]).)*\\]|' +
22301
- '\\((?:(?!' + re.src_ZCc + '|[)]).)*\\)|' +
22302
- '\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\}|' +
22303
- '\\"(?:(?!' + re.src_ZCc + '|["]).)+\\"|' +
22304
- "\\'(?:(?!" + re.src_ZCc + "|[']).)+\\'|" +
22525
+ `(?!${re.src_ZCc}|${text_separators}|[()[\\]{}.,"'?!\\-;]).|` +
22526
+ `\\[(?:(?!${re.src_ZCc}|\\]).)*\\]|` +
22527
+ `\\((?:(?!${re.src_ZCc}|[)]).)*\\)|` +
22528
+ `\\{(?:(?!${re.src_ZCc}|[}]).)*\\}|` +
22529
+ `\\"(?:(?!${re.src_ZCc}|["]).)+\\"|` +
22530
+ `\\'(?:(?!${re.src_ZCc}|[']).)+\\'|` +
22305
22531
 
22306
22532
  // allow `I'm_king` if no pair found
22307
- "\\'(?=" + re.src_pseudo_letter + '|[-])|' +
22533
+ `\\'(?=${re.src_pseudo_letter}|[-])|` +
22308
22534
 
22309
22535
  // google has many dots in "google search" links (#66, #81).
22310
22536
  // github has ... in commit range links,
@@ -22316,30 +22542,32 @@ function reFactory (opts) {
22316
22542
  // until more examples found.
22317
22543
  '\\.{2,}[a-zA-Z0-9%/&]|' +
22318
22544
 
22319
- '\\.(?!' + re.src_ZCc + '|[.]|$)|' +
22545
+ `\\.(?!${re.src_ZCc}|[.]|$)|` +
22320
22546
  (opts['---']
22321
22547
  ? '\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate
22322
22548
  : '\\-+|'
22323
22549
  ) +
22324
22550
  // allow `,,,` in paths
22325
- ',(?!' + re.src_ZCc + '|$)|' +
22551
+ `,(?!${re.src_ZCc}|$)|` +
22326
22552
 
22327
22553
  // allow `;` if not followed by space-like char
22328
- ';(?!' + re.src_ZCc + '|$)|' +
22554
+ `;(?!${re.src_ZCc}|$)|` +
22329
22555
 
22330
22556
  // allow `!!!` in paths, but not at the end
22331
- '\\!+(?!' + re.src_ZCc + '|[!]|$)|' +
22557
+ `\\!+(?!${re.src_ZCc}|[!]|$)|` +
22332
22558
 
22333
- '\\?(?!' + re.src_ZCc + '|[?]|$)' +
22559
+ `\\?(?!${re.src_ZCc}|[?]|$)` +
22334
22560
  ')+' +
22335
22561
  '|\\/' +
22336
22562
  ')?';
22337
22563
 
22338
22564
  // Allow anything in markdown spec, forbid quote (") at the first position
22339
22565
  // because emails enclosed in quotes are far more common
22566
+ // Max name length capped to 64 chars (RFC 5321). This also prevents O(n^2)
22567
+ // rescans to the end on inputs like `mailto:mailto:...`
22340
22568
  re.src_email_name =
22341
22569
 
22342
- '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*';
22570
+ '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}';
22343
22571
 
22344
22572
  re.src_xn =
22345
22573
 
@@ -22354,7 +22582,7 @@ function reFactory (opts) {
22354
22582
  '(?:' +
22355
22583
  re.src_xn +
22356
22584
  '|' +
22357
- re.src_pseudo_letter + '{1,63}' +
22585
+ `${re.src_pseudo_letter}{1,63}` +
22358
22586
  ')';
22359
22587
 
22360
22588
  re.src_domain =
@@ -22362,9 +22590,9 @@ function reFactory (opts) {
22362
22590
  '(?:' +
22363
22591
  re.src_xn +
22364
22592
  '|' +
22365
- '(?:' + re.src_pseudo_letter + ')' +
22593
+ `(?:${re.src_pseudo_letter})` +
22366
22594
  '|' +
22367
- '(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +
22595
+ `(?:${re.src_pseudo_letter}(?:-|${re.src_pseudo_letter}){0,61}${re.src_pseudo_letter})` +
22368
22596
  ')';
22369
22597
 
22370
22598
  re.src_host =
@@ -22373,7 +22601,7 @@ function reFactory (opts) {
22373
22601
  // Don't need IP check, because digits are already allowed in normal domain names
22374
22602
  // src_ip4 +
22375
22603
  // '|' +
22376
- '(?:(?:(?:' + re.src_domain + ')\\.)*' + re.src_domain/* _root */ + ')' +
22604
+ `(?:(?:(?:${re.src_domain})\\.)*${re.src_domain})`/* _root */ +
22377
22605
  ')';
22378
22606
 
22379
22607
  re.tpl_host_fuzzy =
@@ -22381,12 +22609,12 @@ function reFactory (opts) {
22381
22609
  '(?:' +
22382
22610
  re.src_ip4 +
22383
22611
  '|' +
22384
- '(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))' +
22612
+ `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))` +
22385
22613
  ')';
22386
22614
 
22387
22615
  re.tpl_host_no_ip_fuzzy =
22388
22616
 
22389
- '(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))';
22617
+ `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))`;
22390
22618
 
22391
22619
  re.src_host_strict =
22392
22620
 
@@ -22415,24 +22643,24 @@ function reFactory (opts) {
22415
22643
  // Rude test fuzzy links by host, for quick deny
22416
22644
  re.tpl_host_fuzzy_test =
22417
22645
 
22418
- 'localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';
22646
+ `localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:${re.src_ZPCc}|>|$))`;
22419
22647
 
22420
22648
  re.tpl_email_fuzzy =
22421
22649
 
22422
- '(^|' + text_separators + '|"|\\(|' + re.src_ZCc + ')' +
22423
- '(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';
22650
+ `(^|${text_separators}|"|\\(|${re.src_ZCc})` +
22651
+ `(${re.src_email_name}@${re.tpl_host_fuzzy_strict})`;
22424
22652
 
22425
22653
  re.tpl_link_fuzzy =
22426
22654
  // Fuzzy link can't be prepended with .:/\- and non punctuation.
22427
22655
  // but can start with > (markdown blockquote)
22428
- '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
22429
- '((?![$+<=>^`|\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';
22656
+ `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` +
22657
+ `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_fuzzy_strict}${re.src_path})`;
22430
22658
 
22431
22659
  re.tpl_link_no_ip_fuzzy =
22432
22660
  // Fuzzy link can't be prepended with .:/\- and non punctuation.
22433
22661
  // but can start with > (markdown blockquote)
22434
- '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
22435
- '((?![$+<=>^`|\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';
22662
+ `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` +
22663
+ `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_no_ip_fuzzy_strict}${re.src_path})`;
22436
22664
 
22437
22665
  return re
22438
22666
  }
@@ -22488,7 +22716,7 @@ const defaultSchemas = {
22488
22716
  if (!self.re.http) {
22489
22717
  // compile lazily, because "host"-containing variables can change on tlds update.
22490
22718
  self.re.http = new RegExp(
22491
- '^\\/\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'
22719
+ `^\\/\\/${self.re.src_auth}${self.re.src_host_port_strict}${self.re.src_path}`, 'i'
22492
22720
  );
22493
22721
  }
22494
22722
  if (self.re.http.test(tail)) {
@@ -22510,7 +22738,7 @@ const defaultSchemas = {
22510
22738
  self.re.src_auth +
22511
22739
  // Don't allow single-level domains, because of false positives like '//test'
22512
22740
  // with code comments
22513
- '(?:localhost|(?:(?:' + self.re.src_domain + ')\\.)+' + self.re.src_domain_root + ')' +
22741
+ `(?:localhost|(?:(?:${self.re.src_domain})\\.)+${self.re.src_domain_root})` +
22514
22742
  self.re.src_port +
22515
22743
  self.re.src_host_terminator +
22516
22744
  self.re.src_path,
@@ -22534,7 +22762,7 @@ const defaultSchemas = {
22534
22762
 
22535
22763
  if (!self.re.mailto) {
22536
22764
  self.re.mailto = new RegExp(
22537
- '^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'
22765
+ `^${self.re.src_email_name}@${self.re.src_host_strict}`, 'i'
22538
22766
  );
22539
22767
  }
22540
22768
  if (self.re.mailto.test(tail)) {
@@ -22546,17 +22774,11 @@ const defaultSchemas = {
22546
22774
  };
22547
22775
 
22548
22776
  // RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)
22549
- /* eslint-disable-next-line max-len */
22550
22777
  const tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';
22551
22778
 
22552
22779
  // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
22553
22780
  const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
22554
22781
 
22555
- function resetScanCache (self) {
22556
- self.__index__ = -1;
22557
- self.__text_cache__ = '';
22558
- }
22559
-
22560
22782
  function createValidator (re) {
22561
22783
  return function (text, pos) {
22562
22784
  const tail = text.slice(pos);
@@ -22595,8 +22817,11 @@ function compile (self) {
22595
22817
  function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) }
22596
22818
 
22597
22819
  re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');
22820
+ re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig');
22598
22821
  re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');
22822
+ re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig');
22599
22823
  re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');
22824
+ re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig');
22600
22825
  re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');
22601
22826
 
22602
22827
  //
@@ -22608,7 +22833,7 @@ function compile (self) {
22608
22833
  self.__compiled__ = {}; // Reset compiled data
22609
22834
 
22610
22835
  function schemaError (name, val) {
22611
- throw new Error('(LinkifyIt) Invalid schema "' + name + '": ' + val)
22836
+ throw new Error(`(LinkifyIt) Invalid schema "${name}": ${val}`)
22612
22837
  }
22613
22838
 
22614
22839
  Object.keys(self.__schemas__).forEach(function (name) {
@@ -22682,20 +22907,14 @@ function compile (self) {
22682
22907
  .map(escapeRE)
22683
22908
  .join('|');
22684
22909
  // (?!_) cause 1.5x slowdown
22685
- self.re.schema_test = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'i');
22686
- self.re.schema_search = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'ig');
22687
- self.re.schema_at_start = RegExp('^' + self.re.schema_search.source, 'i');
22910
+ self.re.schema_test = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'i');
22911
+ self.re.schema_search = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'ig');
22912
+ self.re.schema_at_start = RegExp(`^${self.re.schema_search.source}`, 'i');
22688
22913
 
22689
22914
  self.re.pretest = RegExp(
22690
- '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
22915
+ `(${self.re.schema_test.source})|(${self.re.host_fuzzy_test.source})|@`,
22691
22916
  'i'
22692
22917
  );
22693
-
22694
- //
22695
- // Cleanup
22696
- //
22697
-
22698
- resetScanCache(self);
22699
22918
  }
22700
22919
 
22701
22920
  /**
@@ -22703,55 +22922,45 @@ function compile (self) {
22703
22922
  *
22704
22923
  * Match result. Single element of array, returned by [[LinkifyIt#match]]
22705
22924
  **/
22706
- function Match (self, shift) {
22707
- const start = self.__index__;
22708
- const end = self.__last_index__;
22709
- const text = self.__text_cache__.slice(start, end);
22925
+ function Match (text, schema, index, lastIndex) {
22926
+ const raw = text.slice(index, lastIndex);
22710
22927
 
22711
22928
  /**
22712
22929
  * Match#schema -> String
22713
22930
  *
22714
22931
  * Prefix (protocol) for matched string.
22715
22932
  **/
22716
- this.schema = self.__schema__.toLowerCase();
22933
+ this.schema = schema.toLowerCase();
22717
22934
  /**
22718
22935
  * Match#index -> Number
22719
22936
  *
22720
22937
  * First position of matched string.
22721
22938
  **/
22722
- this.index = start + shift;
22939
+ this.index = index;
22723
22940
  /**
22724
22941
  * Match#lastIndex -> Number
22725
22942
  *
22726
22943
  * Next position after matched string.
22727
22944
  **/
22728
- this.lastIndex = end + shift;
22945
+ this.lastIndex = lastIndex;
22729
22946
  /**
22730
22947
  * Match#raw -> String
22731
22948
  *
22732
22949
  * Matched string.
22733
22950
  **/
22734
- this.raw = text;
22951
+ this.raw = raw;
22735
22952
  /**
22736
22953
  * Match#text -> String
22737
22954
  *
22738
22955
  * Notmalized text of matched string.
22739
22956
  **/
22740
- this.text = text;
22957
+ this.text = raw;
22741
22958
  /**
22742
22959
  * Match#url -> String
22743
22960
  *
22744
22961
  * Normalized url of matched string.
22745
22962
  **/
22746
- this.url = text;
22747
- }
22748
-
22749
- function createMatch (self, shift) {
22750
- const match = new Match(self, shift);
22751
-
22752
- self.__compiled__[match.schema].normalize(match, self);
22753
-
22754
- return match
22963
+ this.url = raw;
22755
22964
  }
22756
22965
 
22757
22966
  /**
@@ -22806,12 +23015,6 @@ function LinkifyIt (schemas, options) {
22806
23015
 
22807
23016
  this.__opts__ = assign({}, defaultOptions, options);
22808
23017
 
22809
- // Cache last tested result. Used to skip repeating steps on next `match` call.
22810
- this.__index__ = -1;
22811
- this.__last_index__ = -1; // Next scan position
22812
- this.__schema__ = '';
22813
- this.__text_cache__ = '';
22814
-
22815
23018
  this.__schemas__ = assign({}, defaultSchemas, schemas);
22816
23019
  this.__compiled__ = {};
22817
23020
 
@@ -22853,69 +23056,38 @@ LinkifyIt.prototype.set = function set (options) {
22853
23056
  * Searches linkifiable pattern and returns `true` on success or `false` on fail.
22854
23057
  **/
22855
23058
  LinkifyIt.prototype.test = function test (text) {
22856
- // Reset scan cache
22857
- this.__text_cache__ = text;
22858
- this.__index__ = -1;
22859
-
22860
23059
  if (!text.length) { return false }
22861
23060
 
22862
- let m, ml, me, len, shift, next, re, tld_pos, at_pos;
23061
+ let m, re;
22863
23062
 
22864
23063
  // try to scan for link with schema - that's the most simple rule
22865
23064
  if (this.re.schema_test.test(text)) {
22866
23065
  re = this.re.schema_search;
22867
23066
  re.lastIndex = 0;
22868
23067
  while ((m = re.exec(text)) !== null) {
22869
- len = this.testSchemaAt(text, m[2], re.lastIndex);
22870
- if (len) {
22871
- this.__schema__ = m[2];
22872
- this.__index__ = m.index + m[1].length;
22873
- this.__last_index__ = m.index + m[0].length + len;
22874
- break
22875
- }
23068
+ if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }
22876
23069
  }
22877
23070
  }
22878
23071
 
22879
23072
  if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
22880
23073
  // guess schemaless links
22881
- tld_pos = text.search(this.re.host_fuzzy_test);
22882
- if (tld_pos >= 0) {
22883
- // if tld is located after found link - no need to check fuzzy pattern
22884
- if (this.__index__ < 0 || tld_pos < this.__index__) {
22885
- if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
22886
- shift = ml.index + ml[1].length;
22887
-
22888
- if (this.__index__ < 0 || shift < this.__index__) {
22889
- this.__schema__ = '';
22890
- this.__index__ = shift;
22891
- this.__last_index__ = ml.index + ml[0].length;
22892
- }
22893
- }
23074
+ if (text.search(this.re.host_fuzzy_test) >= 0) {
23075
+ if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) {
23076
+ return true
22894
23077
  }
22895
23078
  }
22896
23079
  }
22897
23080
 
22898
23081
  if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
22899
23082
  // guess schemaless emails
22900
- at_pos = text.indexOf('@');
22901
- if (at_pos >= 0) {
23083
+ if (text.indexOf('@') >= 0) {
22902
23084
  // We can't skip this check, because this cases are possible:
22903
23085
  // 192.168.1.1@gmail.com, my.in@example.com
22904
- if ((me = text.match(this.re.email_fuzzy)) !== null) {
22905
- shift = me.index + me[1].length;
22906
- next = me.index + me[0].length;
22907
-
22908
- if (this.__index__ < 0 || shift < this.__index__ ||
22909
- (shift === this.__index__ && next > this.__last_index__)) {
22910
- this.__schema__ = 'mailto:';
22911
- this.__index__ = shift;
22912
- this.__last_index__ = next;
22913
- }
22914
- }
23086
+ if (text.match(this.re.email_fuzzy) !== null) { return true }
22915
23087
  }
22916
23088
  }
22917
23089
 
22918
- return this.__index__ >= 0
23090
+ return false
22919
23091
  };
22920
23092
 
22921
23093
  /**
@@ -22964,23 +23136,88 @@ LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) {
22964
23136
  **/
22965
23137
  LinkifyIt.prototype.match = function match (text) {
22966
23138
  const result = [];
22967
- let shift = 0;
23139
+ const type_schemed = [];
23140
+ const type_fuzzy_link = [];
23141
+ const type_fuzzy_email = [];
23142
+ let m, len, re;
22968
23143
 
22969
- // Try to take previous element from cache, if .test() called before
22970
- if (this.__index__ >= 0 && this.__text_cache__ === text) {
22971
- result.push(createMatch(this, shift));
22972
- shift = this.__last_index__;
23144
+ function choose (a, b) {
23145
+ if (!a) { return b }
23146
+ if (!b) { return a }
23147
+ if (a.index !== b.index) { return a.index < b.index ? a : b }
23148
+ return a.lastIndex >= b.lastIndex ? a : b
22973
23149
  }
22974
23150
 
22975
- // Cut head if cache was used
22976
- let tail = shift ? text.slice(shift) : text;
23151
+ if (!text.length) { return null }
22977
23152
 
22978
- // Scan string until end reached
22979
- while (this.test(tail)) {
22980
- result.push(createMatch(this, shift));
23153
+ // scan for links with schema
23154
+ if (this.re.schema_test.test(text)) {
23155
+ re = this.re.schema_search;
23156
+ re.lastIndex = 0;
23157
+ while ((m = re.exec(text)) !== null) {
23158
+ len = this.testSchemaAt(text, m[2], re.lastIndex);
23159
+ if (len) {
23160
+ type_schemed.push({
23161
+ schema: m[2],
23162
+ index: m.index + m[1].length,
23163
+ lastIndex: m.index + m[0].length + len
23164
+ });
23165
+ }
23166
+ }
23167
+ }
23168
+
23169
+ if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
23170
+ re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global;
23171
+ re.lastIndex = 0;
23172
+ while ((m = re.exec(text)) !== null) {
23173
+ type_fuzzy_link.push({
23174
+ schema: '',
23175
+ index: m.index + m[1].length,
23176
+ lastIndex: m.index + m[0].length
23177
+ });
23178
+ }
23179
+ }
23180
+
23181
+ if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
23182
+ re = this.re.email_fuzzy_global;
23183
+ re.lastIndex = 0;
23184
+ while ((m = re.exec(text)) !== null) {
23185
+ type_fuzzy_email.push({
23186
+ schema: 'mailto:',
23187
+ index: m.index + m[1].length,
23188
+ lastIndex: m.index + m[0].length
23189
+ });
23190
+ }
23191
+ }
23192
+
23193
+ const indexes = [0, 0, 0];
23194
+ let lastIndex = 0;
23195
+
23196
+ for (;;) {
23197
+ const candidates = [
23198
+ type_schemed[indexes[0]],
23199
+ type_fuzzy_email[indexes[1]],
23200
+ type_fuzzy_link[indexes[2]]
23201
+ ];
22981
23202
 
22982
- tail = tail.slice(this.__last_index__);
22983
- shift += this.__last_index__;
23203
+ const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]);
23204
+
23205
+ if (!candidate) { break }
23206
+
23207
+ if (candidate === candidates[0]) {
23208
+ indexes[0]++;
23209
+ } else if (candidate === candidates[1]) {
23210
+ indexes[1]++;
23211
+ } else {
23212
+ indexes[2]++;
23213
+ }
23214
+
23215
+ if (candidate.index < lastIndex) { continue }
23216
+
23217
+ const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex);
23218
+ this.__compiled__[match.schema].normalize(match, this);
23219
+ result.push(match);
23220
+ lastIndex = candidate.lastIndex;
22984
23221
  }
22985
23222
 
22986
23223
  if (result.length) {
@@ -22997,10 +23234,6 @@ LinkifyIt.prototype.match = function match (text) {
22997
23234
  * of the string, and null otherwise.
22998
23235
  **/
22999
23236
  LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
23000
- // Reset scan cache
23001
- this.__text_cache__ = text;
23002
- this.__index__ = -1;
23003
-
23004
23237
  if (!text.length) return null
23005
23238
 
23006
23239
  const m = this.re.schema_at_start.exec(text);
@@ -23009,11 +23242,10 @@ LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
23009
23242
  const len = this.testSchemaAt(text, m[2], m[0].length);
23010
23243
  if (!len) return null
23011
23244
 
23012
- this.__schema__ = m[2];
23013
- this.__index__ = m.index + m[1].length;
23014
- this.__last_index__ = m.index + m[0].length + len;
23245
+ const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len);
23015
23246
 
23016
- return createMatch(this, 0)
23247
+ this.__compiled__[match.schema].normalize(match, this);
23248
+ return match
23017
23249
  };
23018
23250
 
23019
23251
  /** chainable
@@ -23061,10 +23293,10 @@ LinkifyIt.prototype.normalize = function normalize (match) {
23061
23293
  // Do minimal possible changes by default. Need to collect feedback prior
23062
23294
  // to move forward https://github.com/markdown-it/linkify-it/issues/1
23063
23295
 
23064
- if (!match.schema) { match.url = 'http://' + match.url; }
23296
+ if (!match.schema) { match.url = `http://${match.url}`; }
23065
23297
 
23066
23298
  if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {
23067
- match.url = 'mailto:' + match.url;
23299
+ match.url = `mailto:${match.url}`;
23068
23300
  }
23069
23301
  };
23070
23302
 
@@ -24064,7 +24296,7 @@ function MarkdownIt (presetName, options) {
24064
24296
  * ```javascript
24065
24297
  * var md = require('markdown-it')()
24066
24298
  * .set({ html: true, breaks: true })
24067
- * .set({ typographer, true });
24299
+ * .set({ typographer: true });
24068
24300
  * ```
24069
24301
  *
24070
24302
  * __Note:__ To achieve the best possible performance, don't modify a