@janhq/remend 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,6 +81,81 @@ Available options:
81
81
  | `strikethrough` | Complete strikethrough formatting (`~~`) |
82
82
  | `katex` | Complete block KaTeX math (`$$`) |
83
83
  | `setextHeadings` | Handle incomplete setext headings |
84
+ | `handlers` | Custom handlers to extend remend |
85
+
86
+ ### Custom Handlers
87
+
88
+ You can extend remend with custom handlers to complete your own markers during streaming. This is useful for custom syntax like `<<<JOKE>>>` blocks or other domain-specific patterns.
89
+
90
+ ```typescript
91
+ import remend, { type RemendHandler } from "remend";
92
+
93
+ const jokeHandler: RemendHandler = {
94
+ name: "joke",
95
+ handle: (text) => {
96
+ // Complete <<<JOKE>>> marks that aren't closed
97
+ const match = text.match(/<<<JOKE>>>([^<]*)$/);
98
+ if (match && !text.endsWith("<<</JOKE>>>")) {
99
+ return `${text}<<</JOKE>>>`;
100
+ }
101
+ return text;
102
+ },
103
+ priority: 80, // Runs after most built-ins (0-70)
104
+ };
105
+
106
+ const result = remend(content, { handlers: [jokeHandler] });
107
+ ```
108
+
109
+ #### Handler Interface
110
+
111
+ ```typescript
112
+ interface RemendHandler {
113
+ name: string; // Unique identifier
114
+ handle: (text: string) => string; // Transform function
115
+ priority?: number; // Lower runs first (default: 100)
116
+ }
117
+ ```
118
+
119
+ #### Built-in Priorities
120
+
121
+ Built-in handlers use priorities 0-70. Custom handlers default to 100 (run after built-ins):
122
+
123
+ | Handler | Priority |
124
+ |---------|----------|
125
+ | `setextHeadings` | 0 |
126
+ | `links` | 10 |
127
+ | `boldItalic` | 20 |
128
+ | `bold` | 30 |
129
+ | `italic` | 40-42 |
130
+ | `inlineCode` | 50 |
131
+ | `strikethrough` | 60 |
132
+ | `katex` | 70 |
133
+ | Custom (default) | 100 |
134
+
135
+ #### Exported Utilities
136
+
137
+ Remend exports utility functions for context detection in custom handlers:
138
+
139
+ ```typescript
140
+ import {
141
+ isWithinCodeBlock,
142
+ isWithinMathBlock,
143
+ isWithinLinkOrImageUrl,
144
+ isWordChar,
145
+ } from "remend";
146
+
147
+ const handler: RemendHandler = {
148
+ name: "custom",
149
+ handle: (text) => {
150
+ // Skip if we're inside a code block
151
+ if (isWithinCodeBlock(text, text.length - 1)) {
152
+ return text;
153
+ }
154
+ // Your logic here
155
+ return text;
156
+ },
157
+ };
158
+ ```
84
159
 
85
160
  ### Usage with Remark
86
161
 
package/dist/index.cjs CHANGED
@@ -1,18 +1,18 @@
1
- 'use strict';var p=/(\*\*)([^*]*?)$/,I=/(__)([^_]*?)$/,P=/(\*\*\*)([^*]*?)$/,B=/(\*)([^*]*?)$/,$=/(_)([^_]*?)$/,M=/(`)([^`]*?)$/,A=/(~~)([^~]*?)$/,c=/^[\s_~*`]*$/,k=/^[\s]*[-*+][\s]+$/,C=/[\p{L}\p{N}_]/u,S=/^```[^`\n]*```?$/,_=/^\*{4,}$/;var a=n=>{if(!n)return false;let r=n.charCodeAt(0);return r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===95?true:C.test(n)},g=(n,r)=>{let e=false;for(let s=0;s<r;s+=1)n[s]==="`"&&n[s+1]==="`"&&n[s+2]==="`"&&(e=!e,s+=2);return e},O=(n,r)=>{let e=1;for(let s=r-1;s>=0;s-=1)if(n[s]==="]")e+=1;else if(n[s]==="["&&(e-=1,e===0))return s;return -1},T=(n,r)=>{let e=1;for(let s=r+1;s<n.length;s+=1)if(n[s]==="[")e+=1;else if(n[s]==="]"&&(e-=1,e===0))return s;return -1},d=(n,r)=>{let e=false,s=false;for(let i=0;i<n.length&&i<r;i+=1){if(n[i]==="\\"&&n[i+1]==="$"){i+=1;continue}n[i]==="$"&&(n[i+1]==="$"?(s=!s,i+=1,e=false):s||(e=!e));}return e||s},z=(n,r)=>{for(let e=r;e<n.length;e+=1){if(n[e]===")")return true;if(n[e]===`
2
- `)return false}return false},b=(n,r)=>{for(let e=r-1;e>=0;e-=1){if(n[e]===")")return false;if(n[e]==="(")return e>0&&n[e-1]==="]"?z(n,r):false;if(n[e]===`
3
- `)return false}return false},h=(n,r,e)=>{let s=0;for(let o=r-1;o>=0;o-=1)if(n[o]===`
4
- `){s=o+1;break}let i=n.length;for(let o=r;o<n.length;o+=1)if(n[o]===`
5
- `){i=o;break}let l=n.substring(s,i),t=0,f=false;for(let o of l)if(o===e)t+=1;else if(o!==" "&&o!==" "){f=true;break}return t>=3&&!f};var Q=(n,r,e)=>{if(e!==" "&&e!==" ")return false;let s=0;for(let i=r-1;i>=0;i-=1)if(n[i]===`
6
- `){s=i+1;break}for(let i=s;i<r;i+=1)if(n[i]!==" "&&n[i]!==" ")return false;return true},Y=(n,r,e,s)=>e==="\\"||n.includes("$")&&d(n,r)?true:e!=="*"&&s==="*"?(r<n.length-2?n[r+2]:"")!=="*":!!(e==="*"||e&&s&&a(e)&&a(s)||Q(n,r,s)),U=n=>{let r=0,e=n.length;for(let s=0;s<e;s+=1){if(n[s]!=="*")continue;let i=s>0?n[s-1]:"",l=s<e-1?n[s+1]:"";Y(n,s,i,l)||(r+=1);}return r},j=(n,r,e,s)=>!!(e==="\\"||n.includes("$")&&d(n,r)||b(n,r)||e==="_"||s==="_"||e&&s&&a(e)&&a(s)),q=n=>{let r=0,e=n.length;for(let s=0;s<e;s+=1){if(n[s]!=="_")continue;let i=s>0?n[s-1]:"",l=s<e-1?n[s+1]:"";j(n,s,i,l)||(r+=1);}return r},G=n=>{let r=0,e=0;for(let s=0;s<n.length;s+=1)n[s]==="*"?e+=1:(e>=3&&(r+=Math.floor(e/3)),e=0);return e>=3&&(r+=Math.floor(e/3)),r},J=(n,r,e)=>{if(!r||c.test(r))return true;let i=n.substring(0,e).lastIndexOf(`
7
- `),l=i===-1?0:i+1,t=n.substring(l,e);return k.test(t)&&r.includes(`
8
- `)?true:h(n,e,"*")},N=n=>{let r=n.match(p);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return g(n,s)||J(n,e,s)?n:(n.match(/\*\*/g)||[]).length%2===1?`${n}**`:n},V=(n,r,e)=>{if(!r||c.test(r))return true;let i=n.substring(0,e).lastIndexOf(`
9
- `),l=i===-1?0:i+1,t=n.substring(l,e);return k.test(t)&&r.includes(`
10
- `)?true:h(n,e,"_")},w=n=>{let r=n.match(I);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return g(n,s)||V(n,e,s)?n:(n.match(/__/g)||[]).length%2===1?`${n}__`:n},X=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="*"&&n[r-1]!=="*"&&n[r+1]!=="*"&&n[r-1]!=="\\"&&!d(n,r)){let e=r>0?n[r-1]:"",s=r<n.length-1?n[r+1]:"";if(e&&s&&a(e)&&a(s))continue;return r}return -1},L=n=>{if(!n.match(B))return n;let e=X(n);if(e===-1||g(n,e))return n;let s=n.substring(e+1);return !s||c.test(s)?n:U(n)%2===1?`${n}*`:n},W=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="_"&&n[r-1]!=="_"&&n[r+1]!=="_"&&n[r-1]!=="\\"&&!d(n,r)&&!b(n,r)){let e=r>0?n[r-1]:"",s=r<n.length-1?n[r+1]:"";if(e&&s&&a(e)&&a(s))continue;return r}return -1},Z=n=>{let r=n.length;for(;r>0&&n[r-1]===`
11
- `;)r-=1;if(r<n.length){let e=n.slice(0,r),s=n.slice(r);return `${e}_${s}`}return `${n}_`},x=n=>{if(!n.endsWith("**"))return null;let r=n.slice(0,-2);if((r.match(/\*\*/g)||[]).length%2!==1)return null;let s=r.indexOf("**"),i=W(r);return s!==-1&&i!==-1&&s<i?`${r}_**`:null},R=n=>{if(!n.match($))return n;let e=W(n);if(e===-1||g(n,e))return n;let s=n.substring(e+1);if(!s||c.test(s))return n;if(q(n)%2===1){let l=x(n);return l!==null?l:Z(n)}return n},nn=n=>{let r=(n.match(/\*\*/g)||[]).length,e=U(n);return r%2===0&&e%2===0},rn=(n,r,e)=>!r||c.test(r)||g(n,e)?true:h(n,e,"*"),E=n=>{if(_.test(n))return n;let r=n.match(P);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return rn(n,e,s)?n:G(n)%2===1?nn(n)?n:`${n}***`:n};var m=(n,r)=>{let e=false,s=false;for(let i=0;i<r;i+=1){if(n.substring(i,i+3)==="```"){s=!s,i+=2;continue}!s&&n[i]==="`"&&(e=!e);}return e||s},en=(n,r)=>{let e=n.substring(r,r+3)==="```",s=r>0&&n.substring(r-1,r+2)==="```",i=r>1&&n.substring(r-2,r+1)==="```";return e||s||i},H=n=>{let r=0;for(let e=0;e<n.length;e+=1)n[e]==="`"&&!en(n,e)&&(r+=1);return r};var sn=n=>!n.match(S)||n.includes(`
12
- `)?null:n.endsWith("``")&&!n.endsWith("```")?`${n}\``:n,tn=n=>(n.match(/```/g)||[]).length%2===1,D=n=>{let r=sn(n);if(r!==null)return r;let e=n.match(M);if(e&&!tn(n)){let s=e[2];if(!s||c.test(s))return n;if(H(n)%2===1)return `${n}\``}return n};var ln=(n,r)=>r>=2&&n.substring(r-2,r+1)==="```"||r>=1&&n.substring(r-1,r+2)==="```"||r<=n.length-3&&n.substring(r,r+3)==="```",on=n=>{let r=0,e=false;for(let s=0;s<n.length-1;s+=1)n[s]==="`"&&!ln(n,s)&&(e=!e),!e&&n[s]==="$"&&n[s+1]==="$"&&(r+=1,s+=1);return r},cn=n=>{let r=n.indexOf("$$");return r!==-1&&n.indexOf(`
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var rn=Object.defineProperty,en=Object.defineProperties;var tn=Object.getOwnPropertyDescriptors;var T=Object.getOwnPropertySymbols;var sn=Object.prototype.hasOwnProperty,on=Object.prototype.propertyIsEnumerable;var S=(n,r,e)=>r in n?rn(n,r,{enumerable:true,configurable:true,writable:true,value:e}):n[r]=e,b=(n,r)=>{for(var e in r||(r={}))sn.call(r,e)&&S(n,e,r[e]);if(T)for(var e of T(r))on.call(r,e)&&S(n,e,r[e]);return n},I=(n,r)=>en(n,tn(r));var _=/(\*\*)([^*]*\*?)$/,L=/(__)([^_]*?)$/,E=/(\*\*\*)([^*]*?)$/,O=/(\*)([^*]*?)$/,U=/(_)([^_]*?)$/,y=/(`)([^`]*?)$/,N=/(~~)([^~]*?)$/,u=/^[\s_~*`]*$/,A=/^[\s]*[-*+][\s]+$/,R=/[\p{L}\p{N}_]/u,D=/^```[^`\n]*```?$/,H=/^\*{4,}$/;var W=/(__)([^_]+)_$/,K=/(~~)([^~]+)~$/,w=/__/g,P=/~~/g;var f=n=>{if(!n)return false;let r=n.charCodeAt(0);return r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===95?true:R.test(n)},d=(n,r)=>{let e=false;for(let i=0;i<r;i+=1)n[i]==="`"&&n[i+1]==="`"&&n[i+2]==="`"&&(e=!e,i+=2);return e},G=(n,r)=>{let e=1;for(let i=r-1;i>=0;i-=1)if(n[i]==="]")e+=1;else if(n[i]==="["&&(e-=1,e===0))return i;return -1},B=(n,r)=>{let e=1;for(let i=r+1;i<n.length;i+=1)if(n[i]==="[")e+=1;else if(n[i]==="]"&&(e-=1,e===0))return i;return -1},g=(n,r)=>{let e=false,i=false;for(let t=0;t<n.length&&t<r;t+=1){if(n[t]==="\\"&&n[t+1]==="$"){t+=1;continue}n[t]==="$"&&(n[t+1]==="$"?(i=!i,t+=1,e=false):i||(e=!e));}return e||i},ln=(n,r)=>{for(let e=r;e<n.length;e+=1){if(n[e]===")")return true;if(n[e]===`
2
+ `)return false}return false},p=(n,r)=>{for(let e=r-1;e>=0;e-=1){if(n[e]===")")return false;if(n[e]==="(")return e>0&&n[e-1]==="]"?ln(n,r):false;if(n[e]===`
3
+ `)return false}return false},k=(n,r,e)=>{let i=0;for(let s=r-1;s>=0;s-=1)if(n[s]===`
4
+ `){i=s+1;break}let t=n.length;for(let s=r;s<n.length;s+=1)if(n[s]===`
5
+ `){t=s;break}let o=n.substring(i,t),a=0,l=false;for(let s of o)if(s===e)a+=1;else if(s!==" "&&s!==" "){l=true;break}return a>=3&&!l};var an=(n,r,e)=>{if(e!==" "&&e!==" ")return false;let i=0;for(let t=r-1;t>=0;t-=1)if(n[t]===`
6
+ `){i=t+1;break}for(let t=i;t<r;t+=1)if(n[t]!==" "&&n[t]!==" ")return false;return true},cn=(n,r,e,i)=>e==="\\"||n.includes("$")&&g(n,r)?true:e!=="*"&&i==="*"?(r<n.length-2?n[r+2]:"")!=="*":!!(e==="*"||e&&i&&f(e)&&f(i)||an(n,r,i)),F=n=>{let r=0,e=n.length;for(let i=0;i<e;i+=1){if(n[i]!=="*")continue;let t=i>0?n[i-1]:"",o=i<e-1?n[i+1]:"";cn(n,i,t,o)||(r+=1);}return r},un=(n,r,e,i)=>!!(e==="\\"||n.includes("$")&&g(n,r)||p(n,r)||e==="_"||i==="_"||e&&i&&f(e)&&f(i)),fn=n=>{let r=0,e=n.length;for(let i=0;i<e;i+=1){if(n[i]!=="_")continue;let t=i>0?n[i-1]:"",o=i<e-1?n[i+1]:"";un(n,i,t,o)||(r+=1);}return r},dn=n=>{let r=0,e=0;for(let i=0;i<n.length;i+=1)n[i]==="*"?e+=1:(e>=3&&(r+=Math.floor(e/3)),e=0);return e>=3&&(r+=Math.floor(e/3)),r},gn=(n,r,e)=>{if(!r||u.test(r))return true;let t=n.substring(0,e).lastIndexOf(`
7
+ `),o=t===-1?0:t+1,a=n.substring(o,e);return A.test(a)&&r.includes(`
8
+ `)?true:k(n,e,"*")},X=n=>{let r=n.match(_);if(!r)return n;let e=r[2],i=n.lastIndexOf(r[1]);return d(n,i)||gn(n,e,i)?n:(n.match(/\*\*/g)||[]).length%2===1?e.endsWith("*")?`${n}*`:`${n}**`:n},hn=(n,r,e)=>{if(!r||u.test(r))return true;let t=n.substring(0,e).lastIndexOf(`
9
+ `),o=t===-1?0:t+1,a=n.substring(o,e);return A.test(a)&&r.includes(`
10
+ `)?true:k(n,e,"_")},v=n=>{let r=n.match(L);if(!r){let o=n.match(W);if(o){let a=n.lastIndexOf(o[1]);if(!d(n,a)&&(n.match(w)||[]).length%2===1)return `${n}_`}return n}let e=r[2],i=n.lastIndexOf(r[1]);return d(n,i)||hn(n,e,i)?n:(n.match(/__/g)||[]).length%2===1?`${n}__`:n},mn=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="*"&&n[r-1]!=="*"&&n[r+1]!=="*"&&n[r-1]!=="\\"&&!g(n,r)){let e=r>0?n[r-1]:"",i=r<n.length-1?n[r+1]:"";if(e&&i&&f(e)&&f(i))continue;return r}return -1},Y=n=>{if(!n.match(O))return n;let e=mn(n);if(e===-1||d(n,e))return n;let i=n.substring(e+1);return !i||u.test(i)?n:F(n)%2===1?`${n}*`:n},j=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="_"&&n[r-1]!=="_"&&n[r+1]!=="_"&&n[r-1]!=="\\"&&!g(n,r)&&!p(n,r)){let e=r>0?n[r-1]:"",i=r<n.length-1?n[r+1]:"";if(e&&i&&f(e)&&f(i))continue;return r}return -1},pn=n=>{let r=n.length;for(;r>0&&n[r-1]===`
11
+ `;)r-=1;if(r<n.length){let e=n.slice(0,r),i=n.slice(r);return `${e}_${i}`}return `${n}_`},kn=n=>{if(!n.endsWith("**"))return null;let r=n.slice(0,-2);if((r.match(/\*\*/g)||[]).length%2!==1)return null;let i=r.indexOf("**"),t=j(r);return i!==-1&&t!==-1&&i<t?`${r}_**`:null},z=n=>{if(!n.match(U))return n;let e=j(n);if(e===-1||d(n,e))return n;let i=n.substring(e+1);if(!i||u.test(i))return n;if(fn(n)%2===1){let o=kn(n);return o!==null?o:pn(n)}return n},bn=n=>{let r=(n.match(/\*\*/g)||[]).length,e=F(n);return r%2===0&&e%2===0},In=(n,r,e)=>!r||u.test(r)||d(n,e)?true:k(n,e,"*"),Q=n=>{if(H.test(n))return n;let r=n.match(E);if(!r)return n;let e=r[2],i=n.lastIndexOf(r[1]);return In(n,e,i)?n:dn(n)%2===1?bn(n)?n:`${n}***`:n};var h=(n,r)=>{let e=false,i=false;for(let t=0;t<r;t+=1){if(n.substring(t,t+3)==="```"){i=!i,t+=2;continue}!i&&n[t]==="`"&&(e=!e);}return e||i},An=(n,r)=>{let e=n.substring(r,r+3)==="```",i=r>0&&n.substring(r-1,r+2)==="```",t=r>1&&n.substring(r-2,r+1)==="```";return e||i||t},q=n=>{let r=0;for(let e=0;e<n.length;e+=1)n[e]==="`"&&!An(n,e)&&(r+=1);return r};var Pn=n=>!n.match(D)||n.includes(`
12
+ `)?null:n.endsWith("``")&&!n.endsWith("```")?`${n}\``:n,Bn=n=>(n.match(/```/g)||[]).length%2===1,J=n=>{let r=Pn(n);if(r!==null)return r;let e=n.match(y);if(e&&!Bn(n)){let i=e[2];if(!i||u.test(i))return n;if(q(n)%2===1)return `${n}\``}return n};var Cn=(n,r)=>r>=2&&n.substring(r-2,r+1)==="```"||r>=1&&n.substring(r-1,r+2)==="```"||r<=n.length-3&&n.substring(r,r+3)==="```",$n=n=>{let r=0,e=false;for(let i=0;i<n.length-1;i+=1)n[i]==="`"&&!Cn(n,i)&&(e=!e),!e&&n[i]==="$"&&n[i+1]==="$"&&(r+=1,i+=1);return r},Mn=n=>{let r=n.indexOf("$$");return r!==-1&&n.indexOf(`
13
13
  `,r)!==-1&&!n.endsWith(`
14
14
  `)?`${n}
15
- $$`:`${n}$$`},F=n=>on(n)%2===0?n:cn(n);var an=(n,r)=>{if(n.substring(r+2).includes(")"))return null;let s=O(n,r);if(s===-1||m(n,s))return null;let i=s>0&&n[s-1]==="!",l=i?s-1:s,t=n.substring(0,l);if(i)return t;let f=n.substring(s+1,r);return `${t}[${f}](streamdown:incomplete-link)`},un=(n,r)=>{let e=r>0&&n[r-1]==="!",s=e?r-1:r;if(!n.substring(r+1).includes("]")){let t=n.substring(0,s);return e?t:`${n}](streamdown:incomplete-link)`}if(T(n,r)===-1){let t=n.substring(0,s);return e?t:`${n}](streamdown:incomplete-link)`}return null},v=n=>{let r=n.lastIndexOf("](");if(r!==-1&&!m(n,r)){let e=an(n,r);if(e!==null)return e}for(let e=n.length-1;e>=0;e-=1)if(n[e]==="["&&!m(n,e)){let s=un(n,e);if(s!==null)return s}return n};var fn=/^-{1,2}$/,gn=/^[\s]*-{1,2}[\s]+$/,dn=/^={1,2}$/,hn=/^[\s]*={1,2}[\s]+$/,K=n=>{if(!n||typeof n!="string")return n;let r=n.lastIndexOf(`
16
- `);if(r===-1)return n;let e=n.substring(r+1),s=n.substring(0,r),i=e.trim();if(fn.test(i)&&!e.match(gn)){let t=s.split(`
17
- `).at(-1);if(t&&t.trim().length>0)return `${n}\u200B`}if(dn.test(i)&&!e.match(hn)){let t=s.split(`
18
- `).at(-1);if(t&&t.trim().length>0)return `${n}\u200B`}return n};var y=n=>{let r=n.match(A);if(r){let e=r[2];if(!e||c.test(e))return n;if((n.match(/~~/g)||[]).length%2===1)return `${n}~~`}return n};var u=n=>n!==false,mn=(n,r)=>{if(!n||typeof n!="string")return n;let e=n.endsWith(" ")&&!n.endsWith(" ")?n.slice(0,-1):n;if(u(r==null?void 0:r.setextHeadings)&&(e=K(e)),u(r==null?void 0:r.links)||u(r==null?void 0:r.images)){let s=v(e);if(s.endsWith("](streamdown:incomplete-link)"))return s;e=s;}return u(r==null?void 0:r.boldItalic)&&(e=E(e)),u(r==null?void 0:r.bold)&&(e=N(e)),u(r==null?void 0:r.italic)&&(e=w(e),e=L(e),e=R(e)),u(r==null?void 0:r.inlineCode)&&(e=D(e)),u(r==null?void 0:r.strikethrough)&&(e=y(e)),u(r==null?void 0:r.katex)&&(e=F(e)),e},Fn=mn;module.exports=Fn;
15
+ $$`:`${n}$$`},V=n=>$n(n)%2===0?n:Mn(n);var Tn=(n,r,e)=>{if(n.substring(r+2).includes(")"))return null;let t=G(n,r);if(t===-1||h(n,t))return null;let o=t>0&&n[t-1]==="!",a=o?t-1:t,l=n.substring(0,a);if(o)return l;let s=n.substring(t+1,r);return e==="text-only"?`${l}${s}`:`${l}[${s}](streamdown:incomplete-link)`},Z=(n,r)=>{for(let e=0;e<=r;e++)if(n[e]==="["&&!h(n,e)){if(e>0&&n[e-1]==="!")continue;let i=B(n,e);if(i===-1)return e;if(i+1<n.length&&n[i+1]==="("){let t=n.indexOf(")",i+2);t!==-1&&(e=t);}}return -1},Sn=(n,r,e)=>{let i=r>0&&n[r-1]==="!",t=i?r-1:r,o=n.substring(r+1);if(!o.includes("]")){let l=n.substring(0,t);if(i)return l;if(e==="text-only"){let s=Z(n,r);return s!==-1?n.substring(0,s)+n.substring(s+1):`${l}${o}`}return `${n}](streamdown:incomplete-link)`}if(B(n,r)===-1){let l=n.substring(0,t);if(i)return l;if(e==="text-only"){let s=Z(n,r);if(s!==-1)return n.substring(0,s)+n.substring(s+1);let m=n.substring(r+1);return `${l}${m}`}return `${n}](streamdown:incomplete-link)`}return null},C=(n,r="protocol")=>{let e=n.lastIndexOf("](");if(e!==-1&&!h(n,e)){let i=Tn(n,e,r);if(i!==null)return i}for(let i=n.length-1;i>=0;i-=1)if(n[i]==="["&&!h(n,i)){let t=Sn(n,i,r);if(t!==null)return t}return n};var _n=/^-{1,2}$/,Ln=/^[\s]*-{1,2}[\s]+$/,En=/^={1,2}$/,On=/^[\s]*={1,2}[\s]+$/,x=n=>{if(!n||typeof n!="string")return n;let r=n.lastIndexOf(`
16
+ `);if(r===-1)return n;let e=n.substring(r+1),i=n.substring(0,r),t=e.trim();if(_n.test(t)&&!e.match(Ln)){let a=i.split(`
17
+ `).at(-1);if(a&&a.trim().length>0)return `${n}\u200B`}if(En.test(t)&&!e.match(On)){let a=i.split(`
18
+ `).at(-1);if(a&&a.trim().length>0)return `${n}\u200B`}return n};var nn=n=>{let r=n.match(N);if(r){let e=r[2];if(!e||u.test(e))return n;if((n.match(P)||[]).length%2===1)return `${n}~~`}else if(n.match(K)&&(n.match(P)||[]).length%2===1)return `${n}~`;return n};var $=n=>n!==false,c={SETEXT_HEADINGS:0,LINKS:10,BOLD_ITALIC:20,BOLD:30,ITALIC_DOUBLE_UNDERSCORE:40,ITALIC_SINGLE_ASTERISK:41,ITALIC_SINGLE_UNDERSCORE:42,INLINE_CODE:50,STRIKETHROUGH:60,KATEX:70,DEFAULT:100},Un=[{handler:{name:"setextHeadings",handle:x,priority:c.SETEXT_HEADINGS},optionKey:"setextHeadings"},{handler:{name:"links",handle:C,priority:c.LINKS},optionKey:"links",earlyReturn:n=>n.endsWith("](streamdown:incomplete-link)")},{handler:{name:"boldItalic",handle:Q,priority:c.BOLD_ITALIC},optionKey:"boldItalic"},{handler:{name:"bold",handle:X,priority:c.BOLD},optionKey:"bold"},{handler:{name:"italicDoubleUnderscore",handle:v,priority:c.ITALIC_DOUBLE_UNDERSCORE},optionKey:"italic"},{handler:{name:"italicSingleAsterisk",handle:Y,priority:c.ITALIC_SINGLE_ASTERISK},optionKey:"italic"},{handler:{name:"italicSingleUnderscore",handle:z,priority:c.ITALIC_SINGLE_UNDERSCORE},optionKey:"italic"},{handler:{name:"inlineCode",handle:J,priority:c.INLINE_CODE},optionKey:"inlineCode"},{handler:{name:"strikethrough",handle:nn,priority:c.STRIKETHROUGH},optionKey:"strikethrough"},{handler:{name:"katex",handle:V,priority:c.KATEX},optionKey:"katex"}],yn=n=>{var e;let r=(e=n==null?void 0:n.linkMode)!=null?e:"protocol";return Un.filter(({handler:i,optionKey:t})=>i.name==="links"?$(n==null?void 0:n.links)||$(n==null?void 0:n.images):$(n==null?void 0:n[t])).map(({handler:i,earlyReturn:t})=>i.name==="links"?{handler:I(b({},i),{handle:o=>C(o,r)}),earlyReturn:r==="protocol"?t:void 0}:{handler:i,earlyReturn:t})},Nn=(n,r)=>{var a;if(!n||typeof n!="string")return n;let e=n.endsWith(" ")&&!n.endsWith(" ")?n.slice(0,-1):n,i=yn(r),t=((a=r==null?void 0:r.handlers)!=null?a:[]).map(l=>{var s;return {handler:I(b({},l),{priority:(s=l.priority)!=null?s:c.DEFAULT}),earlyReturn:void 0}}),o=[...i,...t].sort((l,s)=>{var m,M;return ((m=l.handler.priority)!=null?m:c.DEFAULT)-((M=s.handler.priority)!=null?M:c.DEFAULT)});for(let{handler:l,earlyReturn:s}of o)if(e=l.handle(e),s!=null&&s(e))return e;return e},sr=Nn;exports.default=sr;exports.isWithinCodeBlock=d;exports.isWithinLinkOrImageUrl=p;exports.isWithinMathBlock=g;exports.isWordChar=f;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,21 @@
1
+ type LinkMode = "protocol" | "text-only";
2
+
3
+ declare const isWordChar: (char: string) => boolean;
4
+ declare const isWithinCodeBlock: (text: string, position: number) => boolean;
5
+ declare const isWithinMathBlock: (text: string, position: number) => boolean;
6
+ declare const isWithinLinkOrImageUrl: (text: string, position: number) => boolean;
7
+
8
+ /**
9
+ * Handler function that transforms text during streaming.
10
+ */
11
+ interface RemendHandler {
12
+ /** Unique identifier for this handler */
13
+ name: string;
14
+ /** Handler function: takes text, returns modified text */
15
+ handle: (text: string) => string;
16
+ /** Priority (lower runs first). Built-in priorities: 0-100. Default: 100 */
17
+ priority?: number;
18
+ }
1
19
  /**
2
20
  * Configuration options for the remend function.
3
21
  * All options default to `true` when not specified.
@@ -8,6 +26,12 @@ interface RemendOptions {
8
26
  links?: boolean;
9
27
  /** Complete images (e.g., `![alt](url` → removed) */
10
28
  images?: boolean;
29
+ /**
30
+ * How to handle incomplete links:
31
+ * - `'protocol'`: Use `streamdown:incomplete-link` placeholder URL (default)
32
+ * - `'text-only'`: Display only the link text without any link markup
33
+ */
34
+ linkMode?: "protocol" | "text-only";
11
35
  /** Complete bold formatting (e.g., `**text` → `**text**`) */
12
36
  bold?: boolean;
13
37
  /** Complete italic formatting (e.g., `*text` → `*text*` or `_text` → `_text_`) */
@@ -22,7 +46,9 @@ interface RemendOptions {
22
46
  katex?: boolean;
23
47
  /** Handle incomplete setext headings to prevent misinterpretation */
24
48
  setextHeadings?: boolean;
49
+ /** Custom handlers to extend remend */
50
+ handlers?: RemendHandler[];
25
51
  }
26
52
  declare const remend: (text: string, options?: RemendOptions) => string;
27
53
 
28
- export { type RemendOptions, remend as default };
54
+ export { type LinkMode, type RemendHandler, type RemendOptions, remend as default, isWithinCodeBlock, isWithinLinkOrImageUrl, isWithinMathBlock, isWordChar };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,21 @@
1
+ type LinkMode = "protocol" | "text-only";
2
+
3
+ declare const isWordChar: (char: string) => boolean;
4
+ declare const isWithinCodeBlock: (text: string, position: number) => boolean;
5
+ declare const isWithinMathBlock: (text: string, position: number) => boolean;
6
+ declare const isWithinLinkOrImageUrl: (text: string, position: number) => boolean;
7
+
8
+ /**
9
+ * Handler function that transforms text during streaming.
10
+ */
11
+ interface RemendHandler {
12
+ /** Unique identifier for this handler */
13
+ name: string;
14
+ /** Handler function: takes text, returns modified text */
15
+ handle: (text: string) => string;
16
+ /** Priority (lower runs first). Built-in priorities: 0-100. Default: 100 */
17
+ priority?: number;
18
+ }
1
19
  /**
2
20
  * Configuration options for the remend function.
3
21
  * All options default to `true` when not specified.
@@ -8,6 +26,12 @@ interface RemendOptions {
8
26
  links?: boolean;
9
27
  /** Complete images (e.g., `![alt](url` → removed) */
10
28
  images?: boolean;
29
+ /**
30
+ * How to handle incomplete links:
31
+ * - `'protocol'`: Use `streamdown:incomplete-link` placeholder URL (default)
32
+ * - `'text-only'`: Display only the link text without any link markup
33
+ */
34
+ linkMode?: "protocol" | "text-only";
11
35
  /** Complete bold formatting (e.g., `**text` → `**text**`) */
12
36
  bold?: boolean;
13
37
  /** Complete italic formatting (e.g., `*text` → `*text*` or `_text` → `_text_`) */
@@ -22,7 +46,9 @@ interface RemendOptions {
22
46
  katex?: boolean;
23
47
  /** Handle incomplete setext headings to prevent misinterpretation */
24
48
  setextHeadings?: boolean;
49
+ /** Custom handlers to extend remend */
50
+ handlers?: RemendHandler[];
25
51
  }
26
52
  declare const remend: (text: string, options?: RemendOptions) => string;
27
53
 
28
- export { type RemendOptions, remend as default };
54
+ export { type LinkMode, type RemendHandler, type RemendOptions, remend as default, isWithinCodeBlock, isWithinLinkOrImageUrl, isWithinMathBlock, isWordChar };
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
- var p=/(\*\*)([^*]*?)$/,I=/(__)([^_]*?)$/,P=/(\*\*\*)([^*]*?)$/,B=/(\*)([^*]*?)$/,$=/(_)([^_]*?)$/,M=/(`)([^`]*?)$/,A=/(~~)([^~]*?)$/,c=/^[\s_~*`]*$/,k=/^[\s]*[-*+][\s]+$/,C=/[\p{L}\p{N}_]/u,S=/^```[^`\n]*```?$/,_=/^\*{4,}$/;var a=n=>{if(!n)return false;let r=n.charCodeAt(0);return r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===95?true:C.test(n)},g=(n,r)=>{let e=false;for(let s=0;s<r;s+=1)n[s]==="`"&&n[s+1]==="`"&&n[s+2]==="`"&&(e=!e,s+=2);return e},O=(n,r)=>{let e=1;for(let s=r-1;s>=0;s-=1)if(n[s]==="]")e+=1;else if(n[s]==="["&&(e-=1,e===0))return s;return -1},T=(n,r)=>{let e=1;for(let s=r+1;s<n.length;s+=1)if(n[s]==="[")e+=1;else if(n[s]==="]"&&(e-=1,e===0))return s;return -1},d=(n,r)=>{let e=false,s=false;for(let i=0;i<n.length&&i<r;i+=1){if(n[i]==="\\"&&n[i+1]==="$"){i+=1;continue}n[i]==="$"&&(n[i+1]==="$"?(s=!s,i+=1,e=false):s||(e=!e));}return e||s},z=(n,r)=>{for(let e=r;e<n.length;e+=1){if(n[e]===")")return true;if(n[e]===`
2
- `)return false}return false},b=(n,r)=>{for(let e=r-1;e>=0;e-=1){if(n[e]===")")return false;if(n[e]==="(")return e>0&&n[e-1]==="]"?z(n,r):false;if(n[e]===`
3
- `)return false}return false},h=(n,r,e)=>{let s=0;for(let o=r-1;o>=0;o-=1)if(n[o]===`
4
- `){s=o+1;break}let i=n.length;for(let o=r;o<n.length;o+=1)if(n[o]===`
5
- `){i=o;break}let l=n.substring(s,i),t=0,f=false;for(let o of l)if(o===e)t+=1;else if(o!==" "&&o!==" "){f=true;break}return t>=3&&!f};var Q=(n,r,e)=>{if(e!==" "&&e!==" ")return false;let s=0;for(let i=r-1;i>=0;i-=1)if(n[i]===`
6
- `){s=i+1;break}for(let i=s;i<r;i+=1)if(n[i]!==" "&&n[i]!==" ")return false;return true},Y=(n,r,e,s)=>e==="\\"||n.includes("$")&&d(n,r)?true:e!=="*"&&s==="*"?(r<n.length-2?n[r+2]:"")!=="*":!!(e==="*"||e&&s&&a(e)&&a(s)||Q(n,r,s)),U=n=>{let r=0,e=n.length;for(let s=0;s<e;s+=1){if(n[s]!=="*")continue;let i=s>0?n[s-1]:"",l=s<e-1?n[s+1]:"";Y(n,s,i,l)||(r+=1);}return r},j=(n,r,e,s)=>!!(e==="\\"||n.includes("$")&&d(n,r)||b(n,r)||e==="_"||s==="_"||e&&s&&a(e)&&a(s)),q=n=>{let r=0,e=n.length;for(let s=0;s<e;s+=1){if(n[s]!=="_")continue;let i=s>0?n[s-1]:"",l=s<e-1?n[s+1]:"";j(n,s,i,l)||(r+=1);}return r},G=n=>{let r=0,e=0;for(let s=0;s<n.length;s+=1)n[s]==="*"?e+=1:(e>=3&&(r+=Math.floor(e/3)),e=0);return e>=3&&(r+=Math.floor(e/3)),r},J=(n,r,e)=>{if(!r||c.test(r))return true;let i=n.substring(0,e).lastIndexOf(`
7
- `),l=i===-1?0:i+1,t=n.substring(l,e);return k.test(t)&&r.includes(`
8
- `)?true:h(n,e,"*")},N=n=>{let r=n.match(p);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return g(n,s)||J(n,e,s)?n:(n.match(/\*\*/g)||[]).length%2===1?`${n}**`:n},V=(n,r,e)=>{if(!r||c.test(r))return true;let i=n.substring(0,e).lastIndexOf(`
9
- `),l=i===-1?0:i+1,t=n.substring(l,e);return k.test(t)&&r.includes(`
10
- `)?true:h(n,e,"_")},w=n=>{let r=n.match(I);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return g(n,s)||V(n,e,s)?n:(n.match(/__/g)||[]).length%2===1?`${n}__`:n},X=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="*"&&n[r-1]!=="*"&&n[r+1]!=="*"&&n[r-1]!=="\\"&&!d(n,r)){let e=r>0?n[r-1]:"",s=r<n.length-1?n[r+1]:"";if(e&&s&&a(e)&&a(s))continue;return r}return -1},L=n=>{if(!n.match(B))return n;let e=X(n);if(e===-1||g(n,e))return n;let s=n.substring(e+1);return !s||c.test(s)?n:U(n)%2===1?`${n}*`:n},W=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="_"&&n[r-1]!=="_"&&n[r+1]!=="_"&&n[r-1]!=="\\"&&!d(n,r)&&!b(n,r)){let e=r>0?n[r-1]:"",s=r<n.length-1?n[r+1]:"";if(e&&s&&a(e)&&a(s))continue;return r}return -1},Z=n=>{let r=n.length;for(;r>0&&n[r-1]===`
11
- `;)r-=1;if(r<n.length){let e=n.slice(0,r),s=n.slice(r);return `${e}_${s}`}return `${n}_`},x=n=>{if(!n.endsWith("**"))return null;let r=n.slice(0,-2);if((r.match(/\*\*/g)||[]).length%2!==1)return null;let s=r.indexOf("**"),i=W(r);return s!==-1&&i!==-1&&s<i?`${r}_**`:null},R=n=>{if(!n.match($))return n;let e=W(n);if(e===-1||g(n,e))return n;let s=n.substring(e+1);if(!s||c.test(s))return n;if(q(n)%2===1){let l=x(n);return l!==null?l:Z(n)}return n},nn=n=>{let r=(n.match(/\*\*/g)||[]).length,e=U(n);return r%2===0&&e%2===0},rn=(n,r,e)=>!r||c.test(r)||g(n,e)?true:h(n,e,"*"),E=n=>{if(_.test(n))return n;let r=n.match(P);if(!r)return n;let e=r[2],s=n.lastIndexOf(r[1]);return rn(n,e,s)?n:G(n)%2===1?nn(n)?n:`${n}***`:n};var m=(n,r)=>{let e=false,s=false;for(let i=0;i<r;i+=1){if(n.substring(i,i+3)==="```"){s=!s,i+=2;continue}!s&&n[i]==="`"&&(e=!e);}return e||s},en=(n,r)=>{let e=n.substring(r,r+3)==="```",s=r>0&&n.substring(r-1,r+2)==="```",i=r>1&&n.substring(r-2,r+1)==="```";return e||s||i},H=n=>{let r=0;for(let e=0;e<n.length;e+=1)n[e]==="`"&&!en(n,e)&&(r+=1);return r};var sn=n=>!n.match(S)||n.includes(`
12
- `)?null:n.endsWith("``")&&!n.endsWith("```")?`${n}\``:n,tn=n=>(n.match(/```/g)||[]).length%2===1,D=n=>{let r=sn(n);if(r!==null)return r;let e=n.match(M);if(e&&!tn(n)){let s=e[2];if(!s||c.test(s))return n;if(H(n)%2===1)return `${n}\``}return n};var ln=(n,r)=>r>=2&&n.substring(r-2,r+1)==="```"||r>=1&&n.substring(r-1,r+2)==="```"||r<=n.length-3&&n.substring(r,r+3)==="```",on=n=>{let r=0,e=false;for(let s=0;s<n.length-1;s+=1)n[s]==="`"&&!ln(n,s)&&(e=!e),!e&&n[s]==="$"&&n[s+1]==="$"&&(r+=1,s+=1);return r},cn=n=>{let r=n.indexOf("$$");return r!==-1&&n.indexOf(`
1
+ var rn=Object.defineProperty,en=Object.defineProperties;var tn=Object.getOwnPropertyDescriptors;var T=Object.getOwnPropertySymbols;var sn=Object.prototype.hasOwnProperty,on=Object.prototype.propertyIsEnumerable;var S=(n,r,e)=>r in n?rn(n,r,{enumerable:true,configurable:true,writable:true,value:e}):n[r]=e,b=(n,r)=>{for(var e in r||(r={}))sn.call(r,e)&&S(n,e,r[e]);if(T)for(var e of T(r))on.call(r,e)&&S(n,e,r[e]);return n},I=(n,r)=>en(n,tn(r));var _=/(\*\*)([^*]*\*?)$/,L=/(__)([^_]*?)$/,E=/(\*\*\*)([^*]*?)$/,O=/(\*)([^*]*?)$/,U=/(_)([^_]*?)$/,y=/(`)([^`]*?)$/,N=/(~~)([^~]*?)$/,u=/^[\s_~*`]*$/,A=/^[\s]*[-*+][\s]+$/,R=/[\p{L}\p{N}_]/u,D=/^```[^`\n]*```?$/,H=/^\*{4,}$/;var W=/(__)([^_]+)_$/,K=/(~~)([^~]+)~$/,w=/__/g,P=/~~/g;var f=n=>{if(!n)return false;let r=n.charCodeAt(0);return r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===95?true:R.test(n)},d=(n,r)=>{let e=false;for(let i=0;i<r;i+=1)n[i]==="`"&&n[i+1]==="`"&&n[i+2]==="`"&&(e=!e,i+=2);return e},G=(n,r)=>{let e=1;for(let i=r-1;i>=0;i-=1)if(n[i]==="]")e+=1;else if(n[i]==="["&&(e-=1,e===0))return i;return -1},B=(n,r)=>{let e=1;for(let i=r+1;i<n.length;i+=1)if(n[i]==="[")e+=1;else if(n[i]==="]"&&(e-=1,e===0))return i;return -1},g=(n,r)=>{let e=false,i=false;for(let t=0;t<n.length&&t<r;t+=1){if(n[t]==="\\"&&n[t+1]==="$"){t+=1;continue}n[t]==="$"&&(n[t+1]==="$"?(i=!i,t+=1,e=false):i||(e=!e));}return e||i},ln=(n,r)=>{for(let e=r;e<n.length;e+=1){if(n[e]===")")return true;if(n[e]===`
2
+ `)return false}return false},p=(n,r)=>{for(let e=r-1;e>=0;e-=1){if(n[e]===")")return false;if(n[e]==="(")return e>0&&n[e-1]==="]"?ln(n,r):false;if(n[e]===`
3
+ `)return false}return false},k=(n,r,e)=>{let i=0;for(let s=r-1;s>=0;s-=1)if(n[s]===`
4
+ `){i=s+1;break}let t=n.length;for(let s=r;s<n.length;s+=1)if(n[s]===`
5
+ `){t=s;break}let o=n.substring(i,t),a=0,l=false;for(let s of o)if(s===e)a+=1;else if(s!==" "&&s!==" "){l=true;break}return a>=3&&!l};var an=(n,r,e)=>{if(e!==" "&&e!==" ")return false;let i=0;for(let t=r-1;t>=0;t-=1)if(n[t]===`
6
+ `){i=t+1;break}for(let t=i;t<r;t+=1)if(n[t]!==" "&&n[t]!==" ")return false;return true},cn=(n,r,e,i)=>e==="\\"||n.includes("$")&&g(n,r)?true:e!=="*"&&i==="*"?(r<n.length-2?n[r+2]:"")!=="*":!!(e==="*"||e&&i&&f(e)&&f(i)||an(n,r,i)),F=n=>{let r=0,e=n.length;for(let i=0;i<e;i+=1){if(n[i]!=="*")continue;let t=i>0?n[i-1]:"",o=i<e-1?n[i+1]:"";cn(n,i,t,o)||(r+=1);}return r},un=(n,r,e,i)=>!!(e==="\\"||n.includes("$")&&g(n,r)||p(n,r)||e==="_"||i==="_"||e&&i&&f(e)&&f(i)),fn=n=>{let r=0,e=n.length;for(let i=0;i<e;i+=1){if(n[i]!=="_")continue;let t=i>0?n[i-1]:"",o=i<e-1?n[i+1]:"";un(n,i,t,o)||(r+=1);}return r},dn=n=>{let r=0,e=0;for(let i=0;i<n.length;i+=1)n[i]==="*"?e+=1:(e>=3&&(r+=Math.floor(e/3)),e=0);return e>=3&&(r+=Math.floor(e/3)),r},gn=(n,r,e)=>{if(!r||u.test(r))return true;let t=n.substring(0,e).lastIndexOf(`
7
+ `),o=t===-1?0:t+1,a=n.substring(o,e);return A.test(a)&&r.includes(`
8
+ `)?true:k(n,e,"*")},X=n=>{let r=n.match(_);if(!r)return n;let e=r[2],i=n.lastIndexOf(r[1]);return d(n,i)||gn(n,e,i)?n:(n.match(/\*\*/g)||[]).length%2===1?e.endsWith("*")?`${n}*`:`${n}**`:n},hn=(n,r,e)=>{if(!r||u.test(r))return true;let t=n.substring(0,e).lastIndexOf(`
9
+ `),o=t===-1?0:t+1,a=n.substring(o,e);return A.test(a)&&r.includes(`
10
+ `)?true:k(n,e,"_")},v=n=>{let r=n.match(L);if(!r){let o=n.match(W);if(o){let a=n.lastIndexOf(o[1]);if(!d(n,a)&&(n.match(w)||[]).length%2===1)return `${n}_`}return n}let e=r[2],i=n.lastIndexOf(r[1]);return d(n,i)||hn(n,e,i)?n:(n.match(/__/g)||[]).length%2===1?`${n}__`:n},mn=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="*"&&n[r-1]!=="*"&&n[r+1]!=="*"&&n[r-1]!=="\\"&&!g(n,r)){let e=r>0?n[r-1]:"",i=r<n.length-1?n[r+1]:"";if(e&&i&&f(e)&&f(i))continue;return r}return -1},Y=n=>{if(!n.match(O))return n;let e=mn(n);if(e===-1||d(n,e))return n;let i=n.substring(e+1);return !i||u.test(i)?n:F(n)%2===1?`${n}*`:n},j=n=>{for(let r=0;r<n.length;r+=1)if(n[r]==="_"&&n[r-1]!=="_"&&n[r+1]!=="_"&&n[r-1]!=="\\"&&!g(n,r)&&!p(n,r)){let e=r>0?n[r-1]:"",i=r<n.length-1?n[r+1]:"";if(e&&i&&f(e)&&f(i))continue;return r}return -1},pn=n=>{let r=n.length;for(;r>0&&n[r-1]===`
11
+ `;)r-=1;if(r<n.length){let e=n.slice(0,r),i=n.slice(r);return `${e}_${i}`}return `${n}_`},kn=n=>{if(!n.endsWith("**"))return null;let r=n.slice(0,-2);if((r.match(/\*\*/g)||[]).length%2!==1)return null;let i=r.indexOf("**"),t=j(r);return i!==-1&&t!==-1&&i<t?`${r}_**`:null},z=n=>{if(!n.match(U))return n;let e=j(n);if(e===-1||d(n,e))return n;let i=n.substring(e+1);if(!i||u.test(i))return n;if(fn(n)%2===1){let o=kn(n);return o!==null?o:pn(n)}return n},bn=n=>{let r=(n.match(/\*\*/g)||[]).length,e=F(n);return r%2===0&&e%2===0},In=(n,r,e)=>!r||u.test(r)||d(n,e)?true:k(n,e,"*"),Q=n=>{if(H.test(n))return n;let r=n.match(E);if(!r)return n;let e=r[2],i=n.lastIndexOf(r[1]);return In(n,e,i)?n:dn(n)%2===1?bn(n)?n:`${n}***`:n};var h=(n,r)=>{let e=false,i=false;for(let t=0;t<r;t+=1){if(n.substring(t,t+3)==="```"){i=!i,t+=2;continue}!i&&n[t]==="`"&&(e=!e);}return e||i},An=(n,r)=>{let e=n.substring(r,r+3)==="```",i=r>0&&n.substring(r-1,r+2)==="```",t=r>1&&n.substring(r-2,r+1)==="```";return e||i||t},q=n=>{let r=0;for(let e=0;e<n.length;e+=1)n[e]==="`"&&!An(n,e)&&(r+=1);return r};var Pn=n=>!n.match(D)||n.includes(`
12
+ `)?null:n.endsWith("``")&&!n.endsWith("```")?`${n}\``:n,Bn=n=>(n.match(/```/g)||[]).length%2===1,J=n=>{let r=Pn(n);if(r!==null)return r;let e=n.match(y);if(e&&!Bn(n)){let i=e[2];if(!i||u.test(i))return n;if(q(n)%2===1)return `${n}\``}return n};var Cn=(n,r)=>r>=2&&n.substring(r-2,r+1)==="```"||r>=1&&n.substring(r-1,r+2)==="```"||r<=n.length-3&&n.substring(r,r+3)==="```",$n=n=>{let r=0,e=false;for(let i=0;i<n.length-1;i+=1)n[i]==="`"&&!Cn(n,i)&&(e=!e),!e&&n[i]==="$"&&n[i+1]==="$"&&(r+=1,i+=1);return r},Mn=n=>{let r=n.indexOf("$$");return r!==-1&&n.indexOf(`
13
13
  `,r)!==-1&&!n.endsWith(`
14
14
  `)?`${n}
15
- $$`:`${n}$$`},F=n=>on(n)%2===0?n:cn(n);var an=(n,r)=>{if(n.substring(r+2).includes(")"))return null;let s=O(n,r);if(s===-1||m(n,s))return null;let i=s>0&&n[s-1]==="!",l=i?s-1:s,t=n.substring(0,l);if(i)return t;let f=n.substring(s+1,r);return `${t}[${f}](streamdown:incomplete-link)`},un=(n,r)=>{let e=r>0&&n[r-1]==="!",s=e?r-1:r;if(!n.substring(r+1).includes("]")){let t=n.substring(0,s);return e?t:`${n}](streamdown:incomplete-link)`}if(T(n,r)===-1){let t=n.substring(0,s);return e?t:`${n}](streamdown:incomplete-link)`}return null},v=n=>{let r=n.lastIndexOf("](");if(r!==-1&&!m(n,r)){let e=an(n,r);if(e!==null)return e}for(let e=n.length-1;e>=0;e-=1)if(n[e]==="["&&!m(n,e)){let s=un(n,e);if(s!==null)return s}return n};var fn=/^-{1,2}$/,gn=/^[\s]*-{1,2}[\s]+$/,dn=/^={1,2}$/,hn=/^[\s]*={1,2}[\s]+$/,K=n=>{if(!n||typeof n!="string")return n;let r=n.lastIndexOf(`
16
- `);if(r===-1)return n;let e=n.substring(r+1),s=n.substring(0,r),i=e.trim();if(fn.test(i)&&!e.match(gn)){let t=s.split(`
17
- `).at(-1);if(t&&t.trim().length>0)return `${n}\u200B`}if(dn.test(i)&&!e.match(hn)){let t=s.split(`
18
- `).at(-1);if(t&&t.trim().length>0)return `${n}\u200B`}return n};var y=n=>{let r=n.match(A);if(r){let e=r[2];if(!e||c.test(e))return n;if((n.match(/~~/g)||[]).length%2===1)return `${n}~~`}return n};var u=n=>n!==false,mn=(n,r)=>{if(!n||typeof n!="string")return n;let e=n.endsWith(" ")&&!n.endsWith(" ")?n.slice(0,-1):n;if(u(r==null?void 0:r.setextHeadings)&&(e=K(e)),u(r==null?void 0:r.links)||u(r==null?void 0:r.images)){let s=v(e);if(s.endsWith("](streamdown:incomplete-link)"))return s;e=s;}return u(r==null?void 0:r.boldItalic)&&(e=E(e)),u(r==null?void 0:r.bold)&&(e=N(e)),u(r==null?void 0:r.italic)&&(e=w(e),e=L(e),e=R(e)),u(r==null?void 0:r.inlineCode)&&(e=D(e)),u(r==null?void 0:r.strikethrough)&&(e=y(e)),u(r==null?void 0:r.katex)&&(e=F(e)),e},Fn=mn;export{Fn as default};
15
+ $$`:`${n}$$`},V=n=>$n(n)%2===0?n:Mn(n);var Tn=(n,r,e)=>{if(n.substring(r+2).includes(")"))return null;let t=G(n,r);if(t===-1||h(n,t))return null;let o=t>0&&n[t-1]==="!",a=o?t-1:t,l=n.substring(0,a);if(o)return l;let s=n.substring(t+1,r);return e==="text-only"?`${l}${s}`:`${l}[${s}](streamdown:incomplete-link)`},Z=(n,r)=>{for(let e=0;e<=r;e++)if(n[e]==="["&&!h(n,e)){if(e>0&&n[e-1]==="!")continue;let i=B(n,e);if(i===-1)return e;if(i+1<n.length&&n[i+1]==="("){let t=n.indexOf(")",i+2);t!==-1&&(e=t);}}return -1},Sn=(n,r,e)=>{let i=r>0&&n[r-1]==="!",t=i?r-1:r,o=n.substring(r+1);if(!o.includes("]")){let l=n.substring(0,t);if(i)return l;if(e==="text-only"){let s=Z(n,r);return s!==-1?n.substring(0,s)+n.substring(s+1):`${l}${o}`}return `${n}](streamdown:incomplete-link)`}if(B(n,r)===-1){let l=n.substring(0,t);if(i)return l;if(e==="text-only"){let s=Z(n,r);if(s!==-1)return n.substring(0,s)+n.substring(s+1);let m=n.substring(r+1);return `${l}${m}`}return `${n}](streamdown:incomplete-link)`}return null},C=(n,r="protocol")=>{let e=n.lastIndexOf("](");if(e!==-1&&!h(n,e)){let i=Tn(n,e,r);if(i!==null)return i}for(let i=n.length-1;i>=0;i-=1)if(n[i]==="["&&!h(n,i)){let t=Sn(n,i,r);if(t!==null)return t}return n};var _n=/^-{1,2}$/,Ln=/^[\s]*-{1,2}[\s]+$/,En=/^={1,2}$/,On=/^[\s]*={1,2}[\s]+$/,x=n=>{if(!n||typeof n!="string")return n;let r=n.lastIndexOf(`
16
+ `);if(r===-1)return n;let e=n.substring(r+1),i=n.substring(0,r),t=e.trim();if(_n.test(t)&&!e.match(Ln)){let a=i.split(`
17
+ `).at(-1);if(a&&a.trim().length>0)return `${n}\u200B`}if(En.test(t)&&!e.match(On)){let a=i.split(`
18
+ `).at(-1);if(a&&a.trim().length>0)return `${n}\u200B`}return n};var nn=n=>{let r=n.match(N);if(r){let e=r[2];if(!e||u.test(e))return n;if((n.match(P)||[]).length%2===1)return `${n}~~`}else if(n.match(K)&&(n.match(P)||[]).length%2===1)return `${n}~`;return n};var $=n=>n!==false,c={SETEXT_HEADINGS:0,LINKS:10,BOLD_ITALIC:20,BOLD:30,ITALIC_DOUBLE_UNDERSCORE:40,ITALIC_SINGLE_ASTERISK:41,ITALIC_SINGLE_UNDERSCORE:42,INLINE_CODE:50,STRIKETHROUGH:60,KATEX:70,DEFAULT:100},Un=[{handler:{name:"setextHeadings",handle:x,priority:c.SETEXT_HEADINGS},optionKey:"setextHeadings"},{handler:{name:"links",handle:C,priority:c.LINKS},optionKey:"links",earlyReturn:n=>n.endsWith("](streamdown:incomplete-link)")},{handler:{name:"boldItalic",handle:Q,priority:c.BOLD_ITALIC},optionKey:"boldItalic"},{handler:{name:"bold",handle:X,priority:c.BOLD},optionKey:"bold"},{handler:{name:"italicDoubleUnderscore",handle:v,priority:c.ITALIC_DOUBLE_UNDERSCORE},optionKey:"italic"},{handler:{name:"italicSingleAsterisk",handle:Y,priority:c.ITALIC_SINGLE_ASTERISK},optionKey:"italic"},{handler:{name:"italicSingleUnderscore",handle:z,priority:c.ITALIC_SINGLE_UNDERSCORE},optionKey:"italic"},{handler:{name:"inlineCode",handle:J,priority:c.INLINE_CODE},optionKey:"inlineCode"},{handler:{name:"strikethrough",handle:nn,priority:c.STRIKETHROUGH},optionKey:"strikethrough"},{handler:{name:"katex",handle:V,priority:c.KATEX},optionKey:"katex"}],yn=n=>{var e;let r=(e=n==null?void 0:n.linkMode)!=null?e:"protocol";return Un.filter(({handler:i,optionKey:t})=>i.name==="links"?$(n==null?void 0:n.links)||$(n==null?void 0:n.images):$(n==null?void 0:n[t])).map(({handler:i,earlyReturn:t})=>i.name==="links"?{handler:I(b({},i),{handle:o=>C(o,r)}),earlyReturn:r==="protocol"?t:void 0}:{handler:i,earlyReturn:t})},Nn=(n,r)=>{var a;if(!n||typeof n!="string")return n;let e=n.endsWith(" ")&&!n.endsWith(" ")?n.slice(0,-1):n,i=yn(r),t=((a=r==null?void 0:r.handlers)!=null?a:[]).map(l=>{var s;return {handler:I(b({},l),{priority:(s=l.priority)!=null?s:c.DEFAULT}),earlyReturn:void 0}}),o=[...i,...t].sort((l,s)=>{var m,M;return ((m=l.handler.priority)!=null?m:c.DEFAULT)-((M=s.handler.priority)!=null?M:c.DEFAULT)});for(let{handler:l,earlyReturn:s}of o)if(e=l.handle(e),s!=null&&s(e))return e;return e},sr=Nn;export{sr as default,d as isWithinCodeBlock,p as isWithinLinkOrImageUrl,g as isWithinMathBlock,f as isWordChar};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@janhq/remend",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -35,6 +35,7 @@
35
35
  "description": "Self-healing markdown. Intelligently parses and styles incomplete Markdown blocks.",
36
36
  "devDependencies": {
37
37
  "@vitest/coverage-v8": "^4.0.15",
38
+ "mdast-util-from-markdown": "^2.0.2",
38
39
  "tsup": "^8.5.1",
39
40
  "vitest": "^4.0.15"
40
41
  }