// Forked from https://github.com/inkling/htmldiff.js/blob/master/js/htmldiff.js // The MIT License (MIT) // Copyright (c) 2012 The Network Inc. and contributors // Copyright (c) 2022 idesis GmbH, Max-Keith-Straße 66 (E 11), D-45136 Essen, https://www.idesis.de // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /** * htmldiff.js is a library that compares HTML content. It creates a diff between two * HTML documents by combining the two documents and wrapping the differences with * and tags. Here is a high-level overview of how the diff works. * * 1. Tokenize the before and after HTML with htmlToTokens. * 2. Generate a list of operations that convert the before list of tokens to the after * list of tokens with calculateOperations, which does the following: * a. Find all the matching blocks of tokens between the before and after lists of * tokens with findMatchingBlocks. This is done by finding the single longest * matching block with findMatch, then iteratively finding the next longest * matching blocks that precede and follow the longest matching block. * b. Determine insertions, deletions, and replacements from the matching blocks. * This is done in calculateOperations. * 3. Render the list of operations by wrapping tokens with and tags where * appropriate with renderOperations. * * Example usage: * * var htmldiff = require('htmldiff.js'); * * htmldiff('

this is some text

', '

this is some more text

') * == '

this is some more text

' * * htmldiff('

this is some text

', '

this is some more text

', 'diff-class') * == '

this is some more text

' */ "use strict"; type Token = { string: string; key: string; }; type Segment = { beforeTokens: Array; afterTokens: Array; beforeIndex: number; afterIndex: number; beforeMap: object; afterMap: object; }; type MatchT = { segment: Segment; length: number; startInBefore: number; endInBefore: number; startInAfter: number; endInAfter: number; segmentStartInBefore: number; segmentStartInAfter: number; segmentEndInBefore: number; segmentEndInAfter: number; }; type OperationType = "insert" | "delete" | "replace" | "equal" | "none"; type Operation = { action: OperationType; startInBefore: number; endInBefore: number | null; startInAfter: number | null; endInAfter: number | null; }; function isEndOfTag(char: string) { return char === ">"; } function isStartOfTag(char: string) { return char === "<"; } function isWhitespace(char: string) { return /^\s+$/.test(char); } /** * Determines if the given token is a tag. * * @param {string} token The token in question. * * @return {boolean|string} False if the token is not a tag, or the tag name otherwise. */ function isTag(token: string): boolean | string { const match = token.match(/^\s*<([^!>][^>]*)>\s*$/); return !!match && match[1].trim().split(" ")[0]; } function isntTag(token: string) { return !isTag(token); } function isStartofHTMLComment(word: string) { return /^