create-volt 0.48.0 → 0.48.2
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/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/templates/blog/setup/index.html +2 -3
- package/templates/blog/setup/setup.js +16 -11
- package/templates/default/setup/index.html +2 -3
- package/templates/default/setup/setup.js +16 -11
- package/templates/docs/setup/index.html +2 -3
- package/templates/docs/setup/setup.js +16 -11
- package/templates/starter/setup/index.html +2 -3
- package/templates/starter/setup/setup.js +16 -11
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `create-volt` are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/), and this project adheres to
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.48.2] - 2026-06-29
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Config is desktop-only, so the **editor view is now much wider** (up to
|
|
11
|
+
`min(1200px, 95vw)`) while settings stay a readable 720px — view-responsive.
|
|
12
|
+
|
|
13
|
+
## [0.48.1] - 2026-06-29
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Config WYSIWYG loads RTEPro at a **major-version float** (`@1`) instead of a
|
|
17
|
+
pinned patch, so RTEPro 1.x updates flow without a create-volt release. Dropped
|
|
18
|
+
the marked dependency entirely — RTEPro takes markdown directly via setMarkdown().
|
|
19
|
+
|
|
7
20
|
## [0.48.0] - 2026-06-29
|
|
8
21
|
|
|
9
22
|
### Added
|
|
@@ -628,6 +641,8 @@ All notable changes to `create-volt` are documented here. The format follows
|
|
|
628
641
|
watching and full-page hot reload. Supports `--skip-install` and `--force`,
|
|
629
642
|
and auto-detects npm / pnpm / yarn / bun for the install step.
|
|
630
643
|
|
|
644
|
+
[0.48.2]: https://github.com/MIR-2025/volt/releases/tag/v0.48.2
|
|
645
|
+
[0.48.1]: https://github.com/MIR-2025/volt/releases/tag/v0.48.1
|
|
631
646
|
[0.48.0]: https://github.com/MIR-2025/volt/releases/tag/v0.48.0
|
|
632
647
|
[0.47.0]: https://github.com/MIR-2025/volt/releases/tag/v0.47.0
|
|
633
648
|
[0.46.0]: https://github.com/MIR-2025/volt/releases/tag/v0.46.0
|
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<button id="theme-toggle" class="btn btn-sm btn-outline-secondary">Light mode</button>
|
|
23
|
-
<main class="container py-5" style="max-width:
|
|
23
|
+
<main id="wrap" class="container py-5" style="max-width: 720px;">
|
|
24
24
|
<header class="mb-4">
|
|
25
25
|
<h1 class="h3"><span class="accent"><img src="/logo.webp" alt="" style="height:1em;vertical-align:-.15em" /> Set up your Volt app</span></h1>
|
|
26
26
|
<p class="text-muted mb-0">Fill these in and the app starts. This page is disposable — it disappears once you click Apply. Re-open it anytime with <code>npm run dev -- --edit</code>.</p>
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
});
|
|
41
41
|
})();
|
|
42
42
|
</script>
|
|
43
|
-
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1
|
|
44
|
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
43
|
+
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1/rte-pro.js"></script>
|
|
45
44
|
<script type="module" src="/setup.js"></script>
|
|
46
45
|
</body>
|
|
47
46
|
</html>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// settings → writes .env (a VOLT_ADDONS list + settings), adds any needed
|
|
3
3
|
// packages, installs, and starts the app. Add-on code is bundled; enabling is
|
|
4
4
|
// just config.
|
|
5
|
-
import { signal, computed, html, mount } from "/volt.js";
|
|
5
|
+
import { signal, computed, effect, html, mount } from "/volt.js";
|
|
6
6
|
|
|
7
7
|
const { available, themes = [], current, defaultPort, configDefaultPort = 5050 } = await (await fetch("/setup/state")).json();
|
|
8
8
|
const depsOf = Object.fromEntries(available.map((a) => [a.name, a.dependsOn || []]));
|
|
@@ -271,6 +271,11 @@ const aiSettings = () =>
|
|
|
271
271
|
|
|
272
272
|
// --- Manage content (a second screen reached via "Manage content →") ---
|
|
273
273
|
const view = signal("config"); // "config" | "manage"
|
|
274
|
+
// Desktop-only config: keep settings readable, but let the editor go wide.
|
|
275
|
+
effect(() => {
|
|
276
|
+
const w = document.getElementById("wrap");
|
|
277
|
+
if (w) w.style.maxWidth = view() === "manage" ? "min(1200px, 95vw)" : "720px";
|
|
278
|
+
});
|
|
274
279
|
// upgrade check: compare bundled version to npm latest; offer a one-click upgrade
|
|
275
280
|
const upgrade = signal(null); // { current, latest, available }
|
|
276
281
|
fetch("/setup/upgrade-check").then((r) => r.json()).then((u) => upgrade(u)).catch(() => {});
|
|
@@ -303,28 +308,28 @@ const items = signal({ pages: [], posts: [] });
|
|
|
303
308
|
const editing = signal(null); // { type, slug, title, isNew } — set only on open/save/close
|
|
304
309
|
let ed = null; // live RTEPro instance for the open editor
|
|
305
310
|
const loadItems = async () => items(await (await fetch("/setup/content")).json());
|
|
306
|
-
// raw .md → { title,
|
|
311
|
+
// raw .md → { title, body, isHtml }; RTEPro takes markdown directly (setMarkdown),
|
|
312
|
+
// so no markdown library is needed.
|
|
307
313
|
function parseDoc(raw) {
|
|
308
314
|
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
309
315
|
const front = fm ? fm[1] : "";
|
|
310
316
|
const title = ((front.match(/^title:\s*(.+)$/m) || [])[1] || "").trim();
|
|
311
|
-
|
|
312
|
-
const bodyHtml = /^format:\s*html\s*$/m.test(front) ? body : window.marked.parse(body);
|
|
313
|
-
return { title, bodyHtml };
|
|
317
|
+
return { title, body: fm ? raw.slice(fm[0].length) : raw, isHtml: /^format:\s*html\s*$/m.test(front) };
|
|
314
318
|
}
|
|
315
|
-
function mountEditor(
|
|
319
|
+
function mountEditor(doc) {
|
|
316
320
|
ed = window.RTEPro.init("#mg-editor", { height: "60vh", placeholder: "Write…" });
|
|
317
|
-
ed.setHTML(
|
|
321
|
+
if (doc && doc.isHtml) ed.setHTML(doc.body || "");
|
|
322
|
+
else ed.setMarkdown((doc && doc.body) || "");
|
|
318
323
|
}
|
|
319
324
|
async function editItem(type, slug) {
|
|
320
325
|
const d = await (await fetch(`/setup/content/raw?type=${type}&slug=${encodeURIComponent(slug)}`)).json();
|
|
321
|
-
const
|
|
322
|
-
editing({ type, slug, title, isNew: false });
|
|
323
|
-
queueMicrotask(() => mountEditor(
|
|
326
|
+
const doc = parseDoc(d.body || "");
|
|
327
|
+
editing({ type, slug, title: doc.title, isNew: false });
|
|
328
|
+
queueMicrotask(() => mountEditor(doc));
|
|
324
329
|
}
|
|
325
330
|
function newItem(type) {
|
|
326
331
|
editing({ type, slug: "", title: "", isNew: true });
|
|
327
|
-
queueMicrotask(() => mountEditor(""));
|
|
332
|
+
queueMicrotask(() => mountEditor({ body: "", isHtml: false }));
|
|
328
333
|
}
|
|
329
334
|
// markdown can't round-trip complex layouts (columns, inline styles, merged cells,
|
|
330
335
|
// embeds) — save those as HTML so they aren't flattened.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<button id="theme-toggle" class="btn btn-sm btn-outline-secondary">Light mode</button>
|
|
23
|
-
<main class="container py-5" style="max-width:
|
|
23
|
+
<main id="wrap" class="container py-5" style="max-width: 720px;">
|
|
24
24
|
<header class="mb-4">
|
|
25
25
|
<h1 class="h3"><span class="accent"><img src="/logo.webp" alt="" style="height:1em;vertical-align:-.15em" /> Set up your Volt app</span></h1>
|
|
26
26
|
<p class="text-muted mb-0">Fill these in and the app starts. This page is disposable — it disappears once you click Apply. Re-open it anytime with <code>npm run dev -- --edit</code>.</p>
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
});
|
|
41
41
|
})();
|
|
42
42
|
</script>
|
|
43
|
-
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1
|
|
44
|
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
43
|
+
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1/rte-pro.js"></script>
|
|
45
44
|
<script type="module" src="/setup.js"></script>
|
|
46
45
|
</body>
|
|
47
46
|
</html>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// settings → writes .env (a VOLT_ADDONS list + settings), adds any needed
|
|
3
3
|
// packages, installs, and starts the app. Add-on code is bundled; enabling is
|
|
4
4
|
// just config.
|
|
5
|
-
import { signal, computed, html, mount } from "/volt.js";
|
|
5
|
+
import { signal, computed, effect, html, mount } from "/volt.js";
|
|
6
6
|
|
|
7
7
|
const { available, themes = [], current, defaultPort, configDefaultPort = 5050 } = await (await fetch("/setup/state")).json();
|
|
8
8
|
const depsOf = Object.fromEntries(available.map((a) => [a.name, a.dependsOn || []]));
|
|
@@ -271,6 +271,11 @@ const aiSettings = () =>
|
|
|
271
271
|
|
|
272
272
|
// --- Manage content (a second screen reached via "Manage content →") ---
|
|
273
273
|
const view = signal("config"); // "config" | "manage"
|
|
274
|
+
// Desktop-only config: keep settings readable, but let the editor go wide.
|
|
275
|
+
effect(() => {
|
|
276
|
+
const w = document.getElementById("wrap");
|
|
277
|
+
if (w) w.style.maxWidth = view() === "manage" ? "min(1200px, 95vw)" : "720px";
|
|
278
|
+
});
|
|
274
279
|
// upgrade check: compare bundled version to npm latest; offer a one-click upgrade
|
|
275
280
|
const upgrade = signal(null); // { current, latest, available }
|
|
276
281
|
fetch("/setup/upgrade-check").then((r) => r.json()).then((u) => upgrade(u)).catch(() => {});
|
|
@@ -303,28 +308,28 @@ const items = signal({ pages: [], posts: [] });
|
|
|
303
308
|
const editing = signal(null); // { type, slug, title, isNew } — set only on open/save/close
|
|
304
309
|
let ed = null; // live RTEPro instance for the open editor
|
|
305
310
|
const loadItems = async () => items(await (await fetch("/setup/content")).json());
|
|
306
|
-
// raw .md → { title,
|
|
311
|
+
// raw .md → { title, body, isHtml }; RTEPro takes markdown directly (setMarkdown),
|
|
312
|
+
// so no markdown library is needed.
|
|
307
313
|
function parseDoc(raw) {
|
|
308
314
|
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
309
315
|
const front = fm ? fm[1] : "";
|
|
310
316
|
const title = ((front.match(/^title:\s*(.+)$/m) || [])[1] || "").trim();
|
|
311
|
-
|
|
312
|
-
const bodyHtml = /^format:\s*html\s*$/m.test(front) ? body : window.marked.parse(body);
|
|
313
|
-
return { title, bodyHtml };
|
|
317
|
+
return { title, body: fm ? raw.slice(fm[0].length) : raw, isHtml: /^format:\s*html\s*$/m.test(front) };
|
|
314
318
|
}
|
|
315
|
-
function mountEditor(
|
|
319
|
+
function mountEditor(doc) {
|
|
316
320
|
ed = window.RTEPro.init("#mg-editor", { height: "60vh", placeholder: "Write…" });
|
|
317
|
-
ed.setHTML(
|
|
321
|
+
if (doc && doc.isHtml) ed.setHTML(doc.body || "");
|
|
322
|
+
else ed.setMarkdown((doc && doc.body) || "");
|
|
318
323
|
}
|
|
319
324
|
async function editItem(type, slug) {
|
|
320
325
|
const d = await (await fetch(`/setup/content/raw?type=${type}&slug=${encodeURIComponent(slug)}`)).json();
|
|
321
|
-
const
|
|
322
|
-
editing({ type, slug, title, isNew: false });
|
|
323
|
-
queueMicrotask(() => mountEditor(
|
|
326
|
+
const doc = parseDoc(d.body || "");
|
|
327
|
+
editing({ type, slug, title: doc.title, isNew: false });
|
|
328
|
+
queueMicrotask(() => mountEditor(doc));
|
|
324
329
|
}
|
|
325
330
|
function newItem(type) {
|
|
326
331
|
editing({ type, slug: "", title: "", isNew: true });
|
|
327
|
-
queueMicrotask(() => mountEditor(""));
|
|
332
|
+
queueMicrotask(() => mountEditor({ body: "", isHtml: false }));
|
|
328
333
|
}
|
|
329
334
|
// markdown can't round-trip complex layouts (columns, inline styles, merged cells,
|
|
330
335
|
// embeds) — save those as HTML so they aren't flattened.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<button id="theme-toggle" class="btn btn-sm btn-outline-secondary">Light mode</button>
|
|
23
|
-
<main class="container py-5" style="max-width:
|
|
23
|
+
<main id="wrap" class="container py-5" style="max-width: 720px;">
|
|
24
24
|
<header class="mb-4">
|
|
25
25
|
<h1 class="h3"><span class="accent"><img src="/logo.webp" alt="" style="height:1em;vertical-align:-.15em" /> Set up your Volt app</span></h1>
|
|
26
26
|
<p class="text-muted mb-0">Fill these in and the app starts. This page is disposable — it disappears once you click Apply. Re-open it anytime with <code>npm run dev -- --edit</code>.</p>
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
});
|
|
41
41
|
})();
|
|
42
42
|
</script>
|
|
43
|
-
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1
|
|
44
|
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
43
|
+
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1/rte-pro.js"></script>
|
|
45
44
|
<script type="module" src="/setup.js"></script>
|
|
46
45
|
</body>
|
|
47
46
|
</html>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// settings → writes .env (a VOLT_ADDONS list + settings), adds any needed
|
|
3
3
|
// packages, installs, and starts the app. Add-on code is bundled; enabling is
|
|
4
4
|
// just config.
|
|
5
|
-
import { signal, computed, html, mount } from "/volt.js";
|
|
5
|
+
import { signal, computed, effect, html, mount } from "/volt.js";
|
|
6
6
|
|
|
7
7
|
const { available, themes = [], current, defaultPort, configDefaultPort = 5050 } = await (await fetch("/setup/state")).json();
|
|
8
8
|
const depsOf = Object.fromEntries(available.map((a) => [a.name, a.dependsOn || []]));
|
|
@@ -271,6 +271,11 @@ const aiSettings = () =>
|
|
|
271
271
|
|
|
272
272
|
// --- Manage content (a second screen reached via "Manage content →") ---
|
|
273
273
|
const view = signal("config"); // "config" | "manage"
|
|
274
|
+
// Desktop-only config: keep settings readable, but let the editor go wide.
|
|
275
|
+
effect(() => {
|
|
276
|
+
const w = document.getElementById("wrap");
|
|
277
|
+
if (w) w.style.maxWidth = view() === "manage" ? "min(1200px, 95vw)" : "720px";
|
|
278
|
+
});
|
|
274
279
|
// upgrade check: compare bundled version to npm latest; offer a one-click upgrade
|
|
275
280
|
const upgrade = signal(null); // { current, latest, available }
|
|
276
281
|
fetch("/setup/upgrade-check").then((r) => r.json()).then((u) => upgrade(u)).catch(() => {});
|
|
@@ -303,28 +308,28 @@ const items = signal({ pages: [], posts: [] });
|
|
|
303
308
|
const editing = signal(null); // { type, slug, title, isNew } — set only on open/save/close
|
|
304
309
|
let ed = null; // live RTEPro instance for the open editor
|
|
305
310
|
const loadItems = async () => items(await (await fetch("/setup/content")).json());
|
|
306
|
-
// raw .md → { title,
|
|
311
|
+
// raw .md → { title, body, isHtml }; RTEPro takes markdown directly (setMarkdown),
|
|
312
|
+
// so no markdown library is needed.
|
|
307
313
|
function parseDoc(raw) {
|
|
308
314
|
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
309
315
|
const front = fm ? fm[1] : "";
|
|
310
316
|
const title = ((front.match(/^title:\s*(.+)$/m) || [])[1] || "").trim();
|
|
311
|
-
|
|
312
|
-
const bodyHtml = /^format:\s*html\s*$/m.test(front) ? body : window.marked.parse(body);
|
|
313
|
-
return { title, bodyHtml };
|
|
317
|
+
return { title, body: fm ? raw.slice(fm[0].length) : raw, isHtml: /^format:\s*html\s*$/m.test(front) };
|
|
314
318
|
}
|
|
315
|
-
function mountEditor(
|
|
319
|
+
function mountEditor(doc) {
|
|
316
320
|
ed = window.RTEPro.init("#mg-editor", { height: "60vh", placeholder: "Write…" });
|
|
317
|
-
ed.setHTML(
|
|
321
|
+
if (doc && doc.isHtml) ed.setHTML(doc.body || "");
|
|
322
|
+
else ed.setMarkdown((doc && doc.body) || "");
|
|
318
323
|
}
|
|
319
324
|
async function editItem(type, slug) {
|
|
320
325
|
const d = await (await fetch(`/setup/content/raw?type=${type}&slug=${encodeURIComponent(slug)}`)).json();
|
|
321
|
-
const
|
|
322
|
-
editing({ type, slug, title, isNew: false });
|
|
323
|
-
queueMicrotask(() => mountEditor(
|
|
326
|
+
const doc = parseDoc(d.body || "");
|
|
327
|
+
editing({ type, slug, title: doc.title, isNew: false });
|
|
328
|
+
queueMicrotask(() => mountEditor(doc));
|
|
324
329
|
}
|
|
325
330
|
function newItem(type) {
|
|
326
331
|
editing({ type, slug: "", title: "", isNew: true });
|
|
327
|
-
queueMicrotask(() => mountEditor(""));
|
|
332
|
+
queueMicrotask(() => mountEditor({ body: "", isHtml: false }));
|
|
328
333
|
}
|
|
329
334
|
// markdown can't round-trip complex layouts (columns, inline styles, merged cells,
|
|
330
335
|
// embeds) — save those as HTML so they aren't flattened.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<button id="theme-toggle" class="btn btn-sm btn-outline-secondary">Light mode</button>
|
|
23
|
-
<main class="container py-5" style="max-width:
|
|
23
|
+
<main id="wrap" class="container py-5" style="max-width: 720px;">
|
|
24
24
|
<header class="mb-4">
|
|
25
25
|
<h1 class="h3"><span class="accent"><img src="/logo.webp" alt="" style="height:1em;vertical-align:-.15em" /> Set up your Volt app</span></h1>
|
|
26
26
|
<p class="text-muted mb-0">Fill these in and the app starts. This page is disposable — it disappears once you click Apply. Re-open it anytime with <code>npm run dev -- --edit</code>.</p>
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
});
|
|
41
41
|
})();
|
|
42
42
|
</script>
|
|
43
|
-
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1
|
|
44
|
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
43
|
+
<script src="https://cdn.jsdelivr.net/npm/rte-rich-text-editor-pro@1/rte-pro.js"></script>
|
|
45
44
|
<script type="module" src="/setup.js"></script>
|
|
46
45
|
</body>
|
|
47
46
|
</html>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// settings → writes .env (a VOLT_ADDONS list + settings), adds any needed
|
|
3
3
|
// packages, installs, and starts the app. Add-on code is bundled; enabling is
|
|
4
4
|
// just config.
|
|
5
|
-
import { signal, computed, html, mount } from "/volt.js";
|
|
5
|
+
import { signal, computed, effect, html, mount } from "/volt.js";
|
|
6
6
|
|
|
7
7
|
const { available, themes = [], current, defaultPort, configDefaultPort = 5050 } = await (await fetch("/setup/state")).json();
|
|
8
8
|
const depsOf = Object.fromEntries(available.map((a) => [a.name, a.dependsOn || []]));
|
|
@@ -271,6 +271,11 @@ const aiSettings = () =>
|
|
|
271
271
|
|
|
272
272
|
// --- Manage content (a second screen reached via "Manage content →") ---
|
|
273
273
|
const view = signal("config"); // "config" | "manage"
|
|
274
|
+
// Desktop-only config: keep settings readable, but let the editor go wide.
|
|
275
|
+
effect(() => {
|
|
276
|
+
const w = document.getElementById("wrap");
|
|
277
|
+
if (w) w.style.maxWidth = view() === "manage" ? "min(1200px, 95vw)" : "720px";
|
|
278
|
+
});
|
|
274
279
|
// upgrade check: compare bundled version to npm latest; offer a one-click upgrade
|
|
275
280
|
const upgrade = signal(null); // { current, latest, available }
|
|
276
281
|
fetch("/setup/upgrade-check").then((r) => r.json()).then((u) => upgrade(u)).catch(() => {});
|
|
@@ -303,28 +308,28 @@ const items = signal({ pages: [], posts: [] });
|
|
|
303
308
|
const editing = signal(null); // { type, slug, title, isNew } — set only on open/save/close
|
|
304
309
|
let ed = null; // live RTEPro instance for the open editor
|
|
305
310
|
const loadItems = async () => items(await (await fetch("/setup/content")).json());
|
|
306
|
-
// raw .md → { title,
|
|
311
|
+
// raw .md → { title, body, isHtml }; RTEPro takes markdown directly (setMarkdown),
|
|
312
|
+
// so no markdown library is needed.
|
|
307
313
|
function parseDoc(raw) {
|
|
308
314
|
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
309
315
|
const front = fm ? fm[1] : "";
|
|
310
316
|
const title = ((front.match(/^title:\s*(.+)$/m) || [])[1] || "").trim();
|
|
311
|
-
|
|
312
|
-
const bodyHtml = /^format:\s*html\s*$/m.test(front) ? body : window.marked.parse(body);
|
|
313
|
-
return { title, bodyHtml };
|
|
317
|
+
return { title, body: fm ? raw.slice(fm[0].length) : raw, isHtml: /^format:\s*html\s*$/m.test(front) };
|
|
314
318
|
}
|
|
315
|
-
function mountEditor(
|
|
319
|
+
function mountEditor(doc) {
|
|
316
320
|
ed = window.RTEPro.init("#mg-editor", { height: "60vh", placeholder: "Write…" });
|
|
317
|
-
ed.setHTML(
|
|
321
|
+
if (doc && doc.isHtml) ed.setHTML(doc.body || "");
|
|
322
|
+
else ed.setMarkdown((doc && doc.body) || "");
|
|
318
323
|
}
|
|
319
324
|
async function editItem(type, slug) {
|
|
320
325
|
const d = await (await fetch(`/setup/content/raw?type=${type}&slug=${encodeURIComponent(slug)}`)).json();
|
|
321
|
-
const
|
|
322
|
-
editing({ type, slug, title, isNew: false });
|
|
323
|
-
queueMicrotask(() => mountEditor(
|
|
326
|
+
const doc = parseDoc(d.body || "");
|
|
327
|
+
editing({ type, slug, title: doc.title, isNew: false });
|
|
328
|
+
queueMicrotask(() => mountEditor(doc));
|
|
324
329
|
}
|
|
325
330
|
function newItem(type) {
|
|
326
331
|
editing({ type, slug: "", title: "", isNew: true });
|
|
327
|
-
queueMicrotask(() => mountEditor(""));
|
|
332
|
+
queueMicrotask(() => mountEditor({ body: "", isHtml: false }));
|
|
328
333
|
}
|
|
329
334
|
// markdown can't round-trip complex layouts (columns, inline styles, merged cells,
|
|
330
335
|
// embeds) — save those as HTML so they aren't flattened.
|