Skip to content

feat: Add llm_friendly_source option for LLM-compatible source rendering #300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions docs/usage/configuration/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,62 @@ def some_function():
<p>Docstring of the function.</p>
////
///

[](){#option-llm_friendly_source}
## `llm_friendly_source`

- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
<!-- - **:octicons-project-template-24: Template :material-null:** (contained in [`class.html`][class template] and [`function.html`][function template]) -->

When [`show_source`](#show_source) is enabled, render source code in a format more compatible with LLM-focused tools. This removes line numbers and uses simple markdown code blocks instead of complex HTML tables.

This is particularly useful when using tools like mkdocs-llmstxt that convert documentation to LLM-friendly text formats.

```yaml title="in mkdocs.yml (global configuration)"
plugins:
- mkdocstrings:
handlers:
python:
options:
show_source: true
llm_friendly_source: true
```

```md title="or in docs/some_page.md (local configuration)"
::: path.to.object
options:
show_source: true
llm_friendly_source: true
```

/// admonition | Preview
type: preview

//// tab | LLM-friendly source
<h2><code>some_function()</code></h2>
<p>Docstring of the function.</p>

///// details | Source code in `package/module.py`
type: quote

```python
def some_function():
...
```
/////
////

//// tab | Traditional source (with line numbers)
<h2><code>some_function()</code></h2>
<p>Docstring of the function.</p>

///// details | Source code in `package/module.py`
type: quote

```python linenums="1"
def some_function():
...
```
/////
////
///
8 changes: 8 additions & 0 deletions src/mkdocstrings_handlers/python/_internal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,14 @@ class PythonInputOptions:
),
] = True

llm_friendly_source: Annotated[
bool,
_Field(
group="general",
description="When show_source is enabled, render source code in a format more compatible with LLM-focused tools (no line numbers, simple markdown code blocks).",
),
] = False

show_submodules: Annotated[
bool,
_Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,13 @@ Context:
{{ init.relative_filepath }}
{%- endif -%}
</code></summary>
{{ init.source|highlight(language="python", linestart=init.lineno or 0, linenums=True) }}
{% if config.llm_friendly_source %}
<div class="language-python highlight">
<pre><code class="language-python">{{ init.source }}</code></pre>
</div>
{% else %}
{{ init.source|highlight(language="python", linestart=init.lineno or 0, linenums=True) }}
{% endif %}
</details>
{% endwith %}
{% endif %}
Expand All @@ -213,7 +219,13 @@ Context:
{{ class.relative_filepath }}
{%- endif -%}
</code></summary>
{{ class.source|highlight(language="python", linestart=class.lineno or 0, linenums=True) }}
{% if config.llm_friendly_source %}
<div class="language-python highlight">
<pre><code class="language-python">{{ class.source }}</code></pre>
</div>
{% else %}
{{ class.source|highlight(language="python", linestart=class.lineno or 0, linenums=True) }}
{% endif %}
</details>
{% endif %}
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,13 @@ Context:
{{ function.relative_filepath }}
{%- endif -%}
</code></summary>
{{ function.source|highlight(language="python", linestart=function.lineno or 0, linenums=True) }}
{% if config.llm_friendly_source %}
<div class="language-python highlight">
<pre><code class="language-python">{{ function.source }}</code></pre>
</div>
{% else %}
{{ function.source|highlight(language="python", linestart=function.lineno or 0, linenums=True) }}
{% endif %}
</details>
{% endif %}
{% endblock source %}
Expand Down
24 changes: 24 additions & 0 deletions tests/test_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,30 @@ def function(self):
assert handler.render(module, PythonOptions(show_source=True))


def test_llm_friendly_source_rendering(handler: PythonHandler) -> None:
"""Test LLM-friendly source code rendering."""
code = dedent(
"""
class Example:
'''Example class.'''

def method(self):
'''Example method.'''
return "hello"
""",
)
with temporary_visited_module(code) as module:
# Test traditional rendering (with line numbers)
traditional_html = handler.render(module["Example"], PythonOptions(show_source=True, llm_friendly_source=False))
assert "linenums" in traditional_html or "lineno" in traditional_html

# Test LLM-friendly rendering (without line numbers, simple code blocks)
llm_friendly_html = handler.render(module["Example"], PythonOptions(show_source=True, llm_friendly_source=True))
assert '<pre><code class="language-python">' in llm_friendly_html
assert "linenums" not in llm_friendly_html
assert "lineno" not in llm_friendly_html


def test_give_precedence_to_user_paths() -> None:
"""Assert user paths take precedence over default paths."""
last_sys_path = sys.path[-1]
Expand Down
Loading