diff options
author | EuAndreh <eu@euandre.org> | 2025-04-18 02:17:12 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-04-18 02:48:42 -0300 |
commit | 020c1e77489b772f854bb3288b9c8d2818a6bf9d (patch) | |
tree | 142aec725a52162a446ea7d947cb4347c9d573c9 /src/content/tils/2020/08/13/code-jekyll.adoc | |
parent | Makefile: Remove security.txt.gz (diff) | |
download | euandre.org-020c1e77489b772f854bb3288b9c8d2818a6bf9d.tar.gz euandre.org-020c1e77489b772f854bb3288b9c8d2818a6bf9d.tar.xz |
git mv src/content/* src/content/en/
Diffstat (limited to 'src/content/tils/2020/08/13/code-jekyll.adoc')
-rw-r--r-- | src/content/tils/2020/08/13/code-jekyll.adoc | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/src/content/tils/2020/08/13/code-jekyll.adoc b/src/content/tils/2020/08/13/code-jekyll.adoc deleted file mode 100644 index 6bd90b0..0000000 --- a/src/content/tils/2020/08/13/code-jekyll.adoc +++ /dev/null @@ -1,159 +0,0 @@ -= Anchor headers and code lines in Jekyll - -:empty: -:jekyll: https://jekyllrb.com/ -:kramdown: https://kramdown.gettalong.org/ -:rouge: https://rouge.jneen.net/ -:jekyll-hook: https://jekyllrb.com/docs/plugins/hooks/ - -The default Jekyll toolbox ({jekyll}[Jekyll], {kramdown}[kramdown] and -{rouge}[rouge]) doesn't provide with a configuration option to add anchors to -headers and code blocks. - -The best way I found of doing this is by creating a simple Jekyll plugin, more -specifically, a {jekyll-hook}[Jekyll hook]. These allow you to jump in to the -Jekyll build and add a processing stage before of after Jekyll performs -something. - -All you have to do is add the code to `_plugins/my-jekyll-plugin-code.rb`, and -Jekyll knows to pick it up and call your code on the appropriate time. - -== Anchor on headers - -:jemoji: https://github.com/jekyll/jemoji -:jekyll-mentions: https://github.com/jekyll/jekyll-mentions -:html-regex: https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 - -Since I wanted to add anchors to headers in all documents, this Jekyll hook -works on `:documents` after they have been transformed into HTML, the -`:post_render` phase: - -[source,ruby] ----- -Jekyll::Hooks.register :documents, :post_render do |doc| - if doc.output_ext == ".html" - doc.output = - doc.output.gsub( - /<h([1-6])(.*?)id="([\w-]+)"(.*?)>(.*?)<\/h[1-6]>/, - '<a href="#\3"><h\1\2id="\3"\4>\5</h\1></a>' - ) - end -end ----- - -I've derived my implementations from two -"official"{empty}footnote:official[ - I don't know how official they are, I just assumed it because they live in the - same organization inside GitHub that Jekyll does. -] hooks, {jemoji}[jemoji] and {jekyll-mentions}[jekyll-mentions]. - -All I did was to wrap the header tag inside an `<a>`, and set the `href` of that -`<a>` to the existing id of the header. Before the hook the HTML looks like: - -[source,html] ----- -...some unmodified text... -<h2 id="my-header"> - My header -</h2> -...more unmodified text... ----- - -And after the hook should turn that into: - -[source,html] ----- -...some unmodified text... -<a href="#my-header"> - <h2 id="my-header"> - My header - </h2> -</a> -...more unmodified text... ----- - -The used regexp tries to match only h1-h6 tags, and keep the rest of the HTML -attributes untouched, since this isn't a general HTML parser, but the generated -HTML is somewhat under your control. Use at your own risk because -{html-regex}[you shouldn't parse HTML with regexps]. Also I used this strategy -in my environment, where no other plugins are installed. I haven't considered -how this approach may conflict with other Jekyll plugins. - -In the new anchor tag you can add your custom CSS class to style it as you wish. - -== Anchor on code blocks - -Adding anchors to code blocks needs a little bit of extra work, because line -numbers themselves don't have preexisting ids, so we need to generate them -without duplications between multiple code blocks in the same page. - -Similarly, this Jekyll hook also works on `:documents` in the `:post_render` -phase: - -[source,ruby] ----- -PREFIX = '<pre class="lineno">' -POSTFIX = '</pre>' -Jekyll::Hooks.register :documents, :post_render do |doc| - if doc.output_ext == ".html" - code_block_counter = 1 - doc.output = doc.output.gsub(/<pre class="lineno">[\n0-9]+<\/pre>/) do |match| - line_numbers = match - .gsub(/<pre class="lineno">([\n0-9]+)<\/pre>/, '\1') - .split("\n") - - anchored_line_numbers_array = line_numbers.map do |n| - id = "B#{code_block_counter}-L#{n}" - "<a id=\"#{id}\" href=\"##{id}\">#{n}</a>" - end - code_block_counter += 1 - - PREFIX + anchored_line_numbers_array.join("\n") + POSTFIX - end - end -end ----- - -This solution assumes the default Jekyll toolbox with code line numbers turned -on in `_config.yml`: - -[source,yaml] ----- -kramdown: - syntax_highlighter_opts: - span: - line_numbers: false - block: - line_numbers: true ----- - -The anchors go from B1-L1 to BN-LN, using the `code_block_counter` to track -which code block we're in and don't duplicate anchor ids. Before the hook the -HTML looks like: - -[source,html] ----- -...some unmodified text... -<pre class="lineno">1 -2 -3 -4 -5 -</pre> -...more unmodified text... ----- - -And after the hook should turn that into: - -[source,html] ----- -...some unmodified text... -<pre class="lineno"><a id="B1-L1" href="#B1-L1">1</a> -<a id="B1-L2" href="#B1-L2">2</a> -<a id="B1-L3" href="#B1-L3">3</a> -<a id="B1-L4" href="#B1-L4">4</a> -<a id="B1-L5" href="#B1-L5">5</a></pre> -...more unmodified text... ----- - -Happy writing :) |