gradyhorn
gradyhorn

Reputation: 65

Change the width of difflib.make_file() HTML Table?

I am creating diff files for legal documents with the python difflib and make_file(), which outputs HTML files containing a Table with the Diffs.

But the output tables are so wide that they are unreadable.

Is there any way to change the width of the table or add other css from my function call? I can't find anything related in the documentation.

In case it is not possible, what could be a solution to my "table width too wide" problem?

I already tried adding bootstrap and putting the table into a div that is responsive, but it didn't work.

Upvotes: 2

Views: 3264

Answers (1)

furas
furas

Reputation: 143097

You can use wrapcolumn= in HtmlDiff

import difflib
import webbrowser

d = difflib.HtmlDiff(wrapcolumn=10)

lines1 = ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']
lines2 = ['XXXXXXXXXXXXXaaaaaaaaaYYYaaaaaaZZZZZZZZZZZaaaaZZZZZZZZ']

html = d.make_file(lines1, lines2)

with open('output.html', 'w') as fh: 
    fh.write(html)

webbrowser.open('output.html')

Without wrapcolumn=

enter image description here

With wrapcolumn=10

enter image description here


EDIT:

I didn't test it but in source code of diff you can see hidden variables _styles, _table_template, _file_template which you could replace in HtmlDiff to generate different HTML. This way you could add classes and styles to format it.

It may also need to change hidden _format_line to remove nowrap="nowrap"


EDIT:

I use HtmlDiff to create own class with new _format_line() without nowrap="nowrap" and now I can add styles with width and word-break

import difflib
import webbrowser

# --- classes ---

class MyHTML(difflib.HtmlDiff):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
   
        # append new styles inside new class 
        self._styles = self._styles + """
table.diff {width: 300px}
.diff_sub {display: inline-block; word-break: break-word;}
.diff_add {display: inline-block; word-break: break-word;}
"""

    # function from source code - I remove only `nowrap="nowrap"`
    def _format_line(self,side,flag,linenum,text):
        """Returns HTML markup of "from" / "to" text lines
        side -- 0 or 1 indicating "from" or "to" text
        flag -- indicates if difference on line
        linenum -- line number (used for line number column)
        text -- line text to be marked up
        """
        try:
            linenum = '%d' % linenum
            id = ' id="%s%s"' % (self._prefix[side],linenum)
        except TypeError:
            # handle blank lines where linenum is '>' or ''
            id = ''
        # replace those things that would get confused with HTML symbols
        text=text.replace("&","&amp;").replace(">","&gt;").replace("<","&lt;")

        # make space non-breakable so they don't get compressed or line wrapped
        text = text.replace(' ','&nbsp;').rstrip()

        return '<td class="diff_header"%s>%s</td><td>%s</td>' \
               % (id,linenum,text)

# --- main ---

d = MyHTML()

# >>> changing styles after creating `MyHTML` or in original `HtmlDiff <<<
#d._styles = d._styles + """
#table.diff {width: 300px}
#.diff_sub {display: inline-block; word-break: break-word;}
#.diff_add {display: inline-block; word-break: break-word;}
#"""

#d._file_template = """new template"""
    

lines1 = ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']
lines2 = ['XXXXXXXXXXXXXaaaaaaaaaYYYaaaaaaZZZZZZZZZZZaaaaZZZZZZZZ']

html = d.make_file(lines1, lines2)

with open('output.html', 'w') as fh: 
    fh.write(html)

webbrowser.open('output.html')

Shorter version

import difflib
import webbrowser

d = HtmlDiff(wrapcolumn=10)

d._file_template = """new template with %(charset)s %(styles)s %(table)s %(legend)s"""         
#d._styles = """new styles"""         

lines1 = ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']
lines2 = ['XXXXXXXXXXXXXaaaaaaaaaYYYaaaaaaZZZZZZZZZZZaaaaZZZZZZZZ']

html = d.make_file(lines1, lines2)

with open('output.html', 'w') as fh: 
    fh.write(html)

webbrowser.open('output.html')

Upvotes: 5

Related Questions