diff --git a/app/src/lib/nostr/translations.test.ts b/app/src/lib/nostr/translations.test.ts new file mode 100644 index 0000000..df82317 --- /dev/null +++ b/app/src/lib/nostr/translations.test.ts @@ -0,0 +1,51 @@ +import { describe, it, expect } from 'vitest'; +import { parseTranslationRefs } from './translations'; +import type { NostrEvent } from './loaders'; + +function ev(tags: string[][]): NostrEvent { + return { + id: 'x', + pubkey: 'p', + created_at: 0, + kind: 30023, + tags, + content: '', + sig: 's' + } as unknown as NostrEvent; +} + +describe('parseTranslationRefs', () => { + it('extrahiert a-tags mit marker "translation"', () => { + const e = ev([ + ['d', 'x'], + ['a', '30023:abc:other-slug', '', 'translation'], + ['a', '30023:abc:third-slug', '', 'translation'] + ]); + expect(parseTranslationRefs(e)).toEqual([ + { kind: 30023, pubkey: 'abc', dtag: 'other-slug' }, + { kind: 30023, pubkey: 'abc', dtag: 'third-slug' } + ]); + }); + + it('ignoriert a-tags ohne marker "translation"', () => { + const e = ev([ + ['a', '30023:abc:root-thread', '', 'root'], + ['a', '30023:abc:x', '', 'reply'] + ]); + expect(parseTranslationRefs(e)).toEqual([]); + }); + + it('ignoriert a-tags mit malformed coordinate', () => { + const e = ev([ + ['a', 'not-a-coord', '', 'translation'], + ['a', '30023:abc:ok', '', 'translation'] + ]); + expect(parseTranslationRefs(e)).toEqual([ + { kind: 30023, pubkey: 'abc', dtag: 'ok' } + ]); + }); + + it('leeres tag-array → leere liste', () => { + expect(parseTranslationRefs(ev([]))).toEqual([]); + }); +}); diff --git a/app/src/lib/nostr/translations.ts b/app/src/lib/nostr/translations.ts new file mode 100644 index 0000000..8b1cd6c --- /dev/null +++ b/app/src/lib/nostr/translations.ts @@ -0,0 +1,27 @@ +import type { NostrEvent } from './loaders'; + +export interface TranslationRef { + kind: number; + pubkey: string; + dtag: string; +} + +const COORD_RE = /^(\d+):([0-9a-f]+):([a-z0-9][a-z0-9-]*)$/; + +export function parseTranslationRefs(event: NostrEvent): TranslationRef[] { + const refs: TranslationRef[] = []; + for (const tag of event.tags) { + if (tag[0] !== 'a') continue; + if (tag[3] !== 'translation') continue; + const coord = tag[1]; + if (typeof coord !== 'string') continue; + const m = coord.match(COORD_RE); + if (!m) continue; + refs.push({ + kind: parseInt(m[1], 10), + pubkey: m[2], + dtag: m[3] + }); + } + return refs; +} diff --git a/app/vite.config.ts b/app/vite.config.ts index 1955da7..ed494ba 100644 --- a/app/vite.config.ts +++ b/app/vite.config.ts @@ -4,7 +4,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ plugins: [sveltekit()], test: { - include: ['tests/unit/**/*.{test,spec}.{js,ts}'], + include: ['tests/unit/**/*.{test,spec}.{js,ts}', 'src/**/*.{test,spec}.{js,ts}'], environment: 'jsdom', globals: true }