Skip to content

Commit b263f6b

Browse files
authored
Merge pull request #1463 from Isaac-Flath/HTMLRendererImprovements
Html renderer improvements
2 parents dc110c9 + 16fc9bc commit b263f6b

File tree

3 files changed

+80
-15
lines changed

3 files changed

+80
-15
lines changed

nbdev/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@
334334
'nbdev.showdoc.ShowDocRenderer': ('api/showdoc.html#showdocrenderer', 'nbdev/showdoc.py'),
335335
'nbdev.showdoc.ShowDocRenderer.__init__': ('api/showdoc.html#showdocrenderer.__init__', 'nbdev/showdoc.py'),
336336
'nbdev.showdoc._bold': ('api/showdoc.html#_bold', 'nbdev/showdoc.py'),
337+
'nbdev.showdoc._create_html_table': ('api/showdoc.html#_create_html_table', 'nbdev/showdoc.py'),
337338
'nbdev.showdoc._docstring': ('api/showdoc.html#_docstring', 'nbdev/showdoc.py'),
338339
'nbdev.showdoc._escape_markdown': ('api/showdoc.html#_escape_markdown', 'nbdev/showdoc.py'),
339340
'nbdev.showdoc._ext_link': ('api/showdoc.html#_ext_link', 'nbdev/showdoc.py'),

nbdev/showdoc.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,24 +192,47 @@ def show_doc(sym, # Symbol to document
192192
if isinstance(sym, TypeDispatch): pass
193193
else:return renderer(sym or show_doc, name=name, title_level=title_level)
194194

195+
# %% ../nbs/api/08_showdoc.ipynb
196+
def _create_html_table(table_str):
197+
def split_row(row):
198+
return re.findall(r'\|(?:(?:\\.|[^|\\])*)', row)
199+
200+
def unescape_cell(cell):
201+
return cell.strip(' *|').replace(r'\|', '|')
202+
203+
lines = table_str.strip().split('\n')
204+
header = [f"<th>{unescape_cell(cell)}</th>" for cell in split_row(lines[0])]
205+
rows = [[f"<td>{unescape_cell(cell)}</td>" for cell in split_row(line)] for line in lines[2:]]
206+
207+
return f'''<table>
208+
<thead><tr>{' '.join(header)}</tr></thead>
209+
<tbody>{''.join(f'<tr>{" ".join(row)}</tr>' for row in rows)}</tbody>
210+
</table>'''
211+
195212
# %% ../nbs/api/08_showdoc.ipynb
196213
def _html_link(url, txt): return f'<a href="{url}" target="_blank" rel="noreferrer noopener">{txt}</a>'
197214

215+
# %% ../nbs/api/08_showdoc.ipynb
198216
class BasicHtmlRenderer(ShowDocRenderer):
199-
"Simple HTML renderer for `show_doc`"
217+
"HTML renderer for `show_doc`"
200218
def _repr_html_(self):
201219
doc = '<hr/>\n'
220+
src = NbdevLookup().code(self.fn)
202221
doc += f'<h{self.title_level}>{self.nm}</h{self.title_level}>\n'
203-
doc += f'<blockquote><pre><code>{self.nm}{_fmt_sig(self.sig)}</code></pre></blockquote>'
204-
if self.docs: doc += f"<p><i>{self.docs}</i></p>"
222+
sig = _fmt_sig(self.sig) if self.sig else ''
223+
# Escape < and > characters in the signature
224+
sig = sig.replace('<', '&lt;').replace('>', '&gt;')
225+
doc += f'<blockquote><pre><code>{self.nm} {sig}</code></pre></blockquote>'
226+
if self.docs:
227+
doc += f"<p><i>{self.docs}</i></p>"
228+
if src: doc += f"<br/>{_html_link(src, 'source')}"
229+
if self.dm.has_docment: doc += _create_html_table(str(self.dm))
205230
return doc
206231

207232
def doc(self):
208233
"Show `show_doc` info along with link to docs"
209234
from IPython.display import display,HTML
210235
res = self._repr_html_()
211-
docs = NbdevLookup().doc(self.fn)
212-
if docs is not None: res += '\n<p>' +_html_link(docs, "Show in docs") + '</p>'
213236
display(HTML(res))
214237

215238
# %% ../nbs/api/08_showdoc.ipynb

nbs/api/08_showdoc.ipynb

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -957,31 +957,70 @@
957957
"You can replace the default markdown show_doc renderer with custom renderers. For instance, nbdev comes with a simple example for rendering with raw HTML."
958958
]
959959
},
960+
{
961+
"cell_type": "code",
962+
"execution_count": null,
963+
"id": "5271cd9a",
964+
"metadata": {},
965+
"outputs": [],
966+
"source": [
967+
"#| export\n",
968+
"def _create_html_table(table_str):\n",
969+
" def split_row(row):\n",
970+
" return re.findall(r'\\|(?:(?:\\\\.|[^|\\\\])*)', row)\n",
971+
" \n",
972+
" def unescape_cell(cell): \n",
973+
" return cell.strip(' *|').replace(r'\\|', '|')\n",
974+
" \n",
975+
" lines = table_str.strip().split('\\n')\n",
976+
" header = [f\"<th>{unescape_cell(cell)}</th>\" for cell in split_row(lines[0])]\n",
977+
" rows = [[f\"<td>{unescape_cell(cell)}</td>\" for cell in split_row(line)] for line in lines[2:]]\n",
978+
" \n",
979+
" return f'''<table>\n",
980+
" <thead><tr>{' '.join(header)}</tr></thead>\n",
981+
" <tbody>{''.join(f'<tr>{\" \".join(row)}</tr>' for row in rows)}</tbody>\n",
982+
" </table>'''"
983+
]
984+
},
985+
{
986+
"cell_type": "code",
987+
"execution_count": null,
988+
"id": "a4ae5b2a",
989+
"metadata": {},
990+
"outputs": [],
991+
"source": [
992+
"#| export\n",
993+
"def _html_link(url, txt): return f'<a href=\"{url}\" target=\"_blank\" rel=\"noreferrer noopener\">{txt}</a>'"
994+
]
995+
},
960996
{
961997
"cell_type": "code",
962998
"execution_count": null,
963999
"id": "147626ee",
9641000
"metadata": {},
9651001
"outputs": [],
9661002
"source": [
967-
"#|export\n",
968-
"def _html_link(url, txt): return f'<a href=\"{url}\" target=\"_blank\" rel=\"noreferrer noopener\">{txt}</a>'\n",
969-
"\n",
1003+
"#| export\n",
9701004
"class BasicHtmlRenderer(ShowDocRenderer):\n",
971-
" \"Simple HTML renderer for `show_doc`\"\n",
1005+
" \"HTML renderer for `show_doc`\"\n",
9721006
" def _repr_html_(self):\n",
9731007
" doc = '<hr/>\\n'\n",
1008+
" src = NbdevLookup().code(self.fn)\n",
9741009
" doc += f'<h{self.title_level}>{self.nm}</h{self.title_level}>\\n'\n",
975-
" doc += f'<blockquote><pre><code>{self.nm}{_fmt_sig(self.sig)}</code></pre></blockquote>'\n",
976-
" if self.docs: doc += f\"<p><i>{self.docs}</i></p>\"\n",
1010+
" sig = _fmt_sig(self.sig) if self.sig else ''\n",
1011+
" # Escape < and > characters in the signature\n",
1012+
" sig = sig.replace('<', '&lt;').replace('>', '&gt;')\n",
1013+
" doc += f'<blockquote><pre><code>{self.nm} {sig}</code></pre></blockquote>'\n",
1014+
" if self.docs:\n",
1015+
" doc += f\"<p><i>{self.docs}</i></p>\"\n",
1016+
" if src: doc += f\"<br/>{_html_link(src, 'source')}\"\n",
1017+
" if self.dm.has_docment: doc += _create_html_table(str(self.dm))\n",
9771018
" return doc\n",
9781019
"\n",
9791020
" def doc(self):\n",
9801021
" \"Show `show_doc` info along with link to docs\"\n",
9811022
" from IPython.display import display,HTML\n",
9821023
" res = self._repr_html_()\n",
983-
" docs = NbdevLookup().doc(self.fn)\n",
984-
" if docs is not None: res += '\\n<p>' +_html_link(docs, \"Show in docs\") + '</p>'\n",
9851024
" display(HTML(res))"
9861025
]
9871026
},
@@ -1009,8 +1048,10 @@
10091048
"text/html": [
10101049
"<hr/>\n",
10111050
"<h3>show_doc</h3>\n",
1012-
"<blockquote><pre><code>show_doc(sym, renderer=None, name:str|None=None, title_level:int=3)</code></pre></blockquote><p>Show signature and docstring for `sym`</p>\n",
1013-
"<p><a href=\"https://nbdev.fast.ai/api/showdoc.html#show_doc\" target=\"_blank\" rel=\"noreferrer noopener\">Show in docs</a></p>"
1051+
"<blockquote><pre><code>show_doc (sym, renderer=None, name:str|None=None, title_level:int=3)</code></pre></blockquote><p><i>Show signature and docstring for `sym`</i></p><br/><a href=\"https://github.com/fastai/nbdev/blob/master/nbdev/showdoc.py#L182\" target=\"_blank\" rel=\"noreferrer noopener\">source</a><table>\n",
1052+
" <thead><tr><th></th> <th>Type</th> <th>Default</th> <th>Details</th> <th></th></tr></thead>\n",
1053+
" <tbody><tr><td>sym</td> <td></td> <td></td> <td>Symbol to document</td> <td></td></tr><tr><td>renderer</td> <td>NoneType</td> <td>None</td> <td>Optional renderer (defaults to markdown)</td> <td></td></tr><tr><td>name</td> <td>str | None</td> <td>None</td> <td>Optionally override displayed name of `sym`</td> <td></td></tr><tr><td>title_level</td> <td>int</td> <td>3</td> <td>Heading level to use for symbol name</td> <td></td></tr></tbody>\n",
1054+
" </table>"
10141055
],
10151056
"text/plain": [
10161057
"<IPython.core.display.HTML object>"

0 commit comments

Comments
 (0)