icon und menu update

This commit is contained in:
beo3000 2026-03-02 20:59:57 +01:00
parent 3a4fc0e8e0
commit cf220dd3a0
14 changed files with 13225 additions and 89 deletions

View File

@ -1 +1 @@
1.2.14
1.2.17

View File

@ -25,6 +25,7 @@
"dexie": "^4.0.11",
"dompurify": "^3.3.1",
"highlight.js": "^11.11.1",
"lucide-svelte": "^0.576.0",
"marked": "^17.0.3",
"tiptap-markdown": "^0.9.0"
},

View File

@ -2,6 +2,8 @@
import { page } from "$app/state";
import { goto } from "$app/navigation";
import { commandBarOpen } from "$lib/stores/commandBar";
import { LayoutList, CalendarRange, FolderOpen, BookOpen, Search, Menu } from "lucide-svelte";
import type { Component } from "svelte";
interface Props {
onsidebaropen: () => void;
@ -13,7 +15,8 @@
interface Tab {
id: string;
label: string;
icon: string;
icon: Component;
color: string;
action: () => void;
active: boolean;
}
@ -22,42 +25,48 @@
{
id: "daily",
label: "Daily Log",
icon: "📋",
icon: LayoutList,
color: "text-slate-400",
action: () => goto("/context/daily-log"),
active: currentPath === "/context/daily-log" || currentPath === "/",
},
{
id: "meetings",
label: "Meetings",
icon: "👥",
icon: CalendarRange,
color: "text-violet-400",
action: () => goto("/meetings"),
active: currentPath === "/meetings",
},
{
id: "projects",
label: "Projekte",
icon: "📁",
icon: FolderOpen,
color: "text-amber-400",
action: () => goto("/projects"),
active: currentPath === "/projects",
},
{
id: "wiki",
label: "Wiki",
icon: "📖",
icon: BookOpen,
color: "text-orange-400",
action: () => goto("/wiki"),
active: currentPath.startsWith("/wiki"),
},
{
id: "search",
label: "Suche",
icon: "🔍",
icon: Search,
color: "text-muted",
action: () => ($commandBarOpen = true),
active: false,
},
{
id: "more",
label: "Mehr",
icon: "☰",
icon: Menu,
color: "text-muted",
action: () => onsidebaropen(),
active: false,
},
@ -69,12 +78,13 @@
style="padding-bottom: env(safe-area-inset-bottom, 0px);"
>
{#each tabs as tab}
{@const Icon = tab.icon}
<button
class="flex flex-1 flex-col items-center gap-0.5 py-2.5 text-xs transition-colors
{tab.active ? 'text-accent' : 'text-muted'}"
class="flex flex-1 flex-col items-center justify-center gap-1 py-2.5 min-h-[52px] text-xs transition-colors
{tab.active ? tab.color + ' font-medium' : 'text-muted'}"
onclick={tab.action}
>
<span class="text-lg leading-none">{tab.icon}</span>
<Icon size={22} />
<span>{tab.label}</span>
</button>
{/each}

View File

@ -8,6 +8,7 @@
import { updateEvent, updateEventNotes, softDeleteContext } from '$lib/db/repositories';
import { notesTopicId } from '$lib/db/repositories';
import { mention } from '$lib/actions/mention';
import { Pencil, Trash2 } from 'lucide-svelte';
import { handlePersonClick } from '$lib/actions/refClick';
import { goto } from '$app/navigation';
@ -179,8 +180,8 @@
</div>
</div>
<div class="flex gap-1 opacity-0 transition-opacity group-hover:opacity-100">
<button class="rounded p-1 text-muted hover:text-white" onclick={(e) => { e.stopPropagation(); startEditMeta(); }} title="Bearbeiten">✏️</button>
<button class="rounded p-1 text-muted hover:text-red-400" onclick={(e) => { e.stopPropagation(); handleDelete(); }} title="Löschen">🗑️</button>
<button class="rounded p-1 text-muted hover:text-white" onclick={(e) => { e.stopPropagation(); startEditMeta(); }} title="Bearbeiten"><Pencil size={14} /></button>
<button class="rounded p-1 text-muted hover:text-red-400" onclick={(e) => { e.stopPropagation(); handleDelete(); }} title="Löschen"><Trash2 size={14} /></button>
</div>
</div>
{/if}

View File

@ -11,6 +11,11 @@
import { deletedItemCount } from '$lib/stores/agenda';
import { favoriteNotebooks } from '$lib/stores/wiki';
import { scopeColor, scopeIcon } from '$lib/stores/scopeContext';
import {
CalendarDays, CalendarRange, Users, FolderOpen, Building2, User, BookOpen,
LayoutList, Archive, Trash2, Settings, HardDrive, LogOut,
ChevronDown, Home, RefreshCw
} from 'lucide-svelte';
const isDev = import.meta.env.DEV;
const trashCount$ = deletedItemCount();
@ -55,14 +60,14 @@
// Active nav item style: subtle left border indicator
function navItem(active: boolean) {
return active
? 'mb-1 w-full rounded-r px-2.5 py-2 text-left text-sm border-l-2 border-accent bg-white/8 font-semibold text-white'
: 'mb-1 w-full rounded px-2.5 py-2 text-left text-sm border-l-2 border-transparent text-[#aaa] hover:bg-white/5 hover:text-white transition-colors';
? 'mb-1 w-full rounded-r px-3 py-2.5 text-left text-sm border-l-2 border-accent bg-white/10 font-semibold text-white'
: 'mb-1 w-full rounded px-3 py-2.5 text-left text-sm border-l-2 border-transparent text-[#aaa] hover:bg-white/5 hover:text-white transition-colors';
}
// Section header: ▼ toggle (small) + label (navigates to overview)
const sectionHeader = 'flex items-center gap-2 mt-6 mb-1 pl-1 pr-1';
const sectionToggle = 'text-[10px] text-muted hover:text-white transition-colors flex-shrink-0 px-1 py-1';
const sectionLabel = 'text-xs uppercase text-muted hover:text-white flex items-center gap-1.5 transition-colors flex-1 text-left font-medium tracking-wide';
const sectionToggle = 'text-xs text-muted hover:text-white transition-colors flex-shrink-0 px-2 py-1.5';
const sectionLabel = 'text-sm text-muted hover:text-white flex items-center gap-1.5 transition-colors flex-1 text-left font-semibold';
</script>
{#if !hideLogo}
@ -74,21 +79,25 @@
{/if}
<!-- General -->
<div class="mb-1 mt-6 pl-1 text-xs uppercase text-muted flex items-center gap-1.5 font-medium tracking-wide"><span>🏠</span> General</div>
<div class="mb-1 mt-6 pl-1 text-sm text-muted flex items-center gap-2 font-semibold">
<Home size={15} class="flex-shrink-0 text-slate-400" /> General
</div>
<ul class="m-0 list-none p-0">
{#if dailyLog}
<li>
<button class={navItem(currentId === 'daily-log')} onclick={() => navigate('daily-log')}>
{dailyLog.name}
<button class={navItem(currentId === 'daily-log') + ' flex items-center gap-2'} onclick={() => navigate('daily-log')}>
<LayoutList size={15} class="flex-shrink-0 text-slate-400" />
<span class="truncate">{dailyLog.name}</span>
</button>
</li>
{/if}
<li>
<button
class={navItem(page.url.pathname.startsWith('/journal/archive'))}
class={navItem(page.url.pathname.startsWith('/journal/archive')) + ' flex items-center gap-2'}
onclick={() => { goto('/journal/archive'); onnavigate?.(); }}
>
Archiv
<Archive size={15} class="flex-shrink-0 text-slate-400" />
<span class="truncate">Archiv</span>
</button>
</li>
</ul>
@ -96,18 +105,19 @@
<!-- Jour Fixes -->
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('meetings')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['meetings'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="transition-transform {collapsed['meetings'] ? '-rotate-90' : ''}" />
</button>
<button class={sectionLabel} onclick={() => { goto('/meetings'); onnavigate?.(); }}>
<span>💬</span> Jour Fixes
<CalendarRange size={15} class="flex-shrink-0 text-violet-400" /> Jour Fixes
</button>
</div>
{#if !collapsed['meetings']}
<ul class="m-0 list-none p-0">
{#each meetings as ctx}
<li>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{ctx.name}
<button class={navItem(currentId === ctx.id) + ' flex items-center gap-2'} onclick={() => navigate(ctx.id)}>
<CalendarDays size={14} class="flex-shrink-0 text-violet-400/60" />
<span class="truncate">{ctx.name}</span>
</button>
</li>
{/each}
@ -117,18 +127,19 @@
<!-- Projects -->
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('projects')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['projects'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="transition-transform {collapsed['projects'] ? '-rotate-90' : ''}" />
</button>
<button class={sectionLabel} onclick={() => { goto('/projects'); onnavigate?.(); }}>
<span>📁</span> Projects
<FolderOpen size={15} class="flex-shrink-0 text-amber-400" /> Projects
</button>
</div>
{#if !collapsed['projects']}
<ul class="m-0 list-none p-0">
{#each projects as ctx}
<li>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
<button class={navItem(currentId === ctx.id) + ' flex items-center gap-2'} onclick={() => navigate(ctx.id)}>
<FolderOpen size={14} class="flex-shrink-0 text-amber-400/60" />
<span class="truncate">{displayName(ctx)}</span>
</button>
</li>
{/each}
@ -138,18 +149,19 @@
<!-- Companies -->
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('companies')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['companies'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="transition-transform {collapsed['companies'] ? '-rotate-90' : ''}" />
</button>
<button class={sectionLabel} onclick={() => { goto('/companies'); onnavigate?.(); }}>
<span>🏢</span> Firmen
<Building2 size={15} class="flex-shrink-0 text-sky-400" /> Firmen
</button>
</div>
{#if !collapsed['companies']}
<ul class="m-0 list-none p-0">
{#each companies as ctx}
<li>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
<button class={navItem(currentId === ctx.id) + ' flex items-center gap-2'} onclick={() => navigate(ctx.id)}>
<Building2 size={14} class="flex-shrink-0 text-sky-400/60" />
<span class="truncate">{displayName(ctx)}</span>
</button>
</li>
{/each}
@ -159,18 +171,19 @@
<!-- People -->
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('people')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['people'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="transition-transform {collapsed['people'] ? '-rotate-90' : ''}" />
</button>
<button class={sectionLabel} onclick={() => { goto('/persons'); onnavigate?.(); }}>
<span>👤</span> People
<Users size={15} class="flex-shrink-0 text-emerald-400" /> People
</button>
</div>
{#if !collapsed['people']}
<ul class="m-0 list-none p-0">
{#each people as ctx}
<li>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
<button class={navItem(currentId === ctx.id) + ' flex items-center gap-2'} onclick={() => navigate(ctx.id)}>
<User size={14} class="flex-shrink-0 text-emerald-400/60" />
<span class="truncate">{displayName(ctx)}</span>
</button>
</li>
{/each}
@ -180,10 +193,10 @@
<!-- Wiki -->
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('wiki')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['wiki'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="transition-transform {collapsed['wiki'] ? '-rotate-90' : ''}" />
</button>
<button class={sectionLabel} onclick={() => { goto('/wiki'); onnavigate?.(); }}>
<span>📖</span> Wiki
<BookOpen size={15} class="flex-shrink-0 text-orange-400" /> Wiki
</button>
</div>
{#if !collapsed['wiki']}
@ -191,39 +204,35 @@
{#each ($wikiNotebooks$ ?? []) as nb}
<li>
<button
class={navItem(page.url.pathname === `/wiki/notebook/${nb.id}`)}
class={navItem(page.url.pathname === `/wiki/notebook/${nb.id}`) + ' flex items-center gap-2'}
onclick={() => { goto(`/wiki/notebook/${nb.id}`); onnavigate?.(); }}
>
{nb.name}
<BookOpen size={14} class="flex-shrink-0 text-orange-400/60" />
<span class="truncate">{nb.name}</span>
</button>
</li>
{/each}
</ul>
{/if}
<div class="mt-4">
<div class="mt-auto border-t border-border pt-3">
<button
class={navItem(page.url.pathname === '/trash') + ' flex items-center gap-2'}
class={navItem(page.url.pathname === '/trash') + ' flex items-center gap-2 mb-2'}
onclick={() => { goto('/trash'); onnavigate?.(); }}
>
<span>🗑</span>
<Trash2 size={15} class="flex-shrink-0 text-red-400/70" />
<span>Papierkorb</span>
{#if ($trashCount$ ?? 0) > 0}
<span class="ml-auto rounded-full bg-white/15 px-1.5 py-0.5 text-xs text-[#888] leading-none">{$trashCount$}</span>
{/if}
</button>
</div>
<div class="mt-auto border-t border-border pt-3">
<div class="mb-2 flex items-center justify-between px-1">
<button
class="flex items-center gap-1.5 text-xs text-muted hover:text-white transition-colors"
onclick={() => { goto('/sync'); onnavigate?.(); }}
>
{#if $syncStatus === 'syncing'}
<svg class="h-3 w-3 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 12a9 9 0 1 1-6.219-8.56" stroke-linecap="round"/>
</svg>
<RefreshCw size={12} class="animate-spin" />
<span>Syncing…</span>
{:else if $syncStatus === 'auth-required'}
<span class="text-yellow-400">⚠ Neu anmelden</span>
@ -240,13 +249,13 @@
onclick={() => fullSync()}
disabled={$syncStatus === 'syncing'}
title="Full sync"
></button>
><RefreshCw size={13} /></button>
</div>
<button
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white flex items-center gap-1"
class="mb-1 w-full rounded px-3 py-2.5 text-left text-sm text-muted transition-colors hover:bg-white/5 hover:text-white flex items-center gap-2"
onclick={() => toggleSection('user')}
>
<span class="inline-block text-[10px] transition-transform {collapsed['user'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
<ChevronDown size={14} class="flex-shrink-0 transition-transform {collapsed['user'] ? '-rotate-90' : ''}" />
{#if $account}
<span class="truncate" title={$account.username}>{$account.name ?? $account.username}</span>
{:else}
@ -255,22 +264,25 @@
</button>
{#if !collapsed['user']}
<button
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white pl-5"
class="mb-1 w-full rounded px-3 py-2.5 text-left text-sm text-muted transition-colors hover:bg-white/5 hover:text-white flex items-center gap-2 pl-6"
onclick={() => { goto('/settings'); onnavigate?.(); }}
>
Einstellungen
<Settings size={14} class="flex-shrink-0 opacity-60" />
<span>Einstellungen</span>
</button>
<button
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white pl-5"
class="mb-1 w-full rounded px-3 py-2.5 text-left text-sm text-muted transition-colors hover:bg-white/5 hover:text-white flex items-center gap-2 pl-6"
onclick={() => { goto('/backup'); onnavigate?.(); }}
>
Backup
<HardDrive size={14} class="flex-shrink-0 opacity-60" />
<span>Backup</span>
</button>
<button
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white pl-5"
class="mb-1 w-full rounded px-3 py-2.5 text-left text-sm text-muted transition-colors hover:bg-white/5 hover:text-white flex items-center gap-2 pl-6"
onclick={() => logout()}
>
Sign out
<LogOut size={14} class="flex-shrink-0 opacity-60" />
<span>Sign out</span>
</button>
{/if}
{#if isDev}

View File

@ -5,6 +5,7 @@
import type { HistoryEntry } from '@ka-note/shared';
import HistoryEntryText from './HistoryEntryText.svelte';
import LinkTitle from './LinkTitle.svelte';
import { Check, CalendarDays, ArrowUpRight, Trash2 } from 'lucide-svelte';
interface Props {
entry: HistoryEntry;
@ -100,25 +101,25 @@
{:else}
<div class="flex gap-1.5">
<button
class="rounded bg-green-700 px-2.5 py-1.5 text-base leading-none text-white hover:brightness-110 active:brightness-90"
class="flex items-center justify-center rounded bg-green-700 px-2.5 py-1.5 text-white hover:brightness-110 active:brightness-90"
title="Erledigt"
onclick={handleOk}
></button>
><Check size={15} /></button>
<button
class="rounded bg-amber-700 px-2.5 py-1.5 text-base leading-none text-white hover:brightness-110 active:brightness-90"
class="flex items-center justify-center rounded bg-amber-700 px-2.5 py-1.5 text-white hover:brightness-110 active:brightness-90"
title="Verschieben"
onclick={() => showVerschieben = true}
>📅</button>
><CalendarDays size={15} /></button>
<button
class="rounded bg-[#444] px-2.5 py-1.5 text-base leading-none text-white hover:bg-[#555] active:bg-[#555]"
class="flex items-center justify-center rounded bg-[#444] px-2.5 py-1.5 text-white hover:bg-[#555] active:bg-[#555]"
title="In Thema wandeln"
onclick={() => showConvert = true}
></button>
><ArrowUpRight size={15} /></button>
<button
class="ml-auto rounded bg-red-900/60 px-2.5 py-1.5 text-base leading-none text-red-300 hover:bg-red-800 active:bg-red-800"
class="ml-auto flex items-center justify-center rounded bg-red-900/60 px-2.5 py-1.5 text-red-300 hover:bg-red-800 active:bg-red-800"
title="Löschen"
onclick={handleDelete}
>🗑</button>
><Trash2 size={15} /></button>
</div>
{/if}
</div>

View File

@ -370,7 +370,7 @@ export async function createHistoryEntry(topicId: string, date: string, text: st
updatedAt: now(),
deletedAt: null,
version: 1,
...(isPrivate ? { isPrivate: true } : {})
isPrivate: !!isPrivate
};
await db.historyEntries.put(entry);
return entry;

View File

@ -37,6 +37,7 @@
"dexie": "^4.0.11",
"dompurify": "^3.3.1",
"highlight.js": "^11.11.1",
"lucide-svelte": "^0.576.0",
"marked": "^17.0.3",
"tiptap-markdown": "^0.9.0"
},
@ -2665,7 +2666,6 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@ -2676,7 +2676,6 @@
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@ -2687,7 +2686,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@ -2708,14 +2706,12 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@ -3344,7 +3340,6 @@
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz",
"integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
@ -3969,7 +3964,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/linkify-it": {
@ -4015,14 +4009,12 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"devOptional": true,
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@ -4112,7 +4104,6 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@ -4241,7 +4232,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@ -4657,7 +4647,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -5004,7 +4993,6 @@
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz",
"integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==",
"dev": true,
"license": "MIT"
},
"node_modules/dexie": {
@ -5959,14 +5947,12 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"dev": true,
"license": "MIT"
},
"node_modules/esrap": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.3.tgz",
"integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@ -6960,7 +6946,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
@ -7330,7 +7315,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true,
"license": "MIT"
},
"node_modules/lodash": {
@ -7364,11 +7348,19 @@
"yallist": "^3.0.2"
}
},
"node_modules/lucide-svelte": {
"version": "0.576.0",
"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.576.0.tgz",
"integrity": "sha512-bm7RCoptI8unoEyo9H9sRHTHgnleuBW8npge05ZtxHkNsDNnO3p/BQEU79sshf4k+MSrjqlWvsCN5vVZtgV7ww==",
"license": "ISC",
"peerDependencies": {
"svelte": "^3 || ^4 || ^5.0.0-next.42"
}
},
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@ -9247,7 +9239,6 @@
"version": "5.53.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.0.tgz",
"integrity": "sha512-7dhHkSamGS2vtoBmIW2hRab+gl5Z60alEHZB4910ePqqJNxAWnDAxsofVmlZ2tREmWyHNE+A1nCKwICAquoD2A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
@ -11046,7 +11037,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/zod": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3524
ka-note/repair/dump.sql Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,13 @@
import { readFileSync, writeFileSync } from 'fs';
let sql = readFileSync('dump-fixed.sql', 'utf8');
// unistr('\uXXXX') -> plain UTF-8 string
sql = sql.replace(/unistr\('((?:[^'\\]|\\.)*)'\)/g, (_, inner) => {
const decoded = inner.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
return `'${decoded}'`;
});
// ROLLBACK at end of corrupt dump -> COMMIT so import doesn't discard everything
sql = sql.replace(/^ROLLBACK;.*$/m, 'COMMIT;');
writeFileSync('dump-fixed2.sql', sql, 'utf8');
console.log('done');

Binary file not shown.

Binary file not shown.