csr tangled client in solid-js
15

Configure Feed

Select the types of activity you want to include in your feed.

make tangled.org links navigate to untangled

dawn (May 30, 2026, 6:53 AM +0300) 2c16f701 ee3234f4

+30 -2
+30 -2
src/components/repo.tsx
··· 27 27 GitPullRequest, 28 28 } from 'lucide-solid'; 29 29 import { marked } from 'marked'; 30 - import { A } from '@solidjs/router'; 30 + import { A, useNavigate } from '@solidjs/router'; 31 31 import { For, Show, createEffect, createMemo, createSignal, onCleanup, onMount, type Component, type JSX } from 'solid-js'; 32 32 import type { RepoContext, TreeEntry } from '../lib/api/repos'; 33 33 import type { Did } from '@atcute/lexicons/syntax'; ··· 901 901 ); 902 902 903 903 export const MarkdownBlock: Component<{ markdown: string; variant?: 'default' | 'readme' | 'code' }> = (props) => { 904 + const navigate = useNavigate(); 905 + 904 906 const html = createMemo(() => 905 907 DOMPurify.sanitize(marked.parse(props.markdown, { async: false }) as string, { 906 908 ADD_ATTR: ['class'], ··· 914 916 : 'prose prose-sm sm:prose-base min-w-0 max-w-none break-words untangled-anywhere dark:prose-invert prose-p:text-gray-800 dark:prose-p:text-gray-200 prose-li:text-gray-800 dark:prose-li:text-gray-200 prose-pre:max-w-full prose-pre:overflow-x-auto prose-pre:rounded-md prose-pre:bg-gray-950 dark:prose-pre:bg-gray-950 prose-code:break-words prose-a:break-all', 915 917 ); 916 918 917 - return <div class={classes()} innerHTML={html()} />; 919 + const onMarkdownClick = (event: MouseEvent) => { 920 + const anchor = (event.target as HTMLElement).closest('a'); 921 + if (!anchor || event.defaultPrevented) { 922 + return; 923 + } 924 + 925 + const href = anchor.getAttribute('href'); 926 + if (!href || !href.startsWith('https://tangled.org/')) { 927 + return; 928 + } 929 + 930 + if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) { 931 + return; 932 + } 933 + 934 + try { 935 + const url = new URL(href); 936 + if (url.hostname === 'tangled.org') { 937 + event.preventDefault(); 938 + navigate(url.pathname + url.search + url.hash); 939 + } 940 + } catch { 941 + // ignore 942 + } 943 + }; 944 + 945 + return <div class={classes()} innerHTML={html()} onClick={onMarkdownClick} />; 918 946 }; 919 947 920 948 const splitCodeLines = (value: string): string[] => {