diff --git a/package.json b/package.json
index b7f59aae8a..f4af7b8313 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
},
"dependencies": {
"@babel/runtime": "^7.12.5",
+ "@types/commonmark": "^0.27.4",
"await-lock": "^2.1.0",
"blurhash": "^1.1.3",
"browser-encrypt-attachment": "^0.3.0",
diff --git a/src/Markdown.js b/src/Markdown.ts
similarity index 74%
rename from src/Markdown.js
rename to src/Markdown.ts
index f670bded12..96169d4011 100644
--- a/src/Markdown.js
+++ b/src/Markdown.ts
@@ -1,5 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
+Copyright 2021 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,16 +16,24 @@ limitations under the License.
*/
import * as commonmark from 'commonmark';
-import {escape} from "lodash";
+import { escape } from "lodash";
const ALLOWED_HTML_TAGS = ['sub', 'sup', 'del', 'u'];
// These types of node are definitely text
const TEXT_NODES = ['text', 'softbreak', 'linebreak', 'paragraph', 'document'];
-function is_allowed_html_tag(node) {
+// As far as @types/commonmark is concerned, these are not public, so add them
+interface CommonmarkHtmlRendererInternal extends commonmark.HtmlRenderer {
+ paragraph: (node: commonmark.Node, entering: boolean) => void;
+ link: (node: commonmark.Node, entering: boolean) => void;
+ html_inline: (node: commonmark.Node) => void; // eslint-disable-line camelcase
+ html_block: (node: commonmark.Node) => void; // eslint-disable-line camelcase
+}
+
+function isAllowedHtmlTag(node: commonmark.Node): boolean {
if (node.literal != null &&
- node.literal.match('^<((div|span) data-mx-maths="[^"]*"|\/(div|span))>$') != null) {
+ node.literal.match('^<((div|span) data-mx-maths="[^"]*"|/(div|span))>$') != null) {
return true;
}
@@ -39,21 +48,12 @@ function is_allowed_html_tag(node) {
return false;
}
-function html_if_tag_allowed(node) {
- if (is_allowed_html_tag(node)) {
- this.lit(node.literal);
- return;
- } else {
- this.lit(escape(node.literal));
- }
-}
-
/*
* Returns true if the parse output containing the node
* comprises multiple block level elements (ie. lines),
* or false if it is only a single line.
*/
-function is_multi_line(node) {
+function isMultiLine(node: commonmark.Node): boolean {
let par = node;
while (par.parent) {
par = par.parent;
@@ -67,6 +67,9 @@ function is_multi_line(node) {
* it's plain text.
*/
export default class Markdown {
+ private input: string;
+ private parsed: commonmark.Node;
+
constructor(input) {
this.input = input;
@@ -74,7 +77,7 @@ export default class Markdown {
this.parsed = parser.parse(this.input);
}
- isPlainText() {
+ isPlainText(): boolean {
const walker = this.parsed.walker();
let ev;
@@ -87,7 +90,7 @@ export default class Markdown {
// if it's an allowed html tag, we need to render it and therefore
// we will need to use HTML. If it's not allowed, it's not HTML since
// we'll just be treating it as text.
- if (is_allowed_html_tag(node)) {
+ if (isAllowedHtmlTag(node)) {
return false;
}
} else {
@@ -97,7 +100,7 @@ export default class Markdown {
return true;
}
- toHTML({ externalLinks = false } = {}) {
+ toHTML({ externalLinks = false } = {}): string {
const renderer = new commonmark.HtmlRenderer({
safe: false,
@@ -107,7 +110,7 @@ export default class Markdown {
// block quote ends up all on one line
// (https://github.com/vector-im/element-web/issues/3154)
softbreak: '
',
- });
+ }) as CommonmarkHtmlRendererInternal;
// Trying to strip out the wrapping