UNPKG

@druid-sh/sdk

Version:

Druid.sh SDK for rendering blog content with SSR support

149 lines (148 loc) 9.58 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlogPost = BlogPost; const html_react_parser_1 = __importStar(require("html-react-parser")); const image_1 = __importDefault(require("next/image")); const link_1 = __importDefault(require("next/link")); const react_1 = __importDefault(require("react")); const CopyButton_1 = __importDefault(require("./CopyButton")); const isInternalLink = (href) => { return (href.startsWith("/") || href.startsWith("#") || (!href.startsWith("http://") && !href.startsWith("https://"))); }; async function BlogPost({ data }) { const { post, basePath } = data; if (!post) { return (react_1.default.createElement("div", { className: "flex h-screen items-center justify-center" }, "Post not found")); } const formattedDate = new Date(post.publishedAt).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", }); return (react_1.default.createElement("div", null, react_1.default.createElement("div", { className: "max-w-6xl mx-auto mb-8" }, react_1.default.createElement(link_1.default, { href: basePath, className: "inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors" }, react_1.default.createElement("span", null, "\u2190 Back to Blog"))), react_1.default.createElement("article", { className: "max-w-3xl mx-auto" }, react_1.default.createElement("header", { className: "mb-8 border-b pb-8" }, react_1.default.createElement("h1", { className: "text-3xl font-extrabold tracking-tight sm:text-4xl md:text-5xl text-foreground" }, post.title), react_1.default.createElement("div", { className: "mt-6 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-muted-foreground" }, react_1.default.createElement("div", { className: "flex items-center gap-2" }, post.author.avatar && (react_1.default.createElement(image_1.default, { src: post.author.avatar, alt: post.author.name, width: 28, height: 28, className: "rounded-full" })), react_1.default.createElement("span", { className: "font-medium text-foreground" }, post.author.name)), react_1.default.createElement("span", null, "\u2022"), react_1.default.createElement("time", { dateTime: post.publishedAt }, formattedDate)), react_1.default.createElement("div", { className: "mt-6 flex flex-wrap gap-2" }, post.tags.map((tag) => (react_1.default.createElement(link_1.default, { key: tag.slug, href: `${basePath}/tag/${tag.slug}`, className: "inline-block rounded-full bg-secondary px-3 py-1 text-xs font-semibold text-secondary-foreground transition-colors hover:bg-secondary/80" }, "#", tag.name))))), post.coverImage && (react_1.default.createElement("div", { className: "my-8" }, react_1.default.createElement(image_1.default, { src: post.coverImage, alt: post.title, width: 1200, height: 600, sizes: "(max-width: 800px) 100vw, 800px", className: "w-full h-auto object-cover rounded-lg border", priority: true }))), react_1.default.createElement("div", { className: "prose prose-lg dark:prose-invert max-w-none \n prose-headings:font-bold prose-headings:tracking-tight \n prose-a:text-primary prose-a:no-underline hover:prose-a:underline\n prose-blockquote:border-l-primary\n prose-img:rounded-lg prose-img:border" }, (0, html_react_parser_1.default)(post.content, { replace: (domNode) => { var _a, _b; // Only process element nodes, not text nodes or other types if (domNode.type !== "tag") { return; } if (domNode.name === "img") { const { src, alt, width, height } = domNode.attribs || {}; return (react_1.default.createElement(image_1.default, { key: src, src: src, alt: alt || "", width: width ? parseInt(width) : 800, height: height ? parseInt(height) : 600, sizes: "(max-width: 768px) 100vw, 700px", className: "w-full h-auto object-cover rounded-lg border" })); } else if (domNode.name === "a") { const _c = domNode.attribs || {}, { href, target, rel } = _c, otherAttribs = __rest(_c, ["href", "target", "rel"]); if (!href) { return; } const children = domNode.children ? (0, html_react_parser_1.domToReact)(domNode.children) : null; if (isInternalLink(href)) { return (react_1.default.createElement(link_1.default, Object.assign({ key: href, href: href }, otherAttribs), children)); } else { return (react_1.default.createElement("a", Object.assign({ key: href, href: href, target: target || "_blank", rel: rel || "noopener noreferrer" }, otherAttribs), children)); } } else if (domNode.name === "pre") { // const hasCodeBlock = domNode.children?.some( // (child: any) => // child.type === "tag" && // child.name === "code" && // child.attribs?.class?.includes("language-") // ); // if (hasCodeBlock) { const codeElement = (_a = domNode.children) === null || _a === void 0 ? void 0 : _a.find((child) => child.type === "tag" && child.name === "code"); const getTextContent = (node) => { if (node.type === "text") { return node.data || ""; } if (node.children) { return node.children.map(getTextContent).join(""); } return ""; }; const codeText = codeElement ? getTextContent(codeElement) : ""; const existingClass = ((_b = domNode.attribs) === null || _b === void 0 ? void 0 : _b.class) || ""; const newClass = existingClass.includes("hljs") ? existingClass : `${existingClass} hljs border`.trim(); return (react_1.default.createElement("div", { className: "relative group" }, react_1.default.createElement("pre", Object.assign({}, domNode.attribs, { className: newClass }), (0, html_react_parser_1.domToReact)(domNode.children)), react_1.default.createElement("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity" }, react_1.default.createElement(CopyButton_1.default, { text: codeText })))); // } } // For all other elements, let html-react-parser handle them normally return; }, }))))); }