diff --git a/src/lib/components/blog/breadcrumbs.svelte b/src/lib/components/blog/breadcrumbs.svelte new file mode 100644 index 000000000..85ebd9ac0 --- /dev/null +++ b/src/lib/components/blog/breadcrumbs.svelte @@ -0,0 +1,9 @@ + + +
+ Blog + / + {title} +
diff --git a/src/lib/components/blog/post-meta.svelte b/src/lib/components/blog/post-meta.svelte new file mode 100644 index 000000000..1d6539251 --- /dev/null +++ b/src/lib/components/blog/post-meta.svelte @@ -0,0 +1,93 @@ + + +
+
+
+ + + {#if timeToRead} + {timeToRead} min + {/if} +
+

+ {title} +

+ {#if description} +

+ {description} +

+ {/if} +
+ +
+ {#if authorData} + + {#if authorData.avatar} + {authorData.name} + {/if} +
+

+ {authorData.name} +

+

{authorData.role}

+
+
+ {/if} + +
+ SHARE + +
    + {#each socialSharingOptions as sharingOption} +
  • + {#if sharingOption.type === 'link'} + + + {:else} + + {/if} +
  • + {/each} +
+
+
+
diff --git a/src/lib/components/blog/table-of-contents.svelte b/src/lib/components/blog/table-of-contents.svelte new file mode 100644 index 000000000..ef5d3c354 --- /dev/null +++ b/src/lib/components/blog/table-of-contents.svelte @@ -0,0 +1,49 @@ + + + + + diff --git a/src/lib/utils/copy.ts b/src/lib/utils/copy.ts index 3b8ba9401..907f33d62 100644 --- a/src/lib/utils/copy.ts +++ b/src/lib/utils/copy.ts @@ -1,47 +1,11 @@ import { writable } from 'svelte/store'; +import { tryCatch } from './try-catch'; -async function securedCopy(value: string) { - try { - await navigator.clipboard.writeText(value); - } catch { - return false; - } +export const copyToClipboard = async (value: string) => { + const { data } = await tryCatch(navigator.clipboard.writeText(value)); - return true; -} - -function unsecuredCopy(value: string) { - const textArea = document.createElement('textarea'); - textArea.value = value; - - // Avoid scrolling to bottom - textArea.style.top = '0'; - textArea.style.left = '0'; - textArea.style.position = 'fixed'; - - document.body.appendChild(textArea); - textArea.focus(); - textArea.select(); - - let success = true; - try { - document.execCommand('copy'); - } catch { - success = false; - } finally { - document.body.removeChild(textArea); - } - - return success; -} - -export async function copy(value: string) { - // securedCopy works only in HTTPS environment. - // unsecuredCopy works in HTTP and only runs if securedCopy fails. - const success = (await securedCopy(value)) || unsecuredCopy(value); - - return success; -} + return data; +}; export function createCopy(value: string) { const copied = writable(false); @@ -50,7 +14,7 @@ export function createCopy(value: string) { function handleCopy() { if (timeout) clearTimeout(timeout); copied.set(true); - copy(value); + copyToClipboard(value); timeout = setTimeout(() => copied.set(false), 1000); } @@ -59,3 +23,23 @@ export function createCopy(value: string) { copy: handleCopy }; } + +export const handleCopy = (value: string, duration: number = 1000) => { + const copied = writable(false); + let timeout: ReturnType | undefined = undefined; + + const copy = () => { + if (timeout) clearTimeout(timeout); + copied.set(true); + copyToClipboard(value); + timeout = setTimeout(() => copied.set(false), duration); + }; + + return { + copied, + copy + }; +}; + +// backward compatibility +export { copyToClipboard as copy }; diff --git a/src/lib/utils/date.ts b/src/lib/utils/date.ts index 4dfea9fbf..56147eda2 100644 --- a/src/lib/utils/date.ts +++ b/src/lib/utils/date.ts @@ -1,9 +1,9 @@ +import { format } from 'date-fns'; + export const formatDate = (date: string | Date | number): string => { const dt = new Date(date); - const month = dt.toLocaleString('en-US', { month: 'short' }); - const day = dt.getDate(); - const year = dt.getFullYear(); - return `${month} ${day}, ${year}`; + + return format(dt, 'MMMM d, yyyy'); }; export const addDays = (date: Date, days: number) => { diff --git a/src/lib/utils/try-catch.ts b/src/lib/utils/try-catch.ts new file mode 100644 index 000000000..6773a787a --- /dev/null +++ b/src/lib/utils/try-catch.ts @@ -0,0 +1,20 @@ +type Success = { + data: T; + error: null; +}; + +type Failure = { + data: null; + error: E; +}; + +type Result = Success | Failure; + +export const tryCatch = async (promise: Promise): Promise> => { + try { + const data = await promise; + return { data, error: null }; + } catch (error) { + return { data: null, error: error as E }; + } +}; diff --git a/src/markdoc/layouts/Post.svelte b/src/markdoc/layouts/Post.svelte index a2aa26034..04bd744cf 100644 --- a/src/markdoc/layouts/Post.svelte +++ b/src/markdoc/layouts/Post.svelte @@ -1,6 +1,5 @@ @@ -109,150 +85,40 @@
-
{ - readPercentage = e.detail.percentage; - }} - > -
-
-
-
-
-
- - - -

- {title} -

- {#if description} -

- {description} -

- {/if} - {#if authorData} - - {/if} - - -
- {#if cover} -
- -
- {/if} - -
- {#if lastUpdated} - - Updated: - - - {/if} - - -
-
- - -
- {#if typeof callToAction === 'boolean'} - - {:else if typeof callToAction === 'object'} - +
+
+ +
+
+ + {#if cover} +
+ +
{/if} + +
+ {#if lastUpdated} + + Updated: + + + {/if} + + +
-
+ + +
+ {#if typeof callToAction === 'boolean'} + + {:else if typeof callToAction === 'object'} + + {/if}
@@ -288,43 +154,3 @@
- -
- - diff --git a/src/markdoc/nodes/Heading.svelte b/src/markdoc/nodes/Heading.svelte index 9ff3a7994..5c2507acd 100644 --- a/src/markdoc/nodes/Heading.svelte +++ b/src/markdoc/nodes/Heading.svelte @@ -11,8 +11,8 @@ const tag = `h${level + 1}`; const ctx = hasContext('headings') ? getContext('headings') : undefined; const classList: Record = { - 1: 'text-label mb-4', - 2: 'text-description mb-4', + 1: 'text-description mb-4', + 2: 'text-description text-primary mb-4', 3: 'text-body font-medium mb-4', 4: 'text-sub-body font-medium' }; @@ -24,6 +24,8 @@ return; } + console.log(element.textContent); + $ctx = { ...$ctx, [id]: { @@ -40,6 +42,7 @@ } }); }; + const observer = new IntersectionObserver(callback, { root: null, threshold: 1 @@ -60,7 +63,7 @@ bind:this={element} class:web-snap-location={id && !inReferences} class:web-snap-location-references={id && inReferences} - class="{headingClass} text-primary" + class="{headingClass} text-primary font-medium" > @@ -68,7 +71,7 @@