forked from CringeStudios/gamja
Switch from anchorme to linkifyjs
This commit is contained in:
parent
a7d3a3940a
commit
631f119061
@ -11,6 +11,7 @@
|
|||||||
<noscript>
|
<noscript>
|
||||||
<p>Unfortunately gamja requires JavaScript. Please enable it!</p>
|
<p>Unfortunately gamja requires JavaScript. Please enable it!</p>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
<script src="./node_modules/linkifyjs/dist/linkify.min.js"></script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { html, render } from "./lib/index.js";
|
import { html, render } from "./lib/index.js";
|
||||||
import App from "./components/app.js";
|
import App from "./components/app.js";
|
||||||
|
@ -4,5 +4,6 @@ import { h } from "../node_modules/preact/dist/preact.module.js";
|
|||||||
import htm from "../node_modules/htm/dist/htm.module.js";
|
import htm from "../node_modules/htm/dist/htm.module.js";
|
||||||
export const html = htm.bind(h);
|
export const html = htm.bind(h);
|
||||||
|
|
||||||
import "../node_modules/anchorme/dist/browser/anchorme.min.js";
|
// TODO: replace with proper import once this is merged and released:
|
||||||
export const anchorme = window.anchorme;
|
// https://github.com/Hypercontext/linkifyjs/pull/356
|
||||||
|
export const linkifyjs = window.linkify;
|
||||||
|
100
lib/linkify.js
100
lib/linkify.js
@ -1,65 +1,81 @@
|
|||||||
import { anchorme, html } from "./index.js";
|
import { linkifyjs, html } from "./index.js";
|
||||||
|
|
||||||
function linkifyChannel(text, transformChannel) {
|
linkifyjs.options.defaults.defaultProtocol = "https";
|
||||||
// Don't match punctuation at the end of the channel name
|
|
||||||
const channelRegex = /(^|\s)(#[^\s]+[^\s.?!…():;,])/gi;
|
|
||||||
|
|
||||||
let children = [];
|
linkifyjs.registerCustomProtocol("irc");
|
||||||
let match;
|
linkifyjs.registerCustomProtocol("ircs");
|
||||||
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;
|
|
||||||
|
|
||||||
children.push(text.substring(last, start));
|
linkifyjs.registerPlugin('ircChannel', ({ scanner, parser, utils }) => {
|
||||||
children.push(transformChannel(channel));
|
const { POUND, DOMAIN, TLD, LOCALHOST, UNDERSCORE, DOT, HYPHEN } = scanner.tokens;
|
||||||
|
const START_STATE = parser.start;
|
||||||
|
|
||||||
last = end;
|
const Channel = utils.createTokenClass('ircChannel', {
|
||||||
}
|
isLink: true,
|
||||||
children.push(text.substring(last));
|
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) {
|
export default function linkify(text, onChannelClick) {
|
||||||
function transformChannel(channel) {
|
let links = linkifyjs.find(text);
|
||||||
function onClick(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
onChannelClick(channel);
|
|
||||||
}
|
|
||||||
return html`
|
|
||||||
<a
|
|
||||||
href="irc:///${encodeURIComponent(channel)}"
|
|
||||||
onClick=${onClick}
|
|
||||||
>${channel}</a>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = anchorme.list(text);
|
|
||||||
|
|
||||||
let children = [];
|
let children = [];
|
||||||
let last = 0;
|
let last = 0;
|
||||||
links.forEach((match) => {
|
links.forEach((match) => {
|
||||||
|
if (!match.isLink) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const prefix = text.substring(last, match.start)
|
const prefix = text.substring(last, match.start)
|
||||||
children.push(...linkifyChannel(prefix, transformChannel));
|
children.push(prefix);
|
||||||
|
|
||||||
let proto = match.protocol || "https://";
|
// TODO: handle all irc/ircs URLs
|
||||||
if (match.isEmail) {
|
if (match.href.startsWith("irc:///")) {
|
||||||
proto = "mailto:";
|
function onClick(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
onChannelClick(match.value);
|
||||||
}
|
}
|
||||||
|
children.push(html`
|
||||||
let url = match.string;
|
<a
|
||||||
if (!url.startsWith(proto)) {
|
href="${match.href}"
|
||||||
url = proto + url;
|
onClick=${onClick}
|
||||||
|
>${match.value}</a>
|
||||||
|
`);
|
||||||
|
} else {
|
||||||
|
children.push(html`
|
||||||
|
<a
|
||||||
|
href=${match.href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>${match.value}</a>
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
children.push(html`<a href=${url} target="_blank" rel="noreferrer noopener">${match.string}</a>`);
|
|
||||||
|
|
||||||
last = match.end;
|
last = match.end;
|
||||||
});
|
});
|
||||||
|
|
||||||
const suffix = text.substring(last)
|
const suffix = text.substring(last)
|
||||||
children.push(...linkifyChannel(suffix, transformChannel));
|
children.push(suffix);
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
22
package-lock.json
generated
22
package-lock.json
generated
@ -6,19 +6,14 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "gamja",
|
"name": "gamja",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anchorme": "^2.1.2",
|
|
||||||
"htm": "^3.0.4",
|
"htm": "^3.0.4",
|
||||||
|
"linkifyjs": "^3.0.2",
|
||||||
"preact": "^10.5.9"
|
"preact": "^10.5.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"http-server": "^13.0.2"
|
"http-server": "^13.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/anchorme": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/anchorme/-/anchorme-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-2iPY3kxDDZvtRzauqKDb4v7a5sTF4GZ+esQTY8nGYvmhAtGTeFPMn4cRnvyWS1qmtPTP0Mv8hyLOp9l3ZzWMKg=="
|
|
||||||
},
|
|
||||||
"node_modules/async": {
|
"node_modules/async": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
||||||
@ -201,6 +196,11 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/linkifyjs": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-PSHDxSAWkZQ208W4PI/+yo9NHSI6NAHKmazMtyRavyibJgrPOioPIjQn7zyapASQlKoPmAV+tOlqzTqX3XFWXQ=="
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
@ -345,11 +345,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anchorme": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/anchorme/-/anchorme-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-2iPY3kxDDZvtRzauqKDb4v7a5sTF4GZ+esQTY8nGYvmhAtGTeFPMn4cRnvyWS1qmtPTP0Mv8hyLOp9l3ZzWMKg=="
|
|
||||||
},
|
|
||||||
"async": {
|
"async": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
||||||
@ -482,6 +477,11 @@
|
|||||||
"url-join": "^2.0.5"
|
"url-join": "^2.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"linkifyjs": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-PSHDxSAWkZQ208W4PI/+yo9NHSI6NAHKmazMtyRavyibJgrPOioPIjQn7zyapASQlKoPmAV+tOlqzTqX3XFWXQ=="
|
||||||
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "gamja",
|
"name": "gamja",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anchorme": "^2.1.2",
|
|
||||||
"htm": "^3.0.4",
|
"htm": "^3.0.4",
|
||||||
|
"linkifyjs": "^3.0.2",
|
||||||
"preact": "^10.5.9"
|
"preact": "^10.5.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user