From 0fbea5e4cfb4dc94c6ea0f3d8cb1a947162e88b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Dec 2025 19:22:32 +0000 Subject: [PATCH 1/3] Initial plan From 1e089bf8621848951eb45ceaa54d94a0571aa499 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Dec 2025 19:33:18 +0000 Subject: [PATCH 2/3] Fix DOMDocument loadHTML warnings by suppressing libxml errors Co-authored-by: jschroed91 <2540804+jschroed91@users.noreply.github.com> --- .phpunit.result.cache | 1 + lib/Caxy/HtmlDiff/ListDiffLines.php | 14 ++++++ lib/Caxy/HtmlDiff/Table/TableDiff.php | 7 +++ .../HtmlDiff/nested-list-warning.html | 46 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 .phpunit.result.cache create mode 100644 tests/fixtures/HtmlDiff/nested-list-warning.html diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000..dfec038 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":[],"times":{"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"ICC-5136.html\"":0.012,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"first-and-last.html\"":0.009,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"issue-28-link-changes.html\"":0.005,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"keep-newlines-test.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"multibyte.html\"":0.001,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"multiline-tag.html\"":0,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"nested-list-warning.html\"":0.012,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"new-paragraph-and-list.html\"":0.071,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-2.html\"":0.008,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-3.html\"":0.026,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-4.html\"":0.025,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-5.html\"":0.059,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-6.html\"":0.031,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-8.html\"":0.016,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-9.html\"":0.005,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"simple-list.html\"":0.017,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"space-inside-isolated-tag.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"spaces-added.html\"":0.001,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"spaces-removed-inside-tag.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"table-whitespace-issue.html\"":0.011,"Caxy\\Tests\\HtmlDiff\\Functional\\HTMLPurifierConfigTest::testHtmlDiffConfigTraditional":0.026,"Caxy\\Tests\\HtmlDiff\\Functional\\HTMLPurifierConfigTest::testHtmlDiffConfigStatic":0.005}} \ No newline at end of file diff --git a/lib/Caxy/HtmlDiff/ListDiffLines.php b/lib/Caxy/HtmlDiff/ListDiffLines.php index cfc68c7..ea3cb8c 100644 --- a/lib/Caxy/HtmlDiff/ListDiffLines.php +++ b/lib/Caxy/HtmlDiff/ListDiffLines.php @@ -87,12 +87,19 @@ protected function listByLines(string $old, string $new) : string $new = mb_encode_numericentity($new, [0x80, 0x10FFFF, 0, ~0], 'UTF-8'); $old = mb_encode_numericentity($old, [0x80, 0x10FFFF, 0, ~0], 'UTF-8'); + // Suppress libxml errors to avoid warnings from malformed HTML fragments + $previousLibxmlUseInternalErrors = libxml_use_internal_errors(true); + $newDom = new DOMDocument(); $newDom->loadHTML($new); $oldDom = new DOMDocument(); $oldDom->loadHTML($old); + // Restore previous libxml error handling state + libxml_clear_errors(); + libxml_use_internal_errors($previousLibxmlUseInternalErrors); + $newListNode = $this->findListNode($newDom); $oldListNode = $this->findListNode($oldDom); @@ -405,9 +412,16 @@ private function setInnerHtml(DOMNode $node, string $html) : void $node->nodeValue = ''; + // Suppress libxml errors to avoid warnings from malformed HTML fragments + $previousLibxmlUseInternalErrors = libxml_use_internal_errors(true); + $bufferDom = new DOMDocument('1.0', 'UTF-8'); $bufferDom->loadHTML($html); + // Restore previous libxml error handling state + libxml_clear_errors(); + libxml_use_internal_errors($previousLibxmlUseInternalErrors); + $bodyNode = $bufferDom->getElementsByTagName('body')->item(0); foreach ($bodyNode->childNodes as $childNode) { diff --git a/lib/Caxy/HtmlDiff/Table/TableDiff.php b/lib/Caxy/HtmlDiff/Table/TableDiff.php index ed46d94..4ff899f 100644 --- a/lib/Caxy/HtmlDiff/Table/TableDiff.php +++ b/lib/Caxy/HtmlDiff/Table/TableDiff.php @@ -626,9 +626,16 @@ protected function buildTableDoms() */ protected function createDocumentWithHtml($text) { + // Suppress libxml errors to avoid warnings from malformed HTML fragments + $previousLibxmlUseInternalErrors = libxml_use_internal_errors(true); + $dom = new \DOMDocument(); $dom->loadHTML(htmlspecialchars_decode(iconv('UTF-8', 'ISO-8859-1//IGNORE', htmlentities($text, ENT_COMPAT, 'UTF-8')), ENT_QUOTES)); + // Restore previous libxml error handling state + libxml_clear_errors(); + libxml_use_internal_errors($previousLibxmlUseInternalErrors); + return $dom; } diff --git a/tests/fixtures/HtmlDiff/nested-list-warning.html b/tests/fixtures/HtmlDiff/nested-list-warning.html new file mode 100644 index 0000000..1a4d590 --- /dev/null +++ b/tests/fixtures/HtmlDiff/nested-list-warning.html @@ -0,0 +1,46 @@ + + + +
    +
  1. +
      +
    1. This sentence.
    2. +
    +
  2. +
  3. : +
      +
    1. Another item
    2. +
    +
  4. +
+
    +
  1. :
  2. +
  3. Saturn
  4. +
+ +
    +
  1. +
      +
    1. This sentence.
    2. +
    +
  2. +
  3. : +
      +
    1. Another item
    2. +
    +
  4. +
  5. : +
      +
    1. Saturn
    2. +
    +
  6. +
+ +
  1. +
      +
    1. This sentence.
    2. +
    +
  2. : +
    1. This sentence.
    2. Another item
  3. : +
    1. Another item
    2. Saturn
  1. :
  2. Saturn
From 2c1e3d70f7038d2ff3e70ed5c2efb9179c9c0bfc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Dec 2025 19:34:13 +0000 Subject: [PATCH 3/3] Add .phpunit.result.cache to .gitignore Co-authored-by: jschroed91 <2540804+jschroed91@users.noreply.github.com> --- .gitignore | 3 ++- .phpunit.result.cache | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 .phpunit.result.cache diff --git a/.gitignore b/.gitignore index 183037e..318cfe6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ vendor/ /demo/bower_components /demo/node_modules .DS_Store -.idea \ No newline at end of file +.idea +.phpunit.result.cache \ No newline at end of file diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index dfec038..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":[],"times":{"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"ICC-5136.html\"":0.012,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"first-and-last.html\"":0.009,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"issue-28-link-changes.html\"":0.005,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"keep-newlines-test.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"multibyte.html\"":0.001,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"multiline-tag.html\"":0,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"nested-list-warning.html\"":0.012,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"new-paragraph-and-list.html\"":0.071,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-2.html\"":0.008,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-3.html\"":0.026,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-4.html\"":0.025,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-5.html\"":0.059,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-6.html\"":0.031,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-8.html\"":0.016,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"override-9.html\"":0.005,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"simple-list.html\"":0.017,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"space-inside-isolated-tag.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"spaces-added.html\"":0.001,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"spaces-removed-inside-tag.html\"":0.003,"Caxy\\Tests\\HtmlDiff\\Functional\\HtmlDiffFunctionalTest::testHtmlDiff with data set \"table-whitespace-issue.html\"":0.011,"Caxy\\Tests\\HtmlDiff\\Functional\\HTMLPurifierConfigTest::testHtmlDiffConfigTraditional":0.026,"Caxy\\Tests\\HtmlDiff\\Functional\\HTMLPurifierConfigTest::testHtmlDiffConfigStatic":0.005}} \ No newline at end of file