@aiquants/markdown 6.4.1 → 7.0.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
@@ -57,7 +57,8 @@ export MARKDOWN_API_BINARY=/path/to/markdown-api
57
57
 
58
58
  | 変数 | 既定値 | 用途 |
59
59
  | --- | --- | --- |
60
- | `MARKDOWN_SOCKET_PATH` | `/tmp/markdown.sock` | サービスと通信する UNIX ドメインソケットのパス |
60
+ | `MARKDOWN_SOCKET_PATH` | (必須) | サービスと通信する UNIX ドメインソケットのパス (サービスも同じ変数を読む)。未設定か空なら `parseMarkdown` は変数を名指して失敗し、サービスは起動しない (パスを推し量らない) |
61
+ | `MARKDOWN_SOCKET_MODE` | `0600` | サービスのソケットの権限。`0600` (所有者のみ) か `0660` (所有者とグループ) だけで、ほかの値ではサービスが値を名指して起動しない (ソケットの上では何も認証しないため、ほかの利用者へは開かない) |
61
62
  | `MARKDOWN_API_BINARY` | (なし) | 自前ビルドしたバイナリの明示指定 |
62
63
  | `MARKDOWN_API_STARTUP_TIMEOUT_MS` | `10000` | 自動起動したサービスが待ち受け開始するまでの猶予 |
63
64
  | `MARKDOWN_MAX_SOURCE_BYTES` | `8388608` (8 MiB) | サービスが受け付ける Markdown の本文の最大 (`@import` で取り込んだ分を含む) |
Binary file
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("./errors-BW5JXRoX.cjs"),p=require("./linkCards-Bjd_vW39.cjs"),w=require("./simple-logger-9yf7ypyB.cjs"),Te=require("node:dns/promises"),O=require("node:net"),x=require("undici"),be=require("htmlparser2"),Ee=require("node:child_process"),R=require("node:fs"),Se=require("node:module"),_e=require("node:path"),ye=require("node:url"),U=require("@connectrpc/connect"),ie=require("@connectrpc/connect-node"),u=require("@bufbuild/protobuf");var H=typeof document<"u"?document.currentScript:null;function le(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const ce=le(O),P=le(_e),ve=[[[0],8],[[10],8],[[100,64],10],[[127],8],[[169,254],16],[[172,16],12],[[192,0,0],24],[[192,0,2],24],[[192,168],16],[[198,18],15],[[198,51,100],24],[[203,0,113],24],[[224],4],[[240],4]],Ae=[[[100,65435],32],[[0,0,0,0,65535,0],96],[[256,0,0,0],64],[[256,0,0,1],64],[[8193,0],32],[[8193,2,0],48],[[8193,3512],32],[[8194],16],[[16383],20],[[24320],16],[[64512],7],[[65152],10],[[65216],10],[[65280],8]],S=new O.BlockList;for(const[r,t]of ve){const e=[...r,0,0,0].slice(0,4).join(".");S.addSubnet(e,t,"ipv4"),S.addSubnet(`::ffff:${e}`,96+t,"ipv6"),S.addSubnet(`::${e}`,96+t,"ipv6")}for(const[r,t]of Ae)S.addSubnet(`${r.map(e=>e.toString(16)).join(":")}::`,t,"ipv6");const K=r=>{const t=r.replace(/^\[/u,"").replace(/\]$/u,"").replace(/%.*$/su,""),e=O.isIP(t);return e!==0&&S.check(t,e===4?"ipv4":"ipv6")},ue="ERR_LINK_CARD_PRIVATE_ADDRESS",Q=Object.freeze({timeoutMs:1e3,tries:2}),ee=new Te.Resolver({timeout:Q.timeoutMs,tries:Q.tries}),te=(r,t)=>({error:Object.assign(new Error(`Blocked hostname resolving to a private address: ${r} -> ${t}`),{code:ue})}),Le=async(r,t)=>{const e=O.isIP(r);if(e!==0)return K(r)?te(r,r):{error:null,family:e===4?4:6,addresses:[r]};const[n,o]=await Promise.allSettled([t===6?Promise.resolve([]):ee.resolve4(r),t===4?Promise.resolve([]):ee.resolve6(r)]),s=n.status==="fulfilled"?n.value:[],a=o.status==="fulfilled"?o.value:[],i=[...s,...a].find(M=>K(M));if(i!==void 0)return te(r,i);const[l,...c]=s;if(l!==void 0)return{error:null,family:4,addresses:[l,...c]};const[f,...y]=a;return f!==void 0?{error:null,family:6,addresses:[f,...y]}:n.status==="rejected"?{error:n.reason}:o.status==="rejected"?{error:o.reason}:{error:Object.assign(new Error(`No address for ${r}`),{code:"ENOTFOUND"})}},Re=(r,t,e)=>{const n=t.family===4||t.family==="IPv4"?4:t.family===6||t.family==="IPv6"?6:0;Le(r,n).then(o=>{if(o.error!==null){e(o.error,"");return}const{family:s,addresses:a}=o;t.all===!0?e(null,a.map(i=>({address:i,family:s}))):e(null,a[0],s)})},Ce=new Set(["127.0.0.1","0.0.0.0","[::1]"]),Oe=[".local",".internal",".home.arpa"],z=(r,t)=>{let e;try{e=new URL(r)}catch{return{ok:!1,reason:"forbidden-url",detail:"Invalid URL"}}if(e.protocol!=="http:"&&e.protocol!=="https:")return{ok:!1,reason:"forbidden-url",detail:"Only http(s) URLs are allowed"};if(e.username!==""||e.password!=="")return{ok:!1,reason:"forbidden-url",detail:"URLs with a user name or password are not allowed"};e.hash="";const n=e.hostname.replace(/\.+$/u,"");return n==="localhost"||n.endsWith(".localhost")||Ce.has(n)?{ok:!1,reason:"private-network",detail:"Localhost access is not allowed"}:K(n)?{ok:!1,reason:"private-network",detail:"Private network access is not allowed"}:!(n.startsWith("[")||n.includes("."))||Oe.some(s=>n.endsWith(s))?{ok:!1,reason:"private-network",detail:"Internal domain access is not allowed"}:{ok:!0,href:e.href}},de=r=>{let t;try{t=new URL(r)}catch{return"(unparsable URL)"}return t.protocol!=="http:"&&t.protocol!=="https:"?`(a ${t.protocol} URL)`:(t.username="",t.password="",t.href)},fe=1024,Me=/^[\t\n\f\r ]$/u,g=r=>Me.test(r),$=r=>r.replace(/[A-Z]/gu,t=>t.toLowerCase()),q=r=>{try{return new TextDecoder(r).encoding}catch{return null}},Ie=r=>r[0]===239&&r[1]===187&&r[2]===191?"utf-8":r[0]===254&&r[1]===255?"utf-16be":r[0]===255&&r[1]===254?"utf-16le":null,Pe=r=>{for(const t of r.split(";").slice(1)){const e=t.indexOf("=");if(e!==-1&&t.slice(0,e).trim().toLowerCase()==="charset")return t.slice(e+1).trim().replace(/^"(.*)"$/su,"$1")}return null},xe=r=>{let t=0;for(;;){const e=r.indexOf("charset",t);if(e===-1)return null;let n=e+7;for(;g(r.charAt(n));)n+=1;if(r.charAt(n)!=="="){t=n;continue}for(n+=1;g(r.charAt(n));)n+=1;const o=r.charAt(n);if(o==='"'||o==="'"){const a=r.indexOf(o,n+1);return a===-1?null:r.slice(n+1,a)}const s=r.slice(n).search(/[\t\n\f\r ;]/u);return s===-1?r.slice(n):r.slice(n,n+s)}},me=(r,t)=>{let e=t;for(;g(r.charAt(e))||r.charAt(e)==="/";)e+=1;if(r.charAt(e)===">"||e>=r.length)return{attribute:null,end:e};let n="";for(;;){const a=r.charAt(e);if(a==="")return{attribute:null,end:e};if(a==="="&&n!=="")break;if(g(a)){for(;g(r.charAt(e));)e+=1;if(r.charAt(e)!=="=")return{attribute:{name:n,value:""},end:e};break}if(a==="/"||a===">")return{attribute:{name:n,value:""},end:e};n+=$(a),e+=1}for(e+=1;g(r.charAt(e));)e+=1;const o=r.charAt(e);if(o==='"'||o==="'"){const a=r.indexOf(o,e+1);return a===-1?{attribute:null,end:r.length}:{attribute:{name:n,value:$(r.slice(e+1,a))},end:a+1}}if(o===">")return{attribute:{name:n,value:""},end:e};const s=r.slice(e).search(/[\t\n\f\r >]/u);return s===-1?{attribute:null,end:r.length}:{attribute:{name:n,value:$(r.slice(e,e+s))},end:e+s}},Ne=(r,t)=>{const e=new Set;let n=!1,o=null,s=null,a=t;for(;;){const{attribute:i,end:l}=me(r,a);if(a=l,i===null)break;if(!e.has(i.name))if(e.add(i.name),i.name==="http-equiv")n=i.value==="content-type";else if(i.name==="content"){const c=xe(i.value),f=c===null?null:q(c);f!==null&&s===null&&(s=f,o=!0)}else i.name==="charset"&&(s=q(i.value)??!1,o=!1)}return o===null||typeof s!="string"||o&&!n?{encoding:null,end:a}:s==="utf-16be"||s==="utf-16le"?{encoding:"utf-8",end:a}:{encoding:s==="x-user-defined"?"windows-1252":s,end:a}},De=r=>{const t=Array.from(r.subarray(0,fe),n=>String.fromCharCode(n)).join("");let e=0;for(;e<t.length;)if(t.startsWith("<!--",e)){const n=t.indexOf("-->",e+2);if(n===-1)return null;e=n+3}else if(/^<meta[\t\n\f\r /]$/iu.test(t.slice(e,e+6))){const{encoding:n,end:o}=Ne(t,e+5);if(n!==null)return n;e=o+1}else if(/^<\/?[A-Za-z]/u.test(t.slice(e,e+3))){let n=e+1;for(;n<t.length&&!g(t.charAt(n))&&t.charAt(n)!==">";)n+=1;for(;;){const o=me(t,n);if(n=o.end,o.attribute===null)break}e=n+1}else if(/^<[!/?]$/u.test(t.slice(e,e+2))){const n=t.indexOf(">",e+1);if(n===-1)return null;e=n+1}else e+=1;return null},Be=(r,t)=>{const e=Ie(r);if(e!==null)return e;const n=Pe(t),o=n===null?null:q(n);return o!==null?o:De(r)??"utf-8"},Ue=(r,t)=>{const e=new Uint8Array(t);let n=0;for(const o of r)e.set(o,n),n+=o.byteLength;return e},He=r=>{const t=[];let e=0,n=null;const o=()=>{const s=Ue(t,e);t.length=0;const a=new TextDecoder(Be(s,r));return n=a,{started:a,text:a.decode(s,{stream:!0})}};return{write:s=>n!==null?n.decode(s,{stream:!0}):(t.push(s),e+=s.byteLength,e<fe?"":o().text),end:()=>{if(n!==null)return n.decode();const{started:s,text:a}=o();return a+s.decode()}}},$e=(r,t,e)=>{const n=new Map,o=new Map;return s=>{const a=n.get(s);if(a!==void 0&&a.expireAt>e())return Promise.resolve(a.value);const i=o.get(s);if(i!==void 0)return i;const l=r(s).then(c=>(!n.has(s)&&n.size>=t.maxEntries&&n.delete(n.keys().next().value),n.set(s,{value:c,expireAt:e()+t.ttlMsOf(c)}),c)).finally(()=>{o.delete(s)});return o.set(s,l),l}},je=65536,Ke=new Set([301,302,303,307,308]),qe=new Set(["text/html","application/xhtml+xml"]),ze=new Set(["ERR_IP_BLOCKED",ue]),pe=Object.freeze({timeoutMs:5e3,maxRedirects:5,maxBodyBytes:8*1024*1024}),Fe=Object.freeze({lookup:Re,blockList:S}),Je=(r,t)=>{const e=x.buildConnector({lookup:r.lookup,blockList:r.blockList,timeout:t}),n=x.buildConnector({timeout:t});return(o,s)=>{if(o.protocol!=="https:"){e(o,s);return}const a=O.connect({host:o.hostname,port:Number(o.port===""?443:o.port),lookup:r.lookup,blockList:r.blockList}),i=l=>{a.destroy(),s(l,null)};a.setTimeout(t,()=>i(Object.assign(new Error(`Connect timeout: ${o.hostname}`),{code:"UND_ERR_CONNECT_TIMEOUT"}))),a.once("error",i),a.once("connect",()=>{a.setTimeout(0),a.removeListener("error",i),n({...o,httpSocket:a},s)})}},Xe=r=>new x.Agent({maxHeaderSize:je,connect:Je(Fe,pe.timeoutMs)}),j=async r=>{r.body!==null&&await Promise.allSettled([r.body.cancel()])},Ge=r=>r!==null&&qe.has(r.split(";",1)[0].trim().toLowerCase()),Ve=r=>{const t=[r];for(let e=0;e<16&&t.length>0;e+=1){const n=t.shift();if(!(n instanceof Error))continue;const o=n.code;if(typeof o=="string"&&ze.has(o))return n.message;t.push(n.cause,...n instanceof AggregateError?n.errors:[])}return null},he=(r,t)=>{const e=Ve(r);return e!==null?(w.linkCardLogger.info("Refused link-card connection to a private address:",t,e),{ok:!1,reason:"private-network"}):(w.linkCardLogger.error("Error fetching link-card metadata:",r),{ok:!1,reason:"unreachable"})},We=()=>new Promise(r=>{setImmediate(r)}),Ye=async(r,t,e,n)=>{if(r.body===null)return{ok:!0,value:t.end()};const o=r.body.getReader();let s=0;for(;;){let a;try{a=await o.read()}catch(f){return he(f,n)}if(a.done)break;const i=e-s,l=a.value.byteLength>i,c=l?a.value.subarray(0,i):a.value;if(s+=c.byteLength,!t.write(c)){await Promise.allSettled([o.cancel()]);break}if(l){await Promise.allSettled([o.cancel()]),w.linkCardLogger.warn("Link-card page body exceeds the size limit; parsing only its first bytes:",n,e);break}await We()}return{ok:!0,value:t.end()}},Ze=async(r,t,e,n)=>{let o=r;for(let s=0;s<=t.limits.maxRedirects;s+=1){let a;try{a=await x.fetch(o,{signal:n,redirect:"manual",dispatcher:t.agent})}catch(f){return he(f,o)}const i=Ke.has(a.status)?a.headers.get("location")?.trim()??"":"";if(i===""){if(!a.ok)return await j(a),{ok:!1,reason:"unreachable"};const f=a.headers.get("content-type");return Ge(f)?Ye(a,e({url:o,contentType:f}),t.limits.maxBodyBytes,o):(await j(a),{ok:!1,reason:"not-html"})}await j(a);let l;try{l=new URL(i,o)}catch{return w.linkCardLogger.error("Blocked redirect to an unparsable Location from:",o),{ok:!1,reason:"unreachable"}}const c=z(l.href);if(!c.ok)return w.linkCardLogger.info("Refused link-card redirect:",de(l),`(${c.reason}: ${c.detail})`),{ok:!1,reason:c.reason};o=c.href}return w.linkCardLogger.error("Too many redirects while fetching link-card metadata:",r),{ok:!1,reason:"unreachable"}},Qe=(r,t,e)=>{const n=new AbortController,o=setTimeout(()=>n.abort(),t.limits.timeoutMs);return Ze(r,t,e,n.signal).finally(()=>{clearTimeout(o)})},et=256,tt=4096,rt=64,nt=new Set(["html","head","title","meta","link","base","basefont","bgsound","noframes","script","style","template","noscript"]),ot=new Set(["title","script","style"]),at=new Set(["noscript","template","noframes"]),st=r=>r?.toLowerCase().split(/[\t\n\f\r ]+/u).includes("icon")===!0,it=(r,t)=>{if(r===void 0)return t;let e;try{e=new URL(r,t)}catch{return t}return(e.protocol==="http:"||e.protocol==="https:")&&e.href.length<=p.LINK_CARD_URL_LIMIT?e.href:t},re=(r,t,e)=>{const n=r?.trim();if(n===void 0||n==="")return;let o;try{o=new URL(n,t)}catch{return}return o.href.length<=p.LINK_CARD_URL_LIMIT&&z(o.href).ok?o.href:void 0},lt=(r,t)=>{let e=!1,n=0,o=0,s=0,a=null,i=null,l=null,c,f,y,M,F,J,X=!1,G,V=!1;const D=()=>{e=!0,B.pause()},B=new be.Parser({onopentagname(d){n+=1,o+=1,s=0,(n>et||o>tt||a===null&&!nt.has(d))&&D()},onattribute(){s+=1,s>rt&&D()},onopentag(d,m){if(!(e||a!==null)){if(at.has(d)){a=n;return}if(d==="meta"){const h=m.content;m.property==="og:site_name"&&(M=h),m.property==="og:title"&&(f=h),m.property==="og:description"&&(y=h),m.property==="og:image"&&(F=h),m.name==="description"&&(y=h)}else d==="link"&&!X&&st(m.rel)?(X=!0,J=m.href):d==="base"&&!V&&Object.hasOwn(m,"href")&&(V=!0,G=m.href);ot.has(d)&&(i=d,d==="title"&&c===void 0&&(l=""))}},ontext(d){a===null&&(l!==null?l+=d:i===null&&/[^\t\n\f\r ]/u.test(d)&&D())},onclosetag(d){if(!e){if(n-=1,a!==null){n<a&&(a=null);return}d===i&&(i=null,l!==null&&(c=l,l=null))}}},{decodeEntities:!0});return{write:d=>(e||B.write(d),!e),end:()=>{e||B.end();const d=p.linkCardTextOf(f,p.LINK_CARD_TEXT_LIMITS.title)??p.linkCardTextOf(c,p.LINK_CARD_TEXT_LIMITS.title),m=p.linkCardTextOf(y,p.LINK_CARD_TEXT_LIMITS.description),h=p.linkCardTextOf(M,p.LINK_CARD_TEXT_LIMITS.siteName),W=it(G,r),Y=re(F,W),Z=re(J,W);return{...d===null?{}:{title:d},...m===null?{}:{description:m},...h===null?{}:{site_name:h},...Y===void 0?{}:{image:Y},...Z===void 0?{}:{icon:Z}}}}},ct=new Set(["authorize"]),ut="private, max-age=1800",dt=3600*1e3,we=Object.freeze({"private-network":1800,"forbidden-url":1800,unreachable:300,"not-html":300}),ft=1e3,I="no-store",v=(r,t,e,n,o={})=>new Response(r.method==="HEAD"?null:JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":n,"X-Content-Type-Options":"nosniff",...o}}),ne=r=>new Response(null,{status:204,headers:{"Cache-Control":`private, max-age=${we[r]}`,"X-Content-Type-Options":"nosniff",[p.LINK_CARD_SKIP_HEADER]:r}}),mt=r=>{if(typeof r!="object"||r===null)throw new TypeError("createLinkCardHandler: options must be an object with an authorize function");if(typeof r.authorize!="function")throw new TypeError("createLinkCardHandler: options.authorize must be a function (pass () => true to serve everyone)");const t=Object.keys(r).filter(e=>!ct.has(e));if(t.length>0)throw new TypeError(`createLinkCardHandler: unknown option(s): ${t.join(", ")}`)},pt=r=>t=>{const e=He(t.contentType),n=lt(t.url);return{write:o=>n.write(e.write(o)),end:()=>(n.write(e.end()),n.end())}},ht=(r,t)=>{mt(r);const{authorize:e}=r,n=Xe(),o=$e(s=>Qe(s,{agent:n,scope:t,limits:pe},pt()),{maxEntries:ft,ttlMsOf:s=>s.ok?dt:we[s.reason]*1e3},Date.now);return async s=>{if(s.method!=="GET"&&s.method!=="HEAD")return v(s,405,{error:"Method Not Allowed"},I,{Allow:"GET, HEAD"});if(await e(s)!==!0)return v(s,401,{error:"Unauthorized"},I);const a=new URL(s.url).searchParams.get("url");if(a===null||a==="")return v(s,400,{error:"Missing 'url' parameter"},I);const i=z(a);if(!i.ok)return w.linkCardLogger.info("Refused link-card URL:",de(a),`(${i.reason}: ${i.detail})`),ne(i.reason);let l;try{l=await o(i.href)}catch(c){return w.linkCardLogger.error("Unexpected error while reading link-card metadata:",i.href,c),v(s,500,{error:"Internal Server Error"},I)}return l.ok?v(s,200,l.value,ut):ne(l.reason)}},wt=r=>ht(r,"public");class T extends u.Message{markdownText="";filePath="";workspaceRoot="";validateExistence=!1;enableSubscript;enableSuperscript;enableMark;enableTableMerge;enableEmbeds;enableZennDirectives;resolveImports=!1;maxHtmlBytes;deny;includeSourceLines=!1;constructor(t){super(),u.proto3.util.initPartial(t,this)}static runtime=u.proto3;static typeName="markdown.v1.ConvertRequest";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"markdown_text",kind:"scalar",T:9},{no:2,name:"file_path",kind:"scalar",T:9},{no:3,name:"workspace_root",kind:"scalar",T:9},{no:4,name:"validate_existence",kind:"scalar",T:8},{no:5,name:"enable_subscript",kind:"scalar",T:8,opt:!0},{no:6,name:"enable_superscript",kind:"scalar",T:8,opt:!0},{no:7,name:"enable_mark",kind:"scalar",T:8,opt:!0},{no:8,name:"enable_table_merge",kind:"scalar",T:8,opt:!0},{no:9,name:"enable_embeds",kind:"scalar",T:8,opt:!0},{no:10,name:"enable_zenn_directives",kind:"scalar",T:8,opt:!0},{no:11,name:"resolve_imports",kind:"scalar",T:8},{no:12,name:"max_html_bytes",kind:"scalar",T:13,opt:!0},{no:13,name:"deny",kind:"message",T:k},{no:14,name:"include_source_lines",kind:"scalar",T:8}]);static fromBinary(t,e){return new T().fromBinary(t,e)}static fromJson(t,e){return new T().fromJson(t,e)}static fromJsonString(t,e){return new T().fromJsonString(t,e)}static equals(t,e){return u.proto3.util.equals(T,t,e)}}class k extends u.Message{segmentPatterns=[];constructor(t){super(),u.proto3.util.initPartial(t,this)}static runtime=u.proto3;static typeName="markdown.v1.DenyRules";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"segment_patterns",kind:"scalar",T:9,repeated:!0}]);static fromBinary(t,e){return new k().fromBinary(t,e)}static fromJson(t,e){return new k().fromJson(t,e)}static fromJsonString(t,e){return new k().fromJsonString(t,e)}static equals(t,e){return u.proto3.util.equals(k,t,e)}}class b extends u.Message{htmlContent="";headings=[];constructor(t){super(),u.proto3.util.initPartial(t,this)}static runtime=u.proto3;static typeName="markdown.v1.ConvertResponse";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"html_content",kind:"scalar",T:9},{no:2,name:"headings",kind:"message",T:E,repeated:!0}]);static fromBinary(t,e){return new b().fromBinary(t,e)}static fromJson(t,e){return new b().fromJson(t,e)}static fromJsonString(t,e){return new b().fromJsonString(t,e)}static equals(t,e){return u.proto3.util.equals(b,t,e)}}class E extends u.Message{text="";depth=0;id="";constructor(t){super(),u.proto3.util.initPartial(t,this)}static runtime=u.proto3;static typeName="markdown.v1.Heading";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"text",kind:"scalar",T:9},{no:2,name:"depth",kind:"scalar",T:5},{no:3,name:"id",kind:"scalar",T:9}]);static fromBinary(t,e){return new E().fromBinary(t,e)}static fromJson(t,e){return new E().fromJson(t,e)}static fromJsonString(t,e){return new E().fromJsonString(t,e)}static equals(t,e){return u.proto3.util.equals(E,t,e)}}const gt={typeName:"markdown.v1.MarkdownService",methods:{convert:{name:"Convert",I:T,O:b,kind:u.MethodKind.Unary}}},_=process.env.MARKDOWN_SOCKET_PATH||"/tmp/markdown.sock",kt=new ie.Http2SessionManager("http://localhost",void 0,{createConnection:()=>ce.connect(_)}),oe=()=>{try{return P.dirname(ye.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:H&&H.tagName.toUpperCase()==="SCRIPT"&&H.src||new URL("index.server.cjs",document.baseURI).href))}catch{return __dirname}},ge=()=>`@aiquants/markdown-${process.platform}-${process.arch}`,ae=()=>process.platform==="win32"?"bin/markdown-api.exe":"bin/markdown-api",Tt=()=>{const r=process.env.MARKDOWN_API_BINARY;if(r&&R.existsSync(r))return r;try{const e=Se.createRequire(P.join(oe(),"index.js")).resolve(`${ge()}/${ae()}`);if(R.existsSync(e))return e}catch{}const t=P.join(oe(),"..","..","go","markdown-api","dist",P.basename(ae()));return R.existsSync(t)?t:void 0},bt=()=>[`markdown-api binary not found for ${process.platform}-${process.arch}.`,`Expected the optional dependency ${ge()} to be installed.`,"If your platform is unsupported, build the service yourself","(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)","and point MARKDOWN_API_BINARY at it."].join(" "),ke=()=>new Promise(r=>{const t=ce.connect(_);t.on("connect",()=>{t.destroy(),r(!0)}),t.on("error",()=>r(!1))}),se=async r=>{const t=Date.now();for(;Date.now()-t<r;){if(await ke())return!0;await new Promise(e=>setTimeout(e,100))}return!1};let A=null,L=null;const Et=2e3,St=()=>{const r=Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);return Number.isFinite(r)&&r>0?r:1e4};let N=null;const _t=async()=>{if(await ke())return!0;if(L)return L;L=(async()=>{const t=Tt();if(!t)return await se(Et)?!0:(N=bt(),!1);N=null;try{R.existsSync(_)&&R.unlinkSync(_)}catch{}try{A=Ee.spawn(t,[],{stdio:"ignore"});const e=()=>{if(A){try{A.kill("SIGTERM")}catch{}A=null}};return process.once("exit",e),await se(St())?!0:(console.error("markdown-api Go server did not become ready on socket:",_),e(),process.removeListener("exit",e),!1)}catch(e){return console.error("Failed to spawn markdown-api Go server:",e),A=null,!1}})();const r=await L;return r||(L=null),r},yt=r=>{if(C.assertConversionOptions(r,"parseMarkdown"),r.timeoutMs!==void 0&&(!Number.isSafeInteger(r.timeoutMs)||r.timeoutMs<=0))throw new RangeError(`parseMarkdown: timeoutMs must be a positive integer, got ${r.timeoutMs}`)},vt=async(r,t,e,n,o)=>{if(yt(o),!await _t()){const i=N?` ${N}`:"";throw new Error(`markdown service is not reachable on ${_}.${i}`)}const s={};n&&(s.Authorization=`Bearer ${n}`);const a=U.createClient(gt,ie.createConnectTransport({baseUrl:"http://localhost",httpVersion:"2",sessionManager:kt,readMaxBytes:2*o.maxHtmlBytes+C.RESPONSE_HEADROOM_BYTES}));try{const i=await a.convert({markdownText:r,filePath:t,workspaceRoot:e,validateExistence:o.validateExistence??!0,enableSubscript:o.enableSubscript,enableSuperscript:o.enableSuperscript,enableMark:o.enableMark,enableTableMerge:o.enableTableMerge,enableEmbeds:o.enableEmbeds,enableZennDirectives:o.enableZennDirectives,resolveImports:o.resolveImports??!1,includeSourceLines:o.includeSourceLines??!1,maxHtmlBytes:o.maxHtmlBytes,deny:new k({segmentPatterns:[...o.deniedPathSegments]})},{headers:s,signal:o.signal,timeoutMs:o.timeoutMs});return{htmlContent:i.htmlContent,headings:i.headings.map(l=>({text:l.text,depth:l.depth,id:l.id}))}}catch(i){throw i instanceof U.ConnectError&&i.code===U.Code.ResourceExhausted?new C.MarkdownResourceExhaustedError(i.rawMessage,{cause:i}):i}};exports.MAX_HTML_BYTES_LIMIT=C.MAX_HTML_BYTES_LIMIT;exports.MarkdownResourceExhaustedError=C.MarkdownResourceExhaustedError;exports.createLinkCardHandler=wt;exports.parseMarkdown=vt;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("./errors-BW5JXRoX.cjs"),p=require("./linkCards-Bjd_vW39.cjs"),w=require("./simple-logger-9yf7ypyB.cjs"),Te=require("node:dns/promises"),O=require("node:net"),N=require("undici"),be=require("htmlparser2"),Ee=require("node:child_process"),R=require("node:fs"),_e=require("node:module"),Se=require("node:path"),ve=require("node:url"),B=require("@connectrpc/connect"),ie=require("@connectrpc/connect-node"),u=require("@bufbuild/protobuf");var H=typeof document<"u"?document.currentScript:null;function le(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const e in t)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(r,e,n.get?n:{enumerable:!0,get:()=>t[e]})}}return r.default=t,Object.freeze(r)}const ce=le(O),P=le(Se),ye=[[[0],8],[[10],8],[[100,64],10],[[127],8],[[169,254],16],[[172,16],12],[[192,0,0],24],[[192,0,2],24],[[192,168],16],[[198,18],15],[[198,51,100],24],[[203,0,113],24],[[224],4],[[240],4]],Ae=[[[100,65435],32],[[0,0,0,0,65535,0],96],[[256,0,0,0],64],[[256,0,0,1],64],[[8193,0],32],[[8193,2,0],48],[[8193,3512],32],[[8194],16],[[16383],20],[[24320],16],[[64512],7],[[65152],10],[[65216],10],[[65280],8]],S=new O.BlockList;for(const[t,r]of ye){const e=[...t,0,0,0].slice(0,4).join(".");S.addSubnet(e,r,"ipv4"),S.addSubnet(`::ffff:${e}`,96+r,"ipv6"),S.addSubnet(`::${e}`,96+r,"ipv6")}for(const[t,r]of Ae)S.addSubnet(`${t.map(e=>e.toString(16)).join(":")}::`,r,"ipv6");const K=t=>{const r=t.replace(/^\[/u,"").replace(/\]$/u,"").replace(/%.*$/su,""),e=O.isIP(r);return e!==0&&S.check(r,e===4?"ipv4":"ipv6")},ue="ERR_LINK_CARD_PRIVATE_ADDRESS",Q=Object.freeze({timeoutMs:1e3,tries:2}),ee=new Te.Resolver({timeout:Q.timeoutMs,tries:Q.tries}),te=(t,r)=>({error:Object.assign(new Error(`Blocked hostname resolving to a private address: ${t} -> ${r}`),{code:ue})}),Le=async(t,r)=>{const e=O.isIP(t);if(e!==0)return K(t)?te(t,t):{error:null,family:e===4?4:6,addresses:[t]};const[n,o]=await Promise.allSettled([r===6?Promise.resolve([]):ee.resolve4(t),r===4?Promise.resolve([]):ee.resolve6(t)]),s=n.status==="fulfilled"?n.value:[],a=o.status==="fulfilled"?o.value:[],i=[...s,...a].find(M=>K(M));if(i!==void 0)return te(t,i);const[l,...c]=s;if(l!==void 0)return{error:null,family:4,addresses:[l,...c]};const[f,...v]=a;return f!==void 0?{error:null,family:6,addresses:[f,...v]}:n.status==="rejected"?{error:n.reason}:o.status==="rejected"?{error:o.reason}:{error:Object.assign(new Error(`No address for ${t}`),{code:"ENOTFOUND"})}},Re=(t,r,e)=>{const n=r.family===4||r.family==="IPv4"?4:r.family===6||r.family==="IPv6"?6:0;Le(t,n).then(o=>{if(o.error!==null){e(o.error,"");return}const{family:s,addresses:a}=o;r.all===!0?e(null,a.map(i=>({address:i,family:s}))):e(null,a[0],s)})},Ce=new Set(["127.0.0.1","0.0.0.0","[::1]"]),Oe=[".local",".internal",".home.arpa"],z=(t,r)=>{let e;try{e=new URL(t)}catch{return{ok:!1,reason:"forbidden-url",detail:"Invalid URL"}}if(e.protocol!=="http:"&&e.protocol!=="https:")return{ok:!1,reason:"forbidden-url",detail:"Only http(s) URLs are allowed"};if(e.username!==""||e.password!=="")return{ok:!1,reason:"forbidden-url",detail:"URLs with a user name or password are not allowed"};e.hash="";const n=e.hostname.replace(/\.+$/u,"");return n==="localhost"||n.endsWith(".localhost")||Ce.has(n)?{ok:!1,reason:"private-network",detail:"Localhost access is not allowed"}:K(n)?{ok:!1,reason:"private-network",detail:"Private network access is not allowed"}:!(n.startsWith("[")||n.includes("."))||Oe.some(s=>n.endsWith(s))?{ok:!1,reason:"private-network",detail:"Internal domain access is not allowed"}:{ok:!0,href:e.href}},de=t=>{let r;try{r=new URL(t)}catch{return"(unparsable URL)"}return r.protocol!=="http:"&&r.protocol!=="https:"?`(a ${r.protocol} URL)`:(r.username="",r.password="",r.href)},fe=1024,Me=/^[\t\n\f\r ]$/u,g=t=>Me.test(t),$=t=>t.replace(/[A-Z]/gu,r=>r.toLowerCase()),q=t=>{try{return new TextDecoder(t).encoding}catch{return null}},Ie=t=>t[0]===239&&t[1]===187&&t[2]===191?"utf-8":t[0]===254&&t[1]===255?"utf-16be":t[0]===255&&t[1]===254?"utf-16le":null,Pe=t=>{for(const r of t.split(";").slice(1)){const e=r.indexOf("=");if(e!==-1&&r.slice(0,e).trim().toLowerCase()==="charset")return r.slice(e+1).trim().replace(/^"(.*)"$/su,"$1")}return null},Ne=t=>{let r=0;for(;;){const e=t.indexOf("charset",r);if(e===-1)return null;let n=e+7;for(;g(t.charAt(n));)n+=1;if(t.charAt(n)!=="="){r=n;continue}for(n+=1;g(t.charAt(n));)n+=1;const o=t.charAt(n);if(o==='"'||o==="'"){const a=t.indexOf(o,n+1);return a===-1?null:t.slice(n+1,a)}const s=t.slice(n).search(/[\t\n\f\r ;]/u);return s===-1?t.slice(n):t.slice(n,n+s)}},me=(t,r)=>{let e=r;for(;g(t.charAt(e))||t.charAt(e)==="/";)e+=1;if(t.charAt(e)===">"||e>=t.length)return{attribute:null,end:e};let n="";for(;;){const a=t.charAt(e);if(a==="")return{attribute:null,end:e};if(a==="="&&n!=="")break;if(g(a)){for(;g(t.charAt(e));)e+=1;if(t.charAt(e)!=="=")return{attribute:{name:n,value:""},end:e};break}if(a==="/"||a===">")return{attribute:{name:n,value:""},end:e};n+=$(a),e+=1}for(e+=1;g(t.charAt(e));)e+=1;const o=t.charAt(e);if(o==='"'||o==="'"){const a=t.indexOf(o,e+1);return a===-1?{attribute:null,end:t.length}:{attribute:{name:n,value:$(t.slice(e+1,a))},end:a+1}}if(o===">")return{attribute:{name:n,value:""},end:e};const s=t.slice(e).search(/[\t\n\f\r >]/u);return s===-1?{attribute:null,end:t.length}:{attribute:{name:n,value:$(t.slice(e,e+s))},end:e+s}},xe=(t,r)=>{const e=new Set;let n=!1,o=null,s=null,a=r;for(;;){const{attribute:i,end:l}=me(t,a);if(a=l,i===null)break;if(!e.has(i.name))if(e.add(i.name),i.name==="http-equiv")n=i.value==="content-type";else if(i.name==="content"){const c=Ne(i.value),f=c===null?null:q(c);f!==null&&s===null&&(s=f,o=!0)}else i.name==="charset"&&(s=q(i.value)??!1,o=!1)}return o===null||typeof s!="string"||o&&!n?{encoding:null,end:a}:s==="utf-16be"||s==="utf-16le"?{encoding:"utf-8",end:a}:{encoding:s==="x-user-defined"?"windows-1252":s,end:a}},De=t=>{const r=Array.from(t.subarray(0,fe),n=>String.fromCharCode(n)).join("");let e=0;for(;e<r.length;)if(r.startsWith("<!--",e)){const n=r.indexOf("-->",e+2);if(n===-1)return null;e=n+3}else if(/^<meta[\t\n\f\r /]$/iu.test(r.slice(e,e+6))){const{encoding:n,end:o}=xe(r,e+5);if(n!==null)return n;e=o+1}else if(/^<\/?[A-Za-z]/u.test(r.slice(e,e+3))){let n=e+1;for(;n<r.length&&!g(r.charAt(n))&&r.charAt(n)!==">";)n+=1;for(;;){const o=me(r,n);if(n=o.end,o.attribute===null)break}e=n+1}else if(/^<[!/?]$/u.test(r.slice(e,e+2))){const n=r.indexOf(">",e+1);if(n===-1)return null;e=n+1}else e+=1;return null},Ue=(t,r)=>{const e=Ie(t);if(e!==null)return e;const n=Pe(r),o=n===null?null:q(n);return o!==null?o:De(t)??"utf-8"},Be=(t,r)=>{const e=new Uint8Array(r);let n=0;for(const o of t)e.set(o,n),n+=o.byteLength;return e},He=t=>{const r=[];let e=0,n=null;const o=()=>{const s=Be(r,e);r.length=0;const a=new TextDecoder(Ue(s,t));return n=a,{started:a,text:a.decode(s,{stream:!0})}};return{write:s=>n!==null?n.decode(s,{stream:!0}):(r.push(s),e+=s.byteLength,e<fe?"":o().text),end:()=>{if(n!==null)return n.decode();const{started:s,text:a}=o();return a+s.decode()}}},$e=(t,r,e)=>{const n=new Map,o=new Map;return s=>{const a=n.get(s);if(a!==void 0&&a.expireAt>e())return Promise.resolve(a.value);const i=o.get(s);if(i!==void 0)return i;const l=t(s).then(c=>(!n.has(s)&&n.size>=r.maxEntries&&n.delete(n.keys().next().value),n.set(s,{value:c,expireAt:e()+r.ttlMsOf(c)}),c)).finally(()=>{o.delete(s)});return o.set(s,l),l}},je=65536,Ke=new Set([301,302,303,307,308]),qe=new Set(["text/html","application/xhtml+xml"]),ze=new Set(["ERR_IP_BLOCKED",ue]),pe=Object.freeze({timeoutMs:5e3,maxRedirects:5,maxBodyBytes:8*1024*1024}),Xe=Object.freeze({lookup:Re,blockList:S}),Fe=(t,r)=>{const e=N.buildConnector({lookup:t.lookup,blockList:t.blockList,timeout:r}),n=N.buildConnector({timeout:r});return(o,s)=>{if(o.protocol!=="https:"){e(o,s);return}const a=O.connect({host:o.hostname,port:Number(o.port===""?443:o.port),lookup:t.lookup,blockList:t.blockList}),i=l=>{a.destroy(),s(l,null)};a.setTimeout(r,()=>i(Object.assign(new Error(`Connect timeout: ${o.hostname}`),{code:"UND_ERR_CONNECT_TIMEOUT"}))),a.once("error",i),a.once("connect",()=>{a.setTimeout(0),a.removeListener("error",i),n({...o,httpSocket:a},s)})}},Je=t=>new N.Agent({maxHeaderSize:je,connect:Fe(Xe,pe.timeoutMs)}),j=async t=>{t.body!==null&&await Promise.allSettled([t.body.cancel()])},Ge=t=>t!==null&&qe.has(t.split(";",1)[0].trim().toLowerCase()),Ve=t=>{const r=[t];for(let e=0;e<16&&r.length>0;e+=1){const n=r.shift();if(!(n instanceof Error))continue;const o=n.code;if(typeof o=="string"&&ze.has(o))return n.message;r.push(n.cause,...n instanceof AggregateError?n.errors:[])}return null},he=(t,r)=>{const e=Ve(t);return e!==null?(w.linkCardLogger.info("Refused link-card connection to a private address:",r,e),{ok:!1,reason:"private-network"}):(w.linkCardLogger.error("Error fetching link-card metadata:",t),{ok:!1,reason:"unreachable"})},We=()=>new Promise(t=>{setImmediate(t)}),Ye=async(t,r,e,n)=>{if(t.body===null)return{ok:!0,value:r.end()};const o=t.body.getReader();let s=0;for(;;){let a;try{a=await o.read()}catch(f){return he(f,n)}if(a.done)break;const i=e-s,l=a.value.byteLength>i,c=l?a.value.subarray(0,i):a.value;if(s+=c.byteLength,!r.write(c)){await Promise.allSettled([o.cancel()]);break}if(l){await Promise.allSettled([o.cancel()]),w.linkCardLogger.warn("Link-card page body exceeds the size limit; parsing only its first bytes:",n,e);break}await We()}return{ok:!0,value:r.end()}},Ze=async(t,r,e,n)=>{let o=t;for(let s=0;s<=r.limits.maxRedirects;s+=1){let a;try{a=await N.fetch(o,{signal:n,redirect:"manual",dispatcher:r.agent})}catch(f){return he(f,o)}const i=Ke.has(a.status)?a.headers.get("location")?.trim()??"":"";if(i===""){if(!a.ok)return await j(a),{ok:!1,reason:"unreachable"};const f=a.headers.get("content-type");return Ge(f)?Ye(a,e({url:o,contentType:f}),r.limits.maxBodyBytes,o):(await j(a),{ok:!1,reason:"not-html"})}await j(a);let l;try{l=new URL(i,o)}catch{return w.linkCardLogger.error("Blocked redirect to an unparsable Location from:",o),{ok:!1,reason:"unreachable"}}const c=z(l.href);if(!c.ok)return w.linkCardLogger.info("Refused link-card redirect:",de(l),`(${c.reason}: ${c.detail})`),{ok:!1,reason:c.reason};o=c.href}return w.linkCardLogger.error("Too many redirects while fetching link-card metadata:",t),{ok:!1,reason:"unreachable"}},Qe=(t,r,e)=>{const n=new AbortController,o=setTimeout(()=>n.abort(),r.limits.timeoutMs);return Ze(t,r,e,n.signal).finally(()=>{clearTimeout(o)})},et=256,tt=4096,rt=64,nt=new Set(["html","head","title","meta","link","base","basefont","bgsound","noframes","script","style","template","noscript"]),ot=new Set(["title","script","style"]),at=new Set(["noscript","template","noframes"]),st=t=>t?.toLowerCase().split(/[\t\n\f\r ]+/u).includes("icon")===!0,it=(t,r)=>{if(t===void 0)return r;let e;try{e=new URL(t,r)}catch{return r}return(e.protocol==="http:"||e.protocol==="https:")&&e.href.length<=p.LINK_CARD_URL_LIMIT?e.href:r},re=(t,r,e)=>{const n=t?.trim();if(n===void 0||n==="")return;let o;try{o=new URL(n,r)}catch{return}return o.href.length<=p.LINK_CARD_URL_LIMIT&&z(o.href).ok?o.href:void 0},lt=(t,r)=>{let e=!1,n=0,o=0,s=0,a=null,i=null,l=null,c,f,v,M,X,F,J=!1,G,V=!1;const D=()=>{e=!0,U.pause()},U=new be.Parser({onopentagname(d){n+=1,o+=1,s=0,(n>et||o>tt||a===null&&!nt.has(d))&&D()},onattribute(){s+=1,s>rt&&D()},onopentag(d,m){if(!(e||a!==null)){if(at.has(d)){a=n;return}if(d==="meta"){const h=m.content;m.property==="og:site_name"&&(M=h),m.property==="og:title"&&(f=h),m.property==="og:description"&&(v=h),m.property==="og:image"&&(X=h),m.name==="description"&&(v=h)}else d==="link"&&!J&&st(m.rel)?(J=!0,F=m.href):d==="base"&&!V&&Object.hasOwn(m,"href")&&(V=!0,G=m.href);ot.has(d)&&(i=d,d==="title"&&c===void 0&&(l=""))}},ontext(d){a===null&&(l!==null?l+=d:i===null&&/[^\t\n\f\r ]/u.test(d)&&D())},onclosetag(d){if(!e){if(n-=1,a!==null){n<a&&(a=null);return}d===i&&(i=null,l!==null&&(c=l,l=null))}}},{decodeEntities:!0});return{write:d=>(e||U.write(d),!e),end:()=>{e||U.end();const d=p.linkCardTextOf(f,p.LINK_CARD_TEXT_LIMITS.title)??p.linkCardTextOf(c,p.LINK_CARD_TEXT_LIMITS.title),m=p.linkCardTextOf(v,p.LINK_CARD_TEXT_LIMITS.description),h=p.linkCardTextOf(M,p.LINK_CARD_TEXT_LIMITS.siteName),W=it(G,t),Y=re(X,W),Z=re(F,W);return{...d===null?{}:{title:d},...m===null?{}:{description:m},...h===null?{}:{site_name:h},...Y===void 0?{}:{image:Y},...Z===void 0?{}:{icon:Z}}}}},ct=new Set(["authorize"]),ut="private, max-age=1800",dt=3600*1e3,we=Object.freeze({"private-network":1800,"forbidden-url":1800,unreachable:300,"not-html":300}),ft=1e3,I="no-store",y=(t,r,e,n,o={})=>new Response(t.method==="HEAD"?null:JSON.stringify(e),{status:r,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":n,"X-Content-Type-Options":"nosniff",...o}}),ne=t=>new Response(null,{status:204,headers:{"Cache-Control":`private, max-age=${we[t]}`,"X-Content-Type-Options":"nosniff",[p.LINK_CARD_SKIP_HEADER]:t}}),mt=t=>{if(typeof t!="object"||t===null)throw new TypeError("createLinkCardHandler: options must be an object with an authorize function");if(typeof t.authorize!="function")throw new TypeError("createLinkCardHandler: options.authorize must be a function (pass () => true to serve everyone)");const r=Object.keys(t).filter(e=>!ct.has(e));if(r.length>0)throw new TypeError(`createLinkCardHandler: unknown option(s): ${r.join(", ")}`)},pt=t=>r=>{const e=He(r.contentType),n=lt(r.url);return{write:o=>n.write(e.write(o)),end:()=>(n.write(e.end()),n.end())}},ht=(t,r)=>{mt(t);const{authorize:e}=t,n=Je(),o=$e(s=>Qe(s,{agent:n,scope:r,limits:pe},pt()),{maxEntries:ft,ttlMsOf:s=>s.ok?dt:we[s.reason]*1e3},Date.now);return async s=>{if(s.method!=="GET"&&s.method!=="HEAD")return y(s,405,{error:"Method Not Allowed"},I,{Allow:"GET, HEAD"});if(await e(s)!==!0)return y(s,401,{error:"Unauthorized"},I);const a=new URL(s.url).searchParams.get("url");if(a===null||a==="")return y(s,400,{error:"Missing 'url' parameter"},I);const i=z(a);if(!i.ok)return w.linkCardLogger.info("Refused link-card URL:",de(a),`(${i.reason}: ${i.detail})`),ne(i.reason);let l;try{l=await o(i.href)}catch(c){return w.linkCardLogger.error("Unexpected error while reading link-card metadata:",i.href,c),y(s,500,{error:"Internal Server Error"},I)}return l.ok?y(s,200,l.value,ut):ne(l.reason)}},wt=t=>ht(t,"public");class b extends u.Message{markdownText="";filePath="";workspaceRoot="";validateExistence=!1;enableSubscript;enableSuperscript;enableMark;enableTableMerge;enableEmbeds;enableZennDirectives;resolveImports=!1;maxHtmlBytes;deny;includeSourceLines=!1;constructor(r){super(),u.proto3.util.initPartial(r,this)}static runtime=u.proto3;static typeName="markdown.v1.ConvertRequest";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"markdown_text",kind:"scalar",T:9},{no:2,name:"file_path",kind:"scalar",T:9},{no:3,name:"workspace_root",kind:"scalar",T:9},{no:4,name:"validate_existence",kind:"scalar",T:8},{no:5,name:"enable_subscript",kind:"scalar",T:8,opt:!0},{no:6,name:"enable_superscript",kind:"scalar",T:8,opt:!0},{no:7,name:"enable_mark",kind:"scalar",T:8,opt:!0},{no:8,name:"enable_table_merge",kind:"scalar",T:8,opt:!0},{no:9,name:"enable_embeds",kind:"scalar",T:8,opt:!0},{no:10,name:"enable_zenn_directives",kind:"scalar",T:8,opt:!0},{no:11,name:"resolve_imports",kind:"scalar",T:8},{no:12,name:"max_html_bytes",kind:"scalar",T:13,opt:!0},{no:13,name:"deny",kind:"message",T:k},{no:14,name:"include_source_lines",kind:"scalar",T:8}]);static fromBinary(r,e){return new b().fromBinary(r,e)}static fromJson(r,e){return new b().fromJson(r,e)}static fromJsonString(r,e){return new b().fromJsonString(r,e)}static equals(r,e){return u.proto3.util.equals(b,r,e)}}class k extends u.Message{segmentPatterns=[];constructor(r){super(),u.proto3.util.initPartial(r,this)}static runtime=u.proto3;static typeName="markdown.v1.DenyRules";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"segment_patterns",kind:"scalar",T:9,repeated:!0}]);static fromBinary(r,e){return new k().fromBinary(r,e)}static fromJson(r,e){return new k().fromJson(r,e)}static fromJsonString(r,e){return new k().fromJsonString(r,e)}static equals(r,e){return u.proto3.util.equals(k,r,e)}}class E extends u.Message{htmlContent="";headings=[];constructor(r){super(),u.proto3.util.initPartial(r,this)}static runtime=u.proto3;static typeName="markdown.v1.ConvertResponse";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"html_content",kind:"scalar",T:9},{no:2,name:"headings",kind:"message",T:_,repeated:!0}]);static fromBinary(r,e){return new E().fromBinary(r,e)}static fromJson(r,e){return new E().fromJson(r,e)}static fromJsonString(r,e){return new E().fromJsonString(r,e)}static equals(r,e){return u.proto3.util.equals(E,r,e)}}class _ extends u.Message{text="";depth=0;id="";constructor(r){super(),u.proto3.util.initPartial(r,this)}static runtime=u.proto3;static typeName="markdown.v1.Heading";static fields=u.proto3.util.newFieldList(()=>[{no:1,name:"text",kind:"scalar",T:9},{no:2,name:"depth",kind:"scalar",T:5},{no:3,name:"id",kind:"scalar",T:9}]);static fromBinary(r,e){return new _().fromBinary(r,e)}static fromJson(r,e){return new _().fromJson(r,e)}static fromJsonString(r,e){return new _().fromJsonString(r,e)}static equals(r,e){return u.proto3.util.equals(_,r,e)}}const gt={typeName:"markdown.v1.MarkdownService",methods:{convert:{name:"Convert",I:b,O:E,kind:u.MethodKind.Unary}}},T=()=>{const t=process.env.MARKDOWN_SOCKET_PATH;if(t===void 0||t==="")throw new Error("MARKDOWN_SOCKET_PATH is required: set it to the path of the markdown-api service's UNIX domain socket, the same value the service reads");return t},kt=new ie.Http2SessionManager("http://localhost",void 0,{createConnection:()=>ce.connect(T())}),oe=()=>{try{return P.dirname(ve.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:H&&H.tagName.toUpperCase()==="SCRIPT"&&H.src||new URL("index.server.cjs",document.baseURI).href))}catch{return __dirname}},ge=()=>`@aiquants/markdown-${process.platform}-${process.arch}`,ae=()=>process.platform==="win32"?"bin/markdown-api.exe":"bin/markdown-api",Tt=()=>{const t=process.env.MARKDOWN_API_BINARY;if(t&&R.existsSync(t))return t;try{const e=_e.createRequire(P.join(oe(),"index.js")).resolve(`${ge()}/${ae()}`);if(R.existsSync(e))return e}catch{}const r=P.join(oe(),"..","..","go","markdown-api","dist",P.basename(ae()));return R.existsSync(r)?r:void 0},bt=()=>[`markdown-api binary not found for ${process.platform}-${process.arch}.`,`Expected the optional dependency ${ge()} to be installed.`,"If your platform is unsupported, build the service yourself","(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)","and point MARKDOWN_API_BINARY at it."].join(" "),ke=()=>new Promise(t=>{const r=ce.connect(T());r.on("connect",()=>{r.destroy(),t(!0)}),r.on("error",()=>t(!1))}),se=async t=>{const r=Date.now();for(;Date.now()-r<t;){if(await ke())return!0;await new Promise(e=>setTimeout(e,100))}return!1};let A=null,L=null;const Et=2e3,_t=()=>{const t=Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);return Number.isFinite(t)&&t>0?t:1e4};let x=null;const St=async()=>{if(await ke())return!0;if(L)return L;L=(async()=>{const r=Tt();if(!r)return await se(Et)?!0:(x=bt(),!1);x=null;try{R.existsSync(T())&&R.unlinkSync(T())}catch{}try{A=Ee.spawn(r,[],{stdio:"ignore"});const e=()=>{if(A){try{A.kill("SIGTERM")}catch{}A=null}};return process.once("exit",e),await se(_t())?!0:(console.error("markdown-api Go server did not become ready on socket:",T()),e(),process.removeListener("exit",e),!1)}catch(e){return console.error("Failed to spawn markdown-api Go server:",e),A=null,!1}})();const t=await L;return t||(L=null),t},vt=t=>{if(C.assertConversionOptions(t,"parseMarkdown"),t.timeoutMs!==void 0&&(!Number.isSafeInteger(t.timeoutMs)||t.timeoutMs<=0))throw new RangeError(`parseMarkdown: timeoutMs must be a positive integer, got ${t.timeoutMs}`)},yt=async(t,r,e,n,o)=>{if(T(),vt(o),!await St()){const i=x?` ${x}`:"";throw new Error(`markdown service is not reachable on ${T()}.${i}`)}const s={};n&&(s.Authorization=`Bearer ${n}`);const a=B.createClient(gt,ie.createConnectTransport({baseUrl:"http://localhost",httpVersion:"2",sessionManager:kt,readMaxBytes:2*o.maxHtmlBytes+C.RESPONSE_HEADROOM_BYTES}));try{const i=await a.convert({markdownText:t,filePath:r,workspaceRoot:e,validateExistence:o.validateExistence??!0,enableSubscript:o.enableSubscript,enableSuperscript:o.enableSuperscript,enableMark:o.enableMark,enableTableMerge:o.enableTableMerge,enableEmbeds:o.enableEmbeds,enableZennDirectives:o.enableZennDirectives,resolveImports:o.resolveImports??!1,includeSourceLines:o.includeSourceLines??!1,maxHtmlBytes:o.maxHtmlBytes,deny:new k({segmentPatterns:[...o.deniedPathSegments]})},{headers:s,signal:o.signal,timeoutMs:o.timeoutMs});return{htmlContent:i.htmlContent,headings:i.headings.map(l=>({text:l.text,depth:l.depth,id:l.id}))}}catch(i){throw i instanceof B.ConnectError&&i.code===B.Code.ResourceExhausted?new C.MarkdownResourceExhaustedError(i.rawMessage,{cause:i}):i}};exports.MAX_HTML_BYTES_LIMIT=C.MAX_HTML_BYTES_LIMIT;exports.MarkdownResourceExhaustedError=C.MarkdownResourceExhaustedError;exports.createLinkCardHandler=wt;exports.parseMarkdown=yt;
@@ -2,9 +2,9 @@ import { R as ge, c as ke, a as be } from "./errors-Blk_XJ9C.js";
2
2
  import { d as er } from "./errors-Blk_XJ9C.js";
3
3
  import { l as L, L as O, a as ae, b as Ee } from "./linkCards-1JxY8wdm.js";
4
4
  import { l as h } from "./simple-logger-DwH1YQvq.js";
5
- import { Resolver as Te } from "node:dns/promises";
5
+ import { Resolver as ve } from "node:dns/promises";
6
6
  import * as se from "node:net";
7
- import { BlockList as ve, isIP as ie, connect as Se } from "node:net";
7
+ import { BlockList as Te, isIP as ie, connect as Se } from "node:net";
8
8
  import { Agent as ye, buildConnector as Y, fetch as Ae } from "undici";
9
9
  import { Parser as _e } from "htmlparser2";
10
10
  import { spawn as Re } from "node:child_process";
@@ -13,8 +13,8 @@ import { createRequire as Oe } from "node:module";
13
13
  import * as M from "node:path";
14
14
  import { fileURLToPath as Pe } from "node:url";
15
15
  import { createClient as Ce, ConnectError as Me, Code as Ie } from "@connectrpc/connect";
16
- import { Http2SessionManager as xe, createConnectTransport as Ne } from "@connectrpc/connect-node";
17
- import { Message as x, proto3 as d, MethodKind as De } from "@bufbuild/protobuf";
16
+ import { Http2SessionManager as Ne, createConnectTransport as xe } from "@connectrpc/connect-node";
17
+ import { Message as N, proto3 as d, MethodKind as De } from "@bufbuild/protobuf";
18
18
  const Be = [
19
19
  [[0], 8],
20
20
  [[10], 8],
@@ -45,45 +45,45 @@ const Be = [
45
45
  [[65152], 10],
46
46
  [[65216], 10],
47
47
  [[65280], 8]
48
- ], T = new ve();
49
- for (const [r, t] of Be) {
50
- const e = [...r, 0, 0, 0].slice(0, 4).join(".");
51
- T.addSubnet(e, t, "ipv4"), T.addSubnet(`::ffff:${e}`, 96 + t, "ipv6"), T.addSubnet(`::${e}`, 96 + t, "ipv6");
48
+ ], T = new Te();
49
+ for (const [t, r] of Be) {
50
+ const e = [...t, 0, 0, 0].slice(0, 4).join(".");
51
+ T.addSubnet(e, r, "ipv4"), T.addSubnet(`::ffff:${e}`, 96 + r, "ipv6"), T.addSubnet(`::${e}`, 96 + r, "ipv6");
52
52
  }
53
- for (const [r, t] of Ue)
54
- T.addSubnet(`${r.map((e) => e.toString(16)).join(":")}::`, t, "ipv6");
55
- const $ = (r) => {
56
- const t = r.replace(/^\[/u, "").replace(/\]$/u, "").replace(/%.*$/su, ""), e = ie(t);
57
- return e !== 0 && T.check(t, e === 4 ? "ipv4" : "ipv6");
58
- }, le = "ERR_LINK_CARD_PRIVATE_ADDRESS", Z = Object.freeze({ timeoutMs: 1e3, tries: 2 }), q = new Te({ timeout: Z.timeoutMs, tries: Z.tries }), Q = (r, t) => ({
59
- error: Object.assign(new Error(`Blocked hostname resolving to a private address: ${r} -> ${t}`), { code: le })
60
- }), $e = async (r, t) => {
61
- const e = ie(r);
53
+ for (const [t, r] of Ue)
54
+ T.addSubnet(`${t.map((e) => e.toString(16)).join(":")}::`, r, "ipv6");
55
+ const $ = (t) => {
56
+ const r = t.replace(/^\[/u, "").replace(/\]$/u, "").replace(/%.*$/su, ""), e = ie(r);
57
+ return e !== 0 && T.check(r, e === 4 ? "ipv4" : "ipv6");
58
+ }, le = "ERR_LINK_CARD_PRIVATE_ADDRESS", Z = Object.freeze({ timeoutMs: 1e3, tries: 2 }), q = new ve({ timeout: Z.timeoutMs, tries: Z.tries }), Q = (t, r) => ({
59
+ error: Object.assign(new Error(`Blocked hostname resolving to a private address: ${t} -> ${r}`), { code: le })
60
+ }), $e = async (t, r) => {
61
+ const e = ie(t);
62
62
  if (e !== 0)
63
- return $(r) ? Q(r, r) : { error: null, family: e === 4 ? 4 : 6, addresses: [r] };
64
- const [n, o] = await Promise.allSettled([t === 6 ? Promise.resolve([]) : q.resolve4(r), t === 4 ? Promise.resolve([]) : q.resolve6(r)]), s = n.status === "fulfilled" ? n.value : [], a = o.status === "fulfilled" ? o.value : [], i = [...s, ...a].find((R) => $(R));
65
- if (i !== void 0) return Q(r, i);
63
+ return $(t) ? Q(t, t) : { error: null, family: e === 4 ? 4 : 6, addresses: [t] };
64
+ const [n, o] = await Promise.allSettled([r === 6 ? Promise.resolve([]) : q.resolve4(t), r === 4 ? Promise.resolve([]) : q.resolve6(t)]), s = n.status === "fulfilled" ? n.value : [], a = o.status === "fulfilled" ? o.value : [], i = [...s, ...a].find((R) => $(R));
65
+ if (i !== void 0) return Q(t, i);
66
66
  const [l, ...c] = s;
67
67
  if (l !== void 0) return { error: null, family: 4, addresses: [l, ...c] };
68
68
  const [f, ...S] = a;
69
- return f !== void 0 ? { error: null, family: 6, addresses: [f, ...S] } : n.status === "rejected" ? { error: n.reason } : o.status === "rejected" ? { error: o.reason } : { error: Object.assign(new Error(`No address for ${r}`), { code: "ENOTFOUND" }) };
70
- }, He = (r, t, e) => {
71
- const n = t.family === 4 || t.family === "IPv4" ? 4 : t.family === 6 || t.family === "IPv6" ? 6 : 0;
72
- $e(r, n).then((o) => {
69
+ return f !== void 0 ? { error: null, family: 6, addresses: [f, ...S] } : n.status === "rejected" ? { error: n.reason } : o.status === "rejected" ? { error: o.reason } : { error: Object.assign(new Error(`No address for ${t}`), { code: "ENOTFOUND" }) };
70
+ }, He = (t, r, e) => {
71
+ const n = r.family === 4 || r.family === "IPv4" ? 4 : r.family === 6 || r.family === "IPv6" ? 6 : 0;
72
+ $e(t, n).then((o) => {
73
73
  if (o.error !== null) {
74
74
  e(o.error, "");
75
75
  return;
76
76
  }
77
77
  const { family: s, addresses: a } = o;
78
- t.all === !0 ? e(
78
+ r.all === !0 ? e(
79
79
  null,
80
80
  a.map((i) => ({ address: i, family: s }))
81
81
  ) : e(null, a[0], s);
82
82
  });
83
- }, je = /* @__PURE__ */ new Set(["127.0.0.1", "0.0.0.0", "[::1]"]), ze = [".local", ".internal", ".home.arpa"], j = (r, t) => {
83
+ }, je = /* @__PURE__ */ new Set(["127.0.0.1", "0.0.0.0", "[::1]"]), Ke = [".local", ".internal", ".home.arpa"], j = (t, r) => {
84
84
  let e;
85
85
  try {
86
- e = new URL(r);
86
+ e = new URL(t);
87
87
  } catch {
88
88
  return { ok: !1, reason: "forbidden-url", detail: "Invalid URL" };
89
89
  }
@@ -93,79 +93,79 @@ const $ = (r) => {
93
93
  return { ok: !1, reason: "forbidden-url", detail: "URLs with a user name or password are not allowed" };
94
94
  e.hash = "";
95
95
  const n = e.hostname.replace(/\.+$/u, "");
96
- return n === "localhost" || n.endsWith(".localhost") || je.has(n) ? { ok: !1, reason: "private-network", detail: "Localhost access is not allowed" } : $(n) ? { ok: !1, reason: "private-network", detail: "Private network access is not allowed" } : !(n.startsWith("[") || n.includes(".")) || ze.some((s) => n.endsWith(s)) ? { ok: !1, reason: "private-network", detail: "Internal domain access is not allowed" } : { ok: !0, href: e.href };
97
- }, ce = (r) => {
98
- let t;
96
+ return n === "localhost" || n.endsWith(".localhost") || je.has(n) ? { ok: !1, reason: "private-network", detail: "Localhost access is not allowed" } : $(n) ? { ok: !1, reason: "private-network", detail: "Private network access is not allowed" } : !(n.startsWith("[") || n.includes(".")) || Ke.some((s) => n.endsWith(s)) ? { ok: !1, reason: "private-network", detail: "Internal domain access is not allowed" } : { ok: !0, href: e.href };
97
+ }, ce = (t) => {
98
+ let r;
99
99
  try {
100
- t = new URL(r);
100
+ r = new URL(t);
101
101
  } catch {
102
102
  return "(unparsable URL)";
103
103
  }
104
- return t.protocol !== "http:" && t.protocol !== "https:" ? `(a ${t.protocol} URL)` : (t.username = "", t.password = "", t.href);
105
- }, ue = 1024, Je = /^[\t\n\f\r ]$/u, w = (r) => Je.test(r), B = (r) => r.replace(/[A-Z]/gu, (t) => t.toLowerCase()), H = (r) => {
104
+ return r.protocol !== "http:" && r.protocol !== "https:" ? `(a ${r.protocol} URL)` : (r.username = "", r.password = "", r.href);
105
+ }, ue = 1024, ze = /^[\t\n\f\r ]$/u, w = (t) => ze.test(t), B = (t) => t.replace(/[A-Z]/gu, (r) => r.toLowerCase()), H = (t) => {
106
106
  try {
107
- return new TextDecoder(r).encoding;
107
+ return new TextDecoder(t).encoding;
108
108
  } catch {
109
109
  return null;
110
110
  }
111
- }, Ke = (r) => r[0] === 239 && r[1] === 187 && r[2] === 191 ? "utf-8" : r[0] === 254 && r[1] === 255 ? "utf-16be" : r[0] === 255 && r[1] === 254 ? "utf-16le" : null, Fe = (r) => {
112
- for (const t of r.split(";").slice(1)) {
113
- const e = t.indexOf("=");
114
- if (e !== -1 && t.slice(0, e).trim().toLowerCase() === "charset")
115
- return t.slice(e + 1).trim().replace(/^"(.*)"$/su, "$1");
111
+ }, Je = (t) => t[0] === 239 && t[1] === 187 && t[2] === 191 ? "utf-8" : t[0] === 254 && t[1] === 255 ? "utf-16be" : t[0] === 255 && t[1] === 254 ? "utf-16le" : null, Fe = (t) => {
112
+ for (const r of t.split(";").slice(1)) {
113
+ const e = r.indexOf("=");
114
+ if (e !== -1 && r.slice(0, e).trim().toLowerCase() === "charset")
115
+ return r.slice(e + 1).trim().replace(/^"(.*)"$/su, "$1");
116
116
  }
117
117
  return null;
118
- }, Ge = (r) => {
119
- let t = 0;
118
+ }, Ge = (t) => {
119
+ let r = 0;
120
120
  for (; ; ) {
121
- const e = r.indexOf("charset", t);
121
+ const e = t.indexOf("charset", r);
122
122
  if (e === -1) return null;
123
123
  let n = e + 7;
124
- for (; w(r.charAt(n)); ) n += 1;
125
- if (r.charAt(n) !== "=") {
126
- t = n;
124
+ for (; w(t.charAt(n)); ) n += 1;
125
+ if (t.charAt(n) !== "=") {
126
+ r = n;
127
127
  continue;
128
128
  }
129
- for (n += 1; w(r.charAt(n)); ) n += 1;
130
- const o = r.charAt(n);
129
+ for (n += 1; w(t.charAt(n)); ) n += 1;
130
+ const o = t.charAt(n);
131
131
  if (o === '"' || o === "'") {
132
- const a = r.indexOf(o, n + 1);
133
- return a === -1 ? null : r.slice(n + 1, a);
132
+ const a = t.indexOf(o, n + 1);
133
+ return a === -1 ? null : t.slice(n + 1, a);
134
134
  }
135
- const s = r.slice(n).search(/[\t\n\f\r ;]/u);
136
- return s === -1 ? r.slice(n) : r.slice(n, n + s);
135
+ const s = t.slice(n).search(/[\t\n\f\r ;]/u);
136
+ return s === -1 ? t.slice(n) : t.slice(n, n + s);
137
137
  }
138
- }, de = (r, t) => {
139
- let e = t;
140
- for (; w(r.charAt(e)) || r.charAt(e) === "/"; ) e += 1;
141
- if (r.charAt(e) === ">" || e >= r.length) return { attribute: null, end: e };
138
+ }, de = (t, r) => {
139
+ let e = r;
140
+ for (; w(t.charAt(e)) || t.charAt(e) === "/"; ) e += 1;
141
+ if (t.charAt(e) === ">" || e >= t.length) return { attribute: null, end: e };
142
142
  let n = "";
143
143
  for (; ; ) {
144
- const a = r.charAt(e);
144
+ const a = t.charAt(e);
145
145
  if (a === "") return { attribute: null, end: e };
146
146
  if (a === "=" && n !== "") break;
147
147
  if (w(a)) {
148
- for (; w(r.charAt(e)); ) e += 1;
149
- if (r.charAt(e) !== "=") return { attribute: { name: n, value: "" }, end: e };
148
+ for (; w(t.charAt(e)); ) e += 1;
149
+ if (t.charAt(e) !== "=") return { attribute: { name: n, value: "" }, end: e };
150
150
  break;
151
151
  }
152
152
  if (a === "/" || a === ">") return { attribute: { name: n, value: "" }, end: e };
153
153
  n += B(a), e += 1;
154
154
  }
155
- for (e += 1; w(r.charAt(e)); ) e += 1;
156
- const o = r.charAt(e);
155
+ for (e += 1; w(t.charAt(e)); ) e += 1;
156
+ const o = t.charAt(e);
157
157
  if (o === '"' || o === "'") {
158
- const a = r.indexOf(o, e + 1);
159
- return a === -1 ? { attribute: null, end: r.length } : { attribute: { name: n, value: B(r.slice(e + 1, a)) }, end: a + 1 };
158
+ const a = t.indexOf(o, e + 1);
159
+ return a === -1 ? { attribute: null, end: t.length } : { attribute: { name: n, value: B(t.slice(e + 1, a)) }, end: a + 1 };
160
160
  }
161
161
  if (o === ">") return { attribute: { name: n, value: "" }, end: e };
162
- const s = r.slice(e).search(/[\t\n\f\r >]/u);
163
- return s === -1 ? { attribute: null, end: r.length } : { attribute: { name: n, value: B(r.slice(e, e + s)) }, end: e + s };
164
- }, Xe = (r, t) => {
162
+ const s = t.slice(e).search(/[\t\n\f\r >]/u);
163
+ return s === -1 ? { attribute: null, end: t.length } : { attribute: { name: n, value: B(t.slice(e, e + s)) }, end: e + s };
164
+ }, Xe = (t, r) => {
165
165
  const e = /* @__PURE__ */ new Set();
166
- let n = !1, o = null, s = null, a = t;
166
+ let n = !1, o = null, s = null, a = r;
167
167
  for (; ; ) {
168
- const { attribute: i, end: l } = de(r, a);
168
+ const { attribute: i, end: l } = de(t, a);
169
169
  if (a = l, i === null) break;
170
170
  if (!e.has(i.name))
171
171
  if (e.add(i.name), i.name === "http-equiv")
@@ -176,110 +176,110 @@ const $ = (r) => {
176
176
  } else i.name === "charset" && (s = H(i.value) ?? !1, o = !1);
177
177
  }
178
178
  return o === null || typeof s != "string" || o && !n ? { encoding: null, end: a } : s === "utf-16be" || s === "utf-16le" ? { encoding: "utf-8", end: a } : { encoding: s === "x-user-defined" ? "windows-1252" : s, end: a };
179
- }, Ve = (r) => {
180
- const t = Array.from(r.subarray(0, ue), (n) => String.fromCharCode(n)).join("");
179
+ }, Ve = (t) => {
180
+ const r = Array.from(t.subarray(0, ue), (n) => String.fromCharCode(n)).join("");
181
181
  let e = 0;
182
- for (; e < t.length; )
183
- if (t.startsWith("<!--", e)) {
184
- const n = t.indexOf("-->", e + 2);
182
+ for (; e < r.length; )
183
+ if (r.startsWith("<!--", e)) {
184
+ const n = r.indexOf("-->", e + 2);
185
185
  if (n === -1) return null;
186
186
  e = n + 3;
187
- } else if (/^<meta[\t\n\f\r /]$/iu.test(t.slice(e, e + 6))) {
188
- const { encoding: n, end: o } = Xe(t, e + 5);
187
+ } else if (/^<meta[\t\n\f\r /]$/iu.test(r.slice(e, e + 6))) {
188
+ const { encoding: n, end: o } = Xe(r, e + 5);
189
189
  if (n !== null) return n;
190
190
  e = o + 1;
191
- } else if (/^<\/?[A-Za-z]/u.test(t.slice(e, e + 3))) {
191
+ } else if (/^<\/?[A-Za-z]/u.test(r.slice(e, e + 3))) {
192
192
  let n = e + 1;
193
- for (; n < t.length && !w(t.charAt(n)) && t.charAt(n) !== ">"; ) n += 1;
193
+ for (; n < r.length && !w(r.charAt(n)) && r.charAt(n) !== ">"; ) n += 1;
194
194
  for (; ; ) {
195
- const o = de(t, n);
195
+ const o = de(r, n);
196
196
  if (n = o.end, o.attribute === null) break;
197
197
  }
198
198
  e = n + 1;
199
- } else if (/^<[!/?]$/u.test(t.slice(e, e + 2))) {
200
- const n = t.indexOf(">", e + 1);
199
+ } else if (/^<[!/?]$/u.test(r.slice(e, e + 2))) {
200
+ const n = r.indexOf(">", e + 1);
201
201
  if (n === -1) return null;
202
202
  e = n + 1;
203
203
  } else
204
204
  e += 1;
205
205
  return null;
206
- }, We = (r, t) => {
207
- const e = Ke(r);
206
+ }, We = (t, r) => {
207
+ const e = Je(t);
208
208
  if (e !== null) return e;
209
- const n = Fe(t), o = n === null ? null : H(n);
210
- return o !== null ? o : Ve(r) ?? "utf-8";
211
- }, Ye = (r, t) => {
212
- const e = new Uint8Array(t);
209
+ const n = Fe(r), o = n === null ? null : H(n);
210
+ return o !== null ? o : Ve(t) ?? "utf-8";
211
+ }, Ye = (t, r) => {
212
+ const e = new Uint8Array(r);
213
213
  let n = 0;
214
- for (const o of r)
214
+ for (const o of t)
215
215
  e.set(o, n), n += o.byteLength;
216
216
  return e;
217
- }, Ze = (r) => {
218
- const t = [];
217
+ }, Ze = (t) => {
218
+ const r = [];
219
219
  let e = 0, n = null;
220
220
  const o = () => {
221
- const s = Ye(t, e);
222
- t.length = 0;
223
- const a = new TextDecoder(We(s, r));
221
+ const s = Ye(r, e);
222
+ r.length = 0;
223
+ const a = new TextDecoder(We(s, t));
224
224
  return n = a, { started: a, text: a.decode(s, { stream: !0 }) };
225
225
  };
226
226
  return {
227
- write: (s) => n !== null ? n.decode(s, { stream: !0 }) : (t.push(s), e += s.byteLength, e < ue ? "" : o().text),
227
+ write: (s) => n !== null ? n.decode(s, { stream: !0 }) : (r.push(s), e += s.byteLength, e < ue ? "" : o().text),
228
228
  end: () => {
229
229
  if (n !== null) return n.decode();
230
230
  const { started: s, text: a } = o();
231
231
  return a + s.decode();
232
232
  }
233
233
  };
234
- }, qe = (r, t, e) => {
234
+ }, qe = (t, r, e) => {
235
235
  const n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
236
236
  return (s) => {
237
237
  const a = n.get(s);
238
238
  if (a !== void 0 && a.expireAt > e()) return Promise.resolve(a.value);
239
239
  const i = o.get(s);
240
240
  if (i !== void 0) return i;
241
- const l = r(s).then((c) => (!n.has(s) && n.size >= t.maxEntries && n.delete(n.keys().next().value), n.set(s, { value: c, expireAt: e() + t.ttlMsOf(c) }), c)).finally(() => {
241
+ const l = t(s).then((c) => (!n.has(s) && n.size >= r.maxEntries && n.delete(n.keys().next().value), n.set(s, { value: c, expireAt: e() + r.ttlMsOf(c) }), c)).finally(() => {
242
242
  o.delete(s);
243
243
  });
244
244
  return o.set(s, l), l;
245
245
  };
246
- }, Qe = 65536, et = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]), tt = /* @__PURE__ */ new Set(["text/html", "application/xhtml+xml"]), rt = /* @__PURE__ */ new Set(["ERR_IP_BLOCKED", le]), fe = Object.freeze({ timeoutMs: 5e3, maxRedirects: 5, maxBodyBytes: 8 * 1024 * 1024 }), nt = Object.freeze({ lookup: He, blockList: T }), ot = (r, t) => {
247
- const e = Y({ lookup: r.lookup, blockList: r.blockList, timeout: t }), n = Y({ timeout: t });
246
+ }, Qe = 65536, et = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]), tt = /* @__PURE__ */ new Set(["text/html", "application/xhtml+xml"]), rt = /* @__PURE__ */ new Set(["ERR_IP_BLOCKED", le]), fe = Object.freeze({ timeoutMs: 5e3, maxRedirects: 5, maxBodyBytes: 8 * 1024 * 1024 }), nt = Object.freeze({ lookup: He, blockList: T }), ot = (t, r) => {
247
+ const e = Y({ lookup: t.lookup, blockList: t.blockList, timeout: r }), n = Y({ timeout: r });
248
248
  return (o, s) => {
249
249
  if (o.protocol !== "https:") {
250
250
  e(o, s);
251
251
  return;
252
252
  }
253
- const a = Se({ host: o.hostname, port: Number(o.port === "" ? 443 : o.port), lookup: r.lookup, blockList: r.blockList }), i = (l) => {
253
+ const a = Se({ host: o.hostname, port: Number(o.port === "" ? 443 : o.port), lookup: t.lookup, blockList: t.blockList }), i = (l) => {
254
254
  a.destroy(), s(l, null);
255
255
  };
256
- a.setTimeout(t, () => i(Object.assign(new Error(`Connect timeout: ${o.hostname}`), { code: "UND_ERR_CONNECT_TIMEOUT" }))), a.once("error", i), a.once("connect", () => {
256
+ a.setTimeout(r, () => i(Object.assign(new Error(`Connect timeout: ${o.hostname}`), { code: "UND_ERR_CONNECT_TIMEOUT" }))), a.once("error", i), a.once("connect", () => {
257
257
  a.setTimeout(0), a.removeListener("error", i), n({ ...o, httpSocket: a }, s);
258
258
  });
259
259
  };
260
- }, at = (r) => new ye({
260
+ }, at = (t) => new ye({
261
261
  maxHeaderSize: Qe,
262
262
  connect: ot(nt, fe.timeoutMs)
263
- }), U = async (r) => {
264
- r.body !== null && await Promise.allSettled([r.body.cancel()]);
265
- }, st = (r) => r !== null && tt.has(r.split(";", 1)[0].trim().toLowerCase()), it = (r) => {
266
- const t = [r];
267
- for (let e = 0; e < 16 && t.length > 0; e += 1) {
268
- const n = t.shift();
263
+ }), U = async (t) => {
264
+ t.body !== null && await Promise.allSettled([t.body.cancel()]);
265
+ }, st = (t) => t !== null && tt.has(t.split(";", 1)[0].trim().toLowerCase()), it = (t) => {
266
+ const r = [t];
267
+ for (let e = 0; e < 16 && r.length > 0; e += 1) {
268
+ const n = r.shift();
269
269
  if (!(n instanceof Error)) continue;
270
270
  const o = n.code;
271
271
  if (typeof o == "string" && rt.has(o)) return n.message;
272
- t.push(n.cause, ...n instanceof AggregateError ? n.errors : []);
272
+ r.push(n.cause, ...n instanceof AggregateError ? n.errors : []);
273
273
  }
274
274
  return null;
275
- }, me = (r, t) => {
276
- const e = it(r);
277
- return e !== null ? (h.info("Refused link-card connection to a private address:", t, e), { ok: !1, reason: "private-network" }) : (h.error("Error fetching link-card metadata:", r), { ok: !1, reason: "unreachable" });
278
- }, lt = () => new Promise((r) => {
279
- setImmediate(r);
280
- }), ct = async (r, t, e, n) => {
281
- if (r.body === null) return { ok: !0, value: t.end() };
282
- const o = r.body.getReader();
275
+ }, me = (t, r) => {
276
+ const e = it(t);
277
+ return e !== null ? (h.info("Refused link-card connection to a private address:", r, e), { ok: !1, reason: "private-network" }) : (h.error("Error fetching link-card metadata:", t), { ok: !1, reason: "unreachable" });
278
+ }, lt = () => new Promise((t) => {
279
+ setImmediate(t);
280
+ }), ct = async (t, r, e, n) => {
281
+ if (t.body === null) return { ok: !0, value: r.end() };
282
+ const o = t.body.getReader();
283
283
  let s = 0;
284
284
  for (; ; ) {
285
285
  let a;
@@ -290,7 +290,7 @@ const $ = (r) => {
290
290
  }
291
291
  if (a.done) break;
292
292
  const i = e - s, l = a.value.byteLength > i, c = l ? a.value.subarray(0, i) : a.value;
293
- if (s += c.byteLength, !t.write(c)) {
293
+ if (s += c.byteLength, !r.write(c)) {
294
294
  await Promise.allSettled([o.cancel()]);
295
295
  break;
296
296
  }
@@ -300,13 +300,13 @@ const $ = (r) => {
300
300
  }
301
301
  await lt();
302
302
  }
303
- return { ok: !0, value: t.end() };
304
- }, ut = async (r, t, e, n) => {
305
- let o = r;
306
- for (let s = 0; s <= t.limits.maxRedirects; s += 1) {
303
+ return { ok: !0, value: r.end() };
304
+ }, ut = async (t, r, e, n) => {
305
+ let o = t;
306
+ for (let s = 0; s <= r.limits.maxRedirects; s += 1) {
307
307
  let a;
308
308
  try {
309
- a = await Ae(o, { signal: n, redirect: "manual", dispatcher: t.agent });
309
+ a = await Ae(o, { signal: n, redirect: "manual", dispatcher: r.agent });
310
310
  } catch (f) {
311
311
  return me(f, o);
312
312
  }
@@ -315,7 +315,7 @@ const $ = (r) => {
315
315
  if (!a.ok)
316
316
  return await U(a), { ok: !1, reason: "unreachable" };
317
317
  const f = a.headers.get("content-type");
318
- return st(f) ? ct(a, e({ url: o, contentType: f }), t.limits.maxBodyBytes, o) : (await U(a), { ok: !1, reason: "not-html" });
318
+ return st(f) ? ct(a, e({ url: o, contentType: f }), r.limits.maxBodyBytes, o) : (await U(a), { ok: !1, reason: "not-html" });
319
319
  }
320
320
  await U(a);
321
321
  let l;
@@ -329,42 +329,42 @@ const $ = (r) => {
329
329
  return h.info("Refused link-card redirect:", ce(l), `(${c.reason}: ${c.detail})`), { ok: !1, reason: c.reason };
330
330
  o = c.href;
331
331
  }
332
- return h.error("Too many redirects while fetching link-card metadata:", r), { ok: !1, reason: "unreachable" };
333
- }, dt = (r, t, e) => {
334
- const n = new AbortController(), o = setTimeout(() => n.abort(), t.limits.timeoutMs);
335
- return ut(r, t, e, n.signal).finally(() => {
332
+ return h.error("Too many redirects while fetching link-card metadata:", t), { ok: !1, reason: "unreachable" };
333
+ }, dt = (t, r, e) => {
334
+ const n = new AbortController(), o = setTimeout(() => n.abort(), r.limits.timeoutMs);
335
+ return ut(t, r, e, n.signal).finally(() => {
336
336
  clearTimeout(o);
337
337
  });
338
- }, ft = 256, mt = 4096, pt = 64, ht = /* @__PURE__ */ new Set(["html", "head", "title", "meta", "link", "base", "basefont", "bgsound", "noframes", "script", "style", "template", "noscript"]), wt = /* @__PURE__ */ new Set(["title", "script", "style"]), gt = /* @__PURE__ */ new Set(["noscript", "template", "noframes"]), kt = (r) => r?.toLowerCase().split(/[\t\n\f\r ]+/u).includes("icon") === !0, bt = (r, t) => {
339
- if (r === void 0) return t;
338
+ }, ft = 256, mt = 4096, pt = 64, ht = /* @__PURE__ */ new Set(["html", "head", "title", "meta", "link", "base", "basefont", "bgsound", "noframes", "script", "style", "template", "noscript"]), wt = /* @__PURE__ */ new Set(["title", "script", "style"]), gt = /* @__PURE__ */ new Set(["noscript", "template", "noframes"]), kt = (t) => t?.toLowerCase().split(/[\t\n\f\r ]+/u).includes("icon") === !0, bt = (t, r) => {
339
+ if (t === void 0) return r;
340
340
  let e;
341
341
  try {
342
- e = new URL(r, t);
342
+ e = new URL(t, r);
343
343
  } catch {
344
- return t;
344
+ return r;
345
345
  }
346
- return (e.protocol === "http:" || e.protocol === "https:") && e.href.length <= ae ? e.href : t;
347
- }, ee = (r, t, e) => {
348
- const n = r?.trim();
346
+ return (e.protocol === "http:" || e.protocol === "https:") && e.href.length <= ae ? e.href : r;
347
+ }, ee = (t, r, e) => {
348
+ const n = t?.trim();
349
349
  if (n === void 0 || n === "") return;
350
350
  let o;
351
351
  try {
352
- o = new URL(n, t);
352
+ o = new URL(n, r);
353
353
  } catch {
354
354
  return;
355
355
  }
356
356
  return o.href.length <= ae && j(o.href).ok ? o.href : void 0;
357
- }, Et = (r, t) => {
358
- let e = !1, n = 0, o = 0, s = 0, a = null, i = null, l = null, c, f, S, R, z, J, K = !1, F, G = !1;
359
- const N = () => {
357
+ }, Et = (t, r) => {
358
+ let e = !1, n = 0, o = 0, s = 0, a = null, i = null, l = null, c, f, S, R, K, z, J = !1, F, G = !1;
359
+ const x = () => {
360
360
  e = !0, D.pause();
361
361
  }, D = new _e(
362
362
  {
363
363
  onopentagname(u) {
364
- n += 1, o += 1, s = 0, (n > ft || o > mt || a === null && !ht.has(u)) && N();
364
+ n += 1, o += 1, s = 0, (n > ft || o > mt || a === null && !ht.has(u)) && x();
365
365
  },
366
366
  onattribute() {
367
- s += 1, s > pt && N();
367
+ s += 1, s > pt && x();
368
368
  },
369
369
  onopentag(u, m) {
370
370
  if (!(e || a !== null)) {
@@ -374,13 +374,13 @@ const $ = (r) => {
374
374
  }
375
375
  if (u === "meta") {
376
376
  const p = m.content;
377
- m.property === "og:site_name" && (R = p), m.property === "og:title" && (f = p), m.property === "og:description" && (S = p), m.property === "og:image" && (z = p), m.name === "description" && (S = p);
378
- } else u === "link" && !K && kt(m.rel) ? (K = !0, J = m.href) : u === "base" && !G && Object.hasOwn(m, "href") && (G = !0, F = m.href);
377
+ m.property === "og:site_name" && (R = p), m.property === "og:title" && (f = p), m.property === "og:description" && (S = p), m.property === "og:image" && (K = p), m.name === "description" && (S = p);
378
+ } else u === "link" && !J && kt(m.rel) ? (J = !0, z = m.href) : u === "base" && !G && Object.hasOwn(m, "href") && (G = !0, F = m.href);
379
379
  wt.has(u) && (i = u, u === "title" && c === void 0 && (l = ""));
380
380
  }
381
381
  },
382
382
  ontext(u) {
383
- a === null && (l !== null ? l += u : i === null && /[^\t\n\f\r ]/u.test(u) && N());
383
+ a === null && (l !== null ? l += u : i === null && /[^\t\n\f\r ]/u.test(u) && x());
384
384
  },
385
385
  onclosetag(u) {
386
386
  if (!e) {
@@ -398,7 +398,7 @@ const $ = (r) => {
398
398
  write: (u) => (e || D.write(u), !e),
399
399
  end: () => {
400
400
  e || D.end();
401
- const u = L(f, O.title) ?? L(c, O.title), m = L(S, O.description), p = L(R, O.siteName), X = bt(F, r), V = ee(z, X), W = ee(J, X);
401
+ const u = L(f, O.title) ?? L(c, O.title), m = L(S, O.description), p = L(R, O.siteName), X = bt(F, t), V = ee(K, X), W = ee(z, X);
402
402
  return {
403
403
  ...u === null ? {} : { title: u },
404
404
  ...m === null ? {} : { description: m },
@@ -408,30 +408,30 @@ const $ = (r) => {
408
408
  };
409
409
  }
410
410
  };
411
- }, Tt = /* @__PURE__ */ new Set(["authorize"]), vt = "private, max-age=1800", St = 3600 * 1e3, pe = Object.freeze({ "private-network": 1800, "forbidden-url": 1800, unreachable: 300, "not-html": 300 }), yt = 1e3, P = "no-store", y = (r, t, e, n, o = {}) => new Response(r.method === "HEAD" ? null : JSON.stringify(e), {
412
- status: t,
411
+ }, vt = /* @__PURE__ */ new Set(["authorize"]), Tt = "private, max-age=1800", St = 3600 * 1e3, pe = Object.freeze({ "private-network": 1800, "forbidden-url": 1800, unreachable: 300, "not-html": 300 }), yt = 1e3, P = "no-store", y = (t, r, e, n, o = {}) => new Response(t.method === "HEAD" ? null : JSON.stringify(e), {
412
+ status: r,
413
413
  headers: { "Content-Type": "application/json; charset=utf-8", "Cache-Control": n, "X-Content-Type-Options": "nosniff", ...o }
414
- }), te = (r) => new Response(null, {
414
+ }), te = (t) => new Response(null, {
415
415
  status: 204,
416
- headers: { "Cache-Control": `private, max-age=${pe[r]}`, "X-Content-Type-Options": "nosniff", [Ee]: r }
417
- }), At = (r) => {
418
- if (typeof r != "object" || r === null)
416
+ headers: { "Cache-Control": `private, max-age=${pe[t]}`, "X-Content-Type-Options": "nosniff", [Ee]: t }
417
+ }), At = (t) => {
418
+ if (typeof t != "object" || t === null)
419
419
  throw new TypeError("createLinkCardHandler: options must be an object with an authorize function");
420
- if (typeof r.authorize != "function")
420
+ if (typeof t.authorize != "function")
421
421
  throw new TypeError("createLinkCardHandler: options.authorize must be a function (pass () => true to serve everyone)");
422
- const t = Object.keys(r).filter((e) => !Tt.has(e));
423
- if (t.length > 0)
424
- throw new TypeError(`createLinkCardHandler: unknown option(s): ${t.join(", ")}`);
425
- }, _t = (r) => (t) => {
426
- const e = Ze(t.contentType), n = Et(t.url);
422
+ const r = Object.keys(t).filter((e) => !vt.has(e));
423
+ if (r.length > 0)
424
+ throw new TypeError(`createLinkCardHandler: unknown option(s): ${r.join(", ")}`);
425
+ }, _t = (t) => (r) => {
426
+ const e = Ze(r.contentType), n = Et(r.url);
427
427
  return {
428
428
  write: (o) => n.write(e.write(o)),
429
429
  end: () => (n.write(e.end()), n.end())
430
430
  };
431
- }, Rt = (r, t) => {
432
- At(r);
433
- const { authorize: e } = r, n = at(), o = qe(
434
- (s) => dt(s, { agent: n, scope: t, limits: fe }, _t()),
431
+ }, Rt = (t, r) => {
432
+ At(t);
433
+ const { authorize: e } = t, n = at(), o = qe(
434
+ (s) => dt(s, { agent: n, scope: r, limits: fe }, _t()),
435
435
  { maxEntries: yt, ttlMsOf: (s) => s.ok ? St : pe[s.reason] * 1e3 },
436
436
  Date.now
437
437
  );
@@ -452,10 +452,10 @@ const $ = (r) => {
452
452
  } catch (c) {
453
453
  return h.error("Unexpected error while reading link-card metadata:", i.href, c), y(s, 500, { error: "Internal Server Error" }, P);
454
454
  }
455
- return l.ok ? y(s, 200, l.value, vt) : te(l.reason);
455
+ return l.ok ? y(s, 200, l.value, Tt) : te(l.reason);
456
456
  };
457
- }, Yt = (r) => Rt(r, "public");
458
- class k extends x {
457
+ }, Yt = (t) => Rt(t, "public");
458
+ class b extends N {
459
459
  /**
460
460
  * @generated from field: string markdown_text = 1;
461
461
  */
@@ -564,8 +564,8 @@ class k extends x {
564
564
  * @generated from field: bool include_source_lines = 14;
565
565
  */
566
566
  includeSourceLines = !1;
567
- constructor(t) {
568
- super(), d.util.initPartial(t, this);
567
+ constructor(r) {
568
+ super(), d.util.initPartial(r, this);
569
569
  }
570
570
  static runtime = d;
571
571
  static typeName = "markdown.v1.ConvertRequest";
@@ -621,44 +621,44 @@ class k extends x {
621
621
  /* ScalarType.BOOL */
622
622
  }
623
623
  ]);
624
- static fromBinary(t, e) {
625
- return new k().fromBinary(t, e);
624
+ static fromBinary(r, e) {
625
+ return new b().fromBinary(r, e);
626
626
  }
627
- static fromJson(t, e) {
628
- return new k().fromJson(t, e);
627
+ static fromJson(r, e) {
628
+ return new b().fromJson(r, e);
629
629
  }
630
- static fromJsonString(t, e) {
631
- return new k().fromJsonString(t, e);
630
+ static fromJsonString(r, e) {
631
+ return new b().fromJsonString(r, e);
632
632
  }
633
- static equals(t, e) {
634
- return d.util.equals(k, t, e);
633
+ static equals(r, e) {
634
+ return d.util.equals(b, r, e);
635
635
  }
636
636
  }
637
- class g extends x {
637
+ class g extends N {
638
638
  /**
639
639
  * @generated from field: repeated string segment_patterns = 1;
640
640
  */
641
641
  segmentPatterns = [];
642
- constructor(t) {
643
- super(), d.util.initPartial(t, this);
642
+ constructor(r) {
643
+ super(), d.util.initPartial(r, this);
644
644
  }
645
645
  static runtime = d;
646
646
  static typeName = "markdown.v1.DenyRules";
647
647
  static fields = d.util.newFieldList(() => [{ no: 1, name: "segment_patterns", kind: "scalar", T: 9, repeated: !0 }]);
648
- static fromBinary(t, e) {
649
- return new g().fromBinary(t, e);
648
+ static fromBinary(r, e) {
649
+ return new g().fromBinary(r, e);
650
650
  }
651
- static fromJson(t, e) {
652
- return new g().fromJson(t, e);
651
+ static fromJson(r, e) {
652
+ return new g().fromJson(r, e);
653
653
  }
654
- static fromJsonString(t, e) {
655
- return new g().fromJsonString(t, e);
654
+ static fromJsonString(r, e) {
655
+ return new g().fromJsonString(r, e);
656
656
  }
657
- static equals(t, e) {
658
- return d.util.equals(g, t, e);
657
+ static equals(r, e) {
658
+ return d.util.equals(g, r, e);
659
659
  }
660
660
  }
661
- class b extends x {
661
+ class E extends N {
662
662
  /**
663
663
  * @generated from field: string html_content = 1;
664
664
  */
@@ -667,8 +667,8 @@ class b extends x {
667
667
  * @generated from field: repeated markdown.v1.Heading headings = 2;
668
668
  */
669
669
  headings = [];
670
- constructor(t) {
671
- super(), d.util.initPartial(t, this);
670
+ constructor(r) {
671
+ super(), d.util.initPartial(r, this);
672
672
  }
673
673
  static runtime = d;
674
674
  static typeName = "markdown.v1.ConvertResponse";
@@ -680,22 +680,22 @@ class b extends x {
680
680
  T: 9
681
681
  /* ScalarType.STRING */
682
682
  },
683
- { no: 2, name: "headings", kind: "message", T: E, repeated: !0 }
683
+ { no: 2, name: "headings", kind: "message", T: v, repeated: !0 }
684
684
  ]);
685
- static fromBinary(t, e) {
686
- return new b().fromBinary(t, e);
685
+ static fromBinary(r, e) {
686
+ return new E().fromBinary(r, e);
687
687
  }
688
- static fromJson(t, e) {
689
- return new b().fromJson(t, e);
688
+ static fromJson(r, e) {
689
+ return new E().fromJson(r, e);
690
690
  }
691
- static fromJsonString(t, e) {
692
- return new b().fromJsonString(t, e);
691
+ static fromJsonString(r, e) {
692
+ return new E().fromJsonString(r, e);
693
693
  }
694
- static equals(t, e) {
695
- return d.util.equals(b, t, e);
694
+ static equals(r, e) {
695
+ return d.util.equals(E, r, e);
696
696
  }
697
697
  }
698
- class E extends x {
698
+ class v extends N {
699
699
  /**
700
700
  * @generated from field: string text = 1;
701
701
  */
@@ -708,8 +708,8 @@ class E extends x {
708
708
  * @generated from field: string id = 3;
709
709
  */
710
710
  id = "";
711
- constructor(t) {
712
- super(), d.util.initPartial(t, this);
711
+ constructor(r) {
712
+ super(), d.util.initPartial(r, this);
713
713
  }
714
714
  static runtime = d;
715
715
  static typeName = "markdown.v1.Heading";
@@ -736,17 +736,17 @@ class E extends x {
736
736
  /* ScalarType.STRING */
737
737
  }
738
738
  ]);
739
- static fromBinary(t, e) {
740
- return new E().fromBinary(t, e);
739
+ static fromBinary(r, e) {
740
+ return new v().fromBinary(r, e);
741
741
  }
742
- static fromJson(t, e) {
743
- return new E().fromJson(t, e);
742
+ static fromJson(r, e) {
743
+ return new v().fromJson(r, e);
744
744
  }
745
- static fromJsonString(t, e) {
746
- return new E().fromJsonString(t, e);
745
+ static fromJsonString(r, e) {
746
+ return new v().fromJsonString(r, e);
747
747
  }
748
- static equals(t, e) {
749
- return d.util.equals(E, t, e);
748
+ static equals(r, e) {
749
+ return d.util.equals(v, r, e);
750
750
  }
751
751
  }
752
752
  const Lt = {
@@ -757,13 +757,18 @@ const Lt = {
757
757
  */
758
758
  convert: {
759
759
  name: "Convert",
760
- I: k,
761
- O: b,
760
+ I: b,
761
+ O: E,
762
762
  kind: De.Unary
763
763
  }
764
764
  }
765
- }, v = process.env.MARKDOWN_SOCKET_PATH || "/tmp/markdown.sock", Ot = new xe("http://localhost", void 0, {
766
- createConnection: () => se.connect(v)
765
+ }, k = () => {
766
+ const t = process.env.MARKDOWN_SOCKET_PATH;
767
+ if (t === void 0 || t === "")
768
+ throw new Error("MARKDOWN_SOCKET_PATH is required: set it to the path of the markdown-api service's UNIX domain socket, the same value the service reads");
769
+ return t;
770
+ }, Ot = new Ne("http://localhost", void 0, {
771
+ createConnection: () => se.connect(k())
767
772
  }), re = () => {
768
773
  try {
769
774
  return M.dirname(Pe(import.meta.url));
@@ -771,31 +776,31 @@ const Lt = {
771
776
  return __dirname;
772
777
  }
773
778
  }, he = () => `@aiquants/markdown-${process.platform}-${process.arch}`, ne = () => process.platform === "win32" ? "bin/markdown-api.exe" : "bin/markdown-api", Pt = () => {
774
- const r = process.env.MARKDOWN_API_BINARY;
775
- if (r && C(r))
776
- return r;
779
+ const t = process.env.MARKDOWN_API_BINARY;
780
+ if (t && C(t))
781
+ return t;
777
782
  try {
778
783
  const e = Oe(M.join(re(), "index.js")).resolve(`${he()}/${ne()}`);
779
784
  if (C(e))
780
785
  return e;
781
786
  } catch {
782
787
  }
783
- const t = M.join(re(), "..", "..", "go", "markdown-api", "dist", M.basename(ne()));
784
- return C(t) ? t : void 0;
788
+ const r = M.join(re(), "..", "..", "go", "markdown-api", "dist", M.basename(ne()));
789
+ return C(r) ? r : void 0;
785
790
  }, Ct = () => [
786
791
  `markdown-api binary not found for ${process.platform}-${process.arch}.`,
787
792
  `Expected the optional dependency ${he()} to be installed.`,
788
793
  "If your platform is unsupported, build the service yourself",
789
794
  "(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)",
790
795
  "and point MARKDOWN_API_BINARY at it."
791
- ].join(" "), we = () => new Promise((r) => {
792
- const t = se.connect(v);
793
- t.on("connect", () => {
794
- t.destroy(), r(!0);
795
- }), t.on("error", () => r(!1));
796
- }), oe = async (r) => {
797
- const t = Date.now();
798
- for (; Date.now() - t < r; ) {
796
+ ].join(" "), we = () => new Promise((t) => {
797
+ const r = se.connect(k());
798
+ r.on("connect", () => {
799
+ r.destroy(), t(!0);
800
+ }), r.on("error", () => t(!1));
801
+ }), oe = async (t) => {
802
+ const r = Date.now();
803
+ for (; Date.now() - r < t; ) {
799
804
  if (await we()) return !0;
800
805
  await new Promise((e) => setTimeout(e, 100));
801
806
  }
@@ -803,24 +808,24 @@ const Lt = {
803
808
  };
804
809
  let A = null, _ = null;
805
810
  const Mt = 2e3, It = () => {
806
- const r = Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);
807
- return Number.isFinite(r) && r > 0 ? r : 1e4;
811
+ const t = Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);
812
+ return Number.isFinite(t) && t > 0 ? t : 1e4;
808
813
  };
809
814
  let I = null;
810
- const xt = async () => {
815
+ const Nt = async () => {
811
816
  if (await we()) return !0;
812
817
  if (_) return _;
813
818
  _ = (async () => {
814
- const t = Pt();
815
- if (!t)
819
+ const r = Pt();
820
+ if (!r)
816
821
  return await oe(Mt) ? !0 : (I = Ct(), !1);
817
822
  I = null;
818
823
  try {
819
- C(v) && Le(v);
824
+ C(k()) && Le(k());
820
825
  } catch {
821
826
  }
822
827
  try {
823
- A = Re(t, [], { stdio: "ignore" });
828
+ A = Re(r, [], { stdio: "ignore" });
824
829
  const e = () => {
825
830
  if (A) {
826
831
  try {
@@ -830,29 +835,29 @@ const xt = async () => {
830
835
  A = null;
831
836
  }
832
837
  };
833
- return process.once("exit", e), await oe(It()) ? !0 : (console.error("markdown-api Go server did not become ready on socket:", v), e(), process.removeListener("exit", e), !1);
838
+ return process.once("exit", e), await oe(It()) ? !0 : (console.error("markdown-api Go server did not become ready on socket:", k()), e(), process.removeListener("exit", e), !1);
834
839
  } catch (e) {
835
840
  return console.error("Failed to spawn markdown-api Go server:", e), A = null, !1;
836
841
  }
837
842
  })();
838
- const r = await _;
839
- return r || (_ = null), r;
840
- }, Nt = (r) => {
841
- if (be(r, "parseMarkdown"), r.timeoutMs !== void 0 && (!Number.isSafeInteger(r.timeoutMs) || r.timeoutMs <= 0))
842
- throw new RangeError(`parseMarkdown: timeoutMs must be a positive integer, got ${r.timeoutMs}`);
843
- }, Zt = async (r, t, e, n, o) => {
844
- if (Nt(o), !await xt()) {
843
+ const t = await _;
844
+ return t || (_ = null), t;
845
+ }, xt = (t) => {
846
+ if (be(t, "parseMarkdown"), t.timeoutMs !== void 0 && (!Number.isSafeInteger(t.timeoutMs) || t.timeoutMs <= 0))
847
+ throw new RangeError(`parseMarkdown: timeoutMs must be a positive integer, got ${t.timeoutMs}`);
848
+ }, Zt = async (t, r, e, n, o) => {
849
+ if (k(), xt(o), !await Nt()) {
845
850
  const i = I ? ` ${I}` : "";
846
- throw new Error(`markdown service is not reachable on ${v}.${i}`);
851
+ throw new Error(`markdown service is not reachable on ${k()}.${i}`);
847
852
  }
848
853
  const s = {};
849
854
  n && (s.Authorization = `Bearer ${n}`);
850
- const a = Ce(Lt, Ne({ baseUrl: "http://localhost", httpVersion: "2", sessionManager: Ot, readMaxBytes: 2 * o.maxHtmlBytes + ge }));
855
+ const a = Ce(Lt, xe({ baseUrl: "http://localhost", httpVersion: "2", sessionManager: Ot, readMaxBytes: 2 * o.maxHtmlBytes + ge }));
851
856
  try {
852
857
  const i = await a.convert(
853
858
  {
854
- markdownText: r,
855
- filePath: t,
859
+ markdownText: t,
860
+ filePath: r,
856
861
  workspaceRoot: e,
857
862
  validateExistence: o.validateExistence ?? !0,
858
863
  enableSubscript: o.enableSubscript,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/markdown",
3
- "version": "6.4.1",
3
+ "version": "7.0.0",
4
4
  "description": "Markdown renderer for React with advanced features",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -161,15 +161,17 @@
161
161
  "access": "public"
162
162
  },
163
163
  "optionalDependencies": {
164
- "@aiquants/markdown-linux-x64": "6.4.1",
165
- "@aiquants/markdown-linux-arm64": "6.4.1",
166
- "@aiquants/markdown-darwin-x64": "6.4.1",
167
- "@aiquants/markdown-darwin-arm64": "6.4.1",
168
- "@aiquants/markdown-win32-x64": "6.4.1",
169
- "@aiquants/markdown-win32-arm64": "6.4.1"
164
+ "@aiquants/markdown-linux-x64": "7.0.0",
165
+ "@aiquants/markdown-linux-arm64": "7.0.0",
166
+ "@aiquants/markdown-darwin-x64": "7.0.0",
167
+ "@aiquants/markdown-darwin-arm64": "7.0.0",
168
+ "@aiquants/markdown-win32-x64": "7.0.0",
169
+ "@aiquants/markdown-win32-arm64": "7.0.0"
170
170
  },
171
171
  "scripts": {
172
- "build": "rimraf dist && vite build && vite build --config vite.config.cli.ts && pnpm build:converter && pnpm build:css && node ../../.config/scripts/strip-dts-comments.mjs dist && node scripts/verify-dist.mjs dist",
172
+ "build": "pnpm -w run workspace:build \"$PNPM_SCRIPT_SRC_DIR\"",
173
+ "prebuild:self": "pnpm -w run workspace:sync \"$PNPM_SCRIPT_SRC_DIR\"",
174
+ "build:self": "rimraf dist && vite build && vite build --config vite.config.cli.ts && pnpm build:converter && pnpm build:css && node ../../.config/scripts/strip-dts-comments.mjs dist && node scripts/verify-dist.mjs dist",
173
175
  "build:converter": "node scripts/build-converter.mjs",
174
176
  "build:css": "tailwindcss -i src/styles/tailwind.css -o dist/styles/markdown.css --minify",
175
177
  "build:go": "go build -C ../go/markdown-api -trimpath -ldflags=\"-s -w\" -o dist/markdown-api .",
@@ -181,9 +183,6 @@
181
183
  "publish:platforms": "node scripts/publish-platform-packages.mjs",
182
184
  "dev": "vite build --watch",
183
185
  "watch": "vite build --watch",
184
- "demo:dev": "cd demo && pnpm run dev",
185
- "demo:build": "cd demo && pnpm run build",
186
- "demo:start": "cd demo && pnpm start",
187
186
  "typecheck": "tsc --noEmit",
188
187
  "test": "vitest",
189
188
  "test:run": "vitest run",