Files
emdash-patch-imageupload/demos/plugins-demo/src/pages/posts/[slug].astro
kunthawat 2d1be52177 Emdash source with visual editor image upload fix
Fixes:
1. media.ts: wrap placeholder generation in try-catch
2. toolbar.ts: check r.ok, display error message in popover
2026-05-03 10:44:54 +07:00

177 lines
3.5 KiB
Plaintext

---
/**
* Individual post page with PortableText rendering
*
* This demonstrates the embeds plugin auto-registering components
* for YouTube, Vimeo, etc. with the PortableText renderer.
*/
import { getEmDashEntry, decodeSlug } from "emdash";
import { PortableText } from "emdash/ui";
import { embedComponents } from "@emdash-cms/plugin-embeds/astro";
const slug = decodeSlug(Astro.params.slug);
const { entry: post } = slug
? await getEmDashEntry("posts", slug)
: { entry: null };
if (!post) {
return Astro.redirect("/404");
}
const title = post.data.title;
const content = post.data.content;
const metaDescription = post.data.excerpt;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title || "Post"} - EmDash Plugins Demo</title>
{metaDescription && <meta name="description" content={metaDescription} />}
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family:
system-ui,
-apple-system,
sans-serif;
line-height: 1.6;
color: #1a1a1a;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
}
.meta {
font-size: 0.875rem;
color: #6b7280;
margin-bottom: 2rem;
}
.back {
display: inline-block;
margin-bottom: 1rem;
color: #2563eb;
}
/* Content styles */
.content {
margin-top: 2rem;
}
.content h1 {
font-size: 1.75rem;
margin-top: 2rem;
margin-bottom: 1rem;
}
.content h2 {
font-size: 1.5rem;
margin-top: 2rem;
margin-bottom: 1rem;
}
.content h3 {
font-size: 1.25rem;
margin-top: 1.5rem;
margin-bottom: 0.75rem;
}
.content p {
margin-bottom: 1rem;
}
.content ul,
.content ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
}
.content li {
margin-bottom: 0.5rem;
}
.content blockquote {
border-left: 4px solid #e5e7eb;
padding-left: 1rem;
margin: 1rem 0;
color: #4b5563;
font-style: italic;
}
.content pre {
background: #f3f4f6;
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin: 1rem 0;
}
.content code {
background: #f3f4f6;
padding: 0.125rem 0.375rem;
border-radius: 4px;
font-size: 0.875em;
}
.content pre code {
background: none;
padding: 0;
}
.content img {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 1rem 0;
}
.content a {
color: #2563eb;
}
/* Embed styles */
.content iframe {
max-width: 100%;
border-radius: 8px;
margin: 1rem 0;
}
footer {
margin-top: 3rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
font-size: 0.875rem;
}
footer a {
color: #2563eb;
}
</style>
</head>
<body>
<a href="/posts" class="back">&larr; Back to posts</a>
<article>
<h1>{title || "Untitled"}</h1>
<div class="meta">
{post.data.status === "draft" && <span>Draft</span>}
</div>
<div class="content">
{
Array.isArray(content) && content.length > 0 ? (
<PortableText
value={content}
components={{ type: embedComponents }}
/>
) : typeof content === "string" && content ? (
<p>{content}</p>
) : (
<p style="color: #6b7280; font-style: italic;">No content yet.</p>
)
}
</div>
</article>
<footer>
<a href={`/_emdash/admin/content/posts/${post.id}`}>Edit in Admin</a>
</footer>
</body>
</html>