Skip to content

Extra Newline When Highlighting Specific Lines #2122

@damned-me

Description

@damned-me

Hello!

I was trying out a new Jekyll feature — Marking Specific Lines, implemented here — and encountered some strange behavior.

The issue can be reproduced by rendering the following (I'm using the Minima v3 theme).

{% highlight ruby linenos mark_lines="2" %}
def foo
  puts 'foo'
end
{% endhighlight %}

{% highlight ruby linenos %}
def foo
  puts 'foo'
end
{% endhighlight %}

And it should look something like the following:

Image

I would expect the first block to present the same content as the second one. However, this doesn't happen due to what I believe is a bug in the HTML generation. Specifically, a newline is appended to the last processed line (after <span class="k">end</span>).

Generated HTML:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">foo</span>
<span class="hll">  <span class="nb">puts</span> <span class="s1">'foo'</span>
</span><span class="k">end</span>

</pre></td></tr></tbody></table></code></pre></figure>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">foo</span>
  <span class="nb">puts</span> <span class="s1">'foo'</span>
<span class="k">end</span>
</pre></td></tr></tbody></table></code></pre></figure>

I think the root cause for this behavior is here, where the newline character is appended without checking whether the line is the last one being processed.

While I don’t usually code in Ruby — apologies if the implementation quality is lacking — the following rewrite of the stream function effectively fixes the issue on my setup:

def stream(tokens)
    last_line = nil
    token_lines(tokens).with_index(1) do |line_tokens, lineno|
        if last_line
            yield last_line + "\n"
        end
        
        line = @delegate.format(line_tokens)
        line = %(<span class="#{@highlight_line_class}">#{line}</span>) if @highlight_lines.include?(lineno)
        last_line = line
    end
    
    yield last_line if last_line
end

Resulting in the following generated HTML:

Image

Correctly generated HTML

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">foo</span>
<span class="hll">  <span class="nb">puts</span> <span class="s1">'foo'</span></span>
<span class="k">end</span>
</pre></td></tr></tbody></table></code></pre></figure>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">foo</span>
  <span class="nb">puts</span> <span class="s1">'foo'</span>
<span class="k">end</span>
</pre></td></tr></tbody></table></code></pre></figure>

System:

  • OS: Linux 9fe7e33eef81 6.8.0-1020-raspi #24-Ubuntu SMP PREEMPT_DYNAMIC Sun Feb 23 08:39:32 UTC 2025 aarch64 GNU/Linux
  • Ruby version : ruby 3.3.8 (2025-04-09 revision b200bad6cd) [aarch64-linux]
  • Rouge version : Rouge 4.5.1

Let me know if I can provide any additional useful information.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugfix-requestA request for a bugfix to be developed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions