fix(visual-editing): don’t open admin for portableText; simplify starter PT markup (#40)

* fix(visual-editing): PT inline editing; align starter templates

* chore(admin): format router.tsx

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
This commit is contained in:
Hasan Smadi
2026-04-07 00:10:09 +04:00
committed by GitHub
parent ec1e71ec2f
commit dbaf8c6f85
6 changed files with 35 additions and 25 deletions

View File

@@ -688,6 +688,11 @@ export function renderToolbar(config: ToolbarConfig): string {
return f ? f.kind : null;
}
// Load manifest early so the first click can resolve field kinds without racing the event.
if (isEditMode) {
fetchManifest();
}
// Save a single field value
function saveField(collection, id, field, value) {
setSaveState("saving");
@@ -1236,31 +1241,39 @@ export function renderToolbar(config: ToolbarConfig): string {
var ref = target.getAttribute && target.getAttribute("data-emdash-ref");
if (ref) {
e.preventDefault();
e.stopPropagation();
try {
var annotation = JSON.parse(ref);
// Entry-level annotation (no field) — ignore, it's a container
if (!annotation.field) return;
// Entry-level annotation (no field) — keep walking for a field-level ancestor
if (!annotation.field) {
target = target.parentElement;
continue;
}
// Fetch manifest to determine field type, then dispatch
fetchManifest().then(function(manifest) {
var kind = getFieldKind(manifest, annotation.collection, annotation.field);
// Close any open image popover before starting a new edit
function dispatchInline(kind) {
closeImagePopover();
// Portable Text is edited in-page by InlinePortableTextEditor — do not open admin
if (kind === "portableText") {
return;
}
e.preventDefault();
e.stopPropagation();
if (kind === "string" || kind === "text") {
startTextEdit(target, annotation);
} else if (kind === "image") {
startImageEdit(target, annotation);
} else {
// Fallback: open admin for unsupported types
openAdmin(annotation);
}
});
}
if (manifestCache) {
dispatchInline(getFieldKind(manifestCache, annotation.collection, annotation.field));
} else {
fetchManifest().then(function(manifest) {
dispatchInline(getFieldKind(manifest, annotation.collection, annotation.field));
});
}
} catch (err) {
console.error("Failed to parse emdash ref:", err);
}

View File

@@ -61,6 +61,11 @@ describe("renderToolbar", () => {
expect(html).toContain("/_emdash/api/manifest");
});
it("skips toolbar interception for portableText (inline editor)", () => {
const html = renderToolbar({ editMode: true, isPreview: false });
expect(html).toContain("portableText");
});
it("includes entry status badge styles", () => {
const html = renderToolbar({ editMode: true, isPreview: false });
expect(html).toContain("emdash-tb-badge--draft");

View File

@@ -33,8 +33,6 @@ const seo = getSeoMeta(page, {
<article>
<h1 {...page.edit.title}>{page.data.title}</h1>
<div {...page.edit.content}>
<PortableText value={page.data.content} />
</div>
<PortableText value={page.data.content} />
</article>
</Base>

View File

@@ -69,9 +69,7 @@ const categories = await getEntryTerms("posts", post.data.id, "category");
)
}
<div {...post.edit.content}>
<PortableText value={post.data.content} />
</div>
<PortableText value={post.data.content} />
{
tags.length > 0 && (

View File

@@ -33,8 +33,6 @@ const seo = getSeoMeta(page, {
<article>
<h1 {...page.edit.title}>{page.data.title}</h1>
<div {...page.edit.content}>
<PortableText value={page.data.content} />
</div>
<PortableText value={page.data.content} />
</article>
</Base>

View File

@@ -69,9 +69,7 @@ const categories = await getEntryTerms("posts", post.data.id, "category");
)
}
<div {...post.edit.content}>
<PortableText value={post.data.content} />
</div>
<PortableText value={post.data.content} />
{
tags.length > 0 && (