Compare commits

..
7 Commits
8 changed files with 89 additions and 16 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install -e . --group dev
# - name: Run mypy
# run: |
+18
View File
@@ -1,6 +1,24 @@
Changelog
=========
0.5.3
-----
- Make sphinx a required dependency since there are imports from Sphinx
`#44 <https://github.com/jdillard/sphinx-llms-txt/pull/44>`_
0.5.2
-----
- Remove support for singlehtml
`#40 <https://github.com/jdillard/sphinx-llms-txt/pull/40>`_
0.5.1
-----
- Only allow builders that have _sources directory
`#38 <https://github.com/jdillard/sphinx-llms-txt/pull/38>`_
0.5.0
-----
+4
View File
@@ -11,6 +11,10 @@ A Sphinx extension that generates a summary `llms.txt` file and a single combine
See [sphinx-llms-txt documentation](https://sphinx-llms-txt.readthedocs.io/en/latest/index.html) for installation and configuration instructions.
## Contributing
Pull Requests welcome! See [Contributing](https://sphinx-llms-txt.readthedocs.io/en/latest/contributing.html) for instructions on how best to contribute.
## License
MIT License - see LICENSE file for details.
+1 -1
View File
@@ -19,7 +19,7 @@ Local development
.. code-block:: console
pip install -e ".[dev]"
pip install -e . --group dev
#. Install pre-commit Git hook scripts:
+4 -2
View File
@@ -26,13 +26,16 @@ classifiers = [
license = {text = "MIT"}
readme = "README.md"
dynamic = ["version"]
dependencies = [
"sphinx",
]
[project.urls]
download = "https://pypi.org/project/sphinx-llms-txt/"
source = "https://github.com/jdillard/sphinx-llms-txt"
changelog = "https://github.com/jdillard/sphinx-llms-txt/blob/master/CHANGELOG.rst"
[project.optional-dependencies]
[dependency-groups]
dev = [
"pytest>=7.0.0",
"black",
@@ -40,7 +43,6 @@ dev = [
"mypy",
"isort",
"pre-commit",
"sphinx",
]
test = [
"pytest>=7.0.0",
+24 -10
View File
@@ -1,5 +1,14 @@
"""
Sphinx extension to create a combined sources file (llms-full.txt)
Sphinx extension that generates llms.txt and llms-full.txt files for LLM consumption.
This extension collects documentation content from Sphinx projects and generates
two output files:
- llms.txt: A concise Markdown summary with project overview and page links
- llms-full.txt: A comprehensive reStructuredText file containing all documentation
content with resolved includes and path references
The extension processes content during the build phase, handles page-level and
block-level ignore directives, and can optionally include source code files.
"""
from typing import Any, Dict
@@ -12,7 +21,7 @@ from .manager import LLMSFullManager
from .processor import DocumentProcessor
from .writer import FileWriter
__version__ = "0.5.0"
__version__ = "0.5.3"
# Export classes needed by tests
__all__ = [
@@ -104,7 +113,6 @@ def build_finished(app: Sphinx, exception):
def setup(app: Sphinx) -> Dict[str, Any]:
"""Set up the Sphinx extension."""
# Add configuration options
app.add_config_value("llms_txt_file", True, "env")
app.add_config_value("llms_txt_filename", "llms.txt", "env")
app.add_config_value("llms_txt_full_file", True, "env")
@@ -118,14 +126,20 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value("llms_txt_code_files", [], "env")
app.add_config_value("llms_txt_code_base_path", None, "env")
# Connect to Sphinx events
app.connect("doctree-resolved", doctree_resolved)
app.connect("build-finished", build_finished)
def builder_inited(app):
"""Used to limit what builders are allowed to run the extension."""
# Reset manager and root paragraph for each build
global _manager, _root_first_paragraph
_manager = LLMSFullManager()
_root_first_paragraph = ""
allowed_builders = ["html", "dirhtml"]
if hasattr(app, "builder") and app.builder.name in allowed_builders:
# Reset manager and root paragraph for each build
global _manager, _root_first_paragraph
_manager = LLMSFullManager()
_root_first_paragraph = ""
app.connect("doctree-resolved", doctree_resolved)
app.connect("build-finished", build_finished)
app.connect("builder-inited", builder_inited)
return {
"version": __version__,
-1
View File
@@ -197,7 +197,6 @@ class LLMSFullManager:
possible_sources = [
Path(outdir) / "_sources",
Path(outdir) / "html" / "_sources",
Path(outdir) / "singlehtml" / "_sources",
]
for path in possible_sources:
+36
View File
@@ -41,6 +41,42 @@ def test_setup_returns_valid_dict():
assert "parallel_write_safe" in result
def test_builder_inited_with_disallowed_builder():
"""Test that disallowed builders do not trigger extension setup."""
import sphinx_llms_txt
# Reset global state
sphinx_llms_txt._manager = sphinx_llms_txt.LLMSFullManager()
sphinx_llms_txt._root_first_paragraph = ""
# Mock a Sphinx app with a disallowed builder
class MockBuilder:
name = "text" # Not in allowed list
class MockApp:
def __init__(self):
self.config_values = {}
self.connections = {}
self.builder = MockBuilder()
def add_config_value(self, name, default, rebuild):
self.config_values[name] = (default, rebuild)
def connect(self, event, handler):
self.connections[event] = handler
app = MockApp()
setup(app)
# Trigger builder-inited
builder_inited_handler = app.connections["builder-inited"]
builder_inited_handler(app)
# With disallowed builder, other events should NOT be connected
assert "doctree-resolved" not in app.connections
assert "build-finished" not in app.connections
def test_document_collector_initialization():
"""Test initialization of DocumentCollector."""
collector = DocumentCollector()