aboutsummaryrefslogtreecommitdiff
path: root/lib/linkify.js
blob: 4f0e66930b1e104a99fdcccef1e10b81853ed2ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { linkifyjs, html } from "./index.js";

linkifyjs.options.defaults.defaultProtocol = "https";

linkifyjs.registerCustomProtocol("irc");
linkifyjs.registerCustomProtocol("ircs");
linkifyjs.registerCustomProtocol("geo", true);

const IRCChannelToken = linkifyjs.createTokenClass("ircChannel", {
	isLink: true,
	toHref() {
		return "irc:///" + this.v;
	},
});

linkifyjs.registerPlugin("ircChannel", ({ scanner, parser }) => {
	const { POUND, UNDERSCORE, DOT, HYPHEN } = scanner.tokens;
	const { alphanumeric } = scanner.tokens.groups;

	const Prefix = parser.start.tt(POUND);
	const Channel = new linkifyjs.State(IRCChannelToken);
	const Divider = Channel.tt(DOT);

	Prefix.ta(alphanumeric, Channel);
	Prefix.tt(POUND, Channel);
	Prefix.tt(UNDERSCORE, Channel);
	Prefix.tt(DOT, Divider);
	Prefix.tt(HYPHEN, Channel);
	Channel.ta(alphanumeric, Channel);
	Channel.tt(POUND, Channel);
	Channel.tt(UNDERSCORE, Channel);
	Channel.tt(HYPHEN, Channel);
	Divider.ta(alphanumeric, Channel);
});

export default function linkify(text, onClick) {
	let links = linkifyjs.find(text);

	let children = [];
	let last = 0;
	links.forEach((match) => {
		if (!match.isLink) {
			return;
		}

		const prefix = text.substring(last, match.start)
		children.push(prefix);

		children.push(html`
			<a
				href=${match.href}
				target="_blank"
				rel="noreferrer noopener"
				onClick=${onClick}
			>${match.value}</a>
		`);

		last = match.end;
	});

	const suffix = text.substring(last)
	children.push(suffix);

	return children;
}