atagen

malice

public
Star0
Watch0
4f91f89d99fa00315aff796b1ce189c0d9d4fc4e
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git

Blame: web/src/lib/MessageText.svelte

df3c0f2b3da4atagen2026-10-22 13:07 UTC1
<script lang="ts">
df3c0f2b3da4atagen2026-10-22 13:07 UTC2
  import EmojiText from './EmojiText.svelte';
6d6a4c34bdc1atagen2026-10-24 06:51 UTC3
  import RichNodes from './RichNodes.svelte';
705b1e1062c2atagen2026-10-23 09:05 UTC4
  import { parseCode } from './code';
705b1e1062c2atagen2026-10-23 09:05 UTC5
  import { segmentInline } from './inline';
705b1e1062c2atagen2026-10-23 09:05 UTC6
  import type { Mention } from './mentions';
6d6a4c34bdc1atagen2026-10-24 06:51 UTC7
  import { parseRich } from './rich';
df3c0f2b3da4atagen2026-10-22 13:07 UTC8
df3c0f2b3da4atagen2026-10-22 13:07 UTC9
  export let text: string;
6d6a4c34bdc1atagen2026-10-24 06:51 UTC10
  export let html: string | null = null;
df3c0f2b3da4atagen2026-10-22 13:07 UTC11
  export let jumbo = false;
705b1e1062c2atagen2026-10-23 09:05 UTC12
  export let mentions: Mention[] = [];
705b1e1062c2atagen2026-10-23 09:05 UTC13
  export let self: string | null = null;
787cdbbf0721atagen2026-10-24 06:50 UTC14
  export let nameOf: (userId: string) => string | null = () => null;
df3c0f2b3da4atagen2026-10-22 13:07 UTC15
6d6a4c34bdc1atagen2026-10-24 06:51 UTC16
  $: rich = html ? parseRich(html) : null;
df3c0f2b3da4atagen2026-10-22 13:07 UTC17
  $: segments = parseCode(text);
705b1e1062c2atagen2026-10-23 09:05 UTC18
  $: pieces = segments.map((s) => (s.kind === 'text' ? segmentInline(s.text, mentions) : []));
705b1e1062c2atagen2026-10-23 09:05 UTC19
  $: single = segments.length === 1 && pieces[0].length === 1;
df3c0f2b3da4atagen2026-10-22 13:07 UTC20
</script>
df3c0f2b3da4atagen2026-10-22 13:07 UTC21
445bf199a9cfatagen2026-10-25 02:56 UTC22
{#if rich}<div class="rich"><RichNodes nodes={rich} {mentions} {self} {nameOf} /></div>{:else}{#each segments as s, i}{#if s.kind === 'inline'}<code class="inline">{s.text}</code>{:else if s.kind === 'block'}<pre class="block"><code>{s.text}</code></pre>{:else}{#each pieces[i] as p}{#if p.kind === 'mention'}<span class="mention" class:me={p.user_id === self} title={p.user_id}><EmojiText text={p.text === p.user_id ? (nameOf(p.user_id) ?? p.text) : p.text} /></span>{:else if p.kind === 'link'}<a class="link" href={p.href} target="_blank" rel="noopener noreferrer"><EmojiText text={p.text} /></a>{:else}<EmojiText text={p.text} jumbo={jumbo && single} />{/if}{/each}{/if}{/each}{/if}
df3c0f2b3da4atagen2026-10-22 13:07 UTC23
df3c0f2b3da4atagen2026-10-22 13:07 UTC24
<style>
6d6a4c34bdc1atagen2026-10-24 06:51 UTC25
  code, .rich :global(code) {
df3c0f2b3da4atagen2026-10-22 13:07 UTC26
    font-family: ui-monospace, 'JetBrains Mono', 'Fira Code', Menlo, monospace;
df3c0f2b3da4atagen2026-10-22 13:07 UTC27
    font-size: 0.9em;
df3c0f2b3da4atagen2026-10-22 13:07 UTC28
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC29
  .inline, .rich :global(:not(pre) > code) {
df3c0f2b3da4atagen2026-10-22 13:07 UTC30
    padding: 1px 5px;
05a48e9e7942atagen2026-10-24 09:32 UTC31
    border-radius: var(--r-sm);
df3c0f2b3da4atagen2026-10-22 13:07 UTC32
    background: var(--bg-soft);
df3c0f2b3da4atagen2026-10-22 13:07 UTC33
    border: 1px solid var(--border);
df3c0f2b3da4atagen2026-10-22 13:07 UTC34
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC35
  .block, .rich :global(pre) {
df3c0f2b3da4atagen2026-10-22 13:07 UTC36
    margin: 4px 0;
df3c0f2b3da4atagen2026-10-22 13:07 UTC37
    padding: 8px 10px;
05a48e9e7942atagen2026-10-24 09:32 UTC38
    border-radius: var(--r-sm);
df3c0f2b3da4atagen2026-10-22 13:07 UTC39
    background: var(--bg-soft);
df3c0f2b3da4atagen2026-10-22 13:07 UTC40
    border: 1px solid var(--border);
df3c0f2b3da4atagen2026-10-22 13:07 UTC41
    overflow-x: auto;
df3c0f2b3da4atagen2026-10-22 13:07 UTC42
    white-space: pre;
df3c0f2b3da4atagen2026-10-22 13:07 UTC43
    line-height: 1.4;
df3c0f2b3da4atagen2026-10-22 13:07 UTC44
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC45
  .mention, .rich :global(.mention) {
705b1e1062c2atagen2026-10-23 09:05 UTC46
    padding: 0 4px;
05a48e9e7942atagen2026-10-24 09:32 UTC47
    border-radius: var(--r-sm);
705b1e1062c2atagen2026-10-23 09:05 UTC48
    font-weight: 600;
705b1e1062c2atagen2026-10-23 09:05 UTC49
    color: var(--accent);
705b1e1062c2atagen2026-10-23 09:05 UTC50
    background: color-mix(in srgb, var(--accent) 18%, transparent);
705b1e1062c2atagen2026-10-23 09:05 UTC51
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC52
  .mention.me, .rich :global(.mention.me) {
705b1e1062c2atagen2026-10-23 09:05 UTC53
    color: var(--warn-text);
705b1e1062c2atagen2026-10-23 09:05 UTC54
    background: color-mix(in srgb, var(--warn) 28%, transparent);
705b1e1062c2atagen2026-10-23 09:05 UTC55
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC56
  .link, .rich :global(.link) { color: var(--accent); overflow-wrap: anywhere; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC57
  .link:hover, .rich :global(.link:hover) { text-decoration: underline; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC58
  .rich { white-space: normal; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC59
  .rich :global(:is(p, ul, ol, blockquote, h1, h2, h3, h4, h5, h6, table, details)) { margin: 4px 0; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC60
  .rich :global(:first-child) { margin-top: 0; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC61
  .rich :global(:last-child) { margin-bottom: 0; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC62
  .rich :global(:is(ul, ol)) { padding-left: 22px; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC63
  .rich :global(blockquote) {
6d6a4c34bdc1atagen2026-10-24 06:51 UTC64
    padding: 2px 10px;
6d6a4c34bdc1atagen2026-10-24 06:51 UTC65
    border-left: 3px solid var(--border);
6d6a4c34bdc1atagen2026-10-24 06:51 UTC66
    color: var(--muted);
6d6a4c34bdc1atagen2026-10-24 06:51 UTC67
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC68
  .rich :global(:is(h1, h2, h3, h4, h5, h6)) { line-height: 1.3; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC69
  .rich :global(h1) { font-size: 1.4em; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC70
  .rich :global(h2) { font-size: 1.25em; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC71
  .rich :global(:is(h3, h4, h5, h6)) { font-size: 1.1em; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC72
  .rich :global(hr) { border: none; border-top: 1px solid var(--border); margin: 8px 0; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC73
  .rich :global(table) { border-collapse: collapse; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC74
  .rich :global(:is(th, td)) { border: 1px solid var(--border); padding: 3px 8px; text-align: left; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC75
  .rich :global(.spoiler) {
05a48e9e7942atagen2026-10-24 09:32 UTC76
    border-radius: var(--r-sm);
6d6a4c34bdc1atagen2026-10-24 06:51 UTC77
    background: var(--text);
6d6a4c34bdc1atagen2026-10-24 06:51 UTC78
    color: transparent;
6d6a4c34bdc1atagen2026-10-24 06:51 UTC79
    cursor: pointer;
6d6a4c34bdc1atagen2026-10-24 06:51 UTC80
  }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC81
  .rich :global(.spoiler:is(:hover, :focus)) { background: var(--bg-soft); color: inherit; }
6d6a4c34bdc1atagen2026-10-24 06:51 UTC82
  .rich :global(.emote) { height: 1.6em; width: auto; vertical-align: middle; }
df3c0f2b3da4atagen2026-10-22 13:07 UTC83
</style>