Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintignore.errorfiles
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ src/components/views/settings/DevicesPanel.js
src/components/views/settings/IntegrationsManager.js
src/components/views/settings/Notifications.js
src/ContentMessages.js
src/HtmlUtils.js
src/ImageUtils.js
src/languageHandler.js
src/linkify-matrix.js
Expand Down
105 changes: 40 additions & 65 deletions src/HtmlUtils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017, 2018 New Vector Ltd
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -15,14 +16,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import ReplyThread from "./components/views/elements/ReplyThread";

const React = require('react');
const sanitizeHtml = require('sanitize-html');
const highlight = require('highlight.js');
const linkifyMatrix = require('./linkify-matrix');
import React from 'react';
import ReplyThread from './components/views/elements/ReplyThread';
import sanitizeHtml from 'sanitize-html';
import linkifyMatrix from './linkify-matrix';
import escape from 'lodash/escape';
import emojione from 'emojione';
import classNames from 'classnames';
Expand Down Expand Up @@ -64,11 +61,15 @@ export function containsEmoji(str) {
* because we want to include emoji shortnames in title text
*/
function unicodeToImage(str) {
let replaceWith, unicode, alt, short, fname;
let replaceWith;
let unicode;
let alt;
let short;
let fname;
const mappedUnicode = emojione.mapUnicodeToShort();

str = str.replace(emojione.regUnicode, function(unicodeChar) {
if ( (typeof unicodeChar === 'undefined') || (unicodeChar === '') || (!(unicodeChar in emojione.jsEscapeMap)) ) {
if ((typeof unicodeChar === 'undefined') || (unicodeChar === '') || (!(unicodeChar in emojione.jsEscapeMap))) {
// if the unicodeChar doesnt exist just return the entire match
return unicodeChar;
} else {
Expand All @@ -82,7 +83,8 @@ function unicodeToImage(str) {
alt = (emojione.unicodeAlt) ? emojione.convert(unicode.toUpperCase()) : mappedUnicode[unicode];
const title = mappedUnicode[unicode];

replaceWith = `<img class="mx_emojione" title="${title}" alt="${alt}" src="${emojione.imagePathSVG}${fname}.svg${emojione.cacheBustParam}"/>`;
replaceWith = `<img class="mx_emojione" title="${title}" alt="${alt}" ` +
`src="${emojione.imagePathSVG}${fname}.svg${emojione.cacheBustParam}"/>`;
return replaceWith;
}
});
Expand All @@ -95,10 +97,10 @@ function unicodeToImage(str) {
* character number), return an image node with the corresponding
* emoji.
*
* @param alt {string} String to use for the image alt text
* @param useSvg {boolean} Whether to use SVG image src. If False, PNG will be used.
* @param unicode {integer} One or more integers representing unicode characters
* @returns A img node with the corresponding emoji
* @param {string} alt String to use for the image alt text
* @param {boolean} useSvg Whether to use SVG image src. If False, PNG will be used.
* @param {number} unicode One or more integers representing unicode characters
* @returns {Element} A img node with the corresponding emoji
*/
export function charactersToImageNode(alt, useSvg, ...unicode) {
const fileName = unicode.map((u) => {
Expand Down Expand Up @@ -134,9 +136,7 @@ export function processHtmlForSending(html: string): string {
// Replace "<br>\n" with "\n" within `<pre>` tags because the <br> is
// redundant. This is a workaround for a bug in draft-js-export-html:
// https://github.com/sstur/draft-js-export-html/issues/62
contentHTML += '<pre>' +
element.innerHTML.replace(/<br>\n/g, '\n').trim() +
'</pre>';
contentHTML += `<pre>${element.innerHTML.replace(/<br>\n/g, '\n').trim()}</pre>`;
} else {
const temp = document.createElement('div');
temp.appendChild(element.cloneNode(true));
Expand All @@ -163,7 +163,8 @@ export function sanitizedHtmlNode(insaneHtml) {
* Note that the HTML sanitiser library has its own internal logic for
* doing this, to which we pass the same list of schemes. This is used in
* other places we need to sanitise URLs.
* @return true if permitted, otherwise false
* @param {string} inputUrl the url to test
* @return {boolean} true if permitted, otherwise false
*/
export function isUrlPermitted(inputUrl) {
try {
Expand Down Expand Up @@ -240,6 +241,11 @@ const sanitizeHtmlParams = {
attribs.width || 800,
attribs.height || 600,
);

if (!attribs.title && attribs.alt) {
attribs.title = attribs.alt;
}

return { tagName: tagName, attribs: attribs };
},
'code': function(tagName, attribs) {
Expand Down Expand Up @@ -304,10 +310,11 @@ class BaseHighlighter {
* @param {string[]} safeHighlights A list of substrings to highlight,
* sorted by descending length.
*
* returns a list of results (strings for HtmlHighligher, react nodes for
* @returns {*[]} a list of results (strings for HtmlHighligher, react nodes for
* TextHighlighter).
*/
applyHighlights(safeSnippet, safeHighlights) {
let subSnippet;
let lastOffset = 0;
let offset;
let nodes = [];
Expand All @@ -316,7 +323,7 @@ class BaseHighlighter {
while ((offset = safeSnippet.toLowerCase().indexOf(safeHighlight.toLowerCase(), lastOffset)) >= 0) {
// handle preamble
if (offset > lastOffset) {
var subSnippet = safeSnippet.substring(lastOffset, offset);
subSnippet = safeSnippet.substring(lastOffset, offset);
nodes = nodes.concat(this._applySubHighlights(subSnippet, safeHighlights));
}

Expand Down Expand Up @@ -361,57 +368,25 @@ class HtmlHighlighter extends BaseHighlighter {
return snippet;
}

let span = "<span class=\""+this.highlightClass+"\">"
+ snippet + "</span>";
let span = `<span class="${this.highlightClass}">${snippet}</span>`;

if (this.highlightLink) {
span = "<a href=\""+encodeURI(this.highlightLink)+"\">"
+span+"</a>";
span = `<a href="${encodeURI(this.highlightLink)}">${span}</a>`;
}
return span;
}
}

class TextHighlighter extends BaseHighlighter {
constructor(highlightClass, highlightLink) {
super(highlightClass, highlightLink);
this._key = 0;
}

/* create a <span> node to hold the given content
*
* snippet: content of the span
* highlight: true to highlight as a search match
*
* returns a React node
*/
_processSnippet(snippet, highlight) {
const key = this._key++;

let node =
<span key={key} className={highlight ? this.highlightClass : null}>
{ snippet }
</span>;

if (highlight && this.highlightLink) {
node = <a key={key} href={this.highlightLink}>{ node }</a>;
}

return node;
}
}


/* turn a matrix event body into html
*
* content: 'content' of the MatrixEvent
*
* highlights: optional list of words to highlight, ordered by longest word first
*
* opts.highlightLink: optional href to add to highlighted words
* opts.disableBigEmoji: optional argument to disable the big emoji class.
* opts.stripReplyFallback: optional argument specifying the event is a reply and so fallback needs removing
*/
/* turn a matrix event body into html
*
* content: 'content' of the MatrixEvent
*
* highlights: optional list of words to highlight, ordered by longest word first
*
* opts.highlightLink: optional href to add to highlighted words
* opts.disableBigEmoji: optional argument to disable the big emoji class.
* opts.stripReplyFallback: optional argument specifying the event is a reply and so fallback needs removing
*/
export function bodyToHtml(content, highlights, opts={}) {
const isHtmlMessage = content.format === "org.matrix.custom.html" && content.formatted_body;

Expand Down