Switch from anchorme to linkifyjs
This commit is contained in:
parent
a7d3a3940a
commit
631f119061
5 changed files with 75 additions and 57 deletions
102
lib/linkify.js
102
lib/linkify.js
|
@ -1,65 +1,81 @@
|
|||
import { anchorme, html } from "./index.js";
|
||||
import { linkifyjs, html } from "./index.js";
|
||||
|
||||
function linkifyChannel(text, transformChannel) {
|
||||
// Don't match punctuation at the end of the channel name
|
||||
const channelRegex = /(^|\s)(#[^\s]+[^\s.?!…():;,])/gi;
|
||||
linkifyjs.options.defaults.defaultProtocol = "https";
|
||||
|
||||
let children = [];
|
||||
let match;
|
||||
let last = 0;
|
||||
while ((match = channelRegex.exec(text)) !== null) {
|
||||
let channel = match[2];
|
||||
let start = match.index + match[1].length;
|
||||
let end = start + match[2].length;
|
||||
linkifyjs.registerCustomProtocol("irc");
|
||||
linkifyjs.registerCustomProtocol("ircs");
|
||||
|
||||
children.push(text.substring(last, start));
|
||||
children.push(transformChannel(channel));
|
||||
linkifyjs.registerPlugin('ircChannel', ({ scanner, parser, utils }) => {
|
||||
const { POUND, DOMAIN, TLD, LOCALHOST, UNDERSCORE, DOT, HYPHEN } = scanner.tokens;
|
||||
const START_STATE = parser.start;
|
||||
|
||||
last = end;
|
||||
}
|
||||
children.push(text.substring(last));
|
||||
const Channel = utils.createTokenClass('ircChannel', {
|
||||
isLink: true,
|
||||
toHref() {
|
||||
return "irc:///" + this.toString();
|
||||
},
|
||||
});
|
||||
|
||||
return children;
|
||||
}
|
||||
const HASH_STATE = START_STATE.tt(POUND);
|
||||
|
||||
const CHAN_STATE = HASH_STATE.tt(DOMAIN, Channel);
|
||||
HASH_STATE.tt(TLD, CHAN_STATE);
|
||||
HASH_STATE.tt(LOCALHOST, CHAN_STATE);
|
||||
HASH_STATE.tt(POUND, CHAN_STATE);
|
||||
|
||||
CHAN_STATE.tt(UNDERSCORE, CHAN_STATE);
|
||||
CHAN_STATE.tt(DOMAIN, CHAN_STATE);
|
||||
CHAN_STATE.tt(TLD, CHAN_STATE);
|
||||
CHAN_STATE.tt(LOCALHOST, CHAN_STATE);
|
||||
|
||||
const CHAN_DIVIDER_STATE = CHAN_STATE.tt(DOT);
|
||||
|
||||
CHAN_DIVIDER_STATE.tt(UNDERSCORE, CHAN_STATE);
|
||||
CHAN_DIVIDER_STATE.tt(DOMAIN, CHAN_STATE);
|
||||
CHAN_DIVIDER_STATE.tt(TLD, CHAN_STATE);
|
||||
CHAN_DIVIDER_STATE.tt(LOCALHOST, CHAN_STATE);
|
||||
});
|
||||
|
||||
export default function linkify(text, onChannelClick) {
|
||||
function transformChannel(channel) {
|
||||
function onClick(event) {
|
||||
event.preventDefault();
|
||||
onChannelClick(channel);
|
||||
}
|
||||
return html`
|
||||
<a
|
||||
href="irc:///${encodeURIComponent(channel)}"
|
||||
onClick=${onClick}
|
||||
>${channel}</a>`;
|
||||
}
|
||||
|
||||
let links = anchorme.list(text);
|
||||
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(...linkifyChannel(prefix, transformChannel));
|
||||
children.push(prefix);
|
||||
|
||||
let proto = match.protocol || "https://";
|
||||
if (match.isEmail) {
|
||||
proto = "mailto:";
|
||||
// TODO: handle all irc/ircs URLs
|
||||
if (match.href.startsWith("irc:///")) {
|
||||
function onClick(event) {
|
||||
event.preventDefault();
|
||||
onChannelClick(match.value);
|
||||
}
|
||||
children.push(html`
|
||||
<a
|
||||
href="${match.href}"
|
||||
onClick=${onClick}
|
||||
>${match.value}</a>
|
||||
`);
|
||||
} else {
|
||||
children.push(html`
|
||||
<a
|
||||
href=${match.href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>${match.value}</a>
|
||||
`);
|
||||
}
|
||||
|
||||
let url = match.string;
|
||||
if (!url.startsWith(proto)) {
|
||||
url = proto + url;
|
||||
}
|
||||
|
||||
children.push(html`<a href=${url} target="_blank" rel="noreferrer noopener">${match.string}</a>`);
|
||||
|
||||
last = match.end;
|
||||
});
|
||||
|
||||
const suffix = text.substring(last)
|
||||
children.push(...linkifyChannel(suffix, transformChannel));
|
||||
children.push(suffix);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue