sphinx-touchbook 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 (115) hide show
  1. sphinx_touchbook-0.1.0/.gitignore +24 -0
  2. sphinx_touchbook-0.1.0/LICENSE +28 -0
  3. sphinx_touchbook-0.1.0/PKG-INFO +156 -0
  4. sphinx_touchbook-0.1.0/README.md +98 -0
  5. sphinx_touchbook-0.1.0/docs/accessibility.rst +83 -0
  6. sphinx_touchbook-0.1.0/docs/components/tb-blank.rst +194 -0
  7. sphinx_touchbook-0.1.0/docs/components/tb-choice.rst +420 -0
  8. sphinx_touchbook-0.1.0/docs/components/tb-click.rst +273 -0
  9. sphinx_touchbook-0.1.0/docs/components/tb-code.rst +800 -0
  10. sphinx_touchbook-0.1.0/docs/components/tb-file.rst +241 -0
  11. sphinx_touchbook-0.1.0/docs/components/tb-formula.rst +344 -0
  12. sphinx_touchbook-0.1.0/docs/components/tb-group.rst +160 -0
  13. sphinx_touchbook-0.1.0/docs/components/tb-match.rst +198 -0
  14. sphinx_touchbook-0.1.0/docs/components/tb-micro-parsons.rst +167 -0
  15. sphinx_touchbook-0.1.0/docs/components/tb-order.rst +112 -0
  16. sphinx_touchbook-0.1.0/docs/components/tb-parsons.rst +216 -0
  17. sphinx_touchbook-0.1.0/docs/components/tb-reveal.rst +196 -0
  18. sphinx_touchbook-0.1.0/docs/components/tb-video.rst +211 -0
  19. sphinx_touchbook-0.1.0/docs/conf.py +30 -0
  20. sphinx_touchbook-0.1.0/docs/directives.rst +135 -0
  21. sphinx_touchbook-0.1.0/docs/index.rst +12 -0
  22. sphinx_touchbook-0.1.0/docs/intro.rst +109 -0
  23. sphinx_touchbook-0.1.0/package-lock.json +1824 -0
  24. sphinx_touchbook-0.1.0/package.json +9 -0
  25. sphinx_touchbook-0.1.0/pyproject.toml +72 -0
  26. sphinx_touchbook-0.1.0/src/sphinx_touchbook/__init__.py +627 -0
  27. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/__init__.py +15 -0
  28. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/blank.py +192 -0
  29. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/choice.py +240 -0
  30. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/click.py +302 -0
  31. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/code.py +294 -0
  32. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/common.py +24 -0
  33. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/file.py +138 -0
  34. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/formula.py +242 -0
  35. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/match.py +127 -0
  36. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/micro_parsons.py +117 -0
  37. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/order.py +89 -0
  38. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/parsons.py +199 -0
  39. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/reveal.py +50 -0
  40. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/tabs.py +69 -0
  41. sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/video.py +244 -0
  42. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/__init__.py +11 -0
  43. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/blank.py +120 -0
  44. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/choice.py +190 -0
  45. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/click.py +170 -0
  46. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/code.py +138 -0
  47. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/file.py +97 -0
  48. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/formula.py +116 -0
  49. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/match.py +259 -0
  50. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/micro_parsons.py +147 -0
  51. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/order.py +133 -0
  52. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/parsons.py +155 -0
  53. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/reveal.py +69 -0
  54. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/tabs.py +85 -0
  55. sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/video.py +154 -0
  56. sphinx_touchbook-0.1.0/src/sphinx_touchbook/nodes.py +156 -0
  57. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/Baby_Chick_Hatching.jpg +0 -0
  58. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/Baby_Chick_Hatching.webm +0 -0
  59. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/hand-index-thumb.svg +3 -0
  60. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-blank.css +51 -0
  61. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-blank.js +107 -0
  62. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-choice.css +82 -0
  63. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-choice.js +111 -0
  64. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-click.css +84 -0
  65. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-click.js +70 -0
  66. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-code.css +121 -0
  67. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-code.js +802 -0
  68. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-file.css +52 -0
  69. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-file.js +101 -0
  70. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-formula.css +66 -0
  71. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-formula.js +200 -0
  72. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-group.css +36 -0
  73. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-group.js +175 -0
  74. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-match.css +90 -0
  75. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-match.js +85 -0
  76. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-micro-parsons.css +103 -0
  77. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-micro-parsons.js +139 -0
  78. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-order.css +104 -0
  79. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-order.js +108 -0
  80. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-parsons.css +120 -0
  81. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-parsons.js +201 -0
  82. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-reveal.css +43 -0
  83. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-reveal.js +120 -0
  84. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-video.css +143 -0
  85. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-video.js +274 -0
  86. sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/wilms-tumor-ct-scan.ogv +0 -0
  87. sphinx_touchbook-0.1.0/src/sphinx_touchbook/transforms.py +209 -0
  88. sphinx_touchbook-0.1.0/tests/test_tb_blank.py +187 -0
  89. sphinx_touchbook-0.1.0/tests/test_tb_choice.py +544 -0
  90. sphinx_touchbook-0.1.0/tests/test_tb_click.py +290 -0
  91. sphinx_touchbook-0.1.0/tests/test_tb_code.py +821 -0
  92. sphinx_touchbook-0.1.0/tests/test_tb_file.py +548 -0
  93. sphinx_touchbook-0.1.0/tests/test_tb_formula.py +294 -0
  94. sphinx_touchbook-0.1.0/tests/test_tb_group.py +223 -0
  95. sphinx_touchbook-0.1.0/tests/test_tb_match.py +244 -0
  96. sphinx_touchbook-0.1.0/tests/test_tb_micro_parsons.py +191 -0
  97. sphinx_touchbook-0.1.0/tests/test_tb_order.py +226 -0
  98. sphinx_touchbook-0.1.0/tests/test_tb_parsons.py +277 -0
  99. sphinx_touchbook-0.1.0/tests/test_tb_reveal.py +229 -0
  100. sphinx_touchbook-0.1.0/tests/test_tb_video.py +435 -0
  101. sphinx_touchbook-0.1.0/tests/web-components/helpers.js +23 -0
  102. sphinx_touchbook-0.1.0/tests/web-components/tb-blank.test.js +99 -0
  103. sphinx_touchbook-0.1.0/tests/web-components/tb-choice.test.js +134 -0
  104. sphinx_touchbook-0.1.0/tests/web-components/tb-click.test.js +106 -0
  105. sphinx_touchbook-0.1.0/tests/web-components/tb-code.test.js +578 -0
  106. sphinx_touchbook-0.1.0/tests/web-components/tb-file.test.js +79 -0
  107. sphinx_touchbook-0.1.0/tests/web-components/tb-formula.test.js +159 -0
  108. sphinx_touchbook-0.1.0/tests/web-components/tb-group-focus.test.js +308 -0
  109. sphinx_touchbook-0.1.0/tests/web-components/tb-group.test.js +159 -0
  110. sphinx_touchbook-0.1.0/tests/web-components/tb-match.test.js +135 -0
  111. sphinx_touchbook-0.1.0/tests/web-components/tb-micro-parsons.test.js +127 -0
  112. sphinx_touchbook-0.1.0/tests/web-components/tb-order.test.js +98 -0
  113. sphinx_touchbook-0.1.0/tests/web-components/tb-parsons.test.js +165 -0
  114. sphinx_touchbook-0.1.0/tests/web-components/tb-reveal.test.js +87 -0
  115. sphinx_touchbook-0.1.0/tests/web-components/tb-video.test.js +305 -0
@@ -0,0 +1,24 @@
1
+ # Byte-code
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Python packaging
7
+ dist/
8
+
9
+ # Sphinx documentation
10
+ docs/_build/
11
+ _build/
12
+ build/
13
+
14
+ # Python Environments
15
+ .env
16
+ .venv
17
+ env/
18
+ venv/
19
+ ENV/
20
+ env.bak/
21
+ venv.bak/
22
+
23
+ # JavaScript dependencies
24
+ node_modules/
@@ -0,0 +1,28 @@
1
+ Unless otherwise indicated, all code in the Sphinx-Touchbook project is
2
+ licenced under the two clause BSD licence below.
3
+
4
+ Copyright (c) 2026, Dave Parillo,
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+
11
+ * Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+
14
+ * Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: sphinx-touchbook
3
+ Version: 0.1.0
4
+ Summary: Sphinx directives and Web Components for interactive textbook content.
5
+ Project-URL: Homepage, https://github.com/DaveParillo/sphinx-touchbook
6
+ Project-URL: Issues, https://github.com/DaveParillo/sphinx-touchbook/issues
7
+ Author-email: Dave Parillo <dparillo@sdccd.edu>
8
+ License: Unless otherwise indicated, all code in the Sphinx-Touchbook project is
9
+ licenced under the two clause BSD licence below.
10
+
11
+ Copyright (c) 2026, Dave Parillo,
12
+ All rights reserved.
13
+
14
+ Redistribution and use in source and binary forms, with or without
15
+ modification, are permitted provided that the following conditions are
16
+ met:
17
+
18
+ * Redistributions of source code must retain the above copyright
19
+ notice, this list of conditions and the following disclaimer.
20
+
21
+ * Redistributions in binary form must reproduce the above copyright
22
+ notice, this list of conditions and the following disclaimer in the
23
+ documentation and/or other materials provided with the distribution.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ License-File: LICENSE
37
+ Classifier: Development Status :: 3 - Alpha
38
+ Classifier: Framework :: Sphinx :: Extension
39
+ Classifier: Intended Audience :: Education
40
+ Classifier: License :: OSI Approved :: BSD License
41
+ Classifier: Operating System :: OS Independent
42
+ Classifier: Programming Language :: Python :: 3
43
+ Classifier: Topic :: Documentation :: Sphinx
44
+ Classifier: Topic :: Education
45
+ Requires-Python: >=3.10
46
+ Requires-Dist: sphinx>=7
47
+ Provides-Extra: docs
48
+ Requires-Dist: sphinx-nefertiti; extra == 'docs'
49
+ Requires-Dist: sphinx>=7; extra == 'docs'
50
+ Provides-Extra: publish
51
+ Requires-Dist: build; extra == 'publish'
52
+ Requires-Dist: hatchling; extra == 'publish'
53
+ Requires-Dist: twine; extra == 'publish'
54
+ Provides-Extra: test
55
+ Requires-Dist: beautifulsoup4; extra == 'test'
56
+ Requires-Dist: pytest; extra == 'test'
57
+ Description-Content-Type: text/markdown
58
+
59
+ # sphinx-touchbook
60
+ [![Tests](https://img.shields.io/github/actions/workflow/status/daveparillo/sphinx-touchbook/publish-authorguide.yml?branch=main&label=tests)](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
61
+ [![Author Guide](https://img.shields.io/github/actions/workflow/status/daveparillo/sphinx-touchbook/publish-authorguide.yml?branch=main&label=docs)](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
62
+ [![License](https://img.shields.io/github/license/daveparillo/sphinx-touchbook)](LICENSE)
63
+
64
+ `sphinx-touchbook` is a Sphinx extension project for authors who want
65
+ interactive textbook pages without giving up ordinary Sphinx documents.
66
+ Authors write semantic reStructuredText directives, Sphinx parses them into
67
+ docutils nodes, Python generators render builder-specific output, and
68
+ JavaScript components progressively enhance the generated HTML.
69
+
70
+ This project is inspired by
71
+ [Runestone Interactive](https://github.com/RunestoneInteractive),
72
+ which pioneered interactive textbook components for computer science education.
73
+ `sphinx-touchbook` is a Sphinx-oriented port of that general idea: it keeps
74
+ authoring and builds inside Sphinx while Runestone's main project has moved
75
+ away from Sphinx-based authoring and toward PreTeXt-authored books.
76
+
77
+ The focus of this project is 'Sphinx-native' interactive books and nothing else.
78
+ Runestone is a much more sophisticated environment with instructor resources,
79
+ student tracking, and LMS integration.
80
+ If you want those features then you should consider Runestone as a resource.
81
+
82
+ ## Setup
83
+
84
+ To build documents Python is required.
85
+
86
+ Create and activate a virtual environment:
87
+
88
+ ```bash
89
+ python3 -m venv .venv
90
+ source .venv/bin/activate
91
+ ```
92
+
93
+ Install the Python package with test and documentation dependencies:
94
+
95
+ ```bash
96
+ python3 -m pip install --upgrade pip
97
+ python3 -m pip install ".[test,docs]"
98
+ ```
99
+
100
+ To test documents Node.js with `npm` is required.
101
+
102
+ Install JavaScript test dependencies:
103
+
104
+ ```bash
105
+ npm ci
106
+ ```
107
+
108
+ ## Build Documents
109
+
110
+ Build the author guide as HTML:
111
+
112
+ ```bash
113
+ python3 -m sphinx -b html docs build/authorguide --fail-on-warning
114
+ ```
115
+
116
+ The generated site starts at:
117
+
118
+ ```text
119
+ build/authorguide/index.html
120
+ ```
121
+
122
+ To build LaTeX or PDF requires either a local LaTeX installation
123
+ compatible with Sphinx, or a docker image:
124
+
125
+ Build LaTeX source locally:
126
+
127
+ ```bash
128
+ python3 -m sphinx -b latex docs build/latex --fail-on-warning
129
+ ```
130
+
131
+ Build the author guide PDF with the Sphinx LaTeX container:
132
+
133
+ ```bash
134
+ docker run --rm \
135
+ -v "$PWD:/docs" \
136
+ -w /docs \
137
+ sphinxdoc/sphinx-latexpdf:latest \
138
+ sh -c 'python3 -m pip install ".[docs]" && python -m sphinx -M latexpdf docs build/latexpdf --fail-on-warning'
139
+ ```
140
+
141
+ ## Run Tests
142
+
143
+ Run the Python directive and generator tests:
144
+
145
+ ```bash
146
+ python3 -m pytest tests/test_*.py
147
+ ```
148
+
149
+ Run isolated JavaScript component tests:
150
+
151
+ ```bash
152
+ npm run test:web-components
153
+ ```
154
+
155
+ See the author guide in `docs/` for directive syntax, options, examples,
156
+ accessibility notes, and fallback behavior.
@@ -0,0 +1,98 @@
1
+ # sphinx-touchbook
2
+ [![Tests](https://img.shields.io/github/actions/workflow/status/daveparillo/sphinx-touchbook/publish-authorguide.yml?branch=main&label=tests)](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
3
+ [![Author Guide](https://img.shields.io/github/actions/workflow/status/daveparillo/sphinx-touchbook/publish-authorguide.yml?branch=main&label=docs)](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
4
+ [![License](https://img.shields.io/github/license/daveparillo/sphinx-touchbook)](LICENSE)
5
+
6
+ `sphinx-touchbook` is a Sphinx extension project for authors who want
7
+ interactive textbook pages without giving up ordinary Sphinx documents.
8
+ Authors write semantic reStructuredText directives, Sphinx parses them into
9
+ docutils nodes, Python generators render builder-specific output, and
10
+ JavaScript components progressively enhance the generated HTML.
11
+
12
+ This project is inspired by
13
+ [Runestone Interactive](https://github.com/RunestoneInteractive),
14
+ which pioneered interactive textbook components for computer science education.
15
+ `sphinx-touchbook` is a Sphinx-oriented port of that general idea: it keeps
16
+ authoring and builds inside Sphinx while Runestone's main project has moved
17
+ away from Sphinx-based authoring and toward PreTeXt-authored books.
18
+
19
+ The focus of this project is 'Sphinx-native' interactive books and nothing else.
20
+ Runestone is a much more sophisticated environment with instructor resources,
21
+ student tracking, and LMS integration.
22
+ If you want those features then you should consider Runestone as a resource.
23
+
24
+ ## Setup
25
+
26
+ To build documents Python is required.
27
+
28
+ Create and activate a virtual environment:
29
+
30
+ ```bash
31
+ python3 -m venv .venv
32
+ source .venv/bin/activate
33
+ ```
34
+
35
+ Install the Python package with test and documentation dependencies:
36
+
37
+ ```bash
38
+ python3 -m pip install --upgrade pip
39
+ python3 -m pip install ".[test,docs]"
40
+ ```
41
+
42
+ To test documents Node.js with `npm` is required.
43
+
44
+ Install JavaScript test dependencies:
45
+
46
+ ```bash
47
+ npm ci
48
+ ```
49
+
50
+ ## Build Documents
51
+
52
+ Build the author guide as HTML:
53
+
54
+ ```bash
55
+ python3 -m sphinx -b html docs build/authorguide --fail-on-warning
56
+ ```
57
+
58
+ The generated site starts at:
59
+
60
+ ```text
61
+ build/authorguide/index.html
62
+ ```
63
+
64
+ To build LaTeX or PDF requires either a local LaTeX installation
65
+ compatible with Sphinx, or a docker image:
66
+
67
+ Build LaTeX source locally:
68
+
69
+ ```bash
70
+ python3 -m sphinx -b latex docs build/latex --fail-on-warning
71
+ ```
72
+
73
+ Build the author guide PDF with the Sphinx LaTeX container:
74
+
75
+ ```bash
76
+ docker run --rm \
77
+ -v "$PWD:/docs" \
78
+ -w /docs \
79
+ sphinxdoc/sphinx-latexpdf:latest \
80
+ sh -c 'python3 -m pip install ".[docs]" && python -m sphinx -M latexpdf docs build/latexpdf --fail-on-warning'
81
+ ```
82
+
83
+ ## Run Tests
84
+
85
+ Run the Python directive and generator tests:
86
+
87
+ ```bash
88
+ python3 -m pytest tests/test_*.py
89
+ ```
90
+
91
+ Run isolated JavaScript component tests:
92
+
93
+ ```bash
94
+ npm run test:web-components
95
+ ```
96
+
97
+ See the author guide in `docs/` for directive syntax, options, examples,
98
+ accessibility notes, and fallback behavior.
@@ -0,0 +1,83 @@
1
+ Accessibility And Keyboard Use
2
+ ==============================
3
+
4
+ Touchbook directives use native HTML controls wherever possible. Buttons,
5
+ inputs, text areas, selects, links, and dialogs keep their browser keyboard
6
+ behavior and programmatic labels. This helps assistive technology and lets each
7
+ browser expose controls in the way users expect.
8
+
9
+ Keyboard Basics
10
+ ---------------
11
+
12
+ Most Touchbook controls follow standard browser behavior:
13
+
14
+ * ``Tab`` moves forward through focusable controls.
15
+ * ``Shift+Tab`` moves backward through focusable controls.
16
+ * ``Enter`` activates links and most buttons.
17
+ * ``Space`` activates buttons, checkboxes, radio buttons, and similar controls.
18
+ * Arrow keys may move within composite widgets, such as tab groups.
19
+
20
+ Tab Groups
21
+ ----------
22
+
23
+ The ``tb-group`` directive renders an ARIA tab interface. Only the selected tab
24
+ is in the normal ``Tab`` order. This is intentional and follows the common
25
+ roving-tabindex pattern for tabs.
26
+
27
+ When focus is on a tab:
28
+
29
+ * ``ArrowRight`` moves to the next tab.
30
+ * ``ArrowLeft`` moves to the previous tab.
31
+ * ``Home`` moves to the first tab.
32
+ * ``End`` moves to the last tab.
33
+ * ``Tab`` moves into the selected tab panel when that panel contains a
34
+ focusable control.
35
+
36
+ For example, if a ``tb-group`` has ``Source`` and ``Rendered`` tabs, ``Tab``
37
+ does not normally move from ``Source`` to ``Rendered``. Use the arrow keys to
38
+ select ``Rendered``. Then use ``Tab`` to enter the rendered content.
39
+
40
+ Platform Settings
41
+ -----------------
42
+
43
+ Keyboard navigation can depend on operating system and browser settings. If
44
+ ``Tab`` skips buttons or other native controls, check the platform settings
45
+ before assuming the page is broken.
46
+
47
+ macOS
48
+ In System Settings, open **Keyboard** and enable full keyboard navigation.
49
+ Safari also has a browser-specific setting in **Advanced** named
50
+ **Press Tab to highlight each item on a webpage**.
51
+
52
+ When full keyboard access is disabled, macOS browsers may require
53
+ ``Option+Tab`` or ``Alt+Tab`` to move to buttons and other controls.
54
+
55
+ Windows
56
+ Windows browsers usually include buttons in the normal ``Tab`` order. If
57
+ navigation seems incomplete, check browser accessibility settings and any
58
+ installed keyboard or assistive-technology utilities. In Microsoft Edge and
59
+ Chrome, also check whether caret browsing or extension settings are changing
60
+ keyboard behavior.
61
+
62
+ Linux
63
+ Linux behavior depends on the desktop environment, browser, and assistive
64
+ technology stack. GNOME, KDE, Firefox, Chrome, and Chromium usually include
65
+ native buttons in the normal ``Tab`` order. If they do not, check desktop
66
+ keyboard accessibility settings, browser settings, and screen-reader or
67
+ extension configuration.
68
+
69
+ Testing Guidance
70
+ ----------------
71
+
72
+ When testing Touchbook content for keyboard accessibility:
73
+
74
+ * Test with full keyboard navigation enabled.
75
+ * Confirm that every visible control can receive focus.
76
+ * Confirm that visible focus is easy to see.
77
+ * Activate buttons with ``Space`` and ``Enter``.
78
+ * Test ``tb-group`` tabs with arrow keys, not only with ``Tab``.
79
+ * Test the static fallback output when building text or PDF formats.
80
+
81
+ Touchbook should provide accessible controls and predictable focus behavior.
82
+ Operating system and browser settings can still change how users move through
83
+ native controls.
@@ -0,0 +1,194 @@
1
+ tb-blank
2
+ ========
3
+
4
+ The ``tb-blank`` directive creates a fill-in-the-blank question.
5
+ Authors place one or more ``{{blank}}`` markers in normal Sphinx content.
6
+ Nested ``tb-answer`` blocks define accepted answers, targeted hints for common
7
+ wrong answers, and fallback incorrect feedback.
8
+
9
+ Synopsis
10
+ --------
11
+
12
+ The general format of the ``tb-blank`` directive is:
13
+
14
+ .. code-block:: rst
15
+
16
+ .. tb-blank::
17
+ :optional parameter: value
18
+
19
+ + --- Prompt area ---
20
+ |
21
+ | question text and optional Sphinx content with {{blank}} markers
22
+ |
23
+ + --- Answer area ---
24
+ |
25
+ | .. tb-answer:: optional-blank-id
26
+ | :match: accepted answer
27
+ | :feedback: correct feedback
28
+ | :hint: known wrong answer; targeted feedback
29
+ | :incorrect: fallback incorrect feedback
30
+ |
31
+ + -----------------
32
+
33
+ Options
34
+ -------
35
+
36
+ **case-sensitive**
37
+ ``Flag``. Optional.
38
+ Require exact case when comparing submitted answers. By default, matching is
39
+ case-insensitive.
40
+
41
+ **name**
42
+ ``String``. Optional.
43
+ Sphinx reference name for this fill-in-the-blank question.
44
+ This is a
45
+ `Docutils common option <https://docutils.sourceforge.io/docs/ref/rst/directives.html#common-options>`__.
46
+ If omitted, docutils assigns a deterministic generated ID derived from the
47
+ document and node position.
48
+
49
+ **preserve-whitespace**
50
+ ``Flag``. Optional.
51
+ Preserve leading and trailing whitespace when comparing submitted answers.
52
+ By default, submitted answers and expected answers are trimmed.
53
+
54
+ Answer Options
55
+ --------------
56
+
57
+ Nested ``tb-answer`` blocks support these options:
58
+
59
+ **feedback**
60
+ ``String``. Optional.
61
+ Feedback shown when a submitted answer matches one of the accepted answers.
62
+
63
+ **hint**
64
+ ``String``. Optional. Repeatable.
65
+ Known wrong answer and targeted feedback separated by the first semicolon.
66
+ For example, ``:hint: 7; Check the assignment in the else block.``.
67
+
68
+ **incorrect**
69
+ ``String``. Optional.
70
+ Feedback shown when the submitted answer does not match an accepted answer
71
+ or a known wrong answer.
72
+
73
+ **match**
74
+ ``String``. Required. Repeatable.
75
+ Accepted answer. Matching is case-insensitive and trims leading and trailing
76
+ whitespace unless directive options override those defaults.
77
+
78
+ **regex**
79
+ ``Flag``. Optional.
80
+ Treat ``match`` values as regular expressions.
81
+
82
+ Accessibility behavior
83
+ ----------------------
84
+
85
+ HTML uses native text inputs and a native button. Result text uses a status
86
+ region so assistive technology can announce feedback after checking.
87
+
88
+ Fallback behavior
89
+ -----------------
90
+
91
+ HTML without JavaScript renders the prompt and input fields. Text and
92
+ PDF-oriented builders render each blank as an underline. Answers and feedback
93
+ are not rendered in fallback output.
94
+
95
+ Examples
96
+ --------
97
+
98
+ Example 1: Single blank
99
+ ~~~~~~~~~~~~~~~~~~~~~~~
100
+
101
+ .. tb-group::
102
+ :name: blank-ex1-tabs
103
+
104
+ .. tb-tab:: Source
105
+
106
+ .. code-block:: rst
107
+
108
+ .. tb-blank::
109
+
110
+ The capital of France is {{blank}}.
111
+
112
+ .. tb-answer::
113
+ :match: Paris
114
+ :feedback: Correct.
115
+ :incorrect: Try again.
116
+
117
+ .. tb-tab:: Rendered
118
+
119
+ .. tb-blank::
120
+
121
+ The capital of France is {{blank}}.
122
+
123
+ .. tb-answer::
124
+ :match: Paris
125
+ :feedback: Correct.
126
+ :incorrect: Try again.
127
+
128
+ Example 2: Code reasoning with targeted hints
129
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130
+
131
+ .. tb-group::
132
+ :name: blank-ex2-tabs
133
+
134
+ .. tb-tab:: Source
135
+
136
+ .. code-block:: rst
137
+
138
+ .. tb-blank::
139
+
140
+ .. code-block:: c
141
+
142
+ int main(void) {
143
+ int a = 7;
144
+ int b = 4;
145
+
146
+ if (a<=b) {
147
+ a = 99;
148
+ } else {
149
+ int t = a;
150
+ a = b;
151
+ b = t;
152
+ }
153
+ return a;
154
+ }
155
+
156
+ What value is returned from main? {{blank}}
157
+
158
+ .. tb-answer::
159
+ :match: 4
160
+ :match: 4.0
161
+ :feedback: Correct.
162
+ :hint: 7; No, because the variable a is modified in the else block.
163
+ :hint: 99; No. Since a is greater than b, line 6 is never executed.
164
+ :incorrect: Sorry, no. What is happening in the else block?
165
+
166
+ .. tb-tab:: Rendered
167
+
168
+ .. tb-blank::
169
+
170
+ .. code-block:: c
171
+
172
+ int main(void) {
173
+ int a = 7;
174
+ int b = 4;
175
+
176
+ if (a<=b) {
177
+ a = 99;
178
+ } else {
179
+ int t = a;
180
+ a = b;
181
+ b = t;
182
+ }
183
+ return a;
184
+ }
185
+
186
+ What value is returned from main? {{blank}}
187
+
188
+ .. tb-answer::
189
+ :match: 4
190
+ :match: 4.0
191
+ :feedback: Correct.
192
+ :hint: 7; No, because the variable a is modified in the else block.
193
+ :hint: 99; No. Since a is greater than b, line 6 is never executed.
194
+ :incorrect: Sorry, no. What is happening in the else block?