Skip to content

singlemarkdown builder#37

Open
akaihola wants to merge 13 commits intoliran-funaro:mainfrom
akaihola:singlemarkdown
Open

singlemarkdown builder#37
akaihola wants to merge 13 commits intoliran-funaro:mainfrom
akaihola:singlemarkdown

Conversation

@akaihola
Copy link

Similar to the singlehtml built-in builder in Sphinx, the singlemarkdown builder collects all documentation pages together in a single .md file.

This is useful e.g. for providing documentation of a Python package to a language model / coding agent.

@coveralls
Copy link

coveralls commented May 17, 2025

Pull Request Test Coverage Report for Build 18984393558

Details

  • 136 of 150 (90.67%) changed or added relevant lines in 6 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.6%) to 97.747%

Changes Missing Coverage Covered Lines Changed/Added Lines %
sphinx_markdown_builder/singletranslator.py 12 16 75.0%
sphinx_markdown_builder/singlemarkdown.py 118 128 92.19%
Totals Coverage Status
Change from base Build 18555332874: -0.6%
Covered Lines: 911
Relevant Lines: 932

💛 - Coveralls

@liran-funaro
Copy link
Owner

@akaihola This seems like a nice addition. Can you address the failing tests?
I think it is due to the use of the type hint str|None which is not supported by python 3.9.
Python 3.9 is still a supported version, so I suggest to use the common approach Optional[str] for now.

@akaihola
Copy link
Author

@akaihola This seems like a nice addition. Can you address the failing tests? I think it is due to the use of the type hint str|None which is not supported by python 3.9. Python 3.9 is still a supported version, so I suggest to use the common approach Optional[str] for now.

Fixed!

@jdillard
Copy link

jdillard commented Oct 28, 2025

This is great! I pulled it into an experimental PR to try and use it to generate a llms-full.txt and noticed an issue with how some of the headings were generated:

## Changelog

# Changelog

## 0.7.0

- Add `llms_txt_uri_template` configuration option to control the link behavior in `llms_txt_filename`.
  [#48](https://github.com/jdillard/sphinx-llms-txt/pull/48)

### 0.6.0

- Improve \_sources directory handling
  [#47](https://github.com/jdillard/sphinx-llms-txt/pull/47)

#### 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)

The headings look fine on the normal markdown builder for that page: https://sphinx-llms-txt--51.org.readthedocs.build/en/51/changelog.md

edit: I made a (AI generated) PR here: akaihola#1

@akaihola
Copy link
Author

Thanks @jdillard! Obviously the original behavior is wrong. I'd like to add a failing unit test for your example case in this PR, and then verify that jdillard/sphinx-llms-txt#51 fixes it. I'll also rebase on liran-funaro:main and solve the conflict in sphinx_markdown_builder/__init__.py. You'll need to then rebase your PR.

This commit adds a functional SingleFileMarkdownBuilder that generates a single consolidated Markdown file from Sphinx documentation rather than separate files for each document.

Key changes:
- Complete implementation of SingleFileMarkdownBuilder with custom write_documents() method
- Add custom SingleMarkdownTranslator to properly handle document anchors and styling
- Add table of contents and document anchors to improve navigation in the single file
- Simplify cross-references by using document anchors within the same file
- Reformat test file to follow code style without functional changes

The builder can be used with: sphinx-build -M singlemarkdown ./docs ./build
The output will be a single file at ./build/singlemarkdown/<root_doc>.md
…tion errors

- Refactor setup function in __init__.py with proper type hints and return metadata
- Update singlemarkdown.py to follow Sphinx extension pattern by removing duplicate builder registration
- Follow pattern from Sphinx's singlehtml.py implementation
- Ensure proper extension loading through app.setup_extension
This commit adds the missing render_partial method to the SingleFileMarkdownBuilder class,
which resolves the 'no-member' errors in the singlemarkdown.py file.

The implementation:
- Creates a proper render_partial method based on Sphinx's similar functionality
- Uses StringOutput instead of StringIO for proper document rendering
- Ensures correct type handling for method return values
- Updates write_documents method to use StringOutput for consistency

Fixes E1101: Instance of 'SingleFileMarkdownBuilder' has no 'render_partial' member (no-member)
- Add proper type annotations to class attributes and method parameters/return types
- Fix potential type incompatibilities with appropriate casts
- Add pyright-specific comments to suppress false positives
- Improve variable naming and eliminate unused variables
- Replace implicit variable assignments with explicit ones using underscore
…nnotations

- Add extensive unit tests for SingleFileMarkdownBuilder methods
- Create separate test file for SingleMarkdownTranslator
- Improve Path handling in tests using pathlib
- Add proper type annotations for MarkdownWriter variable
- Test error handling and edge cases for better coverage
- Add parametrized tests to test singlemarkdown with various configuration options
- Test handling of missing build directories
- Test handling of file permission issues
- Match the integration test pattern from test_builder.py
- Enhance error handling and coverage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants