@public-ui/hydrate 2.2.24-rc.0 → 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.mjs CHANGED
@@ -225,7 +225,7 @@ var HYDRATED_STYLE_ID = "sty-id";
225
225
  var HYDRATE_CHILD_ID = "c-id";
226
226
  var SLOT_FB_CSS = "slot-fb{display:contents}slot-fb[hidden]{display:none}";
227
227
  var XLINK_NS = "http://www.w3.org/1999/xlink";
228
- var h$1 = (nodeName, vnodeData, ...children) => {
228
+ var h = (nodeName, vnodeData, ...children) => {
229
229
  let child = null;
230
230
  let key = null;
231
231
  let slotName = null;
@@ -327,7 +327,7 @@ var convertToPrivate = (node) => {
327
327
  if (node.vname) {
328
328
  vnodeData.name = node.vname;
329
329
  }
330
- return h$1(node.vtag, vnodeData, ...node.vchildren || []);
330
+ return h(node.vtag, vnodeData, ...node.vchildren || []);
331
331
  }
332
332
  const vnode = newVNode(node.vtag, node.vtext);
333
333
  vnode.$attrs$ = node.vattrs;
@@ -1162,7 +1162,7 @@ var renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => {
1162
1162
  const hostElm = hostRef.$hostElement$;
1163
1163
  const cmpMeta = hostRef.$cmpMeta$;
1164
1164
  const oldVNode = hostRef.$vnode$ || newVNode(null, null);
1165
- const rootVnode = isHost(renderFnResults) ? renderFnResults : h$1(null, null, renderFnResults);
1165
+ const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
1166
1166
  hostTagName = hostElm.tagName;
1167
1167
  if (cmpMeta.$attrsToReflect$) {
1168
1168
  rootVnode.$attrs$ = rootVnode.$attrs$ || {};
@@ -1886,14 +1886,14 @@ var hAsync = (nodeName, vnodeData, ...children) => {
1886
1886
  const flatChildren = children.flat(Infinity);
1887
1887
  if (flatChildren.some((child) => child instanceof Promise)) {
1888
1888
  return Promise.all(flatChildren).then((resolvedChildren) => {
1889
- return h$1(nodeName, vnodeData, ...resolvedChildren);
1889
+ return h(nodeName, vnodeData, ...resolvedChildren);
1890
1890
  }).catch((err2) => {
1891
- return h$1(nodeName, vnodeData);
1891
+ return h(nodeName, vnodeData);
1892
1892
  });
1893
1893
  }
1894
- return h$1(nodeName, vnodeData, ...flatChildren);
1894
+ return h(nodeName, vnodeData, ...flatChildren);
1895
1895
  }
1896
- return h$1(nodeName, vnodeData);
1896
+ return h(nodeName, vnodeData);
1897
1897
  };
1898
1898
  function proxyHostElement(elm, cmpMeta) {
1899
1899
  if (typeof elm.componentOnReady !== "function") {
@@ -2654,9 +2654,9 @@ var loglevel = {exports: {}};
2654
2654
  }));
2655
2655
  }(loglevel));
2656
2656
 
2657
- var h = loglevel.exports;
2657
+ var f = loglevel.exports;
2658
2658
 
2659
- 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,a="JEST_WORKER_ID"in t,o="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,u=typeof navigator<"u"&&/playwright|puppeteer|webdriver|selenium|testcafe/i.test(navigator.userAgent);return e||s||a||o||r||i||c||u},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,a]of n$1.A11yUi.PERFORMANCE_MEASURES.entries())t[s]=[a.totalTime/a.count,a.count];const e=Object.entries(t).sort((s,a)=>a[1][0]-s[1][0]);return console.table(Object.fromEntries(e.map(([s,[a,o]])=>[s,{"avg (ms)":parseFloat(a.toFixed(2)),count:o}]))),t}}};let f=!1;const k=/^[a-z][a-z0-9]{1,}(-[a-z0-9]+)?$/,G=t=>typeof t=="string"&&k.test(t),A=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]+)?$/`)},b=t=>t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\s*([{},;])\s*/g,"$1").replace(/:\s+/g,":").replace(/\s+/g," ").replace(/;\}/g,"}").trim(),x=(t,e,s,a)=>g(t,e,s,a),g=(t,e,s,a)=>{a=a??{},a.append=a.append??!1,A(t),!f&&(f=!0,h.warn(`[Theming] The theme process is locked. This means that the theme "${t}" should not be patched.
2659
+ 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.
2660
2660
 
2661
2661
  import { register } from 'adopted-style-sheets';
2662
2662
  import { defineCustomElements } from '...';
@@ -2666,94 +2666,94 @@ const j=(t,e)=>s=>s(t,e),F=(t,e)=>s=>s(t,e,{append:!1}),Y=()=>{const t=typeof pr
2666
2666
  .then(() => {
2667
2667
  // run your app or website
2668
2668
  })
2669
- .catch(console.warn);`));let o=n$1.A11yUi.THEMES.get(t);if(o||(o=new Map,n$1.A11yUi.THEMES.set(t,o)),a.append&&o.has(e)){const r=o.get(e);o.set(e,b(`${r}${s}`));}else o.set(e,b(s));},K=(t,e,s,a)=>E(t,e,s,a),E=(t,e,s,a)=>(A(t),typeof e=="object"&&e!==null&&Object.getOwnPropertyNames(e).forEach(o=>{const r=e[o],i=o.toLowerCase(),c=typeof a?.transformTagName=="function"&&!["GLOBAL","PROPERTIES"].includes(o)?a.transformTagName(i):o;typeof r=="string"&&r.length>0&&g(t,c.toUpperCase(),r,s);}),t);const v=new Set,N=new Map,ee=/--[^;]+/g,te=/:/,se=typeof MutationObserver<"u";let R=()=>{};const ae=(t,e)=>{let s=e.match(ee);if(Array.isArray(s)){s=s.filter(o=>te.test(o));const a=document.createElement("style");a.innerHTML=`.${t} {${s.join(";")}}`,document.querySelector("head")?.appendChild(a);}v.add(t);},y=(t,e)=>{const s=n$1.A11yUi.THEMES.get(t);if(s instanceof Map){const a=s.get(e);if(a!==void 0)return a}return ""},oe=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},ne=(t,e)=>{try{if(n$1.A11yUi.Theme?.mode==="ssr")throw new Error("SSR");const s=e.filter(a=>typeof a=="string"&&a.length>0).map(a=>{let o=N.get(a);return o||(o=new CSSStyleSheet,o.replaceSync(a),N.set(a,o)),o});t.adoptedStyleSheets=s;}catch{for(let a=e.length-1;a>=0;a--){const o=e[a];if(typeof o!="string"||o.length===0)continue;const r=e.length-1-a,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=o,t.insertBefore(i,t.firstChild);}}},re=(t,e,s)=>{if(s===!1||s?.mode!=="before"&&s?.mode!=="after")return;const a=Array.from(t.childNodes).filter(r=>r instanceof HTMLStyleElement&&r.tagName==="STYLE");let o;try{o=Array.from(t.adoptedStyleSheets);}catch{o=[];}if(!(a.length===0&&o.length===0))if(s.mode==="before"){const r=[...o.map(i=>Array.from(i.cssRules).map(c=>c.cssText).join("")),...a.map(i=>i.innerHTML)];e.unshift(...r);}else a.forEach(r=>e.push(r.innerHTML)),o.forEach(r=>e.push(Array.from(r.cssRules).map(i=>i.cssText).join("")));},ie=(t,e,s)=>{const a=e.name||"default";let o;try{if(t.shadowRoot===null)throw new Error("ShadowRoot is null");o=t.shadowRoot;}catch{o=t;}const r=n$1.A11yUi.CSS_STYLE_CACHE.get(a)?.get(t.tagName);if(r)_(t,o,r,s);else {const i=y(a,"PROPERTIES"),c=y(a,"GLOBAL"),u=y(a,t.tagName);v.has(a)===!1&&ae(a,c);const p=[i,c,u];if(re(o,p,e.encroachCss),e.cache===!0){let m=n$1.A11yUi.CSS_STYLE_CACHE.get(a);m||(m=new Map,n$1.A11yUi.CSS_STYLE_CACHE.set(a,m)),m.set(t.tagName,p);}_(t,o,p,s);}},_=(t,e,s,a)=>{const o=n$1.A11yUi.Theme?.loglevel==="debug",r=o?performance.now():0;if(oe(e),ne(e,s),fe(t),requestAnimationFrame(a),o){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:a}=e;ie(t,a,s);}};const me={attributes:!0,attributeFilter:[],childList:!1,subtree:!1},I=se?new MutationObserver((t,e)=>{const s=[];for(const a of t){const o=a.target;o.classList.contains("hydrated")&&n$1.A11yUi.STYLING_TASK_QUEUE.has(o)&&(O(o),s.push(o));}for(const a of s)e.observe(a,me);}):null;I&&(R=()=>{});const fe=t=>{n$1.A11yUi.STYLING_TASK_QUEUE.delete(t),R();};class ye{Prefix;Key;Tag;createTheme=(e,s)=>F(e,s);createTranslation=(e,s)=>j(e,s);constructor(e,s,a){this.Prefix=e,this.Key=Object.getOwnPropertyNames(s),this.Tag=Object.getOwnPropertyNames(a);}}
2669
+ .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);}}
2670
2670
 
2671
2671
  var KeyEnum;
2672
2672
  (function (KeyEnum) {
2673
- KeyEnum[KeyEnum["error"] = 0] = "error";
2674
- KeyEnum[KeyEnum["warning"] = 1] = "warning";
2675
- KeyEnum[KeyEnum["info"] = 2] = "info";
2676
- KeyEnum[KeyEnum["success"] = 3] = "success";
2677
- KeyEnum[KeyEnum["message"] = 4] = "message";
2678
- KeyEnum[KeyEnum["close"] = 5] = "close";
2679
- KeyEnum[KeyEnum["form-description"] = 6] = "form-description";
2680
- KeyEnum[KeyEnum["of"] = 7] = "of";
2681
- KeyEnum[KeyEnum["characters"] = 8] = "characters";
2682
- KeyEnum[KeyEnum["new"] = 9] = "new";
2683
- KeyEnum[KeyEnum["no-entries"] = 10] = "no-entries";
2684
- KeyEnum[KeyEnum["change-order"] = 11] = "change-order";
2685
- KeyEnum[KeyEnum["action-running"] = 12] = "action-running";
2686
- KeyEnum[KeyEnum["action-done"] = 13] = "action-done";
2687
- KeyEnum[KeyEnum["page-first"] = 14] = "page-first";
2688
- KeyEnum[KeyEnum["page-back"] = 15] = "page-back";
2689
- KeyEnum[KeyEnum["page-next"] = 16] = "page-next";
2690
- KeyEnum[KeyEnum["page-last"] = 17] = "page-last";
2691
- KeyEnum[KeyEnum["entries-per-site"] = 18] = "entries-per-site";
2692
- KeyEnum[KeyEnum["page-current"] = 19] = "page-current";
2693
- KeyEnum[KeyEnum["page-selected"] = 20] = "page-selected";
2694
- KeyEnum[KeyEnum["page-per-site"] = 21] = "page-per-site";
2695
- KeyEnum[KeyEnum["logo-description"] = 22] = "logo-description";
2696
- KeyEnum[KeyEnum["open-link-in-tab"] = 23] = "open-link-in-tab";
2697
- KeyEnum[KeyEnum["kolibri-logo"] = 24] = "kolibri-logo";
2673
+ KeyEnum["error"] = "error";
2674
+ KeyEnum["warning"] = "warning";
2675
+ KeyEnum["info"] = "info";
2676
+ KeyEnum["success"] = "success";
2677
+ KeyEnum["message"] = "message";
2678
+ KeyEnum["close"] = "close";
2679
+ KeyEnum["form-description"] = "form-description";
2680
+ KeyEnum["of"] = "of";
2681
+ KeyEnum["characters"] = "characters";
2682
+ KeyEnum["new"] = "new";
2683
+ KeyEnum["no-entries"] = "no-entries";
2684
+ KeyEnum["change-order"] = "change-order";
2685
+ KeyEnum["action-running"] = "action-running";
2686
+ KeyEnum["action-done"] = "action-done";
2687
+ KeyEnum["page-first"] = "page-first";
2688
+ KeyEnum["page-back"] = "page-back";
2689
+ KeyEnum["page-next"] = "page-next";
2690
+ KeyEnum["page-last"] = "page-last";
2691
+ KeyEnum["entries-per-site"] = "entries-per-site";
2692
+ KeyEnum["page-current"] = "page-current";
2693
+ KeyEnum["page-selected"] = "page-selected";
2694
+ KeyEnum["page-per-site"] = "page-per-site";
2695
+ KeyEnum["logo-description"] = "logo-description";
2696
+ KeyEnum["open-link-in-tab"] = "open-link-in-tab";
2697
+ KeyEnum["kolibri-logo"] = "kolibri-logo";
2698
2698
  })(KeyEnum || (KeyEnum = {}));
2699
2699
 
2700
2700
  var TagEnum;
2701
2701
  (function (TagEnum) {
2702
- TagEnum[TagEnum["abbr"] = 0] = "abbr";
2703
- TagEnum[TagEnum["accordion"] = 1] = "accordion";
2704
- TagEnum[TagEnum["alert"] = 2] = "alert";
2705
- TagEnum[TagEnum["avatar"] = 3] = "avatar";
2706
- TagEnum[TagEnum["badge"] = 4] = "badge";
2707
- TagEnum[TagEnum["breadcrumb"] = 5] = "breadcrumb";
2708
- TagEnum[TagEnum["button"] = 6] = "button";
2709
- TagEnum[TagEnum["button-group"] = 7] = "button-group";
2710
- TagEnum[TagEnum["button-link"] = 8] = "button-link";
2711
- TagEnum[TagEnum["card"] = 9] = "card";
2712
- TagEnum[TagEnum["combobox"] = 10] = "combobox";
2713
- TagEnum[TagEnum["details"] = 11] = "details";
2714
- TagEnum[TagEnum["drawer"] = 12] = "drawer";
2715
- TagEnum[TagEnum["form"] = 13] = "form";
2716
- TagEnum[TagEnum["heading"] = 14] = "heading";
2717
- TagEnum[TagEnum["icon"] = 15] = "icon";
2718
- TagEnum[TagEnum["image"] = 16] = "image";
2719
- TagEnum[TagEnum["indented-text"] = 17] = "indented-text";
2720
- TagEnum[TagEnum["input-checkbox"] = 18] = "input-checkbox";
2721
- TagEnum[TagEnum["input-color"] = 19] = "input-color";
2722
- TagEnum[TagEnum["input-date"] = 20] = "input-date";
2723
- TagEnum[TagEnum["input-email"] = 21] = "input-email";
2724
- TagEnum[TagEnum["input-file"] = 22] = "input-file";
2725
- TagEnum[TagEnum["input-number"] = 23] = "input-number";
2726
- TagEnum[TagEnum["input-password"] = 24] = "input-password";
2727
- TagEnum[TagEnum["input-radio"] = 25] = "input-radio";
2728
- TagEnum[TagEnum["input-range"] = 26] = "input-range";
2729
- TagEnum[TagEnum["input-text"] = 27] = "input-text";
2730
- TagEnum[TagEnum["kolibri"] = 28] = "kolibri";
2731
- TagEnum[TagEnum["link"] = 29] = "link";
2732
- TagEnum[TagEnum["link-button"] = 30] = "link-button";
2733
- TagEnum[TagEnum["link-group"] = 31] = "link-group";
2734
- TagEnum[TagEnum["logo"] = 32] = "logo";
2735
- TagEnum[TagEnum["modal"] = 33] = "modal";
2736
- TagEnum[TagEnum["nav"] = 34] = "nav";
2737
- TagEnum[TagEnum["pagination"] = 35] = "pagination";
2738
- TagEnum[TagEnum["popover-button"] = 36] = "popover-button";
2739
- TagEnum[TagEnum["progress"] = 37] = "progress";
2740
- TagEnum[TagEnum["quote"] = 38] = "quote";
2741
- TagEnum[TagEnum["select"] = 39] = "select";
2742
- TagEnum[TagEnum["single-select"] = 40] = "single-select";
2743
- TagEnum[TagEnum["skip-nav"] = 41] = "skip-nav";
2744
- TagEnum[TagEnum["spin"] = 42] = "spin";
2745
- TagEnum[TagEnum["split-button"] = 43] = "split-button";
2746
- TagEnum[TagEnum["symbol"] = 44] = "symbol";
2747
- TagEnum[TagEnum["table"] = 45] = "table";
2748
- TagEnum[TagEnum["table-stateful"] = 46] = "table-stateful";
2749
- TagEnum[TagEnum["table-stateless"] = 47] = "table-stateless";
2750
- TagEnum[TagEnum["tabs"] = 48] = "tabs";
2751
- TagEnum[TagEnum["textarea"] = 49] = "textarea";
2752
- TagEnum[TagEnum["toast-container"] = 50] = "toast-container";
2753
- TagEnum[TagEnum["toolbar"] = 51] = "toolbar";
2754
- TagEnum[TagEnum["tooltip"] = 52] = "tooltip";
2755
- TagEnum[TagEnum["tree"] = 53] = "tree";
2756
- TagEnum[TagEnum["tree-item"] = 54] = "tree-item";
2702
+ TagEnum["abbr"] = "abbr";
2703
+ TagEnum["accordion"] = "accordion";
2704
+ TagEnum["alert"] = "alert";
2705
+ TagEnum["avatar"] = "avatar";
2706
+ TagEnum["badge"] = "badge";
2707
+ TagEnum["breadcrumb"] = "breadcrumb";
2708
+ TagEnum["button"] = "button";
2709
+ TagEnum["button-group"] = "button-group";
2710
+ TagEnum["button-link"] = "button-link";
2711
+ TagEnum["card"] = "card";
2712
+ TagEnum["combobox"] = "combobox";
2713
+ TagEnum["details"] = "details";
2714
+ TagEnum["drawer"] = "drawer";
2715
+ TagEnum["form"] = "form";
2716
+ TagEnum["heading"] = "heading";
2717
+ TagEnum["icon"] = "icon";
2718
+ TagEnum["image"] = "image";
2719
+ TagEnum["indented-text"] = "indented-text";
2720
+ TagEnum["input-checkbox"] = "input-checkbox";
2721
+ TagEnum["input-color"] = "input-color";
2722
+ TagEnum["input-date"] = "input-date";
2723
+ TagEnum["input-email"] = "input-email";
2724
+ TagEnum["input-file"] = "input-file";
2725
+ TagEnum["input-number"] = "input-number";
2726
+ TagEnum["input-password"] = "input-password";
2727
+ TagEnum["input-radio"] = "input-radio";
2728
+ TagEnum["input-range"] = "input-range";
2729
+ TagEnum["input-text"] = "input-text";
2730
+ TagEnum["kolibri"] = "kolibri";
2731
+ TagEnum["link"] = "link";
2732
+ TagEnum["link-button"] = "link-button";
2733
+ TagEnum["link-group"] = "link-group";
2734
+ TagEnum["logo"] = "logo";
2735
+ TagEnum["modal"] = "modal";
2736
+ TagEnum["nav"] = "nav";
2737
+ TagEnum["pagination"] = "pagination";
2738
+ TagEnum["popover-button"] = "popover-button";
2739
+ TagEnum["progress"] = "progress";
2740
+ TagEnum["quote"] = "quote";
2741
+ TagEnum["select"] = "select";
2742
+ TagEnum["single-select"] = "single-select";
2743
+ TagEnum["skip-nav"] = "skip-nav";
2744
+ TagEnum["spin"] = "spin";
2745
+ TagEnum["split-button"] = "split-button";
2746
+ TagEnum["symbol"] = "symbol";
2747
+ TagEnum["table"] = "table";
2748
+ TagEnum["table-stateful"] = "table-stateful";
2749
+ TagEnum["table-stateless"] = "table-stateless";
2750
+ TagEnum["tabs"] = "tabs";
2751
+ TagEnum["textarea"] = "textarea";
2752
+ TagEnum["toast-container"] = "toast-container";
2753
+ TagEnum["toolbar"] = "toolbar";
2754
+ TagEnum["tooltip"] = "tooltip";
2755
+ TagEnum["tree"] = "tree";
2756
+ TagEnum["tree-item"] = "tree-item";
2757
2757
  })(TagEnum || (TagEnum = {}));
2758
2758
 
2759
2759
  const alertTypeOptions = ['default', 'info', 'success', 'warning', 'error'];
@@ -3798,9 +3798,9 @@ const koliBriQuerySelector = (selector, node) => querySelector(selector, node ||
3798
3798
  const koliBriQuerySelectorAll = (selector, node) => querySelectorAll(selector, node || getDocument());
3799
3799
  class KoliBriDevHelper {
3800
3800
  }
3801
- KoliBriDevHelper.getCssStyle = y;
3802
- KoliBriDevHelper.patchTheme = K;
3803
- KoliBriDevHelper.patchThemeTag = x;
3801
+ KoliBriDevHelper.getCssStyle = T;
3802
+ KoliBriDevHelper.patchTheme = z;
3803
+ KoliBriDevHelper.patchThemeTag = D;
3804
3804
  KoliBriDevHelper.querySelector = koliBriQuerySelector;
3805
3805
  KoliBriDevHelper.querySelectorAll = koliBriQuerySelectorAll;
3806
3806
  KoliBriDevHelper.stringifyJson = stringifyJson;
@@ -4497,7 +4497,7 @@ var KoliBriProgressVariantEnum;
4497
4497
  KoliBriProgressVariantEnum["cycle"] = "cycle";
4498
4498
  })(KoliBriProgressVariantEnum || (KoliBriProgressVariantEnum = {}));
4499
4499
 
4500
- new ye('kol', KeyEnum, TagEnum);
4500
+ new Ee('kol', KeyEnum, TagEnum);
4501
4501
 
4502
4502
  let nonce = () => Math.floor(Math.random() * 16777215).toString(16);
4503
4503
  if (processEnv === 'test') {
@@ -12369,12 +12369,12 @@ function getOppositePlacement(placement) {
12369
12369
  return oppositeSideMap[side] + placement.slice(side.length);
12370
12370
  }
12371
12371
  function expandPaddingObject(padding) {
12372
+ var _padding$top, _padding$right, _padding$bottom, _padding$left;
12372
12373
  return {
12373
- top: 0,
12374
- right: 0,
12375
- bottom: 0,
12376
- left: 0,
12377
- ...padding
12374
+ top: (_padding$top = padding.top) != null ? _padding$top : 0,
12375
+ right: (_padding$right = padding.right) != null ? _padding$right : 0,
12376
+ bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0,
12377
+ left: (_padding$left = padding.left) != null ? _padding$left : 0
12378
12378
  };
12379
12379
  }
12380
12380
  function getPaddingObject(padding) {
@@ -12449,13 +12449,9 @@ function computeCoordsFromPlacement(_ref, placement, rtl) {
12449
12449
  y: reference.y
12450
12450
  };
12451
12451
  }
12452
- switch (getAlignment(placement)) {
12453
- case 'start':
12454
- coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
12455
- break;
12456
- case 'end':
12457
- coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
12458
- break;
12452
+ const alignment = getAlignment(placement);
12453
+ if (alignment) {
12454
+ coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);
12459
12455
  }
12460
12456
  return coords;
12461
12457
  }
@@ -12504,10 +12500,7 @@ async function detectOverflow(state, options) {
12504
12500
  height: rects.floating.height
12505
12501
  } : rects.reference;
12506
12502
  const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
12507
- const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
12508
- x: 1,
12509
- y: 1
12510
- } : {
12503
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
12511
12504
  x: 1,
12512
12505
  y: 1
12513
12506
  };
@@ -12680,17 +12673,16 @@ const arrow$1 = options => ({
12680
12673
 
12681
12674
  // Make sure the arrow doesn't overflow the floating element if the center
12682
12675
  // point is outside the floating element's bounds.
12683
- const min$1 = minPadding;
12684
12676
  const max = clientSize - arrowDimensions[length] - maxPadding;
12685
12677
  const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
12686
- const offset = clamp(min$1, center, max);
12678
+ const offset = clamp(minPadding, center, max);
12687
12679
 
12688
12680
  // If the reference is small enough that the arrow's padding causes it to
12689
12681
  // to point to nothing for an aligned placement, adjust the offset of the
12690
12682
  // floating element itself. To ensure `shift()` continues to take action,
12691
12683
  // a single reset is performed when this is true.
12692
- const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
12693
- const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
12684
+ const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < minPadding ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
12685
+ const alignmentOffset = shouldAddOffset ? center < minPadding ? center - minPadding : center - max : 0;
12694
12686
  return {
12695
12687
  [axis]: coords[axis] + alignmentOffset,
12696
12688
  data: {
@@ -12744,13 +12736,11 @@ const autoPlacement = function (options) {
12744
12736
  ...detectOverflowOptions
12745
12737
  } = evaluate(options, state);
12746
12738
  const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;
12747
- const overflow = await platform.detectOverflow(state, detectOverflowOptions);
12748
12739
  const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;
12749
12740
  const currentPlacement = placements$1[currentIndex];
12750
12741
  if (currentPlacement == null) {
12751
12742
  return {};
12752
12743
  }
12753
- const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
12754
12744
 
12755
12745
  // Make `computeCoords` start from the right place.
12756
12746
  if (placement !== currentPlacement) {
@@ -12760,6 +12750,8 @@ const autoPlacement = function (options) {
12760
12750
  }
12761
12751
  };
12762
12752
  }
12753
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
12754
+ const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
12763
12755
  const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];
12764
12756
  const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {
12765
12757
  placement: currentPlacement,
@@ -13066,12 +13058,19 @@ const inline$1 = function (options) {
13066
13058
  y
13067
13059
  } = evaluate(options, state);
13068
13060
  const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);
13061
+
13062
+ // No rects (e.g. a hidden or detached reference, or a collapsed range) —
13063
+ // keep the existing reference rect rather than resetting to an invalid
13064
+ // one with non-finite values.
13065
+ if (!nativeClientRects.length) {
13066
+ return {};
13067
+ }
13069
13068
  const clientRects = getRectsByLine(nativeClientRects);
13070
13069
  const fallback = rectToClientRect(getBoundingRect(nativeClientRects));
13071
13070
  const paddingObject = getPaddingObject(padding);
13072
13071
  function getBoundingClientRect() {
13073
13072
  // There are two rects and they are disjoined.
13074
- if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {
13073
+ if (clientRects.length === 2 && (clientRects[0].left > clientRects[1].right || clientRects[1].left > clientRects[0].right) && x != null && y != null) {
13075
13074
  // Find the first rect in which the point is fully inside.
13076
13075
  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;
13077
13076
  }
@@ -13086,18 +13085,12 @@ const inline$1 = function (options) {
13086
13085
  const bottom = lastRect.bottom;
13087
13086
  const left = isTop ? firstRect.left : lastRect.left;
13088
13087
  const right = isTop ? firstRect.right : lastRect.right;
13089
- const width = right - left;
13090
- const height = bottom - top;
13091
- return {
13092
- top,
13093
- bottom,
13094
- left,
13095
- right,
13096
- width,
13097
- height,
13088
+ return rectToClientRect({
13098
13089
  x: left,
13099
- y: top
13100
- };
13090
+ y: top,
13091
+ width: right - left,
13092
+ height: bottom - top
13093
+ });
13101
13094
  }
13102
13095
  const isLeftSide = getSide(placement) === 'left';
13103
13096
  const maxRight = max(...clientRects.map(rect => rect.right));
@@ -13105,20 +13098,12 @@ const inline$1 = function (options) {
13105
13098
  const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);
13106
13099
  const top = measureRects[0].top;
13107
13100
  const bottom = measureRects[measureRects.length - 1].bottom;
13108
- const left = minLeft;
13109
- const right = maxRight;
13110
- const width = right - left;
13111
- const height = bottom - top;
13112
- return {
13113
- top,
13114
- bottom,
13115
- left,
13116
- right,
13117
- width,
13118
- height,
13119
- x: left,
13120
- y: top
13121
- };
13101
+ return rectToClientRect({
13102
+ x: minLeft,
13103
+ y: top,
13104
+ width: maxRight - minLeft,
13105
+ height: bottom - top
13106
+ });
13122
13107
  }
13123
13108
  return fallback;
13124
13109
  }
@@ -13268,23 +13253,16 @@ const shift$1 = function (options) {
13268
13253
  y
13269
13254
  };
13270
13255
  const overflow = await platform.detectOverflow(state, detectOverflowOptions);
13271
- const crossAxis = getSideAxis(getSide(placement));
13256
+ const crossAxis = getSideAxis(placement);
13272
13257
  const mainAxis = getOppositeAxis(crossAxis);
13273
13258
  let mainAxisCoord = coords[mainAxis];
13274
13259
  let crossAxisCoord = coords[crossAxis];
13260
+ const clampCoord = (axis, coord) => clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);
13275
13261
  if (checkMainAxis) {
13276
- const minSide = mainAxis === 'y' ? 'top' : 'left';
13277
- const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
13278
- const min = mainAxisCoord + overflow[minSide];
13279
- const max = mainAxisCoord - overflow[maxSide];
13280
- mainAxisCoord = clamp(min, mainAxisCoord, max);
13262
+ mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);
13281
13263
  }
13282
13264
  if (checkCrossAxis) {
13283
- const minSide = crossAxis === 'y' ? 'top' : 'left';
13284
- const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
13285
- const min = crossAxisCoord + overflow[minSide];
13286
- const max = crossAxisCoord - overflow[maxSide];
13287
- crossAxisCoord = clamp(min, crossAxisCoord, max);
13265
+ crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);
13288
13266
  }
13289
13267
  const limitedCoords = limiter.fn({
13290
13268
  ...state,
@@ -13315,6 +13293,7 @@ const limitShift = function (options) {
13315
13293
  return {
13316
13294
  options,
13317
13295
  fn(state) {
13296
+ var _rawOffset$mainAxis, _rawOffset$crossAxis;
13318
13297
  const {
13319
13298
  x,
13320
13299
  y,
@@ -13340,9 +13319,8 @@ const limitShift = function (options) {
13340
13319
  mainAxis: rawOffset,
13341
13320
  crossAxis: 0
13342
13321
  } : {
13343
- mainAxis: 0,
13344
- crossAxis: 0,
13345
- ...rawOffset
13322
+ mainAxis: (_rawOffset$mainAxis = rawOffset.mainAxis) != null ? _rawOffset$mainAxis : 0,
13323
+ crossAxis: (_rawOffset$crossAxis = rawOffset.crossAxis) != null ? _rawOffset$crossAxis : 0
13346
13324
  };
13347
13325
  if (checkMainAxis) {
13348
13326
  const len = mainAxis === 'y' ? 'height' : 'width';
@@ -13374,6 +13352,12 @@ const limitShift = function (options) {
13374
13352
  };
13375
13353
  };
13376
13354
 
13355
+ // Method syntax keeps callback parameters bivariant, but expressing the
13356
+ // explicit `| undefined` required by `exactOptionalPropertyTypes` needs
13357
+ // property syntax, which is contravariant under `strictFunctionTypes`.
13358
+ // Extracting the function from a method position restores that bivariance so
13359
+ // consumers can still assign callbacks with narrower parameter types.
13360
+
13377
13361
  /**
13378
13362
  * Provides data that allows you to change the size of the floating element —
13379
13363
  * for instance, prevent it from overflowing the clipping boundary or match the
@@ -13388,7 +13372,6 @@ const size = function (options) {
13388
13372
  name: 'size',
13389
13373
  options,
13390
13374
  async fn(state) {
13391
- var _state$middlewareData, _state$middlewareData2;
13392
13375
  const {
13393
13376
  placement,
13394
13377
  rects,
@@ -13420,24 +13403,21 @@ const size = function (options) {
13420
13403
  const maximumClippingWidth = width - overflow.left - overflow.right;
13421
13404
  const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
13422
13405
  const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
13423
- const noShift = !state.middlewareData.shift;
13406
+ const shiftData = state.middlewareData.shift;
13407
+ const noShift = !shiftData;
13424
13408
  let availableHeight = overflowAvailableHeight;
13425
13409
  let availableWidth = overflowAvailableWidth;
13426
- if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
13410
+ if (shiftData != null && shiftData.enabled.x) {
13427
13411
  availableWidth = maximumClippingWidth;
13428
13412
  }
13429
- if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
13413
+ if (shiftData != null && shiftData.enabled.y) {
13430
13414
  availableHeight = maximumClippingHeight;
13431
13415
  }
13432
13416
  if (noShift && !alignment) {
13433
- const xMin = max(overflow.left, 0);
13434
- const xMax = max(overflow.right, 0);
13435
- const yMin = max(overflow.top, 0);
13436
- const yMax = max(overflow.bottom, 0);
13437
13417
  if (isYAxis) {
13438
- availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
13418
+ availableWidth = width - 2 * max(overflow.left, overflow.right);
13439
13419
  } else {
13440
- availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
13420
+ availableHeight = height - 2 * max(overflow.top, overflow.bottom);
13441
13421
  }
13442
13422
  }
13443
13423
  await apply({
@@ -13593,7 +13573,7 @@ function getParentNode(node) {
13593
13573
  function getNearestOverflowAncestor(node) {
13594
13574
  const parentNode = getParentNode(node);
13595
13575
  if (isLastTraversableNode(parentNode)) {
13596
- return node.ownerDocument ? node.ownerDocument.body : node.body;
13576
+ return (node.ownerDocument || node).body;
13597
13577
  }
13598
13578
  if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
13599
13579
  return parentNode;
@@ -13690,10 +13670,7 @@ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
13690
13670
  if (isFixed === void 0) {
13691
13671
  isFixed = false;
13692
13672
  }
13693
- if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
13694
- return false;
13695
- }
13696
- return isFixed;
13673
+ return !!floatingOffsetParent && isFixed && floatingOffsetParent === getWindow(element);
13697
13674
  }
13698
13675
 
13699
13676
  function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
@@ -13720,12 +13697,12 @@ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetPar
13720
13697
  let y = (clientRect.top + visualOffsets.y) / scale.y;
13721
13698
  let width = clientRect.width / scale.x;
13722
13699
  let height = clientRect.height / scale.y;
13723
- if (domElement) {
13700
+ if (domElement && offsetParent) {
13724
13701
  const win = getWindow(domElement);
13725
- const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
13702
+ const offsetWin = isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
13726
13703
  let currentWin = win;
13727
13704
  let currentIFrame = getFrameElement(currentWin);
13728
- while (currentIFrame && offsetParent && offsetWin !== currentWin) {
13705
+ while (currentIFrame && offsetWin !== currentWin) {
13729
13706
  const iframeScale = getScale(currentIFrame);
13730
13707
  const iframeRect = currentIFrame.getBoundingClientRect();
13731
13708
  const css = getComputedStyle$1(currentIFrame);
@@ -13789,7 +13766,7 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
13789
13766
  let scale = createCoords(1);
13790
13767
  const offsets = createCoords(0);
13791
13768
  const isOffsetParentAnElement = isHTMLElement(offsetParent);
13792
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
13769
+ if (isOffsetParentAnElement || !isFixed) {
13793
13770
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
13794
13771
  scroll = getNodeScroll(offsetParent);
13795
13772
  }
@@ -13810,18 +13787,17 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
13810
13787
  }
13811
13788
 
13812
13789
  function getClientRects(element) {
13813
- return Array.from(element.getClientRects());
13790
+ return element.getClientRects ? Array.from(element.getClientRects()) : [];
13814
13791
  }
13815
13792
 
13816
13793
  // Gets the entire size of the scrollable document area, even extending outside
13817
13794
  // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
13818
- function getDocumentRect(element) {
13819
- const html = getDocumentElement(element);
13820
- const scroll = getNodeScroll(element);
13821
- const body = element.ownerDocument.body;
13795
+ function getDocumentRect(html) {
13796
+ const scroll = getNodeScroll(html);
13797
+ const body = html.ownerDocument.body;
13822
13798
  const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
13823
13799
  const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
13824
- let x = -scroll.scrollLeft + getWindowScrollBarX(element);
13800
+ let x = -scroll.scrollLeft + getWindowScrollBarX(html);
13825
13801
  const y = -scroll.scrollTop;
13826
13802
  if (getComputedStyle$1(body).direction === 'rtl') {
13827
13803
  x += max(html.clientWidth, body.clientWidth) - width;
@@ -13838,7 +13814,11 @@ function getDocumentRect(element) {
13838
13814
  // calculation is affected by unusual styles.
13839
13815
  // Most scrollbars leave 15-18px of space.
13840
13816
  const SCROLLBAR_MAX = 25;
13841
- function getViewportRect(element, strategy) {
13817
+ function getViewportRect(element, strategy, rootBoundary) {
13818
+ if (rootBoundary === void 0) {
13819
+ rootBoundary = 'viewport';
13820
+ }
13821
+ const isLayoutViewport = rootBoundary === 'layoutViewport';
13842
13822
  const win = getWindow(element);
13843
13823
  const html = getDocumentElement(element);
13844
13824
  const visualViewport = win.visualViewport;
@@ -13847,31 +13827,42 @@ function getViewportRect(element, strategy) {
13847
13827
  let x = 0;
13848
13828
  let y = 0;
13849
13829
  if (visualViewport) {
13850
- width = visualViewport.width;
13851
- height = visualViewport.height;
13852
- const visualViewportBased = isWebKit();
13853
- if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
13854
- x = visualViewport.offsetLeft;
13855
- y = visualViewport.offsetTop;
13830
+ // Client coordinates are relative to the layout viewport, except in
13831
+ // WebKit with an `absolute` strategy, where they are relative to the
13832
+ // visual viewport.
13833
+ const layoutRelativeClientCoords = !isWebKit() || strategy === 'fixed';
13834
+ if (isLayoutViewport) {
13835
+ if (!layoutRelativeClientCoords) {
13836
+ x = -visualViewport.offsetLeft;
13837
+ y = -visualViewport.offsetTop;
13838
+ }
13839
+ } else {
13840
+ width = visualViewport.width;
13841
+ height = visualViewport.height;
13842
+ if (layoutRelativeClientCoords) {
13843
+ x = visualViewport.offsetLeft;
13844
+ y = visualViewport.offsetTop;
13845
+ }
13856
13846
  }
13857
13847
  }
13858
13848
  const windowScrollbarX = getWindowScrollBarX(html);
13859
- // <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the
13860
- // visual width of the <html> but this is not considered in the size
13861
- // of `html.clientWidth`.
13849
+ // `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks
13850
+ // the visual width but isn't reflected in `html.clientWidth`, so subtract it.
13851
+ // Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also
13852
+ // reserves an empty inline-start gutter that clips nothing, so exclude just
13853
+ // the one scrollbar-side gutter — halve the measured (two-gutter) total. A
13854
+ // left-side scrollbar (`windowScrollbarX > 0`) is already handled by
13855
+ // `getHTMLOffset`/`visualViewport.width`; skip it here.
13862
13856
  if (windowScrollbarX <= 0) {
13863
13857
  const doc = html.ownerDocument;
13864
13858
  const body = doc.body;
13865
13859
  const bodyStyles = getComputedStyle(body);
13866
13860
  const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
13867
- const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
13868
- if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
13869
- width -= clippingStableScrollbarWidth;
13861
+ const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
13862
+ const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;
13863
+ if (gutter <= SCROLLBAR_MAX) {
13864
+ width -= gutter;
13870
13865
  }
13871
- } else if (windowScrollbarX <= SCROLLBAR_MAX) {
13872
- // If the <body> scrollbar is on the left, the width needs to be extended
13873
- // by the scrollbar amount so there isn't extra space on the right.
13874
- width += windowScrollbarX;
13875
13866
  }
13876
13867
  return {
13877
13868
  width,
@@ -13886,7 +13877,7 @@ function getInnerBoundingClientRect(element, strategy) {
13886
13877
  const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
13887
13878
  const top = clientRect.top + element.clientTop;
13888
13879
  const left = clientRect.left + element.clientLeft;
13889
- const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
13880
+ const scale = getScale(element);
13890
13881
  const width = element.clientWidth * scale.x;
13891
13882
  const height = element.clientHeight * scale.y;
13892
13883
  const x = left * scale.x;
@@ -13900,8 +13891,8 @@ function getInnerBoundingClientRect(element, strategy) {
13900
13891
  }
13901
13892
  function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
13902
13893
  let rect;
13903
- if (clippingAncestor === 'viewport') {
13904
- rect = getViewportRect(element, strategy);
13894
+ if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {
13895
+ rect = getViewportRect(element, strategy, clippingAncestor);
13905
13896
  } else if (clippingAncestor === 'document') {
13906
13897
  rect = getDocumentRect(getDocumentElement(element));
13907
13898
  } else if (isElement(clippingAncestor)) {
@@ -13917,13 +13908,6 @@ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy)
13917
13908
  }
13918
13909
  return rectToClientRect(rect);
13919
13910
  }
13920
- function hasFixedPositionAncestor(element, stopNode) {
13921
- const parentNode = getParentNode(element);
13922
- if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
13923
- return false;
13924
- }
13925
- return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
13926
- }
13927
13911
 
13928
13912
  // A "clipping ancestor" is an `overflow` element with the characteristic of
13929
13913
  // clipping (or hiding) child elements. This returns all clipping ancestors
@@ -13934,7 +13918,7 @@ function getClippingElementAncestors(element, cache) {
13934
13918
  return cachedResult;
13935
13919
  }
13936
13920
  let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
13937
- let currentContainingBlockComputedStyle = null;
13921
+ let lastKeptComputedStyle = null;
13938
13922
  const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
13939
13923
  let currentNode = elementIsFixed ? getParentNode(element) : element;
13940
13924
 
@@ -13942,16 +13926,20 @@ function getClippingElementAncestors(element, cache) {
13942
13926
  while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
13943
13927
  const computedStyle = getComputedStyle$1(currentNode);
13944
13928
  const currentNodeIsContaining = isContainingBlock(currentNode);
13945
- if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
13946
- currentContainingBlockComputedStyle = null;
13947
- }
13948
- const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === 'absolute' || currentContainingBlockComputedStyle.position === 'fixed') || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
13929
+ // Position of the containing block chain below the current node. A fixed
13930
+ // element whose containing block hasn't been found yet is a fixed chain.
13931
+ const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';
13932
+
13933
+ // A non-containing ancestor does not clip the element when the chain
13934
+ // below it escapes it: a fixed chain escapes all ancestors up to the
13935
+ // next containing block, an absolute chain escapes static ancestors.
13936
+ const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');
13949
13937
  if (shouldDropCurrentNode) {
13950
13938
  // Drop non-containing blocks.
13951
13939
  result = result.filter(ancestor => ancestor !== currentNode);
13952
13940
  } else {
13953
- // Record last containing block for next iteration.
13954
- currentContainingBlockComputedStyle = computedStyle;
13941
+ // The kept node carries the chain position for the next iteration.
13942
+ lastKeptComputedStyle = computedStyle;
13955
13943
  }
13956
13944
  currentNode = getParentNode(currentNode);
13957
13945
  }
@@ -14011,13 +13999,7 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
14011
13999
  scrollTop: 0
14012
14000
  };
14013
14001
  const offsets = createCoords(0);
14014
-
14015
- // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
14016
- // Firefox with layout.scrollbar.side = 3 in about:config to test this.
14017
- function setLeftRTLScrollbarOffset() {
14018
- offsets.x = getWindowScrollBarX(documentElement);
14019
- }
14020
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
14002
+ if (isOffsetParentAnElement || !isFixed) {
14021
14003
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
14022
14004
  scroll = getNodeScroll(offsetParent);
14023
14005
  }
@@ -14025,12 +14007,13 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
14025
14007
  const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
14026
14008
  offsets.x = offsetRect.x + offsetParent.clientLeft;
14027
14009
  offsets.y = offsetRect.y + offsetParent.clientTop;
14028
- } else if (documentElement) {
14029
- setLeftRTLScrollbarOffset();
14030
14010
  }
14031
14011
  }
14032
- if (isFixed && !isOffsetParentAnElement && documentElement) {
14033
- setLeftRTLScrollbarOffset();
14012
+
14013
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
14014
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
14015
+ if (!isOffsetParentAnElement && documentElement) {
14016
+ offsets.x = getWindowScrollBarX(documentElement);
14034
14017
  }
14035
14018
  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
14036
14019
  const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
@@ -14130,7 +14113,7 @@ function rectsAreEqual(a, b) {
14130
14113
  }
14131
14114
 
14132
14115
  // https://samthor.au/2021/observing-dom/
14133
- function observeMove(element, onMove) {
14116
+ function observeMove(element, onMove, ancestorResize) {
14134
14117
  let io = null;
14135
14118
  let timeoutId;
14136
14119
  const root = getDocumentElement(element);
@@ -14173,13 +14156,22 @@ function observeMove(element, onMove) {
14173
14156
  let isFirstUpdate = true;
14174
14157
  function handleObserve(entries) {
14175
14158
  const ratio = entries[0].intersectionRatio;
14159
+
14160
+ // The entry is a snapshot, so the reference may have moved since the
14161
+ // intersection was computed (under performance constraints, or between
14162
+ // consecutive frames of a multi-frame layout shift). The reported ratio
14163
+ // and the observed area are stale in that case and cannot be trusted to
14164
+ // detect subsequent movement, so refresh regardless of the ratio.
14165
+ if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
14166
+ return refresh();
14167
+ }
14176
14168
  if (ratio !== threshold) {
14177
14169
  if (!isFirstUpdate) {
14178
14170
  return refresh();
14179
14171
  }
14180
14172
  if (!ratio) {
14181
- // If the reference is clipped, the ratio is 0. Throttle the refresh
14182
- // to prevent an infinite loop of updates.
14173
+ // If the reference is clipped in place, the ratio is 0. Throttle
14174
+ // the refresh to prevent an infinite loop of updates.
14183
14175
  timeoutId = setTimeout(() => {
14184
14176
  refresh(false, 1e-7);
14185
14177
  }, 1000);
@@ -14187,16 +14179,6 @@ function observeMove(element, onMove) {
14187
14179
  refresh(false, ratio);
14188
14180
  }
14189
14181
  }
14190
- if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
14191
- // It's possible that even though the ratio is reported as 1, the
14192
- // element is not actually fully within the IntersectionObserver's root
14193
- // area anymore. This can happen under performance constraints. This may
14194
- // be a bug in the browser's IntersectionObserver implementation. To
14195
- // work around this, we compare the element's bounding rect now with
14196
- // what it was at the time we created the IntersectionObserver. If they
14197
- // are not equal then the element moved, so we refresh.
14198
- refresh();
14199
- }
14200
14182
  isFirstUpdate = false;
14201
14183
  }
14202
14184
 
@@ -14213,8 +14195,18 @@ function observeMove(element, onMove) {
14213
14195
  }
14214
14196
  io.observe(element);
14215
14197
  }
14198
+ const win = getWindow(element);
14199
+ // The window is a resize ancestor, so when `ancestorResize` is enabled its
14200
+ // listener already runs the update on resize. Here we only need to rebuild
14201
+ // the `IntersectionObserver` for the new root size, skipping a redundant
14202
+ // update. When `ancestorResize` is disabled, this becomes the sole update.
14203
+ const handleResize = () => refresh(ancestorResize);
14204
+ win.addEventListener('resize', handleResize);
14216
14205
  refresh(true);
14217
- return cleanup;
14206
+ return () => {
14207
+ win.removeEventListener('resize', handleResize);
14208
+ cleanup();
14209
+ };
14218
14210
  }
14219
14211
 
14220
14212
  /**
@@ -14239,12 +14231,10 @@ function autoUpdate(reference, floating, update, options) {
14239
14231
  const referenceEl = unwrapElement(reference);
14240
14232
  const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];
14241
14233
  ancestors.forEach(ancestor => {
14242
- ancestorScroll && ancestor.addEventListener('scroll', update, {
14243
- passive: true
14244
- });
14234
+ ancestorScroll && ancestor.addEventListener('scroll', update);
14245
14235
  ancestorResize && ancestor.addEventListener('resize', update);
14246
14236
  });
14247
- const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
14237
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;
14248
14238
  let reobserveFrame = -1;
14249
14239
  let resizeObserver = null;
14250
14240
  if (elementResize) {
@@ -14373,11 +14363,9 @@ const computePosition = (reference, floating, options) => {
14373
14363
  // multiple lifecycle resets re-use the same result. It only lives for a
14374
14364
  // single call. If other functions become expensive, we can add them as well.
14375
14365
  const cache = new Map();
14376
- const mergedOptions = {
14377
- platform,
14378
- ...options
14379
- };
14366
+ const mergedOptions = options != null ? options : {};
14380
14367
  const platformWithCache = {
14368
+ ...platform,
14381
14369
  ...mergedOptions.platform,
14382
14370
  _c: cache
14383
14371
  };
@@ -17035,6 +17023,15 @@ getDecoder(xmlDecodeTree);
17035
17023
  function decodeHTML(str, mode = DecodingMode.Legacy) {
17036
17024
  return htmlDecoder(str, mode);
17037
17025
  }
17026
+ /**
17027
+ * Decodes an HTML string, requiring all entities to be terminated by a semicolon.
17028
+ *
17029
+ * @param str The string to decode.
17030
+ * @returns The decoded string.
17031
+ */
17032
+ function decodeHTMLStrict(str) {
17033
+ return htmlDecoder(str, DecodingMode.Strict);
17034
+ }
17038
17035
 
17039
17036
  // Utilities
17040
17037
 
@@ -17075,7 +17072,6 @@ function arrayReplaceAt (src, pos, newElements) {
17075
17072
  }
17076
17073
 
17077
17074
  function isValidEntityCode (c) {
17078
- /* eslint no-bitwise:0 */
17079
17075
  // broken sequence
17080
17076
  if (c >= 0xD800 && c <= 0xDFFF) { return false }
17081
17077
  // never used
@@ -17103,8 +17099,8 @@ function fromCodePoint (c) {
17103
17099
  return String.fromCharCode(c)
17104
17100
  }
17105
17101
 
17106
- const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
17107
- const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
17102
+ const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
17103
+ const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
17108
17104
  const UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');
17109
17105
 
17110
17106
  const DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i;
@@ -17130,12 +17126,6 @@ function replaceEntityPattern (match, name) {
17130
17126
  return match
17131
17127
  }
17132
17128
 
17133
- /* function replaceEntities(str) {
17134
- if (str.indexOf('&') < 0) { return str; }
17135
-
17136
- return str.replace(ENTITY_RE, replaceEntityPattern);
17137
- } */
17138
-
17139
17129
  function unescapeMd (str) {
17140
17130
  if (str.indexOf('\\') < 0) { return str }
17141
17131
  return str.replace(UNESCAPE_MD_RE, '$1')
@@ -17205,13 +17195,15 @@ function isWhiteSpace (code) {
17205
17195
  return false
17206
17196
  }
17207
17197
 
17208
- /* eslint-disable max-len */
17209
-
17210
17198
  // Currently without astral characters support.
17211
17199
  function isPunctChar (ch) {
17212
17200
  return P.test(ch) || regex.test(ch)
17213
17201
  }
17214
17202
 
17203
+ function isPunctCharCode (code) {
17204
+ return isPunctChar(fromCodePoint(code))
17205
+ }
17206
+
17215
17207
  // Markdown ASCII punctuation characters.
17216
17208
  //
17217
17209
  // !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
@@ -17273,6 +17265,7 @@ function normalizeReference (str) {
17273
17265
  // (remove this when node v10 is no longer supported).
17274
17266
  //
17275
17267
  if ('ẞ'.toLowerCase() === 'Ṿ') {
17268
+ /* c8 ignore next 2 */
17276
17269
  str = str.replace(/ẞ/g, 'ß');
17277
17270
  }
17278
17271
 
@@ -17311,6 +17304,28 @@ function normalizeReference (str) {
17311
17304
  return str.toLowerCase().toUpperCase()
17312
17305
  }
17313
17306
 
17307
+ function isAsciiTrimmable (c) {
17308
+ return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d
17309
+ }
17310
+
17311
+ // "Light" .trim() for blocks (headers, paragraphs), where unicode spaces
17312
+ // should be preserved.
17313
+ function asciiTrim (str) {
17314
+ let start = 0;
17315
+ for (; start < str.length; start++) {
17316
+ if (!isAsciiTrimmable(str.charCodeAt(start))) {
17317
+ break
17318
+ }
17319
+ }
17320
+ let end = str.length - 1;
17321
+ for (; end >= start; end--) {
17322
+ if (!isAsciiTrimmable(str.charCodeAt(end))) {
17323
+ break
17324
+ }
17325
+ }
17326
+ return str.slice(start, end + 1)
17327
+ }
17328
+
17314
17329
  // Re-export libraries commonly used in both markdown-it and its plugins,
17315
17330
  // so plugins won't have to depend on them explicitly, which reduces their
17316
17331
  // bundled size (e.g. a browser build).
@@ -17333,8 +17348,10 @@ var utils = /*#__PURE__*/Object.freeze({
17333
17348
  isWhiteSpace: isWhiteSpace,
17334
17349
  isMdAsciiPunct: isMdAsciiPunct,
17335
17350
  isPunctChar: isPunctChar,
17351
+ isPunctCharCode: isPunctCharCode,
17336
17352
  escapeRE: escapeRE$1,
17337
- normalizeReference: normalizeReference
17353
+ normalizeReference: normalizeReference,
17354
+ asciiTrim: asciiTrim
17338
17355
  });
17339
17356
 
17340
17357
  // Parse link label
@@ -17435,7 +17452,7 @@ function parseLinkDestination (str, start, max) {
17435
17452
  if (code < 0x20 || code === 0x7F) { break }
17436
17453
 
17437
17454
  if (code === 0x5C /* \ */ && pos + 1 < max) {
17438
- if (str.charCodeAt(pos + 1) === 0x20) { break }
17455
+ if (str.charCodeAt(pos + 1) === 0x20) { pos++; continue }
17439
17456
  pos += 2;
17440
17457
  continue
17441
17458
  }
@@ -17548,7 +17565,7 @@ const default_rules = {};
17548
17565
  default_rules.code_inline = function (tokens, idx, options, env, slf) {
17549
17566
  const token = tokens[idx];
17550
17567
 
17551
- return '<code' + slf.renderAttrs(token) + '>' +
17568
+ return '<code' + slf.renderAttrs(token) + '>' +
17552
17569
  escapeHtml(token.content) +
17553
17570
  '</code>'
17554
17571
  };
@@ -17556,7 +17573,7 @@ default_rules.code_inline = function (tokens, idx, options, env, slf) {
17556
17573
  default_rules.code_block = function (tokens, idx, options, env, slf) {
17557
17574
  const token = tokens[idx];
17558
17575
 
17559
- return '<pre' + slf.renderAttrs(token) + '><code>' +
17576
+ return '<pre' + slf.renderAttrs(token) + '><code>' +
17560
17577
  escapeHtml(tokens[idx].content) +
17561
17578
  '</code></pre>\n'
17562
17579
  };
@@ -18209,28 +18226,28 @@ function Token (type, tag, nesting) {
18209
18226
  *
18210
18227
  * Type of the token (string, e.g. "paragraph_open")
18211
18228
  **/
18212
- this.type = type;
18229
+ this.type = type;
18213
18230
 
18214
18231
  /**
18215
18232
  * Token#tag -> String
18216
18233
  *
18217
18234
  * html tag name, e.g. "p"
18218
18235
  **/
18219
- this.tag = tag;
18236
+ this.tag = tag;
18220
18237
 
18221
18238
  /**
18222
18239
  * Token#attrs -> Array
18223
18240
  *
18224
18241
  * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
18225
18242
  **/
18226
- this.attrs = null;
18243
+ this.attrs = null;
18227
18244
 
18228
18245
  /**
18229
18246
  * Token#map -> Array
18230
18247
  *
18231
18248
  * Source map info. Format: `[ line_begin, line_end ]`
18232
18249
  **/
18233
- this.map = null;
18250
+ this.map = null;
18234
18251
 
18235
18252
  /**
18236
18253
  * Token#nesting -> Number
@@ -18241,14 +18258,14 @@ function Token (type, tag, nesting) {
18241
18258
  * - `0` means the tag is self-closing
18242
18259
  * - `-1` means the tag is closing
18243
18260
  **/
18244
- this.nesting = nesting;
18261
+ this.nesting = nesting;
18245
18262
 
18246
18263
  /**
18247
18264
  * Token#level -> Number
18248
18265
  *
18249
18266
  * nesting level, the same as `state.level`
18250
18267
  **/
18251
- this.level = 0;
18268
+ this.level = 0;
18252
18269
 
18253
18270
  /**
18254
18271
  * Token#children -> Array
@@ -18263,14 +18280,14 @@ function Token (type, tag, nesting) {
18263
18280
  * In a case of self-closing tag (code, html, fence, etc.),
18264
18281
  * it has contents of this tag.
18265
18282
  **/
18266
- this.content = '';
18283
+ this.content = '';
18267
18284
 
18268
18285
  /**
18269
18286
  * Token#markup -> String
18270
18287
  *
18271
18288
  * '*' or '_' for emphasis, fence string for fence, etc.
18272
18289
  **/
18273
- this.markup = '';
18290
+ this.markup = '';
18274
18291
 
18275
18292
  /**
18276
18293
  * Token#info -> String
@@ -18281,14 +18298,14 @@ function Token (type, tag, nesting) {
18281
18298
  * - The value "auto" for autolink "link_open" and "link_close" tokens
18282
18299
  * - The string value of the item marker for ordered-list "list_item_open" tokens
18283
18300
  **/
18284
- this.info = '';
18301
+ this.info = '';
18285
18302
 
18286
18303
  /**
18287
18304
  * Token#meta -> Object
18288
18305
  *
18289
18306
  * A place for plugins to store an arbitrary data
18290
18307
  **/
18291
- this.meta = null;
18308
+ this.meta = null;
18292
18309
 
18293
18310
  /**
18294
18311
  * Token#block -> Boolean
@@ -18296,7 +18313,7 @@ function Token (type, tag, nesting) {
18296
18313
  * True for block-level tokens, false for inline tokens.
18297
18314
  * Used in renderer to calculate line breaks
18298
18315
  **/
18299
- this.block = false;
18316
+ this.block = false;
18300
18317
 
18301
18318
  /**
18302
18319
  * Token#hidden -> Boolean
@@ -18304,7 +18321,7 @@ function Token (type, tag, nesting) {
18304
18321
  * If it's true, ignore this element when rendering. Used for tight lists
18305
18322
  * to hide paragraphs.
18306
18323
  **/
18307
- this.hidden = false;
18324
+ this.hidden = false;
18308
18325
  }
18309
18326
 
18310
18327
  /**
@@ -18398,8 +18415,8 @@ StateCore.prototype.Token = Token;
18398
18415
  // Normalize input string
18399
18416
 
18400
18417
  // https://spec.commonmark.org/0.29/#line-ending
18401
- const NEWLINES_RE = /\r\n?|\n/g;
18402
- const NULL_RE = /\0/g;
18418
+ const NEWLINES_RE = /\r\n?|\n/g;
18419
+ const NULL_RE = /\0/g;
18403
18420
 
18404
18421
  function normalize (state) {
18405
18422
  let str;
@@ -18417,9 +18434,9 @@ function block (state) {
18417
18434
  let token;
18418
18435
 
18419
18436
  if (state.inlineMode) {
18420
- token = new state.Token('inline', '', 0);
18421
- token.content = state.src;
18422
- token.map = [0, 1];
18437
+ token = new state.Token('inline', '', 0);
18438
+ token.content = state.src;
18439
+ token.map = [0, 1];
18423
18440
  token.children = [];
18424
18441
  state.tokens.push(token);
18425
18442
  } else {
@@ -18440,6 +18457,9 @@ function inline (state) {
18440
18457
  }
18441
18458
 
18442
18459
  // Replace link-like texts with link nodes.
18460
+ //
18461
+ // Currently restricted by `md.validateLink()` to http/https/ftp
18462
+ //
18443
18463
 
18444
18464
  function isLinkOpen$1 (str) {
18445
18465
  return /^<a[>\s]/i.test(str)
@@ -18459,7 +18479,8 @@ function linkify$1 (state) {
18459
18479
  continue
18460
18480
  }
18461
18481
 
18462
- let tokens = blockTokens[j].children;
18482
+ const tokens = blockTokens[j].children;
18483
+ const replacements = [];
18463
18484
 
18464
18485
  let htmlLinkLevel = 0;
18465
18486
 
@@ -18529,43 +18550,70 @@ function linkify$1 (state) {
18529
18550
  const pos = links[ln].index;
18530
18551
 
18531
18552
  if (pos > lastPos) {
18532
- const token = new state.Token('text', '', 0);
18553
+ const token = new state.Token('text', '', 0);
18533
18554
  token.content = text.slice(lastPos, pos);
18534
- token.level = level;
18555
+ token.level = level;
18535
18556
  nodes.push(token);
18536
18557
  }
18537
18558
 
18538
- const token_o = new state.Token('link_open', 'a', 1);
18539
- token_o.attrs = [['href', fullUrl]];
18540
- token_o.level = level++;
18541
- token_o.markup = 'linkify';
18542
- token_o.info = 'auto';
18559
+ const token_o = new state.Token('link_open', 'a', 1);
18560
+ token_o.attrs = [['href', fullUrl]];
18561
+ token_o.level = level++;
18562
+ token_o.markup = 'linkify';
18563
+ token_o.info = 'auto';
18543
18564
  nodes.push(token_o);
18544
18565
 
18545
- const token_t = new state.Token('text', '', 0);
18566
+ const token_t = new state.Token('text', '', 0);
18546
18567
  token_t.content = urlText;
18547
- token_t.level = level;
18568
+ token_t.level = level;
18548
18569
  nodes.push(token_t);
18549
18570
 
18550
- const token_c = new state.Token('link_close', 'a', -1);
18551
- token_c.level = --level;
18552
- token_c.markup = 'linkify';
18553
- token_c.info = 'auto';
18571
+ const token_c = new state.Token('link_close', 'a', -1);
18572
+ token_c.level = --level;
18573
+ token_c.markup = 'linkify';
18574
+ token_c.info = 'auto';
18554
18575
  nodes.push(token_c);
18555
18576
 
18556
18577
  lastPos = links[ln].lastIndex;
18557
18578
  }
18558
18579
  if (lastPos < text.length) {
18559
- const token = new state.Token('text', '', 0);
18580
+ const token = new state.Token('text', '', 0);
18560
18581
  token.content = text.slice(lastPos);
18561
- token.level = level;
18582
+ token.level = level;
18562
18583
  nodes.push(token);
18563
18584
  }
18564
18585
 
18565
- // replace current node
18566
- blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
18586
+ replacements.push({ index: i, nodes });
18567
18587
  }
18568
18588
  }
18589
+
18590
+ if (replacements.length > 0) {
18591
+ let newTokensLength = tokens.length;
18592
+ for (const replacement of replacements) {
18593
+ newTokensLength += replacement.nodes.length - 1;
18594
+ }
18595
+
18596
+ const newTokens = new Array(newTokensLength);
18597
+ let replacementIndex = 0;
18598
+ let newTokenIndex = 0;
18599
+
18600
+ replacements.reverse();
18601
+
18602
+ for (let i = 0; i < tokens.length; i++) {
18603
+ const replacement = replacements[replacementIndex];
18604
+
18605
+ if (replacement?.index === i) {
18606
+ for (const node of replacement.nodes) {
18607
+ newTokens[newTokenIndex++] = node;
18608
+ }
18609
+ replacementIndex++;
18610
+ } else {
18611
+ newTokens[newTokenIndex++] = tokens[i];
18612
+ }
18613
+ }
18614
+
18615
+ blockTokens[j].children = newTokens;
18616
+ }
18569
18617
  }
18570
18618
  }
18571
18619
 
@@ -18676,15 +18724,52 @@ function replace (state) {
18676
18724
  const QUOTE_TEST_RE = /['"]/;
18677
18725
  const QUOTE_RE = /['"]/g;
18678
18726
  const APOSTROPHE = '\u2019'; /* ’ */
18727
+ // Caps memory on malicious input
18728
+ const MAX_OPENERS = 1000;
18729
+
18730
+ function truncateStack (stack, heads, length) {
18731
+ while (stack.length > length) {
18732
+ const item = stack.pop();
18733
+ if (item.isSingleQuote) {
18734
+ heads.single = item.prevSameQuoteIdx;
18735
+ } else {
18736
+ heads.double = item.prevSameQuoteIdx;
18737
+ }
18738
+ }
18739
+ }
18740
+
18741
+ function addReplacement (replacements, tokenIdx, pos, ch) {
18742
+ if (!replacements[tokenIdx]) {
18743
+ replacements[tokenIdx] = [];
18744
+ }
18679
18745
 
18680
- function replaceAt (str, index, ch) {
18681
- return str.slice(0, index) + ch + str.slice(index + 1)
18746
+ replacements[tokenIdx].push({ pos, ch });
18747
+ }
18748
+
18749
+ function applyReplacements (str, replacements) {
18750
+ let result = '';
18751
+ let lastPos = 0;
18752
+
18753
+ replacements.sort((a, b) => a.pos - b.pos);
18754
+
18755
+ for (let i = 0; i < replacements.length; i++) {
18756
+ const replacement = replacements[i];
18757
+
18758
+ result += str.slice(lastPos, replacement.pos) + replacement.ch;
18759
+ lastPos = replacement.pos + 1;
18760
+ }
18761
+
18762
+ return result + str.slice(lastPos)
18682
18763
  }
18683
18764
 
18684
18765
  function process_inlines (tokens, state) {
18685
18766
  let j;
18686
18767
 
18687
18768
  const stack = [];
18769
+ // stack indexes of topmost openers of each type (-1 if none)
18770
+ const heads = { single: -1, double: -1 };
18771
+ // token index -> list of replacements in the original token content
18772
+ const replacements = {};
18688
18773
 
18689
18774
  for (let i = 0; i < tokens.length; i++) {
18690
18775
  const token = tokens[i];
@@ -18694,13 +18779,13 @@ function process_inlines (tokens, state) {
18694
18779
  for (j = stack.length - 1; j >= 0; j--) {
18695
18780
  if (stack[j].level <= thisLevel) { break }
18696
18781
  }
18697
- stack.length = j + 1;
18782
+ truncateStack(stack, heads, j + 1);
18698
18783
 
18699
18784
  if (token.type !== 'text') { continue }
18700
18785
 
18701
- let text = token.content;
18786
+ const text = token.content;
18702
18787
  let pos = 0;
18703
- let max = text.length;
18788
+ const max = text.length;
18704
18789
 
18705
18790
  /* eslint no-labels:0,block-scoped-var:0 */
18706
18791
  OUTER:
@@ -18748,8 +18833,8 @@ function process_inlines (tokens, state) {
18748
18833
  }
18749
18834
  }
18750
18835
 
18751
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
18752
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
18836
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
18837
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
18753
18838
 
18754
18839
  const isLastWhiteSpace = isWhiteSpace(lastChar);
18755
18840
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -18792,60 +18877,60 @@ function process_inlines (tokens, state) {
18792
18877
  if (!canOpen && !canClose) {
18793
18878
  // middle of word
18794
18879
  if (isSingle) {
18795
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
18880
+ addReplacement(replacements, i, t.index, APOSTROPHE);
18796
18881
  }
18797
18882
  continue
18798
18883
  }
18799
18884
 
18800
18885
  if (canClose) {
18801
- // this could be a closing quote, rewind the stack to get a match
18802
- for (j = stack.length - 1; j >= 0; j--) {
18803
- let item = stack[j];
18804
- if (stack[j].level < thisLevel) { break }
18805
- if (item.single === isSingle && stack[j].level === thisLevel) {
18806
- item = stack[j];
18807
-
18808
- let openQuote;
18809
- let closeQuote;
18810
- if (isSingle) {
18811
- openQuote = state.md.options.quotes[2];
18812
- closeQuote = state.md.options.quotes[3];
18813
- } else {
18814
- openQuote = state.md.options.quotes[0];
18815
- closeQuote = state.md.options.quotes[1];
18816
- }
18817
-
18818
- // replace token.content *before* tokens[item.token].content,
18819
- // because, if they are pointing at the same token, replaceAt
18820
- // could mess up indices when quote length != 1
18821
- token.content = replaceAt(token.content, t.index, closeQuote);
18822
- tokens[item.token].content = replaceAt(
18823
- tokens[item.token].content, item.pos, openQuote);
18824
-
18825
- pos += closeQuote.length - 1;
18826
- if (item.token === i) { pos += openQuote.length - 1; }
18886
+ // Stack levels never decrease, so an opener of this type below
18887
+ // the current level means there is no match
18888
+ j = isSingle ? heads.single : heads.double;
18889
+ if (j >= 0 && stack[j].level === thisLevel) {
18890
+ const item = stack[j];
18891
+
18892
+ let openQuote;
18893
+ let closeQuote;
18894
+ if (isSingle) {
18895
+ openQuote = state.md.options.quotes[2];
18896
+ closeQuote = state.md.options.quotes[3];
18897
+ } else {
18898
+ openQuote = state.md.options.quotes[0];
18899
+ closeQuote = state.md.options.quotes[1];
18900
+ }
18827
18901
 
18828
- text = token.content;
18829
- max = text.length;
18902
+ addReplacement(replacements, i, t.index, closeQuote);
18903
+ addReplacement(replacements, item.tokenIdx, item.contentPos, openQuote);
18830
18904
 
18831
- stack.length = j;
18832
- continue OUTER
18833
- }
18905
+ truncateStack(stack, heads, j);
18906
+ continue OUTER
18834
18907
  }
18835
18908
  }
18836
18909
 
18837
18910
  if (canOpen) {
18911
+ if (stack.length >= MAX_OPENERS) { return }
18838
18912
  stack.push({
18839
- token: i,
18840
- pos: t.index,
18841
- single: isSingle,
18842
- level: thisLevel
18913
+ tokenIdx: i,
18914
+ contentPos: t.index,
18915
+ isSingleQuote: isSingle,
18916
+ level: thisLevel,
18917
+ // stack index of the previous opener of the same quote type, -1 if none
18918
+ prevSameQuoteIdx: isSingle ? heads.single : heads.double
18843
18919
  });
18920
+ if (isSingle) {
18921
+ heads.single = stack.length - 1;
18922
+ } else {
18923
+ heads.double = stack.length - 1;
18924
+ }
18844
18925
  } else if (canClose && isSingle) {
18845
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
18926
+ addReplacement(replacements, i, t.index, APOSTROPHE);
18846
18927
  }
18847
18928
  }
18848
18929
  }
18930
+
18931
+ Object.keys(replacements).forEach(function (tokenIdx) {
18932
+ tokens[tokenIdx].content = applyReplacements(tokens[tokenIdx].content, replacements[tokenIdx]);
18933
+ });
18849
18934
  }
18850
18935
 
18851
18936
  function smartquotes (state) {
@@ -18914,15 +18999,15 @@ function text_join (state) {
18914
18999
  **/
18915
19000
 
18916
19001
  const _rules$2 = [
18917
- ['normalize', normalize],
18918
- ['block', block],
18919
- ['inline', inline],
18920
- ['linkify', linkify$1],
18921
- ['replacements', replace],
18922
- ['smartquotes', smartquotes],
19002
+ ['normalize', normalize],
19003
+ ['block', block],
19004
+ ['inline', inline],
19005
+ ['linkify', linkify$1],
19006
+ ['replacements', replace],
19007
+ ['smartquotes', smartquotes],
18923
19008
  // `text_join` finds `text_special` tokens (for escape sequences)
18924
19009
  // and joins them with the rest of the text
18925
- ['text_join', text_join]
19010
+ ['text_join', text_join]
18926
19011
  ];
18927
19012
 
18928
19013
  /**
@@ -18962,7 +19047,7 @@ function StateBlock (src, md, env, tokens) {
18962
19047
  this.src = src;
18963
19048
 
18964
19049
  // link to parser instance
18965
- this.md = md;
19050
+ this.md = md;
18966
19051
 
18967
19052
  this.env = env;
18968
19053
 
@@ -18993,11 +19078,11 @@ function StateBlock (src, md, env, tokens) {
18993
19078
 
18994
19079
  // required block content indent (for example, if we are
18995
19080
  // inside a list, it would be positioned after list marker)
18996
- this.blkIndent = 0;
18997
- this.line = 0; // line index in src
18998
- this.lineMax = 0; // lines count
18999
- this.tight = false; // loose/tight mode for lists
19000
- this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
19081
+ this.blkIndent = 0;
19082
+ this.line = 0; // line index in src
19083
+ this.lineMax = 0; // lines count
19084
+ this.tight = false; // loose/tight mode for lists
19085
+ this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
19001
19086
  this.listIndent = -1; // indent of the current list block (-1 if there isn't any)
19002
19087
 
19003
19088
  // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'
@@ -19323,11 +19408,11 @@ function table (state, startLine, endLine, silent) {
19323
19408
  for (let i = 0; i < columns.length; i++) {
19324
19409
  const token_ho = state.push('th_open', 'th', 1);
19325
19410
  if (aligns[i]) {
19326
- token_ho.attrs = [['style', 'text-align:' + aligns[i]]];
19411
+ token_ho.attrs = [['style', 'text-align:' + aligns[i]]];
19327
19412
  }
19328
19413
 
19329
19414
  const token_il = state.push('inline', '', 0);
19330
- token_il.content = columns[i].trim();
19415
+ token_il.content = columns[i].trim();
19331
19416
  token_il.children = [];
19332
19417
 
19333
19418
  state.push('th_close', 'th', -1);
@@ -19374,11 +19459,11 @@ function table (state, startLine, endLine, silent) {
19374
19459
  for (let i = 0; i < columnCount; i++) {
19375
19460
  const token_tdo = state.push('td_open', 'td', 1);
19376
19461
  if (aligns[i]) {
19377
- token_tdo.attrs = [['style', 'text-align:' + aligns[i]]];
19462
+ token_tdo.attrs = [['style', 'text-align:' + aligns[i]]];
19378
19463
  }
19379
19464
 
19380
19465
  const token_il = state.push('inline', '', 0);
19381
- token_il.content = columns[i] ? columns[i].trim() : '';
19466
+ token_il.content = columns[i] ? columns[i].trim() : '';
19382
19467
  token_il.children = [];
19383
19468
 
19384
19469
  state.push('td_close', 'td', -1);
@@ -19423,9 +19508,9 @@ function code (state, startLine, endLine/*, silent */) {
19423
19508
 
19424
19509
  state.line = last;
19425
19510
 
19426
- const token = state.push('code_block', 'code', 0);
19511
+ const token = state.push('code_block', 'code', 0);
19427
19512
  token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n';
19428
- token.map = [startLine, state.line];
19513
+ token.map = [startLine, state.line];
19429
19514
 
19430
19515
  return true
19431
19516
  }
@@ -19516,11 +19601,11 @@ function fence (state, startLine, endLine, silent) {
19516
19601
 
19517
19602
  state.line = nextLine + (haveEndMarker ? 1 : 0);
19518
19603
 
19519
- const token = state.push('fence', 'code', 0);
19520
- token.info = params;
19604
+ const token = state.push('fence', 'code', 0);
19605
+ token.info = params;
19521
19606
  token.content = state.getLines(startLine + 1, nextLine, len, true);
19522
- token.markup = markup;
19523
- token.map = [startLine, state.line];
19607
+ token.markup = markup;
19608
+ token.map = [startLine, state.line];
19524
19609
 
19525
19610
  return true
19526
19611
  }
@@ -19543,10 +19628,10 @@ function blockquote (state, startLine, endLine, silent) {
19543
19628
  // so no point trying to find the end of it in silent mode
19544
19629
  if (silent) { return true }
19545
19630
 
19546
- const oldBMarks = [];
19631
+ const oldBMarks = [];
19547
19632
  const oldBSCount = [];
19548
- const oldSCount = [];
19549
- const oldTShift = [];
19633
+ const oldSCount = [];
19634
+ const oldTShift = [];
19550
19635
 
19551
19636
  const terminatorRules = state.md.block.ruler.getRules('blockquote');
19552
19637
 
@@ -19706,14 +19791,14 @@ function blockquote (state, startLine, endLine, silent) {
19706
19791
  const oldIndent = state.blkIndent;
19707
19792
  state.blkIndent = 0;
19708
19793
 
19709
- const token_o = state.push('blockquote_open', 'blockquote', 1);
19794
+ const token_o = state.push('blockquote_open', 'blockquote', 1);
19710
19795
  token_o.markup = '>';
19711
19796
  const lines = [startLine, 0];
19712
- token_o.map = lines;
19797
+ token_o.map = lines;
19713
19798
 
19714
19799
  state.md.block.tokenize(state, startLine, nextLine);
19715
19800
 
19716
- const token_c = state.push('blockquote_close', 'blockquote', -1);
19801
+ const token_c = state.push('blockquote_close', 'blockquote', -1);
19717
19802
  token_c.markup = '>';
19718
19803
 
19719
19804
  state.lineMax = oldLineMax;
@@ -19765,8 +19850,8 @@ function hr (state, startLine, endLine, silent) {
19765
19850
 
19766
19851
  state.line = startLine + 1;
19767
19852
 
19768
- const token = state.push('hr', 'hr', 0);
19769
- token.map = [startLine, state.line];
19853
+ const token = state.push('hr', 'hr', 0);
19854
+ token.map = [startLine, state.line];
19770
19855
  token.markup = Array(cnt + 1).join(String.fromCharCode(marker));
19771
19856
 
19772
19857
  return true
@@ -19928,16 +20013,16 @@ function list (state, startLine, endLine, silent) {
19928
20013
  const listTokIdx = state.tokens.length;
19929
20014
 
19930
20015
  if (isOrdered) {
19931
- token = state.push('ordered_list_open', 'ol', 1);
20016
+ token = state.push('ordered_list_open', 'ol', 1);
19932
20017
  if (markerValue !== 1) {
19933
20018
  token.attrs = [['start', markerValue]];
19934
20019
  }
19935
20020
  } else {
19936
- token = state.push('bullet_list_open', 'ul', 1);
20021
+ token = state.push('bullet_list_open', 'ul', 1);
19937
20022
  }
19938
20023
 
19939
20024
  const listLines = [nextLine, 0];
19940
- token.map = listLines;
20025
+ token.map = listLines;
19941
20026
  token.markup = String.fromCharCode(markerCharCode);
19942
20027
 
19943
20028
  //
@@ -19990,10 +20075,10 @@ function list (state, startLine, endLine, silent) {
19990
20075
  const indent = initial + indentAfterMarker;
19991
20076
 
19992
20077
  // Run subparser & write tokens
19993
- token = state.push('list_item_open', 'li', 1);
20078
+ token = state.push('list_item_open', 'li', 1);
19994
20079
  token.markup = String.fromCharCode(markerCharCode);
19995
20080
  const itemLines = [nextLine, 0];
19996
- token.map = itemLines;
20081
+ token.map = itemLines;
19997
20082
  if (isOrdered) {
19998
20083
  token.info = state.src.slice(start, posAfterMarker - 1);
19999
20084
  }
@@ -20042,7 +20127,7 @@ function list (state, startLine, endLine, silent) {
20042
20127
  state.sCount[nextLine] = oldSCount;
20043
20128
  state.tight = oldTight;
20044
20129
 
20045
- token = state.push('list_item_close', 'li', -1);
20130
+ token = state.push('list_item_close', 'li', -1);
20046
20131
  token.markup = String.fromCharCode(markerCharCode);
20047
20132
 
20048
20133
  nextLine = state.line;
@@ -20102,114 +20187,141 @@ function list (state, startLine, endLine, silent) {
20102
20187
  return true
20103
20188
  }
20104
20189
 
20105
- function reference (state, startLine, _endLine, silent) {
20106
- let pos = state.bMarks[startLine] + state.tShift[startLine];
20107
- let max = state.eMarks[startLine];
20108
- let nextLine = startLine + 1;
20109
-
20110
- // if it's indented more than 3 spaces, it should be a code block
20111
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20190
+ // CommonMark limits reference labels to 999 Unicode code points.
20191
+ const MAX_LABEL_LENGTH = 999;
20112
20192
 
20113
- if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false }
20193
+ function countCodePoints (str) {
20194
+ let length = str.length;
20114
20195
 
20115
- function getNextLine (nextLine) {
20116
- const endLine = state.lineMax;
20196
+ for (let i = 0; i < str.length - 1; i++) {
20197
+ const high = str.charCodeAt(i);
20198
+ if (high < 0xD800 || high > 0xDBFF) { continue }
20117
20199
 
20118
- if (nextLine >= endLine || state.isEmpty(nextLine)) {
20119
- // empty line or end of input
20120
- return null
20200
+ const low = str.charCodeAt(i + 1);
20201
+ if (low >= 0xDC00 && low <= 0xDFFF) {
20202
+ length--;
20203
+ i++;
20121
20204
  }
20205
+ }
20122
20206
 
20123
- let isContinuation = false;
20207
+ return length
20208
+ }
20124
20209
 
20125
- // this would be a code block normally, but after paragraph
20126
- // it's considered a lazy continuation regardless of what's there
20127
- if (state.sCount[nextLine] - state.blkIndent > 3) { isContinuation = true; }
20210
+ // Exclusive end offset of the line, after its newline if present
20211
+ function lineEnd (state, line) {
20212
+ return Math.min(state.eMarks[line] + 1, state.src.length)
20213
+ }
20128
20214
 
20129
- // quirk for blockquotes, this line should already be checked by that rule
20130
- if (state.sCount[nextLine] < 0) { isContinuation = true; }
20131
-
20132
- if (!isContinuation) {
20133
- const terminatorRules = state.md.block.ruler.getRules('reference');
20134
- const oldParentType = state.parentType;
20135
- state.parentType = 'reference';
20136
-
20137
- // Some tags can terminate paragraph without empty line.
20138
- let terminate = false;
20139
- for (let i = 0, l = terminatorRules.length; i < l; i++) {
20140
- if (terminatorRules[i](state, nextLine, endLine, true)) {
20141
- terminate = true;
20142
- break
20143
- }
20144
- }
20215
+ // Returns -1 if the reference can't continue on this line
20216
+ function getNextLinePos (state, nextLine) {
20217
+ const endLine = state.lineMax;
20218
+
20219
+ if (nextLine >= endLine || state.isEmpty(nextLine)) {
20220
+ // empty line or end of input
20221
+ return -1
20222
+ }
20223
+
20224
+ let isContinuation = false;
20145
20225
 
20146
- state.parentType = oldParentType;
20147
- if (terminate) {
20148
- // terminated by another block
20149
- return null
20226
+ // this would be a code block normally, but after paragraph
20227
+ // it's considered a lazy continuation regardless of what's there
20228
+ if (state.sCount[nextLine] - state.blkIndent > 3) { isContinuation = true; }
20229
+
20230
+ // quirk for blockquotes, this line should already be checked by that rule
20231
+ if (state.sCount[nextLine] < 0) { isContinuation = true; }
20232
+
20233
+ if (!isContinuation) {
20234
+ const terminatorRules = state.md.block.ruler.getRules('reference');
20235
+ const oldParentType = state.parentType;
20236
+ state.parentType = 'reference';
20237
+
20238
+ // Some tags can terminate paragraph without empty line.
20239
+ let terminate = false;
20240
+ for (let i = 0, l = terminatorRules.length; i < l; i++) {
20241
+ if (terminatorRules[i](state, nextLine, endLine, true)) {
20242
+ terminate = true;
20243
+ break
20150
20244
  }
20151
20245
  }
20152
20246
 
20153
- const pos = state.bMarks[nextLine] + state.tShift[nextLine];
20154
- const max = state.eMarks[nextLine];
20155
-
20156
- // max + 1 explicitly includes the newline
20157
- return state.src.slice(pos, max + 1)
20247
+ state.parentType = oldParentType;
20248
+ if (terminate) {
20249
+ // terminated by another block
20250
+ return -1
20251
+ }
20158
20252
  }
20159
20253
 
20160
- let str = state.src.slice(pos, max + 1);
20254
+ return state.bMarks[nextLine] + state.tShift[nextLine]
20255
+ }
20256
+
20257
+ function reference (state, startLine, _endLine, silent) {
20258
+ const src = state.src;
20259
+ let pos = state.bMarks[startLine] + state.tShift[startLine];
20260
+ let nextLine = startLine + 1;
20161
20261
 
20162
- max = str.length;
20262
+ // if it's indented more than 3 spaces, it should be a code block
20263
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20264
+
20265
+ if (src.charCodeAt(pos) !== 0x5B/* [ */) { return false }
20266
+
20267
+ // Scan the source directly: indexing a string after each appended line
20268
+ // can make V8 copy the accumulated prefix on every continuation.
20269
+ let max = lineEnd(state, startLine);
20270
+
20271
+ let rawLabel = '';
20163
20272
  let labelEnd = -1;
20273
+ let segmentStart = ++pos;
20164
20274
 
20165
- for (pos = 1; pos < max; pos++) {
20166
- const ch = str.charCodeAt(pos);
20167
- if (ch === 0x5B /* [ */) {
20168
- return false
20169
- } else if (ch === 0x5D /* ] */) {
20275
+ while (pos < max) {
20276
+ if (rawLabel.length + pos - segmentStart > MAX_LABEL_LENGTH * 2) { return false }
20277
+
20278
+ let ch = src.charCodeAt(pos);
20279
+ if (ch === 0x5B /* [ */) { return false }
20280
+ if (ch === 0x5D /* ] */) {
20170
20281
  labelEnd = pos;
20171
20282
  break
20172
- } else if (ch === 0x0A /* \n */) {
20173
- const lineContent = getNextLine(nextLine);
20174
- if (lineContent !== null) {
20175
- str += lineContent;
20176
- max = str.length;
20177
- nextLine++;
20178
- }
20179
- } else if (ch === 0x5C /* \ */) {
20180
- pos++;
20181
- if (pos < max && str.charCodeAt(pos) === 0x0A) {
20182
- const lineContent = getNextLine(nextLine);
20183
- if (lineContent !== null) {
20184
- str += lineContent;
20185
- max = str.length;
20186
- nextLine++;
20187
- }
20188
- }
20189
20283
  }
20284
+ if (ch === 0x5C /* \ */) { ch = src.charCodeAt(++pos); }
20285
+
20286
+ if (ch === 0x0A /* \n */ && pos < max) {
20287
+ const nextPos = getNextLinePos(state, nextLine);
20288
+ if (nextPos < 0) { return false }
20289
+ rawLabel += src.slice(segmentStart, max);
20290
+ pos = segmentStart = nextPos;
20291
+ max = lineEnd(state, nextLine++);
20292
+ continue
20293
+ }
20294
+ pos++;
20190
20295
  }
20191
20296
 
20192
- if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
20297
+ if (labelEnd < 0 || src.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
20298
+
20299
+ rawLabel += src.slice(segmentStart, labelEnd);
20300
+
20301
+ if (rawLabel.length > MAX_LABEL_LENGTH && countCodePoints(rawLabel) > MAX_LABEL_LENGTH) {
20302
+ return false
20303
+ }
20193
20304
 
20194
20305
  // [label]: destination 'title'
20195
20306
  // ^^^ skip optional whitespace here
20196
- for (pos = labelEnd + 2; pos < max; pos++) {
20197
- const ch = str.charCodeAt(pos);
20307
+ pos = labelEnd + 2;
20308
+ while (pos < max) {
20309
+ const ch = src.charCodeAt(pos);
20198
20310
  if (ch === 0x0A) {
20199
- const lineContent = getNextLine(nextLine);
20200
- if (lineContent !== null) {
20201
- str += lineContent;
20202
- max = str.length;
20203
- nextLine++;
20204
- }
20205
- } else if (isSpace(ch)) ; else {
20311
+ const nextPos = getNextLinePos(state, nextLine);
20312
+ if (nextPos < 0) { break }
20313
+ pos = nextPos;
20314
+ max = lineEnd(state, nextLine++);
20315
+ } else if (isSpace(ch)) {
20316
+ pos++;
20317
+ } else {
20206
20318
  break
20207
20319
  }
20208
20320
  }
20209
20321
 
20210
20322
  // [label]: destination 'title'
20211
20323
  // ^^^^^^^^^^^ parse this
20212
- const destRes = state.md.helpers.parseLinkDestination(str, pos, max);
20324
+ const destRes = state.md.helpers.parseLinkDestination(src, pos, max);
20213
20325
  if (!destRes.ok) { return false }
20214
20326
 
20215
20327
  const href = state.md.normalizeLink(destRes.str);
@@ -20219,76 +20331,77 @@ function reference (state, startLine, _endLine, silent) {
20219
20331
 
20220
20332
  // save cursor state, we could require to rollback later
20221
20333
  const destEndPos = pos;
20334
+ const destEndMax = max;
20222
20335
  const destEndLineNo = nextLine;
20223
20336
 
20224
20337
  // [label]: destination 'title'
20225
20338
  // ^^^ skipping those spaces
20226
- const start = pos;
20227
- for (; pos < max; pos++) {
20228
- const ch = str.charCodeAt(pos);
20339
+ while (pos < max) {
20340
+ const ch = src.charCodeAt(pos);
20229
20341
  if (ch === 0x0A) {
20230
- const lineContent = getNextLine(nextLine);
20231
- if (lineContent !== null) {
20232
- str += lineContent;
20233
- max = str.length;
20234
- nextLine++;
20235
- }
20236
- } else if (isSpace(ch)) ; else {
20342
+ const nextPos = getNextLinePos(state, nextLine);
20343
+ if (nextPos < 0) { break }
20344
+ pos = nextPos;
20345
+ max = lineEnd(state, nextLine++);
20346
+ } else if (isSpace(ch)) {
20347
+ pos++;
20348
+ } else {
20237
20349
  break
20238
20350
  }
20239
20351
  }
20240
20352
 
20241
20353
  // [label]: destination 'title'
20242
20354
  // ^^^^^^^ parse this
20243
- let titleRes = state.md.helpers.parseLinkTitle(str, pos, max);
20355
+ const titleStart = pos;
20356
+ let titleRes = state.md.helpers.parseLinkTitle(src, pos, max);
20244
20357
  while (titleRes.can_continue) {
20245
- const lineContent = getNextLine(nextLine);
20246
- if (lineContent === null) break
20247
- str += lineContent;
20248
- pos = max;
20249
- max = str.length;
20250
- nextLine++;
20251
- titleRes = state.md.helpers.parseLinkTitle(str, pos, max, titleRes);
20358
+ const nextPos = getNextLinePos(state, nextLine);
20359
+ if (nextPos < 0) break
20360
+ pos = nextPos;
20361
+ max = lineEnd(state, nextLine++);
20362
+ titleRes = state.md.helpers.parseLinkTitle(src, pos, max, titleRes);
20252
20363
  }
20253
20364
  let title;
20254
20365
 
20255
- if (pos < max && start !== pos && titleRes.ok) {
20366
+ if (titleStart !== destEndPos && titleRes.ok) {
20256
20367
  title = titleRes.str;
20257
20368
  pos = titleRes.pos;
20258
20369
  } else {
20259
20370
  title = '';
20260
20371
  pos = destEndPos;
20372
+ max = destEndMax;
20261
20373
  nextLine = destEndLineNo;
20262
20374
  }
20263
20375
 
20264
20376
  // skip trailing spaces until the rest of the line
20265
20377
  while (pos < max) {
20266
- const ch = str.charCodeAt(pos);
20378
+ const ch = src.charCodeAt(pos);
20267
20379
  if (!isSpace(ch)) { break }
20268
20380
  pos++;
20269
20381
  }
20270
20382
 
20271
- if (pos < max && str.charCodeAt(pos) !== 0x0A) {
20383
+ if (pos < max && src.charCodeAt(pos) !== 0x0A) {
20272
20384
  if (title) {
20273
20385
  // garbage at the end of the line after title,
20274
20386
  // but it could still be a valid reference if we roll back
20275
20387
  title = '';
20276
20388
  pos = destEndPos;
20389
+ max = destEndMax;
20277
20390
  nextLine = destEndLineNo;
20278
20391
  while (pos < max) {
20279
- const ch = str.charCodeAt(pos);
20392
+ const ch = src.charCodeAt(pos);
20280
20393
  if (!isSpace(ch)) { break }
20281
20394
  pos++;
20282
20395
  }
20283
20396
  }
20284
20397
  }
20285
20398
 
20286
- if (pos < max && str.charCodeAt(pos) !== 0x0A) {
20399
+ if (pos < max && src.charCodeAt(pos) !== 0x0A) {
20287
20400
  // garbage at the end of the line
20288
20401
  return false
20289
20402
  }
20290
20403
 
20291
- const label = normalizeReference(str.slice(1, labelEnd));
20404
+ const label = normalizeReference(rawLabel);
20292
20405
  if (!label) {
20293
20406
  // CommonMark 0.20 disallows empty labels
20294
20407
  return false
@@ -20379,26 +20492,19 @@ var block_names = [
20379
20492
 
20380
20493
  // Regexps to match html elements
20381
20494
 
20382
- const attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
20495
+ const attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
20383
20496
 
20384
- const unquoted = '[^"\'=<>`\\x00-\\x20]+';
20497
+ const unquoted = '[^"\'=<>`\\x00-\\x20]+';
20385
20498
  const single_quoted = "'[^']*'";
20386
20499
  const double_quoted = '"[^"]*"';
20387
20500
 
20388
- const attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
20389
-
20390
- const attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
20501
+ const attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
20391
20502
 
20392
- const open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
20503
+ const attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
20393
20504
 
20394
- const close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
20395
- const comment = '<!---?>|<!--(?:[^-]|-[^-]|--[^>])*-->';
20396
- const processing = '<[?][\\s\\S]*?[?]>';
20397
- const declaration = '<![A-Za-z][^>]*>';
20398
- const cdata = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>';
20505
+ const open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
20399
20506
 
20400
- const HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
20401
- '|' + processing + '|' + declaration + '|' + cdata + ')');
20507
+ const close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
20402
20508
  const HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');
20403
20509
 
20404
20510
  // HTML block
@@ -20408,12 +20514,12 @@ const HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag +
20408
20514
  //
20409
20515
  const HTML_SEQUENCES = [
20410
20516
  [/^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true],
20411
- [/^<!--/, /-->/, true],
20412
- [/^<\?/, /\?>/, true],
20413
- [/^<![A-Z]/, />/, true],
20517
+ [/^<!--/, /-->/, true],
20518
+ [/^<\?/, /\?>/, true],
20519
+ [/^<![A-Za-z]/, />/, true],
20414
20520
  [/^<!\[CDATA\[/, /\]\]>/, true],
20415
20521
  [new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
20416
- [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
20522
+ [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
20417
20523
  ];
20418
20524
 
20419
20525
  function html_block (state, startLine, endLine, silent) {
@@ -20442,11 +20548,22 @@ function html_block (state, startLine, endLine, silent) {
20442
20548
 
20443
20549
  let nextLine = startLine + 1;
20444
20550
 
20551
+ // Block types 6 and 7 (the only ones whose end condition is a blank line)
20552
+ // have `/^$/` as their closing regexp. For all other types (1-5, e.g.
20553
+ // `<!--` comments), a blank line is regular content and must not terminate
20554
+ // the block - it ends only when its closing sequence is found.
20555
+ const endsOnBlankLine = HTML_SEQUENCES[i][1].test('');
20556
+
20445
20557
  // If we are here - we detected HTML block.
20446
20558
  // Let's roll down till block end.
20447
20559
  if (!HTML_SEQUENCES[i][1].test(lineText)) {
20448
20560
  for (; nextLine < endLine; nextLine++) {
20449
- if (state.sCount[nextLine] < state.blkIndent) { break }
20561
+ if (state.sCount[nextLine] < state.blkIndent) {
20562
+ // An outdented blank line shouldn't end a block that doesn't end on a
20563
+ // blank line (e.g. a `<!--` comment inside a list item). Such blocks
20564
+ // must continue until their closing sequence regardless of indent.
20565
+ if (endsOnBlankLine || !state.isEmpty(nextLine)) { break }
20566
+ }
20450
20567
 
20451
20568
  pos = state.bMarks[nextLine] + state.tShift[nextLine];
20452
20569
  max = state.eMarks[nextLine];
@@ -20461,8 +20578,8 @@ function html_block (state, startLine, endLine, silent) {
20461
20578
 
20462
20579
  state.line = nextLine;
20463
20580
 
20464
- const token = state.push('html_block', '', 0);
20465
- token.map = [startLine, nextLine];
20581
+ const token = state.push('html_block', '', 0);
20582
+ token.map = [startLine, nextLine];
20466
20583
  token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
20467
20584
 
20468
20585
  return true
@@ -20477,7 +20594,7 @@ function heading (state, startLine, endLine, silent) {
20477
20594
  // if it's indented more than 3 spaces, it should be a code block
20478
20595
  if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
20479
20596
 
20480
- let ch = state.src.charCodeAt(pos);
20597
+ let ch = state.src.charCodeAt(pos);
20481
20598
 
20482
20599
  if (ch !== 0x23/* # */ || pos >= max) { return false }
20483
20600
 
@@ -20503,16 +20620,16 @@ function heading (state, startLine, endLine, silent) {
20503
20620
 
20504
20621
  state.line = startLine + 1;
20505
20622
 
20506
- const token_o = state.push('heading_open', 'h' + String(level), 1);
20623
+ const token_o = state.push('heading_open', 'h' + String(level), 1);
20507
20624
  token_o.markup = '########'.slice(0, level);
20508
- token_o.map = [startLine, state.line];
20625
+ token_o.map = [startLine, state.line];
20509
20626
 
20510
- const token_i = state.push('inline', '', 0);
20511
- token_i.content = state.src.slice(pos, max).trim();
20512
- token_i.map = [startLine, state.line];
20627
+ const token_i = state.push('inline', '', 0);
20628
+ token_i.content = asciiTrim(state.src.slice(pos, max));
20629
+ token_i.map = [startLine, state.line];
20513
20630
  token_i.children = [];
20514
20631
 
20515
- const token_c = state.push('heading_close', 'h' + String(level), -1);
20632
+ const token_c = state.push('heading_close', 'h' + String(level), -1);
20516
20633
  token_c.markup = '########'.slice(0, level);
20517
20634
 
20518
20635
  return true
@@ -20577,24 +20694,25 @@ function lheading (state, startLine, endLine/*, silent */) {
20577
20694
 
20578
20695
  if (!level) {
20579
20696
  // Didn't find valid underline
20697
+ state.parentType = oldParentType;
20580
20698
  return false
20581
20699
  }
20582
20700
 
20583
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
20701
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
20584
20702
 
20585
20703
  state.line = nextLine + 1;
20586
20704
 
20587
- const token_o = state.push('heading_open', 'h' + String(level), 1);
20588
- token_o.markup = String.fromCharCode(marker);
20589
- token_o.map = [startLine, state.line];
20705
+ const token_o = state.push('heading_open', 'h' + String(level), 1);
20706
+ token_o.markup = String.fromCharCode(marker);
20707
+ token_o.map = [startLine, state.line];
20590
20708
 
20591
- const token_i = state.push('inline', '', 0);
20592
- token_i.content = content;
20593
- token_i.map = [startLine, state.line - 1];
20709
+ const token_i = state.push('inline', '', 0);
20710
+ token_i.content = content;
20711
+ token_i.map = [startLine, state.line - 1];
20594
20712
  token_i.children = [];
20595
20713
 
20596
- const token_c = state.push('heading_close', 'h' + String(level), -1);
20597
- token_c.markup = String.fromCharCode(marker);
20714
+ const token_c = state.push('heading_close', 'h' + String(level), -1);
20715
+ token_c.markup = String.fromCharCode(marker);
20598
20716
 
20599
20717
  state.parentType = oldParentType;
20600
20718
 
@@ -20629,16 +20747,16 @@ function paragraph (state, startLine, endLine) {
20629
20747
  if (terminate) { break }
20630
20748
  }
20631
20749
 
20632
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
20750
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
20633
20751
 
20634
20752
  state.line = nextLine;
20635
20753
 
20636
- const token_o = state.push('paragraph_open', 'p', 1);
20637
- token_o.map = [startLine, state.line];
20754
+ const token_o = state.push('paragraph_open', 'p', 1);
20755
+ token_o.map = [startLine, state.line];
20638
20756
 
20639
- const token_i = state.push('inline', '', 0);
20640
- token_i.content = content;
20641
- token_i.map = [startLine, state.line];
20757
+ const token_i = state.push('inline', '', 0);
20758
+ token_i.content = content;
20759
+ token_i.map = [startLine, state.line];
20642
20760
  token_i.children = [];
20643
20761
 
20644
20762
  state.push('paragraph_close', 'p', -1);
@@ -20657,17 +20775,17 @@ function paragraph (state, startLine, endLine) {
20657
20775
  const _rules$1 = [
20658
20776
  // First 2 params - rule name & source. Secondary array - list of rules,
20659
20777
  // which can be terminated by this one.
20660
- ['table', table, ['paragraph', 'reference']],
20661
- ['code', code],
20662
- ['fence', fence, ['paragraph', 'reference', 'blockquote', 'list']],
20778
+ ['table', table, ['paragraph', 'reference']],
20779
+ ['code', code],
20780
+ ['fence', fence, ['paragraph', 'reference', 'blockquote', 'list']],
20663
20781
  ['blockquote', blockquote, ['paragraph', 'reference', 'blockquote', 'list']],
20664
- ['hr', hr, ['paragraph', 'reference', 'blockquote', 'list']],
20665
- ['list', list, ['paragraph', 'reference', 'blockquote']],
20666
- ['reference', reference],
20782
+ ['hr', hr, ['paragraph', 'reference', 'blockquote', 'list']],
20783
+ ['list', list, ['paragraph', 'reference', 'blockquote']],
20784
+ ['reference', reference],
20667
20785
  ['html_block', html_block, ['paragraph', 'reference', 'blockquote']],
20668
- ['heading', heading, ['paragraph', 'reference', 'blockquote']],
20669
- ['lheading', lheading],
20670
- ['paragraph', paragraph]
20786
+ ['heading', heading, ['paragraph', 'reference', 'blockquote']],
20787
+ ['lheading', lheading],
20788
+ ['paragraph', paragraph]
20671
20789
  ];
20672
20790
 
20673
20791
  /**
@@ -20795,6 +20913,10 @@ function StateInline (src, md, env, outTokens) {
20795
20913
  this.backticks = {};
20796
20914
  this.backticksScanned = false;
20797
20915
 
20916
+ // Set when html comment / PI / declaration / CDATA has no terminator,
20917
+ // to skip further scans of these constructs
20918
+ this.skipHtmlSpecial = false;
20919
+
20798
20920
  // Counter used to disable inline linkify-it execution
20799
20921
  // inside <a> and markdown links
20800
20922
  this.linkLevel = 0;
@@ -20854,8 +20976,30 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20854
20976
  const max = this.posMax;
20855
20977
  const marker = this.src.charCodeAt(start);
20856
20978
 
20857
- // treat beginning of the line as a whitespace
20858
- const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
20979
+ // Astral characters below are combined manually, because .codePointAt()
20980
+ // does not guarantee numeric type output. And we don't wish JIT cache issues.
20981
+ // The broken surrogate pairs are evaluated as U+FFFD to prevent possible
20982
+ // crashes.
20983
+
20984
+ let lastChar;
20985
+ if (start === 0) {
20986
+ // treat beginning of the line as a whitespace
20987
+ lastChar = 0x20;
20988
+ } else if (start === 1) {
20989
+ lastChar = this.src.charCodeAt(0);
20990
+ if ((lastChar & 0xF800) === 0xD800) { lastChar = 0xFFFD; }
20991
+ } else {
20992
+ lastChar = this.src.charCodeAt(start - 1);
20993
+ if ((lastChar & 0xFC00) === 0xDC00) {
20994
+ // low surrogate => add high one, replace broken pair with U+FFFD
20995
+ const highSurr = this.src.charCodeAt(start - 2);
20996
+ lastChar = (highSurr & 0xFC00) === 0xD800
20997
+ ? 0x10000 + ((highSurr - 0xD800) << 10) + (lastChar - 0xDC00)
20998
+ : 0xFFFD;
20999
+ } else if ((lastChar & 0xFC00) === 0xD800) {
21000
+ lastChar = 0xFFFD;
21001
+ }
21002
+ }
20859
21003
 
20860
21004
  let pos = start;
20861
21005
  while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
@@ -20863,10 +21007,19 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20863
21007
  const count = pos - start;
20864
21008
 
20865
21009
  // treat end of the line as a whitespace
20866
- const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
21010
+ let nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
21011
+ if ((nextChar & 0xFC00) === 0xD800) {
21012
+ // high surrogate => add low one, replace broken pair with U+FFFD
21013
+ const lowSurr = this.src.charCodeAt(pos + 1);
21014
+ nextChar = (lowSurr & 0xFC00) === 0xDC00
21015
+ ? 0x10000 + ((nextChar - 0xD800) << 10) + (lowSurr - 0xDC00)
21016
+ : 0xFFFD;
21017
+ } else if ((nextChar & 0xFC00) === 0xDC00) {
21018
+ nextChar = 0xFFFD;
21019
+ }
20867
21020
 
20868
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
20869
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
21021
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
21022
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
20870
21023
 
20871
21024
  const isLastWhiteSpace = isWhiteSpace(lastChar);
20872
21025
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -20876,8 +21029,8 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
20876
21029
  const right_flanking =
20877
21030
  !isLastWhiteSpace && (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar);
20878
21031
 
20879
- const can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar);
20880
- const can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar);
21032
+ const can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar);
21033
+ const can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar);
20881
21034
 
20882
21035
  return { can_open, can_close, length: count }
20883
21036
  };
@@ -20972,10 +21125,20 @@ module.exports = function text(state, silent) {
20972
21125
  return true;
20973
21126
  }; */
20974
21127
 
20975
- // Process links like https://example.org/
21128
+ // Early process links like https://example.org/ to have priority
21129
+ // over emphasis, etc.
20976
21130
 
20977
21131
  // RFC3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
20978
- const SCHEME_RE = /(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$/i;
21132
+ function isAsciiAlpha (code) {
21133
+ return (code >= 0x41 && code <= 0x5A) || (code >= 0x61 && code <= 0x7A)
21134
+ }
21135
+
21136
+ function isSchemeChar (code) {
21137
+ return (code >= 0x41 && code <= 0x5A) ||
21138
+ (code >= 0x61 && code <= 0x7A) ||
21139
+ (code >= 0x30 && code <= 0x39) ||
21140
+ code === 0x2B || code === 0x2D || code === 0x2E
21141
+ }
20979
21142
 
20980
21143
  function linkify (state, silent) {
20981
21144
  if (!state.md.options.linkify) return false
@@ -20989,19 +21152,27 @@ function linkify (state, silent) {
20989
21152
  if (state.src.charCodeAt(pos + 1) !== 0x2F/* / */) return false
20990
21153
  if (state.src.charCodeAt(pos + 2) !== 0x2F/* / */) return false
20991
21154
 
20992
- const match = state.pending.match(SCHEME_RE);
20993
- if (!match) return false
21155
+ // Search backwards for the scheme, but no more than 10 characters, the length
21156
+ // of the pending string, or the length of the source prefix.
21157
+ // Use state.src instead of state.pending because it is faster to access.
21158
+ const protoMin = pos - Math.min(10, state.pending.length, pos);
21159
+ let protoStart = pos;
21160
+ while (protoStart > protoMin && isSchemeChar(state.src.charCodeAt(protoStart - 1))) {
21161
+ protoStart--;
21162
+ }
21163
+
21164
+ if (protoStart === pos || !isAsciiAlpha(state.src.charCodeAt(protoStart))) return false
20994
21165
 
20995
- const proto = match[1];
21166
+ const protoLength = pos - protoStart;
20996
21167
 
20997
- const link = state.md.linkify.matchAtStart(state.src.slice(pos - proto.length));
21168
+ const link = state.md.linkify.matchAtStart(state.src.slice(protoStart));
20998
21169
  if (!link) return false
20999
21170
 
21000
21171
  let url = link.url;
21001
21172
 
21002
21173
  // invalid link, but still detected by linkify somehow;
21003
21174
  // need to check to prevent infinite loop below
21004
- if (url.length <= proto.length) return false
21175
+ if (url.length <= protoLength) return false
21005
21176
 
21006
21177
  // disallow '*' at the end of the link (conflicts with emphasis)
21007
21178
  // do manual backsearch to avoid perf issues with regex /\*+$/ on "****...****a".
@@ -21017,7 +21188,7 @@ function linkify (state, silent) {
21017
21188
  if (!state.md.validateLink(fullUrl)) return false
21018
21189
 
21019
21190
  if (!silent) {
21020
- state.pending = state.pending.slice(0, -proto.length);
21191
+ state.pending = state.pending.slice(0, -protoLength);
21021
21192
 
21022
21193
  const token_o = state.push('link_open', 'a', 1);
21023
21194
  token_o.attrs = [['href', fullUrl]];
@@ -21032,7 +21203,7 @@ function linkify (state, silent) {
21032
21203
  token_c.info = 'auto';
21033
21204
  }
21034
21205
 
21035
- state.pos += url.length - proto.length;
21206
+ state.pos += url.length - protoLength;
21036
21207
  return true
21037
21208
  }
21038
21209
 
@@ -21115,6 +21286,20 @@ function escape (state, silent) {
21115
21286
  return true
21116
21287
  }
21117
21288
 
21289
+ // '\' before a space is a literal backslash. Don't consume the space, so a
21290
+ // trailing two-space hard line break is still detected by the newline rule.
21291
+ if (ch1 === 0x20) {
21292
+ if (!silent) {
21293
+ const token = state.push('text_special', '', 0);
21294
+ token.content = '\\';
21295
+ token.markup = '\\';
21296
+ token.info = 'escape';
21297
+ }
21298
+
21299
+ state.pos = pos;
21300
+ return true
21301
+ }
21302
+
21118
21303
  let escapedStr = state.src[pos];
21119
21304
 
21120
21305
  if (ch1 >= 0xD800 && ch1 <= 0xDBFF && pos + 1 < max) {
@@ -21138,7 +21323,7 @@ function escape (state, silent) {
21138
21323
  }
21139
21324
 
21140
21325
  token.markup = origStr;
21141
- token.info = 'escape';
21326
+ token.info = 'escape';
21142
21327
  }
21143
21328
 
21144
21329
  state.pos = pos + 1;
@@ -21228,13 +21413,13 @@ function strikethrough_tokenize (state, silent) {
21228
21413
  let token;
21229
21414
 
21230
21415
  if (len % 2) {
21231
- token = state.push('text', '', 0);
21416
+ token = state.push('text', '', 0);
21232
21417
  token.content = ch;
21233
21418
  len--;
21234
21419
  }
21235
21420
 
21236
21421
  for (let i = 0; i < len; i += 2) {
21237
- token = state.push('text', '', 0);
21422
+ token = state.push('text', '', 0);
21238
21423
  token.content = ch + ch;
21239
21424
 
21240
21425
  state.delimiters.push({
@@ -21270,18 +21455,18 @@ function postProcess$1 (state, delimiters) {
21270
21455
 
21271
21456
  const endDelim = delimiters[startDelim.end];
21272
21457
 
21273
- token = state.tokens[startDelim.token];
21274
- token.type = 's_open';
21275
- token.tag = 's';
21458
+ token = state.tokens[startDelim.token];
21459
+ token.type = 's_open';
21460
+ token.tag = 's';
21276
21461
  token.nesting = 1;
21277
- token.markup = '~~';
21462
+ token.markup = '~~';
21278
21463
  token.content = '';
21279
21464
 
21280
- token = state.tokens[endDelim.token];
21281
- token.type = 's_close';
21282
- token.tag = 's';
21465
+ token = state.tokens[endDelim.token];
21466
+ token.type = 's_close';
21467
+ token.tag = 's';
21283
21468
  token.nesting = -1;
21284
- token.markup = '~~';
21469
+ token.markup = '~~';
21285
21470
  token.content = '';
21286
21471
 
21287
21472
  if (state.tokens[endDelim.token - 1].type === 'text' &&
@@ -21416,18 +21601,18 @@ function postProcess (state, delimiters) {
21416
21601
 
21417
21602
  const ch = String.fromCharCode(startDelim.marker);
21418
21603
 
21419
- const token_o = state.tokens[startDelim.token];
21420
- token_o.type = isStrong ? 'strong_open' : 'em_open';
21421
- token_o.tag = isStrong ? 'strong' : 'em';
21604
+ const token_o = state.tokens[startDelim.token];
21605
+ token_o.type = isStrong ? 'strong_open' : 'em_open';
21606
+ token_o.tag = isStrong ? 'strong' : 'em';
21422
21607
  token_o.nesting = 1;
21423
- token_o.markup = isStrong ? ch + ch : ch;
21608
+ token_o.markup = isStrong ? ch + ch : ch;
21424
21609
  token_o.content = '';
21425
21610
 
21426
- const token_c = state.tokens[endDelim.token];
21427
- token_c.type = isStrong ? 'strong_close' : 'em_close';
21428
- token_c.tag = isStrong ? 'strong' : 'em';
21611
+ const token_c = state.tokens[endDelim.token];
21612
+ token_c.type = isStrong ? 'strong_close' : 'em_close';
21613
+ token_c.tag = isStrong ? 'strong' : 'em';
21429
21614
  token_c.nesting = -1;
21430
- token_c.markup = isStrong ? ch + ch : ch;
21615
+ token_c.markup = isStrong ? ch + ch : ch;
21431
21616
  token_c.content = '';
21432
21617
 
21433
21618
  if (isStrong) {
@@ -21579,7 +21764,7 @@ function link (state, silent) {
21579
21764
 
21580
21765
  const token_o = state.push('link_open', 'a', 1);
21581
21766
  const attrs = [['href', href]];
21582
- token_o.attrs = attrs;
21767
+ token_o.attrs = attrs;
21583
21768
  if (title) {
21584
21769
  attrs.push(['title', title]);
21585
21770
  }
@@ -21736,7 +21921,7 @@ function image (state, silent) {
21736
21921
  // Process autolinks '<protocol:...>'
21737
21922
 
21738
21923
  /* eslint max-len:0 */
21739
- 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])?)*)$/;
21924
+ 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])?)*)$/;
21740
21925
  /* eslint-disable-next-line no-control-regex */
21741
21926
  const AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;
21742
21927
 
@@ -21764,17 +21949,17 @@ function autolink (state, silent) {
21764
21949
  if (!state.md.validateLink(fullUrl)) { return false }
21765
21950
 
21766
21951
  if (!silent) {
21767
- const token_o = state.push('link_open', 'a', 1);
21768
- token_o.attrs = [['href', fullUrl]];
21769
- token_o.markup = 'autolink';
21770
- token_o.info = 'auto';
21952
+ const token_o = state.push('link_open', 'a', 1);
21953
+ token_o.attrs = [['href', fullUrl]];
21954
+ token_o.markup = 'autolink';
21955
+ token_o.info = 'auto';
21771
21956
 
21772
- const token_t = state.push('text', '', 0);
21957
+ const token_t = state.push('text', '', 0);
21773
21958
  token_t.content = state.md.normalizeLinkText(url);
21774
21959
 
21775
- const token_c = state.push('link_close', 'a', -1);
21776
- token_c.markup = 'autolink';
21777
- token_c.info = 'auto';
21960
+ const token_c = state.push('link_close', 'a', -1);
21961
+ token_c.markup = 'autolink';
21962
+ token_c.info = 'auto';
21778
21963
  }
21779
21964
 
21780
21965
  state.pos += url.length + 2;
@@ -21786,17 +21971,17 @@ function autolink (state, silent) {
21786
21971
  if (!state.md.validateLink(fullUrl)) { return false }
21787
21972
 
21788
21973
  if (!silent) {
21789
- const token_o = state.push('link_open', 'a', 1);
21790
- token_o.attrs = [['href', fullUrl]];
21791
- token_o.markup = 'autolink';
21792
- token_o.info = 'auto';
21974
+ const token_o = state.push('link_open', 'a', 1);
21975
+ token_o.attrs = [['href', fullUrl]];
21976
+ token_o.markup = 'autolink';
21977
+ token_o.info = 'auto';
21793
21978
 
21794
- const token_t = state.push('text', '', 0);
21979
+ const token_t = state.push('text', '', 0);
21795
21980
  token_t.content = state.md.normalizeLinkText(url);
21796
21981
 
21797
- const token_c = state.push('link_close', 'a', -1);
21798
- token_c.markup = 'autolink';
21799
- token_c.info = 'auto';
21982
+ const token_c = state.push('link_close', 'a', -1);
21983
+ token_c.markup = 'autolink';
21984
+ token_c.info = 'auto';
21800
21985
  }
21801
21986
 
21802
21987
  state.pos += url.length + 2;
@@ -21821,6 +22006,43 @@ function isLetter (ch) {
21821
22006
  return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */)
21822
22007
  }
21823
22008
 
22009
+ // Comment, processing instruction, declaration or CDATA: fixed opener,
22010
+ // then everything up to the first terminator. Returns end position or -1.
22011
+ function scanSpecial (state, pos) {
22012
+ const src = state.src;
22013
+ let start;
22014
+ let terminator;
22015
+
22016
+ if (src.startsWith('<!--', pos)) {
22017
+ if (src.startsWith('>', pos + 4)) { return pos + 5 }
22018
+ if (src.startsWith('->', pos + 4)) { return pos + 6 }
22019
+ start = pos + 4;
22020
+ terminator = '-->';
22021
+ } else if (src.startsWith('<![CDATA[', pos)) {
22022
+ start = pos + 9;
22023
+ terminator = ']]>';
22024
+ } else if (src.charCodeAt(pos + 1) === 0x3F/* ? */) {
22025
+ start = pos + 2;
22026
+ terminator = '?>';
22027
+ } else if (isLetter(src.charCodeAt(pos + 2))) {
22028
+ start = pos + 3;
22029
+ terminator = '>';
22030
+ } else {
22031
+ return -1
22032
+ }
22033
+
22034
+ if (state.skipHtmlSpecial) { return -1 }
22035
+
22036
+ const end = src.indexOf(terminator, start);
22037
+ if (end < 0) {
22038
+ // One flag for all constructs to keep code simple. Valid constructs after
22039
+ // an unclosed one in the same paragraph become text, that's acceptable.
22040
+ state.skipHtmlSpecial = true;
22041
+ return -1
22042
+ }
22043
+ return end + terminator.length
22044
+ }
22045
+
21824
22046
  function html_inline (state, silent) {
21825
22047
  if (!state.md.options.html) { return false }
21826
22048
 
@@ -21832,33 +22054,35 @@ function html_inline (state, silent) {
21832
22054
  return false
21833
22055
  }
21834
22056
 
21835
- // Quick fail on second char
22057
+ let end;
21836
22058
  const ch = state.src.charCodeAt(pos + 1);
21837
- if (ch !== 0x21/* ! */ &&
21838
- ch !== 0x3F/* ? */ &&
21839
- ch !== 0x2F/* / */ &&
21840
- !isLetter(ch)) {
22059
+
22060
+ if (ch === 0x21/* ! */ || ch === 0x3F/* ? */) {
22061
+ end = scanSpecial(state, pos);
22062
+ } else if (ch === 0x2F/* / */ || isLetter(ch)) {
22063
+ const match = state.src.slice(pos).match(HTML_OPEN_CLOSE_TAG_RE);
22064
+ end = match ? pos + match[0].length : -1;
22065
+ } else {
21841
22066
  return false
21842
22067
  }
21843
22068
 
21844
- const match = state.src.slice(pos).match(HTML_TAG_RE);
21845
- if (!match) { return false }
22069
+ if (end < 0) { return false }
21846
22070
 
21847
22071
  if (!silent) {
21848
22072
  const token = state.push('html_inline', '', 0);
21849
- token.content = match[0];
22073
+ token.content = state.src.slice(pos, end);
21850
22074
 
21851
- if (isLinkOpen(token.content)) state.linkLevel++;
22075
+ if (isLinkOpen(token.content)) state.linkLevel++;
21852
22076
  if (isLinkClose(token.content)) state.linkLevel--;
21853
22077
  }
21854
- state.pos += match[0].length;
22078
+ state.pos = end;
21855
22079
  return true
21856
22080
  }
21857
22081
 
21858
22082
  // Process html entity - &#123;, &#xAF;, &quot;, ...
21859
22083
 
21860
22084
  const DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;
21861
- const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
22085
+ const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
21862
22086
 
21863
22087
  function entity (state, silent) {
21864
22088
  const pos = state.pos;
@@ -21876,10 +22100,10 @@ function entity (state, silent) {
21876
22100
  if (!silent) {
21877
22101
  const code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);
21878
22102
 
21879
- const token = state.push('text_special', '', 0);
22103
+ const token = state.push('text_special', '', 0);
21880
22104
  token.content = isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);
21881
- token.markup = match[0];
21882
- token.info = 'entity';
22105
+ token.markup = match[0];
22106
+ token.info = 'entity';
21883
22107
  }
21884
22108
  state.pos += match[0].length;
21885
22109
  return true
@@ -21887,13 +22111,13 @@ function entity (state, silent) {
21887
22111
  } else {
21888
22112
  const match = state.src.slice(pos).match(NAMED_RE);
21889
22113
  if (match) {
21890
- const decoded = decodeHTML(match[0]);
22114
+ const decoded = decodeHTMLStrict(match[0]);
21891
22115
  if (decoded !== match[0]) {
21892
22116
  if (!silent) {
21893
- const token = state.push('text_special', '', 0);
22117
+ const token = state.push('text_special', '', 0);
21894
22118
  token.content = decoded;
21895
- token.markup = match[0];
21896
- token.info = 'entity';
22119
+ token.markup = match[0];
22120
+ token.info = 'entity';
21897
22121
  }
21898
22122
  state.pos += match[0].length;
21899
22123
  return true
@@ -21991,8 +22215,8 @@ function processDelimiters (delimiters) {
21991
22215
  jumps[closerIdx] = closerIdx - openerIdx + lastJump;
21992
22216
  jumps[openerIdx] = lastJump;
21993
22217
 
21994
- closer.open = false;
21995
- opener.end = closerIdx;
22218
+ closer.open = false;
22219
+ opener.end = closerIdx;
21996
22220
  opener.close = false;
21997
22221
  newMinOpenerIdx = -1;
21998
22222
  // treat next token as start of run,
@@ -22077,18 +22301,18 @@ function fragments_join (state) {
22077
22301
  // Parser rules
22078
22302
 
22079
22303
  const _rules = [
22080
- ['text', text],
22081
- ['linkify', linkify],
22082
- ['newline', newline],
22083
- ['escape', escape],
22084
- ['backticks', backtick],
22085
- ['strikethrough', r_strikethrough.tokenize],
22086
- ['emphasis', r_emphasis.tokenize],
22087
- ['link', link],
22088
- ['image', image],
22089
- ['autolink', autolink],
22090
- ['html_inline', html_inline],
22091
- ['entity', entity]
22304
+ ['text', text],
22305
+ ['linkify', linkify],
22306
+ ['newline', newline],
22307
+ ['escape', escape],
22308
+ ['backticks', backtick],
22309
+ ['strikethrough', r_strikethrough.tokenize],
22310
+ ['emphasis', r_emphasis.tokenize],
22311
+ ['link', link],
22312
+ ['image', image],
22313
+ ['autolink', autolink],
22314
+ ['html_inline', html_inline],
22315
+ ['entity', entity]
22092
22316
  ];
22093
22317
 
22094
22318
  // `rule2` ruleset was created specifically for emphasis/strikethrough
@@ -22097,12 +22321,12 @@ const _rules = [
22097
22321
  // Don't use this for anything except pairs (plugins working with `balance_pairs`).
22098
22322
  //
22099
22323
  const _rules2 = [
22100
- ['balance_pairs', link_pairs],
22101
- ['strikethrough', r_strikethrough.postProcess],
22102
- ['emphasis', r_emphasis.postProcess],
22324
+ ['balance_pairs', link_pairs],
22325
+ ['strikethrough', r_strikethrough.postProcess],
22326
+ ['emphasis', r_emphasis.postProcess],
22103
22327
  // rules for pairs separate '**' into its own text tokens, which may be left unused,
22104
22328
  // rule below merges unused segments back with the rest of the text
22105
- ['fragments_join', fragments_join]
22329
+ ['fragments_join', fragments_join]
22106
22330
  ];
22107
22331
 
22108
22332
  /**
@@ -22267,7 +22491,7 @@ function reFactory (opts) {
22267
22491
  // All possible word characters (everything without punctuation, spaces & controls)
22268
22492
  // Defined via punctuation & spaces to save space
22269
22493
  // Should be something like \p{\L\N\S\M} (\w but without `_`)
22270
- re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';
22494
+ re.src_pseudo_letter = `(?:(?!${text_separators}|${re.src_ZPCc})${re.src_Any})`;
22271
22495
  // The same as abothe but without [0-9]
22272
22496
  // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';
22273
22497
 
@@ -22276,7 +22500,9 @@ function reFactory (opts) {
22276
22500
  '(?:(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]?)';
22277
22501
 
22278
22502
  // Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch.
22279
- re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\[\\]()]).)+@)?';
22503
+ // Length is capped to exclude possible rescans till the end and avoid O(n^2)
22504
+ // DoS. No standard limit, just take something reasonable.
22505
+ re.src_auth = `(?:(?:(?!${re.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`;
22280
22506
 
22281
22507
  re.src_port =
22282
22508
 
@@ -22284,23 +22510,23 @@ function reFactory (opts) {
22284
22510
 
22285
22511
  re.src_host_terminator =
22286
22512
 
22287
- '(?=$|' + text_separators + '|' + re.src_ZPCc + ')' +
22288
- '(?!' + (opts['---'] ? '-(?!--)|' : '-|') + '_|:\\d|\\.-|\\.(?!$|' + re.src_ZPCc + '))';
22513
+ `(?=$|${text_separators}|${re.src_ZPCc})` +
22514
+ `(?!${opts['---'] ? '-(?!--)|' : '-|'}_|:\\d|\\.-|\\.(?!$|${re.src_ZPCc}))`;
22289
22515
 
22290
22516
  re.src_path =
22291
22517
 
22292
22518
  '(?:' +
22293
22519
  '[/?#]' +
22294
22520
  '(?:' +
22295
- '(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\]{}.,"\'?!\\-;]).|' +
22296
- '\\[(?:(?!' + re.src_ZCc + '|\\]).)*\\]|' +
22297
- '\\((?:(?!' + re.src_ZCc + '|[)]).)*\\)|' +
22298
- '\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\}|' +
22299
- '\\"(?:(?!' + re.src_ZCc + '|["]).)+\\"|' +
22300
- "\\'(?:(?!" + re.src_ZCc + "|[']).)+\\'|" +
22521
+ `(?!${re.src_ZCc}|${text_separators}|[()[\\]{}.,"'?!\\-;]).|` +
22522
+ `\\[(?:(?!${re.src_ZCc}|\\]).)*\\]|` +
22523
+ `\\((?:(?!${re.src_ZCc}|[)]).)*\\)|` +
22524
+ `\\{(?:(?!${re.src_ZCc}|[}]).)*\\}|` +
22525
+ `\\"(?:(?!${re.src_ZCc}|["]).)+\\"|` +
22526
+ `\\'(?:(?!${re.src_ZCc}|[']).)+\\'|` +
22301
22527
 
22302
22528
  // allow `I'm_king` if no pair found
22303
- "\\'(?=" + re.src_pseudo_letter + '|[-])|' +
22529
+ `\\'(?=${re.src_pseudo_letter}|[-])|` +
22304
22530
 
22305
22531
  // google has many dots in "google search" links (#66, #81).
22306
22532
  // github has ... in commit range links,
@@ -22312,30 +22538,32 @@ function reFactory (opts) {
22312
22538
  // until more examples found.
22313
22539
  '\\.{2,}[a-zA-Z0-9%/&]|' +
22314
22540
 
22315
- '\\.(?!' + re.src_ZCc + '|[.]|$)|' +
22541
+ `\\.(?!${re.src_ZCc}|[.]|$)|` +
22316
22542
  (opts['---']
22317
22543
  ? '\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate
22318
22544
  : '\\-+|'
22319
22545
  ) +
22320
22546
  // allow `,,,` in paths
22321
- ',(?!' + re.src_ZCc + '|$)|' +
22547
+ `,(?!${re.src_ZCc}|$)|` +
22322
22548
 
22323
22549
  // allow `;` if not followed by space-like char
22324
- ';(?!' + re.src_ZCc + '|$)|' +
22550
+ `;(?!${re.src_ZCc}|$)|` +
22325
22551
 
22326
22552
  // allow `!!!` in paths, but not at the end
22327
- '\\!+(?!' + re.src_ZCc + '|[!]|$)|' +
22553
+ `\\!+(?!${re.src_ZCc}|[!]|$)|` +
22328
22554
 
22329
- '\\?(?!' + re.src_ZCc + '|[?]|$)' +
22555
+ `\\?(?!${re.src_ZCc}|[?]|$)` +
22330
22556
  ')+' +
22331
22557
  '|\\/' +
22332
22558
  ')?';
22333
22559
 
22334
22560
  // Allow anything in markdown spec, forbid quote (") at the first position
22335
22561
  // because emails enclosed in quotes are far more common
22562
+ // Max name length capped to 64 chars (RFC 5321). This also prevents O(n^2)
22563
+ // rescans to the end on inputs like `mailto:mailto:...`
22336
22564
  re.src_email_name =
22337
22565
 
22338
- '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*';
22566
+ '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}';
22339
22567
 
22340
22568
  re.src_xn =
22341
22569
 
@@ -22350,7 +22578,7 @@ function reFactory (opts) {
22350
22578
  '(?:' +
22351
22579
  re.src_xn +
22352
22580
  '|' +
22353
- re.src_pseudo_letter + '{1,63}' +
22581
+ `${re.src_pseudo_letter}{1,63}` +
22354
22582
  ')';
22355
22583
 
22356
22584
  re.src_domain =
@@ -22358,9 +22586,9 @@ function reFactory (opts) {
22358
22586
  '(?:' +
22359
22587
  re.src_xn +
22360
22588
  '|' +
22361
- '(?:' + re.src_pseudo_letter + ')' +
22589
+ `(?:${re.src_pseudo_letter})` +
22362
22590
  '|' +
22363
- '(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +
22591
+ `(?:${re.src_pseudo_letter}(?:-|${re.src_pseudo_letter}){0,61}${re.src_pseudo_letter})` +
22364
22592
  ')';
22365
22593
 
22366
22594
  re.src_host =
@@ -22369,7 +22597,7 @@ function reFactory (opts) {
22369
22597
  // Don't need IP check, because digits are already allowed in normal domain names
22370
22598
  // src_ip4 +
22371
22599
  // '|' +
22372
- '(?:(?:(?:' + re.src_domain + ')\\.)*' + re.src_domain/* _root */ + ')' +
22600
+ `(?:(?:(?:${re.src_domain})\\.)*${re.src_domain})`/* _root */ +
22373
22601
  ')';
22374
22602
 
22375
22603
  re.tpl_host_fuzzy =
@@ -22377,12 +22605,12 @@ function reFactory (opts) {
22377
22605
  '(?:' +
22378
22606
  re.src_ip4 +
22379
22607
  '|' +
22380
- '(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))' +
22608
+ `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))` +
22381
22609
  ')';
22382
22610
 
22383
22611
  re.tpl_host_no_ip_fuzzy =
22384
22612
 
22385
- '(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))';
22613
+ `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))`;
22386
22614
 
22387
22615
  re.src_host_strict =
22388
22616
 
@@ -22411,24 +22639,24 @@ function reFactory (opts) {
22411
22639
  // Rude test fuzzy links by host, for quick deny
22412
22640
  re.tpl_host_fuzzy_test =
22413
22641
 
22414
- 'localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';
22642
+ `localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:${re.src_ZPCc}|>|$))`;
22415
22643
 
22416
22644
  re.tpl_email_fuzzy =
22417
22645
 
22418
- '(^|' + text_separators + '|"|\\(|' + re.src_ZCc + ')' +
22419
- '(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';
22646
+ `(^|${text_separators}|"|\\(|${re.src_ZCc})` +
22647
+ `(${re.src_email_name}@${re.tpl_host_fuzzy_strict})`;
22420
22648
 
22421
22649
  re.tpl_link_fuzzy =
22422
22650
  // Fuzzy link can't be prepended with .:/\- and non punctuation.
22423
22651
  // but can start with > (markdown blockquote)
22424
- '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
22425
- '((?![$+<=>^`|\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';
22652
+ `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` +
22653
+ `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_fuzzy_strict}${re.src_path})`;
22426
22654
 
22427
22655
  re.tpl_link_no_ip_fuzzy =
22428
22656
  // Fuzzy link can't be prepended with .:/\- and non punctuation.
22429
22657
  // but can start with > (markdown blockquote)
22430
- '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
22431
- '((?![$+<=>^`|\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';
22658
+ `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` +
22659
+ `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_no_ip_fuzzy_strict}${re.src_path})`;
22432
22660
 
22433
22661
  return re
22434
22662
  }
@@ -22484,7 +22712,7 @@ const defaultSchemas = {
22484
22712
  if (!self.re.http) {
22485
22713
  // compile lazily, because "host"-containing variables can change on tlds update.
22486
22714
  self.re.http = new RegExp(
22487
- '^\\/\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'
22715
+ `^\\/\\/${self.re.src_auth}${self.re.src_host_port_strict}${self.re.src_path}`, 'i'
22488
22716
  );
22489
22717
  }
22490
22718
  if (self.re.http.test(tail)) {
@@ -22506,7 +22734,7 @@ const defaultSchemas = {
22506
22734
  self.re.src_auth +
22507
22735
  // Don't allow single-level domains, because of false positives like '//test'
22508
22736
  // with code comments
22509
- '(?:localhost|(?:(?:' + self.re.src_domain + ')\\.)+' + self.re.src_domain_root + ')' +
22737
+ `(?:localhost|(?:(?:${self.re.src_domain})\\.)+${self.re.src_domain_root})` +
22510
22738
  self.re.src_port +
22511
22739
  self.re.src_host_terminator +
22512
22740
  self.re.src_path,
@@ -22530,7 +22758,7 @@ const defaultSchemas = {
22530
22758
 
22531
22759
  if (!self.re.mailto) {
22532
22760
  self.re.mailto = new RegExp(
22533
- '^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'
22761
+ `^${self.re.src_email_name}@${self.re.src_host_strict}`, 'i'
22534
22762
  );
22535
22763
  }
22536
22764
  if (self.re.mailto.test(tail)) {
@@ -22542,17 +22770,11 @@ const defaultSchemas = {
22542
22770
  };
22543
22771
 
22544
22772
  // RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)
22545
- /* eslint-disable-next-line max-len */
22546
22773
  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]';
22547
22774
 
22548
22775
  // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
22549
22776
  const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
22550
22777
 
22551
- function resetScanCache (self) {
22552
- self.__index__ = -1;
22553
- self.__text_cache__ = '';
22554
- }
22555
-
22556
22778
  function createValidator (re) {
22557
22779
  return function (text, pos) {
22558
22780
  const tail = text.slice(pos);
@@ -22591,8 +22813,11 @@ function compile (self) {
22591
22813
  function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) }
22592
22814
 
22593
22815
  re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');
22816
+ re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig');
22594
22817
  re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');
22818
+ re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig');
22595
22819
  re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');
22820
+ re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig');
22596
22821
  re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');
22597
22822
 
22598
22823
  //
@@ -22604,7 +22829,7 @@ function compile (self) {
22604
22829
  self.__compiled__ = {}; // Reset compiled data
22605
22830
 
22606
22831
  function schemaError (name, val) {
22607
- throw new Error('(LinkifyIt) Invalid schema "' + name + '": ' + val)
22832
+ throw new Error(`(LinkifyIt) Invalid schema "${name}": ${val}`)
22608
22833
  }
22609
22834
 
22610
22835
  Object.keys(self.__schemas__).forEach(function (name) {
@@ -22678,20 +22903,14 @@ function compile (self) {
22678
22903
  .map(escapeRE)
22679
22904
  .join('|');
22680
22905
  // (?!_) cause 1.5x slowdown
22681
- self.re.schema_test = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'i');
22682
- self.re.schema_search = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'ig');
22683
- self.re.schema_at_start = RegExp('^' + self.re.schema_search.source, 'i');
22906
+ self.re.schema_test = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'i');
22907
+ self.re.schema_search = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'ig');
22908
+ self.re.schema_at_start = RegExp(`^${self.re.schema_search.source}`, 'i');
22684
22909
 
22685
22910
  self.re.pretest = RegExp(
22686
- '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
22911
+ `(${self.re.schema_test.source})|(${self.re.host_fuzzy_test.source})|@`,
22687
22912
  'i'
22688
22913
  );
22689
-
22690
- //
22691
- // Cleanup
22692
- //
22693
-
22694
- resetScanCache(self);
22695
22914
  }
22696
22915
 
22697
22916
  /**
@@ -22699,55 +22918,45 @@ function compile (self) {
22699
22918
  *
22700
22919
  * Match result. Single element of array, returned by [[LinkifyIt#match]]
22701
22920
  **/
22702
- function Match (self, shift) {
22703
- const start = self.__index__;
22704
- const end = self.__last_index__;
22705
- const text = self.__text_cache__.slice(start, end);
22921
+ function Match (text, schema, index, lastIndex) {
22922
+ const raw = text.slice(index, lastIndex);
22706
22923
 
22707
22924
  /**
22708
22925
  * Match#schema -> String
22709
22926
  *
22710
22927
  * Prefix (protocol) for matched string.
22711
22928
  **/
22712
- this.schema = self.__schema__.toLowerCase();
22929
+ this.schema = schema.toLowerCase();
22713
22930
  /**
22714
22931
  * Match#index -> Number
22715
22932
  *
22716
22933
  * First position of matched string.
22717
22934
  **/
22718
- this.index = start + shift;
22935
+ this.index = index;
22719
22936
  /**
22720
22937
  * Match#lastIndex -> Number
22721
22938
  *
22722
22939
  * Next position after matched string.
22723
22940
  **/
22724
- this.lastIndex = end + shift;
22941
+ this.lastIndex = lastIndex;
22725
22942
  /**
22726
22943
  * Match#raw -> String
22727
22944
  *
22728
22945
  * Matched string.
22729
22946
  **/
22730
- this.raw = text;
22947
+ this.raw = raw;
22731
22948
  /**
22732
22949
  * Match#text -> String
22733
22950
  *
22734
22951
  * Notmalized text of matched string.
22735
22952
  **/
22736
- this.text = text;
22953
+ this.text = raw;
22737
22954
  /**
22738
22955
  * Match#url -> String
22739
22956
  *
22740
22957
  * Normalized url of matched string.
22741
22958
  **/
22742
- this.url = text;
22743
- }
22744
-
22745
- function createMatch (self, shift) {
22746
- const match = new Match(self, shift);
22747
-
22748
- self.__compiled__[match.schema].normalize(match, self);
22749
-
22750
- return match
22959
+ this.url = raw;
22751
22960
  }
22752
22961
 
22753
22962
  /**
@@ -22802,12 +23011,6 @@ function LinkifyIt (schemas, options) {
22802
23011
 
22803
23012
  this.__opts__ = assign({}, defaultOptions, options);
22804
23013
 
22805
- // Cache last tested result. Used to skip repeating steps on next `match` call.
22806
- this.__index__ = -1;
22807
- this.__last_index__ = -1; // Next scan position
22808
- this.__schema__ = '';
22809
- this.__text_cache__ = '';
22810
-
22811
23014
  this.__schemas__ = assign({}, defaultSchemas, schemas);
22812
23015
  this.__compiled__ = {};
22813
23016
 
@@ -22849,69 +23052,38 @@ LinkifyIt.prototype.set = function set (options) {
22849
23052
  * Searches linkifiable pattern and returns `true` on success or `false` on fail.
22850
23053
  **/
22851
23054
  LinkifyIt.prototype.test = function test (text) {
22852
- // Reset scan cache
22853
- this.__text_cache__ = text;
22854
- this.__index__ = -1;
22855
-
22856
23055
  if (!text.length) { return false }
22857
23056
 
22858
- let m, ml, me, len, shift, next, re, tld_pos, at_pos;
23057
+ let m, re;
22859
23058
 
22860
23059
  // try to scan for link with schema - that's the most simple rule
22861
23060
  if (this.re.schema_test.test(text)) {
22862
23061
  re = this.re.schema_search;
22863
23062
  re.lastIndex = 0;
22864
23063
  while ((m = re.exec(text)) !== null) {
22865
- len = this.testSchemaAt(text, m[2], re.lastIndex);
22866
- if (len) {
22867
- this.__schema__ = m[2];
22868
- this.__index__ = m.index + m[1].length;
22869
- this.__last_index__ = m.index + m[0].length + len;
22870
- break
22871
- }
23064
+ if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }
22872
23065
  }
22873
23066
  }
22874
23067
 
22875
23068
  if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
22876
23069
  // guess schemaless links
22877
- tld_pos = text.search(this.re.host_fuzzy_test);
22878
- if (tld_pos >= 0) {
22879
- // if tld is located after found link - no need to check fuzzy pattern
22880
- if (this.__index__ < 0 || tld_pos < this.__index__) {
22881
- if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
22882
- shift = ml.index + ml[1].length;
22883
-
22884
- if (this.__index__ < 0 || shift < this.__index__) {
22885
- this.__schema__ = '';
22886
- this.__index__ = shift;
22887
- this.__last_index__ = ml.index + ml[0].length;
22888
- }
22889
- }
23070
+ if (text.search(this.re.host_fuzzy_test) >= 0) {
23071
+ if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) {
23072
+ return true
22890
23073
  }
22891
23074
  }
22892
23075
  }
22893
23076
 
22894
23077
  if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
22895
23078
  // guess schemaless emails
22896
- at_pos = text.indexOf('@');
22897
- if (at_pos >= 0) {
23079
+ if (text.indexOf('@') >= 0) {
22898
23080
  // We can't skip this check, because this cases are possible:
22899
23081
  // 192.168.1.1@gmail.com, my.in@example.com
22900
- if ((me = text.match(this.re.email_fuzzy)) !== null) {
22901
- shift = me.index + me[1].length;
22902
- next = me.index + me[0].length;
22903
-
22904
- if (this.__index__ < 0 || shift < this.__index__ ||
22905
- (shift === this.__index__ && next > this.__last_index__)) {
22906
- this.__schema__ = 'mailto:';
22907
- this.__index__ = shift;
22908
- this.__last_index__ = next;
22909
- }
22910
- }
23082
+ if (text.match(this.re.email_fuzzy) !== null) { return true }
22911
23083
  }
22912
23084
  }
22913
23085
 
22914
- return this.__index__ >= 0
23086
+ return false
22915
23087
  };
22916
23088
 
22917
23089
  /**
@@ -22960,23 +23132,88 @@ LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) {
22960
23132
  **/
22961
23133
  LinkifyIt.prototype.match = function match (text) {
22962
23134
  const result = [];
22963
- let shift = 0;
23135
+ const type_schemed = [];
23136
+ const type_fuzzy_link = [];
23137
+ const type_fuzzy_email = [];
23138
+ let m, len, re;
22964
23139
 
22965
- // Try to take previous element from cache, if .test() called before
22966
- if (this.__index__ >= 0 && this.__text_cache__ === text) {
22967
- result.push(createMatch(this, shift));
22968
- shift = this.__last_index__;
23140
+ function choose (a, b) {
23141
+ if (!a) { return b }
23142
+ if (!b) { return a }
23143
+ if (a.index !== b.index) { return a.index < b.index ? a : b }
23144
+ return a.lastIndex >= b.lastIndex ? a : b
22969
23145
  }
22970
23146
 
22971
- // Cut head if cache was used
22972
- let tail = shift ? text.slice(shift) : text;
23147
+ if (!text.length) { return null }
22973
23148
 
22974
- // Scan string until end reached
22975
- while (this.test(tail)) {
22976
- result.push(createMatch(this, shift));
23149
+ // scan for links with schema
23150
+ if (this.re.schema_test.test(text)) {
23151
+ re = this.re.schema_search;
23152
+ re.lastIndex = 0;
23153
+ while ((m = re.exec(text)) !== null) {
23154
+ len = this.testSchemaAt(text, m[2], re.lastIndex);
23155
+ if (len) {
23156
+ type_schemed.push({
23157
+ schema: m[2],
23158
+ index: m.index + m[1].length,
23159
+ lastIndex: m.index + m[0].length + len
23160
+ });
23161
+ }
23162
+ }
23163
+ }
23164
+
23165
+ if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
23166
+ re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global;
23167
+ re.lastIndex = 0;
23168
+ while ((m = re.exec(text)) !== null) {
23169
+ type_fuzzy_link.push({
23170
+ schema: '',
23171
+ index: m.index + m[1].length,
23172
+ lastIndex: m.index + m[0].length
23173
+ });
23174
+ }
23175
+ }
23176
+
23177
+ if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
23178
+ re = this.re.email_fuzzy_global;
23179
+ re.lastIndex = 0;
23180
+ while ((m = re.exec(text)) !== null) {
23181
+ type_fuzzy_email.push({
23182
+ schema: 'mailto:',
23183
+ index: m.index + m[1].length,
23184
+ lastIndex: m.index + m[0].length
23185
+ });
23186
+ }
23187
+ }
23188
+
23189
+ const indexes = [0, 0, 0];
23190
+ let lastIndex = 0;
23191
+
23192
+ for (;;) {
23193
+ const candidates = [
23194
+ type_schemed[indexes[0]],
23195
+ type_fuzzy_email[indexes[1]],
23196
+ type_fuzzy_link[indexes[2]]
23197
+ ];
22977
23198
 
22978
- tail = tail.slice(this.__last_index__);
22979
- shift += this.__last_index__;
23199
+ const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]);
23200
+
23201
+ if (!candidate) { break }
23202
+
23203
+ if (candidate === candidates[0]) {
23204
+ indexes[0]++;
23205
+ } else if (candidate === candidates[1]) {
23206
+ indexes[1]++;
23207
+ } else {
23208
+ indexes[2]++;
23209
+ }
23210
+
23211
+ if (candidate.index < lastIndex) { continue }
23212
+
23213
+ const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex);
23214
+ this.__compiled__[match.schema].normalize(match, this);
23215
+ result.push(match);
23216
+ lastIndex = candidate.lastIndex;
22980
23217
  }
22981
23218
 
22982
23219
  if (result.length) {
@@ -22993,10 +23230,6 @@ LinkifyIt.prototype.match = function match (text) {
22993
23230
  * of the string, and null otherwise.
22994
23231
  **/
22995
23232
  LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
22996
- // Reset scan cache
22997
- this.__text_cache__ = text;
22998
- this.__index__ = -1;
22999
-
23000
23233
  if (!text.length) return null
23001
23234
 
23002
23235
  const m = this.re.schema_at_start.exec(text);
@@ -23005,11 +23238,10 @@ LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
23005
23238
  const len = this.testSchemaAt(text, m[2], m[0].length);
23006
23239
  if (!len) return null
23007
23240
 
23008
- this.__schema__ = m[2];
23009
- this.__index__ = m.index + m[1].length;
23010
- this.__last_index__ = m.index + m[0].length + len;
23241
+ const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len);
23011
23242
 
23012
- return createMatch(this, 0)
23243
+ this.__compiled__[match.schema].normalize(match, this);
23244
+ return match
23013
23245
  };
23014
23246
 
23015
23247
  /** chainable
@@ -23057,10 +23289,10 @@ LinkifyIt.prototype.normalize = function normalize (match) {
23057
23289
  // Do minimal possible changes by default. Need to collect feedback prior
23058
23290
  // to move forward https://github.com/markdown-it/linkify-it/issues/1
23059
23291
 
23060
- if (!match.schema) { match.url = 'http://' + match.url; }
23292
+ if (!match.schema) { match.url = `http://${match.url}`; }
23061
23293
 
23062
23294
  if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {
23063
- match.url = 'mailto:' + match.url;
23295
+ match.url = `mailto:${match.url}`;
23064
23296
  }
23065
23297
  };
23066
23298
 
@@ -24060,7 +24292,7 @@ function MarkdownIt (presetName, options) {
24060
24292
  * ```javascript
24061
24293
  * var md = require('markdown-it')()
24062
24294
  * .set({ html: true, breaks: true })
24063
- * .set({ typographer, true });
24295
+ * .set({ typographer: true });
24064
24296
  * ```
24065
24297
  *
24066
24298
  * __Note:__ To achieve the best possible performance, don't modify a