diff --git a/src/routes/(share)/+layout.svelte b/src/routes/(share)/+layout.svelte new file mode 100644 index 0000000..650f9c0 --- /dev/null +++ b/src/routes/(share)/+layout.svelte @@ -0,0 +1,7 @@ + + +
+ {@render children()} +
diff --git a/src/routes/(share)/s/[token]/+page.server.ts b/src/routes/(share)/s/[token]/+page.server.ts new file mode 100644 index 0000000..bae2fee --- /dev/null +++ b/src/routes/(share)/s/[token]/+page.server.ts @@ -0,0 +1,28 @@ +import { error } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types.js'; +import { getSharedNote } from '$lib/server/shares-service.js'; +import { checkIpRateLimit } from '$lib/server/ip-rate-limit.js'; +import { db } from '$lib/server/db/index.js'; + +export const load: PageServerLoad = async ({ params, getClientAddress }) => { + const ip = getClientAddress(); + if (!checkIpRateLimit(ip)) { + throw error(429, 'Too many requests'); + } + + const data = getSharedNote(db, params.token); + if (!data) { + throw error(404, 'This shared note does not exist or has been removed.'); + } + + return { + token: params.token, + title: data.title, + content: data.content, + checklistMode: data.checklistMode, + color: data.color, + attachments: data.attachments, + createdAt: data.createdAt, + updatedAt: data.updatedAt + }; +}; diff --git a/src/routes/(share)/s/[token]/+page.svelte b/src/routes/(share)/s/[token]/+page.svelte new file mode 100644 index 0000000..d7f7d6d --- /dev/null +++ b/src/routes/(share)/s/[token]/+page.svelte @@ -0,0 +1,123 @@ + + + + {data.title || 'Shared Note'} — Crumbs + + + +
+
+
+ {#if data.title} +

+ {data.title} +

+ {/if} + + {#if data.checklistMode && checklistItems.length > 0} +
    + {#each sortedChecklistItems as item} +
  • + + {item.text} +
  • + {/each} +
+ {:else if data.content} +
+ {@html renderedContent} +
+ {/if} + + {#if imageAttachments.length > 0} +
+ {#each imageAttachments as attachment} + {attachment.filename} + {/each} +
+ {/if} +
+ +
+ + {formatDate(data.updatedAt)} + +
+
+ +
+ + POWERED BY CRUMBS + +
+