|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This file provides guidance for AI coding agents working on the **sphinx-design** repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +sphinx-design is a Sphinx extension for designing beautiful, view size responsive web components. It provides: |
| 8 | + |
| 9 | +- Grids, cards, dropdowns, tabs, badges, buttons, and icons |
| 10 | +- Responsive design inspired by [Bootstrap](https://getbootstrap.com/) (v5), [Material Design](https://material.io), and [Material-UI](https://material-ui.com/) |
| 11 | +- Support for both reStructuredText and [MyST Markdown](https://myst-parser.readthedocs.io/) (via integration with myst-parser) |
| 12 | + |
| 13 | +The extension works with multiple Sphinx themes including alabaster, sphinx-rtd-theme, pydata-sphinx-theme, sphinx-book-theme, furo, and sphinx-immaterial. |
| 14 | + |
| 15 | +## Repository Structure |
| 16 | + |
| 17 | +``` |
| 18 | +pyproject.toml # Project configuration and dependencies |
| 19 | +tox.ini # Tox test environment configuration |
| 20 | +package.json # Node.js config for SASS compilation |
| 21 | +
|
| 22 | +sphinx_design/ # Main source code |
| 23 | +├── __init__.py # Package init with setup() entry point |
| 24 | +├── _compat.py # Compatibility utilities |
| 25 | +├── extension.py # Main Sphinx extension setup |
| 26 | +├── shared.py # Shared constants and base classes |
| 27 | +├── badges_buttons.py # Badge and button directives |
| 28 | +├── cards.py # Card directives |
| 29 | +├── dropdown.py # Dropdown directive |
| 30 | +├── grids.py # Grid directives |
| 31 | +├── tabs.py # Tab directives |
| 32 | +├── icons.py # Icon roles (Material, FontAwesome, Octicons) |
| 33 | +├── article_info.py # Article info directive |
| 34 | +└── compiled/ # Compiled static assets (CSS, JS) |
| 35 | +
|
| 36 | +style/ # SASS source files |
| 37 | +├── index.scss # Main SCSS entry point |
| 38 | +├── _variables.scss # SCSS variables |
| 39 | +├── _grids.scss # Grid styles |
| 40 | +├── _cards.scss # Card styles |
| 41 | +├── _tabs.scss # Tab styles |
| 42 | +├── _dropdown.scss # Dropdown styles |
| 43 | +└── ... # Other component styles |
| 44 | +
|
| 45 | +tests/ # Test suite |
| 46 | +├── conftest.py # Pytest fixtures |
| 47 | +├── test_snippets.py # Snippet-based tests |
| 48 | +├── test_misc.py # Miscellaneous tests |
| 49 | +├── test_snippets/ # Test fixture files for snippets |
| 50 | +└── test_misc/ # Test fixture files for misc tests |
| 51 | +
|
| 52 | +docs/ # Documentation source (MyST Markdown) |
| 53 | +├── conf.py # Sphinx configuration |
| 54 | +├── index.md # Documentation index |
| 55 | +├── get_started.md # Getting started guide |
| 56 | +├── grids.md # Grid documentation |
| 57 | +├── cards.md # Card documentation |
| 58 | +├── tabs.md # Tab documentation |
| 59 | +├── dropdowns.md # Dropdown documentation |
| 60 | +├── badges_buttons.md # Badge and button documentation |
| 61 | +└── snippets/ # Code snippets for docs (myst/, rst/) |
| 62 | +``` |
| 63 | + |
| 64 | +## Development Commands |
| 65 | + |
| 66 | +All commands should be run via [`tox`](https://tox.wiki) for consistency. The project uses `tox-uv` for faster environment creation. |
| 67 | + |
| 68 | +### Testing |
| 69 | + |
| 70 | +```bash |
| 71 | +# Run all tests (default Python version) |
| 72 | +tox |
| 73 | + |
| 74 | +# Run tests with a specific Python version |
| 75 | +tox -e py311 |
| 76 | +tox -e py312 |
| 77 | + |
| 78 | +# Run a specific test file |
| 79 | +tox -- tests/test_snippets.py |
| 80 | + |
| 81 | +# Run a specific test function |
| 82 | +tox -- tests/test_snippets.py::test_function_name |
| 83 | + |
| 84 | +# Run tests without myst-parser dependency |
| 85 | +tox -e py311-no-myst |
| 86 | + |
| 87 | +# Run with coverage |
| 88 | +tox -- --cov=sphinx_design |
| 89 | + |
| 90 | +# Update regression test fixtures |
| 91 | +tox -- --force-regen |
| 92 | +``` |
| 93 | + |
| 94 | +### Documentation |
| 95 | + |
| 96 | +```bash |
| 97 | +# Build docs with different themes |
| 98 | +tox -e docs-alabaster |
| 99 | +tox -e docs-rtd |
| 100 | +tox -e docs-pydata |
| 101 | +tox -e docs-sbt |
| 102 | +tox -e docs-furo |
| 103 | +tox -e docs-im |
| 104 | + |
| 105 | +# Clean build (set CLEAN env var) |
| 106 | +CLEAN=1 tox -e docs-furo |
| 107 | + |
| 108 | +# Build with a different builder (e.g., linkcheck) |
| 109 | +BUILDER=linkcheck tox -e docs-furo |
| 110 | +``` |
| 111 | + |
| 112 | +### Code Quality |
| 113 | + |
| 114 | +```bash |
| 115 | +# Type checking with mypy |
| 116 | +tox -e mypy |
| 117 | + |
| 118 | +# Linting with ruff (auto-fix enabled) |
| 119 | +tox -e ruff-check -- --fix |
| 120 | + |
| 121 | +# Formatting with ruff |
| 122 | +tox -e ruff-fmt |
| 123 | + |
| 124 | +# Run pre-commit hooks on all files |
| 125 | +pre-commit run --all-files |
| 126 | + |
| 127 | +# Compile SASS to CSS |
| 128 | +npm run css |
| 129 | +# or via pre-commit |
| 130 | +pre-commit run --all css |
| 131 | +``` |
| 132 | + |
| 133 | +## Code Style Guidelines |
| 134 | + |
| 135 | +- **Formatter/Linter**: Ruff (configured in `pyproject.toml`) |
| 136 | +- **Type Checking**: Mypy (configured in `pyproject.toml`) |
| 137 | +- **Pre-commit**: Use pre-commit hooks for consistent code style |
| 138 | + |
| 139 | +### Best Practices |
| 140 | + |
| 141 | +- **Type annotations**: Use complete type annotations for all function signatures. |
| 142 | +- **Docstrings**: Use Sphinx-style docstrings (`:param:`, `:return:`, `:raises:`). |
| 143 | +- **Directive classes**: Extend `SdDirective` (from `shared.py`) for new directives. |
| 144 | +- **Warning messages**: Use `WARNING_TYPE = "design"` for consistent warning categorization. |
| 145 | +- **Testing**: Write tests for all new functionality. Use `pytest-regressions` for output comparison. |
| 146 | + |
| 147 | +### Docstring Example |
| 148 | + |
| 149 | +```python |
| 150 | +def create_component( |
| 151 | + name: str, |
| 152 | + rawtext: str, |
| 153 | + *, |
| 154 | + classes: Sequence[str] = (), |
| 155 | +) -> nodes.container: |
| 156 | + """Create a component container node. |
| 157 | +
|
| 158 | + :param name: The component name. |
| 159 | + :param rawtext: The raw text content. |
| 160 | + :param classes: Additional CSS classes to apply. |
| 161 | + :return: A container node with the component. |
| 162 | + """ |
| 163 | + ... |
| 164 | +``` |
| 165 | + |
| 166 | +## Testing Guidelines |
| 167 | + |
| 168 | +### Test Structure |
| 169 | + |
| 170 | +- Tests use `pytest` with fixtures from `conftest.py` |
| 171 | +- Regression testing uses `pytest-regressions` for output comparison |
| 172 | +- The `sphinx_builder` fixture creates temporary Sphinx projects for testing |
| 173 | + |
| 174 | +### Writing Tests |
| 175 | + |
| 176 | +1. Use the `sphinx_builder` fixture to create test Sphinx applications |
| 177 | +2. Add test content as `.txt` files in `tests/test_snippets/` or `tests/test_misc/` |
| 178 | +3. Use `file_regression` or `data_regression` fixtures for comparing output |
| 179 | + |
| 180 | +### Example Test Pattern |
| 181 | + |
| 182 | +`````python |
| 183 | +def test_grid_basic(sphinx_builder, file_regression): |
| 184 | + builder = sphinx_builder() |
| 185 | + builder.src_path.joinpath("index.md").write_text( |
| 186 | + """ |
| 187 | +# Test |
| 188 | +
|
| 189 | +````{grid} 2 |
| 190 | +:gutter: 1 |
| 191 | +
|
| 192 | +```{grid-item} |
| 193 | +Item 1 |
| 194 | +``` |
| 195 | +
|
| 196 | +```{grid-item} |
| 197 | +Item 2 |
| 198 | +``` |
| 199 | +```` |
| 200 | +""", |
| 201 | + encoding="utf8", |
| 202 | + ) |
| 203 | + builder.build() |
| 204 | + doctree = builder.get_doctree("index") |
| 205 | + file_regression.check(doctree.pformat(), extension=".xml") |
| 206 | +````` |
| 207 | + |
| 208 | +## Pull Request Requirements |
| 209 | + |
| 210 | +When submitting changes: |
| 211 | + |
| 212 | +1. **Description**: Include a meaningful description or link explaining the change |
| 213 | +2. **Tests**: Include test cases for new functionality or bug fixes |
| 214 | +3. **Documentation**: Update docs if behavior changes or new features are added |
| 215 | +4. **Changelog**: Update `CHANGELOG.md` under the appropriate section |
| 216 | +5. **Code Quality**: Ensure `pre-commit run --all-files` passes |
| 217 | + |
| 218 | +## Architecture Overview |
| 219 | + |
| 220 | +### Extension Setup |
| 221 | + |
| 222 | +The extension follows a modular architecture where each component type has its own module: |
| 223 | + |
| 224 | +``` |
| 225 | +setup() in __init__.py |
| 226 | + └── setup_extension() in extension.py |
| 227 | + ├── setup_badges_and_buttons() |
| 228 | + ├── setup_cards() |
| 229 | + ├── setup_grids() |
| 230 | + ├── setup_dropdown() |
| 231 | + ├── setup_icons() |
| 232 | + ├── setup_tabs() |
| 233 | + └── setup_article_info() |
| 234 | +``` |
| 235 | + |
| 236 | +### Key Components |
| 237 | + |
| 238 | +#### Base Classes (`sphinx_design/shared.py`) |
| 239 | + |
| 240 | +- `SdDirective`: Base class for sphinx-design directives (extends `SphinxDirective`) |
| 241 | +- `create_component()`: Factory function for creating component nodes |
| 242 | +- `WARNING_TYPE`: Constant for warning categorization |
| 243 | + |
| 244 | +#### Directives |
| 245 | + |
| 246 | +Each component type has its own module with directives: |
| 247 | + |
| 248 | +- **Grids** (`grids.py`): `grid`, `grid-item`, `grid-item-card` directives |
| 249 | +- **Cards** (`cards.py`): `card`, `card-header`, `card-footer`, `card-carousel` directives |
| 250 | +- **Tabs** (`tabs.py`): `tab-set`, `tab-item` directives |
| 251 | +- **Dropdowns** (`dropdown.py`): `dropdown` directive |
| 252 | +- **Badges/Buttons** (`badges_buttons.py`): `button-link`, `button-ref` directives and `bdg-*` roles |
| 253 | +- **Icons** (`icons.py`): Icon roles for Material, FontAwesome, and Octicons |
| 254 | + |
| 255 | +#### Static Assets |
| 256 | + |
| 257 | +Compiled CSS and JS are stored in `sphinx_design/compiled/`: |
| 258 | + |
| 259 | +- CSS is compiled from SASS sources in `style/` |
| 260 | +- JavaScript for tab functionality |
| 261 | + |
| 262 | +### Styling |
| 263 | + |
| 264 | +The extension uses SASS for styling: |
| 265 | + |
| 266 | +1. SASS source files are in `style/` |
| 267 | +2. Compiled using `npm run css` (requires Node.js) |
| 268 | +3. Output goes to `sphinx_design/compiled/style.min.css` |
| 269 | +4. CSS is automatically copied to build output during Sphinx builds |
| 270 | + |
| 271 | +## Key Files |
| 272 | + |
| 273 | +- `pyproject.toml` - Project configuration, dependencies, and tool settings |
| 274 | +- `sphinx_design/__init__.py` - Package entry point with `setup()` for Sphinx |
| 275 | +- `sphinx_design/extension.py` - Main extension setup, CSS/JS handling |
| 276 | +- `sphinx_design/shared.py` - Base classes and shared utilities |
| 277 | +- `sphinx_design/grids.py` - Grid layout directives |
| 278 | +- `sphinx_design/cards.py` - Card component directives |
| 279 | +- `sphinx_design/tabs.py` - Tab component directives |
| 280 | + |
| 281 | +## Debugging |
| 282 | + |
| 283 | +- Build docs with `-v` flag for verbose output |
| 284 | +- Check `docs/_build/html/<theme>/` for build outputs |
| 285 | +- Use `tox -- -v --tb=long` for verbose test output with full tracebacks |
| 286 | +- Inspect generated HTML to debug styling issues |
| 287 | + |
| 288 | +## Common Patterns |
| 289 | + |
| 290 | +### Adding a New Component |
| 291 | + |
| 292 | +1. Create a new module in `sphinx_design/` (e.g., `my_component.py`) |
| 293 | +2. Define directive class(es) extending `SdDirective` |
| 294 | +3. Create a `setup_my_component(app: Sphinx)` function |
| 295 | +4. Call the setup function from `setup_extension()` in `extension.py` |
| 296 | +5. Add SASS styles in `style/_my_component.scss` |
| 297 | +6. Import the SASS file in `style/index.scss` |
| 298 | +7. Document in `docs/` |
| 299 | +8. Add tests in `tests/` |
| 300 | + |
| 301 | +### Adding a New Directive Option |
| 302 | + |
| 303 | +1. Add the option to the directive's `option_spec` dictionary |
| 304 | +2. Handle the option in the directive's `run()` method |
| 305 | +3. Add appropriate CSS classes or attributes to the output node |
| 306 | +4. Document the new option |
| 307 | +5. Add tests for the new option |
| 308 | + |
| 309 | +### Working with SASS |
| 310 | + |
| 311 | +1. Edit SASS files in `style/` |
| 312 | +2. Run `npm run css` to compile (or `pre-commit run --all css`) |
| 313 | +3. Compiled output goes to `sphinx_design/compiled/style.min.css` |
| 314 | +4. Test with different themes to ensure compatibility |
| 315 | + |
| 316 | +## Reference Documentation |
| 317 | + |
| 318 | +- [Docutils Repository](https://github.com/live-clones/docutils) |
| 319 | +- [Docutils Documentation](https://docutils.sourceforge.io/) |
| 320 | +- [Docutils Nodes](https://docutils.sourceforge.io/docs/ref/doctree.html) |
| 321 | +- [Docutils release log](https://docutils.sourceforge.io/RELEASE-NOTES.html) |
| 322 | +- [Sphinx Repository](https://github.com/sphinx-doc/sphinx) |
| 323 | +- [Sphinx Extension Development](https://www.sphinx-doc.org/en/master/extdev/index.html) |
| 324 | +- [Bootstrap Documentation](https://getbootstrap.com/docs/5.0/) |
| 325 | +- [SASS Documentation](https://sass-lang.com/documentation) |
0 commit comments