<commit_before>/*
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.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import classNames from 'classnames';
import DiffMatchPatch from 'diff-match-patch';
import {DiffDOM} from "diff-dom";
import { checkBlockNode, bodyToHtml } from "../HtmlUtils";

const decodeEntities = (function() {
    let textarea = null;
    return function(string) {
        if (!textarea) {
            textarea = document.createElement("textarea");
        }
        textarea.innerHTML = string;
        return textarea.value;
    };
})();

function textToHtml(text) {
    const container = document.createElement("div");
    container.textContent = text;
    return container.innerHTML;
}

function getSanitizedHtmlBody(content) {
    const opts = {
        stripReplyFallback: true,
        returnString: true,
    };
    if (content.format === "org.matrix.custom.html") {
        return bodyToHtml(content, null, opts);
    } else {
        // convert the string to something that can be safely
        // embedded in an html document, e.g. use html entities where needed
        // This is also needed so that DiffDOM wouldn't interpret something
        // as a tag when somebody types e.g. "</sarcasm>"

        // as opposed to bodyToHtml, here we also render
        // text messages with dangerouslySetInnerHTML, to unify
        // the code paths and because we need html to show differences
        return textToHtml(bodyToHtml(content, null, opts));
    }
}

function wrapInsertion(child) {
    const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
    wrapper.className = "mx_EditHistoryMessage_insertion";
    wrapper.appendChild(child);
    return wrapper;
}

function wrapDeletion(child) {
    const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
    wrapper.className = "mx_EditHistoryMessage_deletion";
    wrapper.appendChild(child);
    return wrapper;
}

function findRefNodes(root, route, isAddition) {
    let refNode = root;
    let refParentNode;
    const end = isAddition ? route.length - 1 : route.length;
    for (let i = 0; i < end; ++i) {
        refParentNode = refNode;
        refNode = refNode.childNodes[route[i]];
    }
    return {refNode, refParentNode};
}

function diffTreeToDOM(desc) {
    if (desc.nodeName === "#text") {
        return stringAsTextNode(desc.data);<commit_msg>Don't assume that diffs will have an appropriate child node<commit_after>/*
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.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import classNames from 'classnames';
import DiffMatchPatch from 'diff-match-patch';
import {DiffDOM} from "diff-dom";
import { checkBlockNode, bodyToHtml } from "../HtmlUtils";

const decodeEntities = (function() {
    let textarea = null;
    return function(string) {
        if (!textarea) {
            textarea = document.createElement("textarea");
        }
        textarea.innerHTML = string;
        return textarea.value;
    };
})();

function textToHtml(text) {
    const container = document.createElement("div");
    container.textContent = text;
    return container.innerHTML;
}

function getSanitizedHtmlBody(content) {
    const opts = {
        stripReplyFallback: true,
        returnString: true,
    };
    if (content.format === "org.matrix.custom.html") {
        return bodyToHtml(content, null, opts);
    } else {
        // convert the string to something that can be safely
        // embedded in an html document, e.g. use html entities where needed
        // This is also needed so that DiffDOM wouldn't interpret something
        // as a tag when somebody types e.g. "</sarcasm>"

        // as opposed to bodyToHtml, here we also render
        // text messages with dangerouslySetInnerHTML, to unify
        // the code paths and because we need html to show differences
        return textToHtml(bodyToHtml(content, null, opts));
    }
}

function wrapInsertion(child) {
    const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
    wrapper.className = "mx_EditHistoryMessage_insertion";
    wrapper.appendChild(child);
    return wrapper;
}

function wrapDeletion(child) {
    const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
    wrapper.className = "mx_EditHistoryMessage_deletion";
    wrapper.appendChild(child);
    return wrapper;
}

function findRefNodes(root, route, isAddition) {
    let refNode = root;
    let refParentNode;
    const end = isAddition ? route.length - 1 : route.length;
    for (let i = 0; i < end; ++i) {
        refParentNode = refNode;
        // Lists don't have appropriate child nodes we can use.
        if (!refNode.childNodes[route[i]]) continue;
        refNode = refNode.childNodes[route[i]];
    }
    return {refNode, refParentNode};
}

function diffTreeToDOM(desc) {
    if (desc.nodeName === "#text") {
        return stringAsTextNode(desc.data);
{'fraction_non_alphanumeric': 0.09860808317960758, 'fraction_numerical': 0.00335401643468053, 'mean_word_length': 3.275268817204301, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2736527', 'n_tokens_mistral': 1655, 'n_tokens_neox': 1609, 'n_words': 568}