Try convert matrix links to internal links
This commit is contained in:
parent
e5da97fbdf
commit
f955397a37
2 changed files with 26 additions and 5 deletions
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import { MessageBody, HeaderBlock, TableBlock, ListBlock, CodeBlock, PillPart, FormatPart, NewLinePart, RulePart, TextPart, LinkPart, ImagePart } from "./MessageBody.js"
|
import { MessageBody, HeaderBlock, TableBlock, ListBlock, CodeBlock, PillPart, FormatPart, NewLinePart, RulePart, TextPart, LinkPart, ImagePart } from "./MessageBody.js"
|
||||||
import { linkify } from "./linkify/linkify.js";
|
import { linkify } from "./linkify/linkify.js";
|
||||||
|
import {MatrixURL} from "matrix-uri-parser";
|
||||||
|
|
||||||
/* At the time of writing (Jul 1 2021), Matrix Spec recommends
|
/* At the time of writing (Jul 1 2021), Matrix Spec recommends
|
||||||
* allowing the following HTML tags:
|
* allowing the following HTML tags:
|
||||||
|
@ -34,10 +35,11 @@ const baseUrl = 'https://matrix.to';
|
||||||
const linkPrefix = `${baseUrl}/#/`;
|
const linkPrefix = `${baseUrl}/#/`;
|
||||||
|
|
||||||
class Deserializer {
|
class Deserializer {
|
||||||
constructor(result, mediaRepository, allowReplies) {
|
constructor(result, mediaRepository, allowReplies, linkHandler) {
|
||||||
this.allowReplies = allowReplies;
|
this.allowReplies = allowReplies;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.mediaRepository = mediaRepository;
|
this.mediaRepository = mediaRepository;
|
||||||
|
this.linkHandler = linkHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsePillLink(link) {
|
parsePillLink(link) {
|
||||||
|
@ -51,6 +53,13 @@ class Deserializer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseMatrixLink(link) {
|
||||||
|
if (!link.startsWith("matrix:")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new MatrixURL(link);
|
||||||
|
}
|
||||||
|
|
||||||
parseLink(node, children) {
|
parseLink(node, children) {
|
||||||
const href = this.result.getAttributeValue(node, "href");
|
const href = this.result.getAttributeValue(node, "href");
|
||||||
const lcUrl = href?.toLowerCase();
|
const lcUrl = href?.toLowerCase();
|
||||||
|
@ -58,8 +67,12 @@ class Deserializer {
|
||||||
if (!lcUrl || !safeSchemas.some(schema => lcUrl.startsWith(schema))) {
|
if (!lcUrl || !safeSchemas.some(schema => lcUrl.startsWith(schema))) {
|
||||||
return new FormatPart("span", children);
|
return new FormatPart("span", children);
|
||||||
}
|
}
|
||||||
|
const matrixUrl = this.parseMatrixLink(href);
|
||||||
const pillId = this.parsePillLink(href);
|
const pillId = this.parsePillLink(href);
|
||||||
if (pillId) {
|
let replaceHref = null;
|
||||||
|
if (matrixUrl && (replaceHref = this.linkHandler(matrixUrl))) {
|
||||||
|
return new LinkPart(replaceHref, children, true);
|
||||||
|
} else if (pillId) {
|
||||||
return new PillPart(pillId, href, children);
|
return new PillPart(pillId, href, children);
|
||||||
}
|
}
|
||||||
return new LinkPart(href, children);
|
return new LinkPart(href, children);
|
||||||
|
@ -345,9 +358,9 @@ class Deserializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseHTMLBody(platform, mediaRepository, allowReplies, html) {
|
export function parseHTMLBody(platform, mediaRepository, allowReplies, linkHandler, html) {
|
||||||
const parseResult = platform.parseHTML(html);
|
const parseResult = platform.parseHTML(html);
|
||||||
const deserializer = new Deserializer(parseResult, mediaRepository, allowReplies);
|
const deserializer = new Deserializer(parseResult, mediaRepository, allowReplies, linkHandler);
|
||||||
const parts = deserializer.parseAnyNodes(parseResult.rootNodes);
|
const parts = deserializer.parseAnyNodes(parseResult.rootNodes);
|
||||||
return new MessageBody(html, parts);
|
return new MessageBody(html, parts);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import {BaseTextTile, BodyFormat} from "./BaseTextTile.js";
|
import {BaseTextTile, BodyFormat} from "./BaseTextTile.js";
|
||||||
import {parsePlainBody} from "../MessageBody.js";
|
import {parsePlainBody} from "../MessageBody.js";
|
||||||
import {parseHTMLBody} from "../deserialize.js";
|
import {parseHTMLBody} from "../deserialize.js";
|
||||||
|
import {EntityType} from "matrix-uri-parser";
|
||||||
|
|
||||||
export class TextTile extends BaseTextTile {
|
export class TextTile extends BaseTextTile {
|
||||||
_getContentString(key) {
|
_getContentString(key) {
|
||||||
|
@ -47,10 +48,17 @@ export class TextTile extends BaseTextTile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_customMatrixUrl(url) {
|
||||||
|
if (url.kind === EntityType.RoomId) {
|
||||||
|
return this.urlCreator.openRoomActionUrl("!" + url.id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
_parseBody(body, format) {
|
_parseBody(body, format) {
|
||||||
let messageBody;
|
let messageBody;
|
||||||
if (format === BodyFormat.Html) {
|
if (format === BodyFormat.Html) {
|
||||||
messageBody = parseHTMLBody(this.platform, this._mediaRepository, this._entry.isReply, body);
|
messageBody = parseHTMLBody(this.platform, this._mediaRepository, this._entry.isReply, this._customMatrixUrl.bind(this), body);
|
||||||
} else {
|
} else {
|
||||||
messageBody = parsePlainBody(body);
|
messageBody = parsePlainBody(body);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue