deckicorn 0.2.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 (44) hide show
  1. deckicorn-0.2.0/PKG-INFO +97 -0
  2. deckicorn-0.2.0/README.md +72 -0
  3. deckicorn-0.2.0/pyproject.toml +59 -0
  4. deckicorn-0.2.0/setup.cfg +4 -0
  5. deckicorn-0.2.0/src/deckicorn.egg-info/PKG-INFO +97 -0
  6. deckicorn-0.2.0/src/deckicorn.egg-info/SOURCES.txt +42 -0
  7. deckicorn-0.2.0/src/deckicorn.egg-info/dependency_links.txt +1 -0
  8. deckicorn-0.2.0/src/deckicorn.egg-info/entry_points.txt +2 -0
  9. deckicorn-0.2.0/src/deckicorn.egg-info/requires.txt +19 -0
  10. deckicorn-0.2.0/src/deckicorn.egg-info/top_level.txt +5 -0
  11. deckicorn-0.2.0/src/deckicorn_cli/main.py +155 -0
  12. deckicorn-0.2.0/src/deckicorn_md/__init__.py +12 -0
  13. deckicorn-0.2.0/src/deckicorn_md/compiler.py +286 -0
  14. deckicorn-0.2.0/src/deckicorn_md/parser.py +161 -0
  15. deckicorn-0.2.0/src/deckicorn_project/__init__.py +15 -0
  16. deckicorn-0.2.0/src/deckicorn_project/manifest.py +157 -0
  17. deckicorn-0.2.0/src/deckicorn_project/packaging.py +183 -0
  18. deckicorn-0.2.0/src/deckicorn_project/pyinstaller/hooks/hook-arcade.py +54 -0
  19. deckicorn-0.2.0/src/deckicorn_runtime/__init__.py +11 -0
  20. deckicorn-0.2.0/src/deckicorn_runtime/arcade_app.py +270 -0
  21. deckicorn-0.2.0/src/deckicorn_runtime/bounds_overlay.py +116 -0
  22. deckicorn-0.2.0/src/deckicorn_runtime/console.py +51 -0
  23. deckicorn-0.2.0/src/deckicorn_runtime/coords.py +73 -0
  24. deckicorn-0.2.0/src/deckicorn_runtime/navigation.py +76 -0
  25. deckicorn-0.2.0/src/deckicorn_runtime/preview_options.py +146 -0
  26. deckicorn-0.2.0/src/deckicorn_runtime/resources.py +26 -0
  27. deckicorn-0.2.0/src/deckicorn_spec/__init__.py +22 -0
  28. deckicorn-0.2.0/src/deckicorn_spec/io.py +50 -0
  29. deckicorn-0.2.0/src/deckicorn_spec/models.py +184 -0
  30. deckicorn-0.2.0/src/deckicorn_spec/validate.py +100 -0
  31. deckicorn-0.2.0/tests/test_cli_project.py +11 -0
  32. deckicorn-0.2.0/tests/test_compiler.py +40 -0
  33. deckicorn-0.2.0/tests/test_packaging.py +31 -0
  34. deckicorn-0.2.0/tests/test_preview_options.py +82 -0
  35. deckicorn-0.2.0/tests/test_project_manifest.py +80 -0
  36. deckicorn-0.2.0/tests/test_registry_publish.py +50 -0
  37. deckicorn-0.2.0/tests/test_release_ci_gates.py +54 -0
  38. deckicorn-0.2.0/tests/test_release_version.py +39 -0
  39. deckicorn-0.2.0/tests/test_runtime.py +19 -0
  40. deckicorn-0.2.0/tests/test_runtime_coords.py +50 -0
  41. deckicorn-0.2.0/tests/test_runtime_navigation.py +38 -0
  42. deckicorn-0.2.0/tests/test_spec_models.py +110 -0
  43. deckicorn-0.2.0/tests/test_verify_release_ready.py +29 -0
  44. deckicorn-0.2.0/tests/test_verify_release_version.py +37 -0
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: deckicorn
3
+ Version: 0.2.0
4
+ Summary: Spec-driven presentation runtime
5
+ Project-URL: Documentation, https://deckicorn.org
6
+ Project-URL: Repository, https://gitlab.com/libesys/deckicorn/deckicorn-cli
7
+ Project-URL: Changelog, https://deckicorn.org/blog
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: PyYAML>=6.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pre-commit>=4.0; extra == "dev"
14
+ Requires-Dist: pytest>=8.0; extra == "dev"
15
+ Requires-Dist: ruff>=0.8; extra == "dev"
16
+ Requires-Dist: build>=1.0; extra == "dev"
17
+ Requires-Dist: twine>=5.0; extra == "dev"
18
+ Provides-Extra: docs
19
+ Requires-Dist: sphinx>=7.4; extra == "docs"
20
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
21
+ Provides-Extra: runtime
22
+ Requires-Dist: arcade<4,>=3.0; extra == "runtime"
23
+ Provides-Extra: packaging
24
+ Requires-Dist: pyinstaller>=6.0; extra == "packaging"
25
+
26
+ # Deckicorn
27
+
28
+ Spec-driven presentation runtime: compile Markdown decks + layout YAML into a canonical presentation spec, then render with a 2D (Arcade) runtime.
29
+
30
+ ## Documentation
31
+
32
+ - **Public site:** [deckicorn.org](https://deckicorn.org) (Docusaurus + Sphinx API reference)
33
+ - ADR overview: [`docs/README-deckicorn-adr.md`](docs/README-deckicorn-adr.md)
34
+ - Presentation spec: [`docs/SPEC-presentation-spec.md`](docs/SPEC-presentation-spec.md)
35
+ - Deckicorn MD dialect: [`docs/SPEC-deckicorn-md-dialect.md`](docs/SPEC-deckicorn-md-dialect.md)
36
+ - Deck project manifest: [`docs/SPEC-deckicorn-project-manifest.md`](docs/SPEC-deckicorn-project-manifest.md)
37
+ - Implementation plan: [`plan/deckicorn-implementation-plan.md`](plan/deckicorn-implementation-plan.md)
38
+ - AI workflow rules: [`tools/ai-rules/`](tools/ai-rules/)
39
+
40
+ ## Git workflow
41
+
42
+ Day-to-day work happens on **`develop`**; **`master`** is ff-merged when Development CI is green (A2C `development-workflow.md`).
43
+
44
+ ```bash
45
+ git checkout develop
46
+ ```
47
+
48
+ ## Quick start
49
+
50
+ ```bash
51
+ pip install -e ".[dev]"
52
+ pre-commit install
53
+ pre-commit install --hook-type commit-msg
54
+ ```
55
+
56
+ From a deck project directory (see `examples/deckicorn-hello/deckicorn.yaml`):
57
+
58
+ ```bash
59
+ cd examples/deckicorn-hello
60
+ deckicorn build
61
+ deckicorn preview # requires pip install -e ".[runtime]"
62
+ deckicorn preview --show-bounds
63
+ deckicorn package --clean # requires pip install -e ".[runtime,packaging]"
64
+ ```
65
+
66
+ Ad hoc paths (without `deckicorn.yaml`):
67
+
68
+ ```bash
69
+ deckicorn build examples/deckicorn-hello/deck.md \
70
+ --layout examples/deckicorn-hello/layout-default.yaml \
71
+ --out examples/deckicorn-hello/build/deck-spec.yaml
72
+ deckicorn run examples/deckicorn-hello/build/deck-spec.yaml
73
+ ```
74
+
75
+ ## Changelog and pre-commit
76
+
77
+ This repository follows A2C changelog policy (`tools/ai-rules/rules/11-changelog-policy.md`):
78
+
79
+ - Maintain `CHANGELOG.md` in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
80
+ - Curate `## [Unreleased]` as release-relevant work lands.
81
+ - Stage `CHANGELOG.md` with any commit that changes other files (`check-changelog` hook).
82
+
83
+ Version source: root `VERSION` (kept in sync with `pyproject.toml` and `deckicorn_spec.__version__` at release time).
84
+
85
+ Release workflow: [docs/release-pipeline.md](docs/release-pipeline.md).
86
+
87
+ ## Project layout
88
+
89
+ | Path | Purpose |
90
+ |------|---------|
91
+ | `docs/` | ADRs and specs (canonical) |
92
+ | `inputs/` | Read-only intake copies of source docs |
93
+ | `deckicorn-spec` (`src/deckicorn_spec`) | Presentation spec models and validation |
94
+ | `deckicorn-md` (`src/deckicorn_md`) | Deckicorn MD parser and compiler |
95
+ | `deckicorn-runtime` (`src/deckicorn_runtime`) | Presentation runtime |
96
+ | `examples/` | Documented deck projects (`deckicorn-hello/`, …) |
97
+ | `tests/fixtures/decks/` | Broken manifest fixtures for CI and unit tests |
@@ -0,0 +1,72 @@
1
+ # Deckicorn
2
+
3
+ Spec-driven presentation runtime: compile Markdown decks + layout YAML into a canonical presentation spec, then render with a 2D (Arcade) runtime.
4
+
5
+ ## Documentation
6
+
7
+ - **Public site:** [deckicorn.org](https://deckicorn.org) (Docusaurus + Sphinx API reference)
8
+ - ADR overview: [`docs/README-deckicorn-adr.md`](docs/README-deckicorn-adr.md)
9
+ - Presentation spec: [`docs/SPEC-presentation-spec.md`](docs/SPEC-presentation-spec.md)
10
+ - Deckicorn MD dialect: [`docs/SPEC-deckicorn-md-dialect.md`](docs/SPEC-deckicorn-md-dialect.md)
11
+ - Deck project manifest: [`docs/SPEC-deckicorn-project-manifest.md`](docs/SPEC-deckicorn-project-manifest.md)
12
+ - Implementation plan: [`plan/deckicorn-implementation-plan.md`](plan/deckicorn-implementation-plan.md)
13
+ - AI workflow rules: [`tools/ai-rules/`](tools/ai-rules/)
14
+
15
+ ## Git workflow
16
+
17
+ Day-to-day work happens on **`develop`**; **`master`** is ff-merged when Development CI is green (A2C `development-workflow.md`).
18
+
19
+ ```bash
20
+ git checkout develop
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ ```bash
26
+ pip install -e ".[dev]"
27
+ pre-commit install
28
+ pre-commit install --hook-type commit-msg
29
+ ```
30
+
31
+ From a deck project directory (see `examples/deckicorn-hello/deckicorn.yaml`):
32
+
33
+ ```bash
34
+ cd examples/deckicorn-hello
35
+ deckicorn build
36
+ deckicorn preview # requires pip install -e ".[runtime]"
37
+ deckicorn preview --show-bounds
38
+ deckicorn package --clean # requires pip install -e ".[runtime,packaging]"
39
+ ```
40
+
41
+ Ad hoc paths (without `deckicorn.yaml`):
42
+
43
+ ```bash
44
+ deckicorn build examples/deckicorn-hello/deck.md \
45
+ --layout examples/deckicorn-hello/layout-default.yaml \
46
+ --out examples/deckicorn-hello/build/deck-spec.yaml
47
+ deckicorn run examples/deckicorn-hello/build/deck-spec.yaml
48
+ ```
49
+
50
+ ## Changelog and pre-commit
51
+
52
+ This repository follows A2C changelog policy (`tools/ai-rules/rules/11-changelog-policy.md`):
53
+
54
+ - Maintain `CHANGELOG.md` in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
55
+ - Curate `## [Unreleased]` as release-relevant work lands.
56
+ - Stage `CHANGELOG.md` with any commit that changes other files (`check-changelog` hook).
57
+
58
+ Version source: root `VERSION` (kept in sync with `pyproject.toml` and `deckicorn_spec.__version__` at release time).
59
+
60
+ Release workflow: [docs/release-pipeline.md](docs/release-pipeline.md).
61
+
62
+ ## Project layout
63
+
64
+ | Path | Purpose |
65
+ |------|---------|
66
+ | `docs/` | ADRs and specs (canonical) |
67
+ | `inputs/` | Read-only intake copies of source docs |
68
+ | `deckicorn-spec` (`src/deckicorn_spec`) | Presentation spec models and validation |
69
+ | `deckicorn-md` (`src/deckicorn_md`) | Deckicorn MD parser and compiler |
70
+ | `deckicorn-runtime` (`src/deckicorn_runtime`) | Presentation runtime |
71
+ | `examples/` | Documented deck projects (`deckicorn-hello/`, …) |
72
+ | `tests/fixtures/decks/` | Broken manifest fixtures for CI and unit tests |
@@ -0,0 +1,59 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "deckicorn"
7
+ version = "0.2.0"
8
+ description = "Spec-driven presentation runtime"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ dependencies = [
12
+ "pydantic>=2.0",
13
+ "PyYAML>=6.0",
14
+ ]
15
+
16
+ [project.urls]
17
+ Documentation = "https://deckicorn.org"
18
+ Repository = "https://gitlab.com/libesys/deckicorn/deckicorn-cli"
19
+ Changelog = "https://deckicorn.org/blog"
20
+
21
+ [project.optional-dependencies]
22
+ dev = [
23
+ "pre-commit>=4.0",
24
+ "pytest>=8.0",
25
+ "ruff>=0.8",
26
+ "build>=1.0",
27
+ "twine>=5.0",
28
+ ]
29
+ docs = [
30
+ "sphinx>=7.4",
31
+ "sphinx-rtd-theme>=2.0",
32
+ ]
33
+ runtime = [
34
+ "arcade>=3.0,<4",
35
+ ]
36
+ packaging = [
37
+ "pyinstaller>=6.0",
38
+ ]
39
+
40
+ [tool.ruff]
41
+ target-version = "py311"
42
+ line-length = 100
43
+ src = ["src", "tests"]
44
+
45
+ [tool.ruff.lint]
46
+ select = ["E", "F", "I", "UP"]
47
+
48
+ [tool.ruff.format]
49
+ quote-style = "double"
50
+
51
+ [project.scripts]
52
+ deckicorn = "deckicorn_cli.main:main"
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
56
+
57
+ [tool.pytest.ini_options]
58
+ testpaths = ["tests"]
59
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: deckicorn
3
+ Version: 0.2.0
4
+ Summary: Spec-driven presentation runtime
5
+ Project-URL: Documentation, https://deckicorn.org
6
+ Project-URL: Repository, https://gitlab.com/libesys/deckicorn/deckicorn-cli
7
+ Project-URL: Changelog, https://deckicorn.org/blog
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: PyYAML>=6.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pre-commit>=4.0; extra == "dev"
14
+ Requires-Dist: pytest>=8.0; extra == "dev"
15
+ Requires-Dist: ruff>=0.8; extra == "dev"
16
+ Requires-Dist: build>=1.0; extra == "dev"
17
+ Requires-Dist: twine>=5.0; extra == "dev"
18
+ Provides-Extra: docs
19
+ Requires-Dist: sphinx>=7.4; extra == "docs"
20
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
21
+ Provides-Extra: runtime
22
+ Requires-Dist: arcade<4,>=3.0; extra == "runtime"
23
+ Provides-Extra: packaging
24
+ Requires-Dist: pyinstaller>=6.0; extra == "packaging"
25
+
26
+ # Deckicorn
27
+
28
+ Spec-driven presentation runtime: compile Markdown decks + layout YAML into a canonical presentation spec, then render with a 2D (Arcade) runtime.
29
+
30
+ ## Documentation
31
+
32
+ - **Public site:** [deckicorn.org](https://deckicorn.org) (Docusaurus + Sphinx API reference)
33
+ - ADR overview: [`docs/README-deckicorn-adr.md`](docs/README-deckicorn-adr.md)
34
+ - Presentation spec: [`docs/SPEC-presentation-spec.md`](docs/SPEC-presentation-spec.md)
35
+ - Deckicorn MD dialect: [`docs/SPEC-deckicorn-md-dialect.md`](docs/SPEC-deckicorn-md-dialect.md)
36
+ - Deck project manifest: [`docs/SPEC-deckicorn-project-manifest.md`](docs/SPEC-deckicorn-project-manifest.md)
37
+ - Implementation plan: [`plan/deckicorn-implementation-plan.md`](plan/deckicorn-implementation-plan.md)
38
+ - AI workflow rules: [`tools/ai-rules/`](tools/ai-rules/)
39
+
40
+ ## Git workflow
41
+
42
+ Day-to-day work happens on **`develop`**; **`master`** is ff-merged when Development CI is green (A2C `development-workflow.md`).
43
+
44
+ ```bash
45
+ git checkout develop
46
+ ```
47
+
48
+ ## Quick start
49
+
50
+ ```bash
51
+ pip install -e ".[dev]"
52
+ pre-commit install
53
+ pre-commit install --hook-type commit-msg
54
+ ```
55
+
56
+ From a deck project directory (see `examples/deckicorn-hello/deckicorn.yaml`):
57
+
58
+ ```bash
59
+ cd examples/deckicorn-hello
60
+ deckicorn build
61
+ deckicorn preview # requires pip install -e ".[runtime]"
62
+ deckicorn preview --show-bounds
63
+ deckicorn package --clean # requires pip install -e ".[runtime,packaging]"
64
+ ```
65
+
66
+ Ad hoc paths (without `deckicorn.yaml`):
67
+
68
+ ```bash
69
+ deckicorn build examples/deckicorn-hello/deck.md \
70
+ --layout examples/deckicorn-hello/layout-default.yaml \
71
+ --out examples/deckicorn-hello/build/deck-spec.yaml
72
+ deckicorn run examples/deckicorn-hello/build/deck-spec.yaml
73
+ ```
74
+
75
+ ## Changelog and pre-commit
76
+
77
+ This repository follows A2C changelog policy (`tools/ai-rules/rules/11-changelog-policy.md`):
78
+
79
+ - Maintain `CHANGELOG.md` in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
80
+ - Curate `## [Unreleased]` as release-relevant work lands.
81
+ - Stage `CHANGELOG.md` with any commit that changes other files (`check-changelog` hook).
82
+
83
+ Version source: root `VERSION` (kept in sync with `pyproject.toml` and `deckicorn_spec.__version__` at release time).
84
+
85
+ Release workflow: [docs/release-pipeline.md](docs/release-pipeline.md).
86
+
87
+ ## Project layout
88
+
89
+ | Path | Purpose |
90
+ |------|---------|
91
+ | `docs/` | ADRs and specs (canonical) |
92
+ | `inputs/` | Read-only intake copies of source docs |
93
+ | `deckicorn-spec` (`src/deckicorn_spec`) | Presentation spec models and validation |
94
+ | `deckicorn-md` (`src/deckicorn_md`) | Deckicorn MD parser and compiler |
95
+ | `deckicorn-runtime` (`src/deckicorn_runtime`) | Presentation runtime |
96
+ | `examples/` | Documented deck projects (`deckicorn-hello/`, …) |
97
+ | `tests/fixtures/decks/` | Broken manifest fixtures for CI and unit tests |
@@ -0,0 +1,42 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/deckicorn.egg-info/PKG-INFO
4
+ src/deckicorn.egg-info/SOURCES.txt
5
+ src/deckicorn.egg-info/dependency_links.txt
6
+ src/deckicorn.egg-info/entry_points.txt
7
+ src/deckicorn.egg-info/requires.txt
8
+ src/deckicorn.egg-info/top_level.txt
9
+ src/deckicorn_cli/main.py
10
+ src/deckicorn_md/__init__.py
11
+ src/deckicorn_md/compiler.py
12
+ src/deckicorn_md/parser.py
13
+ src/deckicorn_project/__init__.py
14
+ src/deckicorn_project/manifest.py
15
+ src/deckicorn_project/packaging.py
16
+ src/deckicorn_project/pyinstaller/hooks/hook-arcade.py
17
+ src/deckicorn_runtime/__init__.py
18
+ src/deckicorn_runtime/arcade_app.py
19
+ src/deckicorn_runtime/bounds_overlay.py
20
+ src/deckicorn_runtime/console.py
21
+ src/deckicorn_runtime/coords.py
22
+ src/deckicorn_runtime/navigation.py
23
+ src/deckicorn_runtime/preview_options.py
24
+ src/deckicorn_runtime/resources.py
25
+ src/deckicorn_spec/__init__.py
26
+ src/deckicorn_spec/io.py
27
+ src/deckicorn_spec/models.py
28
+ src/deckicorn_spec/validate.py
29
+ tests/test_cli_project.py
30
+ tests/test_compiler.py
31
+ tests/test_packaging.py
32
+ tests/test_preview_options.py
33
+ tests/test_project_manifest.py
34
+ tests/test_registry_publish.py
35
+ tests/test_release_ci_gates.py
36
+ tests/test_release_version.py
37
+ tests/test_runtime.py
38
+ tests/test_runtime_coords.py
39
+ tests/test_runtime_navigation.py
40
+ tests/test_spec_models.py
41
+ tests/test_verify_release_ready.py
42
+ tests/test_verify_release_version.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ deckicorn = deckicorn_cli.main:main
@@ -0,0 +1,19 @@
1
+ pydantic>=2.0
2
+ PyYAML>=6.0
3
+
4
+ [dev]
5
+ pre-commit>=4.0
6
+ pytest>=8.0
7
+ ruff>=0.8
8
+ build>=1.0
9
+ twine>=5.0
10
+
11
+ [docs]
12
+ sphinx>=7.4
13
+ sphinx-rtd-theme>=2.0
14
+
15
+ [packaging]
16
+ pyinstaller>=6.0
17
+
18
+ [runtime]
19
+ arcade<4,>=3.0
@@ -0,0 +1,5 @@
1
+ deckicorn_cli
2
+ deckicorn_md
3
+ deckicorn_project
4
+ deckicorn_runtime
5
+ deckicorn_spec
@@ -0,0 +1,155 @@
1
+ """Deckicorn toolchain CLI (ADR-019)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from pathlib import Path
7
+
8
+ from deckicorn_md.compiler import compile_files
9
+ from deckicorn_project.manifest import (
10
+ MANIFEST_NAME,
11
+ ensure_paths_exist,
12
+ load_project,
13
+ resolve_project_root,
14
+ )
15
+ from deckicorn_project.packaging import package_presentation
16
+ from deckicorn_runtime.console import run_presentation_file as run_console_presentation_file
17
+ from deckicorn_runtime.preview_options import add_preview_arguments
18
+ from deckicorn_spec.io import save_presentation_file
19
+
20
+
21
+ def _add_project_arg(parser: argparse.ArgumentParser) -> None:
22
+ parser.add_argument(
23
+ "--project",
24
+ type=Path,
25
+ default=None,
26
+ help="Deck project root containing deckicorn.yaml (default: current directory)",
27
+ )
28
+
29
+
30
+ def _load_resolved(args: argparse.Namespace):
31
+ root = resolve_project_root(args.project)
32
+ return load_project(root)
33
+
34
+
35
+ def _manifest_available(project: Path | None = None) -> bool:
36
+ root = (project or Path.cwd()).resolve()
37
+ return (root / MANIFEST_NAME).is_file()
38
+
39
+
40
+ def _cmd_build(args: argparse.Namespace) -> int:
41
+ if args.md is not None:
42
+ if not args.layout or not args.out:
43
+ raise SystemExit("build requires --layout and --out when not using a deck project")
44
+ md_path = Path(args.md)
45
+ layout_path = Path(args.layout)
46
+ out_path = Path(args.out)
47
+ else:
48
+ project = _load_resolved(args)
49
+ ensure_paths_exist(project)
50
+ md_path = project.content
51
+ layout_path = project.layout
52
+ out_path = project.build_spec
53
+
54
+ presentation = compile_files(md_path, layout_path)
55
+ out_path.parent.mkdir(parents=True, exist_ok=True)
56
+ save_presentation_file(presentation, out_path)
57
+ print(f"Wrote {out_path}")
58
+ return 0
59
+
60
+
61
+ def _cmd_run(args: argparse.Namespace) -> int:
62
+ if args.spec is not None:
63
+ spec_path = Path(args.spec)
64
+ else:
65
+ project = _load_resolved(args)
66
+ ensure_paths_exist(project, need_spec=True)
67
+ spec_path = project.build_spec
68
+
69
+ run_console_presentation_file(str(spec_path))
70
+ return 0
71
+
72
+
73
+ def _cmd_preview(args: argparse.Namespace) -> int:
74
+ from deckicorn_runtime.arcade_app import run_arcade_presentation
75
+ from deckicorn_runtime.preview_options import preview_options_from_args, profile_bounds_defaults
76
+
77
+ bounds_style = profile_bounds_defaults("minimal")
78
+ if args.spec is not None:
79
+ spec_path = Path(args.spec)
80
+ asset_root = spec_path.parent
81
+ else:
82
+ project = _load_resolved(args)
83
+ ensure_paths_exist(project, need_spec=True)
84
+ spec_path = project.build_spec
85
+ asset_root = project.root
86
+ bounds_style = project.preview_bounds
87
+
88
+ options = preview_options_from_args(args, bounds=bounds_style)
89
+ run_arcade_presentation(
90
+ spec_path,
91
+ asset_root=asset_root,
92
+ width=options.width,
93
+ height=options.height,
94
+ show_element_bounds=options.show_bounds,
95
+ bounds_style=options.bounds,
96
+ )
97
+ return 0
98
+
99
+
100
+ def _cmd_package(args: argparse.Namespace) -> int:
101
+ project = _load_resolved(args)
102
+ binary = package_presentation(project, clean=args.clean)
103
+ print(f"Built {binary}")
104
+ return 0
105
+
106
+
107
+ def main(argv: list[str] | None = None) -> int:
108
+ parser = argparse.ArgumentParser(prog="deckicorn", description="Deckicorn toolchain CLI")
109
+ sub = parser.add_subparsers(dest="command", required=True)
110
+
111
+ build = sub.add_parser("build", help="Compile MD + layout into presentation spec YAML")
112
+ build.add_argument("md", nargs="?", help="Deckicorn MD deck file")
113
+ build.add_argument("--layout", help="Layout overlay YAML")
114
+ build.add_argument("--out", help="Output presentation spec YAML")
115
+ _add_project_arg(build)
116
+ build.set_defaults(func=_cmd_build)
117
+
118
+ run = sub.add_parser("run", help="Run a presentation spec (console mode)")
119
+ run.add_argument("spec", nargs="?", help="Presentation spec YAML")
120
+ _add_project_arg(run)
121
+ run.set_defaults(func=_cmd_run)
122
+
123
+ preview = sub.add_parser("preview", help="Preview a presentation spec in an Arcade window")
124
+ preview.add_argument("spec", nargs="?", help="Presentation spec YAML")
125
+ add_preview_arguments(preview)
126
+ _add_project_arg(preview)
127
+ preview.set_defaults(func=_cmd_preview)
128
+
129
+ package = sub.add_parser("package", help="Package a deck project into a standalone executable")
130
+ package.add_argument("--clean", action="store_true", help="Remove prior build artifacts first")
131
+ _add_project_arg(package)
132
+ package.set_defaults(func=_cmd_package)
133
+
134
+ args = parser.parse_args(argv)
135
+
136
+ if args.command == "build" and args.md is None and not _manifest_available(args.project):
137
+ parser.error(
138
+ "build requires a deck MD path, or run from a directory containing deckicorn.yaml "
139
+ "(or pass --project)",
140
+ )
141
+ if (
142
+ args.command in {"run", "preview"}
143
+ and getattr(args, "spec", None) is None
144
+ and not _manifest_available(args.project)
145
+ ):
146
+ parser.error(
147
+ f"{args.command} requires a spec path, or run from a directory containing "
148
+ "deckicorn.yaml (or pass --project)",
149
+ )
150
+
151
+ return args.func(args)
152
+
153
+
154
+ if __name__ == "__main__":
155
+ raise SystemExit(main())
@@ -0,0 +1,12 @@
1
+ """Deckicorn MD parser and compiler (ADR-013)."""
2
+
3
+ from deckicorn_md.compiler import compile_files, compile_presentation
4
+ from deckicorn_md.parser import ContentDeck, parse_deckicorn_md, parse_deckicorn_md_file
5
+
6
+ __all__ = [
7
+ "ContentDeck",
8
+ "compile_files",
9
+ "compile_presentation",
10
+ "parse_deckicorn_md",
11
+ "parse_deckicorn_md_file",
12
+ ]