# sphinxcontrib.h5p.utils.pkg

Tooling that mirrors the H5P ecosystem into a flat-layout monorepo of
Python packages — one per H5P content type — and generates the Sphinx
extension code that exposes each content type as an `rst` directive.

The generator is deliberately mechanical: each library's
`library.json` and `semantics.json` drive the shape of the emitted
Python package. Library-level overrides sit beside the generated
tree and always take precedence at runtime.

This package is used from the
[sphinxcontrib.h5p](https://bitbucket.org/byteb4rb1e/sphinxcontrib.h5p)
monorepo and is not itself a runtime dependency of anything it
emits.

## Naming taxonomy

A single H5P library carries several names through the pipeline.
Each form has a distinct purpose; one determines the next via strict
rules.

| Form         | Example                                     | Role                                                |
| ------------ | ------------------------------------------- | --------------------------------------------------- |
| machine_name | `H5P.MultiChoice`                           | H5P's own identifier, declared in `library.json`    |
| repo_name    | `h5p-multi-choice`                          | Vendor repository slug                              |
| vendor_name  | `h5p-multi-choice`                          | Same as `repo_name`; subdir under `vendor/`         |
| dir_name     | `multi_choice`                              | Leaf directory under the H5P monorepo               |
| pip_name     | `byteb4rb1e.sphinxcontrib.h5p.multi_choice` | PyPA distribution name                              |
| import_name  | `byteb4rb1e.sphinxcontrib.h5p.multi_choice` | Python module path                                  |

`pip_name` and `import_name` happen to coincide because every
generated package uses the PEP 420 namespace layout — but the two
are kept distinct since PyPA distribution names and Python module
paths are not otherwise interchangeable.

The realisations live in `byteb4rb1e.sphinxcontrib.h5p.utils.pkg.index`.

## Package layout

```
<dir_name>/
├── pyproject.toml
├── vendor/<vendor_name>/              # git submodule of upstream H5P lib
├── src/byteb4rb1e/sphinxcontrib/h5p/<dir_name>/
│   ├── __init__.py                    # extension entry point
│   ├── _generated/                    # regenerated by `pkg build`
│   └── _static/                       # vendored assets, copied by build
└── tests/unit/_generated/             # regenerated by `pkg build`
```

Parent directories above the leaf are PEP 420 implicit namespace
packages; only the leaf carries `__init__.py`. Anything under
`_generated/` is owned by the build step.

## Pipeline

Four stages. Each maps to a Make target and an invocable Python
module.

| Stage     | Make target    | Module                              |
| --------- | -------------- | ----------------------------------- |
| mirror    | `mirror-sync`  | `...utils.pkg.h5porg.repository`    |
| index     | `index`        | `...utils.pkg.h5porg.repository`    |
| bootstrap | `bootstrap`    | `...utils.pkg.bootstrap`            |
| build     | `build`        | `...utils.pkg.build`                |

`mirror` clones upstream H5P repos to Bitbucket; `index` walks them
into `data/package-index.json`; `bootstrap` scaffolds one or more
packages (expanding the `preloadedDependencies` closure); `build`
runs inside a scaffolded package to emit the `_generated/` tree.

## How-tos

- [Mirror upstream H5P](docs/howto/mirror-upstream.rst)
- [Add a new content type](docs/howto/add-content-type.rst)
- [Override generated code](docs/howto/override-generated.rst)
- [Maintenance](docs/howto/maintain.rst)

## Related

- [sphinxcontrib.h5p](https://bitbucket.org/byteb4rb1e/sphinxcontrib.h5p)
  — the monorepo this tool scaffolds into.
- [sphinxcontrib.h5p.core](https://bitbucket.org/byteb4rb1e/sphinxcontrib.h5p.core)
  — shared base classes imported by every generated package.
