@aiquants/markdown 1.11.0 → 1.13.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
@@ -21,6 +21,45 @@ pnpm add @aiquants/markdown
21
21
  yarn add @aiquants/markdown
22
22
  ```
23
23
 
24
+ ### パーサーバイナリの配布
25
+
26
+ Markdown の解析は Go 製サービス (`markdown-api`) が担当します。このバイナリは**プラットフォーム別のパッケージ**として配布され、パッケージマネージャが実行環境に合うものだけを自動選択します (esbuild や Biome と同じ方式)。本体パッケージにバイナリは含まれません。
27
+
28
+ | プラットフォーム | 対応 |
29
+ | --- | --- |
30
+ | Linux x64 / arm64 | ✅ |
31
+ | macOS x64 (Intel) / arm64 (Apple Silicon) | ✅ |
32
+ | Windows x64 / arm64 | ✅ |
33
+
34
+ `postinstall` スクリプトは不要です (実行権限は npm の `bin` 契約で保証されます)。ライフサイクルスクリプトを禁止している環境でもそのまま動きます。
35
+
36
+ `parseMarkdown` は最初の呼び出し時にサービスが待ち受けていなければ自動起動します。プロセスマネージャ (supervisor / systemd など) で `markdown-api` を別プロセスとして管理している構成では、そのソケットへそのまま接続します。
37
+
38
+ <details>
39
+ <summary>上記以外のプラットフォームで使う</summary>
40
+
41
+ サービスを自分でビルドし、その場所を教えてください。
42
+
43
+ ```bash
44
+ git clone https://github.com/fehde-k/aiquants.git
45
+ cd aiquants/packages/go/markdown-api
46
+ go build -o dist/markdown-api .
47
+ ```
48
+
49
+ ```bash
50
+ export MARKDOWN_API_BINARY=/path/to/markdown-api
51
+ ```
52
+
53
+ </details>
54
+
55
+ ### 環境変数
56
+
57
+ | 変数 | 既定値 | 用途 |
58
+ | --- | --- | --- |
59
+ | `MARKDOWN_SOCKET_PATH` | `/tmp/markdown.sock` | サービスと通信する UNIX ドメインソケットのパス |
60
+ | `MARKDOWN_API_BINARY` | (なし) | 自前ビルドしたバイナリの明示指定 |
61
+ | `MARKDOWN_API_STARTUP_TIMEOUT_MS` | `10000` | 自動起動したサービスが待ち受け開始するまでの猶予 |
62
+
24
63
  ## Usage
25
64
 
26
65
  ### Basic Usage
@@ -47,6 +86,9 @@ console.log("Hello, World!")
47
86
  "/workspace"
48
87
  )
49
88
 
89
+ // parseResult: ParseResult
90
+ // htmlContent: string — レンダリング済み HTML
91
+ // headings: { text: string; depth: number; id: string }[] — 目次構築用の見出し一覧
50
92
  return (
51
93
  <MarkdownRenderer
52
94
  htmlContent={parseResult.htmlContent}
@@ -59,7 +101,7 @@ console.log("Hello, World!")
59
101
 
60
102
  ### Pluggable Parser Options
61
103
 
62
- You can dynamically enable or disable custom extensions using `ParseOptions`:
104
+ You can dynamically enable or disable custom extensions using `ParseOptions` (exported from `@aiquants/markdown/server`):
63
105
 
64
106
  ```tsx
65
107
  const parseResult = await parseMarkdown(
@@ -90,7 +132,7 @@ The parser supports the following extended markdown syntax in addition to Common
90
132
 
91
133
  ### Table cell merge markers
92
134
 
93
- - `>`: horizontal merge (colspan) to the nearest left non-marker cell
135
+ - `>`: horizontal merge (colspan) the marker cell is absorbed into the nearest **right** non-marker cell, which gains the colspan
94
136
  - `^`: vertical merge (rowspan) to the nearest upper non-marker cell
95
137
 
96
138
  ```markdown
@@ -139,7 +181,7 @@ This is a nested warning message inside details.
139
181
 
140
182
  ### Notes
141
183
 
142
- - Single-tilde strikethrough is disabled (`singleTilde: false`) so `~text~` is reserved for subscript.
184
+ - goldmark's GFM strikethrough only recognizes double tildes (`~~text~~`), so single-tilde `~text~` is reserved for subscript.
143
185
  - Double-tilde strikethrough (`~~text~~`) remains available via GFM.
144
186
 
145
187
  ## License
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("node:fs/promises"),w=require("node:path"),x=require("unist-util-visit"),v=require("./simple-logger-DZxBpX7v.cjs"),A=require("cheerio"),C=require("url-join"),j=require("node:child_process"),h=require("node:fs"),J=require("node:net"),L=require("node:url"),N=require("@connectrpc/connect"),E=require("@connectrpc/connect-node"),c=require("@bufbuild/protobuf");var M=typeof document<"u"?document.currentScript:null;function R(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const r in t)if(r!=="default"){const i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:()=>t[r]})}}return e.default=t,Object.freeze(e)}const P=R(w),I=R(A),D=R(J),B=/<!--\s+@import\s+"(.+?)"\s+-->/;function $(t){return async e=>{const{markdownFilePath:r}=t,i=w.dirname(r),o=[];if(x.visit(e,"html",(a,n,s)=>{if(!s||typeof n!="number")return;const l=a.value.match(B);if(!l)return;const f=l[1],u=w.resolve(i,f);Array.isArray(s.children)&&o.push({parent:s,index:n,absolutePath:u})}),o.length===0)return;const d=await Promise.all(o.map(async({absolutePath:a})=>{try{const n=await U.readFile(a,"utf-8");return this.parse(n)}catch(n){return n&&n.code==="ENOENT"?v.Logger.warn(`[remark-import-directive] Import file not found: ${a}`):v.Logger.error(`[remark-import-directive] Error processing import: ${a}`,n),null}}));for(let a=o.length-1;a>=0;a--){const{parent:n,index:s}=o[a],l=d[a];l?.children&&Array.isArray(l.children)&&n.children.splice(s,1,...l.children)}}}const z=/^[a-z][a-z0-9+.-]*:/,_=async(t,e,r,i,o=!1)=>{if(!t)return"";if(z.test(t)){const f=t.substring(0,t.indexOf(":")).toLowerCase();if(["http","https","mailto","tel","file"].includes(f))return t}if(t.startsWith("#")||t.startsWith("/"))return t;const d=decodeURIComponent(t),a=w.dirname(r),n=w.normalize(w.join(a,d)),s=w.resolve(i,n);if(!s.startsWith(i)||n.startsWith(".."))return v.Logger.error(`Security Alert: Attempt to access file outside project root: ${s}`),"";if(o)try{await U.access(s)}catch{return v.Logger.warn(`File not found: ${s}`),""}const l=n.replace(/\\/g,"/");return e?C("/assets/",l):`?filePath=${encodeURIComponent(l)}`};function K(t){return async e=>{if(!(t?.markdownFilePath&&t?.workspaceRoot)){v.Logger.warn("remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.");return}const r=[],i=[];x.visit(e,["image","link","html"],a=>{if(a.type==="html")i.push(a);else{const n=a;n.url&&r.push({node:n,isImage:n.type==="image"})}});const o=r.map(async({node:a,isImage:n})=>{const s=await _(a.url,n,t.markdownFilePath,t.workspaceRoot,t.validateExistence);a.url=s}),d=i.map(async a=>{const n=I.load(a.value,null,!1);let s=!1;const l=n("img").toArray();for(const u of l){const m=n(u).attr("src");if(m){const p=await _(m,!0,t.markdownFilePath,t.workspaceRoot,t.validateExistence);p!==m&&(n(u).attr("src",p),s=!0)}}const f=n("a").toArray();for(const u of f){const m=n(u).attr("href");if(m){const p=await _(m,!1,t.markdownFilePath,t.workspaceRoot,t.validateExistence);p!==m&&(n(u).attr("href",p),s=!0)}}if(s){const u=n.html();u&&(a.value=u)}});await Promise.all([...o,...d])}}class k extends c.Message{markdownText="";filePath="";workspaceRoot="";validateExistence=!1;enableSubscript;enableSuperscript;enableMark;enableTableMerge;enableEmbeds;enableZennDirectives;constructor(e){super(),c.proto3.util.initPartial(e,this)}static runtime=c.proto3;static typeName="markdown.v1.ConvertRequest";static fields=c.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}]);static fromBinary(e,r){return new k().fromBinary(e,r)}static fromJson(e,r){return new k().fromJson(e,r)}static fromJsonString(e,r){return new k().fromJsonString(e,r)}static equals(e,r){return c.proto3.util.equals(k,e,r)}}class y extends c.Message{htmlContent="";headings=[];constructor(e){super(),c.proto3.util.initPartial(e,this)}static runtime=c.proto3;static typeName="markdown.v1.ConvertResponse";static fields=c.proto3.util.newFieldList(()=>[{no:1,name:"html_content",kind:"scalar",T:9},{no:2,name:"headings",kind:"message",T:g,repeated:!0}]);static fromBinary(e,r){return new y().fromBinary(e,r)}static fromJson(e,r){return new y().fromJson(e,r)}static fromJsonString(e,r){return new y().fromJsonString(e,r)}static equals(e,r){return c.proto3.util.equals(y,e,r)}}class g extends c.Message{text="";depth=0;id="";constructor(e){super(),c.proto3.util.initPartial(e,this)}static runtime=c.proto3;static typeName="markdown.v1.Heading";static fields=c.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(e,r){return new g().fromBinary(e,r)}static fromJson(e,r){return new g().fromJson(e,r)}static fromJsonString(e,r){return new g().fromJsonString(e,r)}static equals(e,r){return c.proto3.util.equals(g,e,r)}}const W={typeName:"markdown.v1.MarkdownService",methods:{convert:{name:"Convert",I:k,O:y,kind:c.MethodKind.Unary}}},T=process.env.MARKDOWN_SOCKET_PATH||"/tmp/markdown.sock",G=E.createConnectTransport({baseUrl:"http://localhost",httpVersion:"2",nodeOptions:{createConnection:()=>D.connect(T)}}),Z=N.createClient(W,G),H=t=>{try{h.accessSync(t,h.constants.X_OK)}catch{try{h.chmodSync(t,493)}catch(e){console.warn("Failed to set executable permission on markdown-api binary:",e)}}},V=()=>{try{const t=L.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(t).href:M&&M.tagName.toUpperCase()==="SCRIPT"&&M.src||new URL("index.server.cjs",document.baseURI).href);return P.dirname(t)}catch{return __dirname}},X=()=>{const t=V(),e=P.join(t,"markdown-api");if(h.existsSync(e))return e;const r=P.join(t,"..","dist","markdown-api");if(h.existsSync(r))return r;const i=P.join(t,"..","..","go","markdown-api","markdown-api");if(h.existsSync(i))return i},F=()=>new Promise(t=>{const e=D.connect(T);e.on("connect",()=>{e.destroy(),t(!0)}),e.on("error",()=>t(!1))}),Q=async t=>{const e=Date.now();for(;Date.now()-e<t;){if(await F())return!0;await new Promise(r=>setTimeout(r,100))}return!1};let b=null,S=null;const Y=async()=>{if(await F())return!0;if(S)return S;S=(async()=>{const e=X();if(!e)return console.warn("markdown-api binary not found. Cannot auto-start markdown server."),!1;H(e);try{h.existsSync(T)&&h.unlinkSync(T)}catch{}try{b=j.spawn(e,[],{stdio:"ignore"});const r=()=>{if(b){try{b.kill("SIGTERM")}catch{}b=null}};return process.on("exit",r),await Q(1e4)?!0:(console.error("markdown-api Go server did not become ready on socket:",T),r(),!1)}catch(r){return console.error("Failed to spawn markdown-api Go server:",r),b=null,!1}})();const t=await S;return t||(S=null),t},O=async(t,e,r,i,o=!0)=>{await Y();let d=!0,a,n,s,l,f,u;typeof o=="boolean"?d=o:o&&typeof o=="object"&&(d=o.validateExistence??!0,a=o.enableSubscript,n=o.enableSuperscript,s=o.enableMark,l=o.enableTableMerge,f=o.enableEmbeds,u=o.enableZennDirectives);const m={};i&&(m.Authorization=`Bearer ${i}`);const p=await Z.convert({markdownText:t,filePath:e,workspaceRoot:r,validateExistence:d,enableSubscript:a,enableSuperscript:n,enableMark:s,enableTableMerge:l,enableEmbeds:f,enableZennDirectives:u},{headers:m});return{htmlContent:p.htmlContent,headings:p.headings.map(q=>({text:q.text,depth:q.depth,id:q.id}))}};exports.parseMarkdown=O;exports.remarkImportDirective=$;exports.remarkResolveUriAsync=K;exports.transformUriAsync=_;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("node:fs/promises"),h=require("node:path"),x=require("unist-util-visit"),P=require("./simple-logger-DZxBpX7v.cjs"),C=require("cheerio"),L=require("url-join"),j=require("node:child_process"),S=require("node:fs"),B=require("node:module"),J=require("node:net"),W=require("node:url"),K=require("@connectrpc/connect"),z=require("@connectrpc/connect-node"),i=require("@bufbuild/protobuf");var A=typeof document<"u"?document.currentScript:null;function q(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const r in t)if(r!=="default"){const c=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,c.get?c:{enumerable:!0,get:()=>t[r]})}}return e.default=t,Object.freeze(e)}const _=q(h),G=q(C),$=q(J),V=/<!--\s+@import\s+"(.+?)"\s+-->/;function Z(t){return async e=>{const{markdownFilePath:r}=t,c=h.dirname(r),o=[];if(x.visit(e,"html",(a,n,s)=>{if(!s||typeof n!="number")return;const l=a.value.match(V);if(!l)return;const f=l[1],u=h.resolve(c,f);Array.isArray(s.children)&&o.push({parent:s,index:n,absolutePath:u})}),o.length===0)return;const d=await Promise.all(o.map(async({absolutePath:a})=>{try{const n=await I.readFile(a,"utf-8");return this.parse(n)}catch(n){return n&&n.code==="ENOENT"?P.Logger.warn(`[remark-import-directive] Import file not found: ${a}`):P.Logger.error(`[remark-import-directive] Error processing import: ${a}`,n),null}}));for(let a=o.length-1;a>=0;a--){const{parent:n,index:s}=o[a],l=d[a];l?.children&&Array.isArray(l.children)&&n.children.splice(s,1,...l.children)}}}const H=/^[a-z][a-z0-9+.-]*:/,R=async(t,e,r,c,o=!1)=>{if(!t)return"";if(H.test(t)){const f=t.substring(0,t.indexOf(":")).toLowerCase();if(["http","https","mailto","tel","file"].includes(f))return t}if(t.startsWith("#")||t.startsWith("/"))return t;const d=decodeURIComponent(t),a=h.dirname(r),n=h.normalize(h.join(a,d)),s=h.resolve(c,n);if(!s.startsWith(c)||n.startsWith(".."))return P.Logger.error(`Security Alert: Attempt to access file outside project root: ${s}`),"";if(o)try{await I.access(s)}catch{return P.Logger.warn(`File not found: ${s}`),""}const l=n.replace(/\\/g,"/");return e?L("/assets/",l):`?filePath=${encodeURIComponent(l)}`};function X(t){return async e=>{if(!(t?.markdownFilePath&&t?.workspaceRoot)){P.Logger.warn("remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.");return}const r=[],c=[];x.visit(e,["image","link","html"],a=>{if(a.type==="html")c.push(a);else{const n=a;n.url&&r.push({node:n,isImage:n.type==="image"})}});const o=r.map(async({node:a,isImage:n})=>{const s=await R(a.url,n,t.markdownFilePath,t.workspaceRoot,t.validateExistence);a.url=s}),d=c.map(async a=>{const n=G.load(a.value,null,!1);let s=!1;const l=n("img").toArray();for(const u of l){const m=n(u).attr("src");if(m){const p=await R(m,!0,t.markdownFilePath,t.workspaceRoot,t.validateExistence);p!==m&&(n(u).attr("src",p),s=!0)}}const f=n("a").toArray();for(const u of f){const m=n(u).attr("href");if(m){const p=await R(m,!1,t.markdownFilePath,t.workspaceRoot,t.validateExistence);p!==m&&(n(u).attr("href",p),s=!0)}}if(s){const u=n.html();u&&(a.value=u)}});await Promise.all([...o,...d])}}class w extends i.Message{markdownText="";filePath="";workspaceRoot="";validateExistence=!1;enableSubscript;enableSuperscript;enableMark;enableTableMerge;enableEmbeds;enableZennDirectives;constructor(e){super(),i.proto3.util.initPartial(e,this)}static runtime=i.proto3;static typeName="markdown.v1.ConvertRequest";static fields=i.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}]);static fromBinary(e,r){return new w().fromBinary(e,r)}static fromJson(e,r){return new w().fromJson(e,r)}static fromJsonString(e,r){return new w().fromJsonString(e,r)}static equals(e,r){return i.proto3.util.equals(w,e,r)}}class k extends i.Message{htmlContent="";headings=[];constructor(e){super(),i.proto3.util.initPartial(e,this)}static runtime=i.proto3;static typeName="markdown.v1.ConvertResponse";static fields=i.proto3.util.newFieldList(()=>[{no:1,name:"html_content",kind:"scalar",T:9},{no:2,name:"headings",kind:"message",T:y,repeated:!0}]);static fromBinary(e,r){return new k().fromBinary(e,r)}static fromJson(e,r){return new k().fromJson(e,r)}static fromJsonString(e,r){return new k().fromJsonString(e,r)}static equals(e,r){return i.proto3.util.equals(k,e,r)}}class y extends i.Message{text="";depth=0;id="";constructor(e){super(),i.proto3.util.initPartial(e,this)}static runtime=i.proto3;static typeName="markdown.v1.Heading";static fields=i.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(e,r){return new y().fromBinary(e,r)}static fromJson(e,r){return new y().fromJson(e,r)}static fromJsonString(e,r){return new y().fromJsonString(e,r)}static equals(e,r){return i.proto3.util.equals(y,e,r)}}const Y={typeName:"markdown.v1.MarkdownService",methods:{convert:{name:"Convert",I:w,O:k,kind:i.MethodKind.Unary}}},b=process.env.MARKDOWN_SOCKET_PATH||"/tmp/markdown.sock",Q=z.createConnectTransport({baseUrl:"http://localhost",httpVersion:"2",nodeOptions:{createConnection:()=>$.connect(b)}}),O=K.createClient(Y,Q),N=()=>{try{return _.dirname(W.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:A&&A.tagName.toUpperCase()==="SCRIPT"&&A.src||new URL("index.server.cjs",document.baseURI).href))}catch{return __dirname}},D=()=>`@aiquants/markdown-${process.platform}-${process.arch}`,U=()=>process.platform==="win32"?"bin/markdown-api.exe":"bin/markdown-api",ee=()=>{const t=process.env.MARKDOWN_API_BINARY;if(t&&S.existsSync(t))return t;try{const r=B.createRequire(_.join(N(),"index.js")).resolve(`${D()}/${U()}`);if(S.existsSync(r))return r}catch{}const e=_.join(N(),"..","..","go","markdown-api","dist",_.basename(U()));return S.existsSync(e)?e:void 0},te=()=>[`markdown-api binary not found for ${process.platform}-${process.arch}.`,`Expected the optional dependency ${D()} 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(" "),F=()=>new Promise(t=>{const e=$.connect(b);e.on("connect",()=>{e.destroy(),t(!0)}),e.on("error",()=>t(!1))}),E=async t=>{const e=Date.now();for(;Date.now()-e<t;){if(await F())return!0;await new Promise(r=>setTimeout(r,100))}return!1};let T=null,v=null;const re=2e3,ne=()=>{const t=Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);return Number.isFinite(t)&&t>0?t:1e4};let M=null;const ae=async()=>{if(await F())return!0;if(v)return v;v=(async()=>{const e=ee();if(!e)return await E(re)?!0:(M=te(),!1);M=null;try{S.existsSync(b)&&S.unlinkSync(b)}catch{}try{T=j.spawn(e,[],{stdio:"ignore"});const r=()=>{if(T){try{T.kill("SIGTERM")}catch{}T=null}};return process.once("exit",r),await E(ne())?!0:(console.error("markdown-api Go server did not become ready on socket:",b),r(),process.removeListener("exit",r),!1)}catch(r){return console.error("Failed to spawn markdown-api Go server:",r),T=null,!1}})();const t=await v;return t||(v=null),t},oe=async(t,e,r,c,o=!0)=>{if(!await ae()){const g=M?` ${M}`:"";throw new Error(`markdown service is not reachable on ${b}.${g}`)}let d=!0,a,n,s,l,f,u;typeof o=="boolean"?d=o:o&&typeof o=="object"&&(d=o.validateExistence??!0,a=o.enableSubscript,n=o.enableSuperscript,s=o.enableMark,l=o.enableTableMerge,f=o.enableEmbeds,u=o.enableZennDirectives);const m={};c&&(m.Authorization=`Bearer ${c}`);const p=await O.convert({markdownText:t,filePath:e,workspaceRoot:r,validateExistence:d,enableSubscript:a,enableSuperscript:n,enableMark:s,enableTableMerge:l,enableEmbeds:f,enableZennDirectives:u},{headers:m});return{htmlContent:p.htmlContent,headings:p.headings.map(g=>({text:g.text,depth:g.depth,id:g.id}))}};exports.parseMarkdown=oe;exports.remarkImportDirective=Z;exports.remarkResolveUriAsync=X;exports.transformUriAsync=R;
2
2
  //# sourceMappingURL=index.server.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.cjs","sources":["../src/plugins/remark-import-directive.async.server.ts","../src/plugins/transformUri.async.server.ts","../src/plugins/remark-resolve-uri.async.ts","../src/gen/markdown/v1/markdown_pb.ts","../src/gen/markdown/v1/markdown_connect.ts","../src/remarkProcessor.server.ts"],"sourcesContent":["/**\n * @file This file defines a remark plugin to handle `@import` directives in Markdown.\n * @brief このファイルは、Markdown 内の `@import` ディレクティブを処理するための remark プラグインを定義します。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Root } from \"mdast\"\nimport type { Processor } from \"unified\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\n\ntype ParentNodeWithChildren = {\n children: unknown[]\n}\n\nconst importRegex = /<!--\\s+@import\\s+\"(.+?)\"\\s+-->/\n\n/**\n * A remark plugin to support `@import` directives in Markdown.\n * This allows importing content from other Markdown files.\n * Markdown の `@import` ディレクティブをサポートする remark プラグイン。\n * これにより、他の Markdown ファイルからコンテンツをインポート可能。\n *\n * @param this The remark processor instance. / remark プロセッサーのインスタンス。\n * @param options Options for the plugin. / プラグインのオプション。\n * @param options.markdownFilePath The path to the Markdown file being processed. / 処理対象の Markdown ファイルへのパス。\n */\nexport function remarkImportDirective(this: Processor, options: { markdownFilePath: string }) {\n return async (tree: Root): Promise<void> => {\n const { markdownFilePath } = options\n const parentDir = path.dirname(markdownFilePath)\n\n // すべてのインポートディレクティブを収集\n const imports: { parent: ParentNodeWithChildren; index: number; absolutePath: string }[] = []\n visit(tree, \"html\", (node, index, parent) => {\n if (!parent || typeof index !== \"number\") {\n return\n }\n\n const match = node.value.match(importRegex)\n if (!match) {\n return\n }\n\n const importPath = match[1]\n const absolutePath = path.resolve(parentDir, importPath)\n if (Array.isArray((parent as { children?: unknown[] }).children)) {\n imports.push({ parent: parent as ParentNodeWithChildren, index, absolutePath })\n }\n })\n\n if (imports.length === 0) {\n return\n }\n\n // すべてのファイルを読み込み、解析\n const parsedTrees = await Promise.all(\n imports.map(async ({ absolutePath }) => {\n try {\n const fileContent = await fs.readFile(absolutePath, \"utf-8\")\n return this.parse(fileContent) as Root\n } catch (error) {\n if (error && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n Logger.warn(`[remark-import-directive] Import file not found: ${absolutePath}`)\n } else {\n Logger.error(`[remark-import-directive] Error processing import: ${absolutePath}`, error)\n }\n return null // エラー時は null を返却\n }\n }),\n )\n\n // ツリー内のノードを後方から置換\n for (let i = imports.length - 1; i >= 0; i--) {\n const { parent, index } = imports[i]\n const newTree = parsedTrees[i]\n\n if (newTree?.children && Array.isArray(newTree.children)) {\n parent.children.splice(index, 1, ...newTree.children)\n }\n }\n }\n}\n","/**\n * @file Async version of transformUri for file existence validation.\n * @brief ファイル存在確認を含む transformUri の非同期版。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport urlJoin from \"url-join\"\nimport { Logger } from \"../utils/simple-logger\"\n\n// RFC 3986 URI scheme regex\nconst URI_SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:/\n\n/**\n * Async version of transformUri that validates file existence.\n * ファイル存在確認を行う transformUri の非同期版。\n *\n * @param uri The URI to transform. / 変換対象の URI。\n * @param isImage Whether this is an image URI. / 画像 URI かどうか。\n * @param markdownFilePath Path to the markdown file. / Markdown ファイルのパス。\n * @param workspaceRoot Workspace root directory. / ワークスペースのルートディレクトリ。\n * @param validateExistence Whether to validate file existence. / ファイル存在確認を行うかどうか。\n * @returns Promise resolving to the transformed URI. / 変換された URI を返す Promise。\n */\nexport const transformUriAsync = async (uri: string, isImage: boolean, markdownFilePath: string, workspaceRoot: string, validateExistence = false): Promise<string> => {\n if (!uri) {\n return \"\"\n }\n\n // 1. 絶対URL (http, https, mailto, tel) はそのまま返す\n if (URI_SCHEME_REGEX.test(uri)) {\n const protocol = uri.substring(0, uri.indexOf(\":\")).toLowerCase()\n if ([\"http\", \"https\", \"mailto\", \"tel\", \"file\"].includes(protocol)) {\n return uri\n }\n }\n\n // 2. アンカーリンク (#fragment) はそのまま返す\n if (uri.startsWith(\"#\")) {\n return uri\n }\n\n // 3. ルート相対パス (/) はそのまま返す\n if (uri.startsWith(\"/\")) {\n return uri\n }\n\n // 4. 相対パスをプロジェクトルートからのパスとして解決する\n const decodedUri = decodeURIComponent(uri)\n const markdownDir = path.dirname(markdownFilePath)\n const projectRelativePath = path.normalize(path.join(markdownDir, decodedUri))\n\n // セキュリティチェック\n const absolutePath = path.resolve(workspaceRoot, projectRelativePath)\n if (!absolutePath.startsWith(workspaceRoot) || projectRelativePath.startsWith(\"..\")) {\n Logger.error(`Security Alert: Attempt to access file outside project root: ${absolutePath}`)\n return \"\"\n }\n\n // ファイル存在確認(オプション)\n if (validateExistence) {\n try {\n await fs.access(absolutePath)\n } catch {\n Logger.warn(`File not found: ${absolutePath}`)\n return \"\"\n }\n }\n\n const pathForEncoding = projectRelativePath.replace(/\\\\/g, \"/\")\n\n if (isImage) {\n return urlJoin(\"/assets/\", pathForEncoding)\n }\n return `?filePath=${encodeURIComponent(pathForEncoding)}`\n}\n","/**\n * @file Async version of remark-resolve-uri plugin.\n * @brief URI 解決プラグインの非同期版。\n */\nimport * as cheerio from \"cheerio\"\nimport type { Html, Image, Link, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\nimport { transformUriAsync } from \"./transformUri.async.server\"\n\ninterface Options {\n markdownFilePath: string\n workspaceRoot: string\n validateExistence?: boolean\n}\n\n/**\n * An async remark plugin to resolve image and link URIs with optional file validation.\n * ファイル検証オプション付きで画像とリンクの URI を解決する非同期 remark プラグイン。\n */\nexport function remarkResolveUriAsync(options: Options) {\n return async (tree: Root): Promise<void> => {\n if (!(options?.markdownFilePath && options?.workspaceRoot)) {\n Logger.warn(\"remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.\")\n return\n }\n\n // すべての画像とリンクノードを収集\n const uriNodes: Array<{ node: Image | Link; isImage: boolean }> = []\n const htmlNodes: Array<Html> = []\n\n visit(tree, [\"image\", \"link\", \"html\"], (node) => {\n if (node.type === \"html\") {\n htmlNodes.push(node as Html)\n } else {\n const targetNode = node as Image | Link\n if (targetNode.url) {\n uriNodes.push({ node: targetNode, isImage: targetNode.type === \"image\" })\n }\n }\n })\n\n // 並列でURI変換を実行 (標準Markdownノード)\n const transformPromises = uriNodes.map(async ({ node, isImage }) => {\n const transformedUri = await transformUriAsync(node.url, isImage, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n node.url = transformedUri\n })\n\n // 並列でURI変換を実行 (HTMLノード内の属性)\n const htmlTransformPromises = htmlNodes.map(async (node) => {\n // HTMLフラグメントとしてロード (isDocument=false)\n const $ = cheerio.load(node.value, null, false)\n let modified = false\n\n // imgタグのsrc属性を変換\n const imgTags = $(\"img\").toArray()\n for (const img of imgTags) {\n const src = $(img).attr(\"src\")\n if (src) {\n const transformed = await transformUriAsync(src, true, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== src) {\n $(img).attr(\"src\", transformed)\n modified = true\n }\n }\n }\n\n // aタグのhref属性を変換\n const aTags = $(\"a\").toArray()\n for (const a of aTags) {\n const href = $(a).attr(\"href\")\n if (href) {\n const transformed = await transformUriAsync(href, false, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== href) {\n $(a).attr(\"href\", transformed)\n modified = true\n }\n }\n }\n\n if (modified) {\n // 変更があれば node.value を更新\n // html() はエンコードされた実体を返す可能性があるが、HTMLノードとしては許容される\n const newHtml = $.html()\n if (newHtml) {\n node.value = newHtml\n }\n }\n })\n\n await Promise.all([...transformPromises, ...htmlTransformPromises])\n }\n}\n","// @generated by protoc-gen-es v1.10.1 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from \"@bufbuild/protobuf\"\nimport { Message, proto3 } from \"@bufbuild/protobuf\"\n\n/**\n * @generated from message markdown.v1.ConvertRequest\n */\nexport class ConvertRequest extends Message<ConvertRequest> {\n /**\n * @generated from field: string markdown_text = 1;\n */\n markdownText = \"\"\n\n /**\n * @generated from field: string file_path = 2;\n */\n filePath = \"\"\n\n /**\n * @generated from field: string workspace_root = 3;\n */\n workspaceRoot = \"\"\n\n /**\n * @generated from field: bool validate_existence = 4;\n */\n validateExistence = false\n\n /**\n * @generated from field: optional bool enable_subscript = 5;\n */\n enableSubscript?: boolean\n\n /**\n * @generated from field: optional bool enable_superscript = 6;\n */\n enableSuperscript?: boolean\n\n /**\n * @generated from field: optional bool enable_mark = 7;\n */\n enableMark?: boolean\n\n /**\n * @generated from field: optional bool enable_table_merge = 8;\n */\n enableTableMerge?: boolean\n\n /**\n * @generated from field: optional bool enable_embeds = 9;\n */\n enableEmbeds?: boolean\n\n /**\n * @generated from field: optional bool enable_zenn_directives = 10;\n */\n enableZennDirectives?: boolean\n\n constructor(data?: PartialMessage<ConvertRequest>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertRequest\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"markdown_text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"file_path\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 3, name: \"workspace_root\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 4, name: \"validate_existence\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */ },\n { no: 5, name: \"enable_subscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 6, name: \"enable_superscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 7, name: \"enable_mark\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 8, name: \"enable_table_merge\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 9, name: \"enable_embeds\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 10, name: \"enable_zenn_directives\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertRequest {\n return new ConvertRequest().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertRequest | PlainMessage<ConvertRequest> | undefined, b: ConvertRequest | PlainMessage<ConvertRequest> | undefined): boolean {\n return proto3.util.equals(ConvertRequest, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.ConvertResponse\n */\nexport class ConvertResponse extends Message<ConvertResponse> {\n /**\n * @generated from field: string html_content = 1;\n */\n htmlContent = \"\"\n\n /**\n * @generated from field: repeated markdown.v1.Heading headings = 2;\n */\n headings: Heading[] = []\n\n constructor(data?: PartialMessage<ConvertResponse>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertResponse\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"html_content\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"headings\", kind: \"message\", T: Heading, repeated: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertResponse {\n return new ConvertResponse().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertResponse | PlainMessage<ConvertResponse> | undefined, b: ConvertResponse | PlainMessage<ConvertResponse> | undefined): boolean {\n return proto3.util.equals(ConvertResponse, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.Heading\n */\nexport class Heading extends Message<Heading> {\n /**\n * @generated from field: string text = 1;\n */\n text = \"\"\n\n /**\n * @generated from field: int32 depth = 2;\n */\n depth = 0\n\n /**\n * @generated from field: string id = 3;\n */\n id = \"\"\n\n constructor(data?: PartialMessage<Heading>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.Heading\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"depth\", kind: \"scalar\", T: 5 /* ScalarType.INT32 */ },\n { no: 3, name: \"id\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Heading {\n return new Heading().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJsonString(jsonString, options)\n }\n\n static equals(a: Heading | PlainMessage<Heading> | undefined, b: Heading | PlainMessage<Heading> | undefined): boolean {\n return proto3.util.equals(Heading, a, b)\n }\n}\n","// @generated by protoc-gen-connect-es v1.7.0 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport { MethodKind } from \"@bufbuild/protobuf\"\nimport { ConvertRequest, ConvertResponse } from \"./markdown_pb.js\"\n\n/**\n * @generated from service markdown.v1.MarkdownService\n */\nexport const MarkdownService = {\n typeName: \"markdown.v1.MarkdownService\",\n methods: {\n /**\n * @generated from rpc markdown.v1.MarkdownService.Convert\n */\n convert: {\n name: \"Convert\",\n I: ConvertRequest,\n O: ConvertResponse,\n kind: MethodKind.Unary,\n },\n },\n} as const\n","import { spawn } from \"node:child_process\"\nimport { accessSync, chmodSync, constants, existsSync, unlinkSync } from \"node:fs\"\nimport * as net from \"node:net\"\nimport * as path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { createClient } from \"@connectrpc/connect\"\nimport { createConnectTransport } from \"@connectrpc/connect-node\"\nimport { MarkdownService } from \"./gen/markdown/v1/markdown_connect.ts\"\n\nconst SOCKET_PATH = process.env.MARKDOWN_SOCKET_PATH || \"/tmp/markdown.sock\"\n\nconst transport = createConnectTransport({\n baseUrl: \"http://localhost\",\n httpVersion: \"2\",\n nodeOptions: {\n createConnection: () => {\n return net.connect(SOCKET_PATH)\n },\n } as unknown as Record<string, unknown>,\n})\n\nconst client = createClient(MarkdownService, transport)\n\nexport interface ParseResult {\n htmlContent: string\n headings: Array<{\n text: string\n depth: number\n id: string\n }>\n}\n\nexport interface ParseOptions {\n validateExistence?: boolean\n enableSubscript?: boolean\n enableSuperscript?: boolean\n enableMark?: boolean\n enableTableMerge?: boolean\n enableEmbeds?: boolean\n enableZennDirectives?: boolean\n}\n\n/**\n * Ensures that the binary at the specified path has executable permission.\n * 指定されたパスのバイナリに実行権限が付与されていることを確認・保証する処理。\n *\n * @param binPath Path to the binary file / バイナリファイルのパス\n */\nexport const ensureExecutablePermission = (binPath: string): void => {\n try {\n accessSync(binPath, constants.X_OK)\n } catch {\n // 実行権限がない場合、0755 (-rwxr-xr-x) を付与する\n try {\n chmodSync(binPath, 0o755)\n } catch (chmodErr) {\n console.warn(\"Failed to set executable permission on markdown-api binary:\", chmodErr)\n }\n }\n}\n\n// Get the current directory name in an ES Modules friendly way\nconst getDirname = () => {\n try {\n const __filename = fileURLToPath(import.meta.url)\n return path.dirname(__filename)\n } catch {\n return __dirname\n }\n}\n\n// Locate the Go server binary path inside the package or monorepo\nconst getBinaryPath = (): string | undefined => {\n const dir = getDirname()\n // 1. In the same directory as the transpile output (dist/markdown-api)\n const sameDir = path.join(dir, \"markdown-api\")\n if (existsSync(sameDir)) return sameDir\n\n // 2. Fallback to dist directory from src\n const distDir = path.join(dir, \"..\", \"dist\", \"markdown-api\")\n if (existsSync(distDir)) return distDir\n\n // 3. Fallback to monorepo go packages folder for dev environment\n const devDir = path.join(dir, \"..\", \"..\", \"go\", \"markdown-api\", \"markdown-api\")\n if (existsSync(devDir)) return devDir\n\n return undefined\n}\n\nconst canConnect = (): Promise<boolean> =>\n new Promise((resolve) => {\n const socket = net.connect(SOCKET_PATH)\n socket.on(\"connect\", () => {\n socket.destroy()\n resolve(true)\n })\n socket.on(\"error\", () => resolve(false))\n })\n\nconst waitForServer = async (timeoutMs: number): Promise<boolean> => {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (await canConnect()) return true\n await new Promise((r) => setTimeout(r, 100))\n }\n return false\n}\n\nlet spawnedServer: ReturnType<typeof spawn> | null = null\nlet startPromise: Promise<boolean> | null = null\n\nconst ensureServerRunning = async (): Promise<boolean> => {\n if (await canConnect()) return true\n\n if (startPromise) return startPromise\n\n startPromise = (async () => {\n const binPath = getBinaryPath()\n if (!binPath) {\n console.warn(\"markdown-api binary not found. Cannot auto-start markdown server.\")\n return false\n }\n\n // Ensure executable permission on binary\n ensureExecutablePermission(binPath)\n\n // Clean up stale socket file if it exists\n try {\n if (existsSync(SOCKET_PATH)) {\n unlinkSync(SOCKET_PATH)\n }\n } catch {\n // ignore\n }\n\n try {\n spawnedServer = spawn(binPath, [], { stdio: \"ignore\" })\n\n const cleanup = () => {\n if (spawnedServer) {\n try {\n spawnedServer.kill(\"SIGTERM\")\n } catch {\n // ignore\n }\n spawnedServer = null\n }\n }\n\n process.on(\"exit\", cleanup)\n\n const ready = await waitForServer(10000)\n if (!ready) {\n console.error(\"markdown-api Go server did not become ready on socket:\", SOCKET_PATH)\n cleanup()\n return false\n }\n return true\n } catch (err) {\n console.error(\"Failed to spawn markdown-api Go server:\", err)\n spawnedServer = null\n return false\n }\n })()\n\n const success = await startPromise\n if (!success) {\n startPromise = null\n }\n return success\n}\n\nexport const parseMarkdown = async (markdownText: string, markdownFilePath: string, workspaceRoot: string, userOAuthToken?: string, validateExistenceOrOptions: boolean | ParseOptions = true): Promise<ParseResult> => {\n // Automatically ensure the backend Go server is running\n await ensureServerRunning()\n\n let validateExistence = true\n let enableSubscript: boolean | undefined\n let enableSuperscript: boolean | undefined\n let enableMark: boolean | undefined\n let enableTableMerge: boolean | undefined\n let enableEmbeds: boolean | undefined\n let enableZennDirectives: boolean | undefined\n\n if (typeof validateExistenceOrOptions === \"boolean\") {\n validateExistence = validateExistenceOrOptions\n } else if (validateExistenceOrOptions && typeof validateExistenceOrOptions === \"object\") {\n validateExistence = validateExistenceOrOptions.validateExistence ?? true\n enableSubscript = validateExistenceOrOptions.enableSubscript\n enableSuperscript = validateExistenceOrOptions.enableSuperscript\n enableMark = validateExistenceOrOptions.enableMark\n enableTableMerge = validateExistenceOrOptions.enableTableMerge\n enableEmbeds = validateExistenceOrOptions.enableEmbeds\n enableZennDirectives = validateExistenceOrOptions.enableZennDirectives\n }\n\n const headers: Record<string, string> = {}\n if (userOAuthToken) {\n headers.Authorization = `Bearer ${userOAuthToken}`\n }\n\n const response = await client.convert(\n {\n markdownText,\n filePath: markdownFilePath,\n workspaceRoot,\n validateExistence,\n enableSubscript,\n enableSuperscript,\n enableMark,\n enableTableMerge,\n enableEmbeds,\n enableZennDirectives,\n },\n { headers },\n )\n\n return {\n htmlContent: response.htmlContent,\n headings: response.headings.map((h) => ({\n text: h.text,\n depth: h.depth,\n id: h.id,\n })),\n }\n}\n"],"names":["importRegex","remarkImportDirective","options","tree","markdownFilePath","parentDir","path","imports","visit","node","index","parent","match","importPath","absolutePath","parsedTrees","fileContent","fs","error","Logger","i","newTree","URI_SCHEME_REGEX","transformUriAsync","uri","isImage","workspaceRoot","validateExistence","protocol","decodedUri","markdownDir","projectRelativePath","pathForEncoding","urlJoin","remarkResolveUriAsync","uriNodes","htmlNodes","targetNode","transformPromises","transformedUri","htmlTransformPromises","$","cheerio","modified","imgTags","img","src","transformed","aTags","a","href","newHtml","ConvertRequest","Message","data","proto3","bytes","jsonValue","jsonString","b","ConvertResponse","Heading","MarkdownService","MethodKind","SOCKET_PATH","transport","createConnectTransport","net","client","createClient","ensureExecutablePermission","binPath","accessSync","constants","chmodSync","chmodErr","getDirname","__filename","fileURLToPath","getBinaryPath","dir","sameDir","existsSync","distDir","devDir","canConnect","resolve","socket","waitForServer","timeoutMs","start","spawnedServer","startPromise","ensureServerRunning","unlinkSync","spawn","cleanup","err","success","parseMarkdown","markdownText","userOAuthToken","validateExistenceOrOptions","enableSubscript","enableSuperscript","enableMark","enableTableMerge","enableEmbeds","enableZennDirectives","headers","response","h"],"mappings":"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"}
1
+ {"version":3,"file":"index.server.cjs","sources":["../src/plugins/remark-import-directive.async.server.ts","../src/plugins/transformUri.async.server.ts","../src/plugins/remark-resolve-uri.async.ts","../src/gen/markdown/v1/markdown_pb.ts","../src/gen/markdown/v1/markdown_connect.ts","../src/remarkProcessor.server.ts"],"sourcesContent":["/**\n * @file This file defines a remark plugin to handle `@import` directives in Markdown.\n * @brief このファイルは、Markdown 内の `@import` ディレクティブを処理するための remark プラグインを定義します。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Root } from \"mdast\"\nimport type { Processor } from \"unified\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\n\ntype ParentNodeWithChildren = {\n children: unknown[]\n}\n\nconst importRegex = /<!--\\s+@import\\s+\"(.+?)\"\\s+-->/\n\n/**\n * A remark plugin to support `@import` directives in Markdown.\n * This allows importing content from other Markdown files.\n * Markdown の `@import` ディレクティブをサポートする remark プラグイン。\n * これにより、他の Markdown ファイルからコンテンツをインポート可能。\n *\n * @param this The remark processor instance. / remark プロセッサーのインスタンス。\n * @param options Options for the plugin. / プラグインのオプション。\n * @param options.markdownFilePath The path to the Markdown file being processed. / 処理対象の Markdown ファイルへのパス。\n */\nexport function remarkImportDirective(this: Processor, options: { markdownFilePath: string }) {\n return async (tree: Root): Promise<void> => {\n const { markdownFilePath } = options\n const parentDir = path.dirname(markdownFilePath)\n\n // すべてのインポートディレクティブを収集\n const imports: { parent: ParentNodeWithChildren; index: number; absolutePath: string }[] = []\n visit(tree, \"html\", (node, index, parent) => {\n if (!parent || typeof index !== \"number\") {\n return\n }\n\n const match = node.value.match(importRegex)\n if (!match) {\n return\n }\n\n const importPath = match[1]\n const absolutePath = path.resolve(parentDir, importPath)\n if (Array.isArray((parent as { children?: unknown[] }).children)) {\n imports.push({ parent: parent as ParentNodeWithChildren, index, absolutePath })\n }\n })\n\n if (imports.length === 0) {\n return\n }\n\n // すべてのファイルを読み込み、解析\n const parsedTrees = await Promise.all(\n imports.map(async ({ absolutePath }) => {\n try {\n const fileContent = await fs.readFile(absolutePath, \"utf-8\")\n return this.parse(fileContent) as Root\n } catch (error) {\n if (error && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n Logger.warn(`[remark-import-directive] Import file not found: ${absolutePath}`)\n } else {\n Logger.error(`[remark-import-directive] Error processing import: ${absolutePath}`, error)\n }\n return null // エラー時は null を返却\n }\n }),\n )\n\n // ツリー内のノードを後方から置換\n for (let i = imports.length - 1; i >= 0; i--) {\n const { parent, index } = imports[i]\n const newTree = parsedTrees[i]\n\n if (newTree?.children && Array.isArray(newTree.children)) {\n parent.children.splice(index, 1, ...newTree.children)\n }\n }\n }\n}\n","/**\n * @file Async version of transformUri for file existence validation.\n * @brief ファイル存在確認を含む transformUri の非同期版。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport urlJoin from \"url-join\"\nimport { Logger } from \"../utils/simple-logger\"\n\n// RFC 3986 URI scheme regex\nconst URI_SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:/\n\n/**\n * Async version of transformUri that validates file existence.\n * ファイル存在確認を行う transformUri の非同期版。\n *\n * @param uri The URI to transform. / 変換対象の URI。\n * @param isImage Whether this is an image URI. / 画像 URI かどうか。\n * @param markdownFilePath Path to the markdown file. / Markdown ファイルのパス。\n * @param workspaceRoot Workspace root directory. / ワークスペースのルートディレクトリ。\n * @param validateExistence Whether to validate file existence. / ファイル存在確認を行うかどうか。\n * @returns Promise resolving to the transformed URI. / 変換された URI を返す Promise。\n */\nexport const transformUriAsync = async (uri: string, isImage: boolean, markdownFilePath: string, workspaceRoot: string, validateExistence = false): Promise<string> => {\n if (!uri) {\n return \"\"\n }\n\n // 1. 絶対URL (http, https, mailto, tel) はそのまま返す\n if (URI_SCHEME_REGEX.test(uri)) {\n const protocol = uri.substring(0, uri.indexOf(\":\")).toLowerCase()\n if ([\"http\", \"https\", \"mailto\", \"tel\", \"file\"].includes(protocol)) {\n return uri\n }\n }\n\n // 2. アンカーリンク (#fragment) はそのまま返す\n if (uri.startsWith(\"#\")) {\n return uri\n }\n\n // 3. ルート相対パス (/) はそのまま返す\n if (uri.startsWith(\"/\")) {\n return uri\n }\n\n // 4. 相対パスをプロジェクトルートからのパスとして解決する\n const decodedUri = decodeURIComponent(uri)\n const markdownDir = path.dirname(markdownFilePath)\n const projectRelativePath = path.normalize(path.join(markdownDir, decodedUri))\n\n // セキュリティチェック\n const absolutePath = path.resolve(workspaceRoot, projectRelativePath)\n if (!absolutePath.startsWith(workspaceRoot) || projectRelativePath.startsWith(\"..\")) {\n Logger.error(`Security Alert: Attempt to access file outside project root: ${absolutePath}`)\n return \"\"\n }\n\n // ファイル存在確認(オプション)\n if (validateExistence) {\n try {\n await fs.access(absolutePath)\n } catch {\n Logger.warn(`File not found: ${absolutePath}`)\n return \"\"\n }\n }\n\n const pathForEncoding = projectRelativePath.replace(/\\\\/g, \"/\")\n\n if (isImage) {\n return urlJoin(\"/assets/\", pathForEncoding)\n }\n return `?filePath=${encodeURIComponent(pathForEncoding)}`\n}\n","/**\n * @file Async version of remark-resolve-uri plugin.\n * @brief URI 解決プラグインの非同期版。\n */\nimport * as cheerio from \"cheerio\"\nimport type { Html, Image, Link, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\nimport { transformUriAsync } from \"./transformUri.async.server\"\n\ninterface Options {\n markdownFilePath: string\n workspaceRoot: string\n validateExistence?: boolean\n}\n\n/**\n * An async remark plugin to resolve image and link URIs with optional file validation.\n * ファイル検証オプション付きで画像とリンクの URI を解決する非同期 remark プラグイン。\n */\nexport function remarkResolveUriAsync(options: Options) {\n return async (tree: Root): Promise<void> => {\n if (!(options?.markdownFilePath && options?.workspaceRoot)) {\n Logger.warn(\"remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.\")\n return\n }\n\n // すべての画像とリンクノードを収集\n const uriNodes: Array<{ node: Image | Link; isImage: boolean }> = []\n const htmlNodes: Array<Html> = []\n\n visit(tree, [\"image\", \"link\", \"html\"], (node) => {\n if (node.type === \"html\") {\n htmlNodes.push(node as Html)\n } else {\n const targetNode = node as Image | Link\n if (targetNode.url) {\n uriNodes.push({ node: targetNode, isImage: targetNode.type === \"image\" })\n }\n }\n })\n\n // 並列でURI変換を実行 (標準Markdownノード)\n const transformPromises = uriNodes.map(async ({ node, isImage }) => {\n const transformedUri = await transformUriAsync(node.url, isImage, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n node.url = transformedUri\n })\n\n // 並列でURI変換を実行 (HTMLノード内の属性)\n const htmlTransformPromises = htmlNodes.map(async (node) => {\n // HTMLフラグメントとしてロード (isDocument=false)\n const $ = cheerio.load(node.value, null, false)\n let modified = false\n\n // imgタグのsrc属性を変換\n const imgTags = $(\"img\").toArray()\n for (const img of imgTags) {\n const src = $(img).attr(\"src\")\n if (src) {\n const transformed = await transformUriAsync(src, true, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== src) {\n $(img).attr(\"src\", transformed)\n modified = true\n }\n }\n }\n\n // aタグのhref属性を変換\n const aTags = $(\"a\").toArray()\n for (const a of aTags) {\n const href = $(a).attr(\"href\")\n if (href) {\n const transformed = await transformUriAsync(href, false, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== href) {\n $(a).attr(\"href\", transformed)\n modified = true\n }\n }\n }\n\n if (modified) {\n // 変更があれば node.value を更新\n // html() はエンコードされた実体を返す可能性があるが、HTMLノードとしては許容される\n const newHtml = $.html()\n if (newHtml) {\n node.value = newHtml\n }\n }\n })\n\n await Promise.all([...transformPromises, ...htmlTransformPromises])\n }\n}\n","// @generated by protoc-gen-es v1.10.1 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from \"@bufbuild/protobuf\"\nimport { Message, proto3 } from \"@bufbuild/protobuf\"\n\n/**\n * @generated from message markdown.v1.ConvertRequest\n */\nexport class ConvertRequest extends Message<ConvertRequest> {\n /**\n * @generated from field: string markdown_text = 1;\n */\n markdownText = \"\"\n\n /**\n * @generated from field: string file_path = 2;\n */\n filePath = \"\"\n\n /**\n * @generated from field: string workspace_root = 3;\n */\n workspaceRoot = \"\"\n\n /**\n * @generated from field: bool validate_existence = 4;\n */\n validateExistence = false\n\n /**\n * @generated from field: optional bool enable_subscript = 5;\n */\n enableSubscript?: boolean\n\n /**\n * @generated from field: optional bool enable_superscript = 6;\n */\n enableSuperscript?: boolean\n\n /**\n * @generated from field: optional bool enable_mark = 7;\n */\n enableMark?: boolean\n\n /**\n * @generated from field: optional bool enable_table_merge = 8;\n */\n enableTableMerge?: boolean\n\n /**\n * @generated from field: optional bool enable_embeds = 9;\n */\n enableEmbeds?: boolean\n\n /**\n * @generated from field: optional bool enable_zenn_directives = 10;\n */\n enableZennDirectives?: boolean\n\n constructor(data?: PartialMessage<ConvertRequest>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertRequest\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"markdown_text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"file_path\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 3, name: \"workspace_root\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 4, name: \"validate_existence\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */ },\n { no: 5, name: \"enable_subscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 6, name: \"enable_superscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 7, name: \"enable_mark\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 8, name: \"enable_table_merge\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 9, name: \"enable_embeds\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 10, name: \"enable_zenn_directives\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertRequest {\n return new ConvertRequest().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertRequest | PlainMessage<ConvertRequest> | undefined, b: ConvertRequest | PlainMessage<ConvertRequest> | undefined): boolean {\n return proto3.util.equals(ConvertRequest, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.ConvertResponse\n */\nexport class ConvertResponse extends Message<ConvertResponse> {\n /**\n * @generated from field: string html_content = 1;\n */\n htmlContent = \"\"\n\n /**\n * @generated from field: repeated markdown.v1.Heading headings = 2;\n */\n headings: Heading[] = []\n\n constructor(data?: PartialMessage<ConvertResponse>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertResponse\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"html_content\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"headings\", kind: \"message\", T: Heading, repeated: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertResponse {\n return new ConvertResponse().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertResponse | PlainMessage<ConvertResponse> | undefined, b: ConvertResponse | PlainMessage<ConvertResponse> | undefined): boolean {\n return proto3.util.equals(ConvertResponse, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.Heading\n */\nexport class Heading extends Message<Heading> {\n /**\n * @generated from field: string text = 1;\n */\n text = \"\"\n\n /**\n * @generated from field: int32 depth = 2;\n */\n depth = 0\n\n /**\n * @generated from field: string id = 3;\n */\n id = \"\"\n\n constructor(data?: PartialMessage<Heading>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.Heading\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"depth\", kind: \"scalar\", T: 5 /* ScalarType.INT32 */ },\n { no: 3, name: \"id\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Heading {\n return new Heading().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJsonString(jsonString, options)\n }\n\n static equals(a: Heading | PlainMessage<Heading> | undefined, b: Heading | PlainMessage<Heading> | undefined): boolean {\n return proto3.util.equals(Heading, a, b)\n }\n}\n","// @generated by protoc-gen-connect-es v1.7.0 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport { MethodKind } from \"@bufbuild/protobuf\"\nimport { ConvertRequest, ConvertResponse } from \"./markdown_pb.js\"\n\n/**\n * @generated from service markdown.v1.MarkdownService\n */\nexport const MarkdownService = {\n typeName: \"markdown.v1.MarkdownService\",\n methods: {\n /**\n * @generated from rpc markdown.v1.MarkdownService.Convert\n */\n convert: {\n name: \"Convert\",\n I: ConvertRequest,\n O: ConvertResponse,\n kind: MethodKind.Unary,\n },\n },\n} as const\n","import { spawn } from \"node:child_process\"\nimport { existsSync, unlinkSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\nimport * as net from \"node:net\"\nimport * as path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { createClient } from \"@connectrpc/connect\"\nimport { createConnectTransport } from \"@connectrpc/connect-node\"\nimport { MarkdownService } from \"./gen/markdown/v1/markdown_connect.ts\"\n\nconst SOCKET_PATH = process.env.MARKDOWN_SOCKET_PATH || \"/tmp/markdown.sock\"\n\nconst transport = createConnectTransport({\n baseUrl: \"http://localhost\",\n httpVersion: \"2\",\n nodeOptions: {\n createConnection: () => {\n return net.connect(SOCKET_PATH)\n },\n } as unknown as Record<string, unknown>,\n})\n\nconst client = createClient(MarkdownService, transport)\n\nexport interface ParseResult {\n htmlContent: string\n headings: Array<{\n text: string\n depth: number\n id: string\n }>\n}\n\nexport interface ParseOptions {\n validateExistence?: boolean\n enableSubscript?: boolean\n enableSuperscript?: boolean\n enableMark?: boolean\n enableTableMerge?: boolean\n enableEmbeds?: boolean\n enableZennDirectives?: boolean\n}\n\n/**\n * Returns the directory of this module in a way that works for both ESM and CJS output.\n * ESM / CJS どちらのビルド出力でも動作する形で本モジュールのディレクトリを返す処理。\n *\n * @returns Absolute directory path / 絶対ディレクトリパス\n */\nconst getDirname = (): string => {\n try {\n return path.dirname(fileURLToPath(import.meta.url))\n } catch {\n return __dirname\n }\n}\n\n/** プラットフォームパッケージ名 (@aiquants/markdown-linux-x64 等) */\nconst platformPackageName = (): string => `@aiquants/markdown-${process.platform}-${process.arch}`\n\n/** プラットフォームパッケージ内のバイナリ相対パス (Windows のみ .exe) */\nconst platformBinarySubpath = (): string => (process.platform === \"win32\" ? \"bin/markdown-api.exe\" : \"bin/markdown-api\")\n\n/**\n * Locates the `markdown-api` binary for the running platform.\n * 実行中プラットフォーム向けの `markdown-api` バイナリを探索する処理。\n *\n * 探索順:\n * 1. `MARKDOWN_API_BINARY` 環境変数 (自前ビルドの差し込み口)\n * 2. プラットフォームパッケージ (通常の配布経路。Node の解決機構に委ねるため\n * パス組み立てのヒューリスティックが不要)\n * 3. モノレポ開発時に `pnpm run build:go` がビルドする `packages/go/markdown-api/dist/`\n *\n * 候補 3 はモノレポ内の消費アプリからは機能しない。workspace 依存が injected\n * (ハードリンクコピー) で解決されるため、`.pnpm/` 配下のコピーから相対で辿れない。\n * サービスを自前起動する統合テストは `MARKDOWN_API_BINARY` を明示すること。\n *\n * 実行権限は付与しない。バイナリはプラットフォームパッケージの `bin` フィールド経由で\n * 配られ、パッケージマネージャが 0755 を保証する。\n *\n * @returns Absolute binary path, or undefined when unavailable / バイナリの絶対パス。見つからない場合は undefined\n */\nexport const resolveBinaryPath = (): string | undefined => {\n const fromEnvironment = process.env.MARKDOWN_API_BINARY\n if (fromEnvironment && existsSync(fromEnvironment)) {\n return fromEnvironment\n }\n\n try {\n // createRequire の基点はビルド形式に依存しない getDirname() から作る\n // (CJS 出力で import.meta.url がどう変換されても影響を受けない)\n const resolved = createRequire(path.join(getDirname(), \"index.js\")).resolve(`${platformPackageName()}/${platformBinarySubpath()}`)\n if (existsSync(resolved)) {\n return resolved\n }\n } catch {\n // プラットフォームパッケージ未インストール (モノレポ開発時は常にこの経路)\n }\n\n const monorepoBinary = path.join(getDirname(), \"..\", \"..\", \"go\", \"markdown-api\", \"dist\", path.basename(platformBinarySubpath()))\n return existsSync(monorepoBinary) ? monorepoBinary : undefined\n}\n\n/**\n * Builds a diagnosable message for a missing binary.\n * バイナリが見つからない場合の原因診断メッセージを組み立てる処理。\n *\n * 「見つからない」だけでは利用者が次に何をすべきか分からないため、期待した\n * プラットフォームパッケージ名と自前ビルドの差し込み口まで示す。\n *\n * @returns Human-readable diagnostic message / 人間が読める診断メッセージ\n */\nconst describeMissingBinary = (): string =>\n [\n `markdown-api binary not found for ${process.platform}-${process.arch}.`,\n `Expected the optional dependency ${platformPackageName()} to be installed.`,\n \"If your platform is unsupported, build the service yourself\",\n \"(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)\",\n \"and point MARKDOWN_API_BINARY at it.\",\n ].join(\" \")\n\nconst canConnect = (): Promise<boolean> =>\n new Promise((resolve) => {\n const socket = net.connect(SOCKET_PATH)\n socket.on(\"connect\", () => {\n socket.destroy()\n resolve(true)\n })\n socket.on(\"error\", () => resolve(false))\n })\n\nconst waitForServer = async (timeoutMs: number): Promise<boolean> => {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (await canConnect()) return true\n await new Promise((r) => setTimeout(r, 100))\n }\n return false\n}\n\nlet spawnedServer: ReturnType<typeof spawn> | null = null\nlet startPromise: Promise<boolean> | null = null\n\n/**\n * Grace period for a server started outside this process, in milliseconds.\n * 本プロセス外で起動されたサーバを待つ猶予時間 (ミリ秒)。\n *\n * コンテナ環境ではプロセスマネージャ (supervisor 等) が `markdown-api` を別プログラムとして\n * 起動するため、パッケージ内にバイナリは存在しない。その構成で Node 側が先に温まると\n * ソケット未 bind の瞬間に当たりうるので、自前起動を諦める前に短時間だけ待つ。\n * Go 側の bind はミリ秒で完了するため、これで十分。\n */\nconst EXTERNAL_SERVER_GRACE_MS = 2000\n\n/**\n * Time budget for a freshly spawned server to start listening, in milliseconds.\n * 新規起動したサーバが待ち受け開始するまでの猶予時間 (ミリ秒)。\n *\n * 低速な CI コンテナでは既定の 10 秒でも足りないことがあるため環境変数で調整できる。\n * 不正値 (数値でない / 0 以下) は既定へ戻す (設定ミスで永久に待たないようにする)。\n *\n * @returns Timeout in milliseconds / ミリ秒単位のタイムアウト\n */\nconst startupTimeoutMs = (): number => {\n const configured = Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS)\n return Number.isFinite(configured) && configured > 0 ? configured : 10000\n}\n\n/** 自動起動をバイナリ不在で諦めた理由。到達不能エラーへ添えて診断可能にする */\nlet missingBinaryReason: string | null = null\n\nconst ensureServerRunning = async (): Promise<boolean> => {\n if (await canConnect()) return true\n\n if (startPromise) return startPromise\n\n startPromise = (async () => {\n const binPath = resolveBinaryPath()\n if (!binPath) {\n // 外部管理サーバの起動待ちに賭ける。ここで即諦めると、プロセスマネージャ管理型の\n // 構成 (バイナリを同梱しない) で起動直後のリクエストが理由なく失敗する\n if (await waitForServer(EXTERNAL_SERVER_GRACE_MS)) return true\n missingBinaryReason = describeMissingBinary()\n return false\n }\n // バイナリが見つかった以降は不在が理由ではない。古い理由を残すと誤診を招く\n missingBinaryReason = null\n\n // Clean up stale socket file if it exists\n try {\n if (existsSync(SOCKET_PATH)) {\n unlinkSync(SOCKET_PATH)\n }\n } catch {\n // ignore\n }\n\n try {\n spawnedServer = spawn(binPath, [], { stdio: \"ignore\" })\n\n const cleanup = () => {\n if (spawnedServer) {\n try {\n spawnedServer.kill(\"SIGTERM\")\n } catch {\n // 既に終了しているケースは無視する\n }\n spawnedServer = null\n }\n }\n\n // once で登録し、失敗時は明示的に解除する。on のままだと起動失敗を\n // 繰り返すたびにリスナーが蓄積し、MaxListeners 警告とメモリリークを招く\n process.once(\"exit\", cleanup)\n\n const ready = await waitForServer(startupTimeoutMs())\n if (!ready) {\n console.error(\"markdown-api Go server did not become ready on socket:\", SOCKET_PATH)\n cleanup()\n process.removeListener(\"exit\", cleanup)\n return false\n }\n return true\n } catch (err) {\n console.error(\"Failed to spawn markdown-api Go server:\", err)\n spawnedServer = null\n return false\n }\n })()\n\n const success = await startPromise\n if (!success) {\n startPromise = null\n }\n return success\n}\n\nexport const parseMarkdown = async (markdownText: string, markdownFilePath: string, workspaceRoot: string, userOAuthToken?: string, validateExistenceOrOptions: boolean | ParseOptions = true): Promise<ParseResult> => {\n // Automatically ensure the backend Go server is running\n if (!(await ensureServerRunning())) {\n // 到達できないまま RPC へ進むと、利用者には原因不明の ENOENT だけが届く。\n // 自動起動がバイナリ不在で諦めた場合は、必要なパッケージ名まで含めて伝える\n const detail = missingBinaryReason ? ` ${missingBinaryReason}` : \"\"\n throw new Error(`markdown service is not reachable on ${SOCKET_PATH}.${detail}`)\n }\n\n let validateExistence = true\n let enableSubscript: boolean | undefined\n let enableSuperscript: boolean | undefined\n let enableMark: boolean | undefined\n let enableTableMerge: boolean | undefined\n let enableEmbeds: boolean | undefined\n let enableZennDirectives: boolean | undefined\n\n if (typeof validateExistenceOrOptions === \"boolean\") {\n validateExistence = validateExistenceOrOptions\n } else if (validateExistenceOrOptions && typeof validateExistenceOrOptions === \"object\") {\n validateExistence = validateExistenceOrOptions.validateExistence ?? true\n enableSubscript = validateExistenceOrOptions.enableSubscript\n enableSuperscript = validateExistenceOrOptions.enableSuperscript\n enableMark = validateExistenceOrOptions.enableMark\n enableTableMerge = validateExistenceOrOptions.enableTableMerge\n enableEmbeds = validateExistenceOrOptions.enableEmbeds\n enableZennDirectives = validateExistenceOrOptions.enableZennDirectives\n }\n\n const headers: Record<string, string> = {}\n if (userOAuthToken) {\n headers.Authorization = `Bearer ${userOAuthToken}`\n }\n\n const response = await client.convert(\n {\n markdownText,\n filePath: markdownFilePath,\n workspaceRoot,\n validateExistence,\n enableSubscript,\n enableSuperscript,\n enableMark,\n enableTableMerge,\n enableEmbeds,\n enableZennDirectives,\n },\n { headers },\n )\n\n return {\n htmlContent: response.htmlContent,\n headings: response.headings.map((h) => ({\n text: h.text,\n depth: h.depth,\n id: h.id,\n })),\n }\n}\n"],"names":["importRegex","remarkImportDirective","options","tree","markdownFilePath","parentDir","path","imports","visit","node","index","parent","match","importPath","absolutePath","parsedTrees","fileContent","fs","error","Logger","i","newTree","URI_SCHEME_REGEX","transformUriAsync","uri","isImage","workspaceRoot","validateExistence","protocol","decodedUri","markdownDir","projectRelativePath","pathForEncoding","urlJoin","remarkResolveUriAsync","uriNodes","htmlNodes","targetNode","transformPromises","transformedUri","htmlTransformPromises","$","cheerio","modified","imgTags","img","src","transformed","aTags","a","href","newHtml","ConvertRequest","Message","data","proto3","bytes","jsonValue","jsonString","b","ConvertResponse","Heading","MarkdownService","MethodKind","SOCKET_PATH","transport","createConnectTransport","net","client","createClient","getDirname","fileURLToPath","_documentCurrentScript","platformPackageName","platformBinarySubpath","resolveBinaryPath","fromEnvironment","existsSync","resolved","createRequire","monorepoBinary","describeMissingBinary","canConnect","resolve","socket","waitForServer","timeoutMs","start","spawnedServer","startPromise","EXTERNAL_SERVER_GRACE_MS","startupTimeoutMs","configured","missingBinaryReason","ensureServerRunning","binPath","unlinkSync","spawn","cleanup","err","success","parseMarkdown","markdownText","userOAuthToken","validateExistenceOrOptions","detail","enableSubscript","enableSuperscript","enableMark","enableTableMerge","enableEmbeds","enableZennDirectives","headers","response","h"],"mappings":"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"}
@@ -1,115 +1,116 @@
1
- import A from "node:fs/promises";
2
- import * as v from "node:path";
1
+ import I from "node:fs/promises";
2
+ import * as S from "node:path";
3
3
  import h from "node:path";
4
- import { visit as D } from "unist-util-visit";
5
- import { L as S } from "./simple-logger-DIfMY3fH.js";
6
- import * as _ from "cheerio";
7
- import C from "url-join";
8
- import { spawn as E } from "node:child_process";
9
- import { existsSync as P, unlinkSync as U, accessSync as N, constants as I, chmodSync as B } from "node:fs";
10
- import * as J from "node:net";
11
- import { fileURLToPath as j } from "node:url";
12
- import { createClient as L } from "@connectrpc/connect";
13
- import { createConnectTransport as $ } from "@connectrpc/connect-node";
14
- import { Message as x, proto3 as m, MethodKind as q } from "@bufbuild/protobuf";
15
- const z = /<!--\s+@import\s+"(.+?)"\s+-->/;
16
- function me(t) {
4
+ import { visit as x } from "unist-util-visit";
5
+ import { L as P } from "./simple-logger-DIfMY3fH.js";
6
+ import * as J from "cheerio";
7
+ import U from "url-join";
8
+ import { spawn as C } from "node:child_process";
9
+ import { existsSync as R, unlinkSync as L } from "node:fs";
10
+ import { createRequire as j } from "node:module";
11
+ import * as F from "node:net";
12
+ import { fileURLToPath as q } from "node:url";
13
+ import { createClient as W } from "@connectrpc/connect";
14
+ import { createConnectTransport as K } from "@connectrpc/connect-node";
15
+ import { Message as _, proto3 as l, MethodKind as z } from "@bufbuild/protobuf";
16
+ const G = /<!--\s+@import\s+"(.+?)"\s+-->/;
17
+ function pe(r) {
17
18
  return async (e) => {
18
- const { markdownFilePath: r } = t, i = h.dirname(r), o = [];
19
- if (D(e, "html", (a, n, s) => {
19
+ const { markdownFilePath: t } = r, m = h.dirname(t), o = [];
20
+ if (x(e, "html", (a, n, s) => {
20
21
  if (!s || typeof n != "number")
21
22
  return;
22
- const c = a.value.match(z);
23
- if (!c)
23
+ const i = a.value.match(G);
24
+ if (!i)
24
25
  return;
25
- const f = c[1], l = h.resolve(i, f);
26
- Array.isArray(s.children) && o.push({ parent: s, index: n, absolutePath: l });
26
+ const d = i[1], c = h.resolve(m, d);
27
+ Array.isArray(s.children) && o.push({ parent: s, index: n, absolutePath: c });
27
28
  }), o.length === 0)
28
29
  return;
29
- const d = await Promise.all(
30
+ const f = await Promise.all(
30
31
  o.map(async ({ absolutePath: a }) => {
31
32
  try {
32
- const n = await A.readFile(a, "utf-8");
33
+ const n = await I.readFile(a, "utf-8");
33
34
  return this.parse(n);
34
35
  } catch (n) {
35
- return n && n.code === "ENOENT" ? S.warn(`[remark-import-directive] Import file not found: ${a}`) : S.error(`[remark-import-directive] Error processing import: ${a}`, n), null;
36
+ return n && n.code === "ENOENT" ? P.warn(`[remark-import-directive] Import file not found: ${a}`) : P.error(`[remark-import-directive] Error processing import: ${a}`, n), null;
36
37
  }
37
38
  })
38
39
  );
39
40
  for (let a = o.length - 1; a >= 0; a--) {
40
- const { parent: n, index: s } = o[a], c = d[a];
41
- c?.children && Array.isArray(c.children) && n.children.splice(s, 1, ...c.children);
41
+ const { parent: n, index: s } = o[a], i = f[a];
42
+ i?.children && Array.isArray(i.children) && n.children.splice(s, 1, ...i.children);
42
43
  }
43
44
  };
44
45
  }
45
- const K = /^[a-z][a-z0-9+.-]*:/, M = async (t, e, r, i, o = !1) => {
46
- if (!t)
46
+ const Z = /^[a-z][a-z0-9+.-]*:/, M = async (r, e, t, m, o = !1) => {
47
+ if (!r)
47
48
  return "";
48
- if (K.test(t)) {
49
- const f = t.substring(0, t.indexOf(":")).toLowerCase();
50
- if (["http", "https", "mailto", "tel", "file"].includes(f))
51
- return t;
49
+ if (Z.test(r)) {
50
+ const d = r.substring(0, r.indexOf(":")).toLowerCase();
51
+ if (["http", "https", "mailto", "tel", "file"].includes(d))
52
+ return r;
52
53
  }
53
- if (t.startsWith("#") || t.startsWith("/"))
54
- return t;
55
- const d = decodeURIComponent(t), a = h.dirname(r), n = h.normalize(h.join(a, d)), s = h.resolve(i, n);
56
- if (!s.startsWith(i) || n.startsWith(".."))
57
- return S.error(`Security Alert: Attempt to access file outside project root: ${s}`), "";
54
+ if (r.startsWith("#") || r.startsWith("/"))
55
+ return r;
56
+ const f = decodeURIComponent(r), a = h.dirname(t), n = h.normalize(h.join(a, f)), s = h.resolve(m, n);
57
+ if (!s.startsWith(m) || n.startsWith(".."))
58
+ return P.error(`Security Alert: Attempt to access file outside project root: ${s}`), "";
58
59
  if (o)
59
60
  try {
60
- await A.access(s);
61
+ await I.access(s);
61
62
  } catch {
62
- return S.warn(`File not found: ${s}`), "";
63
+ return P.warn(`File not found: ${s}`), "";
63
64
  }
64
- const c = n.replace(/\\/g, "/");
65
- return e ? C("/assets/", c) : `?filePath=${encodeURIComponent(c)}`;
65
+ const i = n.replace(/\\/g, "/");
66
+ return e ? U("/assets/", i) : `?filePath=${encodeURIComponent(i)}`;
66
67
  };
67
- function ue(t) {
68
+ function he(r) {
68
69
  return async (e) => {
69
- if (!(t?.markdownFilePath && t?.workspaceRoot)) {
70
- S.warn("remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.");
70
+ if (!(r?.markdownFilePath && r?.workspaceRoot)) {
71
+ P.warn("remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.");
71
72
  return;
72
73
  }
73
- const r = [], i = [];
74
- D(e, ["image", "link", "html"], (a) => {
74
+ const t = [], m = [];
75
+ x(e, ["image", "link", "html"], (a) => {
75
76
  if (a.type === "html")
76
- i.push(a);
77
+ m.push(a);
77
78
  else {
78
79
  const n = a;
79
- n.url && r.push({ node: n, isImage: n.type === "image" });
80
+ n.url && t.push({ node: n, isImage: n.type === "image" });
80
81
  }
81
82
  });
82
- const o = r.map(async ({ node: a, isImage: n }) => {
83
- const s = await M(a.url, n, t.markdownFilePath, t.workspaceRoot, t.validateExistence);
83
+ const o = t.map(async ({ node: a, isImage: n }) => {
84
+ const s = await M(a.url, n, r.markdownFilePath, r.workspaceRoot, r.validateExistence);
84
85
  a.url = s;
85
- }), d = i.map(async (a) => {
86
- const n = _.load(a.value, null, !1);
86
+ }), f = m.map(async (a) => {
87
+ const n = J.load(a.value, null, !1);
87
88
  let s = !1;
88
- const c = n("img").toArray();
89
- for (const l of c) {
90
- const u = n(l).attr("src");
89
+ const i = n("img").toArray();
90
+ for (const c of i) {
91
+ const u = n(c).attr("src");
91
92
  if (u) {
92
- const p = await M(u, !0, t.markdownFilePath, t.workspaceRoot, t.validateExistence);
93
- p !== u && (n(l).attr("src", p), s = !0);
93
+ const p = await M(u, !0, r.markdownFilePath, r.workspaceRoot, r.validateExistence);
94
+ p !== u && (n(c).attr("src", p), s = !0);
94
95
  }
95
96
  }
96
- const f = n("a").toArray();
97
- for (const l of f) {
98
- const u = n(l).attr("href");
97
+ const d = n("a").toArray();
98
+ for (const c of d) {
99
+ const u = n(c).attr("href");
99
100
  if (u) {
100
- const p = await M(u, !1, t.markdownFilePath, t.workspaceRoot, t.validateExistence);
101
- p !== u && (n(l).attr("href", p), s = !0);
101
+ const p = await M(u, !1, r.markdownFilePath, r.workspaceRoot, r.validateExistence);
102
+ p !== u && (n(c).attr("href", p), s = !0);
102
103
  }
103
104
  }
104
105
  if (s) {
105
- const l = n.html();
106
- l && (a.value = l);
106
+ const c = n.html();
107
+ c && (a.value = c);
107
108
  }
108
109
  });
109
- await Promise.all([...o, ...d]);
110
+ await Promise.all([...o, ...f]);
110
111
  };
111
112
  }
112
- class w extends x {
113
+ class w extends _ {
113
114
  /**
114
115
  * @generated from field: string markdown_text = 1;
115
116
  */
@@ -151,11 +152,11 @@ class w extends x {
151
152
  */
152
153
  enableZennDirectives;
153
154
  constructor(e) {
154
- super(), m.util.initPartial(e, this);
155
+ super(), l.util.initPartial(e, this);
155
156
  }
156
- static runtime = m;
157
+ static runtime = l;
157
158
  static typeName = "markdown.v1.ConvertRequest";
158
- static fields = m.util.newFieldList(() => [
159
+ static fields = l.util.newFieldList(() => [
159
160
  {
160
161
  no: 1,
161
162
  name: "markdown_text",
@@ -191,20 +192,20 @@ class w extends x {
191
192
  { no: 9, name: "enable_embeds", kind: "scalar", T: 8, opt: !0 },
192
193
  { no: 10, name: "enable_zenn_directives", kind: "scalar", T: 8, opt: !0 }
193
194
  ]);
194
- static fromBinary(e, r) {
195
- return new w().fromBinary(e, r);
195
+ static fromBinary(e, t) {
196
+ return new w().fromBinary(e, t);
196
197
  }
197
- static fromJson(e, r) {
198
- return new w().fromJson(e, r);
198
+ static fromJson(e, t) {
199
+ return new w().fromJson(e, t);
199
200
  }
200
- static fromJsonString(e, r) {
201
- return new w().fromJsonString(e, r);
201
+ static fromJsonString(e, t) {
202
+ return new w().fromJsonString(e, t);
202
203
  }
203
- static equals(e, r) {
204
- return m.util.equals(w, e, r);
204
+ static equals(e, t) {
205
+ return l.util.equals(w, e, t);
205
206
  }
206
207
  }
207
- class k extends x {
208
+ class k extends _ {
208
209
  /**
209
210
  * @generated from field: string html_content = 1;
210
211
  */
@@ -214,11 +215,11 @@ class k extends x {
214
215
  */
215
216
  headings = [];
216
217
  constructor(e) {
217
- super(), m.util.initPartial(e, this);
218
+ super(), l.util.initPartial(e, this);
218
219
  }
219
- static runtime = m;
220
+ static runtime = l;
220
221
  static typeName = "markdown.v1.ConvertResponse";
221
- static fields = m.util.newFieldList(() => [
222
+ static fields = l.util.newFieldList(() => [
222
223
  {
223
224
  no: 1,
224
225
  name: "html_content",
@@ -228,20 +229,20 @@ class k extends x {
228
229
  },
229
230
  { no: 2, name: "headings", kind: "message", T: y, repeated: !0 }
230
231
  ]);
231
- static fromBinary(e, r) {
232
- return new k().fromBinary(e, r);
232
+ static fromBinary(e, t) {
233
+ return new k().fromBinary(e, t);
233
234
  }
234
- static fromJson(e, r) {
235
- return new k().fromJson(e, r);
235
+ static fromJson(e, t) {
236
+ return new k().fromJson(e, t);
236
237
  }
237
- static fromJsonString(e, r) {
238
- return new k().fromJsonString(e, r);
238
+ static fromJsonString(e, t) {
239
+ return new k().fromJsonString(e, t);
239
240
  }
240
- static equals(e, r) {
241
- return m.util.equals(k, e, r);
241
+ static equals(e, t) {
242
+ return l.util.equals(k, e, t);
242
243
  }
243
244
  }
244
- class y extends x {
245
+ class y extends _ {
245
246
  /**
246
247
  * @generated from field: string text = 1;
247
248
  */
@@ -255,11 +256,11 @@ class y extends x {
255
256
  */
256
257
  id = "";
257
258
  constructor(e) {
258
- super(), m.util.initPartial(e, this);
259
+ super(), l.util.initPartial(e, this);
259
260
  }
260
- static runtime = m;
261
+ static runtime = l;
261
262
  static typeName = "markdown.v1.Heading";
262
- static fields = m.util.newFieldList(() => [
263
+ static fields = l.util.newFieldList(() => [
263
264
  {
264
265
  no: 1,
265
266
  name: "text",
@@ -282,20 +283,20 @@ class y extends x {
282
283
  /* ScalarType.STRING */
283
284
  }
284
285
  ]);
285
- static fromBinary(e, r) {
286
- return new y().fromBinary(e, r);
286
+ static fromBinary(e, t) {
287
+ return new y().fromBinary(e, t);
287
288
  }
288
- static fromJson(e, r) {
289
- return new y().fromJson(e, r);
289
+ static fromJson(e, t) {
290
+ return new y().fromJson(e, t);
290
291
  }
291
- static fromJsonString(e, r) {
292
- return new y().fromJsonString(e, r);
292
+ static fromJsonString(e, t) {
293
+ return new y().fromJsonString(e, t);
293
294
  }
294
- static equals(e, r) {
295
- return m.util.equals(y, e, r);
295
+ static equals(e, t) {
296
+ return l.util.equals(y, e, t);
296
297
  }
297
298
  }
298
- const W = {
299
+ const H = {
299
300
  typeName: "markdown.v1.MarkdownService",
300
301
  methods: {
301
302
  /**
@@ -305,117 +306,125 @@ const W = {
305
306
  name: "Convert",
306
307
  I: w,
307
308
  O: k,
308
- kind: q.Unary
309
+ kind: z.Unary
309
310
  }
310
311
  }
311
- }, T = process.env.MARKDOWN_SOCKET_PATH || "/tmp/markdown.sock", G = $({
312
+ }, b = process.env.MARKDOWN_SOCKET_PATH || "/tmp/markdown.sock", V = K({
312
313
  baseUrl: "http://localhost",
313
314
  httpVersion: "2",
314
315
  nodeOptions: {
315
- createConnection: () => J.connect(T)
316
+ createConnection: () => F.connect(b)
316
317
  }
317
- }), Z = L(W, G), H = (t) => {
318
+ }), X = W(H, V), E = () => {
318
319
  try {
319
- N(t, I.X_OK);
320
+ return S.dirname(q(import.meta.url));
320
321
  } catch {
321
- try {
322
- B(t, 493);
323
- } catch (e) {
324
- console.warn("Failed to set executable permission on markdown-api binary:", e);
325
- }
322
+ return __dirname;
326
323
  }
327
- }, X = () => {
324
+ }, B = () => `@aiquants/markdown-${process.platform}-${process.arch}`, N = () => process.platform === "win32" ? "bin/markdown-api.exe" : "bin/markdown-api", Y = () => {
325
+ const r = process.env.MARKDOWN_API_BINARY;
326
+ if (r && R(r))
327
+ return r;
328
328
  try {
329
- const t = j(import.meta.url);
330
- return v.dirname(t);
329
+ const t = j(S.join(E(), "index.js")).resolve(`${B()}/${N()}`);
330
+ if (R(t))
331
+ return t;
331
332
  } catch {
332
- return __dirname;
333
333
  }
334
- }, V = () => {
335
- const t = X(), e = v.join(t, "markdown-api");
336
- if (P(e)) return e;
337
- const r = v.join(t, "..", "dist", "markdown-api");
338
- if (P(r)) return r;
339
- const i = v.join(t, "..", "..", "go", "markdown-api", "markdown-api");
340
- if (P(i)) return i;
341
- }, R = () => new Promise((t) => {
342
- const e = J.connect(T);
334
+ const e = S.join(E(), "..", "..", "go", "markdown-api", "dist", S.basename(N()));
335
+ return R(e) ? e : void 0;
336
+ }, Q = () => [
337
+ `markdown-api binary not found for ${process.platform}-${process.arch}.`,
338
+ `Expected the optional dependency ${B()} to be installed.`,
339
+ "If your platform is unsupported, build the service yourself",
340
+ "(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)",
341
+ "and point MARKDOWN_API_BINARY at it."
342
+ ].join(" "), D = () => new Promise((r) => {
343
+ const e = F.connect(b);
343
344
  e.on("connect", () => {
344
- e.destroy(), t(!0);
345
- }), e.on("error", () => t(!1));
346
- }), Q = async (t) => {
345
+ e.destroy(), r(!0);
346
+ }), e.on("error", () => r(!1));
347
+ }), $ = async (r) => {
347
348
  const e = Date.now();
348
- for (; Date.now() - e < t; ) {
349
- if (await R()) return !0;
350
- await new Promise((r) => setTimeout(r, 100));
349
+ for (; Date.now() - e < r; ) {
350
+ if (await D()) return !0;
351
+ await new Promise((t) => setTimeout(t, 100));
351
352
  }
352
353
  return !1;
353
354
  };
354
- let b = null, g = null;
355
- const Y = async () => {
356
- if (await R()) return !0;
357
- if (g) return g;
358
- g = (async () => {
359
- const e = V();
355
+ let T = null, v = null;
356
+ const O = 2e3, ee = () => {
357
+ const r = Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS);
358
+ return Number.isFinite(r) && r > 0 ? r : 1e4;
359
+ };
360
+ let A = null;
361
+ const te = async () => {
362
+ if (await D()) return !0;
363
+ if (v) return v;
364
+ v = (async () => {
365
+ const e = Y();
360
366
  if (!e)
361
- return console.warn("markdown-api binary not found. Cannot auto-start markdown server."), !1;
362
- H(e);
367
+ return await $(O) ? !0 : (A = Q(), !1);
368
+ A = null;
363
369
  try {
364
- P(T) && U(T);
370
+ R(b) && L(b);
365
371
  } catch {
366
372
  }
367
373
  try {
368
- b = E(e, [], { stdio: "ignore" });
369
- const r = () => {
370
- if (b) {
374
+ T = C(e, [], { stdio: "ignore" });
375
+ const t = () => {
376
+ if (T) {
371
377
  try {
372
- b.kill("SIGTERM");
378
+ T.kill("SIGTERM");
373
379
  } catch {
374
380
  }
375
- b = null;
381
+ T = null;
376
382
  }
377
383
  };
378
- return process.on("exit", r), await Q(1e4) ? !0 : (console.error("markdown-api Go server did not become ready on socket:", T), r(), !1);
379
- } catch (r) {
380
- return console.error("Failed to spawn markdown-api Go server:", r), b = null, !1;
384
+ return process.once("exit", t), await $(ee()) ? !0 : (console.error("markdown-api Go server did not become ready on socket:", b), t(), process.removeListener("exit", t), !1);
385
+ } catch (t) {
386
+ return console.error("Failed to spawn markdown-api Go server:", t), T = null, !1;
381
387
  }
382
388
  })();
383
- const t = await g;
384
- return t || (g = null), t;
385
- }, de = async (t, e, r, i, o = !0) => {
386
- await Y();
387
- let d = !0, a, n, s, c, f, l;
388
- typeof o == "boolean" ? d = o : o && typeof o == "object" && (d = o.validateExistence ?? !0, a = o.enableSubscript, n = o.enableSuperscript, s = o.enableMark, c = o.enableTableMerge, f = o.enableEmbeds, l = o.enableZennDirectives);
389
+ const r = await v;
390
+ return r || (v = null), r;
391
+ }, we = async (r, e, t, m, o = !0) => {
392
+ if (!await te()) {
393
+ const g = A ? ` ${A}` : "";
394
+ throw new Error(`markdown service is not reachable on ${b}.${g}`);
395
+ }
396
+ let f = !0, a, n, s, i, d, c;
397
+ typeof o == "boolean" ? f = o : o && typeof o == "object" && (f = o.validateExistence ?? !0, a = o.enableSubscript, n = o.enableSuperscript, s = o.enableMark, i = o.enableTableMerge, d = o.enableEmbeds, c = o.enableZennDirectives);
389
398
  const u = {};
390
- i && (u.Authorization = `Bearer ${i}`);
391
- const p = await Z.convert(
399
+ m && (u.Authorization = `Bearer ${m}`);
400
+ const p = await X.convert(
392
401
  {
393
- markdownText: t,
402
+ markdownText: r,
394
403
  filePath: e,
395
- workspaceRoot: r,
396
- validateExistence: d,
404
+ workspaceRoot: t,
405
+ validateExistence: f,
397
406
  enableSubscript: a,
398
407
  enableSuperscript: n,
399
408
  enableMark: s,
400
- enableTableMerge: c,
401
- enableEmbeds: f,
402
- enableZennDirectives: l
409
+ enableTableMerge: i,
410
+ enableEmbeds: d,
411
+ enableZennDirectives: c
403
412
  },
404
413
  { headers: u }
405
414
  );
406
415
  return {
407
416
  htmlContent: p.htmlContent,
408
- headings: p.headings.map((F) => ({
409
- text: F.text,
410
- depth: F.depth,
411
- id: F.id
417
+ headings: p.headings.map((g) => ({
418
+ text: g.text,
419
+ depth: g.depth,
420
+ id: g.id
412
421
  }))
413
422
  };
414
423
  };
415
424
  export {
416
- de as parseMarkdown,
417
- me as remarkImportDirective,
418
- ue as remarkResolveUriAsync,
425
+ we as parseMarkdown,
426
+ pe as remarkImportDirective,
427
+ he as remarkResolveUriAsync,
419
428
  M as transformUriAsync
420
429
  };
421
430
  //# sourceMappingURL=index.server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":["../src/plugins/remark-import-directive.async.server.ts","../src/plugins/transformUri.async.server.ts","../src/plugins/remark-resolve-uri.async.ts","../src/gen/markdown/v1/markdown_pb.ts","../src/gen/markdown/v1/markdown_connect.ts","../src/remarkProcessor.server.ts"],"sourcesContent":["/**\n * @file This file defines a remark plugin to handle `@import` directives in Markdown.\n * @brief このファイルは、Markdown 内の `@import` ディレクティブを処理するための remark プラグインを定義します。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Root } from \"mdast\"\nimport type { Processor } from \"unified\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\n\ntype ParentNodeWithChildren = {\n children: unknown[]\n}\n\nconst importRegex = /<!--\\s+@import\\s+\"(.+?)\"\\s+-->/\n\n/**\n * A remark plugin to support `@import` directives in Markdown.\n * This allows importing content from other Markdown files.\n * Markdown の `@import` ディレクティブをサポートする remark プラグイン。\n * これにより、他の Markdown ファイルからコンテンツをインポート可能。\n *\n * @param this The remark processor instance. / remark プロセッサーのインスタンス。\n * @param options Options for the plugin. / プラグインのオプション。\n * @param options.markdownFilePath The path to the Markdown file being processed. / 処理対象の Markdown ファイルへのパス。\n */\nexport function remarkImportDirective(this: Processor, options: { markdownFilePath: string }) {\n return async (tree: Root): Promise<void> => {\n const { markdownFilePath } = options\n const parentDir = path.dirname(markdownFilePath)\n\n // すべてのインポートディレクティブを収集\n const imports: { parent: ParentNodeWithChildren; index: number; absolutePath: string }[] = []\n visit(tree, \"html\", (node, index, parent) => {\n if (!parent || typeof index !== \"number\") {\n return\n }\n\n const match = node.value.match(importRegex)\n if (!match) {\n return\n }\n\n const importPath = match[1]\n const absolutePath = path.resolve(parentDir, importPath)\n if (Array.isArray((parent as { children?: unknown[] }).children)) {\n imports.push({ parent: parent as ParentNodeWithChildren, index, absolutePath })\n }\n })\n\n if (imports.length === 0) {\n return\n }\n\n // すべてのファイルを読み込み、解析\n const parsedTrees = await Promise.all(\n imports.map(async ({ absolutePath }) => {\n try {\n const fileContent = await fs.readFile(absolutePath, \"utf-8\")\n return this.parse(fileContent) as Root\n } catch (error) {\n if (error && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n Logger.warn(`[remark-import-directive] Import file not found: ${absolutePath}`)\n } else {\n Logger.error(`[remark-import-directive] Error processing import: ${absolutePath}`, error)\n }\n return null // エラー時は null を返却\n }\n }),\n )\n\n // ツリー内のノードを後方から置換\n for (let i = imports.length - 1; i >= 0; i--) {\n const { parent, index } = imports[i]\n const newTree = parsedTrees[i]\n\n if (newTree?.children && Array.isArray(newTree.children)) {\n parent.children.splice(index, 1, ...newTree.children)\n }\n }\n }\n}\n","/**\n * @file Async version of transformUri for file existence validation.\n * @brief ファイル存在確認を含む transformUri の非同期版。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport urlJoin from \"url-join\"\nimport { Logger } from \"../utils/simple-logger\"\n\n// RFC 3986 URI scheme regex\nconst URI_SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:/\n\n/**\n * Async version of transformUri that validates file existence.\n * ファイル存在確認を行う transformUri の非同期版。\n *\n * @param uri The URI to transform. / 変換対象の URI。\n * @param isImage Whether this is an image URI. / 画像 URI かどうか。\n * @param markdownFilePath Path to the markdown file. / Markdown ファイルのパス。\n * @param workspaceRoot Workspace root directory. / ワークスペースのルートディレクトリ。\n * @param validateExistence Whether to validate file existence. / ファイル存在確認を行うかどうか。\n * @returns Promise resolving to the transformed URI. / 変換された URI を返す Promise。\n */\nexport const transformUriAsync = async (uri: string, isImage: boolean, markdownFilePath: string, workspaceRoot: string, validateExistence = false): Promise<string> => {\n if (!uri) {\n return \"\"\n }\n\n // 1. 絶対URL (http, https, mailto, tel) はそのまま返す\n if (URI_SCHEME_REGEX.test(uri)) {\n const protocol = uri.substring(0, uri.indexOf(\":\")).toLowerCase()\n if ([\"http\", \"https\", \"mailto\", \"tel\", \"file\"].includes(protocol)) {\n return uri\n }\n }\n\n // 2. アンカーリンク (#fragment) はそのまま返す\n if (uri.startsWith(\"#\")) {\n return uri\n }\n\n // 3. ルート相対パス (/) はそのまま返す\n if (uri.startsWith(\"/\")) {\n return uri\n }\n\n // 4. 相対パスをプロジェクトルートからのパスとして解決する\n const decodedUri = decodeURIComponent(uri)\n const markdownDir = path.dirname(markdownFilePath)\n const projectRelativePath = path.normalize(path.join(markdownDir, decodedUri))\n\n // セキュリティチェック\n const absolutePath = path.resolve(workspaceRoot, projectRelativePath)\n if (!absolutePath.startsWith(workspaceRoot) || projectRelativePath.startsWith(\"..\")) {\n Logger.error(`Security Alert: Attempt to access file outside project root: ${absolutePath}`)\n return \"\"\n }\n\n // ファイル存在確認(オプション)\n if (validateExistence) {\n try {\n await fs.access(absolutePath)\n } catch {\n Logger.warn(`File not found: ${absolutePath}`)\n return \"\"\n }\n }\n\n const pathForEncoding = projectRelativePath.replace(/\\\\/g, \"/\")\n\n if (isImage) {\n return urlJoin(\"/assets/\", pathForEncoding)\n }\n return `?filePath=${encodeURIComponent(pathForEncoding)}`\n}\n","/**\n * @file Async version of remark-resolve-uri plugin.\n * @brief URI 解決プラグインの非同期版。\n */\nimport * as cheerio from \"cheerio\"\nimport type { Html, Image, Link, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\nimport { transformUriAsync } from \"./transformUri.async.server\"\n\ninterface Options {\n markdownFilePath: string\n workspaceRoot: string\n validateExistence?: boolean\n}\n\n/**\n * An async remark plugin to resolve image and link URIs with optional file validation.\n * ファイル検証オプション付きで画像とリンクの URI を解決する非同期 remark プラグイン。\n */\nexport function remarkResolveUriAsync(options: Options) {\n return async (tree: Root): Promise<void> => {\n if (!(options?.markdownFilePath && options?.workspaceRoot)) {\n Logger.warn(\"remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.\")\n return\n }\n\n // すべての画像とリンクノードを収集\n const uriNodes: Array<{ node: Image | Link; isImage: boolean }> = []\n const htmlNodes: Array<Html> = []\n\n visit(tree, [\"image\", \"link\", \"html\"], (node) => {\n if (node.type === \"html\") {\n htmlNodes.push(node as Html)\n } else {\n const targetNode = node as Image | Link\n if (targetNode.url) {\n uriNodes.push({ node: targetNode, isImage: targetNode.type === \"image\" })\n }\n }\n })\n\n // 並列でURI変換を実行 (標準Markdownノード)\n const transformPromises = uriNodes.map(async ({ node, isImage }) => {\n const transformedUri = await transformUriAsync(node.url, isImage, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n node.url = transformedUri\n })\n\n // 並列でURI変換を実行 (HTMLノード内の属性)\n const htmlTransformPromises = htmlNodes.map(async (node) => {\n // HTMLフラグメントとしてロード (isDocument=false)\n const $ = cheerio.load(node.value, null, false)\n let modified = false\n\n // imgタグのsrc属性を変換\n const imgTags = $(\"img\").toArray()\n for (const img of imgTags) {\n const src = $(img).attr(\"src\")\n if (src) {\n const transformed = await transformUriAsync(src, true, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== src) {\n $(img).attr(\"src\", transformed)\n modified = true\n }\n }\n }\n\n // aタグのhref属性を変換\n const aTags = $(\"a\").toArray()\n for (const a of aTags) {\n const href = $(a).attr(\"href\")\n if (href) {\n const transformed = await transformUriAsync(href, false, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== href) {\n $(a).attr(\"href\", transformed)\n modified = true\n }\n }\n }\n\n if (modified) {\n // 変更があれば node.value を更新\n // html() はエンコードされた実体を返す可能性があるが、HTMLノードとしては許容される\n const newHtml = $.html()\n if (newHtml) {\n node.value = newHtml\n }\n }\n })\n\n await Promise.all([...transformPromises, ...htmlTransformPromises])\n }\n}\n","// @generated by protoc-gen-es v1.10.1 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from \"@bufbuild/protobuf\"\nimport { Message, proto3 } from \"@bufbuild/protobuf\"\n\n/**\n * @generated from message markdown.v1.ConvertRequest\n */\nexport class ConvertRequest extends Message<ConvertRequest> {\n /**\n * @generated from field: string markdown_text = 1;\n */\n markdownText = \"\"\n\n /**\n * @generated from field: string file_path = 2;\n */\n filePath = \"\"\n\n /**\n * @generated from field: string workspace_root = 3;\n */\n workspaceRoot = \"\"\n\n /**\n * @generated from field: bool validate_existence = 4;\n */\n validateExistence = false\n\n /**\n * @generated from field: optional bool enable_subscript = 5;\n */\n enableSubscript?: boolean\n\n /**\n * @generated from field: optional bool enable_superscript = 6;\n */\n enableSuperscript?: boolean\n\n /**\n * @generated from field: optional bool enable_mark = 7;\n */\n enableMark?: boolean\n\n /**\n * @generated from field: optional bool enable_table_merge = 8;\n */\n enableTableMerge?: boolean\n\n /**\n * @generated from field: optional bool enable_embeds = 9;\n */\n enableEmbeds?: boolean\n\n /**\n * @generated from field: optional bool enable_zenn_directives = 10;\n */\n enableZennDirectives?: boolean\n\n constructor(data?: PartialMessage<ConvertRequest>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertRequest\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"markdown_text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"file_path\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 3, name: \"workspace_root\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 4, name: \"validate_existence\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */ },\n { no: 5, name: \"enable_subscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 6, name: \"enable_superscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 7, name: \"enable_mark\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 8, name: \"enable_table_merge\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 9, name: \"enable_embeds\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 10, name: \"enable_zenn_directives\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertRequest {\n return new ConvertRequest().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertRequest | PlainMessage<ConvertRequest> | undefined, b: ConvertRequest | PlainMessage<ConvertRequest> | undefined): boolean {\n return proto3.util.equals(ConvertRequest, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.ConvertResponse\n */\nexport class ConvertResponse extends Message<ConvertResponse> {\n /**\n * @generated from field: string html_content = 1;\n */\n htmlContent = \"\"\n\n /**\n * @generated from field: repeated markdown.v1.Heading headings = 2;\n */\n headings: Heading[] = []\n\n constructor(data?: PartialMessage<ConvertResponse>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertResponse\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"html_content\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"headings\", kind: \"message\", T: Heading, repeated: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertResponse {\n return new ConvertResponse().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertResponse | PlainMessage<ConvertResponse> | undefined, b: ConvertResponse | PlainMessage<ConvertResponse> | undefined): boolean {\n return proto3.util.equals(ConvertResponse, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.Heading\n */\nexport class Heading extends Message<Heading> {\n /**\n * @generated from field: string text = 1;\n */\n text = \"\"\n\n /**\n * @generated from field: int32 depth = 2;\n */\n depth = 0\n\n /**\n * @generated from field: string id = 3;\n */\n id = \"\"\n\n constructor(data?: PartialMessage<Heading>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.Heading\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"depth\", kind: \"scalar\", T: 5 /* ScalarType.INT32 */ },\n { no: 3, name: \"id\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Heading {\n return new Heading().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJsonString(jsonString, options)\n }\n\n static equals(a: Heading | PlainMessage<Heading> | undefined, b: Heading | PlainMessage<Heading> | undefined): boolean {\n return proto3.util.equals(Heading, a, b)\n }\n}\n","// @generated by protoc-gen-connect-es v1.7.0 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport { MethodKind } from \"@bufbuild/protobuf\"\nimport { ConvertRequest, ConvertResponse } from \"./markdown_pb.js\"\n\n/**\n * @generated from service markdown.v1.MarkdownService\n */\nexport const MarkdownService = {\n typeName: \"markdown.v1.MarkdownService\",\n methods: {\n /**\n * @generated from rpc markdown.v1.MarkdownService.Convert\n */\n convert: {\n name: \"Convert\",\n I: ConvertRequest,\n O: ConvertResponse,\n kind: MethodKind.Unary,\n },\n },\n} as const\n","import { spawn } from \"node:child_process\"\nimport { accessSync, chmodSync, constants, existsSync, unlinkSync } from \"node:fs\"\nimport * as net from \"node:net\"\nimport * as path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { createClient } from \"@connectrpc/connect\"\nimport { createConnectTransport } from \"@connectrpc/connect-node\"\nimport { MarkdownService } from \"./gen/markdown/v1/markdown_connect.ts\"\n\nconst SOCKET_PATH = process.env.MARKDOWN_SOCKET_PATH || \"/tmp/markdown.sock\"\n\nconst transport = createConnectTransport({\n baseUrl: \"http://localhost\",\n httpVersion: \"2\",\n nodeOptions: {\n createConnection: () => {\n return net.connect(SOCKET_PATH)\n },\n } as unknown as Record<string, unknown>,\n})\n\nconst client = createClient(MarkdownService, transport)\n\nexport interface ParseResult {\n htmlContent: string\n headings: Array<{\n text: string\n depth: number\n id: string\n }>\n}\n\nexport interface ParseOptions {\n validateExistence?: boolean\n enableSubscript?: boolean\n enableSuperscript?: boolean\n enableMark?: boolean\n enableTableMerge?: boolean\n enableEmbeds?: boolean\n enableZennDirectives?: boolean\n}\n\n/**\n * Ensures that the binary at the specified path has executable permission.\n * 指定されたパスのバイナリに実行権限が付与されていることを確認・保証する処理。\n *\n * @param binPath Path to the binary file / バイナリファイルのパス\n */\nexport const ensureExecutablePermission = (binPath: string): void => {\n try {\n accessSync(binPath, constants.X_OK)\n } catch {\n // 実行権限がない場合、0755 (-rwxr-xr-x) を付与する\n try {\n chmodSync(binPath, 0o755)\n } catch (chmodErr) {\n console.warn(\"Failed to set executable permission on markdown-api binary:\", chmodErr)\n }\n }\n}\n\n// Get the current directory name in an ES Modules friendly way\nconst getDirname = () => {\n try {\n const __filename = fileURLToPath(import.meta.url)\n return path.dirname(__filename)\n } catch {\n return __dirname\n }\n}\n\n// Locate the Go server binary path inside the package or monorepo\nconst getBinaryPath = (): string | undefined => {\n const dir = getDirname()\n // 1. In the same directory as the transpile output (dist/markdown-api)\n const sameDir = path.join(dir, \"markdown-api\")\n if (existsSync(sameDir)) return sameDir\n\n // 2. Fallback to dist directory from src\n const distDir = path.join(dir, \"..\", \"dist\", \"markdown-api\")\n if (existsSync(distDir)) return distDir\n\n // 3. Fallback to monorepo go packages folder for dev environment\n const devDir = path.join(dir, \"..\", \"..\", \"go\", \"markdown-api\", \"markdown-api\")\n if (existsSync(devDir)) return devDir\n\n return undefined\n}\n\nconst canConnect = (): Promise<boolean> =>\n new Promise((resolve) => {\n const socket = net.connect(SOCKET_PATH)\n socket.on(\"connect\", () => {\n socket.destroy()\n resolve(true)\n })\n socket.on(\"error\", () => resolve(false))\n })\n\nconst waitForServer = async (timeoutMs: number): Promise<boolean> => {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (await canConnect()) return true\n await new Promise((r) => setTimeout(r, 100))\n }\n return false\n}\n\nlet spawnedServer: ReturnType<typeof spawn> | null = null\nlet startPromise: Promise<boolean> | null = null\n\nconst ensureServerRunning = async (): Promise<boolean> => {\n if (await canConnect()) return true\n\n if (startPromise) return startPromise\n\n startPromise = (async () => {\n const binPath = getBinaryPath()\n if (!binPath) {\n console.warn(\"markdown-api binary not found. Cannot auto-start markdown server.\")\n return false\n }\n\n // Ensure executable permission on binary\n ensureExecutablePermission(binPath)\n\n // Clean up stale socket file if it exists\n try {\n if (existsSync(SOCKET_PATH)) {\n unlinkSync(SOCKET_PATH)\n }\n } catch {\n // ignore\n }\n\n try {\n spawnedServer = spawn(binPath, [], { stdio: \"ignore\" })\n\n const cleanup = () => {\n if (spawnedServer) {\n try {\n spawnedServer.kill(\"SIGTERM\")\n } catch {\n // ignore\n }\n spawnedServer = null\n }\n }\n\n process.on(\"exit\", cleanup)\n\n const ready = await waitForServer(10000)\n if (!ready) {\n console.error(\"markdown-api Go server did not become ready on socket:\", SOCKET_PATH)\n cleanup()\n return false\n }\n return true\n } catch (err) {\n console.error(\"Failed to spawn markdown-api Go server:\", err)\n spawnedServer = null\n return false\n }\n })()\n\n const success = await startPromise\n if (!success) {\n startPromise = null\n }\n return success\n}\n\nexport const parseMarkdown = async (markdownText: string, markdownFilePath: string, workspaceRoot: string, userOAuthToken?: string, validateExistenceOrOptions: boolean | ParseOptions = true): Promise<ParseResult> => {\n // Automatically ensure the backend Go server is running\n await ensureServerRunning()\n\n let validateExistence = true\n let enableSubscript: boolean | undefined\n let enableSuperscript: boolean | undefined\n let enableMark: boolean | undefined\n let enableTableMerge: boolean | undefined\n let enableEmbeds: boolean | undefined\n let enableZennDirectives: boolean | undefined\n\n if (typeof validateExistenceOrOptions === \"boolean\") {\n validateExistence = validateExistenceOrOptions\n } else if (validateExistenceOrOptions && typeof validateExistenceOrOptions === \"object\") {\n validateExistence = validateExistenceOrOptions.validateExistence ?? true\n enableSubscript = validateExistenceOrOptions.enableSubscript\n enableSuperscript = validateExistenceOrOptions.enableSuperscript\n enableMark = validateExistenceOrOptions.enableMark\n enableTableMerge = validateExistenceOrOptions.enableTableMerge\n enableEmbeds = validateExistenceOrOptions.enableEmbeds\n enableZennDirectives = validateExistenceOrOptions.enableZennDirectives\n }\n\n const headers: Record<string, string> = {}\n if (userOAuthToken) {\n headers.Authorization = `Bearer ${userOAuthToken}`\n }\n\n const response = await client.convert(\n {\n markdownText,\n filePath: markdownFilePath,\n workspaceRoot,\n validateExistence,\n enableSubscript,\n enableSuperscript,\n enableMark,\n enableTableMerge,\n enableEmbeds,\n enableZennDirectives,\n },\n { headers },\n )\n\n return {\n htmlContent: response.htmlContent,\n headings: response.headings.map((h) => ({\n text: h.text,\n depth: h.depth,\n id: h.id,\n })),\n }\n}\n"],"names":["importRegex","remarkImportDirective","options","tree","markdownFilePath","parentDir","path","imports","visit","node","index","parent","match","importPath","absolutePath","parsedTrees","fileContent","fs","error","Logger","i","newTree","URI_SCHEME_REGEX","transformUriAsync","uri","isImage","workspaceRoot","validateExistence","protocol","decodedUri","markdownDir","projectRelativePath","pathForEncoding","urlJoin","remarkResolveUriAsync","uriNodes","htmlNodes","targetNode","transformPromises","transformedUri","htmlTransformPromises","$","cheerio","modified","imgTags","img","src","transformed","aTags","a","href","newHtml","ConvertRequest","Message","data","proto3","bytes","jsonValue","jsonString","b","ConvertResponse","Heading","MarkdownService","MethodKind","SOCKET_PATH","transport","createConnectTransport","net","client","createClient","ensureExecutablePermission","binPath","accessSync","constants","chmodSync","chmodErr","getDirname","__filename","fileURLToPath","getBinaryPath","dir","sameDir","existsSync","distDir","devDir","canConnect","resolve","socket","waitForServer","timeoutMs","start","spawnedServer","startPromise","ensureServerRunning","unlinkSync","spawn","cleanup","err","success","parseMarkdown","markdownText","userOAuthToken","validateExistenceOrOptions","enableSubscript","enableSuperscript","enableMark","enableTableMerge","enableEmbeds","enableZennDirectives","headers","response","h"],"mappings":"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"}
1
+ {"version":3,"file":"index.server.js","sources":["../src/plugins/remark-import-directive.async.server.ts","../src/plugins/transformUri.async.server.ts","../src/plugins/remark-resolve-uri.async.ts","../src/gen/markdown/v1/markdown_pb.ts","../src/gen/markdown/v1/markdown_connect.ts","../src/remarkProcessor.server.ts"],"sourcesContent":["/**\n * @file This file defines a remark plugin to handle `@import` directives in Markdown.\n * @brief このファイルは、Markdown 内の `@import` ディレクティブを処理するための remark プラグインを定義します。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Root } from \"mdast\"\nimport type { Processor } from \"unified\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\n\ntype ParentNodeWithChildren = {\n children: unknown[]\n}\n\nconst importRegex = /<!--\\s+@import\\s+\"(.+?)\"\\s+-->/\n\n/**\n * A remark plugin to support `@import` directives in Markdown.\n * This allows importing content from other Markdown files.\n * Markdown の `@import` ディレクティブをサポートする remark プラグイン。\n * これにより、他の Markdown ファイルからコンテンツをインポート可能。\n *\n * @param this The remark processor instance. / remark プロセッサーのインスタンス。\n * @param options Options for the plugin. / プラグインのオプション。\n * @param options.markdownFilePath The path to the Markdown file being processed. / 処理対象の Markdown ファイルへのパス。\n */\nexport function remarkImportDirective(this: Processor, options: { markdownFilePath: string }) {\n return async (tree: Root): Promise<void> => {\n const { markdownFilePath } = options\n const parentDir = path.dirname(markdownFilePath)\n\n // すべてのインポートディレクティブを収集\n const imports: { parent: ParentNodeWithChildren; index: number; absolutePath: string }[] = []\n visit(tree, \"html\", (node, index, parent) => {\n if (!parent || typeof index !== \"number\") {\n return\n }\n\n const match = node.value.match(importRegex)\n if (!match) {\n return\n }\n\n const importPath = match[1]\n const absolutePath = path.resolve(parentDir, importPath)\n if (Array.isArray((parent as { children?: unknown[] }).children)) {\n imports.push({ parent: parent as ParentNodeWithChildren, index, absolutePath })\n }\n })\n\n if (imports.length === 0) {\n return\n }\n\n // すべてのファイルを読み込み、解析\n const parsedTrees = await Promise.all(\n imports.map(async ({ absolutePath }) => {\n try {\n const fileContent = await fs.readFile(absolutePath, \"utf-8\")\n return this.parse(fileContent) as Root\n } catch (error) {\n if (error && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n Logger.warn(`[remark-import-directive] Import file not found: ${absolutePath}`)\n } else {\n Logger.error(`[remark-import-directive] Error processing import: ${absolutePath}`, error)\n }\n return null // エラー時は null を返却\n }\n }),\n )\n\n // ツリー内のノードを後方から置換\n for (let i = imports.length - 1; i >= 0; i--) {\n const { parent, index } = imports[i]\n const newTree = parsedTrees[i]\n\n if (newTree?.children && Array.isArray(newTree.children)) {\n parent.children.splice(index, 1, ...newTree.children)\n }\n }\n }\n}\n","/**\n * @file Async version of transformUri for file existence validation.\n * @brief ファイル存在確認を含む transformUri の非同期版。\n */\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport urlJoin from \"url-join\"\nimport { Logger } from \"../utils/simple-logger\"\n\n// RFC 3986 URI scheme regex\nconst URI_SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:/\n\n/**\n * Async version of transformUri that validates file existence.\n * ファイル存在確認を行う transformUri の非同期版。\n *\n * @param uri The URI to transform. / 変換対象の URI。\n * @param isImage Whether this is an image URI. / 画像 URI かどうか。\n * @param markdownFilePath Path to the markdown file. / Markdown ファイルのパス。\n * @param workspaceRoot Workspace root directory. / ワークスペースのルートディレクトリ。\n * @param validateExistence Whether to validate file existence. / ファイル存在確認を行うかどうか。\n * @returns Promise resolving to the transformed URI. / 変換された URI を返す Promise。\n */\nexport const transformUriAsync = async (uri: string, isImage: boolean, markdownFilePath: string, workspaceRoot: string, validateExistence = false): Promise<string> => {\n if (!uri) {\n return \"\"\n }\n\n // 1. 絶対URL (http, https, mailto, tel) はそのまま返す\n if (URI_SCHEME_REGEX.test(uri)) {\n const protocol = uri.substring(0, uri.indexOf(\":\")).toLowerCase()\n if ([\"http\", \"https\", \"mailto\", \"tel\", \"file\"].includes(protocol)) {\n return uri\n }\n }\n\n // 2. アンカーリンク (#fragment) はそのまま返す\n if (uri.startsWith(\"#\")) {\n return uri\n }\n\n // 3. ルート相対パス (/) はそのまま返す\n if (uri.startsWith(\"/\")) {\n return uri\n }\n\n // 4. 相対パスをプロジェクトルートからのパスとして解決する\n const decodedUri = decodeURIComponent(uri)\n const markdownDir = path.dirname(markdownFilePath)\n const projectRelativePath = path.normalize(path.join(markdownDir, decodedUri))\n\n // セキュリティチェック\n const absolutePath = path.resolve(workspaceRoot, projectRelativePath)\n if (!absolutePath.startsWith(workspaceRoot) || projectRelativePath.startsWith(\"..\")) {\n Logger.error(`Security Alert: Attempt to access file outside project root: ${absolutePath}`)\n return \"\"\n }\n\n // ファイル存在確認(オプション)\n if (validateExistence) {\n try {\n await fs.access(absolutePath)\n } catch {\n Logger.warn(`File not found: ${absolutePath}`)\n return \"\"\n }\n }\n\n const pathForEncoding = projectRelativePath.replace(/\\\\/g, \"/\")\n\n if (isImage) {\n return urlJoin(\"/assets/\", pathForEncoding)\n }\n return `?filePath=${encodeURIComponent(pathForEncoding)}`\n}\n","/**\n * @file Async version of remark-resolve-uri plugin.\n * @brief URI 解決プラグインの非同期版。\n */\nimport * as cheerio from \"cheerio\"\nimport type { Html, Image, Link, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { Logger } from \"../utils/simple-logger\"\nimport { transformUriAsync } from \"./transformUri.async.server\"\n\ninterface Options {\n markdownFilePath: string\n workspaceRoot: string\n validateExistence?: boolean\n}\n\n/**\n * An async remark plugin to resolve image and link URIs with optional file validation.\n * ファイル検証オプション付きで画像とリンクの URI を解決する非同期 remark プラグイン。\n */\nexport function remarkResolveUriAsync(options: Options) {\n return async (tree: Root): Promise<void> => {\n if (!(options?.markdownFilePath && options?.workspaceRoot)) {\n Logger.warn(\"remark-resolve-uri-async: markdownFilePath and workspaceRoot are required. Skipping URI resolution.\")\n return\n }\n\n // すべての画像とリンクノードを収集\n const uriNodes: Array<{ node: Image | Link; isImage: boolean }> = []\n const htmlNodes: Array<Html> = []\n\n visit(tree, [\"image\", \"link\", \"html\"], (node) => {\n if (node.type === \"html\") {\n htmlNodes.push(node as Html)\n } else {\n const targetNode = node as Image | Link\n if (targetNode.url) {\n uriNodes.push({ node: targetNode, isImage: targetNode.type === \"image\" })\n }\n }\n })\n\n // 並列でURI変換を実行 (標準Markdownノード)\n const transformPromises = uriNodes.map(async ({ node, isImage }) => {\n const transformedUri = await transformUriAsync(node.url, isImage, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n node.url = transformedUri\n })\n\n // 並列でURI変換を実行 (HTMLノード内の属性)\n const htmlTransformPromises = htmlNodes.map(async (node) => {\n // HTMLフラグメントとしてロード (isDocument=false)\n const $ = cheerio.load(node.value, null, false)\n let modified = false\n\n // imgタグのsrc属性を変換\n const imgTags = $(\"img\").toArray()\n for (const img of imgTags) {\n const src = $(img).attr(\"src\")\n if (src) {\n const transformed = await transformUriAsync(src, true, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== src) {\n $(img).attr(\"src\", transformed)\n modified = true\n }\n }\n }\n\n // aタグのhref属性を変換\n const aTags = $(\"a\").toArray()\n for (const a of aTags) {\n const href = $(a).attr(\"href\")\n if (href) {\n const transformed = await transformUriAsync(href, false, options.markdownFilePath, options.workspaceRoot, options.validateExistence)\n if (transformed !== href) {\n $(a).attr(\"href\", transformed)\n modified = true\n }\n }\n }\n\n if (modified) {\n // 変更があれば node.value を更新\n // html() はエンコードされた実体を返す可能性があるが、HTMLノードとしては許容される\n const newHtml = $.html()\n if (newHtml) {\n node.value = newHtml\n }\n }\n })\n\n await Promise.all([...transformPromises, ...htmlTransformPromises])\n }\n}\n","// @generated by protoc-gen-es v1.10.1 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from \"@bufbuild/protobuf\"\nimport { Message, proto3 } from \"@bufbuild/protobuf\"\n\n/**\n * @generated from message markdown.v1.ConvertRequest\n */\nexport class ConvertRequest extends Message<ConvertRequest> {\n /**\n * @generated from field: string markdown_text = 1;\n */\n markdownText = \"\"\n\n /**\n * @generated from field: string file_path = 2;\n */\n filePath = \"\"\n\n /**\n * @generated from field: string workspace_root = 3;\n */\n workspaceRoot = \"\"\n\n /**\n * @generated from field: bool validate_existence = 4;\n */\n validateExistence = false\n\n /**\n * @generated from field: optional bool enable_subscript = 5;\n */\n enableSubscript?: boolean\n\n /**\n * @generated from field: optional bool enable_superscript = 6;\n */\n enableSuperscript?: boolean\n\n /**\n * @generated from field: optional bool enable_mark = 7;\n */\n enableMark?: boolean\n\n /**\n * @generated from field: optional bool enable_table_merge = 8;\n */\n enableTableMerge?: boolean\n\n /**\n * @generated from field: optional bool enable_embeds = 9;\n */\n enableEmbeds?: boolean\n\n /**\n * @generated from field: optional bool enable_zenn_directives = 10;\n */\n enableZennDirectives?: boolean\n\n constructor(data?: PartialMessage<ConvertRequest>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertRequest\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"markdown_text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"file_path\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 3, name: \"workspace_root\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 4, name: \"validate_existence\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */ },\n { no: 5, name: \"enable_subscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 6, name: \"enable_superscript\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 7, name: \"enable_mark\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 8, name: \"enable_table_merge\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 9, name: \"enable_embeds\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n { no: 10, name: \"enable_zenn_directives\", kind: \"scalar\", T: 8 /* ScalarType.BOOL */, opt: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertRequest {\n return new ConvertRequest().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertRequest {\n return new ConvertRequest().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertRequest | PlainMessage<ConvertRequest> | undefined, b: ConvertRequest | PlainMessage<ConvertRequest> | undefined): boolean {\n return proto3.util.equals(ConvertRequest, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.ConvertResponse\n */\nexport class ConvertResponse extends Message<ConvertResponse> {\n /**\n * @generated from field: string html_content = 1;\n */\n htmlContent = \"\"\n\n /**\n * @generated from field: repeated markdown.v1.Heading headings = 2;\n */\n headings: Heading[] = []\n\n constructor(data?: PartialMessage<ConvertResponse>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.ConvertResponse\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"html_content\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"headings\", kind: \"message\", T: Heading, repeated: true },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ConvertResponse {\n return new ConvertResponse().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ConvertResponse {\n return new ConvertResponse().fromJsonString(jsonString, options)\n }\n\n static equals(a: ConvertResponse | PlainMessage<ConvertResponse> | undefined, b: ConvertResponse | PlainMessage<ConvertResponse> | undefined): boolean {\n return proto3.util.equals(ConvertResponse, a, b)\n }\n}\n\n/**\n * @generated from message markdown.v1.Heading\n */\nexport class Heading extends Message<Heading> {\n /**\n * @generated from field: string text = 1;\n */\n text = \"\"\n\n /**\n * @generated from field: int32 depth = 2;\n */\n depth = 0\n\n /**\n * @generated from field: string id = 3;\n */\n id = \"\"\n\n constructor(data?: PartialMessage<Heading>) {\n super()\n proto3.util.initPartial(data, this)\n }\n\n static readonly runtime: typeof proto3 = proto3\n static readonly typeName = \"markdown.v1.Heading\"\n static readonly fields: FieldList = proto3.util.newFieldList(() => [\n { no: 1, name: \"text\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n { no: 2, name: \"depth\", kind: \"scalar\", T: 5 /* ScalarType.INT32 */ },\n { no: 3, name: \"id\", kind: \"scalar\", T: 9 /* ScalarType.STRING */ },\n ])\n\n static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Heading {\n return new Heading().fromBinary(bytes, options)\n }\n\n static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJson(jsonValue, options)\n }\n\n static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Heading {\n return new Heading().fromJsonString(jsonString, options)\n }\n\n static equals(a: Heading | PlainMessage<Heading> | undefined, b: Heading | PlainMessage<Heading> | undefined): boolean {\n return proto3.util.equals(Heading, a, b)\n }\n}\n","// @generated by protoc-gen-connect-es v1.7.0 with parameter \"target=ts\"\n// @generated from file markdown/v1/markdown.proto (package markdown.v1, syntax proto3)\n/* eslint-disable */\n// @ts-nocheck\n\nimport { MethodKind } from \"@bufbuild/protobuf\"\nimport { ConvertRequest, ConvertResponse } from \"./markdown_pb.js\"\n\n/**\n * @generated from service markdown.v1.MarkdownService\n */\nexport const MarkdownService = {\n typeName: \"markdown.v1.MarkdownService\",\n methods: {\n /**\n * @generated from rpc markdown.v1.MarkdownService.Convert\n */\n convert: {\n name: \"Convert\",\n I: ConvertRequest,\n O: ConvertResponse,\n kind: MethodKind.Unary,\n },\n },\n} as const\n","import { spawn } from \"node:child_process\"\nimport { existsSync, unlinkSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\nimport * as net from \"node:net\"\nimport * as path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { createClient } from \"@connectrpc/connect\"\nimport { createConnectTransport } from \"@connectrpc/connect-node\"\nimport { MarkdownService } from \"./gen/markdown/v1/markdown_connect.ts\"\n\nconst SOCKET_PATH = process.env.MARKDOWN_SOCKET_PATH || \"/tmp/markdown.sock\"\n\nconst transport = createConnectTransport({\n baseUrl: \"http://localhost\",\n httpVersion: \"2\",\n nodeOptions: {\n createConnection: () => {\n return net.connect(SOCKET_PATH)\n },\n } as unknown as Record<string, unknown>,\n})\n\nconst client = createClient(MarkdownService, transport)\n\nexport interface ParseResult {\n htmlContent: string\n headings: Array<{\n text: string\n depth: number\n id: string\n }>\n}\n\nexport interface ParseOptions {\n validateExistence?: boolean\n enableSubscript?: boolean\n enableSuperscript?: boolean\n enableMark?: boolean\n enableTableMerge?: boolean\n enableEmbeds?: boolean\n enableZennDirectives?: boolean\n}\n\n/**\n * Returns the directory of this module in a way that works for both ESM and CJS output.\n * ESM / CJS どちらのビルド出力でも動作する形で本モジュールのディレクトリを返す処理。\n *\n * @returns Absolute directory path / 絶対ディレクトリパス\n */\nconst getDirname = (): string => {\n try {\n return path.dirname(fileURLToPath(import.meta.url))\n } catch {\n return __dirname\n }\n}\n\n/** プラットフォームパッケージ名 (@aiquants/markdown-linux-x64 等) */\nconst platformPackageName = (): string => `@aiquants/markdown-${process.platform}-${process.arch}`\n\n/** プラットフォームパッケージ内のバイナリ相対パス (Windows のみ .exe) */\nconst platformBinarySubpath = (): string => (process.platform === \"win32\" ? \"bin/markdown-api.exe\" : \"bin/markdown-api\")\n\n/**\n * Locates the `markdown-api` binary for the running platform.\n * 実行中プラットフォーム向けの `markdown-api` バイナリを探索する処理。\n *\n * 探索順:\n * 1. `MARKDOWN_API_BINARY` 環境変数 (自前ビルドの差し込み口)\n * 2. プラットフォームパッケージ (通常の配布経路。Node の解決機構に委ねるため\n * パス組み立てのヒューリスティックが不要)\n * 3. モノレポ開発時に `pnpm run build:go` がビルドする `packages/go/markdown-api/dist/`\n *\n * 候補 3 はモノレポ内の消費アプリからは機能しない。workspace 依存が injected\n * (ハードリンクコピー) で解決されるため、`.pnpm/` 配下のコピーから相対で辿れない。\n * サービスを自前起動する統合テストは `MARKDOWN_API_BINARY` を明示すること。\n *\n * 実行権限は付与しない。バイナリはプラットフォームパッケージの `bin` フィールド経由で\n * 配られ、パッケージマネージャが 0755 を保証する。\n *\n * @returns Absolute binary path, or undefined when unavailable / バイナリの絶対パス。見つからない場合は undefined\n */\nexport const resolveBinaryPath = (): string | undefined => {\n const fromEnvironment = process.env.MARKDOWN_API_BINARY\n if (fromEnvironment && existsSync(fromEnvironment)) {\n return fromEnvironment\n }\n\n try {\n // createRequire の基点はビルド形式に依存しない getDirname() から作る\n // (CJS 出力で import.meta.url がどう変換されても影響を受けない)\n const resolved = createRequire(path.join(getDirname(), \"index.js\")).resolve(`${platformPackageName()}/${platformBinarySubpath()}`)\n if (existsSync(resolved)) {\n return resolved\n }\n } catch {\n // プラットフォームパッケージ未インストール (モノレポ開発時は常にこの経路)\n }\n\n const monorepoBinary = path.join(getDirname(), \"..\", \"..\", \"go\", \"markdown-api\", \"dist\", path.basename(platformBinarySubpath()))\n return existsSync(monorepoBinary) ? monorepoBinary : undefined\n}\n\n/**\n * Builds a diagnosable message for a missing binary.\n * バイナリが見つからない場合の原因診断メッセージを組み立てる処理。\n *\n * 「見つからない」だけでは利用者が次に何をすべきか分からないため、期待した\n * プラットフォームパッケージ名と自前ビルドの差し込み口まで示す。\n *\n * @returns Human-readable diagnostic message / 人間が読める診断メッセージ\n */\nconst describeMissingBinary = (): string =>\n [\n `markdown-api binary not found for ${process.platform}-${process.arch}.`,\n `Expected the optional dependency ${platformPackageName()} to be installed.`,\n \"If your platform is unsupported, build the service yourself\",\n \"(https://github.com/fehde-k/aiquants/tree/main/packages/go/markdown-api)\",\n \"and point MARKDOWN_API_BINARY at it.\",\n ].join(\" \")\n\nconst canConnect = (): Promise<boolean> =>\n new Promise((resolve) => {\n const socket = net.connect(SOCKET_PATH)\n socket.on(\"connect\", () => {\n socket.destroy()\n resolve(true)\n })\n socket.on(\"error\", () => resolve(false))\n })\n\nconst waitForServer = async (timeoutMs: number): Promise<boolean> => {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (await canConnect()) return true\n await new Promise((r) => setTimeout(r, 100))\n }\n return false\n}\n\nlet spawnedServer: ReturnType<typeof spawn> | null = null\nlet startPromise: Promise<boolean> | null = null\n\n/**\n * Grace period for a server started outside this process, in milliseconds.\n * 本プロセス外で起動されたサーバを待つ猶予時間 (ミリ秒)。\n *\n * コンテナ環境ではプロセスマネージャ (supervisor 等) が `markdown-api` を別プログラムとして\n * 起動するため、パッケージ内にバイナリは存在しない。その構成で Node 側が先に温まると\n * ソケット未 bind の瞬間に当たりうるので、自前起動を諦める前に短時間だけ待つ。\n * Go 側の bind はミリ秒で完了するため、これで十分。\n */\nconst EXTERNAL_SERVER_GRACE_MS = 2000\n\n/**\n * Time budget for a freshly spawned server to start listening, in milliseconds.\n * 新規起動したサーバが待ち受け開始するまでの猶予時間 (ミリ秒)。\n *\n * 低速な CI コンテナでは既定の 10 秒でも足りないことがあるため環境変数で調整できる。\n * 不正値 (数値でない / 0 以下) は既定へ戻す (設定ミスで永久に待たないようにする)。\n *\n * @returns Timeout in milliseconds / ミリ秒単位のタイムアウト\n */\nconst startupTimeoutMs = (): number => {\n const configured = Number(process.env.MARKDOWN_API_STARTUP_TIMEOUT_MS)\n return Number.isFinite(configured) && configured > 0 ? configured : 10000\n}\n\n/** 自動起動をバイナリ不在で諦めた理由。到達不能エラーへ添えて診断可能にする */\nlet missingBinaryReason: string | null = null\n\nconst ensureServerRunning = async (): Promise<boolean> => {\n if (await canConnect()) return true\n\n if (startPromise) return startPromise\n\n startPromise = (async () => {\n const binPath = resolveBinaryPath()\n if (!binPath) {\n // 外部管理サーバの起動待ちに賭ける。ここで即諦めると、プロセスマネージャ管理型の\n // 構成 (バイナリを同梱しない) で起動直後のリクエストが理由なく失敗する\n if (await waitForServer(EXTERNAL_SERVER_GRACE_MS)) return true\n missingBinaryReason = describeMissingBinary()\n return false\n }\n // バイナリが見つかった以降は不在が理由ではない。古い理由を残すと誤診を招く\n missingBinaryReason = null\n\n // Clean up stale socket file if it exists\n try {\n if (existsSync(SOCKET_PATH)) {\n unlinkSync(SOCKET_PATH)\n }\n } catch {\n // ignore\n }\n\n try {\n spawnedServer = spawn(binPath, [], { stdio: \"ignore\" })\n\n const cleanup = () => {\n if (spawnedServer) {\n try {\n spawnedServer.kill(\"SIGTERM\")\n } catch {\n // 既に終了しているケースは無視する\n }\n spawnedServer = null\n }\n }\n\n // once で登録し、失敗時は明示的に解除する。on のままだと起動失敗を\n // 繰り返すたびにリスナーが蓄積し、MaxListeners 警告とメモリリークを招く\n process.once(\"exit\", cleanup)\n\n const ready = await waitForServer(startupTimeoutMs())\n if (!ready) {\n console.error(\"markdown-api Go server did not become ready on socket:\", SOCKET_PATH)\n cleanup()\n process.removeListener(\"exit\", cleanup)\n return false\n }\n return true\n } catch (err) {\n console.error(\"Failed to spawn markdown-api Go server:\", err)\n spawnedServer = null\n return false\n }\n })()\n\n const success = await startPromise\n if (!success) {\n startPromise = null\n }\n return success\n}\n\nexport const parseMarkdown = async (markdownText: string, markdownFilePath: string, workspaceRoot: string, userOAuthToken?: string, validateExistenceOrOptions: boolean | ParseOptions = true): Promise<ParseResult> => {\n // Automatically ensure the backend Go server is running\n if (!(await ensureServerRunning())) {\n // 到達できないまま RPC へ進むと、利用者には原因不明の ENOENT だけが届く。\n // 自動起動がバイナリ不在で諦めた場合は、必要なパッケージ名まで含めて伝える\n const detail = missingBinaryReason ? ` ${missingBinaryReason}` : \"\"\n throw new Error(`markdown service is not reachable on ${SOCKET_PATH}.${detail}`)\n }\n\n let validateExistence = true\n let enableSubscript: boolean | undefined\n let enableSuperscript: boolean | undefined\n let enableMark: boolean | undefined\n let enableTableMerge: boolean | undefined\n let enableEmbeds: boolean | undefined\n let enableZennDirectives: boolean | undefined\n\n if (typeof validateExistenceOrOptions === \"boolean\") {\n validateExistence = validateExistenceOrOptions\n } else if (validateExistenceOrOptions && typeof validateExistenceOrOptions === \"object\") {\n validateExistence = validateExistenceOrOptions.validateExistence ?? true\n enableSubscript = validateExistenceOrOptions.enableSubscript\n enableSuperscript = validateExistenceOrOptions.enableSuperscript\n enableMark = validateExistenceOrOptions.enableMark\n enableTableMerge = validateExistenceOrOptions.enableTableMerge\n enableEmbeds = validateExistenceOrOptions.enableEmbeds\n enableZennDirectives = validateExistenceOrOptions.enableZennDirectives\n }\n\n const headers: Record<string, string> = {}\n if (userOAuthToken) {\n headers.Authorization = `Bearer ${userOAuthToken}`\n }\n\n const response = await client.convert(\n {\n markdownText,\n filePath: markdownFilePath,\n workspaceRoot,\n validateExistence,\n enableSubscript,\n enableSuperscript,\n enableMark,\n enableTableMerge,\n enableEmbeds,\n enableZennDirectives,\n },\n { headers },\n )\n\n return {\n htmlContent: response.htmlContent,\n headings: response.headings.map((h) => ({\n text: h.text,\n depth: h.depth,\n id: h.id,\n })),\n }\n}\n"],"names":["importRegex","remarkImportDirective","options","tree","markdownFilePath","parentDir","path","imports","visit","node","index","parent","match","importPath","absolutePath","parsedTrees","fileContent","fs","error","Logger","i","newTree","URI_SCHEME_REGEX","transformUriAsync","uri","isImage","workspaceRoot","validateExistence","protocol","decodedUri","markdownDir","projectRelativePath","pathForEncoding","urlJoin","remarkResolveUriAsync","uriNodes","htmlNodes","targetNode","transformPromises","transformedUri","htmlTransformPromises","$","cheerio","modified","imgTags","img","src","transformed","aTags","a","href","newHtml","ConvertRequest","Message","data","proto3","bytes","jsonValue","jsonString","b","ConvertResponse","Heading","MarkdownService","MethodKind","SOCKET_PATH","transport","createConnectTransport","net","client","createClient","getDirname","fileURLToPath","platformPackageName","platformBinarySubpath","resolveBinaryPath","fromEnvironment","existsSync","resolved","createRequire","monorepoBinary","describeMissingBinary","canConnect","resolve","socket","waitForServer","timeoutMs","start","r","spawnedServer","startPromise","EXTERNAL_SERVER_GRACE_MS","startupTimeoutMs","configured","missingBinaryReason","ensureServerRunning","binPath","unlinkSync","spawn","cleanup","err","success","parseMarkdown","markdownText","userOAuthToken","validateExistenceOrOptions","detail","enableSubscript","enableSuperscript","enableMark","enableTableMerge","enableEmbeds","enableZennDirectives","headers","response","h"],"mappings":"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"}
@@ -5,5 +5,5 @@
5
5
  export { remarkImportDirective } from './plugins/remark-import-directive.async.server.ts';
6
6
  export { remarkResolveUriAsync } from './plugins/remark-resolve-uri.async.ts';
7
7
  export { transformUriAsync } from './plugins/transformUri.async.server.ts';
8
- export { type ParseResult, parseMarkdown } from './remarkProcessor.server.ts';
8
+ export { type ParseOptions, type ParseResult, parseMarkdown } from './remarkProcessor.server.ts';
9
9
  //# sourceMappingURL=index.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.d.ts","sourceRoot":"","sources":["../../src/index.server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAE1E,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.server.d.ts","sourceRoot":"","sources":["../../src/index.server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAE1E,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA"}
@@ -16,11 +16,24 @@ export interface ParseOptions {
16
16
  enableZennDirectives?: boolean;
17
17
  }
18
18
  /**
19
- * Ensures that the binary at the specified path has executable permission.
20
- * 指定されたパスのバイナリに実行権限が付与されていることを確認・保証する処理。
19
+ * Locates the `markdown-api` binary for the running platform.
20
+ * 実行中プラットフォーム向けの `markdown-api` バイナリを探索する処理。
21
21
  *
22
- * @param binPath Path to the binary file / バイナリファイルのパス
22
+ * 探索順:
23
+ * 1. `MARKDOWN_API_BINARY` 環境変数 (自前ビルドの差し込み口)
24
+ * 2. プラットフォームパッケージ (通常の配布経路。Node の解決機構に委ねるため
25
+ * パス組み立てのヒューリスティックが不要)
26
+ * 3. モノレポ開発時に `pnpm run build:go` がビルドする `packages/go/markdown-api/dist/`
27
+ *
28
+ * 候補 3 はモノレポ内の消費アプリからは機能しない。workspace 依存が injected
29
+ * (ハードリンクコピー) で解決されるため、`.pnpm/` 配下のコピーから相対で辿れない。
30
+ * サービスを自前起動する統合テストは `MARKDOWN_API_BINARY` を明示すること。
31
+ *
32
+ * 実行権限は付与しない。バイナリはプラットフォームパッケージの `bin` フィールド経由で
33
+ * 配られ、パッケージマネージャが 0755 を保証する。
34
+ *
35
+ * @returns Absolute binary path, or undefined when unavailable / バイナリの絶対パス。見つからない場合は undefined
23
36
  */
24
- export declare const ensureExecutablePermission: (binPath: string) => void;
37
+ export declare const resolveBinaryPath: () => string | undefined;
25
38
  export declare const parseMarkdown: (markdownText: string, markdownFilePath: string, workspaceRoot: string, userOAuthToken?: string, validateExistenceOrOptions?: boolean | ParseOptions) => Promise<ParseResult>;
26
39
  //# sourceMappingURL=remarkProcessor.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remarkProcessor.server.d.ts","sourceRoot":"","sources":["../../src/remarkProcessor.server.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,WAAW;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,EAAE,EAAE,MAAM,CAAA;KACb,CAAC,CAAA;CACL;AAED,MAAM,WAAW,YAAY;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,MAAM,KAAG,IAW5D,CAAA;AAiHD,eAAO,MAAM,aAAa,GAAU,cAAc,MAAM,EAAE,kBAAkB,MAAM,EAAE,eAAe,MAAM,EAAE,iBAAiB,MAAM,EAAE,6BAA4B,OAAO,GAAG,YAAmB,KAAG,OAAO,CAAC,WAAW,CAqDlN,CAAA"}
1
+ {"version":3,"file":"remarkProcessor.server.d.ts","sourceRoot":"","sources":["../../src/remarkProcessor.server.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,WAAW;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,EAAE,EAAE,MAAM,CAAA;KACb,CAAC,CAAA;CACL;AAED,MAAM,WAAW,YAAY;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CACjC;AAsBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,QAAO,MAAM,GAAG,SAmB7C,CAAA;AAwID,eAAO,MAAM,aAAa,GAAU,cAAc,MAAM,EAAE,kBAAkB,MAAM,EAAE,eAAe,MAAM,EAAE,iBAAiB,MAAM,EAAE,6BAA4B,OAAO,GAAG,YAAmB,KAAG,OAAO,CAAC,WAAW,CA0DlN,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"vite.config.d.ts","sourceRoot":"","sources":["../vite.config.ts"],"names":[],"mappings":";AAsCA,wBAiHE"}
1
+ {"version":3,"file":"vite.config.d.ts","sourceRoot":"","sources":["../vite.config.ts"],"names":[],"mappings":";AAsCA,wBAmHE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/markdown",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Markdown renderer for React with advanced features",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -101,7 +101,8 @@
101
101
  "tailwindcss-animate": "^1.0.7",
102
102
  "typescript": "^5.9.3",
103
103
  "vite-plugin-dts": "^4.5.4",
104
- "vitest": "^3.2.4"
104
+ "vitest": "^3.2.4",
105
+ "@aiquants/platform-packaging": "0.1.0"
105
106
  },
106
107
  "keywords": [
107
108
  "markdown",
@@ -117,13 +118,35 @@
117
118
  "url": "https://x.com/fehdek"
118
119
  },
119
120
  "license": "MIT",
121
+ "repository": {
122
+ "type": "git",
123
+ "url": "git+https://github.com/fehde-k/aiquants.git",
124
+ "directory": "packages/markdown"
125
+ },
126
+ "homepage": "https://github.com/fehde-k/aiquants/tree/main/packages/markdown#readme",
127
+ "bugs": {
128
+ "url": "https://github.com/fehde-k/aiquants/issues"
129
+ },
130
+ "engines": {
131
+ "node": ">=20.0.0"
132
+ },
120
133
  "publishConfig": {
121
134
  "access": "public"
122
135
  },
136
+ "optionalDependencies": {
137
+ "@aiquants/markdown-linux-x64": "1.13.0",
138
+ "@aiquants/markdown-linux-arm64": "1.13.0",
139
+ "@aiquants/markdown-darwin-x64": "1.13.0",
140
+ "@aiquants/markdown-darwin-arm64": "1.13.0",
141
+ "@aiquants/markdown-win32-x64": "1.13.0",
142
+ "@aiquants/markdown-win32-arm64": "1.13.0"
143
+ },
123
144
  "scripts": {
124
- "build": "rimraf dist && GOOS=linux GOARCH=amd64 go build -C ../go/markdown-api -o ../../markdown/dist/markdown-api main.go && (chmod +x dist/markdown-api || true) && vite build && vite build --config vite.config.cli.ts && pnpm build:css",
145
+ "build": "rimraf dist && vite build && vite build --config vite.config.cli.ts && pnpm build:css",
125
146
  "build:css": "tailwindcss -i src/styles/tailwind.css -o dist/styles/markdown.css --minify",
126
- "postinstall": "chmod +x dist/markdown-api || true",
147
+ "build:go": "go build -C ../go/markdown-api -trimpath -ldflags=\"-s -w\" -o dist/markdown-api .",
148
+ "build:platforms": "node scripts/build-platform-packages.mjs",
149
+ "publish:platforms": "node scripts/publish-platform-packages.mjs",
127
150
  "dev": "vite build --watch",
128
151
  "watch": "vite build --watch",
129
152
  "demo:dev": "cd demo && pnpm run dev",
@@ -141,8 +164,8 @@
141
164
  "license-check": "pnpm dlx license-checker --production --onlyAllow \"MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;Unlicense\"",
142
165
  "license-check:json": "pnpm dlx license-checker --production --onlyAllow \"MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;Unlicense\" --json",
143
166
  "clean": "rimraf dist",
144
- "publish:patch": "pnpm run typecheck && pnpm run --if-present test && pnpm version patch --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
145
- "publish:minor": "pnpm run typecheck && pnpm run --if-present test && pnpm version minor --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
146
- "publish:major": "pnpm run typecheck && pnpm run --if-present test && pnpm version major --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks"
167
+ "publish:patch": "pnpm run typecheck && pnpm run --if-present test && pnpm version patch --no-git-tag-version --no-git-checks && pnpm run build:platforms && pnpm run publish:platforms && pnpm publish --no-git-checks",
168
+ "publish:minor": "pnpm run typecheck && pnpm run --if-present test && pnpm version minor --no-git-tag-version --no-git-checks && pnpm run build:platforms && pnpm run publish:platforms && pnpm publish --no-git-checks",
169
+ "publish:major": "pnpm run typecheck && pnpm run --if-present test && pnpm version major --no-git-tag-version --no-git-checks && pnpm run build:platforms && pnpm run publish:platforms && pnpm publish --no-git-checks"
147
170
  }
148
171
  }
package/dist/markdown-api DELETED
Binary file