doxtr-doto 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. doxtr_doto-0.1.0/.gitignore +77 -0
  2. doxtr_doto-0.1.0/LICENSE +21 -0
  3. doxtr_doto-0.1.0/PKG-INFO +603 -0
  4. doxtr_doto-0.1.0/README.md +546 -0
  5. doxtr_doto-0.1.0/pyproject.toml +99 -0
  6. doxtr_doto-0.1.0/src/doxtr_doto/__init__.py +567 -0
  7. doxtr_doto-0.1.0/src/doxtr_doto/builders/__init__.py +22 -0
  8. doxtr_doto-0.1.0/src/doxtr_doto/builders/archive_doc.py +222 -0
  9. doxtr_doto-0.1.0/src/doxtr_doto/charts.py +1344 -0
  10. doxtr_doto-0.1.0/src/doxtr_doto/cli/__init__.py +5 -0
  11. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/__init__.py +49 -0
  12. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/add.py +630 -0
  13. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/archive.py +111 -0
  14. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/completion.py +176 -0
  15. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/config.py +116 -0
  16. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/delete.py +357 -0
  17. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/deps.py +336 -0
  18. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/done.py +64 -0
  19. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/export.py +232 -0
  20. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/git.py +234 -0
  21. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/init.py +214 -0
  22. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/list.py +360 -0
  23. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/next.py +306 -0
  24. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/reopen.py +85 -0
  25. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/resolve.py +189 -0
  26. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/search.py +170 -0
  27. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/series.py +404 -0
  28. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/show.py +54 -0
  29. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/stats.py +238 -0
  30. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/tree.py +341 -0
  31. doxtr_doto-0.1.0/src/doxtr_doto/cli/commands/update.py +543 -0
  32. doxtr_doto-0.1.0/src/doxtr_doto/cli/completion.py +307 -0
  33. doxtr_doto-0.1.0/src/doxtr_doto/cli/config.py +447 -0
  34. doxtr_doto-0.1.0/src/doxtr_doto/cli/json_store.py +23 -0
  35. doxtr_doto-0.1.0/src/doxtr_doto/cli/main.py +146 -0
  36. doxtr_doto-0.1.0/src/doxtr_doto/cli/output.py +464 -0
  37. doxtr_doto-0.1.0/src/doxtr_doto/cli/recurrence.py +374 -0
  38. doxtr_doto-0.1.0/src/doxtr_doto/cli/validators.py +110 -0
  39. doxtr_doto-0.1.0/src/doxtr_doto/collectors/__init__.py +708 -0
  40. doxtr_doto-0.1.0/src/doxtr_doto/config.py +195 -0
  41. doxtr_doto-0.1.0/src/doxtr_doto/constants.py +103 -0
  42. doxtr_doto-0.1.0/src/doxtr_doto/date_utils.py +384 -0
  43. doxtr_doto-0.1.0/src/doxtr_doto/directives/__init__.py +14 -0
  44. doxtr_doto-0.1.0/src/doxtr_doto/directives/doto.py +351 -0
  45. doxtr_doto-0.1.0/src/doxtr_doto/directives/doto_list.py +427 -0
  46. doxtr_doto-0.1.0/src/doxtr_doto/directives/doto_summary.py +250 -0
  47. doxtr_doto-0.1.0/src/doxtr_doto/domain.py +312 -0
  48. doxtr_doto-0.1.0/src/doxtr_doto/enums.py +69 -0
  49. doxtr_doto-0.1.0/src/doxtr_doto/exceptions.py +96 -0
  50. doxtr_doto-0.1.0/src/doxtr_doto/fields.py +183 -0
  51. doxtr_doto-0.1.0/src/doxtr_doto/hooks.py +278 -0
  52. doxtr_doto-0.1.0/src/doxtr_doto/integration/__init__.py +30 -0
  53. doxtr_doto-0.1.0/src/doxtr_doto/integration/doxtr.py +402 -0
  54. doxtr_doto-0.1.0/src/doxtr_doto/nodes.py +1429 -0
  55. doxtr_doto-0.1.0/src/doxtr_doto/query.py +174 -0
  56. doxtr_doto-0.1.0/src/doxtr_doto/regex_utils.py +203 -0
  57. doxtr_doto-0.1.0/src/doxtr_doto/roles/__init__.py +8 -0
  58. doxtr_doto-0.1.0/src/doxtr_doto/roles/doto_ref.py +119 -0
  59. doxtr_doto-0.1.0/src/doxtr_doto/sync/__init__.py +705 -0
  60. doxtr_doto-0.1.0/src/doxtr_doto/sync/conflict.py +116 -0
  61. doxtr_doto-0.1.0/src/doxtr_doto/sync/hash.py +67 -0
  62. doxtr_doto-0.1.0/src/doxtr_doto/sync/json_store.py +967 -0
  63. doxtr_doto-0.1.0/src/doxtr_doto/sync/merge.py +229 -0
  64. doxtr_doto-0.1.0/src/doxtr_doto/sync/rst_writer.py +724 -0
  65. doxtr_doto-0.1.0/src/doxtr_doto/template_loader.py +461 -0
  66. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/critical.yaml +9 -0
  67. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/default.yaml +21 -0
  68. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/high.yaml +8 -0
  69. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/low.yaml +8 -0
  70. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/medium.yaml +8 -0
  71. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/styles/minimal.yaml +16 -0
  72. doxtr_doto-0.1.0/src/doxtr_doto/templates/doxtr/task.tex.jinja +14 -0
  73. doxtr_doto-0.1.0/src/doxtr_doto/templates/html/doto-list-cards.html +36 -0
  74. doxtr_doto-0.1.0/src/doxtr_doto/templates/html/doto-list-simple.html +24 -0
  75. doxtr_doto-0.1.0/src/doxtr_doto/templates/html/doto-list-table.html +59 -0
  76. doxtr_doto-0.1.0/src/doxtr_doto/templates/html/doto.html +46 -0
  77. doxtr_doto-0.1.0/src/doxtr_doto/themes/epub/doto-minimal.css +62 -0
  78. doxtr_doto-0.1.0/src/doxtr_doto/themes/epub/doto.css +246 -0
  79. doxtr_doto-0.1.0/src/doxtr_doto/themes/html/doto-minimal.css +112 -0
  80. doxtr_doto-0.1.0/src/doxtr_doto/themes/html/doto.css +716 -0
  81. doxtr_doto-0.1.0/src/doxtr_doto/themes/latex/doto-minimal.sty +51 -0
  82. doxtr_doto-0.1.0/src/doxtr_doto/themes/latex/doto.sty +351 -0
  83. doxtr_doto-0.1.0/src/doxtr_doto/transforms/__init__.py +11 -0
  84. doxtr_doto-0.1.0/src/doxtr_doto/transforms/archive.py +157 -0
  85. doxtr_doto-0.1.0/src/doxtr_doto/transforms/toc_inject.py +50 -0
  86. doxtr_doto-0.1.0/src/doxtr_doto/types.py +132 -0
  87. doxtr_doto-0.1.0/src/doxtr_doto/utils.py +366 -0
  88. doxtr_doto-0.1.0/tests/cli/__init__.py +1 -0
  89. doxtr_doto-0.1.0/tests/cli/test_add_helpers.py +401 -0
  90. doxtr_doto-0.1.0/tests/cli/test_archive.py +213 -0
  91. doxtr_doto-0.1.0/tests/cli/test_commands.py +2748 -0
  92. doxtr_doto-0.1.0/tests/cli/test_delete.py +405 -0
  93. doxtr_doto-0.1.0/tests/cli/test_git.py +354 -0
  94. doxtr_doto-0.1.0/tests/cli/test_init.py +196 -0
  95. doxtr_doto-0.1.0/tests/cli/test_next.py +462 -0
  96. doxtr_doto-0.1.0/tests/cli/test_output.py +194 -0
  97. doxtr_doto-0.1.0/tests/cli/test_recurrence.py +552 -0
  98. doxtr_doto-0.1.0/tests/cli/test_recurring_limits.py +221 -0
  99. doxtr_doto-0.1.0/tests/cli/test_reopen.py +207 -0
  100. doxtr_doto-0.1.0/tests/cli/test_resolve.py +269 -0
  101. doxtr_doto-0.1.0/tests/cli/test_series.py +516 -0
  102. doxtr_doto-0.1.0/tests/cli/test_standalone_mode.py +292 -0
  103. doxtr_doto-0.1.0/tests/cli/test_stats.py +345 -0
  104. doxtr_doto-0.1.0/tests/conftest.py +222 -0
  105. doxtr_doto-0.1.0/tests/sync/__init__.py +1 -0
  106. doxtr_doto-0.1.0/tests/sync/test_conflict_detection.py +418 -0
  107. doxtr_doto-0.1.0/tests/sync/test_conflict_formatting.py +347 -0
  108. doxtr_doto-0.1.0/tests/sync/test_json_store.py +154 -0
  109. doxtr_doto-0.1.0/tests/sync/test_json_store_refactor.py +478 -0
  110. doxtr_doto-0.1.0/tests/sync/test_reopen.py +302 -0
  111. doxtr_doto-0.1.0/tests/sync/test_rst_batching.py +442 -0
  112. doxtr_doto-0.1.0/tests/sync/test_rst_insertion.py +209 -0
  113. doxtr_doto-0.1.0/tests/sync/test_rst_removal.py +399 -0
  114. doxtr_doto-0.1.0/tests/sync/test_rst_writer_edge_cases.py +297 -0
  115. doxtr_doto-0.1.0/tests/sync/test_sync_error_handling.py +297 -0
  116. doxtr_doto-0.1.0/tests/sync/test_three_way_merge.py +184 -0
  117. doxtr_doto-0.1.0/tests/test_archive_doc.py +358 -0
  118. doxtr_doto-0.1.0/tests/test_auto_archive.py +387 -0
  119. doxtr_doto-0.1.0/tests/test_charts.py +863 -0
  120. doxtr_doto-0.1.0/tests/test_config.py +469 -0
  121. doxtr_doto-0.1.0/tests/test_config_features.py +340 -0
  122. doxtr_doto-0.1.0/tests/test_date_utils.py +499 -0
  123. doxtr_doto-0.1.0/tests/test_directive_doto.py +183 -0
  124. doxtr_doto-0.1.0/tests/test_directive_doto_list.py +270 -0
  125. doxtr_doto-0.1.0/tests/test_directive_doto_summary.py +348 -0
  126. doxtr_doto-0.1.0/tests/test_doto_task_methods.py +434 -0
  127. doxtr_doto-0.1.0/tests/test_doxtr_integration.py +299 -0
  128. doxtr_doto-0.1.0/tests/test_enums.py +270 -0
  129. doxtr_doto-0.1.0/tests/test_export_json.py +274 -0
  130. doxtr_doto-0.1.0/tests/test_fields.py +422 -0
  131. doxtr_doto-0.1.0/tests/test_filter_cache.py +471 -0
  132. doxtr_doto-0.1.0/tests/test_graceful_degradation.py +589 -0
  133. doxtr_doto-0.1.0/tests/test_hooks.py +477 -0
  134. doxtr_doto-0.1.0/tests/test_integration_doxtr.py +196 -0
  135. doxtr_doto-0.1.0/tests/test_integration_doxtr_pure.py +134 -0
  136. doxtr_doto-0.1.0/tests/test_output_epub.py +254 -0
  137. doxtr_doto-0.1.0/tests/test_output_html.py +675 -0
  138. doxtr_doto-0.1.0/tests/test_output_latex.py +405 -0
  139. doxtr_doto-0.1.0/tests/test_parallel_build.py +409 -0
  140. doxtr_doto-0.1.0/tests/test_progress.py +537 -0
  141. doxtr_doto-0.1.0/tests/test_query.py +509 -0
  142. doxtr_doto-0.1.0/tests/test_regex_utils.py +297 -0
  143. doxtr_doto-0.1.0/tests/test_role_doto.py +174 -0
  144. doxtr_doto-0.1.0/tests/test_security.py +290 -0
  145. doxtr_doto-0.1.0/tests/test_template_loader.py +569 -0
  146. doxtr_doto-0.1.0/tests/test_theme_selection.py +93 -0
  147. doxtr_doto-0.1.0/tests/test_validation_edge_cases.py +367 -0
@@ -0,0 +1,77 @@
1
+ .DS_Store
2
+
3
+ # Python
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ *.so
8
+ .Python
9
+ build/
10
+ develop-eggs/
11
+ dist/
12
+ downloads/
13
+ eggs/
14
+ .eggs/
15
+ lib/
16
+ lib64/
17
+ parts/
18
+ sdist/
19
+ var/
20
+ wheels/
21
+ *.egg-info/
22
+ .installed.cfg
23
+ *.egg
24
+
25
+ # Testing / coverage
26
+ .coverage
27
+ coverage.xml
28
+ htmlcov/
29
+ .pytest_cache/
30
+
31
+ # Virtual environments
32
+ venv/
33
+ .venv/
34
+ env/
35
+ .env/
36
+
37
+ # Sphinx build artifacts
38
+ *.doctrees
39
+ _source/.doctrees
40
+
41
+ # Generated files
42
+ *.tex
43
+ *.pdf
44
+ *.log
45
+ *.aux
46
+ *.toc
47
+ *.lof
48
+ *.lot
49
+ *.out
50
+ *.ind
51
+ *.idx
52
+ *.ilg
53
+ *.fls
54
+ *.fdb_latexmk
55
+ *.synctex.gz
56
+
57
+ # Test harness build artifacts
58
+ test_harness/build/
59
+ test_harness/source/conf.py
60
+ test_harness/source/_generated_toctree.rst
61
+
62
+ # IDE
63
+ .vscode/
64
+ .idea/
65
+ *.swp
66
+ *.swo
67
+ *~
68
+
69
+ # OS
70
+ .DS_Store
71
+ Thumbs.db
72
+
73
+ # Test assets (generated placeholders)
74
+ test_harness/source/_static/wizard-of-docs*.png
75
+
76
+ # DocDash Docker container
77
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Doxtr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,603 @@
1
+ Metadata-Version: 2.5
2
+ Name: doxtr-doto
3
+ Version: 0.1.0
4
+ Summary: Documentation task management for Sphinx
5
+ Project-URL: Homepage, https://github.com/doxtr/doxtr-doto
6
+ Project-URL: Documentation, https://doxtr-doto.readthedocs.io
7
+ Project-URL: Repository, https://github.com/doxtr/doxtr-doto
8
+ Project-URL: Issues, https://github.com/doxtr/doxtr-doto/issues
9
+ Author: doto contributors
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: documentation,project-management,sphinx,tasks,todo
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Environment :: Plugins
16
+ Classifier: Framework :: Sphinx :: Extension
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Documentation :: Sphinx
25
+ Classifier: Topic :: Software Development :: Documentation
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: sphinx>=7.0
28
+ Provides-Extra: all
29
+ Requires-Dist: click>=8.0; extra == 'all'
30
+ Requires-Dist: jinja2>=3.0; extra == 'all'
31
+ Requires-Dist: kaleido; extra == 'all'
32
+ Requires-Dist: mypy>=1.0; extra == 'all'
33
+ Requires-Dist: plotly>=5; extra == 'all'
34
+ Requires-Dist: pytest-cov>=4.0; extra == 'all'
35
+ Requires-Dist: pytest>=7.0; extra == 'all'
36
+ Requires-Dist: rich>=13.0; extra == 'all'
37
+ Requires-Dist: ruff>=0.1.0; extra == 'all'
38
+ Requires-Dist: tomli-w>=1.0; extra == 'all'
39
+ Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'all'
40
+ Provides-Extra: charts
41
+ Requires-Dist: kaleido; extra == 'charts'
42
+ Requires-Dist: plotly>=5; extra == 'charts'
43
+ Provides-Extra: cli
44
+ Requires-Dist: click>=8.0; extra == 'cli'
45
+ Requires-Dist: rich>=13.0; extra == 'cli'
46
+ Requires-Dist: tomli-w>=1.0; extra == 'cli'
47
+ Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'cli'
48
+ Provides-Extra: dev
49
+ Requires-Dist: jinja2>=3.0; extra == 'dev'
50
+ Requires-Dist: mypy>=1.0; extra == 'dev'
51
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
52
+ Requires-Dist: pytest>=7.0; extra == 'dev'
53
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
54
+ Provides-Extra: templates
55
+ Requires-Dist: jinja2>=3.0; extra == 'templates'
56
+ Description-Content-Type: text/markdown
57
+
58
+ # doxtr-doto - Documentation Task Management for Sphinx
59
+
60
+ **doxtr-doto** (documentation task open) is a Sphinx extension for managing documentation tasks with structured metadata, bidirectional sync with JSON storage, and a companion CLI tool.
61
+
62
+ ## Features
63
+
64
+ - **Structured task directives** - Define tasks with priorities, assignees, due dates, tags, and dependencies
65
+ - **Task lists and summaries** - Display filtered, sorted task lists and statistics
66
+ - **Styled PDF task boxes** - Each task renders as a `tcolorbox` with a high-contrast title bar and readable body (no more white-on-white boxes)
67
+ - **Stacked Font Awesome metadata icons** - PDF task boxes stack a semantic FA icon above each metadata label (calendar for due, user for assignee, flag for priority, etc.), degrading gracefully when Font Awesome is unavailable
68
+ - **Task-list icon modes** - Render list cells as Font Awesome icons, icon+text, or text, with clickable task IDs/titles
69
+ - **Cross-references** - Link to tasks with the `:doto:` role; PDF cross-references are clickable hyperlinks that jump to the task box
70
+ - **Bidirectional sync** - Keep RST files and JSON storage in sync with 3-way merge
71
+ - **Auto-archiving** - Automatically archive completed tasks
72
+ - **CLI tool** - Manage tasks from the command line
73
+ - **Theming** - Customizable HTML and LaTeX output
74
+ - **Charts** - Task summaries with built-in SVG charts, or richer [plotly](https://plotly.com/python/) charts (pie, bar, stacked-bar, progress, burndown)
75
+ - **Doxtr integration** - Optional integration with doxtr-pdf-theme-core: semantic-palette-derived task colors and automatic landscape rotation for wide task tables
76
+
77
+ ## Installation
78
+
79
+ ```bash
80
+ pip install doxtr-doto
81
+
82
+ # With CLI support
83
+ pip install doxtr-doto[cli]
84
+
85
+ # With plotly charts (pie/bar/stacked-bar/progress/burndown)
86
+ pip install doxtr-doto[charts]
87
+
88
+ # Full installation
89
+ pip install doxtr-doto[all]
90
+ ```
91
+
92
+ The `charts` extra installs `plotly>=5` and `kaleido`. Static image export
93
+ (used for HTML `<img>` charts and PDF `\includegraphics`) additionally requires
94
+ a Chrome/Chromium install for kaleido; when plotly, kaleido, or Chrome are
95
+ unavailable, `doto-summary` automatically falls back to built-in,
96
+ dependency-free charts so the build never breaks:
97
+
98
+ - **HTML** falls back to inline SVG charts.
99
+ - **PDF/LaTeX** falls back to native TikZ charts (`\dotochart*` macros in
100
+ `doto.sty`), so the PDF always renders a real visual chart — no browser or
101
+ kaleido required. A child theme can restyle these by redefining the
102
+ `\dotochart*` macros / `dotochart` environment.
103
+
104
+ ## Quick Start
105
+
106
+ 1. Add `doxtr_doto` to your Sphinx extensions in `conf.py`:
107
+
108
+ ```python
109
+ extensions = [
110
+ 'doxtr_doto',
111
+ ]
112
+ ```
113
+
114
+ 2. Create a task in your documentation:
115
+
116
+ ```rst
117
+ .. doto:: Implement user authentication
118
+ :id: TASK-001
119
+ :assignee: alice
120
+ :priority: high
121
+ :status: open
122
+ :due: 2026-08-15
123
+ :tags: security, backend
124
+
125
+ Detailed description of the task goes here.
126
+ ```
127
+
128
+ 3. Display a task list:
129
+
130
+ ```rst
131
+ .. doto-list::
132
+ :status: open, in-progress
133
+ :sort: priority
134
+ :format: table
135
+ ```
136
+
137
+ 4. Reference tasks inline:
138
+
139
+ ```rst
140
+ This relates to :doto:`TASK-001`.
141
+ ```
142
+
143
+ ## Directive Reference
144
+
145
+ ### `.. doto::` - Task Definition
146
+
147
+ Creates a task with structured metadata.
148
+
149
+ **Options:**
150
+
151
+ | Option | Type | Default | Description |
152
+ |--------|------|---------|-------------|
153
+ | `:id:` | string | Auto-generated | Unique task identifier |
154
+ | `:assignee:` | string | None | Person responsible |
155
+ | `:priority:` | enum | `medium` | `low`, `medium`, `high`, `critical` |
156
+ | `:status:` | enum | `open` | `open`, `in-progress`, `blocked`, `done` |
157
+ | `:due:` | date | None | Due date (YYYY-MM-DD) |
158
+ | `:tags:` | list | None | Comma-separated categories |
159
+ | `:depends-on:` | list | None | Comma-separated task IDs |
160
+
161
+ ### `.. doto-list::` - Task List
162
+
163
+ Displays a filtered list of tasks.
164
+
165
+ **Filter Options:** `:assignee:`, `:priority:`, `:status:`, `:tags:`, `:due-before:`, `:due-after:`, `:exclude-status:`
166
+
167
+ **Display Options:** `:sort:`, `:order:`, `:limit:`, `:format:` (table/list/cards), `:show-archived:`, `:columns:`, `:icon-mode:` (icon/icon-text/text)
168
+
169
+ Task IDs and titles in every list format are clickable links to the task box.
170
+ The `:icon-mode:` option overrides the global `doto_list_icon_mode` config for
171
+ a single directive.
172
+
173
+ ```rst
174
+ .. doto-list::
175
+ :format: table
176
+ :columns: id, title, status, priority, assignee
177
+ :icon-mode: icon-text
178
+ ```
179
+
180
+ ### `.. doto-summary::` - Task Statistics
181
+
182
+ Displays task counts grouped by status/priority, optionally with a chart.
183
+
184
+ **Options:** `:group-by:`, `:assignee:`, `:show-chart:`, `:chart-type:`
185
+
186
+ `:chart-type:` accepts `bar`, `pie`, `stacked-bar`, `progress`, and `burndown`.
187
+ The engine is selected by `doto_chart_engine` (`svg` default, or `plotly`).
188
+
189
+ ```rst
190
+ .. doto-summary::
191
+ :group-by: status
192
+ :show-chart: true
193
+ :chart-type: pie
194
+ ```
195
+
196
+ ### `:doto:` Role
197
+
198
+ Cross-reference to a task: `:doto:`TASK-001`` or `:doto:`TASK-001 <custom text>``
199
+
200
+ ## Configuration
201
+
202
+ ```python
203
+ # conf.py
204
+
205
+ # Core settings
206
+ doto_enabled = True
207
+ doto_include_done = True
208
+
209
+ # JSON store
210
+ doto_json_file = ".doto/tasks.json"
211
+ doto_auto_create_json = True
212
+
213
+ # Auto-archive
214
+ doto_auto_archive = False
215
+ doto_archive_doc = "_doto_archive"
216
+ doto_archive_after_days = 0
217
+
218
+ # Sync settings
219
+ doto_sync_on_build = True
220
+ doto_conflict_action = "error" # or "warn", "prefer-rst", "prefer-json"
221
+
222
+ # Defaults
223
+ doto_default_priority = "medium"
224
+ doto_default_status = "open"
225
+
226
+ # Display
227
+ doto_list_columns = ["id", "priority", "status", "assignee", "due", "title"]
228
+ # Task-list cell rendering: "icon" | "icon-text" | "text" (default "icon-text").
229
+ # "icon" = a Font Awesome icon where one fits the field/value (else text)
230
+ # "icon-text" = icon + text
231
+ # "text" = text only
232
+ # Overridable per directive with :icon-mode:.
233
+ doto_list_icon_mode = "icon-text"
234
+
235
+ # Charts
236
+ # Chart engine for doto-summary: "svg" (default) or "plotly".
237
+ # "svg" = built-in inline-SVG charts, no extra dependencies
238
+ # "plotly" = renders static images via plotly + kaleido; falls back
239
+ # automatically when plotly/kaleido/Chrome are unavailable
240
+ # (inline SVG for HTML output, native TikZ charts for PDF/LaTeX)
241
+ # Requires the [charts] extra when set to "plotly".
242
+ doto_chart_engine = "svg"
243
+
244
+ # Validation
245
+ doto_warn_overdue = True
246
+ doto_required_fields = [] # e.g., ["assignee"]
247
+ ```
248
+
249
+ ### CLI Configuration (`.doto.toml`)
250
+
251
+ ```toml
252
+ [doto]
253
+ json_file = ".doto/tasks.json"
254
+ id_prefix = "TASK"
255
+ default_priority = "medium"
256
+ default_status = "open"
257
+
258
+ # Customize default columns for 'doto list'
259
+ list_columns = ["id", "title", "status", "priority", "assignee"]
260
+
261
+ # Valid values
262
+ statuses = ["open", "in-progress", "blocked", "done"]
263
+ priorities = ["low", "medium", "high", "critical"]
264
+ ```
265
+
266
+ ### Environment Variables
267
+
268
+ | Variable | Description |
269
+ |----------|-------------|
270
+ | `DOTO_JSON_FILE` | Path to tasks.json |
271
+ | `DOTO_DEFAULT_PRIORITY` | Default priority for new tasks |
272
+ | `DOTO_DEFAULT_STATUS` | Default status for new tasks |
273
+ | `DOTO_LIST_COLUMNS` | Comma-separated list of columns for `doto list` |
274
+ | `DOTO_COLOR` | Color mode: `auto`, `always`, `never` |
275
+
276
+ ## Command-Line Interface
277
+
278
+ ```bash
279
+ # Initialize doto in a project
280
+ doto init
281
+
282
+ # Enable shell tab completion (bash, zsh, fish)
283
+ doto completion --install
284
+
285
+ # Show current configuration (JSON database path, mode, defaults)
286
+ doto config
287
+ doto config --format json
288
+
289
+ # Add a task
290
+ doto add "Fix authentication bug" --priority high --assignee alice
291
+
292
+ # List tasks
293
+ doto list --status open --format table
294
+ doto list --columns id,title,status,assignee # custom columns
295
+ doto list --with-deps # show dependency info
296
+ doto list --format tree # tree view with deps
297
+
298
+ # Update a task
299
+ doto update TASK-001 --status in-progress
300
+
301
+ # Bulk update tasks with filters
302
+ doto update --filter-status open --priority high --all
303
+ doto update --filter-priority low --status blocked --all
304
+ doto update --filter-assignee alice --status done --all
305
+ doto update --filter-tags bug --add-tags urgent --all
306
+ doto update --filter-overdue --add-tags needs-attention --all
307
+ doto update --filter-status open --priority high --all --dry-run
308
+ doto update --filter-status open --status in-progress --all --yes
309
+
310
+ # Mark as done
311
+ doto done TASK-001
312
+
313
+ # Archive tasks (hide from listings, can reopen later)
314
+ doto archive TASK-001
315
+ doto archive TASK-001 TASK-002 TASK-003
316
+ doto archive TASK-001 --json
317
+
318
+ # Delete tasks permanently (DESTRUCTIVE - cannot be undone)
319
+ doto delete TASK-001 # single task
320
+ doto delete TASK-001 TASK-002 # multiple tasks
321
+ doto delete TASK-001 --force # skip confirmation
322
+ doto delete TASK-001 --dry-run # preview without deleting
323
+ doto delete --filter-status done --all # delete all done tasks
324
+ doto delete --filter-archived --all # delete all archived tasks
325
+ doto delete TASK-001 --json # JSON output
326
+
327
+ # Show next task to work on
328
+ doto next # suggests based on priority, due dates, deps
329
+ doto next --assignee alice # filter by assignee
330
+ doto next --all # show top 5 ready tasks
331
+
332
+ # Show task dependency tree
333
+ doto tree # show all tasks as dependency forest
334
+ doto tree TASK-001 # show what TASK-001 depends on
335
+ doto tree TASK-001 -r # show what depends on TASK-001
336
+ doto tree --compact # minimal output (IDs only)
337
+
338
+ # Show task dependencies (tasks that must be completed first)
339
+ doto deps TASK-001 # direct dependencies
340
+ doto deps TASK-001 --recursive # include transitive dependencies
341
+ doto deps TASK-001 --pending-only # only incomplete dependencies
342
+ doto deps TASK-001 --format tree # tree visualization
343
+
344
+ # Search tasks
345
+ doto search "authentication"
346
+
347
+ # Show statistics
348
+ doto stats --by-status
349
+ ```
350
+
351
+ ### Recurring Tasks
352
+
353
+ Create recurring task series that automatically generate individual tasks:
354
+
355
+ ```bash
356
+ # Create a weekly recurring task
357
+ doto add "Weekly review" --repeat "every friday" --until 2025-12-31
358
+
359
+ # Bi-weekly sprint planning
360
+ doto add "Sprint planning" --repeat "every 2 weeks on monday" --until +6m
361
+
362
+ # Monthly report on the last Friday (with date in title)
363
+ doto add "Monthly report {date}" --repeat "every month on last friday" --until +1y
364
+
365
+ # Quarterly review on the first Monday
366
+ doto add "Quarterly review" --repeat "every 3 months on first monday" --until +2y
367
+ ```
368
+
369
+ **Supported recurrence patterns:**
370
+
371
+ | Pattern | Example |
372
+ |---------|--------|
373
+ | Daily | `every day`, `every 3 days` |
374
+ | Weekly | `every friday`, `every 2 weeks on monday` |
375
+ | Monthly (day) | `every month on 15`, `every 2 months on 1` |
376
+ | Monthly (weekday) | `every month on first monday`, `every month on last friday` |
377
+ | Quarterly | `every 3 months on first monday` |
378
+
379
+ **Title templating:** Use `{date}` in the title to include the occurrence date (e.g., "Weekly review {date}" → "Weekly review Aug 7").
380
+
381
+ ### Managing Series
382
+
383
+ ```bash
384
+ # List all series
385
+ doto series list
386
+
387
+ # Show series details and all tasks
388
+ doto series show SER-001
389
+
390
+ # Mark all past tasks in a series as done
391
+ doto series complete SER-001
392
+
393
+ # Complete tasks before a specific date
394
+ doto series complete SER-001 --before 2025-08-15
395
+
396
+ # Extend a series with a new end date
397
+ doto series extend SER-001 +3m
398
+
399
+ # Delete a series and all its tasks
400
+ doto series delete SER-001
401
+
402
+ # Delete series but keep the tasks
403
+ doto series delete SER-001 --keep-tasks
404
+ ```
405
+
406
+ When viewing a task that's part of a series, the series info is displayed:
407
+
408
+ ```bash
409
+ $ doto show DOTO-002
410
+ ╭─ DOTO-002 - Weekly standup Jul 31 ───────────────────────────────────────────╮
411
+ │ Priority: medium │
412
+ │ Status: open │
413
+ │ Due: 2026-07-31 │
414
+ │ Tags: recurring, meeting │
415
+ │ Series: SER-001 (every friday, until 2026-08-28) │
416
+ ╰──────────────────────────────────────────────────────────────────────────────╯
417
+ ```
418
+
419
+ ### CLI Commands Reference
420
+
421
+ | Command | Description |
422
+ |---------|-------------|
423
+ | `init` | Initialize doto in a project |
424
+ | `completion` | Set up shell tab completion (bash/zsh/fish) |
425
+ | `config` | Show current configuration (JSON path, mode, defaults) |
426
+ | `add` | Add a new task (supports `--repeat` for recurring tasks) |
427
+ | `list` | List tasks with filters and sorting |
428
+ | `show` | Show details of a specific task |
429
+ | `update` | Update task fields |
430
+ | `done` | Mark tasks as done |
431
+ | `next` | Show the next task to work on |
432
+ | `tree` | Display tasks as a dependency tree |
433
+ | `reopen` | Reopen archived tasks |
434
+ | `deps` | Show task dependencies (blocking tasks) |
435
+ | `series` | Manage recurring task series |
436
+ | `resolve` | Resolve merge conflicts between RST and JSON |
437
+ | `delete` | Permanently delete tasks (supports filters) |
438
+ | `archive` | Archive tasks (hide from listings, can reopen) |
439
+ | `export` | Export tasks to various formats (JSON, CSV, Markdown) |
440
+ | `search` | Search tasks by text pattern or regex |
441
+ | `stats` | Show task statistics |
442
+
443
+ ### Filter Options Reference
444
+
445
+ Several commands (`list`, `update`, `delete`) support common filter options:
446
+
447
+ | Option | Short | Commands | Description |
448
+ |--------|-------|----------|-------------|
449
+ | `--status` | `-s` | list | Filter by status (comma-separated) |
450
+ | `--priority` | `-p` | list | Filter by priority (comma-separated) |
451
+ | `--assignee` | `-a` | list | Filter by assignee (comma-separated) |
452
+ | `--tags` | `-t` | list | Filter by tags (comma-separated, matches any) |
453
+ | `--filter-status` | | update, delete | Filter by status (comma-separated) |
454
+ | `--filter-priority` | | update, delete | Filter by priority (comma-separated) |
455
+ | `--filter-assignee` | | update, delete | Filter by assignee (comma-separated) |
456
+ | `--filter-tags` | | update, delete | Filter by tags (comma-separated) |
457
+ | `--filter-overdue` | | update | Filter only overdue tasks |
458
+ | `--filter-archived` | | delete | Only include archived tasks |
459
+ | `--archived` | | list, search, export, stats | Include archived tasks |
460
+
461
+ **Safety flags for bulk operations:**
462
+
463
+ | Flag | Description |
464
+ |------|-------------|
465
+ | `--all` | Required when using filters without specific task IDs (safety measure) |
466
+ | `--dry-run` | Preview which tasks would be affected without making changes |
467
+ | `--yes` / `-y` | Skip confirmation prompt for bulk updates |
468
+ | `--force` / `-f` | Skip confirmation prompt for delete |
469
+
470
+ ### Shell Completion
471
+
472
+ Tab completion is available for bash, zsh, and fish. It completes:
473
+ - Task IDs (with status and title hints)
474
+ - Series IDs (with title hints)
475
+ - Assignee names (from existing tasks)
476
+ - Tags (from existing tasks)
477
+ - Status values (`open`, `in-progress`, `blocked`, `done`)
478
+ - Priority values (`low`, `medium`, `high`, `critical`)
479
+ - Due date shortcuts (`today`, `tomorrow`, `+1w`, `friday`, `next-monday`, `end-of-month`, etc.)
480
+ - Recurrence patterns (`every friday`, `every month on first monday`, etc.)
481
+
482
+ ```bash
483
+ # Install permanently (auto-detects your shell)
484
+ doto completion --install
485
+
486
+ # Or enable for current session only
487
+ eval "$(doto completion bash)" # bash
488
+ eval "$(doto completion zsh)" # zsh
489
+ doto completion fish | source # fish
490
+ ```
491
+
492
+ ## Bidirectional Sync
493
+
494
+ The `.doto/tasks.json` file is the source of truth. The CLI operates on JSON, while Sphinx builds perform bidirectional sync:
495
+
496
+ - Changes in RST files are detected via content hashing
497
+ - Changes in JSON (via CLI) are merged back to RST
498
+ - 3-way merge detects and reports conflicts
499
+ - Archived tasks are removed from RST but preserved in JSON
500
+
501
+ ## Theming
502
+
503
+ ### Custom Theme Override
504
+
505
+ To customize doto's appearance, create a `_doto/` directory in your Sphinx source:
506
+
507
+ ```
508
+ my-project/
509
+ ├── _doto/
510
+ │ ├── html/
511
+ │ │ └── doto-custom.css
512
+ │ ├── latex/
513
+ │ │ └── doto-custom.sty
514
+ │ └── epub/
515
+ │ └── doto-custom.css
516
+ ├── conf.py
517
+ └── index.rst
518
+ ```
519
+
520
+ Files in `_doto/` take precedence over built-in themes. This allows project-specific styling without modifying configuration.
521
+
522
+ ### HTML
523
+
524
+ Built-in themes: `default`, `minimal`
525
+
526
+ CSS variables for customization:
527
+
528
+ ```css
529
+ :root {
530
+ --doto-priority-low: #6c757d;
531
+ --doto-priority-medium: #0d6efd;
532
+ --doto-priority-high: #fd7e14;
533
+ --doto-priority-critical: #dc3545;
534
+ }
535
+ ```
536
+
537
+ ### epub
538
+
539
+ Built-in themes: `default`, `minimal`
540
+
541
+ Set via `doto_epub_theme` in conf.py. epub styles are optimized for e-readers with `page-break-inside: avoid` and simplified layouts.
542
+
543
+ ### LaTeX/PDF
544
+
545
+ Uses `tcolorbox` for styled output. Customize column widths with `doto_latex_column_specs`:
546
+
547
+ ```python
548
+ doto_latex_column_specs = {
549
+ "title": r"p{6cm}", # Wider title column
550
+ "priority": r"c", # Centered
551
+ }
552
+ ```
553
+
554
+ Custom styles via `doto_latex_preamble`.
555
+
556
+ ### Doxtr Integration
557
+
558
+ When `doxtr-pdf-theme-core` is available (and `doto_doxtr_integration` is `auto`
559
+ or `enabled`), doto integrates with its color and layout systems automatically
560
+ for PDF/LaTeX output. Standalone builds (without the theme core) keep doto's
561
+ built-in defaults unchanged.
562
+
563
+ ```python
564
+ # conf.py
565
+ doto_doxtr_integration = "auto" # auto | enabled | disabled
566
+ ```
567
+
568
+ **Semantic colors.** If a `doxtr_semantic_palette` is configured on the theme
569
+ core, doto derives its task-box, priority, and status colors from that palette
570
+ (via the core's `dd:` expression system, e.g. `dd:danger` for `critical`,
571
+ `dd:warning` for `high`, `dd:info` for `in-progress`) and emits them as
572
+ `\definecolor` overrides into the LaTeX preamble after `\usepackage{doto}`. This
573
+ means task boxes match the surrounding theme instead of doto's hardcoded
574
+ defaults. Without a palette (or without the theme core), the defaults in
575
+ `doto.sty` are used.
576
+
577
+ **Auto-landscape wide tables.** When integrated and the theme core's
578
+ `doxtr_table_auto_landscape` is enabled (the default), a `doto-list` task table
579
+ whose column count is at least `doxtr_landscape_min_columns` (theme-core option,
580
+ default `4`) is wrapped in the core's breakable landscape environment so it
581
+ rotates to landscape automatically and does not overflow the page margins.
582
+ Narrow tables (below the threshold) are left in portrait, and standalone builds
583
+ emit the unrotated table unchanged.
584
+
585
+ > `doxtr_semantic_palette`, `doxtr_table_auto_landscape`, and
586
+ > `doxtr_landscape_min_columns` are configuration values owned by
587
+ > `doxtr-pdf-theme-core`; doto only reads them when the theme core is active.
588
+
589
+ ## Development
590
+
591
+ Set up a local development environment and run the checks that CI enforces:
592
+
593
+ ```bash
594
+ pip install -e ".[dev]"
595
+ python scripts/check_imports.py # circular-import check (also run in CI)
596
+ python -m pytest # runs the suite with the coverage gate (fails under 80% via pyproject)
597
+ ```
598
+
599
+ The coverage gate is set to 80% to guard against coverage drift (current coverage is ~83%). The threshold lives in a single place, `pyproject.toml` `[tool.pytest.ini_options]` `addopts`, so running `python -m pytest` locally enforces the same gate as CI. The same import-cycle check (`scripts/check_imports.py`) runs in CI before the test suite.
600
+
601
+ ## License
602
+
603
+ MIT License