diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index 973658c1..c01ef1ad 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -494,3 +494,62 @@ def some_function():

Docstring of the function.

//// /// + +[](){#option-llm_friendly_source} +## `llm_friendly_source` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +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 +

some_function()

+

Docstring of the function.

+ +///// details | Source code in `package/module.py` + type: quote + +```python +def some_function(): + ... +``` +///// +//// + +//// tab | Traditional source (with line numbers) +

some_function()

+

Docstring of the function.

+ +///// details | Source code in `package/module.py` + type: quote + +```python linenums="1" +def some_function(): + ... +``` +///// +//// +/// diff --git a/src/mkdocstrings_handlers/python/_internal/config.py b/src/mkdocstrings_handlers/python/_internal/config.py index c0f9b79e..c7dd599b 100644 --- a/src/mkdocstrings_handlers/python/_internal/config.py +++ b/src/mkdocstrings_handlers/python/_internal/config.py @@ -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( diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja index 8a54dd1b..09e73ffc 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja @@ -200,7 +200,13 @@ Context: {{ init.relative_filepath }} {%- endif -%} - {{ init.source|highlight(language="python", linestart=init.lineno or 0, linenums=True) }} + {% if config.llm_friendly_source %} +
+
{{ init.source }}
+
+ {% else %} + {{ init.source|highlight(language="python", linestart=init.lineno or 0, linenums=True) }} + {% endif %} {% endwith %} {% endif %} @@ -213,7 +219,13 @@ Context: {{ class.relative_filepath }} {%- endif -%} - {{ class.source|highlight(language="python", linestart=class.lineno or 0, linenums=True) }} + {% if config.llm_friendly_source %} +
+
{{ class.source }}
+
+ {% else %} + {{ class.source|highlight(language="python", linestart=class.lineno or 0, linenums=True) }} + {% endif %} {% endif %} {% endif %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja index cd97c8db..48addb9e 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja @@ -153,7 +153,13 @@ Context: {{ function.relative_filepath }} {%- endif -%} - {{ function.source|highlight(language="python", linestart=function.lineno or 0, linenums=True) }} + {% if config.llm_friendly_source %} +
+
{{ function.source }}
+
+ {% else %} + {{ function.source|highlight(language="python", linestart=function.lineno or 0, linenums=True) }} + {% endif %} {% endif %} {% endblock source %} diff --git a/tests/test_handler.py b/tests/test_handler.py index f98ce545..be2331b0 100644 --- a/tests/test_handler.py +++ b/tests/test_handler.py @@ -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 '
' 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]