Skip to content

Commit 2d2a1d6

Browse files
authored
Merge pull request #47 from TheDeveloperDen/fix/json-parse-error
feat: add failovers for missing edit/delete tokens
2 parents 18e8a39 + ca5fd28 commit 2d2a1d6

File tree

9 files changed

+813
-112
lines changed

9 files changed

+813
-112
lines changed

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@sveltejs/vite-plugin-svelte": "^6.2.1",
2222
"@tailwindcss/vite": "^4.1.17",
2323
"@types/node": "^25.0.3",
24+
"shiki": "^3.21.0",
2425
"svelte": "^5.43.8",
2526
"svelte-check": "^4.3.4",
2627
"tailwindcss": "^4.1.17",
@@ -50,6 +51,7 @@
5051
"codemirror": "^6.0.2",
5152
"date-fns": "^4.1.0",
5253
"dotenv": "^17.2.3",
54+
"sharp": "^0.34.5",
5355
"thememirror": "^2.0.1"
5456
}
5557
}

frontend/pnpm-lock.yaml

Lines changed: 604 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
onlyBuiltDependencies:
22
- esbuild
3+
- sharp
Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
<script lang="ts">
2-
let data = $props();
3-
4-
let { title, content } = data;
5-
6-
const MAX_LENGTH = 300;
7-
const truncatedContent =
8-
content.length > MAX_LENGTH
9-
? content.substring(0, MAX_LENGTH) + "..."
10-
: content;
2+
let { title = "Untitled.ts" } = $props();
113
</script>
124

13-
<div
14-
class="flex flex-col justify-center items-center w-full relative h-full bg-neutral-900 p-[50px] font-sans"
15-
>
16-
<div class="w-full flex justify-center mb-2">
17-
<h1 class="text-white text-6xl">
18-
{title}
19-
</h1>
20-
</div>
21-
5+
<div class="flex flex-col w-full h-full bg-[#121212] font-sans">
226
<div
23-
class="flex flex-row justify-start items-center w-full overflow-hidden pl-5"
7+
class="flex items-center w-full h-24 px-10 bg-[#252525] border-b border-[#333]"
248
>
25-
<p
26-
class="text-neutral-500 text-3xl text-left leading-tight overflow-hidden"
27-
>
28-
{truncatedContent}
29-
</p>
9+
<div class="w-4 h-4 rounded-full bg-[#ff5f56] mr-2"></div>
10+
<div class="w-4 h-4 rounded-full bg-[#ffbd2e] mr-2"></div>
11+
<div class="w-4 h-4 rounded-full bg-[#27c93f] mr-10"></div>
12+
13+
<span class="text-[#858585] text-2xl tracking-tight">{title}</span>
3014
</div>
3115
</div>

frontend/src/routes/[id]/+page.svelte

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@
4040
<svelte:head>
4141
<title>DevBin | {data.title}</title>
4242
<meta property="og:title" content={`DevBin | ${data.title}`} />
43-
<meta
44-
property="og:image"
45-
content={page.url.origin + `/paste/${page.params.id}/preview.png`}
46-
/>
43+
<meta property="og:image" content="/paste/{page.params.id}/preview.png" />
44+
<meta name="twitter:card" content="summary_large_image" />
4745
</svelte:head>
4846

4947
<div class="flex-col h-full flex">

frontend/src/routes/paste/[id]/+page.server.ts

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,19 @@ import { fail, redirect } from "@sveltejs/kit";
99
export async function load({ params, request, getClientAddress, cookies }) {
1010
const client_ip = getUserIpAddress(request, getClientAddress);
1111
const { id: paste_id } = params;
12+
let tokens: { edit_token: string; delete_token: string } = {
13+
edit_token: "",
14+
delete_token: "",
15+
};
16+
const storedTokens = cookies.get(paste_id);
1217

13-
const tokens: { edit_token: string; delete_token: string } = JSON.parse(
14-
cookies.get(paste_id) || "",
15-
);
18+
if (storedTokens) {
19+
try {
20+
tokens = JSON.parse(cookies.get(paste_id) || "");
21+
} catch (error) {
22+
console.log("Error parsing token cookie:", error);
23+
}
24+
}
1625

1726
try {
1827
const response = await ApiService.getPasteByUuidPastesPasteIdGet({
@@ -61,9 +70,23 @@ export const actions = {
6170
const data = await request.formData();
6271
const paste_id = data.get("id")?.toString() || "";
6372
const paste_content = data.get("content")?.toString() || "";
64-
const tokens: { edit_token: string; delete_token: string } = JSON.parse(
65-
cookies.get(paste_id) || "",
66-
);
73+
let tokens: { edit_token: string; delete_token: string } = {
74+
edit_token: "",
75+
delete_token: "",
76+
};
77+
const storedTokens = cookies.get(paste_id);
78+
79+
if (storedTokens) {
80+
try {
81+
tokens = JSON.parse(cookies.get(paste_id) || "");
82+
} catch (error) {
83+
console.log("Error parsing token cookie:", error);
84+
}
85+
} else {
86+
return fail(400, {
87+
error: "Missing edit token",
88+
});
89+
}
6790

6891
const response = await ApiService.editPastePastesPasteIdPut({
6992
path: {
@@ -89,9 +112,25 @@ export const actions = {
89112
delete: async ({ cookies, request }) => {
90113
const data = await request.formData();
91114
const paste_id = data.get("id")?.toString() || "";
92-
const tokens: { edit_token: string; delete_token: string } = JSON.parse(
93-
cookies.get(paste_id) || "",
94-
);
115+
116+
let tokens: { edit_token: string; delete_token: string } = {
117+
edit_token: "",
118+
delete_token: "",
119+
};
120+
const storedTokens = cookies.get(paste_id);
121+
122+
if (storedTokens) {
123+
try {
124+
tokens = JSON.parse(cookies.get(paste_id) || "");
125+
} catch (error) {
126+
console.log("Error parsing token cookie:", error);
127+
}
128+
} else {
129+
return fail(400, {
130+
error: "Missing delete token",
131+
});
132+
}
133+
95134
const response = await ApiService.deletePastePastesPasteIdDelete({
96135
path: {
97136
paste_id,

frontend/src/routes/paste/[id]/+page.svelte

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
<meta property="og:title" content={`DevBin | ${data.title}`} />
5555
<meta
5656
property="og:image"
57-
content={page.url.origin + `/paste/${page.params.id}/preview.png`}
57+
content={page.url.origin + `/paste/${data.id}/preview.png`}
5858
/>
5959
</svelte:head>
6060

@@ -139,54 +139,56 @@
139139
<Copy />
140140
</div>
141141
</button>
142-
<div class:hidden={!deletePrompt}>
143-
<p>Are you sure you want to delete this paste?</p>
144-
</div>
145-
<div class="flex flex-row gap-2">
146-
<!-- edit actions -->
147-
<button
148-
onclick={() => (isEditing = false)}
149-
class="button-primary"
150-
formaction="?/edit"
151-
class:hidden={!isEditing}
152-
>
153-
Save
154-
</button>
155-
<button
156-
type={"button"}
157-
onclick={() => (isEditing = !isEditing)}
158-
class={`${isEditing ? "button-ghost" : "button-primary"}`}
159-
class:hidden={deletePrompt}
160-
>
161-
{#if isEditing}
162-
Cancel
163-
{:else}
164-
<Edit />
165-
{/if}
166-
</button>
142+
{#if data.edit_token && data.delete_token}
143+
<div class:hidden={!deletePrompt}>
144+
<p>Are you sure you want to delete this paste?</p>
145+
</div>
146+
<div class="flex flex-row gap-2">
147+
<!-- edit actions -->
148+
<button
149+
onclick={() => (isEditing = false)}
150+
class="button-primary"
151+
formaction="?/edit"
152+
class:hidden={!isEditing}
153+
>
154+
Save
155+
</button>
156+
<button
157+
type={"button"}
158+
onclick={() => (isEditing = !isEditing)}
159+
class={`${isEditing ? "button-ghost" : "button-primary"}`}
160+
class:hidden={deletePrompt}
161+
>
162+
{#if isEditing}
163+
Cancel
164+
{:else}
165+
<Edit />
166+
{/if}
167+
</button>
167168

168-
<!-- delete actions -->
169-
<button
170-
onclick={() => (deletePrompt = true)}
171-
class="button-danger"
172-
formaction="?/delete"
173-
class:hidden={!deletePrompt}
174-
>
175-
Confirm
176-
</button>
177-
<button
178-
onclick={() => (deletePrompt = !deletePrompt)}
179-
class={`${deletePrompt ? "button-outline" : "button-danger"}`}
180-
type="button"
181-
class:hidden={isEditing}
182-
>
183-
{#if deletePrompt}
184-
Cancel
185-
{:else}
186-
<Delete />
187-
{/if}
188-
</button>
189-
</div>
169+
<!-- delete actions -->
170+
<button
171+
onclick={() => (deletePrompt = true)}
172+
class="button-danger"
173+
formaction="?/delete"
174+
class:hidden={!deletePrompt}
175+
>
176+
Confirm
177+
</button>
178+
<button
179+
onclick={() => (deletePrompt = !deletePrompt)}
180+
class={`${deletePrompt ? "button-outline" : "button-danger"}`}
181+
type="button"
182+
class:hidden={isEditing}
183+
>
184+
{#if deletePrompt}
185+
Cancel
186+
{:else}
187+
<Delete />
188+
{/if}
189+
</button>
190+
</div>
191+
{/if}
190192
</div>
191193
</div>
192194
<div class="gap-2 text-end mb-2"></div>

0 commit comments

Comments
 (0)