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.
- sphinx_touchbook-0.1.0/.gitignore +24 -0
- sphinx_touchbook-0.1.0/LICENSE +28 -0
- sphinx_touchbook-0.1.0/PKG-INFO +156 -0
- sphinx_touchbook-0.1.0/README.md +98 -0
- sphinx_touchbook-0.1.0/docs/accessibility.rst +83 -0
- sphinx_touchbook-0.1.0/docs/components/tb-blank.rst +194 -0
- sphinx_touchbook-0.1.0/docs/components/tb-choice.rst +420 -0
- sphinx_touchbook-0.1.0/docs/components/tb-click.rst +273 -0
- sphinx_touchbook-0.1.0/docs/components/tb-code.rst +800 -0
- sphinx_touchbook-0.1.0/docs/components/tb-file.rst +241 -0
- sphinx_touchbook-0.1.0/docs/components/tb-formula.rst +344 -0
- sphinx_touchbook-0.1.0/docs/components/tb-group.rst +160 -0
- sphinx_touchbook-0.1.0/docs/components/tb-match.rst +198 -0
- sphinx_touchbook-0.1.0/docs/components/tb-micro-parsons.rst +167 -0
- sphinx_touchbook-0.1.0/docs/components/tb-order.rst +112 -0
- sphinx_touchbook-0.1.0/docs/components/tb-parsons.rst +216 -0
- sphinx_touchbook-0.1.0/docs/components/tb-reveal.rst +196 -0
- sphinx_touchbook-0.1.0/docs/components/tb-video.rst +211 -0
- sphinx_touchbook-0.1.0/docs/conf.py +30 -0
- sphinx_touchbook-0.1.0/docs/directives.rst +135 -0
- sphinx_touchbook-0.1.0/docs/index.rst +12 -0
- sphinx_touchbook-0.1.0/docs/intro.rst +109 -0
- sphinx_touchbook-0.1.0/package-lock.json +1824 -0
- sphinx_touchbook-0.1.0/package.json +9 -0
- sphinx_touchbook-0.1.0/pyproject.toml +72 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/__init__.py +627 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/__init__.py +15 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/blank.py +192 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/choice.py +240 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/click.py +302 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/code.py +294 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/common.py +24 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/file.py +138 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/formula.py +242 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/match.py +127 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/micro_parsons.py +117 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/order.py +89 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/parsons.py +199 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/reveal.py +50 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/tabs.py +69 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/directives/video.py +244 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/__init__.py +11 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/blank.py +120 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/choice.py +190 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/click.py +170 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/code.py +138 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/file.py +97 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/formula.py +116 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/match.py +259 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/micro_parsons.py +147 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/order.py +133 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/parsons.py +155 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/reveal.py +69 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/tabs.py +85 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/generators/video.py +154 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/nodes.py +156 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/Baby_Chick_Hatching.jpg +0 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/Baby_Chick_Hatching.webm +0 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/hand-index-thumb.svg +3 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-blank.css +51 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-blank.js +107 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-choice.css +82 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-choice.js +111 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-click.css +84 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-click.js +70 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-code.css +121 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-code.js +802 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-file.css +52 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-file.js +101 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-formula.css +66 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-formula.js +200 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-group.css +36 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-group.js +175 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-match.css +90 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-match.js +85 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-micro-parsons.css +103 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-micro-parsons.js +139 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-order.css +104 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-order.js +108 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-parsons.css +120 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-parsons.js +201 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-reveal.css +43 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-reveal.js +120 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-video.css +143 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/tb-video.js +274 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/static/wilms-tumor-ct-scan.ogv +0 -0
- sphinx_touchbook-0.1.0/src/sphinx_touchbook/transforms.py +209 -0
- sphinx_touchbook-0.1.0/tests/test_tb_blank.py +187 -0
- sphinx_touchbook-0.1.0/tests/test_tb_choice.py +544 -0
- sphinx_touchbook-0.1.0/tests/test_tb_click.py +290 -0
- sphinx_touchbook-0.1.0/tests/test_tb_code.py +821 -0
- sphinx_touchbook-0.1.0/tests/test_tb_file.py +548 -0
- sphinx_touchbook-0.1.0/tests/test_tb_formula.py +294 -0
- sphinx_touchbook-0.1.0/tests/test_tb_group.py +223 -0
- sphinx_touchbook-0.1.0/tests/test_tb_match.py +244 -0
- sphinx_touchbook-0.1.0/tests/test_tb_micro_parsons.py +191 -0
- sphinx_touchbook-0.1.0/tests/test_tb_order.py +226 -0
- sphinx_touchbook-0.1.0/tests/test_tb_parsons.py +277 -0
- sphinx_touchbook-0.1.0/tests/test_tb_reveal.py +229 -0
- sphinx_touchbook-0.1.0/tests/test_tb_video.py +435 -0
- sphinx_touchbook-0.1.0/tests/web-components/helpers.js +23 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-blank.test.js +99 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-choice.test.js +134 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-click.test.js +106 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-code.test.js +578 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-file.test.js +79 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-formula.test.js +159 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-group-focus.test.js +308 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-group.test.js +159 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-match.test.js +135 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-micro-parsons.test.js +127 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-order.test.js +98 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-parsons.test.js +165 -0
- sphinx_touchbook-0.1.0/tests/web-components/tb-reveal.test.js +87 -0
- 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
|
+
[](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
|
|
61
|
+
[](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
|
|
62
|
+
[](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
|
+
[](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
|
|
3
|
+
[](https://github.com/daveparillo/sphinx-touchbook/actions/workflows/publish-authorguide.yml)
|
|
4
|
+
[](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?
|