scrolly 0.2.3__tar.gz → 0.2.5__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.
- {scrolly-0.2.3 → scrolly-0.2.5}/.gitignore +3 -0
- scrolly-0.2.5/PKG-INFO +118 -0
- scrolly-0.2.5/README.md +85 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/pyproject.toml +3 -1
- scrolly-0.2.5/scrolly/_cli/_ai_help.py +124 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_cli.py +20 -46
- scrolly-0.2.5/scrolly/_cli/_schema.py +184 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E003.md +2 -2
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E299.md +2 -2
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E601.md +3 -2
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/assets/canvas.css +1 -1
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/assets/canvas.js +15 -1
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/__init__.py +2 -1
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/__init__.py +2 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/_framework/element.py +49 -1
- scrolly-0.2.3/PKG-INFO +0 -81
- scrolly-0.2.3/README.md +0 -50
- {scrolly-0.2.3 → scrolly-0.2.5}/LICENSE +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_errors.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_assets.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_common.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_dom.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_elements.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_slides.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_snaps.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_snapshot.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/_cli/_introspect/_timeline.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/inference.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/introspect.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/model.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/parser.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/schema.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/deck/validator.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/_catalog.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/_codes.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/_report.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/_validation_error.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E001.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E002.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E004.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E005.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E006.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E007.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E008.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E009.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E010.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E011.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E012.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E101.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E102.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E103.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E201.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E202.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E203.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E204.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E205.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E206.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E207.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E301.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E302.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E303.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E304.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E305.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E306.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E307.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E308.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E401.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E402.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E403.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E501.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E502.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E503.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E504.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E505.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E602.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E603.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E701.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/E702.md +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/errors/catalog/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/_bundler.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/assets.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/introspect.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/lint.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/loader.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/orchestrator.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/pipeline/writer.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/assembler.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/assets/mermaid-LICENSE +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/assets/mermaid.min.js +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/bundled_assets.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/color.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/fan.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/nav_data.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/templates/index.html.j2 +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/render/zoom_control.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/ir.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/processor.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/registry.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/rendered.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/_shared.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/html.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/iframe.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/image.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/image_sequence.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/markdown.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/element_ir/renderers/mermaid.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/html.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/introspect.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/_framework/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/_framework/animated_values.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/_framework/utils.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/ir/slide.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/processor.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/registry.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/renderers/__init__.py +0 -0
- {scrolly-0.2.3 → scrolly-0.2.5}/scrolly/slide/renderers/slide.py +0 -0
scrolly-0.2.5/PKG-INFO
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scrolly
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: CLI that compiles a JSON5 deck + slide files into a self-contained 2D-canvas HTML presentation.
|
|
5
|
+
Project-URL: Homepage, https://scrolly.readthedocs.io/en/stable/
|
|
6
|
+
Project-URL: Documentation, https://scrolly.readthedocs.io/en/stable/
|
|
7
|
+
Project-URL: Source, https://github.com/bertpl/scrolly
|
|
8
|
+
Project-URL: Changelog, https://github.com/bertpl/scrolly/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/bertpl/scrolly/issues
|
|
10
|
+
Author-email: Bert Pluymers <bert.pluymers@gmail.com>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: cli,html,presentation,scrollytelling,slides
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Multimedia :: Graphics :: Presentation
|
|
23
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: click>=8.2.0
|
|
26
|
+
Requires-Dist: jinja2>=3.1
|
|
27
|
+
Requires-Dist: json5>=0.13.0
|
|
28
|
+
Requires-Dist: markdown>=3.4
|
|
29
|
+
Requires-Dist: pydantic>=2.0
|
|
30
|
+
Requires-Dist: pyyaml>=6.0
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# scrolly
|
|
35
|
+
|
|
36
|
+
Compile a JSON5 deck into a single, self-contained, scrollable 2D-canvas HTML presentation.
|
|
37
|
+
|
|
38
|
+
*Liked by humans; understood by agents.*
|
|
39
|
+
|
|
40
|
+
[](https://scrolly.readthedocs.io/en/stable/)
|
|
41
|
+
|
|
42
|
+
[](https://github.com/bertpl/scrolly/actions/workflows/push_to_main.yml)
|
|
43
|
+
[](https://pypi.org/project/scrolly/)
|
|
44
|
+
[](https://pypi.org/project/scrolly/)
|
|
45
|
+
[](https://github.com/bertpl/scrolly/blob/main/LICENSE)
|
|
46
|
+
|
|
47
|
+
## Why it's different
|
|
48
|
+
|
|
49
|
+
- **A 2D canvas you fly around**, not a linear reel. Slides sit on an
|
|
50
|
+
integer grid connected by edges; readers zoom out to a deck map and
|
|
51
|
+
zoom into any slide to scroll through it.
|
|
52
|
+
- **Scroll-driven keyframe animation.** Element properties (position,
|
|
53
|
+
size, opacity, scale, angle) interpolate as the reader scrolls — no
|
|
54
|
+
timeline, no autoplay.
|
|
55
|
+
- **One self-contained HTML file.** A default build inlines every
|
|
56
|
+
asset into a single `index.html` with zero external loads — open it
|
|
57
|
+
by double-clicking, host it anywhere, email it.
|
|
58
|
+
- **Agent-friendly.** The CLI exposes full help, input schemas, deck
|
|
59
|
+
introspection, and numbered error codes, so agentic coding tools
|
|
60
|
+
immediately understand how to author and debug scrolly decks.
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install scrolly # or: uv tool install scrolly
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Quickstart
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
scrolly init my-deck # scaffold a starter deck
|
|
72
|
+
scrolly build my-deck/deck.deck.json --out out --force # compile to one HTML file
|
|
73
|
+
open out/index.html # double-click anywhere
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
A deck is a `.deck.json` manifest plus one `.slide.json` per slide (both
|
|
77
|
+
parsed as JSON5):
|
|
78
|
+
|
|
79
|
+
```json5
|
|
80
|
+
// deck.deck.json
|
|
81
|
+
{
|
|
82
|
+
title: "My Deck",
|
|
83
|
+
slides: [
|
|
84
|
+
{ id: "intro", position: [0, 0], source: "slides/intro.slide.json" },
|
|
85
|
+
],
|
|
86
|
+
edges: [],
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```json5
|
|
91
|
+
// slides/intro.slide.json
|
|
92
|
+
{
|
|
93
|
+
title: "My Deck",
|
|
94
|
+
elements: [
|
|
95
|
+
{ markdown: "# My Deck\n\nWelcome to your new presentation." },
|
|
96
|
+
],
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Elements
|
|
101
|
+
|
|
102
|
+
Slides hold elements of six types — `markdown`, `image`, `image_sequence`,
|
|
103
|
+
`mermaid`, `html`, and `iframe` — each animatable via scroll-driven
|
|
104
|
+
keyframes. See the [element reference](https://scrolly.readthedocs.io/en/stable/reference/elements/)
|
|
105
|
+
for fields and examples.
|
|
106
|
+
|
|
107
|
+
## Learn more
|
|
108
|
+
|
|
109
|
+
- **[Documentation](https://scrolly.readthedocs.io/en/stable/)** — guided
|
|
110
|
+
walkthrough, concepts, authoring, and the full reference, with a live
|
|
111
|
+
interactive deck right on the homepage.
|
|
112
|
+
- **[Examples](examples/)** — including the
|
|
113
|
+
[stacked-diffs](examples/stacked-diffs/) hero deck.
|
|
114
|
+
- **[Changelog](CHANGELOG.md)**.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
[MIT](https://github.com/bertpl/scrolly/blob/main/LICENSE).
|
scrolly-0.2.5/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# scrolly
|
|
2
|
+
|
|
3
|
+
Compile a JSON5 deck into a single, self-contained, scrollable 2D-canvas HTML presentation.
|
|
4
|
+
|
|
5
|
+
*Liked by humans; understood by agents.*
|
|
6
|
+
|
|
7
|
+
[](https://scrolly.readthedocs.io/en/stable/)
|
|
8
|
+
|
|
9
|
+
[](https://github.com/bertpl/scrolly/actions/workflows/push_to_main.yml)
|
|
10
|
+
[](https://pypi.org/project/scrolly/)
|
|
11
|
+
[](https://pypi.org/project/scrolly/)
|
|
12
|
+
[](https://github.com/bertpl/scrolly/blob/main/LICENSE)
|
|
13
|
+
|
|
14
|
+
## Why it's different
|
|
15
|
+
|
|
16
|
+
- **A 2D canvas you fly around**, not a linear reel. Slides sit on an
|
|
17
|
+
integer grid connected by edges; readers zoom out to a deck map and
|
|
18
|
+
zoom into any slide to scroll through it.
|
|
19
|
+
- **Scroll-driven keyframe animation.** Element properties (position,
|
|
20
|
+
size, opacity, scale, angle) interpolate as the reader scrolls — no
|
|
21
|
+
timeline, no autoplay.
|
|
22
|
+
- **One self-contained HTML file.** A default build inlines every
|
|
23
|
+
asset into a single `index.html` with zero external loads — open it
|
|
24
|
+
by double-clicking, host it anywhere, email it.
|
|
25
|
+
- **Agent-friendly.** The CLI exposes full help, input schemas, deck
|
|
26
|
+
introspection, and numbered error codes, so agentic coding tools
|
|
27
|
+
immediately understand how to author and debug scrolly decks.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install scrolly # or: uv tool install scrolly
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quickstart
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
scrolly init my-deck # scaffold a starter deck
|
|
39
|
+
scrolly build my-deck/deck.deck.json --out out --force # compile to one HTML file
|
|
40
|
+
open out/index.html # double-click anywhere
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
A deck is a `.deck.json` manifest plus one `.slide.json` per slide (both
|
|
44
|
+
parsed as JSON5):
|
|
45
|
+
|
|
46
|
+
```json5
|
|
47
|
+
// deck.deck.json
|
|
48
|
+
{
|
|
49
|
+
title: "My Deck",
|
|
50
|
+
slides: [
|
|
51
|
+
{ id: "intro", position: [0, 0], source: "slides/intro.slide.json" },
|
|
52
|
+
],
|
|
53
|
+
edges: [],
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```json5
|
|
58
|
+
// slides/intro.slide.json
|
|
59
|
+
{
|
|
60
|
+
title: "My Deck",
|
|
61
|
+
elements: [
|
|
62
|
+
{ markdown: "# My Deck\n\nWelcome to your new presentation." },
|
|
63
|
+
],
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Elements
|
|
68
|
+
|
|
69
|
+
Slides hold elements of six types — `markdown`, `image`, `image_sequence`,
|
|
70
|
+
`mermaid`, `html`, and `iframe` — each animatable via scroll-driven
|
|
71
|
+
keyframes. See the [element reference](https://scrolly.readthedocs.io/en/stable/reference/elements/)
|
|
72
|
+
for fields and examples.
|
|
73
|
+
|
|
74
|
+
## Learn more
|
|
75
|
+
|
|
76
|
+
- **[Documentation](https://scrolly.readthedocs.io/en/stable/)** — guided
|
|
77
|
+
walkthrough, concepts, authoring, and the full reference, with a live
|
|
78
|
+
interactive deck right on the homepage.
|
|
79
|
+
- **[Examples](examples/)** — including the
|
|
80
|
+
[stacked-diffs](examples/stacked-diffs/) hero deck.
|
|
81
|
+
- **[Changelog](CHANGELOG.md)**.
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
[MIT](https://github.com/bertpl/scrolly/blob/main/LICENSE).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "scrolly"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.5"
|
|
4
4
|
description = "CLI that compiles a JSON5 deck + slide files into a self-contained 2D-canvas HTML presentation."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -54,6 +54,8 @@ capture = [
|
|
|
54
54
|
scrolly = "scrolly._cli._cli:cli"
|
|
55
55
|
|
|
56
56
|
[project.urls]
|
|
57
|
+
Homepage = "https://scrolly.readthedocs.io/en/stable/"
|
|
58
|
+
Documentation = "https://scrolly.readthedocs.io/en/stable/"
|
|
57
59
|
Source = "https://github.com/bertpl/scrolly"
|
|
58
60
|
Changelog = "https://github.com/bertpl/scrolly/blob/main/CHANGELOG.md"
|
|
59
61
|
Issues = "https://github.com/bertpl/scrolly/issues"
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Builds the ``scrolly --help-for-ai-tools`` document.
|
|
2
|
+
|
|
3
|
+
One markdown document covering the entire CLI surface in a single read —
|
|
4
|
+
the command tree, every source-file and element schema, and every error
|
|
5
|
+
code — so an LLM agent gets the whole picture without round-tripping
|
|
6
|
+
through ``scrolly schema`` / ``scrolly errors`` per type and code. It is
|
|
7
|
+
a pure aggregator: every section is the output the individual commands
|
|
8
|
+
already produce, merged under markdown headers, never re-rendered.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Iterator
|
|
14
|
+
|
|
15
|
+
import click
|
|
16
|
+
|
|
17
|
+
from scrolly._cli._schema import element_schema_json, file_schema_json, file_type_names
|
|
18
|
+
from scrolly.errors import registered_codes
|
|
19
|
+
from scrolly.errors._catalog import load_body
|
|
20
|
+
from scrolly.slide import element_source_types
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ==================================================================================================
|
|
24
|
+
# Document assembly
|
|
25
|
+
# ==================================================================================================
|
|
26
|
+
def build_ai_help(root_command: click.Command, version: str) -> str:
|
|
27
|
+
"""Render the whole CLI reference as one self-contained markdown document.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
root_command: The top-level ``scrolly`` Click group, walked for the command tree.
|
|
31
|
+
version: The scrolly version string, shown in the document header.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
A single markdown document: header, command tree, file schemas,
|
|
35
|
+
element schemas, and error codes — heading levels nested so the
|
|
36
|
+
whole document forms one consistent hierarchy.
|
|
37
|
+
"""
|
|
38
|
+
sections = [
|
|
39
|
+
_header(version),
|
|
40
|
+
_commands_section(root_command),
|
|
41
|
+
_file_schemas_section(),
|
|
42
|
+
_element_schemas_section(),
|
|
43
|
+
_error_codes_section(),
|
|
44
|
+
]
|
|
45
|
+
return "\n\n".join(sections) + "\n"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _header(version: str) -> str:
|
|
49
|
+
"""Render the document title and one-paragraph orientation."""
|
|
50
|
+
return (
|
|
51
|
+
f"# scrolly {version} — CLI reference for AI tools\n\n"
|
|
52
|
+
"The complete scrolly command-line surface in one document: every command, "
|
|
53
|
+
"every source-file and element schema, and every error code. Generated from "
|
|
54
|
+
"the installed scrolly, so it matches this version exactly."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ==================================================================================================
|
|
59
|
+
# Sections
|
|
60
|
+
# ==================================================================================================
|
|
61
|
+
def _commands_section(root_command: click.Command) -> str:
|
|
62
|
+
"""Render every command's help text, walking the full command tree."""
|
|
63
|
+
blocks = ["## Commands"]
|
|
64
|
+
for path, help_text in _walk_commands(root_command, "scrolly", None):
|
|
65
|
+
blocks.append(f"### `{path}`\n\n```\n{help_text.rstrip()}\n```")
|
|
66
|
+
return "\n\n".join(blocks)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _file_schemas_section() -> str:
|
|
70
|
+
"""Render the JSON Schema for every source-file type (deck, slide)."""
|
|
71
|
+
blocks = ["## File schemas"]
|
|
72
|
+
for name in file_type_names():
|
|
73
|
+
blocks.append(f"### `{name}`\n\n```json\n{file_schema_json(name)}\n```")
|
|
74
|
+
return "\n\n".join(blocks)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _element_schemas_section() -> str:
|
|
78
|
+
"""Render the JSON Schema for every slide-element type."""
|
|
79
|
+
blocks = ["## Element schemas"]
|
|
80
|
+
for key in element_source_types():
|
|
81
|
+
blocks.append(f"### `{key}`\n\n```json\n{element_schema_json(key)}\n```")
|
|
82
|
+
return "\n\n".join(blocks)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _error_codes_section() -> str:
|
|
86
|
+
"""Render the catalog entry for every registered error code.
|
|
87
|
+
|
|
88
|
+
Each catalog body is verbatim markdown starting at its own ``# E…``
|
|
89
|
+
heading; demoting by two levels nests every entry under this section.
|
|
90
|
+
"""
|
|
91
|
+
blocks = ["## Error codes"]
|
|
92
|
+
for code in sorted(registered_codes()):
|
|
93
|
+
blocks.append(_demote_headings(load_body(code).rstrip(), 2))
|
|
94
|
+
return "\n\n".join(blocks)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# ==================================================================================================
|
|
98
|
+
# Helpers
|
|
99
|
+
# ==================================================================================================
|
|
100
|
+
def _walk_commands(
|
|
101
|
+
command: click.Command, info_name: str, parent_ctx: click.Context | None
|
|
102
|
+
) -> Iterator[tuple[str, str]]:
|
|
103
|
+
"""Yield ``(command_path, help_text)`` for a command and all its subcommands, depth-first."""
|
|
104
|
+
ctx = click.Context(command, info_name=info_name, parent=parent_ctx)
|
|
105
|
+
yield ctx.command_path, command.get_help(ctx)
|
|
106
|
+
if isinstance(command, click.Group):
|
|
107
|
+
for name in command.list_commands(ctx):
|
|
108
|
+
sub = command.get_command(ctx, name)
|
|
109
|
+
if sub is None or sub.hidden:
|
|
110
|
+
continue
|
|
111
|
+
yield from _walk_commands(sub, name, ctx)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _demote_headings(markdown: str, levels: int) -> str:
|
|
115
|
+
"""Deepen every ATX heading by ``levels`` ``#``, leaving fenced code blocks untouched."""
|
|
116
|
+
out = []
|
|
117
|
+
in_fence = False
|
|
118
|
+
for line in markdown.splitlines():
|
|
119
|
+
if line.lstrip().startswith("```"):
|
|
120
|
+
in_fence = not in_fence
|
|
121
|
+
if not in_fence and line.startswith("#"):
|
|
122
|
+
line = "#" * levels + line
|
|
123
|
+
out.append(line)
|
|
124
|
+
return "\n".join(out)
|
|
@@ -8,6 +8,7 @@ from rich.console import Console
|
|
|
8
8
|
from scrolly import __version__
|
|
9
9
|
from scrolly._cli._errors import errors_command
|
|
10
10
|
from scrolly._cli._introspect import introspect
|
|
11
|
+
from scrolly._cli._schema import schema
|
|
11
12
|
from scrolly.errors import ScrollyError, ValidationError
|
|
12
13
|
from scrolly.pipeline import build_deck, load_deck
|
|
13
14
|
from scrolly.pipeline.lint import lint_deck
|
|
@@ -15,8 +16,26 @@ from scrolly.pipeline.lint import lint_deck
|
|
|
15
16
|
_err_console = Console(stderr=True, highlight=False)
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
def _emit_ai_help(ctx: click.Context, param: click.Parameter, value: bool) -> None:
|
|
20
|
+
"""Eager ``--help-for-ai-tools`` callback: print the full CLI reference and exit."""
|
|
21
|
+
if not value or ctx.resilient_parsing:
|
|
22
|
+
return
|
|
23
|
+
from scrolly._cli._ai_help import build_ai_help
|
|
24
|
+
|
|
25
|
+
click.echo(build_ai_help(ctx.find_root().command, __version__))
|
|
26
|
+
ctx.exit()
|
|
27
|
+
|
|
28
|
+
|
|
18
29
|
@click.group()
|
|
19
30
|
@click.version_option(__version__, prog_name="scrolly")
|
|
31
|
+
@click.option(
|
|
32
|
+
"--help-for-ai-tools",
|
|
33
|
+
is_flag=True,
|
|
34
|
+
is_eager=True,
|
|
35
|
+
expose_value=False,
|
|
36
|
+
callback=_emit_ai_help,
|
|
37
|
+
help="Print the entire CLI reference (commands, schemas, error codes) as one markdown document for AI agents.",
|
|
38
|
+
)
|
|
20
39
|
def cli() -> None:
|
|
21
40
|
"""scrolly — compile a JSON5 deck into a self-contained 2D-canvas HTML presentation."""
|
|
22
41
|
|
|
@@ -82,52 +101,6 @@ def build(
|
|
|
82
101
|
click.echo(f"Built '{deck.title or '(untitled)'}': {len(deck.slides)} slides, {len(deck.edges)} edges → {out_dir}")
|
|
83
102
|
|
|
84
103
|
|
|
85
|
-
@cli.command()
|
|
86
|
-
@click.argument("type_name", required=False)
|
|
87
|
-
@click.option(
|
|
88
|
-
"--list-types",
|
|
89
|
-
"list_types",
|
|
90
|
-
is_flag=True,
|
|
91
|
-
help="Print bare type names one per line (no descriptions) for scripting use.",
|
|
92
|
-
)
|
|
93
|
-
def schema(type_name: str | None, list_types: bool) -> None:
|
|
94
|
-
"""Show source file schemas.
|
|
95
|
-
|
|
96
|
-
\b
|
|
97
|
-
scrolly schema → formatted index of available types
|
|
98
|
-
scrolly schema <type> → JSON Schema for <type>
|
|
99
|
-
scrolly schema --list-types → bare type names, one per line (agent / scripting)
|
|
100
|
-
"""
|
|
101
|
-
from scrolly.deck import deck_source_schema
|
|
102
|
-
from scrolly.slide import registered_ir_types
|
|
103
|
-
|
|
104
|
-
ir_types = registered_ir_types()
|
|
105
|
-
all_type_names = sorted(["deck", *ir_types])
|
|
106
|
-
|
|
107
|
-
if list_types:
|
|
108
|
-
for name in all_type_names:
|
|
109
|
-
click.echo(name)
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
if type_name is None:
|
|
113
|
-
click.echo("Available schemas:\n")
|
|
114
|
-
click.echo(f" {'deck':<17}{'.deck.json':<24}Deck structure (slides + edges)")
|
|
115
|
-
for name in sorted(ir_types):
|
|
116
|
-
cls = ir_types[name]
|
|
117
|
-
click.echo(f" {name:<17}{cls.SUFFIX:<24}{cls.DESCRIPTION}")
|
|
118
|
-
return
|
|
119
|
-
|
|
120
|
-
if type_name == "deck":
|
|
121
|
-
click.echo(json.dumps(deck_source_schema(), indent=2))
|
|
122
|
-
return
|
|
123
|
-
|
|
124
|
-
if type_name not in ir_types:
|
|
125
|
-
_err_console.print(f"[red]error:[/red] unknown type '{type_name}' (known: {', '.join(all_type_names)})")
|
|
126
|
-
sys.exit(1)
|
|
127
|
-
|
|
128
|
-
click.echo(json.dumps(ir_types[type_name].source_schema(), indent=2))
|
|
129
|
-
|
|
130
|
-
|
|
131
104
|
@cli.command()
|
|
132
105
|
@click.argument("deck_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
|
|
133
106
|
@click.option("--strict", is_flag=True, help="Enable additional lint checks (e.g. out-of-range keyframes).")
|
|
@@ -217,3 +190,4 @@ def init(dir_path: Path) -> None:
|
|
|
217
190
|
|
|
218
191
|
cli.add_command(errors_command)
|
|
219
192
|
cli.add_command(introspect)
|
|
193
|
+
cli.add_command(schema)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""``scrolly schema`` — show source-file and slide-element schemas from the CLI.
|
|
2
|
+
|
|
3
|
+
A Click group with two parallel subcommands, mirroring the
|
|
4
|
+
subcommand-group structure of ``scrolly introspect``:
|
|
5
|
+
|
|
6
|
+
* ``scrolly schema`` — combined index of file and element schemas.
|
|
7
|
+
* ``scrolly schema file`` — index of source-file schemas (deck, slide).
|
|
8
|
+
* ``scrolly schema file <type>`` — JSON Schema for a source-file type.
|
|
9
|
+
* ``scrolly schema file --list-types`` — bare file-type names, one per line.
|
|
10
|
+
* ``scrolly schema element`` — index of element schemas.
|
|
11
|
+
* ``scrolly schema element <type>`` — JSON Schema for an element type.
|
|
12
|
+
* ``scrolly schema element --list-types`` — bare element keys, one per line.
|
|
13
|
+
|
|
14
|
+
``schema`` shows static *type* definitions; ``introspect`` inspects a
|
|
15
|
+
specific *resolved deck instance* — different surfaces, kept distinct.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
import click
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
|
|
26
|
+
_err_console = Console(stderr=True, highlight=False)
|
|
27
|
+
|
|
28
|
+
# Width of the name / suffix columns in the human-readable index, matching
|
|
29
|
+
# the alignment used by ``scrolly errors``.
|
|
30
|
+
_NAME_COL = 17
|
|
31
|
+
_SUFFIX_COL = 24
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# ==================================================================================================
|
|
35
|
+
# schema group
|
|
36
|
+
# ==================================================================================================
|
|
37
|
+
@click.group(name="schema", invoke_without_command=True)
|
|
38
|
+
@click.pass_context
|
|
39
|
+
def schema(ctx: click.Context) -> None:
|
|
40
|
+
"""Show source-file and slide-element schemas.
|
|
41
|
+
|
|
42
|
+
\b
|
|
43
|
+
scrolly schema → combined index (file + element schemas)
|
|
44
|
+
scrolly schema file [<type>] → source-file schemas (deck, slide)
|
|
45
|
+
scrolly schema element [<type>] → slide-element schemas (markdown, image, …)
|
|
46
|
+
|
|
47
|
+
Append --list-types to either subcommand for bare names (agent / scripting).
|
|
48
|
+
Shows static type definitions; use `scrolly introspect` for a resolved deck.
|
|
49
|
+
"""
|
|
50
|
+
if ctx.invoked_subcommand is None:
|
|
51
|
+
_print_file_index()
|
|
52
|
+
click.echo()
|
|
53
|
+
_print_element_index()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# --------------------------------------------------------------------------
|
|
57
|
+
# Subcommands
|
|
58
|
+
# --------------------------------------------------------------------------
|
|
59
|
+
@schema.command(name="file")
|
|
60
|
+
@click.argument("type_name", required=False)
|
|
61
|
+
@click.option(
|
|
62
|
+
"--list-types",
|
|
63
|
+
"list_types",
|
|
64
|
+
is_flag=True,
|
|
65
|
+
help="Print bare file-type names one per line (no descriptions) for scripting use.",
|
|
66
|
+
)
|
|
67
|
+
def schema_file(type_name: str | None, list_types: bool) -> None:
|
|
68
|
+
"""Source-file schemas (deck, slide).
|
|
69
|
+
|
|
70
|
+
\b
|
|
71
|
+
scrolly schema file → formatted index of file types
|
|
72
|
+
scrolly schema file <type> → JSON Schema for <type>
|
|
73
|
+
scrolly schema file --list-types → bare type names, one per line (agent / scripting)
|
|
74
|
+
"""
|
|
75
|
+
names = file_type_names()
|
|
76
|
+
|
|
77
|
+
if list_types:
|
|
78
|
+
for name in names:
|
|
79
|
+
click.echo(name)
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
if type_name is None:
|
|
83
|
+
_print_file_index()
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
schema_text = file_schema_json(type_name)
|
|
87
|
+
if schema_text is None:
|
|
88
|
+
_err_console.print(f"[red]error:[/red] unknown file type '{type_name}' (known: {', '.join(names)})")
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
click.echo(schema_text)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@schema.command(name="element")
|
|
94
|
+
@click.argument("type_name", required=False)
|
|
95
|
+
@click.option(
|
|
96
|
+
"--list-types",
|
|
97
|
+
"list_types",
|
|
98
|
+
is_flag=True,
|
|
99
|
+
help="Print bare element keys one per line (no descriptions) for scripting use.",
|
|
100
|
+
)
|
|
101
|
+
def schema_element(type_name: str | None, list_types: bool) -> None:
|
|
102
|
+
"""Slide-element schemas (markdown, image, …).
|
|
103
|
+
|
|
104
|
+
\b
|
|
105
|
+
scrolly schema element → formatted index of element types
|
|
106
|
+
scrolly schema element <type> → JSON Schema for <type>
|
|
107
|
+
scrolly schema element --list-types → bare element keys, one per line (agent / scripting)
|
|
108
|
+
"""
|
|
109
|
+
from scrolly.slide import element_source_types
|
|
110
|
+
|
|
111
|
+
elements = element_source_types()
|
|
112
|
+
|
|
113
|
+
if list_types:
|
|
114
|
+
for key in elements:
|
|
115
|
+
click.echo(key)
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
if type_name is None:
|
|
119
|
+
_print_element_index()
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
schema_text = element_schema_json(type_name)
|
|
123
|
+
if schema_text is None:
|
|
124
|
+
_err_console.print(f"[red]error:[/red] unknown element type '{type_name}' (known: {', '.join(elements)})")
|
|
125
|
+
sys.exit(1)
|
|
126
|
+
click.echo(schema_text)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# --------------------------------------------------------------------------
|
|
130
|
+
# Schema lookup + index rendering
|
|
131
|
+
# --------------------------------------------------------------------------
|
|
132
|
+
def file_type_names() -> list[str]:
|
|
133
|
+
"""Return the sorted source-file type names (deck + registered slide types)."""
|
|
134
|
+
from scrolly.slide import registered_ir_types
|
|
135
|
+
|
|
136
|
+
return sorted(["deck", *registered_ir_types()])
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _file_schema(type_name: str) -> dict | None:
|
|
140
|
+
"""Return the JSON Schema for a source-file type, or ``None`` if unknown."""
|
|
141
|
+
from scrolly.deck import deck_source_schema
|
|
142
|
+
from scrolly.slide import registered_ir_types
|
|
143
|
+
|
|
144
|
+
if type_name == "deck":
|
|
145
|
+
return deck_source_schema()
|
|
146
|
+
ir_types = registered_ir_types()
|
|
147
|
+
if type_name in ir_types:
|
|
148
|
+
return ir_types[type_name].source_schema()
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def file_schema_json(type_name: str) -> str | None:
|
|
153
|
+
"""Render a source-file type's JSON Schema as indented JSON text, or ``None`` if unknown."""
|
|
154
|
+
schema_dict = _file_schema(type_name)
|
|
155
|
+
return None if schema_dict is None else json.dumps(schema_dict, indent=2)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def element_schema_json(type_name: str) -> str | None:
|
|
159
|
+
"""Render an element type's JSON Schema as indented JSON text, or ``None`` if unknown."""
|
|
160
|
+
from scrolly.slide import element_source_types
|
|
161
|
+
|
|
162
|
+
elements = element_source_types()
|
|
163
|
+
if type_name not in elements:
|
|
164
|
+
return None
|
|
165
|
+
return json.dumps(elements[type_name].source_schema(), indent=2)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _print_file_index() -> None:
|
|
169
|
+
"""Print the human-readable index of source-file schemas."""
|
|
170
|
+
from scrolly.slide import registered_ir_types
|
|
171
|
+
|
|
172
|
+
click.echo("File schemas (source files):\n")
|
|
173
|
+
click.echo(f" {'deck':<{_NAME_COL}}{'.deck.json':<{_SUFFIX_COL}}Deck structure (slides + edges)")
|
|
174
|
+
for name, cls in sorted(registered_ir_types().items()):
|
|
175
|
+
click.echo(f" {name:<{_NAME_COL}}{cls.SUFFIX:<{_SUFFIX_COL}}{cls.DESCRIPTION}")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _print_element_index() -> None:
|
|
179
|
+
"""Print the human-readable index of slide-element schemas."""
|
|
180
|
+
from scrolly.slide import element_source_types
|
|
181
|
+
|
|
182
|
+
click.echo("Element schemas (slide elements):\n")
|
|
183
|
+
for key, cls in element_source_types().items():
|
|
184
|
+
click.echo(f" {key:<{_NAME_COL}}{cls.DESCRIPTION}")
|
|
@@ -14,5 +14,5 @@ require `title` and `elements`; per-slide entries in a deck require
|
|
|
14
14
|
|
|
15
15
|
## How to fix
|
|
16
16
|
|
|
17
|
-
Add the missing field. Run `scrolly schema deck` or `scrolly schema
|
|
18
|
-
slide` to see the full required
|
|
17
|
+
Add the missing field. Run `scrolly schema file deck` or `scrolly schema
|
|
18
|
+
file slide` to see the full required schema for each file type.
|
|
@@ -17,5 +17,5 @@ path embedded in the error message.
|
|
|
17
17
|
## How to fix
|
|
18
18
|
|
|
19
19
|
Read the embedded Pydantic message — it names the field path and the
|
|
20
|
-
constraint that failed. Cross-reference with `scrolly schema slide`
|
|
21
|
-
for the expected
|
|
20
|
+
constraint that failed. Cross-reference with `scrolly schema file slide`
|
|
21
|
+
for the expected schema of the slide source.
|
|
@@ -13,5 +13,6 @@ An element object with no recognised type field — no `markdown:`,
|
|
|
13
13
|
|
|
14
14
|
## How to fix
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Run `scrolly schema element --list-types` to see the valid element
|
|
17
|
+
types, then `scrolly schema element <type>` for one's fields. Each
|
|
18
|
+
element must include the field that names its type.
|
|
@@ -1023,7 +1023,7 @@ body.pan-transitioning .canvas {
|
|
|
1023
1023
|
left: 0;
|
|
1024
1024
|
width: 100%;
|
|
1025
1025
|
height: 100%;
|
|
1026
|
-
background: rgba(
|
|
1026
|
+
background: rgba(200, 200, 200, 0.5);
|
|
1027
1027
|
backdrop-filter: blur(16px);
|
|
1028
1028
|
-webkit-backdrop-filter: blur(16px);
|
|
1029
1029
|
}
|