@portel/photon 1.14.0 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-ui/beam/photon-management.d.ts +1 -1
- package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
- package/dist/auto-ui/beam/photon-management.js +5 -1
- package/dist/auto-ui/beam/photon-management.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.js +31 -9
- package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.js +3 -0
- package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +205 -56
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/bridge/index.d.ts.map +1 -1
- package/dist/auto-ui/bridge/index.js +578 -0
- package/dist/auto-ui/bridge/index.js.map +1 -1
- package/dist/auto-ui/bridge/renderers.d.ts.map +1 -1
- package/dist/auto-ui/bridge/renderers.js +7 -3
- package/dist/auto-ui/bridge/renderers.js.map +1 -1
- package/dist/auto-ui/bridge/types.d.ts +6 -0
- package/dist/auto-ui/bridge/types.d.ts.map +1 -1
- package/dist/auto-ui/frontend/pure-view.html +289 -0
- package/dist/auto-ui/photon-bridge.d.ts +11 -0
- package/dist/auto-ui/photon-bridge.d.ts.map +1 -1
- package/dist/auto-ui/photon-bridge.js +75 -1
- package/dist/auto-ui/photon-bridge.js.map +1 -1
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +29 -3
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/beam-form.bundle.js +5707 -0
- package/dist/beam-form.bundle.js.map +7 -0
- package/dist/beam.bundle.js +2863 -895
- package/dist/beam.bundle.js.map +4 -4
- package/dist/claude-code-plugin.js +11 -3
- package/dist/claude-code-plugin.js.map +1 -1
- package/dist/cli/commands/build.js +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +7 -5
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +18 -4
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/mcp.js +2 -2
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +6 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli-alias.d.ts.map +1 -1
- package/dist/cli-alias.js +3 -2
- package/dist/cli-alias.js.map +1 -1
- package/dist/daemon/client.d.ts +5 -0
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +50 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/manager.d.ts +15 -0
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +142 -11
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/worker-manager.js +1 -1
- package/dist/daemon/worker-manager.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts.map +1 -1
- package/dist/deploy/cloudflare.js +12 -10
- package/dist/deploy/cloudflare.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +37 -2
- package/dist/loader.js.map +1 -1
- package/dist/marketplace-manager.d.ts +9 -0
- package/dist/marketplace-manager.d.ts.map +1 -1
- package/dist/marketplace-manager.js +115 -42
- package/dist/marketplace-manager.js.map +1 -1
- package/dist/meta.d.ts +51 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +320 -0
- package/dist/meta.js.map +1 -0
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +30 -5
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +1 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +33 -21
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/builder-compass.photon.d.ts +167 -0
- package/dist/photons/builder-compass.photon.d.ts.map +1 -0
- package/dist/photons/builder-compass.photon.js +816 -0
- package/dist/photons/builder-compass.photon.js.map +1 -0
- package/dist/photons/builder-compass.photon.ts +1129 -0
- package/dist/photons/docs/ui/docs.html +441 -0
- package/dist/photons/docs.photon.d.ts +237 -0
- package/dist/photons/docs.photon.d.ts.map +1 -0
- package/dist/photons/docs.photon.js +483 -0
- package/dist/photons/docs.photon.js.map +1 -0
- package/dist/photons/docs.photon.ts +536 -0
- package/dist/photons/maker.photon.d.ts.map +1 -1
- package/dist/photons/maker.photon.js +19 -2
- package/dist/photons/maker.photon.js.map +1 -1
- package/dist/photons/maker.photon.ts +18 -2
- package/dist/photons/slides.photon.d.ts +212 -0
- package/dist/photons/slides.photon.d.ts.map +1 -0
- package/dist/photons/slides.photon.js +355 -0
- package/dist/photons/slides.photon.js.map +1 -0
- package/dist/photons/slides.photon.ts +370 -0
- package/dist/photons/spreadsheet/ui/spreadsheet.html +779 -0
- package/dist/photons/spreadsheet.photon.d.ts +554 -0
- package/dist/photons/spreadsheet.photon.d.ts.map +1 -0
- package/dist/photons/spreadsheet.photon.js +1050 -0
- package/dist/photons/spreadsheet.photon.js.map +1 -0
- package/dist/photons/spreadsheet.photon.ts +1239 -0
- package/dist/photons/ui/builder-compass.html +1199 -0
- package/dist/photons/ui/builder-compass.photon.html +380 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +33 -59
- package/dist/server.js.map +1 -1
- package/dist/shared/error-handler.d.ts +8 -0
- package/dist/shared/error-handler.d.ts.map +1 -1
- package/dist/shared/error-handler.js +50 -0
- package/dist/shared/error-handler.js.map +1 -1
- package/dist/shared-utils.d.ts +16 -2
- package/dist/shared-utils.d.ts.map +1 -1
- package/dist/shared-utils.js +37 -3
- package/dist/shared-utils.js.map +1 -1
- package/dist/template-manager.d.ts.map +1 -1
- package/dist/template-manager.js +2 -1
- package/dist/template-manager.js.map +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Docs</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0a0e1a;
|
|
10
|
+
--surface: rgba(15, 20, 35, 0.95);
|
|
11
|
+
--line: rgba(255,255,255,0.08);
|
|
12
|
+
--text: #e5e5e5;
|
|
13
|
+
--muted: rgba(255,255,255,0.4);
|
|
14
|
+
--accent: #67c7ff;
|
|
15
|
+
--page-bg: #ffffff;
|
|
16
|
+
--page-text: #1a1a2e;
|
|
17
|
+
--page-shadow: 0 2px 20px rgba(0,0,0,0.4);
|
|
18
|
+
--spring: cubic-bezier(0.16, 1, 0.3, 1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
* { box-sizing: border-box; margin: 0; }
|
|
22
|
+
|
|
23
|
+
body {
|
|
24
|
+
background: var(--bg);
|
|
25
|
+
color: var(--text);
|
|
26
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
27
|
+
height: 100vh;
|
|
28
|
+
display: grid;
|
|
29
|
+
grid-template-columns: 240px 1fr;
|
|
30
|
+
grid-template-rows: auto 1fr;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* ── Top Bar ── */
|
|
35
|
+
|
|
36
|
+
.topbar {
|
|
37
|
+
grid-column: 1 / -1;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 12px;
|
|
41
|
+
padding: 10px 20px;
|
|
42
|
+
border-bottom: 1px solid var(--line);
|
|
43
|
+
background: var(--surface);
|
|
44
|
+
font-size: 13px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.topbar .title {
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
flex: 1;
|
|
50
|
+
white-space: nowrap;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.topbar .stats {
|
|
56
|
+
color: var(--muted);
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.topbar button {
|
|
62
|
+
background: rgba(255,255,255,0.06);
|
|
63
|
+
border: 1px solid var(--line);
|
|
64
|
+
color: var(--text);
|
|
65
|
+
padding: 6px 14px;
|
|
66
|
+
border-radius: 6px;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
font-size: 12px;
|
|
69
|
+
transition: background 0.15s;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.topbar button:hover { background: rgba(255,255,255,0.12); }
|
|
73
|
+
.topbar button.primary { background: rgba(103,199,255,0.15); border-color: rgba(103,199,255,0.3); }
|
|
74
|
+
|
|
75
|
+
/* ── Sidebar (Outline) ── */
|
|
76
|
+
|
|
77
|
+
.sidebar {
|
|
78
|
+
background: var(--surface);
|
|
79
|
+
border-right: 1px solid var(--line);
|
|
80
|
+
padding: 16px;
|
|
81
|
+
overflow-y: auto;
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
gap: 8px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.sidebar-label {
|
|
88
|
+
font-size: 10px;
|
|
89
|
+
text-transform: uppercase;
|
|
90
|
+
letter-spacing: 0.12em;
|
|
91
|
+
color: var(--muted);
|
|
92
|
+
margin-bottom: 4px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.outline-item {
|
|
96
|
+
display: block;
|
|
97
|
+
width: 100%;
|
|
98
|
+
text-align: left;
|
|
99
|
+
background: none;
|
|
100
|
+
border: none;
|
|
101
|
+
color: var(--text);
|
|
102
|
+
padding: 6px 8px;
|
|
103
|
+
border-radius: 6px;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
font-size: 13px;
|
|
106
|
+
transition: background 0.15s;
|
|
107
|
+
white-space: nowrap;
|
|
108
|
+
overflow: hidden;
|
|
109
|
+
text-overflow: ellipsis;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.outline-item:hover { background: rgba(255,255,255,0.06); }
|
|
113
|
+
.outline-item.h2 { padding-left: 20px; font-size: 12px; }
|
|
114
|
+
.outline-item.h3 { padding-left: 36px; font-size: 11px; color: var(--muted); }
|
|
115
|
+
|
|
116
|
+
.doc-list {
|
|
117
|
+
margin-top: 12px;
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
gap: 4px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.doc-item {
|
|
124
|
+
display: block;
|
|
125
|
+
width: 100%;
|
|
126
|
+
text-align: left;
|
|
127
|
+
background: none;
|
|
128
|
+
border: none;
|
|
129
|
+
color: var(--muted);
|
|
130
|
+
padding: 6px 8px;
|
|
131
|
+
border-radius: 6px;
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
font-size: 12px;
|
|
134
|
+
transition: background 0.15s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.doc-item:hover { background: rgba(255,255,255,0.06); color: var(--text); }
|
|
138
|
+
.doc-item.active { background: rgba(103,199,255,0.1); color: var(--accent); }
|
|
139
|
+
|
|
140
|
+
/* ── Main Editor Area ── */
|
|
141
|
+
|
|
142
|
+
.editor-area {
|
|
143
|
+
display: grid;
|
|
144
|
+
grid-template-columns: 1fr 1fr;
|
|
145
|
+
gap: 0;
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.editor-pane {
|
|
150
|
+
display: flex;
|
|
151
|
+
flex-direction: column;
|
|
152
|
+
border-right: 1px solid var(--line);
|
|
153
|
+
overflow: hidden;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.pane-header {
|
|
157
|
+
padding: 8px 16px;
|
|
158
|
+
font-size: 11px;
|
|
159
|
+
text-transform: uppercase;
|
|
160
|
+
letter-spacing: 0.1em;
|
|
161
|
+
color: var(--muted);
|
|
162
|
+
border-bottom: 1px solid var(--line);
|
|
163
|
+
background: rgba(255,255,255,0.02);
|
|
164
|
+
flex-shrink: 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
textarea {
|
|
168
|
+
flex: 1;
|
|
169
|
+
width: 100%;
|
|
170
|
+
border: none;
|
|
171
|
+
outline: none;
|
|
172
|
+
resize: none;
|
|
173
|
+
background: rgba(6, 10, 20, 0.9);
|
|
174
|
+
color: var(--text);
|
|
175
|
+
padding: 20px 24px;
|
|
176
|
+
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
|
177
|
+
font-size: 13px;
|
|
178
|
+
line-height: 1.7;
|
|
179
|
+
tab-size: 2;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* ── Preview Pane ── */
|
|
183
|
+
|
|
184
|
+
.preview-pane {
|
|
185
|
+
overflow-y: auto;
|
|
186
|
+
background: #1a1e2e;
|
|
187
|
+
padding: 32px;
|
|
188
|
+
display: flex;
|
|
189
|
+
flex-direction: column;
|
|
190
|
+
align-items: center;
|
|
191
|
+
gap: 24px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.page {
|
|
195
|
+
width: 210mm;
|
|
196
|
+
max-width: 100%;
|
|
197
|
+
min-height: 297mm;
|
|
198
|
+
background: var(--page-bg);
|
|
199
|
+
color: var(--page-text);
|
|
200
|
+
box-shadow: var(--page-shadow);
|
|
201
|
+
border-radius: 4px;
|
|
202
|
+
padding: 60px 50px;
|
|
203
|
+
font-family: 'Inter', 'Georgia', serif;
|
|
204
|
+
font-size: 11pt;
|
|
205
|
+
line-height: 1.7;
|
|
206
|
+
animation: page-fade-in 0.3s ease-out both;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@keyframes page-fade-in {
|
|
210
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
211
|
+
to { opacity: 1; transform: translateY(0); }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.page h1 { font-size: 2em; margin: 0 0 0.5em; color: #111; font-weight: 700; }
|
|
215
|
+
.page h2 { font-size: 1.5em; margin: 1.2em 0 0.4em; color: #222; font-weight: 600; border-bottom: 1px solid #e5e5e5; padding-bottom: 0.3em; }
|
|
216
|
+
.page h3 { font-size: 1.2em; margin: 1em 0 0.3em; color: #333; }
|
|
217
|
+
.page p { margin: 0.6em 0; }
|
|
218
|
+
.page ul, .page ol { margin: 0.6em 0; padding-left: 1.8em; }
|
|
219
|
+
.page li { margin: 0.3em 0; }
|
|
220
|
+
.page code { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-size: 0.9em; font-family: 'JetBrains Mono', monospace; }
|
|
221
|
+
.page pre { background: #f5f5f5; padding: 16px; border-radius: 6px; overflow-x: auto; margin: 0.8em 0; }
|
|
222
|
+
.page pre code { background: none; padding: 0; }
|
|
223
|
+
.page blockquote { border-left: 3px solid #ccc; padding-left: 16px; margin: 0.8em 0; color: #555; }
|
|
224
|
+
.page img { max-width: 100%; border-radius: 4px; }
|
|
225
|
+
.page table { border-collapse: collapse; width: 100%; margin: 0.8em 0; }
|
|
226
|
+
.page th, .page td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
|
|
227
|
+
.page th { background: #f8f8f8; font-weight: 600; }
|
|
228
|
+
.page hr { border: none; border-top: 1px solid #e5e5e5; margin: 2em 0; }
|
|
229
|
+
|
|
230
|
+
/* Callout containers */
|
|
231
|
+
.page .callout { padding: 16px 20px; border-radius: 6px; margin: 1em 0; border-left: 4px solid; }
|
|
232
|
+
.page .callout-note { background: #eff6ff; border-color: #3b82f6; }
|
|
233
|
+
.page .callout-warning { background: #fffbeb; border-color: #f59e0b; }
|
|
234
|
+
.page .callout-tip { background: #f0fdf4; border-color: #22c55e; }
|
|
235
|
+
.page .callout-title { font-weight: 600; margin-bottom: 4px; }
|
|
236
|
+
|
|
237
|
+
/* Footnotes */
|
|
238
|
+
.page .footnote { font-size: 0.85em; color: #666; border-top: 1px solid #e5e5e5; padding-top: 8px; margin-top: 2em; }
|
|
239
|
+
|
|
240
|
+
/* Page break indicator */
|
|
241
|
+
.page-break-indicator {
|
|
242
|
+
width: 100%;
|
|
243
|
+
text-align: center;
|
|
244
|
+
color: var(--muted);
|
|
245
|
+
font-size: 11px;
|
|
246
|
+
padding: 4px 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@media (max-width: 1200px) {
|
|
250
|
+
body { grid-template-columns: 1fr; }
|
|
251
|
+
.sidebar { display: none; }
|
|
252
|
+
.editor-area { grid-template-columns: 1fr; }
|
|
253
|
+
.preview-pane { display: none; }
|
|
254
|
+
}
|
|
255
|
+
</style>
|
|
256
|
+
</head>
|
|
257
|
+
<body>
|
|
258
|
+
<div class="topbar">
|
|
259
|
+
<span class="title" id="doc-title">Untitled Document</span>
|
|
260
|
+
<span class="stats" id="doc-stats"></span>
|
|
261
|
+
<button class="primary" id="save-btn">Save</button>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<aside class="sidebar">
|
|
265
|
+
<div class="sidebar-label">Outline</div>
|
|
266
|
+
<div id="outline"></div>
|
|
267
|
+
<div class="sidebar-label" style="margin-top:16px;">Documents</div>
|
|
268
|
+
<div class="doc-list" id="doc-list"></div>
|
|
269
|
+
</aside>
|
|
270
|
+
|
|
271
|
+
<div class="editor-area">
|
|
272
|
+
<div class="editor-pane">
|
|
273
|
+
<div class="pane-header">Markdown</div>
|
|
274
|
+
<textarea id="editor" spellcheck="false"></textarea>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="preview-pane" id="preview"></div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<script>
|
|
280
|
+
const docsApp = window["docs"];
|
|
281
|
+
let state = { markdown: '', frontmatter: {}, outline: [], stats: {} };
|
|
282
|
+
|
|
283
|
+
function parseMCP(raw) {
|
|
284
|
+
if (raw && raw.content && Array.isArray(raw.content)) {
|
|
285
|
+
const item = raw.content.find(c => c.type === "text" && c.text);
|
|
286
|
+
if (item) { try { return JSON.parse(item.text); } catch { return item.text; } }
|
|
287
|
+
}
|
|
288
|
+
return raw;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function renderPreview(markdown) {
|
|
292
|
+
const preview = document.getElementById("preview");
|
|
293
|
+
// Split on page breaks
|
|
294
|
+
const { body } = splitFrontmatter(markdown);
|
|
295
|
+
const pages = body.split(/---pagebreak---/);
|
|
296
|
+
|
|
297
|
+
preview.innerHTML = pages.map((pageContent, i) => {
|
|
298
|
+
const html = renderMarkdown(pageContent.trim());
|
|
299
|
+
return `<div class="page">${html}</div>` +
|
|
300
|
+
(i < pages.length - 1 ? '<div class="page-break-indicator">--- page break ---</div>' : '');
|
|
301
|
+
}).join('');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function splitFrontmatter(md) {
|
|
305
|
+
const match = md.match(/^---\n[\s\S]*?\n---\n?/);
|
|
306
|
+
return { frontmatter: match ? match[0] : '', body: match ? md.slice(match[0].length) : md };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function renderMarkdown(text) {
|
|
310
|
+
// Simple markdown renderer — handles common elements
|
|
311
|
+
let html = text
|
|
312
|
+
// Code blocks
|
|
313
|
+
.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
|
|
314
|
+
// Callout containers
|
|
315
|
+
.replace(/::: (note|warning|tip)\n([\s\S]*?):::/g, (_, type, content) =>
|
|
316
|
+
`<div class="callout callout-${type}"><div class="callout-title">${type.charAt(0).toUpperCase() + type.slice(1)}</div>${renderInline(content.trim())}</div>`)
|
|
317
|
+
// Headings
|
|
318
|
+
.replace(/^### (.+)$/gm, '<h3>$1</h3>')
|
|
319
|
+
.replace(/^## (.+)$/gm, '<h2>$1</h2>')
|
|
320
|
+
.replace(/^# (.+)$/gm, '<h1>$1</h1>')
|
|
321
|
+
// Horizontal rules
|
|
322
|
+
.replace(/^---$/gm, '<hr>')
|
|
323
|
+
// Blockquotes
|
|
324
|
+
.replace(/^> (.+)$/gm, '<blockquote>$1</blockquote>')
|
|
325
|
+
// Unordered lists
|
|
326
|
+
.replace(/^- (.+)$/gm, '<li>$1</li>')
|
|
327
|
+
// Ordered lists
|
|
328
|
+
.replace(/^\d+\. (.+)$/gm, '<li>$1</li>')
|
|
329
|
+
// Footnotes
|
|
330
|
+
.replace(/\[\^(\d+)\]:\s*(.+)$/gm, '<div class="footnote"><sup>$1</sup> $2</div>')
|
|
331
|
+
.replace(/\[\^(\d+)\]/g, '<sup>$1</sup>')
|
|
332
|
+
// Paragraphs
|
|
333
|
+
.replace(/\n\n+/g, '</p><p>')
|
|
334
|
+
// Wrap lists
|
|
335
|
+
.replace(/(<li>[\s\S]*?<\/li>)/g, '<ul>$1</ul>')
|
|
336
|
+
// Clean up double-wrapped lists
|
|
337
|
+
.replace(/<\/ul>\s*<ul>/g, '');
|
|
338
|
+
|
|
339
|
+
html = renderInline(html);
|
|
340
|
+
return `<p>${html}</p>`.replace(/<p><\/p>/g, '').replace(/<p>(<h[1-6])/g, '$1').replace(/(<\/h[1-6]>)<\/p>/g, '$1');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function renderInline(text) {
|
|
344
|
+
return text
|
|
345
|
+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
346
|
+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
347
|
+
.replace(/`(.+?)`/g, '<code>$1</code>')
|
|
348
|
+
.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function renderOutline(outline) {
|
|
352
|
+
const el = document.getElementById("outline");
|
|
353
|
+
if (!outline || !outline.length) { el.innerHTML = '<span style="color:var(--muted);font-size:12px;">No headings</span>'; return; }
|
|
354
|
+
el.innerHTML = outline.map(h =>
|
|
355
|
+
`<button class="outline-item h${h.level}" data-line="${h.line}">${h.text}</button>`
|
|
356
|
+
).join('');
|
|
357
|
+
el.querySelectorAll("[data-line]").forEach(btn => {
|
|
358
|
+
btn.addEventListener("click", () => {
|
|
359
|
+
const editor = document.getElementById("editor");
|
|
360
|
+
const lines = editor.value.split('\n');
|
|
361
|
+
let charPos = 0;
|
|
362
|
+
for (let i = 0; i < parseInt(btn.dataset.line) - 1 && i < lines.length; i++) {
|
|
363
|
+
charPos += lines[i].length + 1;
|
|
364
|
+
}
|
|
365
|
+
editor.focus();
|
|
366
|
+
editor.setSelectionRange(charPos, charPos);
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function updateUI(data) {
|
|
372
|
+
if (!data || data.error) return;
|
|
373
|
+
state = data;
|
|
374
|
+
const fm = data.frontmatter || {};
|
|
375
|
+
document.getElementById("doc-title").textContent = fm.title || data.file || 'Untitled';
|
|
376
|
+
document.getElementById("editor").value = data.markdown || '';
|
|
377
|
+
const s = data.stats || {};
|
|
378
|
+
document.getElementById("doc-stats").textContent =
|
|
379
|
+
`${s.words || 0} words · ${s.readingTime || 1} min read · ${s.headings || 0} sections`;
|
|
380
|
+
renderOutline(data.outline);
|
|
381
|
+
renderPreview(data.markdown || '');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ── Event Handlers ──
|
|
385
|
+
|
|
386
|
+
document.getElementById("save-btn").addEventListener("click", async () => {
|
|
387
|
+
const markdown = document.getElementById("editor").value;
|
|
388
|
+
if (docsApp) {
|
|
389
|
+
const result = parseMCP(await docsApp.save({ markdown }));
|
|
390
|
+
updateUI(result);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Live preview on typing (debounced)
|
|
395
|
+
let previewTimeout;
|
|
396
|
+
document.getElementById("editor").addEventListener("input", () => {
|
|
397
|
+
clearTimeout(previewTimeout);
|
|
398
|
+
previewTimeout = setTimeout(() => {
|
|
399
|
+
renderPreview(document.getElementById("editor").value);
|
|
400
|
+
}, 300);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Keyboard shortcut: Cmd/Ctrl+S to save
|
|
404
|
+
document.addEventListener("keydown", (e) => {
|
|
405
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "s") {
|
|
406
|
+
e.preventDefault();
|
|
407
|
+
document.getElementById("save-btn").click();
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// ── Bridge ──
|
|
412
|
+
|
|
413
|
+
if (docsApp) {
|
|
414
|
+
window.photon?.onResult?.((result) => {
|
|
415
|
+
const data = parseMCP(result);
|
|
416
|
+
if (data && data.markdown) updateUI(data);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
window.photon?.onEmit?.((event) => {
|
|
420
|
+
if (event?.event === "docChanged") {
|
|
421
|
+
docsApp.main().then(r => updateUI(parseMCP(r)));
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Load doc list
|
|
426
|
+
docsApp.list().then(r => {
|
|
427
|
+
const data = parseMCP(r);
|
|
428
|
+
if (data && data.docs) {
|
|
429
|
+
const list = document.getElementById("doc-list");
|
|
430
|
+
list.innerHTML = data.docs.map(d =>
|
|
431
|
+
`<button class="doc-item" data-file="${d.file}">${d.title || d.file}</button>`
|
|
432
|
+
).join('');
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Initial load
|
|
437
|
+
docsApp.main().then(r => updateUI(parseMCP(r)));
|
|
438
|
+
}
|
|
439
|
+
</script>
|
|
440
|
+
</body>
|
|
441
|
+
</html>
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
export default class Docs {
|
|
2
|
+
protected settings: {
|
|
3
|
+
/** @property Directory where document files are stored */
|
|
4
|
+
folder: string;
|
|
5
|
+
};
|
|
6
|
+
memory: {
|
|
7
|
+
get<T>(key: string): Promise<T | null>;
|
|
8
|
+
set(key: string, value: unknown): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
emit: (payload: {
|
|
11
|
+
event: string;
|
|
12
|
+
data: unknown;
|
|
13
|
+
}) => void;
|
|
14
|
+
instanceName: string;
|
|
15
|
+
private get defaultFolder();
|
|
16
|
+
private get docPath();
|
|
17
|
+
onInitialize(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Open the document editor UI
|
|
20
|
+
* @ui editor
|
|
21
|
+
* @autorun
|
|
22
|
+
*/
|
|
23
|
+
main(): Promise<{
|
|
24
|
+
file: string;
|
|
25
|
+
markdown: string;
|
|
26
|
+
frontmatter: Record<string, any>;
|
|
27
|
+
outline: HeadingEntry[];
|
|
28
|
+
stats: {
|
|
29
|
+
words: number;
|
|
30
|
+
chars: number;
|
|
31
|
+
paragraphs: number;
|
|
32
|
+
headings: number;
|
|
33
|
+
readingTime: number;
|
|
34
|
+
sections: {
|
|
35
|
+
heading: string;
|
|
36
|
+
level: number;
|
|
37
|
+
words: number;
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Read the document markdown
|
|
43
|
+
* @readOnly
|
|
44
|
+
*/
|
|
45
|
+
read(): Promise<{
|
|
46
|
+
file: string;
|
|
47
|
+
markdown: string;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Save the full document markdown
|
|
51
|
+
* @param markdown Full markdown content with YAML frontmatter
|
|
52
|
+
* @ui editor
|
|
53
|
+
*/
|
|
54
|
+
save({ markdown }: {
|
|
55
|
+
markdown: string;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
file: string;
|
|
58
|
+
markdown: string;
|
|
59
|
+
frontmatter: Record<string, any>;
|
|
60
|
+
outline: HeadingEntry[];
|
|
61
|
+
stats: {
|
|
62
|
+
words: number;
|
|
63
|
+
chars: number;
|
|
64
|
+
paragraphs: number;
|
|
65
|
+
headings: number;
|
|
66
|
+
readingTime: number;
|
|
67
|
+
sections: {
|
|
68
|
+
heading: string;
|
|
69
|
+
level: number;
|
|
70
|
+
words: number;
|
|
71
|
+
}[];
|
|
72
|
+
};
|
|
73
|
+
}>;
|
|
74
|
+
/**
|
|
75
|
+
* Get the document's heading structure for navigation
|
|
76
|
+
* @readOnly
|
|
77
|
+
*/
|
|
78
|
+
outline(): Promise<{
|
|
79
|
+
outline: HeadingEntry[];
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Edit a specific section by heading path
|
|
83
|
+
* @param section Heading text or path like "Chapter 3/Introduction"
|
|
84
|
+
* @param markdown New content for that section (everything under the heading until next same-level heading)
|
|
85
|
+
* @ui editor
|
|
86
|
+
*/
|
|
87
|
+
edit({ section, markdown: newContent }: {
|
|
88
|
+
section: string;
|
|
89
|
+
markdown: string;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
file: string;
|
|
92
|
+
markdown: string;
|
|
93
|
+
frontmatter: Record<string, any>;
|
|
94
|
+
outline: HeadingEntry[];
|
|
95
|
+
stats: {
|
|
96
|
+
words: number;
|
|
97
|
+
chars: number;
|
|
98
|
+
paragraphs: number;
|
|
99
|
+
headings: number;
|
|
100
|
+
readingTime: number;
|
|
101
|
+
sections: {
|
|
102
|
+
heading: string;
|
|
103
|
+
level: number;
|
|
104
|
+
words: number;
|
|
105
|
+
}[];
|
|
106
|
+
};
|
|
107
|
+
} | {
|
|
108
|
+
error: string;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Append content at the end of the document or after a specific section
|
|
112
|
+
* @param markdown Content to append
|
|
113
|
+
* @param after Optional heading text — inserts after that section instead of end
|
|
114
|
+
* @ui editor
|
|
115
|
+
*/
|
|
116
|
+
append({ markdown: content, after }: {
|
|
117
|
+
markdown: string;
|
|
118
|
+
after?: string;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
file: string;
|
|
121
|
+
markdown: string;
|
|
122
|
+
frontmatter: Record<string, any>;
|
|
123
|
+
outline: HeadingEntry[];
|
|
124
|
+
stats: {
|
|
125
|
+
words: number;
|
|
126
|
+
chars: number;
|
|
127
|
+
paragraphs: number;
|
|
128
|
+
headings: number;
|
|
129
|
+
readingTime: number;
|
|
130
|
+
sections: {
|
|
131
|
+
heading: string;
|
|
132
|
+
level: number;
|
|
133
|
+
words: number;
|
|
134
|
+
}[];
|
|
135
|
+
};
|
|
136
|
+
}>;
|
|
137
|
+
/**
|
|
138
|
+
* Find text in the document with optional fuzzy matching
|
|
139
|
+
* @param query Search text
|
|
140
|
+
* @param fuzzy Enable fuzzy matching {@default false}
|
|
141
|
+
* @param scope Limit search to a section heading
|
|
142
|
+
* @readOnly
|
|
143
|
+
*/
|
|
144
|
+
find({ query, fuzzy, scope }: {
|
|
145
|
+
query: string;
|
|
146
|
+
fuzzy?: boolean;
|
|
147
|
+
scope?: string;
|
|
148
|
+
}): Promise<{
|
|
149
|
+
query: string;
|
|
150
|
+
fuzzy: boolean;
|
|
151
|
+
scope: string | null;
|
|
152
|
+
matches: {
|
|
153
|
+
line: number;
|
|
154
|
+
text: string;
|
|
155
|
+
context: string;
|
|
156
|
+
}[];
|
|
157
|
+
total: number;
|
|
158
|
+
}>;
|
|
159
|
+
/**
|
|
160
|
+
* Find and replace text in the document
|
|
161
|
+
* @param pattern Text to find (string or regex pattern)
|
|
162
|
+
* @param replacement Replacement text
|
|
163
|
+
* @param scope Limit to a section heading
|
|
164
|
+
* @param all Replace all occurrences {@default true}
|
|
165
|
+
* @ui editor
|
|
166
|
+
*/
|
|
167
|
+
replace({ pattern, replacement, scope, all, }: {
|
|
168
|
+
pattern: string;
|
|
169
|
+
replacement: string;
|
|
170
|
+
scope?: string;
|
|
171
|
+
all?: boolean;
|
|
172
|
+
}): Promise<{
|
|
173
|
+
file: string;
|
|
174
|
+
markdown: string;
|
|
175
|
+
frontmatter: Record<string, any>;
|
|
176
|
+
outline: HeadingEntry[];
|
|
177
|
+
stats: {
|
|
178
|
+
words: number;
|
|
179
|
+
chars: number;
|
|
180
|
+
paragraphs: number;
|
|
181
|
+
headings: number;
|
|
182
|
+
readingTime: number;
|
|
183
|
+
sections: {
|
|
184
|
+
heading: string;
|
|
185
|
+
level: number;
|
|
186
|
+
words: number;
|
|
187
|
+
}[];
|
|
188
|
+
};
|
|
189
|
+
replacements: number;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* List saved documents in the docs folder
|
|
193
|
+
* @readOnly
|
|
194
|
+
*/
|
|
195
|
+
list(): Promise<{
|
|
196
|
+
folder: string;
|
|
197
|
+
docs: {
|
|
198
|
+
file: string;
|
|
199
|
+
title: any;
|
|
200
|
+
author: any;
|
|
201
|
+
updatedAt: string;
|
|
202
|
+
wordCount: number;
|
|
203
|
+
}[];
|
|
204
|
+
}>;
|
|
205
|
+
/**
|
|
206
|
+
* Generate table of contents from the document structure
|
|
207
|
+
* @readOnly
|
|
208
|
+
*/
|
|
209
|
+
toc(): Promise<{
|
|
210
|
+
outline: HeadingEntry[];
|
|
211
|
+
markdown: string;
|
|
212
|
+
}>;
|
|
213
|
+
/**
|
|
214
|
+
* Document statistics: word count, reading time, section breakdown
|
|
215
|
+
* @readOnly
|
|
216
|
+
*/
|
|
217
|
+
stats(): Promise<{
|
|
218
|
+
words: number;
|
|
219
|
+
chars: number;
|
|
220
|
+
paragraphs: number;
|
|
221
|
+
headings: number;
|
|
222
|
+
readingTime: number;
|
|
223
|
+
sections: {
|
|
224
|
+
heading: string;
|
|
225
|
+
level: number;
|
|
226
|
+
words: number;
|
|
227
|
+
}[];
|
|
228
|
+
}>;
|
|
229
|
+
private readDoc;
|
|
230
|
+
}
|
|
231
|
+
interface HeadingEntry {
|
|
232
|
+
level: number;
|
|
233
|
+
text: string;
|
|
234
|
+
line: number;
|
|
235
|
+
}
|
|
236
|
+
export {};
|
|
237
|
+
//# sourceMappingURL=docs.photon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.photon.d.ts","sourceRoot":"","sources":["../../src/photons/docs.photon.ts"],"names":[],"mappings":"AA4DA,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB,SAAS,CAAC,QAAQ;QAChB,0DAA0D;;MAE1D;IAEM,MAAM,EAAE;QACd,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACvC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;IACM,IAAI,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1D,YAAY,EAAE,MAAM,CAAC;IAI7B,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,OAAO,GAUlB;IAEK,YAAY;IAUlB;;;;OAIG;IACG,IAAI;;;;;;;;;;;;;;;;;;IAaV;;;OAGG;IACG,IAAI;;;;IAIV;;;;OAIG;IACG,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;IAgB7C;;;OAGG;IACG,OAAO;;;IAKb;;;;;OAKG;IACG,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;IAmBnF;;;;;OAKG;IACG,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;IAyB/E;;;;;;OAMG;IACG,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;kBAM7D,MAAM;kBAAQ,MAAM;qBAAW,MAAM;;;;IAe9D;;;;;;;OAOG;IACG,OAAO,CAAC,EACZ,OAAO,EACP,WAAW,EACX,KAAK,EACL,GAAG,GACJ,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,OAAO,CAAC;KACf;;;;;;;;;;;;;;;;;;;IAqCD;;;OAGG;IACG,IAAI;;;;;;;;;;IAwBV;;;OAGG;IACG,GAAG;;;;IAOT;;;OAGG;IACG,KAAK;;;;;;;;;;;;YAOG,OAAO;CAOtB;AA8CD,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd"}
|