Skip to content

Commit 76d13c2

Browse files
committed
feat: added option to add line numbers to code blocks
As requested in #176 code blocks can be configured to display line numbers by adding a = to the specified language. e.g. ```python= print("Hello Line Numbers!") ```
1 parent c669400 commit 76d13c2

File tree

4 files changed

+87
-9
lines changed

4 files changed

+87
-9
lines changed

otterwiki/renderer.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def wrap(self, source):
5858
yield 0, '</pre></div>'
5959

6060

61-
def pygments_render(code, lang):
61+
def pygments_render(code, lang, linenumbers=False):
6262
try:
6363
lexer = get_lexer_by_name(lang, stripall=True)
6464
except ClassNotFound:
@@ -71,8 +71,8 @@ def pygments_render(code, lang):
7171
mistune.escape(code.strip()),
7272
)
7373
)
74-
formatter = CodeHtmlFormatter(classprefix=".highlight ")
75-
# formatter = html.HtmlFormatter(classprefix=".highlight ")
74+
linenos = "table" if linenumbers else None
75+
formatter = CodeHtmlFormatter(classprefix=".highlight ", linenos=linenos)
7676
return highlight(code, lexer, formatter)
7777

7878

@@ -161,8 +161,9 @@ def clean_html(html: str) -> str:
161161
break
162162
try:
163163
if any(
164-
x in element.attrs.keys() for x in REMOVE_ATTRIBUTES
165-
): # pyright: ignore
164+
x in element.attrs.keys()
165+
for x in REMOVE_ATTRIBUTES # pyright: ignore
166+
):
166167
_escape = True
167168
break
168169
except AttributeError:
@@ -209,7 +210,8 @@ def codespan(self, text):
209210

210211
def block_code(self, code, info=None):
211212
prefix = ""
212-
if not info:
213+
linenumbers = False
214+
if not info or not len(info):
213215
return (
214216
'\n'
215217
+ _pre_copy_to_clipboard_tag()
@@ -218,6 +220,9 @@ def block_code(self, code, info=None):
218220
if cursormagicword in info:
219221
info = info.replace(cursormagicword, "")
220222
prefix = cursormagicword
223+
if info[-1] == "=":
224+
info = info[:-1]
225+
linenumbers = True
221226
cursorline, code = hidemagicword(code)
222227
if info == "math":
223228
html = "".join(
@@ -232,7 +237,9 @@ def block_code(self, code, info=None):
232237
html = '\n<pre class="mermaid">{}\n</pre>\n'.format(code.strip())
233238
return html
234239
else:
235-
html = prefix + pygments_render(code, info)
240+
html = prefix + pygments_render(
241+
code, info, linenumbers=linenumbers
242+
)
236243
html = showmagicword(cursorline, html)
237244
return prefix + html
238245

otterwiki/static/css/elements/page.css

+31
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,34 @@
116116
.page table > :last-child > tr:last-child > th {
117117
border-bottom: 0;
118118
}
119+
120+
/* highlighttable with linenumbers */
121+
122+
.highlight table.highlighttable {
123+
width: 100%;
124+
padding: 0;
125+
margin: 0;
126+
background-color: transparent;
127+
}
128+
129+
.highlight table > tbody > tr > td.linenos {
130+
padding: 0;
131+
margin: 0;
132+
width: 0;
133+
border-right: 0;
134+
background-color: transparent;
135+
}
136+
137+
.highlight table > tbody > tr > td.linenos > div.linenodiv > pre {
138+
background-color: rgba(0, 0, 0, 0.1);
139+
margin-block-start: 0;
140+
margin-block-end: 0;
141+
border: 1px solid rgba(0,0,0,.05);
142+
}
143+
144+
.page table > tbody > tr > td.code {
145+
padding: 0;
146+
border: 0;
147+
margin: 0;
148+
background-color: transparent;
149+
}

otterwiki/templates/snippets/syntax.html

+23-2
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ <h4>{{ name }}</h4>
195195
</div>
196196
</div>
197197

198+
198199
<div class="row">
199200
<div class="col-md-6 col-sm-12 p-5">
200201
<pre>```
@@ -205,12 +206,18 @@ <h4>{{ name }}</h4>
205206
</div>
206207
</div>
207208

209+
210+
<div class="row">
211+
To add syntax highlighting, specify a language next to the backticks before the fenced code block.
212+
</div>
213+
208214
<div class="row">
209215
<div class="col-md-6 col-sm-12 p-5">
210216
<pre class="block-compact">```python
211217
#!/usr/bin/env python
212218
assert 1 + 1 == 2
213-
print("Hello World!")```</pre>
219+
print("Hello World!")
220+
```</pre>
214221
</div>
215222
<div class="col-md-6 col-sm-12 p-5">
216223
<div class="highlight"><pre class="block-compact"><span></span><span class=".highlight ch">#!/usr/bin/env python</span>
@@ -220,6 +227,21 @@ <h4>{{ name }}</h4>
220227
</div>
221228
</div>
222229

230+
<div class="row">
231+
To enable line numbers in the code block, append an equal sign <code>=</code> to the language.
232+
</div>
233+
<div class="row">
234+
<div class="col-md-6 col-sm-12 p-5">
235+
<pre class="block-compact">```python=
236+
print("Hello Line Numbers!")
237+
```</pre>
238+
</div>
239+
<div class="col-md-6 col-sm-12">
240+
<div class="highlight"><table class="highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><div class="copy-to-clipboard-outer"><div class="copy-to-clipboard-inner"><button class="btn alt-dm btn-xsm copy-to-clipboard" onclick="otterwiki.copy_to_clipboard(this);" type="button"><i "="" alt="Copy to clipboard" aria-hidden="true" class="fa fa-copy"></i></button></div><pre class="copy-to-clipboard code"><span class=".highlight nb">print</span><span class=".highlight p">(</span><span class=".highlight s2">"Hello Line Numbers!"</span><span class=".highlight p">)</span>
241+
</pre></div></div></td></tr></tbody></table></div>
242+
</div>
243+
</div>
244+
223245
{{ heading("Mathjax") }}
224246

225247
<div class="row">
@@ -406,4 +428,3 @@ <h4>Alerts</h4>
406428
<a href="http://daringfireball.net/projects/markdown/syntax">syntax</a> for more information.
407429

408430
Please Note: An Otter Wiki is not using the official implementation. This might lead to small differences in the little things.
409-

tests/test_renderer.py

+19
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,25 @@ def test_code():
8181
)
8282
assert pre_code is not None
8383
assert pre_code.text.startswith('non_existing_lexer')
84+
# test highlight with line numbers
85+
html, _ = render.markdown(
86+
"""```python=
87+
n = 2
88+
```"""
89+
)
90+
assert '<table class="highlighttable">' in html
91+
table_code = BeautifulSoup(html, "html.parser").find(
92+
'table', attrs={"class": "highlighttable"}
93+
)
94+
assert table_code is not None
95+
td_linenos = table_code.find(
96+
"td", attrs={"class": "linenos"}
97+
) # pyright: ignore
98+
assert td_linenos is not None
99+
assert td_linenos.text.startswith('1')
100+
td_code = table_code.find("td", attrs={"class": "code"}) # pyright: ignore
101+
assert td_code is not None
102+
assert td_code.text.startswith('n = 2')
84103

85104

86105
def test_img():

0 commit comments

Comments
 (0)