mirror of
https://github.com/thiloho/archtika.git
synced 2025-12-24 07:23:35 +01:00
Refactor web app code and add background color setting
This commit is contained in:
72
web-app/src/lib/components/MarkdownEditor.svelte
Normal file
72
web-app/src/lib/components/MarkdownEditor.svelte
Normal file
@@ -0,0 +1,72 @@
|
||||
<script lang="ts">
|
||||
import { deserialize, applyAction } from "$app/forms";
|
||||
import { textareaScrollTop, previewContent } from "$lib/runes.svelte";
|
||||
|
||||
const {
|
||||
apiPrefix,
|
||||
label,
|
||||
name,
|
||||
content
|
||||
}: { apiPrefix: string; label: string; name: string; content: string } = $props();
|
||||
|
||||
let mainContentTextarea: HTMLTextAreaElement;
|
||||
|
||||
const updateScrollPercentage = () => {
|
||||
const { scrollTop, scrollHeight, clientHeight } = mainContentTextarea;
|
||||
textareaScrollTop.value = (scrollTop / (scrollHeight - clientHeight)) * 100;
|
||||
};
|
||||
|
||||
const handleImagePaste = async (event: ClipboardEvent) => {
|
||||
const clipboardItems = Array.from(event.clipboardData?.items ?? []);
|
||||
const file = clipboardItems.find((item) => item.type.startsWith("image/"));
|
||||
|
||||
if (!file) return null;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const fileObject = file.getAsFile();
|
||||
|
||||
if (!fileObject) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("file", fileObject);
|
||||
|
||||
const request = await fetch("?/pasteImage", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = deserialize(await request.clone().text());
|
||||
applyAction(result);
|
||||
|
||||
const response = await request.json();
|
||||
|
||||
if (JSON.parse(response.data)[1]) {
|
||||
const fileId = JSON.parse(response.data)[4];
|
||||
const fileUrl = `${apiPrefix}/rpc/retrieve_file?id=${fileId}`;
|
||||
|
||||
const target = event.target as HTMLTextAreaElement;
|
||||
const newContent =
|
||||
target.value.slice(0, target.selectionStart) +
|
||||
`` +
|
||||
target.value.slice(target.selectionStart);
|
||||
|
||||
previewContent.value = newContent;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<label>
|
||||
{label}:
|
||||
<textarea
|
||||
{name}
|
||||
rows="20"
|
||||
bind:value={previewContent.value}
|
||||
bind:this={mainContentTextarea}
|
||||
onscroll={updateScrollPercentage}
|
||||
onpaste={handleImagePaste}
|
||||
required>{content}</textarea
|
||||
>
|
||||
</label>
|
||||
@@ -2,30 +2,27 @@
|
||||
import type { Snippet } from "svelte";
|
||||
import { md } from "$lib/utils";
|
||||
import { page } from "$app/stores";
|
||||
import { previewContent, textareaScrollTop } from "$lib/runes.svelte";
|
||||
|
||||
const {
|
||||
id,
|
||||
contentType,
|
||||
title,
|
||||
children,
|
||||
fullPreview = false,
|
||||
previewContent,
|
||||
previewScrollTop = 0
|
||||
fullPreview = false
|
||||
}: {
|
||||
id: string;
|
||||
contentType: string;
|
||||
title: string;
|
||||
children: Snippet;
|
||||
fullPreview?: boolean;
|
||||
previewContent: string;
|
||||
previewScrollTop?: number;
|
||||
} = $props();
|
||||
|
||||
let previewElement: HTMLDivElement;
|
||||
|
||||
$effect(() => {
|
||||
const scrollHeight = previewElement.scrollHeight - previewElement.clientHeight;
|
||||
previewElement.scrollTop = (previewScrollTop / 100) * scrollHeight;
|
||||
previewElement.scrollTop = (textareaScrollTop.value / 100) * scrollHeight;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -66,9 +63,9 @@
|
||||
|
||||
<div class="preview" bind:this={previewElement}>
|
||||
{#if fullPreview}
|
||||
<iframe src={previewContent} title="Preview"></iframe>
|
||||
<iframe src={previewContent.value} title="Preview"></iframe>
|
||||
{:else}
|
||||
{@html md(previewContent, Object.keys($page.params).length > 1 ? true : false)}
|
||||
{@html md(previewContent.value, Object.keys($page.params).length > 1 ? true : false)}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user