diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 6ede36ee81..7fc6908caf 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017, 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -33,6 +34,7 @@ import url from 'url'; import EMOJIBASE from 'emojibase-data/en/compact.json'; import EMOJIBASE_REGEX from 'emojibase-regex'; +import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/RoomPermalinkCreator"; linkifyMatrix(linkify); @@ -158,30 +160,10 @@ const transformTags = { // custom to matrix if (attribs.href) { attribs.target = '_blank'; // by default - let m; - // FIXME: horrible duplication with linkify-matrix - m = attribs.href.match(linkifyMatrix.VECTOR_URL_PATTERN); - if (m) { - attribs.href = m[1]; + const transformed = tryTransformPermalinkToLocalHref(attribs.href); + if (transformed !== attribs.href || attribs.href.match(linkifyMatrix.VECTOR_URL_PATTERN)) { + attribs.href = transformed; delete attribs.target; - } else { - m = attribs.href.match(linkifyMatrix.MATRIXTO_URL_PATTERN); - if (m) { - const entity = m[1]; - switch (entity[0]) { - case '@': - attribs.href = '#/user/' + entity; - break; - case '+': - attribs.href = '#/group/' + entity; - break; - case '#': - case '!': - attribs.href = '#/room/' + entity; - break; - } - delete attribs.target; - } } } attribs.rel = 'noopener'; // https://mathiasbynens.github.io/rel-noopener/ diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index 2d72b7fb41..0bed83ce84 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,6 +16,7 @@ limitations under the License. */ import {baseUrl} from "./utils/permalinks/SpecPermalinkConstructor"; +import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/RoomPermalinkCreator"; function matrixLinkify(linkify) { // Text tokens @@ -225,20 +227,8 @@ matrixLinkify.options = { case 'roomalias': case 'userid': case 'groupid': - return matrixLinkify.MATRIXTO_BASE_URL + '/#/' + href; default: { - // FIXME: horrible duplication with HtmlUtils' transform tags - let m = href.match(matrixLinkify.VECTOR_URL_PATTERN); - if (m) { - return m[1]; - } - m = href.match(matrixLinkify.MATRIXTO_URL_PATTERN); - if (m) { - const entity = m[1]; - if (matrixToEntityMap[entity[0]]) return matrixToEntityMap[entity[0]] + entity; - } - - return href; + return tryTransformPermalinkToLocalHref(href); } } }, @@ -249,8 +239,8 @@ matrixLinkify.options = { target: function(href, type) { if (type === 'url') { - if (href.match(matrixLinkify.VECTOR_URL_PATTERN) || - href.match(matrixLinkify.MATRIXTO_URL_PATTERN)) { + const transformed = tryTransformPermalinkToLocalHref(href); + if (transformed !== href || href.match(matrixLinkify.VECTOR_URL_PATTERN)) { return null; } else { return '_blank'; diff --git a/src/utils/permalinks/RoomPermalinkCreator.js b/src/utils/permalinks/RoomPermalinkCreator.js index 82f92c80c9..489a6c8b82 100644 --- a/src/utils/permalinks/RoomPermalinkCreator.js +++ b/src/utils/permalinks/RoomPermalinkCreator.js @@ -20,6 +20,7 @@ import utils from 'matrix-js-sdk/lib/utils'; import SpecPermalinkConstructor, {baseUrl as matrixtoBaseUrl} from "./SpecPermalinkConstructor"; import PermalinkConstructor, {PermalinkParts} from "./PermalinkConstructor"; import RiotPermalinkConstructor from "./RiotPermalinkConstructor"; +import * as matrixLinkify from "../../linkify-matrix"; const SdkConfig = require("../../SdkConfig"); @@ -286,6 +287,40 @@ export function isPermalinkHost(host: string): boolean { return getPermalinkConstructor().isPermalinkHost(host); } +/** + * Transforms a permalink (or possible permalink) into a local URL if possible. If + * the given permalink is found to not be a permalink, it'll be returned unaltered. + */ +export function tryTransformPermalinkToLocalHref(permalink: string): string { + if (!permalink.startsWith("http:") && !permalink.startsWith("https:")) { + return permalink; + } + + let m = permalink.match(matrixLinkify.VECTOR_URL_PATTERN); + if (m) { + return m[1]; + } + + // A bit of a hack to convert permalinks of unknown origin to Riot links + try { + const permalinkParts = parsePermalink(permalink); + if (permalinkParts) { + if (permalinkParts.roomIdOrAlias) { + const eventIdPart = permalinkParts.eventId ? `/${permalinkParts.eventId}` : ''; + permalink = `#/room/${permalinkParts.roomIdOrAlias}${eventIdPart}`; + } else if (permalinkParts.groupId) { + permalink = `#/group/${permalinkParts.groupId}`; + } else if (permalinkParts.userId) { + permalink = `#/user/${permalinkParts.userId}`; + } // else not a valid permalink for our purposes - do not handle + } + } catch (e) { + // Not an href we need to care about + } + + return permalink; +} + function getPermalinkConstructor(): PermalinkConstructor { const riotPrefix = SdkConfig.get()['permalinkPrefix']; if (riotPrefix && riotPrefix !== matrixtoBaseUrl) {