mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 12:45:11 +08:00
Upgrade linkify to v3.0 (#7282)
Co-authored-by: Timo K <toger5@hotmail.de>
This commit is contained in:
parent
c0681333bf
commit
336e1ae3b6
@ -85,7 +85,9 @@
|
||||
"is-ip": "^3.1.0",
|
||||
"jszip": "^3.7.0",
|
||||
"katex": "^0.12.0",
|
||||
"linkifyjs": "^2.1.9",
|
||||
"linkify-element": "^3.0.4",
|
||||
"linkify-string": "^3.0.4",
|
||||
"linkifyjs": "^3.0.5",
|
||||
"lodash": "^4.17.20",
|
||||
"maplibre-gl": "^1.15.2",
|
||||
"matrix-analytics-events": "https://github.com/matrix-org/matrix-analytics-events.git#1eab4356548c97722a183912fda1ceabbe8cc7c1",
|
||||
|
@ -16,9 +16,10 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import * as linkifyjs from 'linkifyjs';
|
||||
import linkifyElement from 'linkifyjs/element';
|
||||
import linkifyString from 'linkifyjs/string';
|
||||
import linkifyElement from 'linkify-element';
|
||||
import linkifyString from 'linkify-string';
|
||||
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||
import { registerPlugin } from 'linkifyjs';
|
||||
|
||||
import { baseUrl } from "./utils/permalinks/SpecPermalinkConstructor";
|
||||
import {
|
||||
@ -37,73 +38,82 @@ enum Type {
|
||||
GroupId = "groupid"
|
||||
}
|
||||
|
||||
// Linkifyjs types don't have parser, which really makes this harder.
|
||||
const linkifyTokens = (linkifyjs as any).scanner.TOKENS;
|
||||
enum MatrixLinkInitialToken {
|
||||
POUND = linkifyTokens.POUND,
|
||||
PLUS = linkifyTokens.PLUS,
|
||||
AT = linkifyTokens.AT,
|
||||
}
|
||||
// Linkify stuff doesn't type scanner/parser/utils properly :/
|
||||
function matrixOpaqueIdLinkifyParser({
|
||||
scanner,
|
||||
parser,
|
||||
utils,
|
||||
token,
|
||||
name,
|
||||
}: {
|
||||
scanner: any;
|
||||
parser: any;
|
||||
utils: any;
|
||||
token: '#' | '+' | '@';
|
||||
name: Type;
|
||||
}) {
|
||||
const {
|
||||
DOMAIN,
|
||||
DOT,
|
||||
// A generic catchall text token
|
||||
TEXT,
|
||||
NUM,
|
||||
TLD,
|
||||
COLON,
|
||||
SYM,
|
||||
UNDERSCORE,
|
||||
// because 'localhost' is tokenised to the localhost token,
|
||||
// usernames @localhost:foo.com are otherwise not matched!
|
||||
LOCALHOST,
|
||||
} = scanner.tokens;
|
||||
|
||||
/**
|
||||
* Token should be one of the type of linkify.parser.TOKENS[AT | PLUS | POUND]
|
||||
* but due to typing issues it's just not a feasible solution.
|
||||
* This problem kind of gets solved in linkify 3.0
|
||||
*/
|
||||
function parseFreeformMatrixLinks(linkify, token: MatrixLinkInitialToken, type: Type): void {
|
||||
// Text tokens
|
||||
const TT = linkify.scanner.TOKENS;
|
||||
// Multi tokens
|
||||
const MT = linkify.parser.TOKENS;
|
||||
const MultiToken = MT.Base;
|
||||
const S_START = linkify.parser.start;
|
||||
const S_START = parser.start;
|
||||
const matrixSymbol = utils.createTokenClass(name, { isLink: true });
|
||||
|
||||
const TOKEN = function(value) {
|
||||
MultiToken.call(this, value);
|
||||
this.type = type;
|
||||
this.isLink = true;
|
||||
};
|
||||
TOKEN.prototype = new MultiToken();
|
||||
|
||||
const S_TOKEN = S_START.jump(token);
|
||||
const S_TOKEN_NAME = new linkify.parser.State();
|
||||
const S_TOKEN_NAME_COLON = new linkify.parser.State();
|
||||
const S_TOKEN_NAME_COLON_DOMAIN = new linkify.parser.State(TOKEN);
|
||||
const S_TOKEN_NAME_COLON_DOMAIN_DOT = new linkify.parser.State();
|
||||
const S_MX_LINK = new linkify.parser.State(TOKEN);
|
||||
const S_MX_LINK_COLON = new linkify.parser.State();
|
||||
const S_MX_LINK_COLON_NUM = new linkify.parser.State(TOKEN);
|
||||
|
||||
const allowedFreeformTokens = [
|
||||
TT.DOT,
|
||||
TT.PLUS,
|
||||
TT.NUM,
|
||||
TT.DOMAIN,
|
||||
TT.TLD,
|
||||
TT.UNDERSCORE,
|
||||
token,
|
||||
const localpartTokens = [
|
||||
DOMAIN,
|
||||
// IPV4 necessity
|
||||
NUM,
|
||||
TLD,
|
||||
|
||||
// because 'localhost' is tokenised to the localhost token,
|
||||
// usernames @localhost:foo.com are otherwise not matched!
|
||||
TT.LOCALHOST,
|
||||
LOCALHOST,
|
||||
SYM,
|
||||
UNDERSCORE,
|
||||
TEXT,
|
||||
];
|
||||
const domainpartTokens = [DOMAIN, NUM, TLD, LOCALHOST];
|
||||
|
||||
S_TOKEN.on(allowedFreeformTokens, S_TOKEN_NAME);
|
||||
S_TOKEN_NAME.on(allowedFreeformTokens, S_TOKEN_NAME);
|
||||
S_TOKEN_NAME.on(TT.DOMAIN, S_TOKEN_NAME);
|
||||
const INITIAL_STATE = S_START.tt(token);
|
||||
|
||||
S_TOKEN_NAME.on(TT.COLON, S_TOKEN_NAME_COLON);
|
||||
const LOCALPART_STATE = INITIAL_STATE.tt(DOMAIN);
|
||||
for (const token of localpartTokens) {
|
||||
INITIAL_STATE.tt(token, LOCALPART_STATE);
|
||||
LOCALPART_STATE.tt(token, LOCALPART_STATE);
|
||||
}
|
||||
const LOCALPART_STATE_DOT = LOCALPART_STATE.tt(DOT);
|
||||
for (const token of localpartTokens) {
|
||||
LOCALPART_STATE_DOT.tt(token, LOCALPART_STATE);
|
||||
}
|
||||
|
||||
S_TOKEN_NAME_COLON.on(TT.DOMAIN, S_TOKEN_NAME_COLON_DOMAIN);
|
||||
S_TOKEN_NAME_COLON.on(TT.LOCALHOST, S_MX_LINK); // accept #foo:localhost
|
||||
S_TOKEN_NAME_COLON.on(TT.TLD, S_MX_LINK); // accept #foo:com (mostly for (TLD|DOMAIN)+ mixing)
|
||||
S_TOKEN_NAME_COLON_DOMAIN.on(TT.DOT, S_TOKEN_NAME_COLON_DOMAIN_DOT);
|
||||
S_TOKEN_NAME_COLON_DOMAIN_DOT.on(TT.DOMAIN, S_TOKEN_NAME_COLON_DOMAIN);
|
||||
S_TOKEN_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_MX_LINK);
|
||||
const DOMAINPART_STATE_DOT = LOCALPART_STATE.tt(COLON);
|
||||
const DOMAINPART_STATE = DOMAINPART_STATE_DOT.tt(DOMAIN);
|
||||
DOMAINPART_STATE.tt(DOT, DOMAINPART_STATE_DOT);
|
||||
for (const token of domainpartTokens) {
|
||||
DOMAINPART_STATE.tt(token, DOMAINPART_STATE);
|
||||
// we are done if we have a domain
|
||||
DOMAINPART_STATE.tt(token, matrixSymbol);
|
||||
}
|
||||
|
||||
S_MX_LINK.on(TT.DOT, S_TOKEN_NAME_COLON_DOMAIN_DOT); // accept repeated TLDs (e.g .org.uk)
|
||||
S_MX_LINK.on(TT.COLON, S_MX_LINK_COLON); // do not accept trailing `:`
|
||||
S_MX_LINK_COLON.on(TT.NUM, S_MX_LINK_COLON_NUM); // but do accept :NUM (port specifier)
|
||||
// accept repeated TLDs (e.g .org.uk) but do not accept double dots: ..
|
||||
for (const token of domainpartTokens) {
|
||||
DOMAINPART_STATE_DOT.tt(token, DOMAINPART_STATE);
|
||||
}
|
||||
|
||||
const PORT_STATE = DOMAINPART_STATE.tt(COLON);
|
||||
|
||||
PORT_STATE.tt(NUM, matrixSymbol);
|
||||
}
|
||||
|
||||
function onUserClick(event: MouseEvent, userId: string) {
|
||||
@ -199,10 +209,12 @@ export const options = {
|
||||
}
|
||||
},
|
||||
|
||||
linkAttributes: {
|
||||
attributes: {
|
||||
rel: 'noreferrer noopener',
|
||||
},
|
||||
|
||||
className: 'linkified',
|
||||
|
||||
target: function(href: string, type: Type | string): string {
|
||||
if (type === Type.URL) {
|
||||
try {
|
||||
@ -221,12 +233,38 @@ export const options = {
|
||||
};
|
||||
|
||||
// Run the plugins
|
||||
// Linkify room aliases
|
||||
parseFreeformMatrixLinks(linkifyjs, MatrixLinkInitialToken.POUND, Type.RoomAlias);
|
||||
// Linkify group IDs
|
||||
parseFreeformMatrixLinks(linkifyjs, MatrixLinkInitialToken.PLUS, Type.GroupId);
|
||||
// Linkify user IDs
|
||||
parseFreeformMatrixLinks(linkifyjs, MatrixLinkInitialToken.AT, Type.UserId);
|
||||
registerPlugin(Type.RoomAlias, ({ scanner, parser, utils }) => {
|
||||
const token = scanner.tokens.POUND as '#';
|
||||
return matrixOpaqueIdLinkifyParser({
|
||||
scanner,
|
||||
parser,
|
||||
utils,
|
||||
token,
|
||||
name: Type.RoomAlias,
|
||||
});
|
||||
});
|
||||
|
||||
registerPlugin(Type.GroupId, ({ scanner, parser, utils }) => {
|
||||
const token = scanner.tokens.PLUS as '+';
|
||||
return matrixOpaqueIdLinkifyParser({
|
||||
scanner,
|
||||
parser,
|
||||
utils,
|
||||
token,
|
||||
name: Type.GroupId,
|
||||
});
|
||||
});
|
||||
|
||||
registerPlugin(Type.UserId, ({ scanner, parser, utils }) => {
|
||||
const token = scanner.tokens.AT as '@';
|
||||
return matrixOpaqueIdLinkifyParser({
|
||||
scanner,
|
||||
parser,
|
||||
utils,
|
||||
token,
|
||||
name: Type.UserId,
|
||||
});
|
||||
});
|
||||
|
||||
export const linkify = linkifyjs;
|
||||
export const _linkifyElement = linkifyElement;
|
||||
|
@ -16,215 +16,252 @@ limitations under the License.
|
||||
import { linkify } from '../src/linkify-matrix';
|
||||
|
||||
describe('linkify-matrix', () => {
|
||||
describe('roomalias', () => {
|
||||
it('properly parses #_foonetic_xkcd:matrix.org', () => {
|
||||
const test = '#_foonetic_xkcd:matrix.org';
|
||||
const linkTypesByInitialCharacter = {
|
||||
'#': 'roomalias',
|
||||
'@': 'userid',
|
||||
'+': 'groupid',
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param testName Due to all the tests using the same logic underneath, it makes to generate it in a bit smarter way
|
||||
* @param char
|
||||
*/
|
||||
function genTests(char: '#' | '@' | '+') {
|
||||
const type = linkTypesByInitialCharacter[char];
|
||||
it('should not parse ' + char + 'foo without domain', () => {
|
||||
const test = char + "foo";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([]));
|
||||
});
|
||||
describe('ip v4 tests', () => {
|
||||
it('should properly parse IPs v4 as the domain name', () => {
|
||||
const test = char + 'potato:1.2.3.4';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: char + 'potato:1.2.3.4',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length,
|
||||
value: char + 'potato:1.2.3.4',
|
||||
}]));
|
||||
});
|
||||
it('should properly parse IPs v4 with port as the domain name with attached', () => {
|
||||
const test = char + 'potato:1.2.3.4:1337';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: char + 'potato:1.2.3.4:1337',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length,
|
||||
value: char + 'potato:1.2.3.4:1337',
|
||||
}]));
|
||||
});
|
||||
it('should properly parse IPs v4 as the domain name while ignoring missing port', () => {
|
||||
const test = char + 'potato:1.2.3.4:';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: char + 'potato:1.2.3.4',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length - 1,
|
||||
value: char + 'potato:1.2.3.4',
|
||||
}]));
|
||||
});
|
||||
});
|
||||
// Currently those tests are failing, as there's missing implementation.
|
||||
describe.skip('ip v6 tests', () => {
|
||||
it('should properly parse IPs v6 as the domain name', () => {
|
||||
const test = char + "username:[1234:5678::abcd]";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual([{
|
||||
href: char + 'username:[1234:5678::abcd]',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length,
|
||||
value: char + 'username:[1234:5678::abcd]',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should properly parse IPs v6 with port as the domain name', () => {
|
||||
const test = char + "username:[1234:5678::abcd]:1337";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual([{
|
||||
href: char + 'username:[1234:5678::abcd]:1337',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length,
|
||||
value: char + 'username:[1234:5678::abcd]:1337',
|
||||
},
|
||||
]);
|
||||
});
|
||||
// eslint-disable-next-line max-len
|
||||
it('should properly parse IPs v6 while ignoring dangling comma when without port name as the domain name', () => {
|
||||
const test = char + "username:[1234:5678::abcd]:";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual([{
|
||||
href: char + 'username:[1234:5678::abcd]:',
|
||||
type,
|
||||
isLink: true,
|
||||
start: 0,
|
||||
end: test.length - 1,
|
||||
value: char + 'username:[1234:5678::abcd]:',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('properly parses ' + char + '_foonetic_xkcd:matrix.org', () => {
|
||||
const test = '' + char + '_foonetic_xkcd:matrix.org';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#_foonetic_xkcd:matrix.org",
|
||||
type: "roomalias",
|
||||
value: "#_foonetic_xkcd:matrix.org",
|
||||
href: char + "_foonetic_xkcd:matrix.org",
|
||||
type,
|
||||
value: char + "_foonetic_xkcd:matrix.org",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('properly parses #foo:localhost', () => {
|
||||
const test = "#foo:localhost";
|
||||
it('properly parses ' + char + 'foo:localhost', () => {
|
||||
const test = char + "foo:localhost";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:localhost",
|
||||
type: "roomalias",
|
||||
value: "#foo:localhost",
|
||||
href: char + "foo:localhost",
|
||||
type,
|
||||
value: char + "foo:localhost",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('accept #foo:bar.com', () => {
|
||||
const test = '#foo:bar.com';
|
||||
it('accept ' + char + 'foo:bar.com', () => {
|
||||
const test = '' + char + 'foo:bar.com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:bar.com",
|
||||
type: "roomalias",
|
||||
value: "#foo:bar.com",
|
||||
href: char + "foo:bar.com",
|
||||
type,
|
||||
value: char + "foo:bar.com",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('accept #foo:com (mostly for (TLD|DOMAIN)+ mixing)', () => {
|
||||
const test = '#foo:com';
|
||||
it('accept ' + char + 'foo:com (mostly for (TLD|DOMAIN)+ mixing)', () => {
|
||||
const test = '' + char + 'foo:com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:com",
|
||||
type: "roomalias",
|
||||
value: "#foo:com",
|
||||
href: char + "foo:com",
|
||||
type,
|
||||
value: char + "foo:com",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('accept repeated TLDs (e.g .org.uk)', () => {
|
||||
const test = '#foo:bar.org.uk';
|
||||
const test = '' + char + 'foo:bar.org.uk';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:bar.org.uk",
|
||||
type: "roomalias",
|
||||
value: "#foo:bar.org.uk",
|
||||
href: char + "foo:bar.org.uk",
|
||||
type,
|
||||
value: char + "foo:bar.org.uk",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('ignores trailing `:`', () => {
|
||||
const test = '#foo:bar.com:';
|
||||
const test = '' + char + 'foo:bar.com:';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:bar.com",
|
||||
type: "roomalias",
|
||||
value: "#foo:bar.com",
|
||||
type,
|
||||
value: char + "foo:bar.com",
|
||||
href: char + 'foo:bar.com',
|
||||
start: 0,
|
||||
end: test.length - ":".length,
|
||||
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('accept :NUM (port specifier)', () => {
|
||||
const test = '#foo:bar.com:2225';
|
||||
const test = '' + char + 'foo:bar.com:2225';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:bar.com:2225",
|
||||
type: "roomalias",
|
||||
value: "#foo:bar.com:2225",
|
||||
href: char + "foo:bar.com:2225",
|
||||
type,
|
||||
value: char + "foo:bar.com:2225",
|
||||
start: 0,
|
||||
end: test.length,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('ignores all the trailing :', () => {
|
||||
const test = '#foo:bar.com::::';
|
||||
const test = '' + char + 'foo:bar.com::::';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo:bar.com",
|
||||
type: "roomalias",
|
||||
value: "#foo:bar.com",
|
||||
href: char + "foo:bar.com",
|
||||
type,
|
||||
value: char + "foo:bar.com",
|
||||
end: test.length - 4,
|
||||
start: 0,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('properly parses room alias with dots in name', () => {
|
||||
const test = '#foo.asdf:bar.com::::';
|
||||
const test = '' + char + 'foo.asdf:bar.com::::';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "#foo.asdf:bar.com",
|
||||
type: "roomalias",
|
||||
value: "#foo.asdf:bar.com",
|
||||
href: char + "foo.asdf:bar.com",
|
||||
type,
|
||||
value: char + "foo.asdf:bar.com",
|
||||
start: 0,
|
||||
end: test.length - ":".repeat(4).length,
|
||||
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
it('does not parse room alias with too many separators', () => {
|
||||
const test = '#foo:::bar.com';
|
||||
const test = '' + char + 'foo:::bar.com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "http://bar.com",
|
||||
type: "url",
|
||||
value: "bar.com",
|
||||
isLink: true,
|
||||
start: 7,
|
||||
end: test.length,
|
||||
}]));
|
||||
});
|
||||
it('does not parse multiple room aliases in one string', () => {
|
||||
const test = '#foo:bar.com-baz.com';
|
||||
const test = '' + char + 'foo:bar.com-baz.com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
"href": "#foo:bar.com-baz.com",
|
||||
"type": "roomalias",
|
||||
"value": "#foo:bar.com-baz.com",
|
||||
href: char + "foo:bar.com-baz.com",
|
||||
type,
|
||||
value: char + "foo:bar.com-baz.com",
|
||||
end: 20,
|
||||
start: 0,
|
||||
isLink: true,
|
||||
}]));
|
||||
});
|
||||
}
|
||||
|
||||
describe('roomalias plugin', () => {
|
||||
genTests('#');
|
||||
});
|
||||
|
||||
describe('groupid', () => {
|
||||
it('properly parses +foo:localhost', () => {
|
||||
const test = "+foo:localhost";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "+foo:localhost",
|
||||
type: "groupid",
|
||||
value: "+foo:localhost",
|
||||
}]));
|
||||
});
|
||||
it('accept +foo:bar.com', () => {
|
||||
const test = '+foo:bar.com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "+foo:bar.com",
|
||||
type: "groupid",
|
||||
value: "+foo:bar.com",
|
||||
}]));
|
||||
});
|
||||
it('accept +foo:com (mostly for (TLD|DOMAIN)+ mixing)', () => {
|
||||
const test = '+foo:com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "+foo:com",
|
||||
type: "groupid",
|
||||
value: "+foo:com",
|
||||
}]));
|
||||
});
|
||||
it('accept repeated TLDs (e.g .org.uk)', () => {
|
||||
const test = '+foo:bar.org.uk';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "+foo:bar.org.uk",
|
||||
type: "groupid",
|
||||
value: "+foo:bar.org.uk",
|
||||
}]));
|
||||
});
|
||||
it('ignore trailing `:`', () => {
|
||||
const test = '+foo:bar.com:';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
"href": "+foo:bar.com",
|
||||
"type": "groupid",
|
||||
"value": "+foo:bar.com",
|
||||
}]));
|
||||
});
|
||||
it('accept :NUM (port specifier)', () => {
|
||||
const test = '+foo:bar.com:2225';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "+foo:bar.com:2225",
|
||||
type: "groupid",
|
||||
value: "+foo:bar.com:2225",
|
||||
}]));
|
||||
});
|
||||
describe('groupid plugin', () => {
|
||||
genTests('+');
|
||||
});
|
||||
|
||||
describe('userid', () => {
|
||||
it('should not parse @foo without domain', () => {
|
||||
const test = "@foo";
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([]));
|
||||
});
|
||||
it('accept @foo:bar.com', () => {
|
||||
const test = '@foo:bar.com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "@foo:bar.com",
|
||||
type: "userid",
|
||||
value: "@foo:bar.com",
|
||||
}]));
|
||||
});
|
||||
it('accept @foo:com (mostly for (TLD|DOMAIN)+ mixing)', () => {
|
||||
const test = '@foo:com';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "@foo:com",
|
||||
type: "userid",
|
||||
value: "@foo:com",
|
||||
}]));
|
||||
});
|
||||
it('accept repeated TLDs (e.g .org.uk)', () => {
|
||||
const test = '@foo:bar.org.uk';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "@foo:bar.org.uk",
|
||||
type: "userid",
|
||||
value: "@foo:bar.org.uk",
|
||||
}]));
|
||||
});
|
||||
it('do not accept trailing `:`', () => {
|
||||
const test = '@foo:bar.com:';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "@foo:bar.com",
|
||||
type: "userid",
|
||||
value: "@foo:bar.com",
|
||||
}]));
|
||||
});
|
||||
it('accept :NUM (port specifier)', () => {
|
||||
const test = '@foo:bar.com:2225';
|
||||
const found = linkify.find(test);
|
||||
expect(found).toEqual(([{
|
||||
href: "@foo:bar.com:2225",
|
||||
type: "userid",
|
||||
value: "@foo:bar.com:2225",
|
||||
}]));
|
||||
});
|
||||
describe('userid plugin', () => {
|
||||
genTests('@');
|
||||
});
|
||||
});
|
||||
|
20
yarn.lock
20
yarn.lock
@ -3706,7 +3706,7 @@ eslint-module-utils@^2.7.2:
|
||||
debug "^3.2.7"
|
||||
find-up "^2.1.0"
|
||||
|
||||
eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.25.4:
|
||||
eslint-plugin-import@^2.25.4:
|
||||
version "2.25.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
|
||||
integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
|
||||
@ -5968,10 +5968,20 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
linkifyjs@^2.1.9:
|
||||
version "2.1.9"
|
||||
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.9.tgz#af06e45a2866ff06c4766582590d098a4d584702"
|
||||
integrity sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==
|
||||
linkify-element@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/linkify-element/-/linkify-element-3.0.4.tgz#3566a3b48d4c211a684f42a23a9964bf53f3a31a"
|
||||
integrity sha512-xrj2Upv4/XUxvvczoDwojEnzKnfJCHlorAxYmdFPSGNwLz2sXYkYyB7Lw1flkGS7L0yS0dq/HwOotG0Kpaiaxw==
|
||||
|
||||
linkify-string@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/linkify-string/-/linkify-string-3.0.4.tgz#6abf1a5e436e800c729274ae08f5703484647f84"
|
||||
integrity sha512-OnNqqRjlYXaXipIAbBC8sDXsSumI1ftatzFg141Pw9HEXWjTVLFcMZoKbFupshqWRavtNJ6QHLa+u6AlxxgeRw==
|
||||
|
||||
linkifyjs@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.5.tgz#99e51a3a0c0e232fcb63ebb89eea3ff923378f34"
|
||||
integrity sha512-1Y9XQH65eQKA9p2xtk+zxvnTeQBG7rdAXSkUG97DmuI/Xhji9uaUzaWxRj6rf9YC0v8KKHkxav7tnLX82Sz5Fg==
|
||||
|
||||
loader-utils@^2.0.0:
|
||||
version "2.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user