markdown carta, layout

This commit is contained in:
Torsten Simon 2025-04-30 11:28:52 +02:00
parent d3fb4275ba
commit c51137b59e
6 changed files with 1414 additions and 25 deletions

1343
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,9 @@
"dependencies": {
"@nostr-dev-kit/ndk": "^2.14.5",
"@nostr-dev-kit/ndk-svelte": "^2.4.10",
"carta-md": "^4.9.0",
"daisyui": "^5.0.28",
"dompurify": "^3.2.5",
"qrcode": "^1.5.4"
}
}

View file

@ -1,2 +1,10 @@
@import 'tailwindcss';
@plugin "daisyui";
body, html, body > div {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}

View file

@ -6,7 +6,14 @@
import { ndk, ndkReady, user } from '$lib/stores';
import { writable } from 'svelte/store';
import { login } from '$lib';
import { Carta, Markdown, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify';
// Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input)
let carta = new Carta({
sanitizer: DOMPurify.sanitize
});
let reactions = writable([]);
let reacted = writable(window.localStorage.getItem(event.id));
let reaction = writable({})
@ -47,7 +54,8 @@
</script>
<div class="comment w-full border p-2">
<p>{event.content}</p>
<Markdown value={event.content} {carta} />
<div class="flex gap-2 reactions">
{#if $reacted}
<span>👍 {$reactions.length}</span>

View file

@ -5,8 +5,15 @@
import { writable } from 'svelte/store';
import QRCode from 'qrcode';
import { login } from '$lib';
import { Carta, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify';
let question = '';
// Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input)
let carta = new Carta({
sanitizer: DOMPurify.sanitize
});
let question = writable('');
let questionId = writable(''); ;
let questionShortId = 0;
let qrCodeUrl = writable('');
@ -30,7 +37,7 @@
questionShortId = 10000000 + Math.floor(Math.random() * 90000000);
const event = new NDKEvent($ndk, {
kind: 1342,
content: question,
content: $question,
tags: [['d', questionShortId + '']]
});
await event.publish();
@ -89,22 +96,18 @@
{#key $questionId}
{#if $questionId === ''}
<div>
<textarea
class="mb-4 w-full rounded border p-2"
placeholder="Type your question here..."
bind:value={question}
></textarea>
<button class="btn btn-primary rounded" onclick={postQuestion}> Post Question </button>
<MarkdownEditor bind:value={$question} {carta} />
<button class="btn btn-primary rounded mt-5" onclick={postQuestion}> Post Question </button>
</div>
{:else}
<div class="qr-share mt-4">
<h2 class="text-xl font-bold">Share Your Question</h2>
<h3 class="text-center short-id">{questionShortId}</h3>
<img src={$qrCodeUrl} alt="QR Code" class="mt-2" />
<p class="mb-5 text-center">Share this QR code or link:</p>
<p class="text-center">
<a href={`/q/${$questionId}`}>{`/q/`}<span class="font-bold">{questionShortId}</span></a>
<p class="mb-1 text-center">Share this QR code or link:</p>
<p class="text-center mb-2 text-xl">
<a href={`/q/${$questionId}`}>{`${window.location.origin}/q/`}<span class="font-bold">{questionShortId}</span></a>
</p>
<h3 class="text-center text-xl">{questionShortId}</h3>
<div class="mt-4">
<label for="timer" class="mb-2 block">Set Timer (seconds):</label>
<input type="number" id="timer" class="rounded border p-2" bind:value={timer} />
@ -127,11 +130,24 @@
</div>
<style>
/* Optional styling */
:global(.carta-font-code) {
font-family: 'Monaco', monospace;
font-size: 1.1rem;
line-height: 1.1rem;
letter-spacing: normal;
}
:global(.carta-input) {
height: 150px !important;
}
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.short-id {
font-size: 60px;
}
.qr-share img {
width: 100%;
border: 3px solid #eee;

View file

@ -2,24 +2,28 @@
/** @type {import('./$types').PageProps} */
let { data } = $props();
import { onMount } from 'svelte';
import Comment from '$lib/components/Comment.svelte';
import { ndk, connected, ndkReady, user } from '$lib/stores';
import { ndk, ndkReady } from '$lib/stores';
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { writable } from 'svelte/store';
import { login } from '$lib';
import { Carta, Markdown, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify';
// Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input)
let carta = new Carta({
sanitizer: DOMPurify.sanitize
});
function submitComment() {
const commentEvent = new NDKEvent($ndk, {
kind: 2222,
content: comment,
content: $comment,
tags: [['E', data.id]]
});
commentEvent.publish();
}
let comment = '';
let comment = writable('');
let comments = writable([]);
$effect(() => {
@ -39,14 +43,15 @@
{#await $ndk.fetchEvent(data.id) then question}
{#if question}
<div class="question mb-4 w-full rounded border p-4 text-xl">
<h2>Question:<br />{question.content}</h2>
<h2>Question:<br />
<Markdown {carta} value={question.content} />
</h2>
</div>
<div class="mb-2 flex w-full flex-col items-center justify-center gap-2">
<h1 class="text-xl">Ideensammlung</h1>
<textarea class="w-full border p-2" bind:value={comment} placeholder="Mein Kommentar"
></textarea>
<button class="btn btn-success" onclick={() => submitComment()}>Absenden</button>
<MarkdownEditor bind:value={$comment} {carta} />
<button class="btn btn-primary mb-10" onclick={() => submitComment()}>Absenden</button>
</div>
{:else}
<p>Loading...</p>
@ -64,10 +69,17 @@
</div>
<style>
:global(.carta-input) {
height: 100px !important;
}
:global(.carta-editor) {
width: 100% !important;
}
.main-layout {
padding: 30px;
margin: auto;
width: 100vw;
max-width: 600px;
max-width: 700px;
display: flex;
justify-content: center;
flex-direction: column;