diff --git a/CHANGELOG.md b/CHANGELOG.md index 73178142..83a77437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## Unreleased: pdoc next - Fix handling of URL-escaped module names ([#787](https://github.com/mitmproxy/pdoc/pull/787), @iFreilicht) +- Embed local images referenced in docstrings with an HTML image tag (``) in addition to Markdown (`![image](./image.png)`) ([#785](https://github.com/mitmproxy/pdoc/pull/785), @earshinov) ## 2024-12-12: pdoc 15.0.1 diff --git a/pdoc/docstrings.py b/pdoc/docstrings.py index 5c9dc682..7a4624d3 100644 --- a/pdoc/docstrings.py +++ b/pdoc/docstrings.py @@ -63,23 +63,28 @@ def convert(docstring: str, docformat: str, source_file: Path | None) -> str: def embed_images(docstring: str, source_file: Path) -> str: + def local_image_to_data_uri(href: str) -> str: + image_path = source_file.parent / href + image_data = image_path.read_bytes() + image_mime = mimetypes.guess_type(image_path)[0] + image_data_b64 = base64.b64encode(image_data).decode() + return f"data:{image_mime};base64,{image_data_b64}" + def embed_local_image(m: re.Match) -> str: - image_path = source_file.parent / m["href"] try: - image_data = image_path.read_bytes() - image_mime = mimetypes.guess_type(image_path)[0] + href = local_image_to_data_uri(m["href"]) except Exception: return m[0] else: - data = base64.b64encode(image_data).decode() - return f"![{m['alt']}](data:{image_mime};base64,{data})" - - return re.sub( - r"!\[\s*(?P.*?)\s*]\(\s*(?P.+?)\s*\)", - embed_local_image, - docstring, - ) - # TODO: Could probably do more here, e.g. support rST or raw HTML replacements. + return m["before"] + href + m["after"] + + # TODO: Could probably do more here, e.g. support rST replacements. + for regex in [ + r"(?P!\[\s*.*?\s*]\(\s*)(?P.+?)(?P\s*\))", + r"""(?Psrc=['"])(?P.+?)(?P['"])""", + ]: + docstring = re.sub(regex, embed_local_image, docstring) + return docstring def google(docstring: str) -> str: diff --git a/test/testdata/demo_long.html b/test/testdata/demo_long.html index da10bd52..c7af5878 100644 --- a/test/testdata/demo_long.html +++ b/test/testdata/demo_long.html @@ -270,14 +270,14 @@

A Second Section

39 40FOO_CONSTANT: int = 42 41""" - 42A happy constant. ✨ + 42A happy constant. ✨ 43pdoc documents constants with their type annotation and default value. 44""" 45 46FOO_SINGLETON: "Foo" 47""" 48This variable is annotated with a type only, but not assigned to a value. - 49We also haven't defined the associated type (`Foo`) yet, + 49We also haven't defined the associated type (`Foo`) yet, 50so the type annotation in the code in the source code is actually a string literal: 51 52```python @@ -486,31 +486,37 @@

A Second Section

255 ``` 256 257 ![pdoc logo](../../docs/logo.png) -258 """ -259 -260 -261def admonitions(): -262 """ -263 pdoc also supports basic reStructuredText admonitions or GitHub's Markdown alerts: -264 -265 ``` -266 > [!NOTE/WARNING/DANGER] -267 > Useful information that users should know, even when skimming content. -268 -269 .. note/warning/danger:: Optional title -270 Body text +258 +259 ``` +260 <img src="../docs/logo.png" alt="pdoc logo" width="150"> +261 ``` +262 +263 <img src="../../docs/logo.png" alt="pdoc logo" width="150"> +264 """ +265 +266 +267def admonitions(): +268 """ +269 pdoc also supports basic reStructuredText admonitions or GitHub's Markdown alerts: +270 271 ``` -272 -273 > [!NOTE] -274 > Hi there! -275 -276 .. warning:: Be Careful! -277 This warning has both a title *and* content. +272 > [!NOTE/WARNING/DANGER] +273 > Useful information that users should know, even when skimming content. +274 +275 .. note/warning/danger:: Optional title +276 Body text +277 ``` 278 -279 .. danger:: -280 Danger ahead. +279 > [!NOTE] +280 > Hi there! 281 -282 """ +282 .. warning:: Be Careful! +283 This warning has both a title *and* content. +284 +285 .. danger:: +286 Danger ahead. +287 +288 """ @@ -524,7 +530,7 @@

A Second Section

-

A happy constant. ✨
+

A happy constant. ✨ pdoc documents constants with their type annotation and default value.

@@ -539,7 +545,7 @@

A Second Section

This variable is annotated with a type only, but not assigned to a value. -We also haven't defined the associated type (Foo) yet, +We also haven't defined the associated type (Foo) yet, so the type annotation in the code in the source code is actually a string literal:

@@ -1507,7 +1513,13 @@
Inherited Members
256 ``` 257 258 ![pdoc logo](../../docs/logo.png) -259 """ +259 +260 ``` +261 <img src="../docs/logo.png" alt="pdoc logo" width="150"> +262 ``` +263 +264 <img src="../../docs/logo.png" alt="pdoc logo" width="150"> +265 """
@@ -1517,6 +1529,11 @@
Inherited Members

pdoc logo

+ +
<img src="../docs/logo.png" alt="pdoc logo" width="150">
+
+ +

pdoc logo

@@ -1532,28 +1549,28 @@
Inherited Members
-
262def admonitions():
-263    """
-264    pdoc also supports basic reStructuredText admonitions or GitHub's Markdown alerts:
-265
-266    ```
-267    > [!NOTE/WARNING/DANGER]
-268    > Useful information that users should know, even when skimming content.
-269
-270    .. note/warning/danger:: Optional title
-271       Body text
+            
268def admonitions():
+269    """
+270    pdoc also supports basic reStructuredText admonitions or GitHub's Markdown alerts:
+271
 272    ```
-273
-274    > [!NOTE]
-275    > Hi there!
-276
-277    .. warning:: Be Careful!
-278       This warning has both a title *and* content.
+273    > [!NOTE/WARNING/DANGER]
+274    > Useful information that users should know, even when skimming content.
+275
+276    .. note/warning/danger:: Optional title
+277       Body text
+278    ```
 279
-280    .. danger::
-281       Danger ahead.
+280    > [!NOTE]
+281    > Hi there!
 282
-283    """
+283    .. warning:: Be Careful!
+284       This warning has both a title *and* content.
+285
+286    .. danger::
+287       Danger ahead.
+288
+289    """
 
diff --git a/test/testdata/demo_long.py b/test/testdata/demo_long.py index 7b85334e..839ccf0e 100644 --- a/test/testdata/demo_long.py +++ b/test/testdata/demo_long.py @@ -39,14 +39,14 @@ FOO_CONSTANT: int = 42 """ -A happy constant. ✨ +A happy constant. ✨ pdoc documents constants with their type annotation and default value. """ FOO_SINGLETON: "Foo" """ This variable is annotated with a type only, but not assigned to a value. -We also haven't defined the associated type (`Foo`) yet, +We also haven't defined the associated type (`Foo`) yet, so the type annotation in the code in the source code is actually a string literal: ```python @@ -255,6 +255,12 @@ def embed_image(): ``` ![pdoc logo](../../docs/logo.png) + + ``` + pdoc logo + ``` + + pdoc logo """ diff --git a/test/testdata/demo_long.txt b/test/testdata/demo_long.txt index 2d80cf0f..512ec3da 100644 --- a/test/testdata/demo_long.txt +++ b/test/testdata/demo_long.txt @@ -1,7 +1,8 @@ + str: ... # This is a basic modu…>