Replace tiptap with marked + markdown lol

This commit is contained in:
2026-02-03 18:23:15 +13:00
parent ff228befc0
commit af726fc4a0
10 changed files with 39 additions and 66 deletions

View File

@@ -1,5 +0,0 @@
{
"files.associations": {
"*.css": "tailwindcss"
}
}

View File

@@ -40,6 +40,7 @@
"@tiptap/html": "^3.18.0", "@tiptap/html": "^3.18.0",
"@tiptap/pm": "^3.18.0", "@tiptap/pm": "^3.18.0",
"@tiptap/starter-kit": "^3.18.0", "@tiptap/starter-kit": "^3.18.0",
"marked": "^17.0.1",
"postgres": "^3.4.8", "postgres": "^3.4.8",
"tiptap": "^1.32.2" "tiptap": "^1.32.2"
} }

10
pnpm-lock.yaml generated
View File

@@ -32,6 +32,9 @@ importers:
'@tiptap/starter-kit': '@tiptap/starter-kit':
specifier: ^3.18.0 specifier: ^3.18.0
version: 3.18.0 version: 3.18.0
marked:
specifier: ^17.0.1
version: 17.0.1
postgres: postgres:
specifier: ^3.4.8 specifier: ^3.4.8
version: 3.4.8 version: 3.4.8
@@ -1408,6 +1411,11 @@ packages:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true hasBin: true
marked@17.0.1:
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
engines: {node: '>= 20'}
hasBin: true
mdurl@2.0.0: mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
@@ -2698,6 +2706,8 @@ snapshots:
punycode.js: 2.3.1 punycode.js: 2.3.1
uc.micro: 2.1.0 uc.micro: 2.1.0
marked@17.0.1: {}
mdurl@2.0.0: {} mdurl@2.0.0: {}
mini-svg-data-uri@1.4.4: {} mini-svg-data-uri@1.4.4: {}

View File

@@ -9,6 +9,7 @@
let { let {
year = $bindable("2026"), year = $bindable("2026"),
month = $bindable("0"), month = $bindable("0"),
dayClickCallback = $bindable(() => {}),
entries, entries,
} = $props(); } = $props();
@@ -212,11 +213,12 @@
<div class="calendar"> <div class="calendar">
{#each days as day, index} {#each days as day, index}
<div <button
class="day" class="day hover:brightness-80"
class:other-month={!day.isCurrentMonth} class:other-month={!day.isCurrentMonth}
class:today={day.isToday} class:today={day.isToday}
class:has-image={day.entry?.image} class:has-image={day.entry?.image}
onclick={ day.entry ? () => dayClickCallback(day.entry.id) : null }
style={day.entry?.image style={day.entry?.image
? `background-image: url(${day.entry.image}); background-size: cover; background-position: center;` ? `background-image: url(${day.entry.image}); background-size: cover; background-position: center;`
: ""} : ""}
@@ -233,7 +235,7 @@
<span class="entry-indicator"></span> <span class="entry-indicator"></span>
{/if} {/if}
</div> </div>
</div> </button>
{/each} {/each}
</div> </div>
</div> </div>

View File

@@ -39,7 +39,7 @@
<style> <style>
@import 'tailwindcss'; @import 'tailwindcss';
#img-upload-button { /*#img-upload-button {
@apply text-center bg-white/30 h-60 w-full rounded-2xl block hover:text-white/30 transition-all; @apply text-center bg-white/30 h-60 w-full rounded-2xl block hover:text-white/30 transition-all;
} }*/
</style> </style>

View File

@@ -3,17 +3,10 @@
import TextEditor from "./textEditor.svelte"; import TextEditor from "./textEditor.svelte";
import { formatDate } from "$lib/date.ts"; import { formatDate } from "$lib/date.ts";
let { let { entry = $bindable({}) } = $props();
entry = $bindable(""),
editorState = $bindable({ editor: null })
} = $props();
let edit = $state(false); let edit = $state(false);
let editModeText = $derived(edit ? "done" : "edit") let editModeText = $derived(edit ? "done" : "edit")
function getContent() {
return editorState.editor.getJSON();
}
</script> </script>
<div class="flex flex-row mb-2"> <div class="flex flex-row mb-2">
@@ -27,4 +20,4 @@
</div> </div>
<ImageTarget bind:image={entry.image} bind:edit /> <ImageTarget bind:image={entry.image} bind:edit />
<TextEditor bind:content={entry.content} bind:editorState bind:edit /> <TextEditor bind:content={entry.content} bind:edit />

View File

@@ -1,49 +1,20 @@
<script lang="ts"> <script lang="ts">
let { let {
content = $bindable(), content = $bindable(""),
edit = $bindable(false), edit = $bindable(false),
editorState = $bindable({ editor: null }),
} = $props(); } = $props();
import { onMount, onDestroy } from "svelte"; import { marked } from "marked";
import { Editor } from "@tiptap/core";
import { StarterKit } from "@tiptap/starter-kit";
let element = $state();
onMount(() => {
editorState.editor = new Editor({
element: element,
editable: edit,
extensions: [StarterKit],
content: content,
onTransaction: ({ editor }) => {
// Update the state signal to force a re-render
editorState = { editor };
},
});
});
onDestroy(() => {
editorState.editor?.destroy();
});
$effect(() => editorState.editor.setOptions({ editable: edit }));
</script> </script>
<div class="bg-white/20 rounded-2xl p-2 mt-4"> <div class="bg-white/20 min-h-30 rounded-2xl p-2 mt-4">
<div {#if edit}
class="bg-white/10 rounded-xl p-2 text-white/90" <textarea
bind:this={element} class="w-full min-h-30 border-none bg-white/10 rounded-xl p-2"
></div> bind:value={content}
></textarea>
{:else}
{@html marked(content)}
{/if}
<!-- <div class="bg-white/10 rounded-xl p-2 text-white/90"></div> -->
</div> </div>
<style>
button.active {
background: black;
color: white;
}
:global(.tiptap) {
min-height: 240px;
}
</style>

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { generateHTML } from "@tiptap/html"; import { generateHTML } from "@tiptap/html";
import { marked } from 'marked';
import { StarterKit } from "@tiptap/starter-kit"; import { StarterKit } from "@tiptap/starter-kit";
import { formatDate } from "$lib/date.ts"; import { formatDate } from "$lib/date.ts";
@@ -12,7 +13,7 @@
<div class="flex flex-row"> <div class="flex flex-row">
<div> <div>
<p class="text-sm text-white/60">{formattedDate}</p> <p class="text-sm text-white/60">{formattedDate}</p>
{@html generateHTML(entry.content, [StarterKit])} {@html marked(entry.content)}
</div> </div>
<img <img
class="max-h-30 min-h-15 max-w-1/2 rounded-xl object-cover ml-auto" class="max-h-30 min-h-15 max-w-1/2 rounded-xl object-cover ml-auto"

View File

@@ -4,6 +4,6 @@ export const entryTable = pgTable("entries", {
id: integer().primaryKey().generatedAlwaysAsIdentity(), id: integer().primaryKey().generatedAlwaysAsIdentity(),
date: timestamp({ mode: 'date', withTimezone: true }).notNull().defaultNow(), date: timestamp({ mode: 'date', withTimezone: true }).notNull().defaultNow(),
location: json(), location: json(),
content: json(), content: text(),
image: text() image: text()
}); });

View File

@@ -9,21 +9,21 @@
let edit = $state(false) let edit = $state(false)
let selectedEntry = $state() let selectedEntry = $state('')
let selectEntry = async (entryID) => { let selectEntry = async (entryID: string) => {
const res = await fetch(`/api/entry?id=${entryID}`) const res = await fetch(`/api/entry?id=${entryID}`)
selectedEntry = await res.json() selectedEntry = await res.json()
} }
</script> </script>
<Calendar entries={data.all} /> <Calendar entries={data.all} dayClickCallback={async (entryID: string) => await selectEntry(entryID)} />
<div class="flex flex-col md:flex-row space-y-4 w-full mt-6"> <div class="flex flex-col md:flex-row space-y-4 w-full mt-6">
<div class="md:w-1/2 md:order-2"> <div class="md:w-1/2 md:order-2">
{#if selectedEntry} {#if selectedEntry}
<Editor bind:edit bind:entry={selectedEntry} /> <Editor bind:entry={selectedEntry} />
{:else} {:else}
<div class="md:flex flex-col items-center justify-center mx-5 hidden"> <div class="md:flex flex-col items-center justify-center mx-5 hidden">
<p class="text-white/60">Select an entry to view/edit</p> <p class="text-white/60">Select an entry to view/edit</p>