mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-03 16:41:27 +01:00
Terminal-themed markdown diary
Single-user diary served as one Rust binary with the Svelte frontend embedded. - axum 0.8 + SQLite (sqlx), migrations run at startup - stateless HMAC session cookie; credentials from .env, compared in constant time - FTS5 full-text search, user input rewritten into quoted prefix terms - media uploads linked to entries by scanning bodies for /api/media/<id>, which scopes share-token media access and entry deletion - unguessable share links (192-bit token) serving a public read-only page - vim keybindings via CodeMirror plus a modal browse layer and : command line; disabled on touch devices
This commit is contained in:
commit
4002a35305
41 files changed
+6195
No files matched your search
@@ -0,0 +1,86 @@
|
||||
<script lang="ts">
|
||||
import { commands } from './commands'
|
||||
import { diary } from './store.svelte'
|
||||
|
||||
const keys: [string, string][] = [
|
||||
['j / k · ↓ ↑', 'move down / up the entry list'],
|
||||
['gg / G', 'first / last entry'],
|
||||
['Enter · l', 'open the highlighted entry'],
|
||||
['o', 'new entry, straight into insert mode'],
|
||||
['i · a', 'edit the open entry'],
|
||||
['Esc · h · q', 'back out to the list'],
|
||||
['/', 'full-text search'],
|
||||
['n', 'clear the search'],
|
||||
['s', 'toggle sharing for the entry'],
|
||||
['y', 'copy the share link'],
|
||||
['x · dd', 'delete the entry (asks first)'],
|
||||
[': ', 'command line'],
|
||||
['Ctrl-S', 'save, from anywhere'],
|
||||
['?', 'this screen'],
|
||||
]
|
||||
</script>
|
||||
|
||||
<div class="sheet">
|
||||
<header>
|
||||
<span class="accent">:help</span>
|
||||
<button onclick={() => (diary.overlay = 'none')}>esc</button>
|
||||
</header>
|
||||
|
||||
<div class="cols">
|
||||
<section>
|
||||
<h2>keys</h2>
|
||||
<dl>
|
||||
{#each keys as [key, description] (key)}
|
||||
<dt>{key}</dt>
|
||||
<dd>{description}</dd>
|
||||
{/each}
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>commands</h2>
|
||||
<dl>
|
||||
{#each commands as spec (spec.name)}
|
||||
<dt>
|
||||
:{spec.name}{#if spec.aliases?.length}<span class="faint"> ({spec.aliases.join(' ')})</span>{/if}
|
||||
{#if spec.args}<span class="faint"> {spec.args}</span>{/if}
|
||||
</dt>
|
||||
<dd>{spec.help}</dd>
|
||||
{/each}
|
||||
</dl>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<footer class="faint">
|
||||
inside the editor the full vim keymap is live — hjkl, w/b, dd, ciw, visual mode, macros, and
|
||||
<span class="accent">:w</span> to write. drop or paste an image, video or audio file into the
|
||||
editor to attach it.
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.sheet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: min(100%, 90ch);
|
||||
max-height: 100%;
|
||||
background: var(--bg-alt);
|
||||
border: 1px solid var(--accent-dim);
|
||||
border-radius: var(--radius);
|
||||
padding: 14px 16px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
header { display: flex; justify-content: space-between; align-items: center; }
|
||||
|
||||
.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr)); gap: 20px; }
|
||||
|
||||
h2 { font-size: 12px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.1em; margin: 0 0 6px; }
|
||||
|
||||
dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; font-size: 12px; }
|
||||
dt { color: var(--accent); white-space: nowrap; }
|
||||
dd { margin: 0; color: var(--fg-dim); }
|
||||
|
||||
footer { font-size: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
|
||||
</style>
|
||||
Reference in new issue
Block a user