I am using pygments and kramdown in my jekyll blog.
I tried to add code block to markdown list, but display incorrect.
1. first
2. second
{% highlight ruby %}
def foo
puts 'foo'
end
{% endhighlight %}
3. third
generated html:
<ol>
<li>
<p>first</p>
</li>
<li>
<p>second</p>
</li>
</ol>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><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></code></pre></div>
<ol>
<li>third</li>
</ol>
but if I write like this, it is no problem.
1. first
2. second
```
def foo
puts 'foo'
end
```
3. third
Is this pygments or kramdown problem? Hope someone can help me, thanks in advanced!
The problem is not with Liquid or kramdown individually, but how they operate together. Jekyll seems to be processing the files with Liquid first, followed by passing the result to kramdown to be parsed as markdown.
This means that kramdown is seeing something like this:
1. first
2. second
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"> <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>
</code></pre></figure>
3. third
Liquid isn’t keeping the indentation of the code section, and so when processed as markdown it is causing the list to close and the third item to be seen as a new list.
In order to use the highlight
Liquid tag here you need to ensure the result of Liquid processing is the appropriately indented markdown. I don’t know if this is possible with plain Jekyll, but you could do this fairly simply with a plugin (so this won’t work if you are using Github pages).
Create a file named something like _plugins/indent_filter.rb
with these contents:
module IndentFilter
def indent(input)
input.gsub(/\n/, "\n ")
end
end
Liquid::Template.register_filter(IndentFilter)
Now you can use it like this:
1. first
2. second
{% capture the_code %}
{% highlight ruby %}
def foo
puts 'foo'
end
{% endhighlight %}
{% endcapture %}
{{ the_code | indent }}
3. third
Note that you need to use capture
first in order to use the indent
filter (you could probably create a custom tag to use instead of highlight
if you prefer). Also note that the Liquid tags aren’t indented at all, that is handled by the filter.
The result of this after Liquid processing but before markdown is something like this:
1. first
2. second
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><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></code></pre></figure>
3. third
Now the code block is correctly indented so that markdown sees it as the content of the second list item. Since it is already HTML kramdown doesn’t try to process it further, but also it doesn’t cause the list to be closed. The result after markdown processing is:
<ol>
<li>
<p>first</p>
</li>
<li>
<p>second</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><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></code></pre></figure>
</li>
<li>
<p>third</p>
</li>
</ol>
The Jekyll highlight
tag is trimming the content. Since the spaces before your end
statement are in the middle of the text, it won't get trimmed.
Unindent the whole block of code and it should render correctly.
1. first
2. second
{% highlight ruby %}
def foo
puts 'foo'
end
{% endhighlight %}
3. third