+7
-5
frontend/src/lib/components/RichText.svelte
+7
-5
frontend/src/lib/components/RichText.svelte
···
5
* supports:
6
* - bare URLs: https://example.com -> clickable link
7
* - markdown links: [text](https://example.com) -> "text" as clickable link
8
*/
9
10
interface Props {
···
23
function parseText(input: string): TextPart[] {
24
const parts: TextPart[] = [];
25
26
-
// combined regex: markdown links OR bare URLs
27
// markdown: [text](url)
28
// bare URL: https?://... or www....
29
const combinedRegex =
30
-
/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)|(https?:\/\/[^\s<>)\]]+|www\.[^\s<>)\]]+)/gi;
31
32
let lastIndex = 0;
33
let match;
···
49
href: match[2]
50
});
51
} else if (match[3]) {
52
-
// bare URL
53
let href = match[3];
54
-
if (href.startsWith('www.')) {
55
href = 'https://' + href;
56
}
57
parts.push({
···
79
</script>
80
81
<span class={className}
82
-
>{#each parsed as part}{#if part.type === 'link'}<a
83
href={part.href}
84
target="_blank"
85
rel="noopener noreferrer"
···
5
* supports:
6
* - bare URLs: https://example.com -> clickable link
7
* - markdown links: [text](https://example.com) -> "text" as clickable link
8
+
* - domain/path URLs: github.com/user/repo -> clickable link
9
*/
10
11
interface Props {
···
24
function parseText(input: string): TextPart[] {
25
const parts: TextPart[] = [];
26
27
+
// combined regex: markdown links OR bare URLs OR domain/path
28
// markdown: [text](url)
29
// bare URL: https?://... or www....
30
+
// domain/path: github.com/... (must have path to avoid false positives)
31
const combinedRegex =
32
+
/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)|(https?:\/\/[^\s<>)\]]+|www\.[^\s<>)\]]+|[a-z0-9][-a-z0-9]*\.[a-z]{2,}\/[^\s<>)\]]+)/gi;
33
34
let lastIndex = 0;
35
let match;
···
51
href: match[2]
52
});
53
} else if (match[3]) {
54
+
// bare URL or domain/path
55
let href = match[3];
56
+
if (!href.startsWith('http://') && !href.startsWith('https://')) {
57
href = 'https://' + href;
58
}
59
parts.push({
···
81
</script>
82
83
<span class={className}
84
+
>{#each parsed as part, i (i)}{#if part.type === 'link'}<a
85
href={part.href}
86
target="_blank"
87
rel="noopener noreferrer"