ymprint 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.
Files changed (92) hide show
  1. ymprint-0.1.0/PKG-INFO +150 -0
  2. ymprint-0.1.0/README.md +132 -0
  3. ymprint-0.1.0/pyproject.toml +34 -0
  4. ymprint-0.1.0/src/ymprint/__init__.py +2 -0
  5. ymprint-0.1.0/src/ymprint/blocks/__init__.py +107 -0
  6. ymprint-0.1.0/src/ymprint/blocks/admonition_block.py +42 -0
  7. ymprint-0.1.0/src/ymprint/blocks/blockstyles.py +340 -0
  8. ymprint-0.1.0/src/ymprint/blocks/code_block.py +25 -0
  9. ymprint-0.1.0/src/ymprint/blocks/code_block_styles.py +558 -0
  10. ymprint-0.1.0/src/ymprint/blocks/hrule_block.py +26 -0
  11. ymprint-0.1.0/src/ymprint/blocks/image_block.py +59 -0
  12. ymprint-0.1.0/src/ymprint/blocks/json_block.py +31 -0
  13. ymprint-0.1.0/src/ymprint/blocks/matplotfig_block.py +68 -0
  14. ymprint-0.1.0/src/ymprint/blocks/page_break_block.py +10 -0
  15. ymprint-0.1.0/src/ymprint/blocks/python_block.py +31 -0
  16. ymprint-0.1.0/src/ymprint/blocks/quote_block.py +25 -0
  17. ymprint-0.1.0/src/ymprint/blocks/slide_block.py +25 -0
  18. ymprint-0.1.0/src/ymprint/blocks/spacer_block.py +10 -0
  19. ymprint-0.1.0/src/ymprint/cli/config.py +15 -0
  20. ymprint-0.1.0/src/ymprint/cli/main.py +144 -0
  21. ymprint-0.1.0/src/ymprint/cli/throbber.py +176 -0
  22. ymprint-0.1.0/src/ymprint/config/__init__.py +3 -0
  23. ymprint-0.1.0/src/ymprint/config/check.ipynb +213 -0
  24. ymprint-0.1.0/src/ymprint/config/config_loaders.py +126 -0
  25. ymprint-0.1.0/src/ymprint/config/defaults/defaults.ymprint.yml +68 -0
  26. ymprint-0.1.0/src/ymprint/config/docstyles.py +115 -0
  27. ymprint-0.1.0/src/ymprint/config/doctablestyles.py +115 -0
  28. ymprint-0.1.0/src/ymprint/config/doctemplate.py +135 -0
  29. ymprint-0.1.0/src/ymprint/config/font_registry.py +84 -0
  30. ymprint-0.1.0/src/ymprint/config/fonts/AppleGaramond/AppleGaramond-Bold.ttf +0 -0
  31. ymprint-0.1.0/src/ymprint/config/fonts/AppleGaramond/AppleGaramond-BoldItalic.ttf +0 -0
  32. ymprint-0.1.0/src/ymprint/config/fonts/AppleGaramond/AppleGaramond-Italic.ttf +0 -0
  33. ymprint-0.1.0/src/ymprint/config/fonts/AppleGaramond/AppleGaramond.ttf +0 -0
  34. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSans/DejaVuSans-Bold.ttf +0 -0
  35. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSans/DejaVuSans-BoldOblique.ttf +0 -0
  36. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSans/DejaVuSans-Oblique.ttf +0 -0
  37. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSans/DejaVuSans.ttf +0 -0
  38. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansCondensed/DejaVuSansCondensed-Bold.ttf +0 -0
  39. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansCondensed/DejaVuSansCondensed-BoldOblique.ttf +0 -0
  40. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansCondensed/DejaVuSansCondensed-Oblique.ttf +0 -0
  41. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansCondensed/DejaVuSansCondensed.ttf +0 -0
  42. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansMono/DejaVuSansMono-Bold.ttf +0 -0
  43. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansMono/DejaVuSansMono-Oblique.ttf +0 -0
  44. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSansMono/DejaVuSansMono.ttf +0 -0
  45. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerif/DejaVuSerif-Bold.ttf +0 -0
  46. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerif/DejaVuSerif-BoldItalic.ttf +0 -0
  47. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerif/DejaVuSerif-Italic.ttf +0 -0
  48. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerif/DejaVuSerif.ttf +0 -0
  49. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerifCondensed/DejaVuSerifCondensed-Bold.ttf +0 -0
  50. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerifCondensed/DejaVuSerifCondensed-BoldItalic.ttf +0 -0
  51. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerifCondensed/DejaVuSerifCondensed-Italic.ttf +0 -0
  52. ymprint-0.1.0/src/ymprint/config/fonts/DejaVuSerifCondensed/DejaVuSerifCondensed.ttf +0 -0
  53. ymprint-0.1.0/src/ymprint/config/fonts/Inter/Inter-Bold.ttf +0 -0
  54. ymprint-0.1.0/src/ymprint/config/fonts/Inter/Inter-BoldItalic.ttf +0 -0
  55. ymprint-0.1.0/src/ymprint/config/fonts/Inter/Inter-Italic.ttf +0 -0
  56. ymprint-0.1.0/src/ymprint/config/fonts/Inter/Inter.ttf +0 -0
  57. ymprint-0.1.0/src/ymprint/config/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  58. ymprint-0.1.0/src/ymprint/config/fonts/Montserrat/Montserrat-BoldItalic.ttf +0 -0
  59. ymprint-0.1.0/src/ymprint/config/fonts/Montserrat/Montserrat-Italic.ttf +0 -0
  60. ymprint-0.1.0/src/ymprint/config/fonts/Montserrat/Montserrat.ttf +0 -0
  61. ymprint-0.1.0/src/ymprint/config/fonts/NotoSans/NotoSans-Bold.ttf +0 -0
  62. ymprint-0.1.0/src/ymprint/config/fonts/NotoSans/NotoSans-BoldItalic.ttf +0 -0
  63. ymprint-0.1.0/src/ymprint/config/fonts/NotoSans/NotoSans-Italic.ttf +0 -0
  64. ymprint-0.1.0/src/ymprint/config/fonts/NotoSans/NotoSans.ttf +0 -0
  65. ymprint-0.1.0/src/ymprint/config/fonts/NotoSerif/NotoSerif-Bold.ttf +0 -0
  66. ymprint-0.1.0/src/ymprint/config/fonts/NotoSerif/NotoSerif-BoldItalic.ttf +0 -0
  67. ymprint-0.1.0/src/ymprint/config/fonts/NotoSerif/NotoSerif-Italic.ttf +0 -0
  68. ymprint-0.1.0/src/ymprint/config/fonts/NotoSerif/NotoSerif.ttf +0 -0
  69. ymprint-0.1.0/src/ymprint/config/fonts/Playfair/Playfair-Bold.ttf +0 -0
  70. ymprint-0.1.0/src/ymprint/config/fonts/Playfair/Playfair-BoldItalic.ttf +0 -0
  71. ymprint-0.1.0/src/ymprint/config/fonts/Playfair/Playfair-Italic.ttf +0 -0
  72. ymprint-0.1.0/src/ymprint/config/fonts/Playfair/Playfair.ttf +0 -0
  73. ymprint-0.1.0/src/ymprint/config/fonts/Poppins/Poppins-Bold.ttf +0 -0
  74. ymprint-0.1.0/src/ymprint/config/fonts/Poppins/Poppins-BoldItalic.ttf +0 -0
  75. ymprint-0.1.0/src/ymprint/config/fonts/Poppins/Poppins-Italic.ttf +0 -0
  76. ymprint-0.1.0/src/ymprint/config/fonts/Poppins/Poppins.ttf +0 -0
  77. ymprint-0.1.0/src/ymprint/config/fonts/Roboto/Roboto-Bold.ttf +0 -0
  78. ymprint-0.1.0/src/ymprint/config/fonts/Roboto/Roboto-BoldItalic.ttf +0 -0
  79. ymprint-0.1.0/src/ymprint/config/fonts/Roboto/Roboto-Italic.ttf +0 -0
  80. ymprint-0.1.0/src/ymprint/config/fonts/Roboto/Roboto.ttf +0 -0
  81. ymprint-0.1.0/src/ymprint/config/helpers.py +36 -0
  82. ymprint-0.1.0/src/ymprint/config/pdf_fill_forms.py +0 -0
  83. ymprint-0.1.0/src/ymprint/config/pdf_postprocessing.py +139 -0
  84. ymprint-0.1.0/src/ymprint/content_checks.py +141 -0
  85. ymprint-0.1.0/src/ymprint/content_converters.py +107 -0
  86. ymprint-0.1.0/src/ymprint/context_builder.py +70 -0
  87. ymprint-0.1.0/src/ymprint/exceptions.py +2 -0
  88. ymprint-0.1.0/src/ymprint/markdown/inline.py +33 -0
  89. ymprint-0.1.0/src/ymprint/notes.yml +20 -0
  90. ymprint-0.1.0/src/ymprint/report_reader.py +84 -0
  91. ymprint-0.1.0/src/ymprint/story_builder.py +72 -0
  92. ymprint-0.1.0/src/ymprint/yaml_loader.py +13 -0
ymprint-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.3
2
+ Name: ymprint
3
+ Version: 0.1.0
4
+ Summary: Desktop publishing in YAML with Python
5
+ Author: Connor Ferster
6
+ Author-email: Connor Ferster <connor@structuralpython.com>
7
+ Requires-Dist: jinja2>=3.1.6
8
+ Requires-Dist: pydantic>=2.13.4
9
+ Requires-Dist: pygments>=2.20.0
10
+ Requires-Dist: pymupdf>=1.27.2.3
11
+ Requires-Dist: pypdf>=6.14.0
12
+ Requires-Dist: reportlab>=4.5.1
13
+ Requires-Dist: ruamel-yaml>=0.19.1
14
+ Requires-Dist: typer>=0.26.7
15
+ Requires-Dist: wenmode>=0.8.0
16
+ Requires-Python: >=3.14
17
+ Description-Content-Type: text/markdown
18
+
19
+ <p align="center">
20
+ <img src="ymprintlogolarge.png" alt="YMPrint" width="420">
21
+ </p>
22
+
23
+ <h3 align="center">Desktop publishing with YAML</h3>
24
+ <p align="center"><em>The technology of the year 2000…today!</em></p>
25
+
26
+ YMPrint is a Python-based PDF authoring application geared towards professionals who need to
27
+ generate lots of PDF documents. You write the content of your report in YAML (as opposed to
28
+ Markdown) and YMPrint renders it to PDF with near-instant speeds. YMPrint lets you use Python
29
+ scripting within your document, create variables, render variable values, and pass live
30
+ Python objects between report **blocks** to create a truly expressive authoring
31
+ system—the likes of which have not been created before.
32
+
33
+ ```yaml
34
+ Site inspection report:
35
+ - >
36
+ This is the first paragraph. The `>` character tells YAML you are entering a
37
+ multi-line string that should be word-wrapped. Leave a blank line to start a
38
+ new paragraph.
39
+ - Findings:
40
+ - Bullets:
41
+ - The handrail is loose on the north stair.
42
+ - Two ceiling tiles are water-stained in the lobby.
43
+ - Items observed:
44
+ - Item Number: 12.01
45
+ Description: There is a problem here. This report documents it.
46
+ Location: Under the stairs
47
+ ```
48
+
49
+ ```bash
50
+ ym convert report.yml
51
+ # ✍️ .... 📝 ... PDF created: report.pdf
52
+ ```
53
+
54
+ ## Why YMPrint?
55
+
56
+ - **Readable source.** Your document *is* the outline. YAML nesting is the document
57
+ hierarchy — no markup soup, no LaTeX, no HTML.
58
+ - **Batteries included.** Bundled fonts, sensible default styles, and a set of blocks for
59
+ the content markdown can't express.
60
+ - **Dynamic content.** Interpolate variables with Jinja, execute `_py` blocks, load JSON,
61
+ embed matplotlib figures, and auto-fill PDF form fields.
62
+ - **Custom templates.** Overlay your document onto a designed PDF background and
63
+ auto-populate its form fields from document variables.
64
+
65
+ ## Installation
66
+
67
+ Requires **Python 3.14+**.
68
+
69
+ ```bash
70
+ # With uv (recommended) — installs the `ym` command
71
+ uv tool install ymprint
72
+
73
+ # Or with pip
74
+ pip install ymprint
75
+ ```
76
+
77
+ From source:
78
+
79
+ ```bash
80
+ git clone https://github.com/StructuralPython/yamlreports.git
81
+ cd yamlreports
82
+ uv sync
83
+ uv run ym --help
84
+ ```
85
+
86
+ ## Usage
87
+
88
+ YMPrint installs a single command, `ym`, with two subcommands.
89
+
90
+ ### `ym convert` — render once
91
+
92
+ ```bash
93
+ ym convert report.yml # writes report.pdf next to the source
94
+ ym convert report.yml out/doc.pdf # choose an output path
95
+ ```
96
+
97
+ ### `ym live` — hot-reload preview
98
+
99
+ Renders the PDF, opens it in the [Okular](https://okular.kde.org/) viewer, and rebuilds on
100
+ every save. Great for drafting.
101
+
102
+ ```bash
103
+ ym live report.yml
104
+ ```
105
+
106
+ ## Core concepts
107
+
108
+ - **Keys are headings.** A mapping key whose value is content becomes a heading; the value
109
+ is laid out underneath it. Lists render in order, lists of mappings render as tables.
110
+ - **Configuration** lives in underscore-prefixed front matter — `_doc` (page template),
111
+ `_style` (text styles), and `_tablestyle` (table styles) — resolved across three
112
+ inheriting priority levels: internal defaults → project config → document front matter.
113
+ - **Variables** are defined in `_vars`, interpolated into text with Jinja (`{{name}}`), and
114
+ passed as real Python objects into blocks with the `$name` syntax.
115
+ - **Blocks** are underscore-prefixed keys that expand into custom content:
116
+
117
+ | Block | Purpose |
118
+ | --- | --- |
119
+ | `_img` | Embed an image with a caption |
120
+ | `_matplotfig` | Embed a matplotlib figure |
121
+ | `_info` / `_warning` / `_danger` / `_tip` / `_note` | Admonition callouts |
122
+ | `_blockquote` | A quotation with attribution |
123
+ | `_code` | A non-executable, syntax-highlighted code block |
124
+ | `_py` | Execute Python and optionally show the source |
125
+ | `_loadjson` | Load variables from a JSON file |
126
+ | `_pagebreak` | Force a page break |
127
+ | `_hrule` | A configurable horizontal rule |
128
+ | `_spacer` | Insert vertical whitespace |
129
+
130
+ ## Examples
131
+
132
+ The [`Examples/`](Examples) directory contains a runnable report for each major feature —
133
+ a simple document, document configuration, variables, PDF backgrounds, Python execution,
134
+ and the full set of blocks. Render any of them with `ym convert`.
135
+
136
+ ## Documentation
137
+
138
+ The full documentation site lives in [`docs/`](docs) (Sphinx + the Shibuya theme). Build it
139
+ locally with:
140
+
141
+ ```bash
142
+ uv run --with-requirements docs/requirements.txt \
143
+ sphinx-build -b html docs docs/_build/html
144
+ ```
145
+
146
+ Then open `docs/_build/html/index.html`. See [`docs/README.md`](docs/README.md) for details.
147
+
148
+ ## License
149
+
150
+ See [LICENSE](LICENSE).
@@ -0,0 +1,132 @@
1
+ <p align="center">
2
+ <img src="ymprintlogolarge.png" alt="YMPrint" width="420">
3
+ </p>
4
+
5
+ <h3 align="center">Desktop publishing with YAML</h3>
6
+ <p align="center"><em>The technology of the year 2000…today!</em></p>
7
+
8
+ YMPrint is a Python-based PDF authoring application geared towards professionals who need to
9
+ generate lots of PDF documents. You write the content of your report in YAML (as opposed to
10
+ Markdown) and YMPrint renders it to PDF with near-instant speeds. YMPrint lets you use Python
11
+ scripting within your document, create variables, render variable values, and pass live
12
+ Python objects between report **blocks** to create a truly expressive authoring
13
+ system—the likes of which have not been created before.
14
+
15
+ ```yaml
16
+ Site inspection report:
17
+ - >
18
+ This is the first paragraph. The `>` character tells YAML you are entering a
19
+ multi-line string that should be word-wrapped. Leave a blank line to start a
20
+ new paragraph.
21
+ - Findings:
22
+ - Bullets:
23
+ - The handrail is loose on the north stair.
24
+ - Two ceiling tiles are water-stained in the lobby.
25
+ - Items observed:
26
+ - Item Number: 12.01
27
+ Description: There is a problem here. This report documents it.
28
+ Location: Under the stairs
29
+ ```
30
+
31
+ ```bash
32
+ ym convert report.yml
33
+ # ✍️ .... 📝 ... PDF created: report.pdf
34
+ ```
35
+
36
+ ## Why YMPrint?
37
+
38
+ - **Readable source.** Your document *is* the outline. YAML nesting is the document
39
+ hierarchy — no markup soup, no LaTeX, no HTML.
40
+ - **Batteries included.** Bundled fonts, sensible default styles, and a set of blocks for
41
+ the content markdown can't express.
42
+ - **Dynamic content.** Interpolate variables with Jinja, execute `_py` blocks, load JSON,
43
+ embed matplotlib figures, and auto-fill PDF form fields.
44
+ - **Custom templates.** Overlay your document onto a designed PDF background and
45
+ auto-populate its form fields from document variables.
46
+
47
+ ## Installation
48
+
49
+ Requires **Python 3.14+**.
50
+
51
+ ```bash
52
+ # With uv (recommended) — installs the `ym` command
53
+ uv tool install ymprint
54
+
55
+ # Or with pip
56
+ pip install ymprint
57
+ ```
58
+
59
+ From source:
60
+
61
+ ```bash
62
+ git clone https://github.com/StructuralPython/yamlreports.git
63
+ cd yamlreports
64
+ uv sync
65
+ uv run ym --help
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ YMPrint installs a single command, `ym`, with two subcommands.
71
+
72
+ ### `ym convert` — render once
73
+
74
+ ```bash
75
+ ym convert report.yml # writes report.pdf next to the source
76
+ ym convert report.yml out/doc.pdf # choose an output path
77
+ ```
78
+
79
+ ### `ym live` — hot-reload preview
80
+
81
+ Renders the PDF, opens it in the [Okular](https://okular.kde.org/) viewer, and rebuilds on
82
+ every save. Great for drafting.
83
+
84
+ ```bash
85
+ ym live report.yml
86
+ ```
87
+
88
+ ## Core concepts
89
+
90
+ - **Keys are headings.** A mapping key whose value is content becomes a heading; the value
91
+ is laid out underneath it. Lists render in order, lists of mappings render as tables.
92
+ - **Configuration** lives in underscore-prefixed front matter — `_doc` (page template),
93
+ `_style` (text styles), and `_tablestyle` (table styles) — resolved across three
94
+ inheriting priority levels: internal defaults → project config → document front matter.
95
+ - **Variables** are defined in `_vars`, interpolated into text with Jinja (`{{name}}`), and
96
+ passed as real Python objects into blocks with the `$name` syntax.
97
+ - **Blocks** are underscore-prefixed keys that expand into custom content:
98
+
99
+ | Block | Purpose |
100
+ | --- | --- |
101
+ | `_img` | Embed an image with a caption |
102
+ | `_matplotfig` | Embed a matplotlib figure |
103
+ | `_info` / `_warning` / `_danger` / `_tip` / `_note` | Admonition callouts |
104
+ | `_blockquote` | A quotation with attribution |
105
+ | `_code` | A non-executable, syntax-highlighted code block |
106
+ | `_py` | Execute Python and optionally show the source |
107
+ | `_loadjson` | Load variables from a JSON file |
108
+ | `_pagebreak` | Force a page break |
109
+ | `_hrule` | A configurable horizontal rule |
110
+ | `_spacer` | Insert vertical whitespace |
111
+
112
+ ## Examples
113
+
114
+ The [`Examples/`](Examples) directory contains a runnable report for each major feature —
115
+ a simple document, document configuration, variables, PDF backgrounds, Python execution,
116
+ and the full set of blocks. Render any of them with `ym convert`.
117
+
118
+ ## Documentation
119
+
120
+ The full documentation site lives in [`docs/`](docs) (Sphinx + the Shibuya theme). Build it
121
+ locally with:
122
+
123
+ ```bash
124
+ uv run --with-requirements docs/requirements.txt \
125
+ sphinx-build -b html docs docs/_build/html
126
+ ```
127
+
128
+ Then open `docs/_build/html/index.html`. See [`docs/README.md`](docs/README.md) for details.
129
+
130
+ ## License
131
+
132
+ See [LICENSE](LICENSE).
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "ymprint"
3
+ version = "0.1.0"
4
+ description = "Desktop publishing in YAML with Python"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Connor Ferster", email = "connor@structuralpython.com" }
8
+ ]
9
+ requires-python = ">=3.14"
10
+ dependencies = [
11
+ "jinja2>=3.1.6",
12
+ "pydantic>=2.13.4",
13
+ "pygments>=2.20.0",
14
+ "pymupdf>=1.27.2.3",
15
+ "pypdf>=6.14.0",
16
+ "reportlab>=4.5.1",
17
+ "ruamel-yaml>=0.19.1",
18
+ "typer>=0.26.7",
19
+ "wenmode>=0.8.0",
20
+ ]
21
+
22
+ [project.scripts]
23
+ ym = "ymprint.cli.main:app"
24
+
25
+ [build-system]
26
+ requires = ["uv_build>=0.11.16,<0.12.0"]
27
+ build-backend = "uv_build"
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "matplotlib>=3.11.0",
32
+ "pytest>=9.0.3",
33
+ "rich>=15.0.0",
34
+ ]
@@ -0,0 +1,2 @@
1
+ from ymprint import config
2
+ from ymprint import blocks
@@ -0,0 +1,107 @@
1
+ import re
2
+
3
+ from typing import Callable, Optional, Union, TypeAlias, Any
4
+
5
+ from reportlab.platypus import (
6
+ Paragraph,
7
+ Spacer,
8
+ Table,
9
+ Image,
10
+ HRFlowable,
11
+ KeepTogether,
12
+ )
13
+ from reportlab.lib.units import mm
14
+ from ymprint.config.docstyles import ReportStyles
15
+ from ..content_checks import check_for_variable
16
+
17
+ RLFlowables: TypeAlias = Union[Paragraph, Spacer, Table, KeepTogether, Image]
18
+
19
+ YAML_Values: TypeAlias =Union[str, list, dict, float, int, None]
20
+
21
+ # TODO: Create a block registration function and a singleton block registry
22
+
23
+ class BlockExistsError(Exception):
24
+ pass
25
+
26
+ def create_block_registry() -> tuple[Callable, Callable, Callable]:
27
+ """
28
+ Creates the block registry
29
+ """
30
+ _BLOCK_REGISTRY = {}
31
+
32
+ def register_block(block_code: str, block_convert: Callable) -> None:
33
+ """
34
+ Returns None. Adds a new block to the block registry.
35
+
36
+ 'block_code': a str of the form '_{code}' where 'code' is an alphanumeric code used
37
+ to identify the block.
38
+ 'block_convert':a function with the following signature:
39
+ my_func(obj: dict, context: dict) -> list[Flowable]
40
+
41
+ Where:
42
+ obj: a dict which has a key that starts with the block code and a value
43
+ which is a user-defined data structure that contains the data needed
44
+ to generate the block as a ReportLab Flowable.
45
+ context: a dict that contains all of the internal state of this program
46
+ at the time the conversion is executed. This will get passed to your
47
+ function automatically and gives your conversion function access to
48
+ anything and everything it needs to render your custom block.
49
+ Feel free to explore the context dict by using a print(context) call
50
+ in your function.
51
+
52
+ Return:
53
+ A list of ReportLab Flowable from the reportlab.platypus module. Your custom
54
+ block may be just one flowable (like a custom-populated table) or it can
55
+ be a list of many flowable.
56
+ """
57
+ _BLOCK_REGISTRY.update({block_code: block_convert})
58
+
59
+ def list_blocks():
60
+ return list(_BLOCK_REGISTRY.keys())
61
+
62
+ def get_block_callable(block_code: str) -> Optional[Callable]:
63
+ return _BLOCK_REGISTRY.get(block_code)
64
+
65
+ return list_blocks, get_block_callable, register_block
66
+
67
+ list_blocks, get_block_callable, register_block = create_block_registry()
68
+
69
+ def convert_blocks(block_key: str, block_value: YAML_Values, context: dict) -> list[RLFlowables]:
70
+ block_code_pattern = re.compile(r"(^_[a-zA-Z0-9]+)")
71
+ matches = block_code_pattern.match(block_key)
72
+ if matches is not None:
73
+ block_code = matches.groups()[0]
74
+ else:
75
+ raise ValueError(f"Block code not found within block key: {block_key=}")
76
+ block_converter = get_block_callable(block_code)
77
+ block_value_w_python_objects = retrieve_block_variables(block_value, context)
78
+ flowables = block_converter(block_key, block_value_w_python_objects, context)
79
+ return flowables
80
+
81
+
82
+ def retrieve_block_variables(block_value: YAML_Values, context: dict) -> YAML_Values:
83
+ """
84
+ Returns 'block_value' but with list values or dictionary values that have
85
+ the "$VAR" syntax substituted with the object values
86
+ """
87
+ if isinstance(block_value, str) and check_for_variable(block_value, context):
88
+ var_name = get_variable_name(block_value)
89
+ return context['vars'].get(var_name, block_value)
90
+ elif isinstance(block_value, list):
91
+ acc = []
92
+ for elem in block_value:
93
+ new_elem = retrieve_block_variables(elem, context)
94
+ acc.append(new_elem)
95
+ return acc
96
+ elif isinstance(block_value, dict):
97
+ acc = {}
98
+ for k, v in block_value.items():
99
+ new_v = retrieve_block_variables(v, context)
100
+ acc.update({k: new_v})
101
+ return acc
102
+ else:
103
+ return block_value
104
+
105
+
106
+ def get_variable_name(var_string: str) -> str:
107
+ return var_string.lstrip('$')
@@ -0,0 +1,42 @@
1
+ from reportlab.platypus import Table, Paragraph, Spacer, KeepTogether
2
+ from . import register_block
3
+ from typing import Callable, Any
4
+ from . import blockstyles
5
+
6
+ def generate_admonition_block(kind: str) -> Callable:
7
+ """
8
+ Returns a callable to render that particular admonition type
9
+ """
10
+
11
+
12
+ def convert_admonition_block(block_key: str, block_value: Any, context: dict) -> list[KeepTogether | Spacer]:
13
+ # Need an admonition block style or style modification
14
+ available_width = context['frames']['all_pages']['width']
15
+ text_spacing = context['styles']['ymprint'].body.spacing
16
+ text_size = context['styles']['ymprint'].body.size
17
+ space_around = text_spacing * text_size
18
+ width_ratio = 0.8
19
+ block_width = width_ratio * available_width
20
+ value = block_value
21
+ tablestyle = blockstyles.get_table_style(kind)
22
+ body_textstyle = blockstyles.get_text_styles().get(f'admonition_{kind}_body')
23
+ title_textstyle = blockstyles.get_text_styles().get(f'admonition_{kind}_title')
24
+ notice = Paragraph(text=blockstyles.admonition_title_text(kind), style=title_textstyle)
25
+ content = Paragraph(text=value, style=body_textstyle)
26
+ table = Table(
27
+ data=[[notice], [content]],
28
+ colWidths=[block_width],
29
+ style=tablestyle,
30
+ spaceBefore=space_around,
31
+ spaceAfter=space_around
32
+ )
33
+ return [KeepTogether(table), Spacer(1, 10)]
34
+
35
+ return convert_admonition_block
36
+
37
+
38
+ register_block("_info", generate_admonition_block("info"))
39
+ register_block("_warning", generate_admonition_block("warning"))
40
+ register_block("_danger", generate_admonition_block("danger"))
41
+ register_block("_tip", generate_admonition_block("tip"))
42
+ register_block("_note", generate_admonition_block("note"))