https://github.com/python/cpython/commit/7ca6d79fa32d7203ee8d64f47b6b3539a027fdea
commit: 7ca6d79fa32d7203ee8d64f47b6b3539a027fdea
branch: main
author: Wulian233 <[email protected]>
committer: hugovk <[email protected]>
date: 2025-05-28T03:46:41+03:00
summary:

gh-134580: Modernizing `difflib.HtmlDiff` for HTML Output (#134581)

Co-authored-by: Hugo van Kemenade <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-05-23-20-01-52.gh-issue-134580.xnaJ70.rst
M Doc/whatsnew/3.15.rst
M Lib/difflib.py
M Lib/test/test_difflib.py
M Lib/test/test_difflib_expect.html

diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index cd4b2e8b3dd8ed..4d1a27354fc620 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -89,6 +89,13 @@ New modules
 Improved modules
 ================
 
+difflib
+-------
+
+* Improved the styling of HTML diff pages generated by the 
:class:`difflib.HtmlDiff`
+  class, and migrated the output to the HTML5 standard.
+  (Contributed by Jiahao Li in :gh:`134580`.)
+
 ssl
 ---
 
diff --git a/Lib/difflib.py b/Lib/difflib.py
index f1f4e62514a7bd..18801a9b19eb9d 100644
--- a/Lib/difflib.py
+++ b/Lib/difflib.py
@@ -1615,16 +1615,13 @@ def _line_pair_iterator():
 
 
 _file_template = """
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
-
-<html>
-
+<!DOCTYPE html>
+<html lang="en">
 <head>
-    <meta http-equiv="Content-Type"
-          content="text/html; charset=%(charset)s" />
-    <title></title>
-    <style type="text/css">%(styles)s
+    <meta charset="%(charset)s">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Diff comparison</title>
+    <style>%(styles)s
     </style>
 </head>
 
@@ -1636,13 +1633,36 @@ def _line_pair_iterator():
 
 _styles = """
         :root {color-scheme: light dark}
-        table.diff {font-family: Menlo, Consolas, Monaco, Liberation Mono, 
Lucida Console, monospace; border:medium}
-        .diff_header {background-color:#e0e0e0}
-        td.diff_header {text-align:right}
-        .diff_next {background-color:#c0c0c0}
+        table.diff {
+            font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida 
Console, monospace;
+            border: medium;
+        }
+        .diff_header {
+            background-color: #e0e0e0;
+            font-weight: bold;
+        }
+        td.diff_header {
+            text-align: right;
+            padding: 0 8px;
+        }
+        .diff_next {
+            background-color: #c0c0c0;
+            padding: 4px 0;
+        }
         .diff_add {background-color:palegreen}
         .diff_chg {background-color:#ffff77}
         .diff_sub {background-color:#ffaaaa}
+        table.diff[summary="Legends"] {
+            margin-top: 20px;
+            border: 1px solid #ccc;
+        }
+        table.diff[summary="Legends"] th {
+            background-color: #e0e0e0;
+            padding: 4px 8px;
+        }
+        table.diff[summary="Legends"] td {
+            padding: 4px 8px;
+        }
 
         @media (prefers-color-scheme: dark) {
             .diff_header {background-color:#666}
@@ -1650,6 +1670,8 @@ def _line_pair_iterator():
             .diff_add {background-color:darkgreen}
             .diff_chg {background-color:#847415}
             .diff_sub {background-color:darkred}
+            table.diff[summary="Legends"] {border-color:#555}
+            table.diff[summary="Legends"] th{background-color:#666}
         }"""
 
 _table_template = """
@@ -1692,7 +1714,7 @@ class HtmlDiff(object):
     make_table -- generates HTML for a single side by side table
     make_file -- generates complete HTML file with a single side by side table
 
-    See tools/scripts/diff.py for an example usage of this class.
+    See Doc/includes/diff.py for an example usage of this class.
     """
 
     _file_template = _file_template
diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py
index 9e217249be7332..6ac584a08d1e86 100644
--- a/Lib/test/test_difflib.py
+++ b/Lib/test/test_difflib.py
@@ -255,21 +255,21 @@ def test_make_file_default_charset(self):
         html_diff = difflib.HtmlDiff()
         output = html_diff.make_file(patch914575_from1.splitlines(),
                                      patch914575_to1.splitlines())
-        self.assertIn('content="text/html; charset=utf-8"', output)
+        self.assertIn('charset="utf-8"', output)
 
     def test_make_file_iso88591_charset(self):
         html_diff = difflib.HtmlDiff()
         output = html_diff.make_file(patch914575_from1.splitlines(),
                                      patch914575_to1.splitlines(),
                                      charset='iso-8859-1')
-        self.assertIn('content="text/html; charset=iso-8859-1"', output)
+        self.assertIn('charset="iso-8859-1"', output)
 
     def test_make_file_usascii_charset_with_nonascii_input(self):
         html_diff = difflib.HtmlDiff()
         output = html_diff.make_file(patch914575_nonascii_from1.splitlines(),
                                      patch914575_nonascii_to1.splitlines(),
                                      charset='us-ascii')
-        self.assertIn('content="text/html; charset=us-ascii"', output)
+        self.assertIn('charset="us-ascii"', output)
         self.assertIn('&#305;mpl&#305;c&#305;t', output)
 
 class TestDiffer(unittest.TestCase):
diff --git a/Lib/test/test_difflib_expect.html 
b/Lib/test/test_difflib_expect.html
index 9f33a9e9c9cf58..2346a6f9f8dddf 100644
--- a/Lib/test/test_difflib_expect.html
+++ b/Lib/test/test_difflib_expect.html
@@ -1,22 +1,42 @@
 
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
-
-<html>
-
+<!DOCTYPE html>
+<html lang="en">
 <head>
-    <meta http-equiv="Content-Type"
-          content="text/html; charset=utf-8" />
-    <title></title>
-    <style type="text/css">
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Diff comparison</title>
+    <style>
         :root {color-scheme: light dark}
-        table.diff {font-family: Menlo, Consolas, Monaco, Liberation Mono, 
Lucida Console, monospace; border:medium}
-        .diff_header {background-color:#e0e0e0}
-        td.diff_header {text-align:right}
-        .diff_next {background-color:#c0c0c0}
+        table.diff {
+            font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida 
Console, monospace;
+            border: medium;
+        }
+        .diff_header {
+            background-color: #e0e0e0;
+            font-weight: bold;
+        }
+        td.diff_header {
+            text-align: right;
+            padding: 0 8px;
+        }
+        .diff_next {
+            background-color: #c0c0c0;
+            padding: 4px 0;
+        }
         .diff_add {background-color:palegreen}
         .diff_chg {background-color:#ffff77}
         .diff_sub {background-color:#ffaaaa}
+        table.diff[summary="Legends"] {
+            margin-top: 20px;
+            border: 1px solid #ccc;
+        }
+        table.diff[summary="Legends"] th {
+            background-color: #e0e0e0;
+            padding: 4px 8px;
+        }
+        table.diff[summary="Legends"] td {
+            padding: 4px 8px;
+        }
 
         @media (prefers-color-scheme: dark) {
             .diff_header {background-color:#666}
@@ -24,6 +44,8 @@
             .diff_add {background-color:darkgreen}
             .diff_chg {background-color:#847415}
             .diff_sub {background-color:darkred}
+            table.diff[summary="Legends"] {border-color:#555}
+            table.diff[summary="Legends"] th{background-color:#666}
         }
     </style>
 </head>
diff --git 
a/Misc/NEWS.d/next/Library/2025-05-23-20-01-52.gh-issue-134580.xnaJ70.rst 
b/Misc/NEWS.d/next/Library/2025-05-23-20-01-52.gh-issue-134580.xnaJ70.rst
new file mode 100644
index 00000000000000..979d310d3cee58
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-05-23-20-01-52.gh-issue-134580.xnaJ70.rst
@@ -0,0 +1,3 @@
+Improved the styling of HTML diff pages generated by the
+:class:`difflib.HtmlDiff` class, and migrated the output to the HTML5
+standard.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to