# Architecture
`nbprint` is a collection of [`pydantic`](https://docs.pydantic.dev/latest/) models to take or construct a Jupyter notebook from
a set of standard parts, execute it with [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/), and convert it to `html` or `pdf`
with a standard template optionally running [`pagedjs`](https://pagedjs.org) to provide a print-oriented layout.
It can be run off an existing notebook, or using the provided [YAML-based configuration framework](./configuration.md).
```mermaid
graph TB
nb("notebook
(.ipynb)")
nbc{nbconvert}
nbct[/nbprint
template/]
pjs[/paged.js
layout engine/]
o@{ shape: doc, label: "output (html,pdf,etc)" }
nb e2@--->nbc
e2@{animate: true}
nbct --> nbc
pjs --- nbct
nbc e3@-->o
e3@{animate: true}
```
## Components
`nbprint` provides a core `Configuration` object with parameters for controlling:
- `Parameters`: input parameters (like [papermill](https://github.com/nteract/papermill))
- `Outputs`: output assets, generally using `nbconvert` to create an `html` or `pdf` document
- `Page`: print-media specific page elements, like header/footer, page numbers, etc
- `Context`: a shared object instantiated in our notebook and passed to every content cell.
This allows us to represent notebook "state" as a typed `pydantic` model.
- `Content`: a structured object representing the actual cells in our notebook
### `Configuration`
```mermaid
graph LR
subgraph Configuration
pfile@{ shape: doc, label: "Parameters file
(json,jsonl,CLI)" }
paramyaml>yaml]
param["Parameters"]
configyaml> yaml]
config["Configuration"]
ctxyaml>yaml]
ctx["Context"]
pageyaml>yaml]
page["Page"]
cntyaml>yaml]
cnt["Content"]
nb@{ shape: doc, label: "Existing Notebook
(.ipynb)" }
outyaml>yaml]
out["Outputs"]
end
subgraph Notebook
pcell(Parameters Cell)
configcell(Configuration Cell)
pagecell(Page Cell)
ctxcell(Context Cell)
contentcell("Content Cell/s")
outputcell(Outputs Cell)
end
paramyaml eparamyamlparam@---> param
eparamyamlparam@{animate: true}
pfile epfileparam@--->param
epfileparam@{animate: true}
param --> config
ctxyaml ectxyamlctx@---> ctx
ectxyamlctx@{animate: true}
ctx --> config
pageyaml epageyamlpage@---> page
epageyamlpage@{animate: true}
page --> config
nb enbcnt@--->cnt
enbcnt@{animate: true}
cntyaml ecntyamlcnt@---> cnt
ecntyamlcnt@{animate: true}
cnt --> config
outyaml eoutyamlout@---> out
eoutyamlout@{animate: true}
out --> config
configyaml econfigyamlconfig@---> config
econfigyamlconfig@{animate: true}
pcell---configcell
configcell---pagecell
pagecell---ctxcell
ctxcell---contentcell
contentcell --- outputcell
subgraph Output
o@{ shape: doc, label: "output (html,pdf,etc)" }
end
post(Post Processing)
Configuration --> Notebook
Notebook --> Output
Output eOutputPosProcessing@---> post
eOutputPosProcessing@{animate: true}
```
### `Parameters`
Parameters are the first cell of a notebook, and can be passed in during execution to allow for parameterized notebooks.
We provide the following builtin versions:
#### `PapermillParameters`
> `hydra` config: `nbprint/parameters/papermill`
This is a basic object that takes any basic json-serializeable type and provides it in assignment as the first cell.
As an example, the following `YAML`:
```yaml
# @package nbprint.parameters
_target_: nbprint.PapermillParameters
a: abc
b: 1.2
c: true
```
Would result in the following cell:
```python
a = "abc"
b = 1.2
c = True
```
### `Page`
### `Context`
Context is used to wrap variables local to the notebook.
The best documentation is a simple example in YAML form:
```yaml
---
_target_: nbprint.Configuration
context:
_target_: nbprint.example.ExampleContext
content:
- _target_: nbprint.ContentCode
content: |
nbprint_ctx.string = string
- _target_: nbprint.ContentCode
content: |
print(nbprint_ctx.string)
```
This will create two `ContentCode` instances, where one sets a value `string` on the `ExampleContext` instance and the other reads it.
You can of course rely on notebook-global variables, but relying on typed contexts makes it easier to build modular reports.
### `Content`
`Content` is the basic form of displayable content.
It can be used to wrap any generic functionality or Markdown content.
It can also be convenient to reuse display configuration.
Content has a few key attributes:
- `Content.content`: string text content, or a `list[Content]` of subcontent for layout elements
- `Content.style`: A `Style` element based on CSS for styling this content
- `css`: Generic string content to be injected into a `