1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#
msgid ""
msgstr ""
msgid ""
"title: Anchor headers and code lines in Jekyll\n"
"date: 2020-08-13\n"
"layout: post\n"
"lang: en\n"
"ref: anchor-headers-and-code-lines-in-jekyll"
msgstr ""
msgid ""
"The default Jekyll toolbox ([Jekyll](https://jekyllrb.com/), "
"[kramdown](https://kramdown.gettalong.org/) and "
"[rouge](http://rouge.jneen.net/)) doesn't provide with a configuration "
"option to add anchors to headers and code blocks."
msgstr ""
msgid ""
"The best way I found of doing this is by creating a simple Jekyll plugin, "
"more specifically, a [Jekyll "
"hook](https://jekyllrb.com/docs/plugins/hooks/). These allow you to jump in "
"to the Jekyll build and add a processing stage before of after Jekyll "
"performs something."
msgstr ""
msgid ""
"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."
msgstr ""
msgid "Anchor on headers"
msgstr ""
msgid ""
"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:"
msgstr ""
msgid ""
"I've derived my implementations from two \"official\"[^official] hooks, "
"[jemoji](https://github.com/jekyll/jemoji) and [jekyll-"
"mentions](https://github.com/jekyll/jekyll-mentions)."
msgstr ""
msgid ""
"[^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."
msgstr ""
msgid ""
"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:"
msgstr ""
msgid "And after the hook should turn that into:"
msgstr ""
msgid ""
"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 "
"[you shouldn't parse HTML with "
"regexps](https://stackoverflow.com/questions/1732348/regex-match-open-tags-"
"except-xhtml-self-contained-tags/1732454#1732454). 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."
msgstr ""
msgid ""
"In the new anchor tag you can add your custom CSS class to style it as you "
"wish."
msgstr ""
msgid "Anchor on code blocks"
msgstr ""
msgid ""
"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."
msgstr ""
msgid ""
"Similarly, this Jekyll hook also works on `:documents` in the `:post_render`"
" phase:"
msgstr ""
msgid ""
"This solution assumes the default Jekyll toolbox with code line numbers "
"turned on in `_config.yml`:"
msgstr ""
msgid ""
"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:"
msgstr ""
msgid "Happy writing :)"
msgstr ""
msgid ""
"Jekyll::Hooks.register :documents, :post_render do |doc|\n"
" if doc.output_ext == \".html\"\n"
" doc.output =\n"
" doc.output.gsub(\n"
" /<h([1-6])(.*?)id=\"([\\w-]+)\"(.*?)>(.*?)<\\/h[1-6]>/,\n"
" '<a href=\"#\\3\"><h\\1\\2id=\"\\3\"\\4>\\5</h\\1></a>'\n"
" )\n"
" end\n"
"end\n"
msgstr ""
msgid ""
"...some unmodified text...\n"
"<h2 id=\"my-header\">\n"
" My header\n"
"</h2>\n"
"...more unmodified text...\n"
msgstr ""
msgid ""
"...some unmodified text...\n"
"<a href=\"#my-header\">\n"
" <h2 id=\"my-header\">\n"
" My header\n"
" </h2>\n"
"</a>\n"
"...more unmodified text...\n"
msgstr ""
msgid ""
"PREFIX = '<pre class=\"lineno\">'\n"
"POSTFIX = '</pre>'\n"
"Jekyll::Hooks.register :documents, :post_render do |doc|\n"
" if doc.output_ext == \".html\"\n"
" code_block_counter = 1\n"
" doc.output = doc.output.gsub(/<pre class=\"lineno\">[\\n0-9]+<\\/pre>/) do |match|\n"
" line_numbers = match\n"
" .gsub(/<pre class=\"lineno\">([\\n0-9]+)<\\/pre>/, '\\1')\n"
" .split(\"\\n\")\n"
"\n"
" anchored_line_numbers_array = line_numbers.map do |n|\n"
" id = \"B#{code_block_counter}-L#{n}\"\n"
" \"<a id=\\\"#{id}\\\" href=\\\"##{id}\\\">#{n}</a>\"\n"
" end\n"
" code_block_counter += 1\n"
"\n"
" PREFIX + anchored_line_numbers_array.join(\"\\n\") + POSTFIX\n"
" end\n"
" end\n"
"end\n"
msgstr ""
msgid ""
"kramdown:\n"
" syntax_highlighter_opts:\n"
" span:\n"
" line_numbers: false\n"
" block:\n"
" line_numbers: true\n"
msgstr ""
msgid ""
"...some unmodified text...\n"
"<pre class=\"lineno\">1\n"
"2\n"
"3\n"
"4\n"
"5\n"
"</pre>\n"
"...more unmodified text...\n"
msgstr ""
msgid ""
"...some unmodified text...\n"
"<pre class=\"lineno\"><a id=\"B1-L1\" href=\"#B1-L1\">1</a>\n"
"<a id=\"B1-L2\" href=\"#B1-L2\">2</a>\n"
"<a id=\"B1-L3\" href=\"#B1-L3\">3</a>\n"
"<a id=\"B1-L4\" href=\"#B1-L4\">4</a>\n"
"<a id=\"B1-L5\" href=\"#B1-L5\">5</a></pre>\n"
"...more unmodified text...\n"
msgstr ""
|