CircleDot,
GitPullRequest,
} from 'lucide-solid';
import { marked } from 'marked';
import { A } from '@solidjs/router';
import { A, useNavigate } from '@solidjs/router';
import { For, Show, createEffect, createMemo, createSignal, onCleanup, onMount, type Component, type JSX } from 'solid-js';
import type { RepoContext, TreeEntry } from '../lib/api/repos';
import type { Did } from '@atcute/lexicons/syntax';
import { createQuery } from '@tanstack/solid-query';
865 unmodified lines
Expand all
</Show>
);
export const MarkdownBlock: Component<{ markdown: string; variant?: 'default' | 'readme' | 'code' }> = (props) => {
const navigate = useNavigate();
const html = createMemo(() =>
DOMPurify.sanitize(marked.parse(props.markdown, { async: false }) as string, {
ADD_ATTR: ['class'],
}),
? 'font-mono text-sm whitespace-pre-wrap break-words'
: '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',
);
const onMarkdownClick = (event: MouseEvent) => {
const anchor = (event.target as HTMLElement).closest('a');
if (!anchor || event.defaultPrevented) {
return;
}
const href = anchor.getAttribute('href');
if (!href || !href.startsWith('https://tangled.org/')) {
return;
}
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
return;
}
try {
const url = new URL(href);
if (url.hostname === 'tangled.org') {
event.preventDefault();
navigate(url.pathname + url.search + url.hash);
}
} catch {
// ignore
}
};
return <div class={classes()} innerHTML={html()} />;
return <div class={classes()} innerHTML={html()} onClick={onMarkdownClick} />;
};
const splitCodeLines = (value: string): string[] => {
const normalized = value.endsWith('\n') ? value.slice(0, -1) : value;
1070 unmodified lines
Expand all