living-documentation 1.4.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/frontend/index.html +149 -10
- package/dist/src/routes/documents.d.ts.map +1 -1
- package/dist/src/routes/documents.js +36 -0
- package/dist/src/routes/documents.js.map +1 -1
- package/dist/src/routes/images.d.ts +3 -0
- package/dist/src/routes/images.d.ts.map +1 -0
- package/dist/src/routes/images.js +42 -0
- package/dist/src/routes/images.js.map +1 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +5 -1
- package/dist/src/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -175,16 +175,37 @@
|
|
|
175
175
|
</div>
|
|
176
176
|
<!-- Actions -->
|
|
177
177
|
<div class="flex items-center gap-2 shrink-0">
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
<!-- View mode actions -->
|
|
179
|
+
<div id="view-actions" class="flex items-center gap-2">
|
|
180
|
+
<button onclick="exportPDF()" title="Export as PDF"
|
|
181
|
+
class="no-print text-sm px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700
|
|
182
|
+
text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
|
|
183
|
+
📄 Export PDF
|
|
184
|
+
</button>
|
|
185
|
+
<button onclick="copyLink()" id="copy-link-btn" title="Copy link"
|
|
186
|
+
class="no-print text-sm px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700
|
|
187
|
+
text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
|
|
188
|
+
🔗 Copy link
|
|
189
|
+
</button>
|
|
190
|
+
<button onclick="enterEditMode()" title="Edit document"
|
|
191
|
+
class="no-print text-sm px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700
|
|
192
|
+
text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
|
|
193
|
+
✎ Edit
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
<!-- Edit mode actions -->
|
|
197
|
+
<div id="edit-actions" class="hidden flex items-center gap-2">
|
|
198
|
+
<span id="edit-save-msg" class="text-xs"></span>
|
|
199
|
+
<button onclick="exitEditMode()" title="Cancel editing"
|
|
200
|
+
class="text-sm px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700
|
|
201
|
+
text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
|
|
202
|
+
Cancel
|
|
203
|
+
</button>
|
|
204
|
+
<button onclick="saveDocument()" title="Save document"
|
|
205
|
+
class="text-sm px-4 py-1.5 rounded-lg bg-blue-600 hover:bg-blue-700 text-white font-semibold transition-colors">
|
|
206
|
+
Save
|
|
207
|
+
</button>
|
|
208
|
+
</div>
|
|
188
209
|
</div>
|
|
189
210
|
</div>
|
|
190
211
|
</header>
|
|
@@ -201,6 +222,14 @@
|
|
|
201
222
|
prose-code:before:content-none prose-code:after:content-none
|
|
202
223
|
prose-pre:bg-[#0d1117] prose-pre:border prose-pre:border-gray-700">
|
|
203
224
|
</div>
|
|
225
|
+
|
|
226
|
+
<!-- Markdown editor -->
|
|
227
|
+
<textarea id="doc-editor"
|
|
228
|
+
class="hidden w-full min-h-[70vh] px-4 py-3 text-sm font-mono leading-relaxed
|
|
229
|
+
rounded-lg border border-gray-300 dark:border-gray-600
|
|
230
|
+
bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100
|
|
231
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500 resize-y"
|
|
232
|
+
spellcheck="false"></textarea>
|
|
204
233
|
</article>
|
|
205
234
|
|
|
206
235
|
</main>
|
|
@@ -211,6 +240,7 @@
|
|
|
211
240
|
// ── State ──────────────────────────────────────────────────
|
|
212
241
|
let allDocs = [];
|
|
213
242
|
let currentDocId = null;
|
|
243
|
+
let currentDocContent = '';
|
|
214
244
|
let searchQuery = '';
|
|
215
245
|
let expandedCategories = new Set();
|
|
216
246
|
|
|
@@ -384,6 +414,9 @@ async function openDocument(id, skipHistory = false) {
|
|
|
384
414
|
return r.json();
|
|
385
415
|
});
|
|
386
416
|
|
|
417
|
+
currentDocContent = doc.content;
|
|
418
|
+
exitEditMode();
|
|
419
|
+
|
|
387
420
|
document.getElementById('doc-title').textContent = doc.title;
|
|
388
421
|
document.getElementById('doc-category').textContent = doc.category;
|
|
389
422
|
document.getElementById('doc-date').textContent = doc.formattedDate || '';
|
|
@@ -465,6 +498,112 @@ async function doSearch(q) {
|
|
|
465
498
|
} catch { /* ignore */ }
|
|
466
499
|
}
|
|
467
500
|
|
|
501
|
+
// ── Edit mode ──────────────────────────────────────────────
|
|
502
|
+
function enterEditMode() {
|
|
503
|
+
const editor = document.getElementById('doc-editor');
|
|
504
|
+
editor.value = currentDocContent;
|
|
505
|
+
document.getElementById('doc-content').classList.add('hidden');
|
|
506
|
+
editor.classList.remove('hidden');
|
|
507
|
+
document.getElementById('view-actions').classList.add('hidden');
|
|
508
|
+
document.getElementById('edit-actions').classList.remove('hidden');
|
|
509
|
+
editor.focus();
|
|
510
|
+
editor.addEventListener('paste', handleEditorPaste);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function exitEditMode() {
|
|
514
|
+
const editor = document.getElementById('doc-editor');
|
|
515
|
+
editor.removeEventListener('paste', handleEditorPaste);
|
|
516
|
+
editor.classList.add('hidden');
|
|
517
|
+
document.getElementById('doc-content').classList.remove('hidden');
|
|
518
|
+
document.getElementById('edit-actions').classList.add('hidden');
|
|
519
|
+
document.getElementById('view-actions').classList.remove('hidden');
|
|
520
|
+
document.getElementById('edit-save-msg').textContent = '';
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
async function handleEditorPaste(e) {
|
|
524
|
+
const items = Array.from(e.clipboardData?.items ?? []);
|
|
525
|
+
const imageItem = items.find(item => item.type.startsWith('image/'));
|
|
526
|
+
if (!imageItem) return;
|
|
527
|
+
|
|
528
|
+
e.preventDefault();
|
|
529
|
+
|
|
530
|
+
const ext = imageItem.type.split('/')[1].replace('jpeg', 'jpg') || 'png';
|
|
531
|
+
const blob = imageItem.getAsFile();
|
|
532
|
+
if (!blob) return;
|
|
533
|
+
|
|
534
|
+
const editor = document.getElementById('doc-editor');
|
|
535
|
+
const msgEl = document.getElementById('edit-save-msg');
|
|
536
|
+
|
|
537
|
+
// Insert placeholder at cursor while uploading
|
|
538
|
+
const placeholder = ``;
|
|
539
|
+
const start = editor.selectionStart;
|
|
540
|
+
const before = editor.value.slice(0, start);
|
|
541
|
+
const after = editor.value.slice(editor.selectionEnd);
|
|
542
|
+
editor.value = before + placeholder + after;
|
|
543
|
+
editor.selectionStart = editor.selectionEnd = start + placeholder.length;
|
|
544
|
+
|
|
545
|
+
msgEl.textContent = 'Uploading image…';
|
|
546
|
+
msgEl.className = 'text-xs text-gray-400';
|
|
547
|
+
|
|
548
|
+
try {
|
|
549
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
550
|
+
const reader = new FileReader();
|
|
551
|
+
reader.onload = () => resolve(reader.result);
|
|
552
|
+
reader.onerror = reject;
|
|
553
|
+
reader.readAsDataURL(blob);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
const res = await fetch('/api/images/upload', {
|
|
557
|
+
method: 'POST',
|
|
558
|
+
headers: { 'Content-Type': 'application/json' },
|
|
559
|
+
body: JSON.stringify({ data: base64, ext }),
|
|
560
|
+
});
|
|
561
|
+
if (!res.ok) throw new Error(await res.text());
|
|
562
|
+
|
|
563
|
+
const { filename } = await res.json();
|
|
564
|
+
const mdImage = ``;
|
|
565
|
+
|
|
566
|
+
// Replace placeholder with final markdown
|
|
567
|
+
editor.value = editor.value.replace(placeholder, mdImage);
|
|
568
|
+
msgEl.textContent = '';
|
|
569
|
+
} catch (err) {
|
|
570
|
+
// Remove placeholder on failure
|
|
571
|
+
editor.value = editor.value.replace(placeholder, '');
|
|
572
|
+
msgEl.textContent = 'Image upload failed: ' + err.message;
|
|
573
|
+
msgEl.className = 'text-xs text-red-500 dark:text-red-400';
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
async function saveDocument() {
|
|
578
|
+
if (!currentDocId) return;
|
|
579
|
+
const content = document.getElementById('doc-editor').value;
|
|
580
|
+
const msgEl = document.getElementById('edit-save-msg');
|
|
581
|
+
msgEl.textContent = 'Saving…';
|
|
582
|
+
msgEl.className = 'text-xs text-gray-400';
|
|
583
|
+
|
|
584
|
+
try {
|
|
585
|
+
const res = await fetch('/api/documents/' + currentDocId, {
|
|
586
|
+
method: 'PUT',
|
|
587
|
+
headers: { 'Content-Type': 'application/json' },
|
|
588
|
+
body: JSON.stringify({ content }),
|
|
589
|
+
});
|
|
590
|
+
if (!res.ok) throw new Error(await res.text());
|
|
591
|
+
|
|
592
|
+
currentDocContent = content;
|
|
593
|
+
|
|
594
|
+
// Re-fetch rendered HTML and update view
|
|
595
|
+
const doc = await fetch('/api/documents/' + currentDocId).then(r => r.json());
|
|
596
|
+
const contentEl = document.getElementById('doc-content');
|
|
597
|
+
contentEl.innerHTML = doc.html;
|
|
598
|
+
contentEl.querySelectorAll('pre code').forEach(block => hljs.highlightElement(block));
|
|
599
|
+
|
|
600
|
+
exitEditMode();
|
|
601
|
+
} catch (err) {
|
|
602
|
+
msgEl.textContent = 'Save failed: ' + err.message;
|
|
603
|
+
msgEl.className = 'text-xs text-red-500 dark:text-red-400';
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
468
607
|
// ── Helpers ────────────────────────────────────────────────
|
|
469
608
|
function exportPDF() { window.print(); }
|
|
470
609
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../../src/routes/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAwDpD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../../src/routes/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAwDpD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8IxD"}
|
|
@@ -146,6 +146,42 @@ function documentsRouter(docsPath) {
|
|
|
146
146
|
res.status(500).json({ error: 'Failed to read document' });
|
|
147
147
|
}
|
|
148
148
|
});
|
|
149
|
+
// PUT /api/documents/:id — update document content
|
|
150
|
+
router.put('/:id', (req, res) => {
|
|
151
|
+
const id = decodeURIComponent(req.params.id);
|
|
152
|
+
const { content } = req.body;
|
|
153
|
+
if (typeof content !== 'string') {
|
|
154
|
+
return res.status(400).json({ error: 'content is required' });
|
|
155
|
+
}
|
|
156
|
+
const { extraFiles = [] } = (0, config_1.readConfig)(docsPath);
|
|
157
|
+
// Extra file: id is an absolute path without .md
|
|
158
|
+
if (path_1.default.isAbsolute(id)) {
|
|
159
|
+
const filePath = id + '.md';
|
|
160
|
+
if (!extraFiles.includes(filePath)) {
|
|
161
|
+
return res.status(403).json({ error: 'Access denied' });
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
fs_1.default.writeFileSync(filePath, content, 'utf-8');
|
|
165
|
+
return res.json({ ok: true });
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return res.status(500).json({ error: 'Failed to write document' });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Normal file inside docsPath
|
|
172
|
+
const filename = id + '.md';
|
|
173
|
+
const filePath = safeFilePath(docsPath, filename);
|
|
174
|
+
if (!filePath) {
|
|
175
|
+
return res.status(403).json({ error: 'Access denied' });
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
fs_1.default.writeFileSync(filePath, content, 'utf-8');
|
|
179
|
+
return res.json({ ok: true });
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return res.status(500).json({ error: 'Failed to write document' });
|
|
183
|
+
}
|
|
184
|
+
});
|
|
149
185
|
return router;
|
|
150
186
|
}
|
|
151
187
|
//# sourceMappingURL=documents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../../src/routes/documents.ts"],"names":[],"mappings":";;;;;AAwDA,
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../../src/routes/documents.ts"],"names":[],"mappings":";;;;;AAwDA,0CA8IC;AAtMD,qCAAoD;AACpD,4CAAoB;AACpB,gDAAwB;AACxB,mCAAgC;AAChC,0CAA2D;AAC3D,0CAA2C;AAE3C,SAAS,QAAQ,CAAC,QAAgB,EAAE,aAAuB,EAAE,EAAE,eAAwB;IACrF,qDAAqD;IACrD,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QACpE,MAAM,QAAQ,GAAG,cAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAA,sBAAa,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QACtD,SAAS,CAAC,IAAI,CAAC;YACb,GAAG,IAAI;YACP,EAAE,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,MAAM,WAAW,GAAG,YAAE;SACnB,WAAW,CAAC,QAAQ,CAAC;SACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAC9C,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAA,sBAAa,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IAE/D,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,SAAS,EAAE,GAAG,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,QAAgB;IACtD,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,cAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,GAAgB,EAChB,UAAoB;IAEpB,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtC,IAAI,cAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC;QAC5B,OAAO,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IACzD,CAAC;IACD,OAAO,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,SAAgB,eAAe,CAAC,QAAgB;IAC9C,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IAExB,mDAAmD;IACnD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAC/C,IAAI,CAAC;YACH,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC;YAClE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uDAAuD;IACvD,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,CAAE,GAAG,CAAC,KAAK,CAAC,CAAY,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACnE,IAAI,CAAC,KAAK;YAAE,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEhC,IAAI,CAAC;YACH,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;YAC7D,MAAM,OAAO,GAA0C,EAAE,CAAC;YAE1D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;gBAC3D,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBAEpD,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBACxD,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAExD,IAAI,OAAO,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;oBACvC,IAAI,OAAO,GAAG,EAAE,CAAC;oBACjB,IAAI,SAAS,EAAE,CAAC;wBACd,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;wBACjD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;wBACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;wBAC9D,OAAO;4BACL,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gCACtB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;gCACrD,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACtC,CAAC;oBACD,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACvD,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC;QAElE,iDAAiD;QACjD,IAAI,cAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,IAAA,sBAAa,EAAC,cAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC;gBACrE,MAAM,IAAI,GAAG,eAAM,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC;gBAC7C,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,OAAO;QACT,CAAC;QAED,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC;QAC5B,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAA,sBAAa,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,eAAM,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACjD,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,IAA4B,CAAC;QAErD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC;QAEjD,iDAAiD;QACjD,IAAI,cAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,CAAC;gBACH,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC7C,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC;QAC5B,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC;YACH,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../../src/routes/images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAIpD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuCrD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.imagesRouter = imagesRouter;
|
|
7
|
+
const express_1 = require("express");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
function imagesRouter(docsPath) {
|
|
11
|
+
const router = (0, express_1.Router)();
|
|
12
|
+
// POST /api/images/upload — save a base64-encoded image to DOCS_FOLDER/images/
|
|
13
|
+
router.post('/upload', (req, res) => {
|
|
14
|
+
const { data, ext } = req.body;
|
|
15
|
+
if (typeof data !== 'string' || !data) {
|
|
16
|
+
return res.status(400).json({ error: 'data is required' });
|
|
17
|
+
}
|
|
18
|
+
const safeExt = (typeof ext === 'string' ? ext.replace(/[^a-z0-9]/gi, '') : 'png').toLowerCase() || 'png';
|
|
19
|
+
// Strip base64 data URL prefix if present
|
|
20
|
+
const base64 = data.replace(/^data:image\/[^;]+;base64,/, '');
|
|
21
|
+
const imagesDir = path_1.default.join(docsPath, 'images');
|
|
22
|
+
if (!fs_1.default.existsSync(imagesDir)) {
|
|
23
|
+
fs_1.default.mkdirSync(imagesDir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
const now = new Date();
|
|
26
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
27
|
+
const timestamp = `${now.getFullYear()}_${pad(now.getMonth() + 1)}_${pad(now.getDate())}` +
|
|
28
|
+
`_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
29
|
+
const random = Math.random().toString(36).slice(2, 6);
|
|
30
|
+
const filename = `image_${timestamp}_${random}.${safeExt}`;
|
|
31
|
+
const filePath = path_1.default.join(imagesDir, filename);
|
|
32
|
+
try {
|
|
33
|
+
fs_1.default.writeFileSync(filePath, Buffer.from(base64, 'base64'));
|
|
34
|
+
res.json({ filename });
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
res.status(500).json({ error: 'Failed to save image' });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return router;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../../src/routes/images.ts"],"names":[],"mappings":";;;;;AAIA,oCAuCC;AA3CD,qCAAoD;AACpD,4CAAoB;AACpB,gDAAwB;AAExB,SAAgB,YAAY,CAAC,QAAgB;IAC3C,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IAExB,+EAA+E;IAC/E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACrD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAuC,CAAC;QAElE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACtC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC;QAE1G,0CAA0C;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAE9D,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAChD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,YAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,SAAS,GACb,GAAG,GAAG,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE;YACvE,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,SAAS,SAAS,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC1D,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/src/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,EAChC,QAAQ,EACR,IAAI,EACJ,WAAmB,GACpB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgD/B"}
|
package/dist/src/server.js
CHANGED
|
@@ -10,19 +10,23 @@ const child_process_1 = require("child_process");
|
|
|
10
10
|
const documents_1 = require("./routes/documents");
|
|
11
11
|
const config_1 = require("./routes/config");
|
|
12
12
|
const browse_1 = require("./routes/browse");
|
|
13
|
+
const images_1 = require("./routes/images");
|
|
13
14
|
const config_2 = require("./lib/config");
|
|
14
15
|
async function startServer({ docsPath, port, openBrowser = false, }) {
|
|
15
16
|
const app = (0, express_1.default)();
|
|
16
|
-
app.use(express_1.default.json());
|
|
17
|
+
app.use(express_1.default.json({ limit: '20mb' }));
|
|
17
18
|
// Persist initial state to .living-doc.json
|
|
18
19
|
(0, config_2.writeConfig)(docsPath, { docsFolder: docsPath, port });
|
|
19
20
|
// API
|
|
20
21
|
app.use('/api/documents', (0, documents_1.documentsRouter)(docsPath));
|
|
21
22
|
app.use('/api/config', (0, config_1.configRouter)(docsPath));
|
|
22
23
|
app.use('/api/browse', (0, browse_1.browseRouter)());
|
|
24
|
+
app.use('/api/images', (0, images_1.imagesRouter)(docsPath));
|
|
23
25
|
// Static frontend assets
|
|
24
26
|
const frontendPath = path_1.default.join(__dirname, 'frontend');
|
|
25
27
|
app.use(express_1.default.static(frontendPath));
|
|
28
|
+
// Static assets from docs folder (images, etc.)
|
|
29
|
+
app.use('/images', express_1.default.static(path_1.default.join(docsPath, 'images')));
|
|
26
30
|
app.get('/', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'index.html')));
|
|
27
31
|
app.get('/admin', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'admin.html')));
|
|
28
32
|
return new Promise((resolve) => {
|
package/dist/src/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
|