md-redline 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/bin/md-redline +255 -0
  4. package/bin/test-windows.ps1 +70 -0
  5. package/dist/assets/_baseFor-Ck08IaSF.js +1 -0
  6. package/dist/assets/arc-DI2g9LXK.js +1 -0
  7. package/dist/assets/architecture-YZFGNWBL-BDgMfc-b.js +1 -0
  8. package/dist/assets/architectureDiagram-Q4EWVU46-Dg1hcUEa.js +36 -0
  9. package/dist/assets/array-DOVTz2Mq.js +1 -0
  10. package/dist/assets/blockDiagram-DXYQGD6D-BAXkTCAk.js +132 -0
  11. package/dist/assets/c4Diagram-AHTNJAMY-BIkgwQSx.js +10 -0
  12. package/dist/assets/channel-DPCihw7y.js +1 -0
  13. package/dist/assets/chunk-2KRD3SAO-Dc_tBGsw.js +1 -0
  14. package/dist/assets/chunk-336JU56O-Dhi-ID9Y.js +2 -0
  15. package/dist/assets/chunk-426QAEUC-DnFdrNMW.js +1 -0
  16. package/dist/assets/chunk-4BX2VUAB-Z63FkGov.js +1 -0
  17. package/dist/assets/chunk-4TB4RGXK-BAiBlfyy.js +206 -0
  18. package/dist/assets/chunk-55IACEB6-BXDWXbxy.js +1 -0
  19. package/dist/assets/chunk-5FUZZQ4R-C72e1c_O.js +62 -0
  20. package/dist/assets/chunk-5PVQY5BW-BBHW_uCu.js +2 -0
  21. package/dist/assets/chunk-67CJDMHE-3Cf_D9m6.js +1 -0
  22. package/dist/assets/chunk-7N4EOEYR-DAXUXJ2c.js +1 -0
  23. package/dist/assets/chunk-AA7GKIK3-Dr7fOryc.js +1 -0
  24. package/dist/assets/chunk-BSJP7CBP-BmsSs1Nt.js +1 -0
  25. package/dist/assets/chunk-CIAEETIT-QDzV-X_Y.js +1 -0
  26. package/dist/assets/chunk-EDXVE4YY-C25WFHxY.js +1 -0
  27. package/dist/assets/chunk-ENJZ2VHE-_OzxcZOU.js +10 -0
  28. package/dist/assets/chunk-FMBD7UC4-CjsTKY4u.js +15 -0
  29. package/dist/assets/chunk-FOC6F5B3-g-xaH5nc.js +1 -0
  30. package/dist/assets/chunk-ICPOFSXX-iKiUSjDK.js +121 -0
  31. package/dist/assets/chunk-K5T4RW27-CKR-lPBN.js +94 -0
  32. package/dist/assets/chunk-KGLVRYIC-DRccT-B_.js +1 -0
  33. package/dist/assets/chunk-LIHQZDEY-DTbMwMXj.js +1 -0
  34. package/dist/assets/chunk-ORNJ4GCN-DlerdcWX.js +1 -0
  35. package/dist/assets/chunk-OYMX7WX6-Dekv1on2.js +231 -0
  36. package/dist/assets/chunk-QZHKN3VN-BHu0RdKl.js +1 -0
  37. package/dist/assets/chunk-U2HBQHQK-BvtlVHAg.js +70 -0
  38. package/dist/assets/chunk-X2U36JSP-BI_g8mub.js +1 -0
  39. package/dist/assets/chunk-XPW4576I-B39JkmSE.js +32 -0
  40. package/dist/assets/chunk-YZCP3GAM-BfPcXRm2.js +1 -0
  41. package/dist/assets/chunk-ZZ45TVLE-Bg4q68wZ.js +1 -0
  42. package/dist/assets/classDiagram-6PBFFD2Q-p73p727_.js +1 -0
  43. package/dist/assets/classDiagram-v2-HSJHXN6E-C4Ftpivp.js +1 -0
  44. package/dist/assets/clone-CI9aUwHe.js +1 -0
  45. package/dist/assets/cose-bilkent-S5V4N54A-7BpAeDh5.js +1 -0
  46. package/dist/assets/cytoscape.esm-DoTFyJaN.js +321 -0
  47. package/dist/assets/dagre-CilMRazv.js +1 -0
  48. package/dist/assets/dagre-KV5264BT-DDMqpjkB.js +4 -0
  49. package/dist/assets/defaultLocale-Ck2Xxk-C.js +1 -0
  50. package/dist/assets/diagram-5BDNPKRD-BFeyfnCx.js +10 -0
  51. package/dist/assets/diagram-G4DWMVQ6-DoqT-PtF.js +24 -0
  52. package/dist/assets/diagram-MMDJMWI5-BPV6KADk.js +43 -0
  53. package/dist/assets/diagram-TYMM5635-okvcTBtl.js +24 -0
  54. package/dist/assets/dist-C_eddq6m.js +1 -0
  55. package/dist/assets/erDiagram-SMLLAGMA-Dl-Ixy8n.js +85 -0
  56. package/dist/assets/flatten-B8XIuT0x.js +1 -0
  57. package/dist/assets/flowDiagram-DWJPFMVM-CsqWAx5r.js +162 -0
  58. package/dist/assets/ganttDiagram-T4ZO3ILL-mIt6zVeF.js +292 -0
  59. package/dist/assets/gitGraph-7Q5UKJZL-COXHGMvj.js +1 -0
  60. package/dist/assets/gitGraphDiagram-UUTBAWPF-syVqZJX_.js +106 -0
  61. package/dist/assets/graphlib-Bpd0q3yO.js +1 -0
  62. package/dist/assets/index-BoggyWS0.css +2 -0
  63. package/dist/assets/index-aLvjHQW4.js +104 -0
  64. package/dist/assets/info-OMHHGYJF-B-0wfxwL.js +1 -0
  65. package/dist/assets/infoDiagram-42DDH7IO-C0_uqsVa.js +2 -0
  66. package/dist/assets/init-Bft5Ffpj.js +1 -0
  67. package/dist/assets/isEmpty-BrFi5AqV.js +1 -0
  68. package/dist/assets/ishikawaDiagram-UXIWVN3A-CTjFbDBV.js +70 -0
  69. package/dist/assets/journeyDiagram-VCZTEJTY-BDBcej1q.js +139 -0
  70. package/dist/assets/kanban-definition-6JOO6SKY-Ylgzakw7.js +89 -0
  71. package/dist/assets/katex-Uj9wLT16.js +265 -0
  72. package/dist/assets/line-CRxEwpOv.js +1 -0
  73. package/dist/assets/linear-PDPfFByd.js +1 -0
  74. package/dist/assets/mermaid-parser.core-CY-XNOOy.js +4 -0
  75. package/dist/assets/mermaid.core-BPlTADIX.js +11 -0
  76. package/dist/assets/mindmap-definition-QFDTVHPH-TefzJnBM.js +96 -0
  77. package/dist/assets/ordinal-DIg8h6NI.js +1 -0
  78. package/dist/assets/packet-4T2RLAQJ-BW1T_A-C.js +1 -0
  79. package/dist/assets/path-DfRbCp9y.js +1 -0
  80. package/dist/assets/pie-ZZUOXDRM-DkKU-SFu.js +1 -0
  81. package/dist/assets/pieDiagram-DEJITSTG-BCXuaeEy.js +30 -0
  82. package/dist/assets/quadrantDiagram-34T5L4WZ-VSBAicWL.js +7 -0
  83. package/dist/assets/radar-PYXPWWZC-CYvTacKJ.js +1 -0
  84. package/dist/assets/reduce-CV2X8n1a.js +1 -0
  85. package/dist/assets/requirementDiagram-MS252O5E-4NeL9Z6J.js +84 -0
  86. package/dist/assets/rough.esm-Bbn_-PMU.js +1 -0
  87. package/dist/assets/sankeyDiagram-XADWPNL6-DMBSDnrH.js +10 -0
  88. package/dist/assets/sequenceDiagram-FGHM5R23-DVpzcZUi.js +157 -0
  89. package/dist/assets/src-PKe5NtkK.js +1 -0
  90. package/dist/assets/stateDiagram-FHFEXIEX-BkHTlCjL.js +1 -0
  91. package/dist/assets/stateDiagram-v2-QKLJ7IA2-nMeWu9fP.js +1 -0
  92. package/dist/assets/timeline-definition-GMOUNBTQ-CyLt92nf.js +120 -0
  93. package/dist/assets/treeView-SZITEDCU-BUgcJ4eR.js +1 -0
  94. package/dist/assets/treemap-W4RFUUIX-BIWGQ4Pw.js +1 -0
  95. package/dist/assets/vennDiagram-DHZGUBPP-BCK0xB_m.js +34 -0
  96. package/dist/assets/wardley-RL74JXVD-DMZZRlby.js +1 -0
  97. package/dist/assets/wardleyDiagram-NUSXRM2D-BisBgfsF.js +20 -0
  98. package/dist/assets/xychartDiagram-5P7HB3ND-D_REDciv.js +7 -0
  99. package/dist/favicon.svg +15 -0
  100. package/dist/index.html +14 -0
  101. package/dist/screenshot.png +0 -0
  102. package/index.html +13 -0
  103. package/package.json +105 -0
  104. package/public/favicon.svg +15 -0
  105. package/public/screenshot.png +0 -0
  106. package/server/index.test.ts +814 -0
  107. package/server/index.ts +736 -0
  108. package/server/preferences.test.ts +126 -0
  109. package/server/preferences.ts +76 -0
  110. package/src/App.tsx +1620 -0
  111. package/src/components/ActionButton.tsx +41 -0
  112. package/src/components/CommandPalette.tsx +191 -0
  113. package/src/components/CommentCard.tsx +556 -0
  114. package/src/components/CommentForm.tsx +285 -0
  115. package/src/components/CommentSidebar.tsx +428 -0
  116. package/src/components/ConfirmDialog.tsx +64 -0
  117. package/src/components/ContextMenu.tsx +220 -0
  118. package/src/components/DragHandles.tsx +48 -0
  119. package/src/components/FileExplorer.tsx +251 -0
  120. package/src/components/FileOpener.tsx +304 -0
  121. package/src/components/IconButton.tsx +32 -0
  122. package/src/components/KeyboardShortcutsPanel.tsx +136 -0
  123. package/src/components/MarkdownViewer.tsx +682 -0
  124. package/src/components/RawView.tsx +798 -0
  125. package/src/components/SearchBar.tsx +129 -0
  126. package/src/components/Separator.tsx +7 -0
  127. package/src/components/SettingsPanel.tsx +813 -0
  128. package/src/components/SplitIconButton.tsx +133 -0
  129. package/src/components/TabBar.tsx +594 -0
  130. package/src/components/TableOfContents.tsx +70 -0
  131. package/src/components/ThemeSelector.tsx +159 -0
  132. package/src/components/Toast.tsx +99 -0
  133. package/src/components/Toolbar.tsx +161 -0
  134. package/src/components/iconButtonVariants.ts +19 -0
  135. package/src/components/rawView.test.ts +291 -0
  136. package/src/contexts/SettingsContext.tsx +120 -0
  137. package/src/hooks/useAuthor.test.ts +58 -0
  138. package/src/hooks/useAuthor.ts +69 -0
  139. package/src/hooks/useAutoResize.ts +20 -0
  140. package/src/hooks/useCommentCardTriggers.ts +20 -0
  141. package/src/hooks/useComments.test.ts +773 -0
  142. package/src/hooks/useComments.ts +332 -0
  143. package/src/hooks/useContextMenu.ts +48 -0
  144. package/src/hooks/useContextMenuItems.ts +392 -0
  145. package/src/hooks/useDiffSnapshot.test.ts +130 -0
  146. package/src/hooks/useDiffSnapshot.ts +67 -0
  147. package/src/hooks/useDragHandles.ts +417 -0
  148. package/src/hooks/useFileWatcher.ts +45 -0
  149. package/src/hooks/useHeadingTracking.ts +84 -0
  150. package/src/hooks/useMermaidRenderer.ts +75 -0
  151. package/src/hooks/useModalState.ts +22 -0
  152. package/src/hooks/usePageVisible.test.ts +69 -0
  153. package/src/hooks/usePageVisible.ts +19 -0
  154. package/src/hooks/usePaneLayout.test.ts +108 -0
  155. package/src/hooks/usePaneLayout.ts +102 -0
  156. package/src/hooks/useRecentFiles.test.ts +103 -0
  157. package/src/hooks/useRecentFiles.ts +99 -0
  158. package/src/hooks/useResizablePanel.test.ts +84 -0
  159. package/src/hooks/useResizablePanel.ts +118 -0
  160. package/src/hooks/useSearch.test.ts +72 -0
  161. package/src/hooks/useSearch.ts +53 -0
  162. package/src/hooks/useSelection.ts +48 -0
  163. package/src/hooks/useSessionPersistence.test.ts +59 -0
  164. package/src/hooks/useSessionPersistence.ts +43 -0
  165. package/src/hooks/useTabs.test.ts +127 -0
  166. package/src/hooks/useTabs.ts +561 -0
  167. package/src/hooks/useThemePersistence.ts +41 -0
  168. package/src/hooks/useToast.ts +27 -0
  169. package/src/index.css +1047 -0
  170. package/src/lib/agent-prompts.test.ts +34 -0
  171. package/src/lib/agent-prompts.ts +68 -0
  172. package/src/lib/comment-editor-state.ts +6 -0
  173. package/src/lib/comment-parser.test.ts +1959 -0
  174. package/src/lib/comment-parser.ts +1021 -0
  175. package/src/lib/diff.test.ts +164 -0
  176. package/src/lib/diff.ts +139 -0
  177. package/src/lib/heading-slugs.test.ts +85 -0
  178. package/src/lib/heading-slugs.ts +44 -0
  179. package/src/lib/http.test.ts +43 -0
  180. package/src/lib/http.ts +29 -0
  181. package/src/lib/mermaid-highlights.test.ts +517 -0
  182. package/src/lib/mermaid-highlights.ts +936 -0
  183. package/src/lib/mermaid-renderer.test.ts +114 -0
  184. package/src/lib/mermaid-renderer.ts +89 -0
  185. package/src/lib/path-utils.test.ts +17 -0
  186. package/src/lib/path-utils.ts +7 -0
  187. package/src/lib/platform.test.ts +58 -0
  188. package/src/lib/platform.ts +14 -0
  189. package/src/lib/preferences-client.test.ts +177 -0
  190. package/src/lib/preferences-client.ts +94 -0
  191. package/src/lib/selection-resolver.test.ts +118 -0
  192. package/src/lib/selection-resolver.ts +37 -0
  193. package/src/lib/settings.test.ts +152 -0
  194. package/src/lib/settings.ts +78 -0
  195. package/src/lib/shortcut-label.tsx +18 -0
  196. package/src/lib/themes.ts +21 -0
  197. package/src/lib/visible-text.test.ts +86 -0
  198. package/src/lib/visible-text.ts +77 -0
  199. package/src/main.tsx +22 -0
  200. package/src/markdown/pipeline.test.ts +82 -0
  201. package/src/markdown/pipeline.ts +33 -0
  202. package/src/types.test.ts +43 -0
  203. package/src/types.ts +46 -0
  204. package/tsconfig.app.json +28 -0
  205. package/tsconfig.json +7 -0
  206. package/tsconfig.node.json +26 -0
  207. package/vite.config.ts +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dennis Ju
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # <img src="public/favicon.svg" width="30" align="center" /> md-redline
2
+
3
+ Review rendered markdown with inline comments that live in the file.
4
+
5
+ `mdr` is a local review tool for markdown files in human + AI agent workflows. Highlight text in the rendered document, leave feedback, then hand the same file to an agent. Comments are stored inline in the `.md` file itself, so agents can read and address them directly. No sidecar files, no database, no external service. The markdown file stays the source of truth.
6
+
7
+ Markdown has become a common working format for specs, prompts, and design docs between humans and agents. `mdr` gives that workflow review tooling closer to code review: rendered context, inline comments, and a clean diff after changes are made. As Sean Grove argues in [specs are the new code](https://www.youtube.com/watch?v=8rABwKRsec4), specs are becoming the primary unit of work in agentic development. You write and review the spec, agents write the code.
8
+
9
+ ![md-redline screenshot](public/screenshot.png)
10
+
11
+ **See the full review workflow in 30 seconds:**
12
+
13
+ https://github.com/user-attachments/assets/855a9d02-b0fd-4dec-b0a5-742871e8c181
14
+
15
+ ## Review workflow
16
+
17
+ ### Default: comments as agent instructions
18
+
19
+ 1. Open a markdown file in `mdr`.
20
+ 2. Highlight text and leave inline comments.
21
+ 3. Copy the hand-off prompt.
22
+ 4. Paste the prompt into your AI agent.
23
+ 5. The agent edits the file, addresses the feedback, and removes the comment markers it handled.
24
+ 6. Review the result in diff view.
25
+
26
+ ### Optional: resolve workflow
27
+
28
+ Enable resolve mode in Settings for human review with explicit `open` and `resolved` states.
29
+
30
+ ## Quick start
31
+
32
+ Prerequisite: Node 20 or newer.
33
+
34
+ ```bash
35
+ npx md-redline /path/to/spec.md
36
+ ```
37
+
38
+ This starts the local app if needed and opens it in your browser.
39
+
40
+ Or install globally:
41
+
42
+ ```bash
43
+ npm install -g md-redline
44
+ mdr /path/to/spec.md # Open a file
45
+ mdr /path/to/dir # Open a directory
46
+ mdr --stop # Stop the running server
47
+ ```
48
+
49
+ `md-redline` also works as an alias for `mdr`.
50
+
51
+ ## How comments are stored
52
+
53
+ Comments are stored as invisible HTML markers directly in the markdown, immediately before the text they refer to, so both humans and agents can work from the same file.
54
+
55
+ ```markdown
56
+ Some text <!-- @comment{
57
+ "id":"uuid",
58
+ "anchor":"highlighted text",
59
+ "text":"Rewrite this section to be clearer.",
60
+ "author":"User",
61
+ "timestamp":"2026-03-26T12:00:00.000Z",
62
+ "replies":[]
63
+ } -->highlighted text continues here.
64
+ ```
65
+
66
+ This makes feedback:
67
+
68
+ - visible to AI agents via a plain file read
69
+ - portable with the markdown file
70
+ - invisible in normal renderers (GitHub, VS Code preview)
71
+
72
+ ## Who this is for
73
+
74
+ - **People writing specs, prompts, or design docs locally** with file-based AI agents
75
+ - **Teams reviewing docs before they are committed** or sent out for wider review
76
+ - **Anyone in a human + agent editing loop** who wants structured inline feedback in plain files
77
+
78
+ ### Non-goals
79
+
80
+ - Not a collaborative multi-user editing tool.
81
+ - Not a replacement for GitHub PR reviews (use those once the file is in git).
82
+ - Not designed for untrusted content. This is a local dev tool for your own files.
83
+
84
+ ## Features
85
+
86
+ ### Review and commenting
87
+
88
+ - Inline comments anchored to rendered text, including overlapping comments
89
+ - Threaded replies and optional `open` / `resolved` review states
90
+ - Adjustable anchors with drag handles
91
+ - Rendered, raw, and diff views
92
+ - Hand-off prompt copying for one or multiple files
93
+
94
+ ### Navigation and editing
95
+
96
+ - Multi-tab editing with session persistence and tab context menus
97
+ - File explorer, recent files, and native OS file picker
98
+ - Find in document (`Cmd+F`) with match navigation
99
+ - Table of contents with scroll spy
100
+ - Command palette (`Cmd+K`), keyboard shortcuts, and settings panel (`Cmd+,`)
101
+ - Resizable panels and right-click context menus
102
+
103
+ ### Rendering and integrations
104
+
105
+ - Real-time reload via SSE when files change externally
106
+ - Mermaid diagram rendering with commentable text
107
+ - Customizable comment templates
108
+ - 8 themes: Light, Dark, Sepia, Nord, Solarized, GitHub, Rosé Pine, Catppuccin
109
+
110
+ ## Supported platforms
111
+
112
+ - **macOS**: supported
113
+ - **Linux**: supported; system file picker requires `zenity`
114
+ - **Windows**: supported; system file picker uses PowerShell
115
+
116
+ ## Security model
117
+
118
+ `mdr` is a local dev tool. The server reads and writes markdown files inside the current working directory and any path explicitly opened at startup or through the system file picker. File saves use atomic write-then-rename and mtime-based conflict detection to prevent data loss from concurrent edits.
119
+
120
+ Only run it in environments you trust. Mermaid SVG output is sanitized via DOMPurify before rendering.
121
+
122
+ ## Development
123
+
124
+ ### From source
125
+
126
+ ```bash
127
+ git clone https://github.com/dejuknow/md-redline.git
128
+ cd md-redline
129
+ npm install
130
+ npm run dev
131
+ ```
132
+
133
+ Open the local URL printed by Vite (usually `http://localhost:5188`).
134
+
135
+ ### Scripts
136
+
137
+ ```bash
138
+ npm run dev # Start dev server
139
+ npm run lint # Lint
140
+ npm test # Production build + unit tests
141
+ npm run test:e2e # Playwright E2E tests
142
+ npm run build # Production build
143
+ ```
144
+
145
+ ### Agent eval
146
+
147
+ The eval harness tests whether AI agents correctly read, address, and remove inline comments.
148
+
149
+ - `npm run eval:dry` validates eval fixtures
150
+ - `npm run eval` runs the full eval harness
151
+ - See [eval/README.md](./eval/README.md) for details
152
+
153
+ ## Architecture
154
+
155
+ ```text
156
+ bin/md-redline CLI entry point (invoked as `mdr` or `md-redline`)
157
+ server/index.ts Hono server for file I/O, browsing, SSE, and local integrations
158
+ src/App.tsx Main application shell
159
+ src/components/ Viewer, sidebar, raw view, diff view, TOC, explorer, settings, etc.
160
+ src/hooks/ State, persistence, selection, file watching, drag handles, tabs
161
+ src/lib/comment-parser.ts Inline comment parsing and mutation helpers
162
+ src/markdown/pipeline.ts Markdown rendering pipeline
163
+ eval/ Eval harness for agent behavior against inline comments
164
+ e2e/ Playwright end-to-end coverage
165
+ ```
166
+
167
+ ## License
168
+
169
+ [MIT](./LICENSE)
package/bin/md-redline ADDED
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync, spawn } from 'child_process';
4
+ import { readFile, stat, unlink } from 'fs/promises';
5
+ import { homedir, tmpdir } from 'os';
6
+ import { dirname, join, resolve } from 'path';
7
+ import process from 'process';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ const APP_DIR = resolve(__dirname, '..');
14
+ const DEFAULT_SERVER_PORT = 3001;
15
+ const DEFAULT_CLIENT_PORT = 5188;
16
+ const MAX_PORT_SCAN = 10;
17
+ const PORT_FILE = join(tmpdir(), 'md-redline.port');
18
+ const START_TIMEOUT_MS = 15_000;
19
+ const POLL_INTERVAL_MS = 500;
20
+
21
+ function printHelp() {
22
+ console.log('Usage: mdr [file.md | directory]');
23
+ console.log(' mdr --stop');
24
+ console.log('');
25
+ console.log('Opens a markdown file or folder in mdr for inline commenting.');
26
+ console.log('Starts the app automatically if it is not already running.');
27
+ console.log('Supported platforms: macOS, Linux, and Windows.');
28
+ console.log('');
29
+ console.log('Options:');
30
+ console.log(' --stop Stop the running mdr server');
31
+ console.log(' -h, --help Show this help message');
32
+ console.log('');
33
+ console.log('Alias: md-redline');
34
+ }
35
+
36
+ function expandHomePath(inputPath) {
37
+ if (inputPath === '~') return homedir();
38
+ if (inputPath.startsWith('~/') || inputPath.startsWith('~\\')) {
39
+ return resolve(homedir(), inputPath.slice(2));
40
+ }
41
+ return inputPath;
42
+ }
43
+
44
+ async function resolveTarget(arg) {
45
+ if (!arg) return { file: '', dir: '' };
46
+
47
+ const target = resolve(expandHomePath(arg));
48
+ let targetStat;
49
+ try {
50
+ targetStat = await stat(target);
51
+ } catch {
52
+ throw new Error(`not found: ${arg}`);
53
+ }
54
+
55
+ if (targetStat.isDirectory()) return { file: '', dir: target };
56
+ if (targetStat.isFile()) return { file: target, dir: '' };
57
+ throw new Error(`not a file or directory: ${arg}`);
58
+ }
59
+
60
+ async function checkServer(port) {
61
+ try {
62
+ const response = await fetch(`http://localhost:${port}/api/config`, {
63
+ signal: AbortSignal.timeout(1_000),
64
+ });
65
+ return response.ok;
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+
71
+ async function findServerPort() {
72
+ // Try the port file first (fast path)
73
+ try {
74
+ const saved = (await readFile(PORT_FILE, 'utf8')).trim();
75
+ const port = Number(saved);
76
+ if (port && await checkServer(port)) return port;
77
+ } catch {}
78
+
79
+ // Scan the port range as fallback
80
+ for (let p = DEFAULT_SERVER_PORT; p < DEFAULT_SERVER_PORT + MAX_PORT_SCAN; p++) {
81
+ if (await checkServer(p)) return p;
82
+ }
83
+ return null;
84
+ }
85
+
86
+ async function findClientPort() {
87
+ for (let p = DEFAULT_CLIENT_PORT; p < DEFAULT_CLIENT_PORT + MAX_PORT_SCAN; p++) {
88
+ try {
89
+ const response = await fetch(`http://localhost:${p}/__mdr__`, {
90
+ signal: AbortSignal.timeout(1_000),
91
+ });
92
+ if (response.ok && (await response.text()) === 'mdr') return p;
93
+ } catch {}
94
+ }
95
+ return null;
96
+ }
97
+
98
+ function delay(ms) {
99
+ return new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
100
+ }
101
+
102
+ function spawnDetached(command, args) {
103
+ return new Promise((resolveSpawn, rejectSpawn) => {
104
+ const isWin = process.platform === 'win32';
105
+ const child = isWin
106
+ ? spawn([command, ...args].join(' '), {
107
+ cwd: APP_DIR,
108
+ stdio: 'ignore',
109
+ shell: true,
110
+ windowsHide: true,
111
+ })
112
+ : spawn(command, args, {
113
+ cwd: APP_DIR,
114
+ detached: true,
115
+ stdio: 'ignore',
116
+ windowsHide: true,
117
+ });
118
+
119
+ child.once('error', rejectSpawn);
120
+ child.once('spawn', () => {
121
+ child.unref();
122
+ resolveSpawn(child);
123
+ });
124
+ });
125
+ }
126
+
127
+ function killPort(port) {
128
+ try {
129
+ if (process.platform === 'win32') {
130
+ const output = execSync(`netstat -ano | findstr :${port} | findstr LISTENING`, { encoding: 'utf8' });
131
+ const pids = new Set(output.trim().split('\n').map(line => line.trim().split(/\s+/).pop()));
132
+ for (const pid of pids) {
133
+ if (pid && pid !== '0') {
134
+ try { execSync(`taskkill /PID ${pid} /F`, { stdio: 'ignore' }); } catch { /* process may have already exited */ }
135
+ }
136
+ }
137
+ } else {
138
+ execSync(`lsof -ti:${port} | xargs kill 2>/dev/null`, { stdio: 'ignore' });
139
+ }
140
+ return true;
141
+ } catch {
142
+ return false;
143
+ }
144
+ }
145
+
146
+ async function stopServer() {
147
+ const serverPort = await findServerPort();
148
+ if (!serverPort) {
149
+ console.log('mdr is not running.');
150
+ return;
151
+ }
152
+
153
+ console.log('Stopping mdr...');
154
+ killPort(serverPort);
155
+
156
+ // Also kill the Vite client if running (only kill ports that respond)
157
+ const clientPort = await findClientPort();
158
+ if (clientPort) {
159
+ killPort(clientPort);
160
+ }
161
+
162
+ // Clean up port file
163
+ try { await unlink(PORT_FILE); } catch {}
164
+
165
+ console.log('mdr stopped.');
166
+ }
167
+
168
+ async function ensureServerRunning() {
169
+ const existing = await findServerPort();
170
+ if (existing) return;
171
+
172
+ console.log('Starting mdr...');
173
+ const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
174
+ let childExited = false;
175
+ const child = await spawnDetached(npmCommand, ['run', 'dev']);
176
+ child.once('exit', () => {
177
+ childExited = true;
178
+ });
179
+
180
+ const deadline = Date.now() + START_TIMEOUT_MS;
181
+ // Wait for the API server
182
+ while (Date.now() < deadline) {
183
+ if (await findServerPort()) break;
184
+ if (childExited) {
185
+ throw new Error("app failed to start. Run 'npm run dev' manually for details.");
186
+ }
187
+ await delay(POLL_INTERVAL_MS);
188
+ }
189
+ if (!(await findServerPort())) {
190
+ throw new Error('server did not start within 15 seconds.');
191
+ }
192
+ // Also wait for Vite client to be ready
193
+ while (Date.now() < deadline) {
194
+ if (await findClientPort()) {
195
+ console.log('mdr is running.');
196
+ return;
197
+ }
198
+ await delay(POLL_INTERVAL_MS);
199
+ }
200
+ // Server is up but client may still be starting — proceed anyway
201
+ console.log('mdr server is running (client may still be starting).');
202
+ }
203
+
204
+ async function buildUrl(file, dir) {
205
+ const clientPort = await findClientPort() ?? DEFAULT_CLIENT_PORT;
206
+ const baseUrl = `http://localhost:${clientPort}`;
207
+ if (file) return `${baseUrl}?file=${encodeURIComponent(file)}`;
208
+ if (dir) return `${baseUrl}?dir=${encodeURIComponent(dir)}`;
209
+ return baseUrl;
210
+ }
211
+
212
+ async function openInBrowser(url) {
213
+ if (process.platform === 'darwin') {
214
+ await spawnDetached('open', [url]);
215
+ return;
216
+ }
217
+ if (process.platform === 'win32') {
218
+ await spawnDetached('cmd', ['/c', 'start', '', url]);
219
+ return;
220
+ }
221
+ if (process.platform === 'linux') {
222
+ await spawnDetached('xdg-open', [url]);
223
+ return;
224
+ }
225
+ console.log(`Open in your browser: ${url}`);
226
+ }
227
+
228
+ async function main() {
229
+ if (process.argv[2] === '-h' || process.argv[2] === '--help') {
230
+ printHelp();
231
+ return;
232
+ }
233
+
234
+ if (process.argv[2] === '--stop') {
235
+ await stopServer();
236
+ return;
237
+ }
238
+
239
+ try {
240
+ const { file, dir } = await resolveTarget(process.argv[2] ?? '');
241
+ await ensureServerRunning();
242
+ const url = await buildUrl(file, dir);
243
+
244
+ try {
245
+ await openInBrowser(url);
246
+ } catch {
247
+ console.log(`Open in your browser: ${url}`);
248
+ }
249
+ } catch (error) {
250
+ console.error(`Error: ${error instanceof Error ? error.message : 'unknown error'}`);
251
+ process.exitCode = 1;
252
+ }
253
+ }
254
+
255
+ await main();
@@ -0,0 +1,70 @@
1
+ param(
2
+ [switch]$Headed,
3
+ [switch]$UI,
4
+ [switch]$InstallOnly,
5
+ [string]$ProjectRoot = $PSScriptRoot + "\.."
6
+ )
7
+
8
+ # Move to project root
9
+ Push-Location $ProjectRoot
10
+
11
+ Write-Host "`n--- md-redline Windows Test Runner ---" -ForegroundColor Cyan
12
+
13
+ # 1. Check for Node.js
14
+ if (!(Get-Command node -ErrorAction SilentlyContinue)) {
15
+ Write-Host "Error: Node.js is not installed. Please install it from https://nodejs.org/" -ForegroundColor Red
16
+ Pop-Location
17
+ exit 1
18
+ }
19
+
20
+ # 2. Install dependencies if node_modules is missing
21
+ if (!(Test-Path "node_modules")) {
22
+ Write-Host "node_modules not found. Installing dependencies..." -ForegroundColor Yellow
23
+ npm install
24
+ if ($LASTEXITCODE -ne 0) {
25
+ Write-Host "npm install failed." -ForegroundColor Red
26
+ Pop-Location
27
+ exit $LASTEXITCODE
28
+ }
29
+ }
30
+
31
+ # 3. Ensure Playwright browsers are installed
32
+ Write-Host "Checking Playwright browsers..." -ForegroundColor Yellow
33
+ npx playwright install chromium --with-deps
34
+ if ($LASTEXITCODE -ne 0) {
35
+ Write-Host "Playwright installation failed." -ForegroundColor Red
36
+ Pop-Location
37
+ exit $LASTEXITCODE
38
+ }
39
+
40
+ if ($InstallOnly) {
41
+ Write-Host "Setup complete! Browsers and dependencies are ready." -ForegroundColor Green
42
+ Pop-Location
43
+ exit 0
44
+ }
45
+
46
+ # 4. Determine command arguments
47
+ $playwrightArgs = @("test")
48
+ if ($Headed) {
49
+ $playwrightArgs += "--headed"
50
+ Write-Host "Running in HEADED mode..." -ForegroundColor Cyan
51
+ }
52
+ if ($UI) {
53
+ $playwrightArgs += "--ui"
54
+ Write-Host "Opening Playwright UI..." -ForegroundColor Cyan
55
+ }
56
+
57
+ # 5. Run the tests
58
+ Write-Host "Starting tests...`n" -ForegroundColor Green
59
+ npx playwright $playwrightArgs
60
+
61
+ $exitCode = $LASTEXITCODE
62
+ Pop-Location
63
+
64
+ if ($exitCode -eq 0) {
65
+ Write-Host "`nTests passed successfully!" -ForegroundColor Green
66
+ } else {
67
+ Write-Host "`nTests failed with exit code $exitCode" -ForegroundColor Red
68
+ }
69
+
70
+ exit $exitCode
@@ -0,0 +1 @@
1
+ function e(){this.__data__=[],this.size=0}function t(e,t){return e===t||e!==e&&t!==t}function n(e,n){for(var r=e.length;r--;)if(t(e[r][0],n))return r;return-1}var r=Array.prototype.splice;function i(e){var t=this.__data__,i=n(t,e);return i<0?!1:(i==t.length-1?t.pop():r.call(t,i,1),--this.size,!0)}function a(e){var t=this.__data__,r=n(t,e);return r<0?void 0:t[r][1]}function o(e){return n(this.__data__,e)>-1}function s(e,t){var r=this.__data__,i=n(r,e);return i<0?(++this.size,r.push([e,t])):r[i][1]=t,this}function c(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}c.prototype.clear=e,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=o,c.prototype.set=s;function l(){this.__data__=new c,this.size=0}function ee(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}function te(e){return this.__data__.get(e)}function ne(e){return this.__data__.has(e)}var u=typeof global==`object`&&global&&global.Object===Object&&global,re=typeof self==`object`&&self&&self.Object===Object&&self,d=u||re||Function(`return this`)(),f=d.Symbol,p=Object.prototype,ie=p.hasOwnProperty,ae=p.toString,m=f?f.toStringTag:void 0;function oe(e){var t=ie.call(e,m),n=e[m];try{e[m]=void 0;var r=!0}catch{}var i=ae.call(e);return r&&(t?e[m]=n:delete e[m]),i}var se=Object.prototype.toString;function ce(e){return se.call(e)}var le=`[object Null]`,ue=`[object Undefined]`,h=f?f.toStringTag:void 0;function g(e){return e==null?e===void 0?ue:le:h&&h in Object(e)?oe(e):ce(e)}function _(e){var t=typeof e;return e!=null&&(t==`object`||t==`function`)}var de=`[object AsyncFunction]`,fe=`[object Function]`,pe=`[object GeneratorFunction]`,me=`[object Proxy]`;function v(e){if(!_(e))return!1;var t=g(e);return t==fe||t==pe||t==de||t==me}var y=d[`__core-js_shared__`],b=function(){var e=/[^.]+$/.exec(y&&y.keys&&y.keys.IE_PROTO||``);return e?`Symbol(src)_1.`+e:``}();function he(e){return!!b&&b in e}var ge=Function.prototype.toString;function x(e){if(e!=null){try{return ge.call(e)}catch{}try{return e+``}catch{}}return``}var _e=/[\\^$.*+?()[\]{}|]/g,ve=/^\[object .+?Constructor\]$/,ye=Function.prototype,be=Object.prototype,xe=ye.toString,Se=be.hasOwnProperty,Ce=RegExp(`^`+xe.call(Se).replace(_e,`\\$&`).replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,`$1.*?`)+`$`);function we(e){return!_(e)||he(e)?!1:(v(e)?Ce:ve).test(x(e))}function Te(e,t){return e?.[t]}function S(e,t){var n=Te(e,t);return we(n)?n:void 0}var C=S(d,`Map`),w=S(Object,`create`);function T(){this.__data__=w?w(null):{},this.size=0}function E(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}var D=`__lodash_hash_undefined__`,O=Object.prototype.hasOwnProperty;function Ee(e){var t=this.__data__;if(w){var n=t[e];return n===D?void 0:n}return O.call(t,e)?t[e]:void 0}var De=Object.prototype.hasOwnProperty;function Oe(e){var t=this.__data__;return w?t[e]!==void 0:De.call(t,e)}var ke=`__lodash_hash_undefined__`;function Ae(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=w&&t===void 0?ke:t,this}function k(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}k.prototype.clear=T,k.prototype.delete=E,k.prototype.get=Ee,k.prototype.has=Oe,k.prototype.set=Ae;function je(){this.size=0,this.__data__={hash:new k,map:new(C||c),string:new k}}function Me(e){var t=typeof e;return t==`string`||t==`number`||t==`symbol`||t==`boolean`?e!==`__proto__`:e===null}function A(e,t){var n=e.__data__;return Me(t)?n[typeof t==`string`?`string`:`hash`]:n.map}function Ne(e){var t=A(this,e).delete(e);return this.size-=t?1:0,t}function Pe(e){return A(this,e).get(e)}function Fe(e){return A(this,e).has(e)}function Ie(e,t){var n=A(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}function j(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}j.prototype.clear=je,j.prototype.delete=Ne,j.prototype.get=Pe,j.prototype.has=Fe,j.prototype.set=Ie;var Le=200;function Re(e,t){var n=this.__data__;if(n instanceof c){var r=n.__data__;if(!C||r.length<Le-1)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new j(r)}return n.set(e,t),this.size=n.size,this}function M(e){this.size=(this.__data__=new c(e)).size}M.prototype.clear=l,M.prototype.delete=ee,M.prototype.get=te,M.prototype.has=ne,M.prototype.set=Re;var ze=d.Uint8Array,N=Array.isArray;function Be(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}function P(e){return typeof e==`object`&&!!e}var Ve=`[object Arguments]`;function F(e){return P(e)&&g(e)==Ve}var I=Object.prototype,He=I.hasOwnProperty,Ue=I.propertyIsEnumerable,L=F(function(){return arguments}())?F:function(e){return P(e)&&He.call(e,`callee`)&&!Ue.call(e,`callee`)};function We(){return!1}var R=typeof exports==`object`&&exports&&!exports.nodeType&&exports,z=R&&typeof module==`object`&&module&&!module.nodeType&&module,B=z&&z.exports===R?d.Buffer:void 0,V=(B?B.isBuffer:void 0)||We,Ge=9007199254740991,Ke=/^(?:0|[1-9]\d*)$/;function H(e,t){var n=typeof e;return t??=Ge,!!t&&(n==`number`||n!=`symbol`&&Ke.test(e))&&e>-1&&e%1==0&&e<t}var qe=9007199254740991;function U(e){return typeof e==`number`&&e>-1&&e%1==0&&e<=qe}var Je=`[object Arguments]`,Ye=`[object Array]`,Xe=`[object Boolean]`,Ze=`[object Date]`,Qe=`[object Error]`,$e=`[object Function]`,et=`[object Map]`,tt=`[object Number]`,nt=`[object Object]`,rt=`[object RegExp]`,it=`[object Set]`,at=`[object String]`,ot=`[object WeakMap]`,st=`[object ArrayBuffer]`,ct=`[object DataView]`,lt=`[object Float32Array]`,ut=`[object Float64Array]`,dt=`[object Int8Array]`,ft=`[object Int16Array]`,pt=`[object Int32Array]`,mt=`[object Uint8Array]`,ht=`[object Uint8ClampedArray]`,gt=`[object Uint16Array]`,_t=`[object Uint32Array]`,W={};W[lt]=W[ut]=W[dt]=W[ft]=W[pt]=W[mt]=W[ht]=W[gt]=W[_t]=!0,W[Je]=W[Ye]=W[st]=W[Xe]=W[ct]=W[Ze]=W[Qe]=W[$e]=W[et]=W[tt]=W[nt]=W[rt]=W[it]=W[at]=W[ot]=!1;function vt(e){return P(e)&&U(e.length)&&!!W[g(e)]}function G(e){return function(t){return e(t)}}var K=typeof exports==`object`&&exports&&!exports.nodeType&&exports,q=K&&typeof module==`object`&&module&&!module.nodeType&&module,J=q&&q.exports===K&&u.process,Y=function(){try{return q&&q.require&&q.require(`util`).types||J&&J.binding&&J.binding(`util`)}catch{}}(),X=Y&&Y.isTypedArray,Z=X?G(X):vt,yt=Object.prototype.hasOwnProperty;function bt(e,t){var n=N(e),r=!n&&L(e),i=!n&&!r&&V(e),a=!n&&!r&&!i&&Z(e),o=n||r||i||a,s=o?Be(e.length,String):[],c=s.length;for(var l in e)(t||yt.call(e,l))&&!(o&&(l==`length`||i&&(l==`offset`||l==`parent`)||a&&(l==`buffer`||l==`byteLength`||l==`byteOffset`)||H(l,c)))&&s.push(l);return s}var xt=Object.prototype;function St(e){var t=e&&e.constructor;return e===(typeof t==`function`&&t.prototype||xt)}function Ct(e,t){return function(n){return e(t(n))}}function wt(e){return e!=null&&U(e.length)&&!v(e)}var Tt=`Expected a function`;function Q(e,t){if(typeof e!=`function`||t!=null&&typeof t!=`function`)throw TypeError(Tt);var n=function(){var r=arguments,i=t?t.apply(this,r):r[0],a=n.cache;if(a.has(i))return a.get(i);var o=e.apply(this,r);return n.cache=a.set(i,o)||a,o};return n.cache=new(Q.Cache||j),n}Q.Cache=j;function $(e){return e}function Et(e){return function(t,n,r){for(var i=-1,a=Object(t),o=r(t),s=o.length;s--;){var c=o[e?s:++i];if(n(a[c],c,a)===!1)break}return t}}var Dt=Et();export{v as C,d as D,f as E,t as O,x as S,g as T,ze as _,Ct as a,C as b,Z as c,U as d,H as f,N as g,P as h,wt as i,Y as l,L as m,$ as n,St as o,V as p,Q as r,bt as s,Dt as t,G as u,M as v,_ as w,S as x,j as y};
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./path-DfRbCp9y.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-C_eddq6m.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-K5T4RW27-CKR-lPBN.js";import{n as e}from"./chunk-7N4EOEYR-DAXUXJ2c.js";export{e as createArchitectureServices};