diff --git a/src/lib/components/Comments.svelte b/src/lib/components/Comments.svelte index 0446682..672174d 100644 --- a/src/lib/components/Comments.svelte +++ b/src/lib/components/Comments.svelte @@ -400,8 +400,8 @@ {:else} {#if topLevel.length === 0} -
- +
+

{t(T.comments_empty)}

{:else} diff --git a/src/lib/components/PostActions.svelte b/src/lib/components/PostActions.svelte index 9b28a60..6e12a8f 100644 --- a/src/lib/components/PostActions.svelte +++ b/src/lib/components/PostActions.svelte @@ -64,7 +64,9 @@ }); function onCommentClick(e: MouseEvent) { - const el = document.getElementById(commentTargetId) as HTMLDetailsElement | null; + const el = document.getElementById( + commentTargetId, + ) as HTMLDetailsElement | null; if (!el) return; e.preventDefault(); el.open = true; @@ -76,6 +78,17 @@ let copyTimer: ReturnType | null = null; let shareTimer: ReturnType | null = null; + // Share button only renders when the browser actually has a native share- + // sheet — otherwise it would just be a duplicate of "Link kopieren". + // SSR has no `navigator`, so this stays false until client mount. + let canShare = $state(false); + $effect(() => { + canShare = + typeof navigator !== "undefined" && + typeof (navigator as Navigator & { share?: unknown }).share === + "function"; + }); + function flashCopied() { copied = true; if (copyTimer) clearTimeout(copyTimer); @@ -110,17 +123,16 @@ } async function share() { - const w = window as unknown as { navigator: Navigator & { share?: (data: ShareData) => Promise } }; - if (typeof w.navigator.share === "function") { - try { - await w.navigator.share({ title, url }); - flashShared(); - return; - } catch { - // user cancelled or share failed → fall through to copy - } + const nav = navigator as Navigator & { + share?: (data: ShareData) => Promise; + }; + if (typeof nav.share !== "function") return; + try { + await nav.share({ title, url }); + flashShared(); + } catch { + // user cancelled — no fallback, copy-link button covers that case } - await copyLink(); } function print() { @@ -128,56 +140,71 @@ } -
+ +
{#if commentPageId} - + {commentCount ?? "…"} {/if} - - - - - +
+ {#if canShare} + + {/if} + + +
{#if readingTimeMinutes != null && readingTimeMinutes > 0} - - {t(T.post_action_reading_time, { minutes: readingTimeMinutes })} + + {t(T.post_action_reading_time, { minutes: readingTimeMinutes })} {/if}
diff --git a/src/routes/post/[slug]/+page.server.ts b/src/routes/post/[slug]/+page.server.ts index 21e523c..7452ce8 100644 --- a/src/routes/post/[slug]/+page.server.ts +++ b/src/routes/post/[slug]/+page.server.ts @@ -237,10 +237,36 @@ export const load: PageServerLoad = async ({ params, locals, url, setHeaders }) } // Reading-time estimate. ~200 words per minute for German non-fiction. - // Strips HTML tags, then counts whitespace-separated tokens. Includes only - // the prose body (headline + content); rows aren't part of the prose flow. + // Pulls text from headline + body markdown AND from referenced row blocks + // (Termin-Posts have an empty body; their text lives in row1Content + // markdown/text references). Walks the post tree once, collecting any + // `content` / `body` / `text` string fields below row*Content. HTML tags + // get stripped before the word count. const readingTimeMinutes = (() => { - const plain = (contentHeadlineHtml + " " + contentBodyHtml) + const parts: string[] = [contentHeadlineHtml, contentBodyHtml]; + const collect = (node: unknown) => { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (const item of node) collect(item); + return; + } + const obj = node as Record; + for (const [key, value] of Object.entries(obj)) { + if (typeof value === "string") { + if (key === "content" || key === "body" || key === "text") { + parts.push(value); + } + } else { + collect(value); + } + } + }; + collect((post as { row1Content?: unknown }).row1Content); + collect((post as { row2Content?: unknown }).row2Content); + collect((post as { row3Content?: unknown }).row3Content); + + const plain = parts + .join(" ") .replace(/<[^>]+>/g, " ") .replace(/\s+/g, " ") .trim(); diff --git a/src/routes/post/[slug]/+page.svelte b/src/routes/post/[slug]/+page.svelte index e2b2bca..40d11ed 100644 --- a/src/routes/post/[slug]/+page.svelte +++ b/src/routes/post/[slug]/+page.svelte @@ -24,10 +24,10 @@ {/if} -
+
{#if data.rawPostImageUrl}
{:else if data.postImageUrl}
{/if} -
- {#if data.postDate || data.commentPageId} -
- {#if data.postDate} - - {/if} + + +
+ {#if data.postDate} +
+
{/if} -
- -
+ {#if (data.post.postTag ?? []).length > 0} +
+ +
+ {/if} +
-
- -