changeset 25867:a74e9806d17d stable

highlight: produce correct markup when there's a blank line just before EOF Due to how the colorized output from pygments was stripped of <pre> elements, when there was an empty line at the end of a file, highlight extension produced an incorrect markup (no closing tags from the fileline/annotateline template). It wasn't usually noticeable, because browsers were smart enough to see where the missing tags should've been, but in monoblue style it resulted in the last line having twice the normal height. Instead of awkwardly trying to strip outer <pre></pre> tags, let's make the formatter with nowrap=True, which should do what we need in pygments since at least 0.5 (2006-10-30). Example from monoblue style: Before: <div class="source"> <div style="font-family:monospace" class="parity0"> <pre><a class="linenr" href="#l1" id="l1"> 1</a> </pre> </div> <div style="font-family:monospace" class="parity1"> <pre><a class="linenr" href="#l2" id="l2"> 2</a> </div> Now: <div class="source"> <div style="font-family:monospace" class="parity0"> <pre><a class="linenr" href="#l1" id="l1"> 1</a> </pre> </div> <div style="font-family:monospace" class="parity1"> <pre><a class="linenr" href="#l2" id="l2"> 2</a> </pre> </div> </div> (Notice the missing </pre></div> now in place)
author Anton Shestakov <av6@dwimlabs.net>
date Wed, 22 Jul 2015 10:19:17 +0800
parents 8c1d7a0e737b
children 777235417457
files hgext/highlight/highlight.py tests/test-highlight.t
diffstat 2 files changed, 78 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/highlight/highlight.py	Mon Jul 20 23:33:57 2015 -0400
+++ b/hgext/highlight/highlight.py	Wed Jul 22 10:19:17 2015 +0800
@@ -51,12 +51,9 @@
         except (ClassNotFound, ValueError):
             lexer = TextLexer(stripnl=False)
 
-    formatter = HtmlFormatter(style=style)
+    formatter = HtmlFormatter(nowrap=True, style=style)
 
     colorized = highlight(text, lexer, formatter)
-    # strip wrapping div
-    colorized = colorized[:colorized.find('\n</pre>')]
-    colorized = colorized[colorized.find('<pre>') + 5:]
     coloriter = (s.encode(encoding.encoding, 'replace')
                  for s in colorized.splitlines())
 
--- a/tests/test-highlight.t	Mon Jul 20 23:33:57 2015 -0400
+++ b/tests/test-highlight.t	Wed Jul 22 10:19:17 2015 +0800
@@ -45,6 +45,7 @@
   >     p = primes()
   >     print "The first %d primes: %s" % (n, list(islice(p, n)))
   > EOF
+  $ echo >> primes.py  # to test html markup with an empty line just before EOF
   $ hg ci -Ama
   adding primes.py
 
@@ -68,7 +69,7 @@
   <script type="text/javascript" src="/static/mercurial.js"></script>
   
   <link rel="stylesheet" href="/highlightcss" type="text/css" />
-  <title>test: 853dcd4de2a6 primes.py</title>
+  <title>test: 06824edf55d0 primes.py</title>
   </head>
   <body>
   
@@ -106,7 +107,7 @@
   <div class="main">
   <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
   <h3>
-   view primes.py @ 0:<a href="/rev/853dcd4de2a6">853dcd4de2a6</a>
+   view primes.py @ 0:<a href="/rev/06824edf55d0">06824edf55d0</a>
    <span class="tag">tip</span> 
   </h3>
   
@@ -173,7 +174,8 @@
   <span id="l29">    <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></span><a href="#l29"></a>
   <span id="l30">        <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></span><a href="#l30"></a>
   <span id="l31">    <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></span><a href="#l31"></a>
-  <span id="l32">    <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></span><a href="#l32"></a></pre>
+  <span id="l32">    <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></span><a href="#l32"></a>
+  <span id="l33"></span><a href="#l33"></a></pre>
   <div class="sourcelast"></div>
   </div>
   </div>
@@ -240,7 +242,7 @@
   <div class="main">
   <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
   <h3>
-   annotate primes.py @ 0:<a href="/rev/853dcd4de2a6">853dcd4de2a6</a>
+   annotate primes.py @ 0:<a href="/rev/06824edf55d0">06824edf55d0</a>
    <span class="tag">tip</span> 
   </h3>
   
@@ -284,228 +286,235 @@
     
   <tr id="l1">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l1"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l1"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l1">     1</a> <span class="c">#!/usr/bin/env python</span></td>
   </tr>
   <tr id="l2">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l2"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l2"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l2">     2</a> </td>
   </tr>
   <tr id="l3">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l3"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l3"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l3">     3</a> <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></td>
   </tr>
   <tr id="l4">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l4"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l4"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l4">     4</a> </td>
   </tr>
   <tr id="l5">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l5"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l5"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l5">     5</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></td>
   </tr>
   <tr id="l6">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l6"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l6"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l6">     6</a> <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></td>
   </tr>
   <tr id="l7">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l7"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l7"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l7">     7</a> <span class="sd">&quot;&quot;&quot;</span></td>
   </tr>
   <tr id="l8">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l8"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l8"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l8">     8</a> </td>
   </tr>
   <tr id="l9">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l9"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l9"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l9">     9</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></td>
   </tr>
   <tr id="l10">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l10"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l10"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l10">    10</a> </td>
   </tr>
   <tr id="l11">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l11"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l11"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l11">    11</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td>
   </tr>
   <tr id="l12">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l12"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l12"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l12">    12</a>     <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></td>
   </tr>
   <tr id="l13">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l13"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l13"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l13">    13</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
   </tr>
   <tr id="l14">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l14"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l14"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l14">    14</a>         <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></td>
   </tr>
   <tr id="l15">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l15"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l15"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l15">    15</a>         <span class="c"># It is important to yield *here* in order to stop the</span></td>
   </tr>
   <tr id="l16">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l16"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l16"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l16">    16</a>         <span class="c"># infinite recursion.</span></td>
   </tr>
   <tr id="l17">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l17"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l17"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l17">    17</a>         <span class="kn">yield</span> <span class="n">p</span></td>
   </tr>
   <tr id="l18">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l18"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l18"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l18">    18</a>         <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></td>
   </tr>
   <tr id="l19">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l19"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l19"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l19">    19</a>         <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
   </tr>
   <tr id="l20">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l20"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l20"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l20">    20</a>             <span class="kn">yield</span> <span class="n">n</span></td>
   </tr>
   <tr id="l21">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l21"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l21"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l21">    21</a> </td>
   </tr>
   <tr id="l22">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l22"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l22"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l22">    22</a>     <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mf">2</span> <span class="o">==</span> <span class="mf">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></td>
   </tr>
   <tr id="l23">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l23"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l23"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l23">    23</a>     <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mf">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mf">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></td>
   </tr>
   <tr id="l24">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l24"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l24"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l24">    24</a> </td>
   </tr>
   <tr id="l25">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l25"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l25"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l25">    25</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></td>
   </tr>
   <tr id="l26">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l26"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l26"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l26">    26</a>     <span class="kn">import</span> <span class="nn">sys</span></td>
   </tr>
   <tr id="l27">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l27"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l27"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l27">    27</a>     <span class="kn">try</span><span class="p">:</span></td>
   </tr>
   <tr id="l28">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l28"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l28"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l28">    28</a>         <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></td>
   </tr>
   <tr id="l29">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l29"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l29"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l29">    29</a>     <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></td>
   </tr>
   <tr id="l30">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l30"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l30"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l30">    30</a>         <span class="n">n</span> <span class="o">=</span> <span class="mf">10</span></td>
   </tr>
   <tr id="l31">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l31"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l31"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l31">    31</a>     <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></td>
   </tr>
   <tr id="l32">
   <td class="annotate">
-  <a href="/annotate/853dcd4de2a6/primes.py#l32"
-  title="853dcd4de2a6: a">test@0</a>
+  <a href="/annotate/06824edf55d0/primes.py#l32"
+  title="06824edf55d0: a">test@0</a>
   </td>
   <td class="source"><a href="#l32">    32</a>     <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></td>
   </tr>
+  <tr id="l33">
+  <td class="annotate">
+  <a href="/annotate/06824edf55d0/primes.py#l33"
+  title="06824edf55d0: a">test@0</a>
+  </td>
+  <td class="source"><a href="#l33">    33</a> </td>
+  </tr>
   </tbody>
   </table>
   </div>