[diffoscope] 06/06: presenters: html: in html-dir mode, put css/icon in separate files to avoid duplication

Ximin Luo infinity0 at debian.org
Mon Jul 3 20:35:58 CEST 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch WIP/humungous-diffs
in repository diffoscope.

commit 84664773ac5ce826ea18b246ca49a1366e8436a7
Author: Ximin Luo <infinity0 at debian.org>
Date:   Mon Jun 26 16:40:57 2017 +0200

    presenters: html: in html-dir mode, put css/icon in separate files to avoid duplication
---
 diffoscope/presenters/html/html.py      |  85 +++++++-----
 diffoscope/presenters/html/templates.py | 237 ++++++++++++++++----------------
 2 files changed, 171 insertions(+), 151 deletions(-)

diff --git a/diffoscope/presenters/html/html.py b/diffoscope/presenters/html/html.py
index 4d896dc..4c3ae01 100644
--- a/diffoscope/presenters/html/html.py
+++ b/diffoscope/presenters/html/html.py
@@ -31,16 +31,17 @@
 # Dave Burt <dave (at) burt.id.au> (mainly for html theme)
 #
 
-import io
-import os
-import re
-import sys
-import html
+import base64
 import codecs
+import collections
 import contextlib
 import hashlib
+import html
+import io
 import logging
-import contextlib
+import os
+import re
+import sys
 from urllib.parse import urlparse
 
 from diffoscope import VERSION
@@ -178,7 +179,7 @@ def output_node_frame(difference, path, indentstr, indentnum, body):
 {1}{0[1]}</div>
 {2}""", 3).pformatl(indent, header, body)
 
-def output_node(difference, path, indentstr, indentnum, css_url, directory):
+def output_node(ctx, difference, path, indentstr, indentnum):
     """Returns a tuple (parent, continuation) where
 
     - parent is a PartialString representing the body of the node, including
@@ -204,8 +205,7 @@ def output_node(difference, path, indentstr, indentnum, css_url, directory):
     ud_cont = None
     if difference.unified_diff:
         ud_cont = HTMLSideBySidePresenter().output_unified_diff(
-            css_url, directory, difference.unified_diff,
-            difference.has_internal_linenos)
+            ctx, difference.unified_diff, difference.has_internal_linenos)
         udiff = next(ud_cont)
         if isinstance(udiff, PartialString):
             ud_cont = ud_cont.send
@@ -234,15 +234,24 @@ def output_node(difference, path, indentstr, indentnum, css_url, directory):
     assert len(t.holes) >= len(difference.details) + 1 # there might be extra holes for the unified diff continuation
     return cont(t, u""), ud_cont
 
-def output_header(css_url):
+def output_header(css_url, our_css_url=False, icon_url=None):
     if css_url:
-        css_link = '<link href="%s" type="text/css" rel="stylesheet" />' % css_url
+        css_link = u'  <link href="%s" type="text/css" rel="stylesheet" />\n' % css_url
+    else:
+        css_link = u''
+    if our_css_url:
+        css_style = u'  <link href="%s" type="text/css" rel="stylesheet" />\n' % our_css_url
     else:
-        css_link = ''
+        css_style = u'<style type="text/css">\n' + templates.STYLES + u'</style>\n'
+    if icon_url:
+        favicon = icon_url
+    else:
+        favicon = u'data:image/png;base64,' + FAVICON_BASE64
     return templates.HEADER % {
         'title': html.escape(' '.join(sys.argv)),
-        'favicon': FAVICON_BASE64,
+        'favicon': favicon,
         'css_link': css_link,
+        'css_style': css_style
     }
 
 def output_footer(jquery_url=None):
@@ -268,6 +277,13 @@ def spl_file_printer(directory, filename, accum):
         yield recording_print_func
 
 
+class HTMLPrintContext(collections.namedtuple("HTMLPrintContext",
+    "target single_page jquery_url css_url our_css_url icon_url")):
+    @property
+    def directory(self):
+        return None if self.single_page else self.target
+
+
 class HTMLSideBySidePresenter(object):
     supports_visual_diffs = True
 
@@ -327,9 +343,9 @@ class HTMLSideBySidePresenter(object):
         # Takes ownership of print_context
         self.spl_print_ctrl = print_context.__exit__, rotation_params
         self.spl_print_func = print_context.__enter__()
-        _, _, css_url = rotation_params
+        ctx, _ = rotation_params
         # Print file and table headers
-        self.spl_print_func(output_header(css_url))
+        self.spl_print_func(output_header(ctx.css_url, ctx.our_css_url, ctx.icon_url))
 
     def spl_had_entered_child(self):
         return self.spl_print_ctrl and self.spl_print_ctrl[1] and self.spl_current_page > 0
@@ -367,7 +383,7 @@ class HTMLSideBySidePresenter(object):
 
     def new_child_page(self):
         _, rotation_params = self.spl_print_ctrl
-        directory, mainname, css_url = rotation_params
+        ctx, mainname = rotation_params
         self.spl_current_page += 1
         filename = "%s-%s.html" % (mainname, self.spl_current_page)
 
@@ -378,7 +394,7 @@ class HTMLSideBySidePresenter(object):
             self.spl_print_exit(None, None, None)
 
         # rotate to the next child page
-        context = spl_file_printer(directory, filename, self)
+        context = spl_file_printer(ctx.directory, filename, self)
         self.spl_print_enter(context, rotation_params)
         self.spl_print_func(templates.UD_TABLE_HEADER)
 
@@ -435,12 +451,12 @@ class HTMLSideBySidePresenter(object):
             self.spl_print_func(u"</table>")
         yield wrote_all
 
-    def output_unified_diff(self, css_url, directory, unified_diff, has_internal_linenos):
+    def output_unified_diff(self, ctx, unified_diff, has_internal_linenos):
         self.new_unified_diff()
         rotation_params = None
-        if directory:
+        if ctx.directory:
             mainname = hashlib.md5(unified_diff.encode('utf-8')).hexdigest()
-            rotation_params = directory, mainname, css_url
+            rotation_params = ctx, mainname
 
         try:
             udiff = io.StringIO()
@@ -535,10 +551,10 @@ class HTMLPresenter(Presenter):
         else:
             return templates.DIFFNODE_LIMIT
 
-    def output_difference(self, target, difference, css_url, jquery_url, single_page=False):
+    def output_difference(self, ctx, difference):
         outputs = {} # nodes to their partial output
         ancestors = {} # child nodes to ancestor nodes
-        placeholder_len = len(self.output_node_placeholder("XXXXXXXXXXXXXXXX", not single_page))
+        placeholder_len = len(self.output_node_placeholder("XXXXXXXXXXXXXXXX", not ctx.single_page))
         continuations = {} # functions to print unified diff continuations (html-dir only)
         printers = {} # nodes to their printers
 
@@ -553,8 +569,7 @@ class HTMLPresenter(Presenter):
             path = score[3]
             anchor = output_anchor(path)
             logger.debug('html output for %s', anchor)
-            node_output, node_continuation = output_node(
-                node, path, "  ", len(path)-1, css_url, None if single_page else target)
+            node_output, node_continuation = output_node(ctx, node, path, "  ", len(path)-1)
 
             add_to_existing = False
             if ancestor:
@@ -568,7 +583,7 @@ class HTMLPresenter(Presenter):
                 elif page_current + want_to_add < page_limit:
                     add_to_existing = True
                 else:
-                    make_new_subpage = not single_page
+                    make_new_subpage = not ctx.single_page
 
             if add_to_existing:
                 # under limit, add it to an existing page
@@ -592,14 +607,14 @@ class HTMLPresenter(Presenter):
                 else:
                     # unconditionally write the root node regardless of limits
                     assert node is difference
-                    footer = output_footer(jquery_url)
+                    footer = output_footer(ctx.jquery_url)
                     anchor = "index"
 
                 outputs[node] = node_output.frame(
-                    output_header(css_url) + u'<div class="difference">\n',
-                    u'</div>\n' + footer)
-                assert not single_page or node is difference
-                printers[node] = (make_printer, target) if single_page else (file_printer, target, "%s.html" % anchor)
+                    output_header(ctx.css_url, ctx.our_css_url, ctx.icon_url) +
+                    u'<div class="difference">\n', u'</div>\n' + footer)
+                assert not ctx.single_page or node is difference
+                printers[node] = (make_printer, ctx.target) if ctx.single_page else (file_printer, ctx.target, "%s.html" % anchor)
                 stored = node
 
             for child in node.details:
@@ -661,7 +676,12 @@ class HTMLPresenter(Presenter):
             raise ValueError("%s is not a directory" % directory)
 
         jquery_url = self.ensure_jquery(jquery_url, directory, "jquery.js")
-        self.output_difference(directory, difference, css_url, jquery_url)
+        with open(os.path.join(directory, "common.css"), "w") as fp:
+            fp.write(templates.STYLES)
+        with open(os.path.join(directory, "icon.png"), "wb") as fp:
+            fp.write(base64.b64decode(FAVICON_BASE64))
+        ctx = HTMLPrintContext(directory, False, jquery_url, css_url, "common.css", "icon.png")
+        self.output_difference(ctx, difference)
 
 
     def output_html(self, target, difference, css_url=None, jquery_url=None):
@@ -669,7 +689,8 @@ class HTMLPresenter(Presenter):
         Default presenter, all in one HTML file
         """
         jquery_url = self.ensure_jquery(jquery_url, os.getcwd(), None)
-        self.output_difference(target, difference, css_url, jquery_url, single_page=True)
+        ctx = HTMLPrintContext(target, True, jquery_url, css_url, None, None)
+        self.output_difference(ctx, difference)
 
     @classmethod
     def run(cls, data, difference, parsed_args):
diff --git a/diffoscope/presenters/html/templates.py b/diffoscope/presenters/html/templates.py
index 29ad061..8ee04de 100644
--- a/diffoscope/presenters/html/templates.py
+++ b/diffoscope/presenters/html/templates.py
@@ -24,126 +24,9 @@ HEADER = u"""<!DOCTYPE html>
   <meta http-equiv="x-ua-compatible" content="IE=edge">
   <meta name="referrer" content="no-referrer" />
   <meta name="generator" content="diffoscope" />
-  <link rel="icon" type="image/png" href="data:image/png;base64,%(favicon)s" />
+  <link rel="icon" type="image/png" href="%(favicon)s" />
   <title>%(title)s</title>
-  <style type="text/css">
-    body.diffoscope {
-      background: white;
-      color: black;
-    }
-    .diffoscope .footer {
-      font-size: small;
-    }
-    .diffoscope .difference {
-      border: outset #888 1px;
-      background: #E8E8E8;
-      background: rgba(0,0,0,.1);
-      padding: 0.5em;
-      margin: 0.5em 0;
-    }
-    .diffoscope .difference table {
-      table-layout: fixed;
-      width: 100%%;
-      border: 0;
-    }
-    .diffoscope .difference th,
-    .diffoscope .difference td {
-      border: 0;
-    }
-    .diffoscope table.diff {
-      border: 0;
-      border-collapse:collapse;
-      font-size:0.75em;
-      font-family: 'Lucida Console', monospace;
-    }
-    .diffoscope table.diff tr:hover td {
-      background: #FFFF00;
-    }
-    .diffoscope .line {
-      color:#8080a0
-    }
-    .diffoscope th {
-      background: black;
-      color: white
-    }
-    .diffoscope .diffunmodified td {
-      background: #D0D0E0
-    }
-    .diffoscope .diffhunk td {
-      background: #A0A0A0
-    }
-    .diffoscope .diffadded td {
-      background: #CCFFCC
-    }
-    .diffoscope .diffdeleted td {
-      background: #FFCCCC
-    }
-    .diffoscope .diffchanged td {
-      background: #FFFFA0
-    }
-    .diffoscope ins, del {
-      background: #E0C880;
-      text-decoration: none
-    }
-    .diffoscope .diffponct {
-      color: #B08080
-    }
-    .diffoscope .comment {
-      font-style: italic;
-    }
-    .diffoscope .source {
-      font-weight: bold;
-    }
-    .diffoscope .error {
-      border: solid black 1px;
-      background: red;
-      color: white;
-      padding: 0.2em;
-    }
-    .diffoscope .anchor {
-      margin-left: 0.5em;
-      font-size: 80%%;
-      color: #333;
-      text-decoration: none;
-      display: none;
-    }
-    .diffoscope .diffheader:hover .anchor {
-      display: inline;
-    }
-    .diffoscope table.diff tr.ondemand td, .diffoscope div.ondemand-details {
-      background: #f99;
-      text-align: center;
-      padding: 0.5em 0;
-    }
-    .diffoscope table.diff tr.ondemand:hover td, .diffoscope div.ondemand-details:hover {
-      background: #faa;
-      cursor: pointer;
-    }
-    .diffoscope .diffcontrol, .diffoscope .diffcontrol-nochildren {
-      float: left;
-      margin-right: 0.3em;
-      cursor: pointer;
-      display: none; /* currently, only available in html-dir output where jquery is enabled */
-    }
-    .diffoscope .diffheader {
-      cursor: pointer;
-    }
-    .diffoscope .diffheader:hover .diffcontrol {
-      color: #080;
-      font-weight: bold;
-    }
-    .diffoscope .diffcontrol-double {
-      line-height: 250%%;
-    }
-    .diffoscope .colines {
-      width: 3em;
-    }
-    .diffoscope .coldiff {
-      width: 99%%;
-    }
-  </style>
-  %(css_link)s
-</head>
+%(css_style)s%(css_link)s</head>
 <body class="diffoscope">
 """
 
@@ -152,6 +35,122 @@ FOOTER = u"""<div class="footer">Generated by <a href="https://diffoscope.org" r
 </html>
 """
 
+STYLES = u"""body.diffoscope {
+  background: white;
+  color: black;
+}
+.diffoscope .footer {
+  font-size: small;
+}
+.diffoscope .difference {
+  border: outset #888 1px;
+  background: #E8E8E8;
+  background: rgba(0,0,0,.1);
+  padding: 0.5em;
+  margin: 0.5em 0;
+}
+.diffoscope .difference table {
+  table-layout: fixed;
+  width: 100%;
+  border: 0;
+}
+.diffoscope .difference th,
+.diffoscope .difference td {
+  border: 0;
+}
+.diffoscope table.diff {
+  border: 0;
+  border-collapse:collapse;
+  font-size:0.75em;
+  font-family: 'Lucida Console', monospace;
+}
+.diffoscope table.diff tr:hover td {
+  background: #FFFF00;
+}
+.diffoscope .line {
+  color:#8080a0
+}
+.diffoscope th {
+  background: black;
+  color: white
+}
+.diffoscope .diffunmodified td {
+  background: #D0D0E0
+}
+.diffoscope .diffhunk td {
+  background: #A0A0A0
+}
+.diffoscope .diffadded td {
+  background: #CCFFCC
+}
+.diffoscope .diffdeleted td {
+  background: #FFCCCC
+}
+.diffoscope .diffchanged td {
+  background: #FFFFA0
+}
+.diffoscope ins, del {
+  background: #E0C880;
+  text-decoration: none
+}
+.diffoscope .diffponct {
+  color: #B08080
+}
+.diffoscope .comment {
+  font-style: italic;
+}
+.diffoscope .source {
+  font-weight: bold;
+}
+.diffoscope .error {
+  border: solid black 1px;
+  background: red;
+  color: white;
+  padding: 0.2em;
+}
+.diffoscope .anchor {
+  margin-left: 0.5em;
+  font-size: 80%;
+  color: #333;
+  text-decoration: none;
+  display: none;
+}
+.diffoscope .diffheader:hover .anchor {
+  display: inline;
+}
+.diffoscope table.diff tr.ondemand td, .diffoscope div.ondemand-details {
+  background: #f99;
+  text-align: center;
+  padding: 0.5em 0;
+}
+.diffoscope table.diff tr.ondemand:hover td, .diffoscope div.ondemand-details:hover {
+  background: #faa;
+  cursor: pointer;
+}
+.diffoscope .diffcontrol, .diffoscope .diffcontrol-nochildren {
+  float: left;
+  margin-right: 0.3em;
+  cursor: pointer;
+  display: none; /* currently, only available in html-dir output where jquery is enabled */
+}
+.diffoscope .diffheader {
+  cursor: pointer;
+}
+.diffoscope .diffheader:hover .diffcontrol {
+  color: #080;
+  font-weight: bold;
+}
+.diffoscope .diffcontrol-double {
+  line-height: 250%;
+}
+.diffoscope .colines {
+  width: 3em;
+}
+.diffoscope .coldiff {
+  width: 99%;
+}
+"""
+
 SCRIPTS = u"""<script src="%(jquery_url)s"></script>
 <script type="text/javascript">
 $(function() {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list