engrapha-notes 0.1.0__py3-none-any.whl
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.
- engrapha_notes/__init__.py +236 -0
- engrapha_notes/cli.py +883 -0
- engrapha_notes/document.py +2691 -0
- engrapha_notes/helpers.py +4386 -0
- engrapha_notes/packet.py +282 -0
- engrapha_notes/palette.py +61 -0
- engrapha_notes/styles.py +28 -0
- engrapha_notes/theme.py +348 -0
- engrapha_notes-0.1.0.dist-info/METADATA +530 -0
- engrapha_notes-0.1.0.dist-info/RECORD +13 -0
- engrapha_notes-0.1.0.dist-info/WHEEL +5 -0
- engrapha_notes-0.1.0.dist-info/entry_points.txt +3 -0
- engrapha_notes-0.1.0.dist-info/top_level.txt +1 -0
engrapha_notes/theme.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, replace
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from reportlab.lib.colors import HexColor
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def hex_to_rgb(hex_str: str) -> str:
|
|
10
|
+
"""Return a hex string for callers that accept either RGB or hex values."""
|
|
11
|
+
return hex_str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class NotesTheme:
|
|
16
|
+
name: str = "Dark"
|
|
17
|
+
bg: str = "#0d1117"
|
|
18
|
+
surface: str = "#161b22"
|
|
19
|
+
surface_alt: str = "#1c2333"
|
|
20
|
+
card_mid: str = "#1c2333"
|
|
21
|
+
text: str = "#f0f6fc"
|
|
22
|
+
text_dim: str = "#9da7b3"
|
|
23
|
+
text_code: str = "#dbeafe"
|
|
24
|
+
accent: str = "#79c0ff"
|
|
25
|
+
accent2: str = "#bc8cff"
|
|
26
|
+
accent_dim: str = "#2c5b96"
|
|
27
|
+
accent_surface: str = "#1a3b5c"
|
|
28
|
+
cyan: str = "#79c0ff"
|
|
29
|
+
green: str = "#3fb950"
|
|
30
|
+
green_bg: str = "#0d2119"
|
|
31
|
+
yellow: str = "#d29922"
|
|
32
|
+
yellow_bg: str = "#1f1a0a"
|
|
33
|
+
red: str = "#f85149"
|
|
34
|
+
red_bg: str = "#1e0d0d"
|
|
35
|
+
purple: str = "#bc8cff"
|
|
36
|
+
purple_bg: str = "#180d2b"
|
|
37
|
+
white: str = "#f0f6fc"
|
|
38
|
+
danger: str = "#f85149"
|
|
39
|
+
success: str = "#3fb950"
|
|
40
|
+
warning: str = "#d29922"
|
|
41
|
+
info: str = "#79c0ff"
|
|
42
|
+
border: str = "#30363d"
|
|
43
|
+
table_hdr: str = "#1f6feb"
|
|
44
|
+
table_bdr: str = "#30363d"
|
|
45
|
+
code_bg: str = "#161b22"
|
|
46
|
+
body_font: str = "Helvetica"
|
|
47
|
+
heading_font: str = "Helvetica-Bold"
|
|
48
|
+
code_font: str = "Courier"
|
|
49
|
+
size_body: float = 10.0
|
|
50
|
+
size_question: float = 10.0
|
|
51
|
+
border_thickness: float = 1.0
|
|
52
|
+
border_color: str | None = None
|
|
53
|
+
show_headers: bool = False
|
|
54
|
+
divider_thickness: float = 1.0
|
|
55
|
+
left_margin: float = 51.0236220472
|
|
56
|
+
right_margin: float = 51.0236220472
|
|
57
|
+
top_margin: float = 51.0236220472
|
|
58
|
+
bottom_margin: float = 51.0236220472
|
|
59
|
+
double_page_border: bool = False
|
|
60
|
+
page_border_margin: float = 12.0
|
|
61
|
+
page_border_gap: float = 3.0
|
|
62
|
+
page_border_color: str | None = None
|
|
63
|
+
plain_questions: bool = False
|
|
64
|
+
|
|
65
|
+
def rl(self, color_value: str | Any) -> Any:
|
|
66
|
+
"""Convert hex strings to ReportLab colors while preserving color objects."""
|
|
67
|
+
return HexColor(color_value) if isinstance(color_value, str) else color_value
|
|
68
|
+
|
|
69
|
+
def copy_with(self, **kwargs: Any) -> "NotesTheme":
|
|
70
|
+
"""Return a modified copy of the theme."""
|
|
71
|
+
return replace(self, **kwargs)
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def from_accent(cls, accent: str, dark: bool = True, name: str | None = None) -> "NotesTheme":
|
|
75
|
+
"""Build a practical theme from one accent color."""
|
|
76
|
+
base = DARK if dark else LIGHT
|
|
77
|
+
return base.copy_with(name=name or f"Accent {accent}", accent=accent, cyan=accent)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ThemeBuilder:
|
|
81
|
+
"""Small fluent builder for custom note themes."""
|
|
82
|
+
|
|
83
|
+
def __init__(self) -> None:
|
|
84
|
+
self._theme = NotesTheme()
|
|
85
|
+
|
|
86
|
+
def set_colors(self, bg: str, surface: str, accent: str) -> "ThemeBuilder":
|
|
87
|
+
self._theme.bg = bg
|
|
88
|
+
self._theme.surface = surface
|
|
89
|
+
self._theme.surface_alt = surface
|
|
90
|
+
self._theme.card_mid = surface
|
|
91
|
+
self._theme.accent = accent
|
|
92
|
+
self._theme.cyan = accent
|
|
93
|
+
return self
|
|
94
|
+
|
|
95
|
+
def set_fonts(self, body_font: str, heading_font: str, size_body: float, size_question: float | None = None) -> "ThemeBuilder":
|
|
96
|
+
self._theme.body_font = body_font
|
|
97
|
+
self._theme.heading_font = heading_font
|
|
98
|
+
self._theme.size_body = size_body
|
|
99
|
+
if size_question is not None:
|
|
100
|
+
self._theme.size_question = size_question
|
|
101
|
+
return self
|
|
102
|
+
|
|
103
|
+
def set_borders(self, thickness: float, color: str) -> "ThemeBuilder":
|
|
104
|
+
self._theme.border_thickness = thickness
|
|
105
|
+
self._theme.border_color = color
|
|
106
|
+
return self
|
|
107
|
+
|
|
108
|
+
def set_double_border(self, enabled: bool, margin: float = 12.0, gap: float = 3.0, color: str | None = None) -> "ThemeBuilder":
|
|
109
|
+
self._theme.double_page_border = enabled
|
|
110
|
+
self._theme.page_border_margin = margin
|
|
111
|
+
self._theme.page_border_gap = gap
|
|
112
|
+
self._theme.page_border_color = color
|
|
113
|
+
return self
|
|
114
|
+
|
|
115
|
+
def set_header_footer(self, show_headers: bool, divider_thickness: float) -> "ThemeBuilder":
|
|
116
|
+
self._theme.show_headers = show_headers
|
|
117
|
+
self._theme.divider_thickness = divider_thickness
|
|
118
|
+
return self
|
|
119
|
+
|
|
120
|
+
def build(self) -> NotesTheme:
|
|
121
|
+
return self._theme
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
DARK = NotesTheme(name="Dark")
|
|
125
|
+
LIGHT = NotesTheme(
|
|
126
|
+
name="Light",
|
|
127
|
+
bg="#ffffff",
|
|
128
|
+
surface="#f8fafc",
|
|
129
|
+
surface_alt="#e5e7eb",
|
|
130
|
+
card_mid="#e5e7eb",
|
|
131
|
+
text="#111827",
|
|
132
|
+
text_dim="#4b5563",
|
|
133
|
+
text_code="#111827",
|
|
134
|
+
accent="#2563eb",
|
|
135
|
+
accent2="#7c3aed",
|
|
136
|
+
cyan="#2563eb",
|
|
137
|
+
green="#15803d",
|
|
138
|
+
green_bg="#dcfce7",
|
|
139
|
+
yellow="#a16207",
|
|
140
|
+
yellow_bg="#fef9c3",
|
|
141
|
+
red="#dc2626",
|
|
142
|
+
red_bg="#fee2e2",
|
|
143
|
+
purple="#7c3aed",
|
|
144
|
+
purple_bg="#ede9fe",
|
|
145
|
+
white="#111827",
|
|
146
|
+
table_hdr="#2563eb",
|
|
147
|
+
table_bdr="#cbd5e1",
|
|
148
|
+
code_bg="#f1f5f9",
|
|
149
|
+
)
|
|
150
|
+
OCEAN_DARK = DARK.copy_with(
|
|
151
|
+
name="Ocean Dark",
|
|
152
|
+
bg="#020c14",
|
|
153
|
+
surface="#082032",
|
|
154
|
+
surface_alt="#0f2f46",
|
|
155
|
+
card_mid="#0f2f46",
|
|
156
|
+
accent="#22d3ee",
|
|
157
|
+
cyan="#22d3ee",
|
|
158
|
+
)
|
|
159
|
+
FOREST_DARK = DARK.copy_with(
|
|
160
|
+
name="Forest Dark",
|
|
161
|
+
bg="#0b1512",
|
|
162
|
+
surface="#10231c",
|
|
163
|
+
surface_alt="#173528",
|
|
164
|
+
card_mid="#173528",
|
|
165
|
+
accent="#4ade80",
|
|
166
|
+
cyan="#4ade80",
|
|
167
|
+
)
|
|
168
|
+
SUNSET_DARK = DARK.copy_with(
|
|
169
|
+
name="Sunset Dark",
|
|
170
|
+
bg="#0c0811",
|
|
171
|
+
surface="#211225",
|
|
172
|
+
surface_alt="#321a2f",
|
|
173
|
+
card_mid="#321a2f",
|
|
174
|
+
accent="#fb923c",
|
|
175
|
+
cyan="#fb923c",
|
|
176
|
+
)
|
|
177
|
+
MIDNIGHT_DARK = DARK.copy_with(
|
|
178
|
+
name="Midnight Dark",
|
|
179
|
+
bg="#07050f",
|
|
180
|
+
surface="#111026",
|
|
181
|
+
surface_alt="#19183a",
|
|
182
|
+
card_mid="#19183a",
|
|
183
|
+
accent="#818cf8",
|
|
184
|
+
cyan="#818cf8",
|
|
185
|
+
)
|
|
186
|
+
OCEAN_LIGHT = LIGHT.copy_with(
|
|
187
|
+
name="Ocean Light",
|
|
188
|
+
bg="#f0f9ff",
|
|
189
|
+
surface="#ffffff",
|
|
190
|
+
surface_alt="#e0f2fe",
|
|
191
|
+
card_mid="#e0f2fe",
|
|
192
|
+
accent="#0891b2",
|
|
193
|
+
cyan="#0891b2",
|
|
194
|
+
)
|
|
195
|
+
SEPIA = LIGHT.copy_with(
|
|
196
|
+
name="Sepia",
|
|
197
|
+
bg="#faf7f0",
|
|
198
|
+
surface="#fffaf0",
|
|
199
|
+
surface_alt="#f3ead8",
|
|
200
|
+
card_mid="#f3ead8",
|
|
201
|
+
accent="#92400e",
|
|
202
|
+
cyan="#92400e",
|
|
203
|
+
)
|
|
204
|
+
CATPPUCCIN_LATTE = LIGHT.copy_with(
|
|
205
|
+
name="Catppuccin Latte",
|
|
206
|
+
bg="#eff1f5",
|
|
207
|
+
surface="#e6e9ef",
|
|
208
|
+
surface_alt="#dce0e8",
|
|
209
|
+
card_mid="#dce0e8",
|
|
210
|
+
accent="#1e66f5",
|
|
211
|
+
cyan="#1e66f5",
|
|
212
|
+
)
|
|
213
|
+
CATPPUCCIN_MOCHA = DARK.copy_with(
|
|
214
|
+
name="Catppuccin Mocha",
|
|
215
|
+
bg="#1e1e2e",
|
|
216
|
+
surface="#313244",
|
|
217
|
+
surface_alt="#45475a",
|
|
218
|
+
card_mid="#45475a",
|
|
219
|
+
accent="#89b4fa",
|
|
220
|
+
cyan="#89b4fa",
|
|
221
|
+
)
|
|
222
|
+
NOTION = LIGHT.copy_with(
|
|
223
|
+
name="Notion",
|
|
224
|
+
bg="#ffffff",
|
|
225
|
+
surface="#f1f1ef",
|
|
226
|
+
surface_alt="#e3e2e0",
|
|
227
|
+
card_mid="#e3e2e0",
|
|
228
|
+
text="#37352f",
|
|
229
|
+
text_dim="#787774",
|
|
230
|
+
accent="#2383e2",
|
|
231
|
+
cyan="#2383e2",
|
|
232
|
+
table_hdr="#2383e2",
|
|
233
|
+
table_bdr="#e3e2e0",
|
|
234
|
+
code_bg="#f7f6f3",
|
|
235
|
+
)
|
|
236
|
+
GITHUB = LIGHT.copy_with(
|
|
237
|
+
name="GitHub",
|
|
238
|
+
bg="#ffffff",
|
|
239
|
+
surface="#f6f8fa",
|
|
240
|
+
surface_alt="#afb8c1",
|
|
241
|
+
card_mid="#afb8c1",
|
|
242
|
+
text="#24292f",
|
|
243
|
+
text_dim="#57606a",
|
|
244
|
+
accent="#0969da",
|
|
245
|
+
cyan="#0969da",
|
|
246
|
+
table_hdr="#0969da",
|
|
247
|
+
table_bdr="#d0d7de",
|
|
248
|
+
code_bg="#f6f8fa",
|
|
249
|
+
)
|
|
250
|
+
LINEAR = DARK.copy_with(
|
|
251
|
+
name="Linear",
|
|
252
|
+
bg="#0e0e10",
|
|
253
|
+
surface="#151518",
|
|
254
|
+
surface_alt="#222227",
|
|
255
|
+
card_mid="#222227",
|
|
256
|
+
text="#f4f4f5",
|
|
257
|
+
text_dim="#a1a1aa",
|
|
258
|
+
accent="#5e6ad2",
|
|
259
|
+
cyan="#5e6ad2",
|
|
260
|
+
table_hdr="#5e6ad2",
|
|
261
|
+
table_bdr="#222227",
|
|
262
|
+
code_bg="#151518",
|
|
263
|
+
)
|
|
264
|
+
ACADEMIC = LIGHT.copy_with(
|
|
265
|
+
name="Academic",
|
|
266
|
+
bg="#ffffff",
|
|
267
|
+
surface="#ffffff",
|
|
268
|
+
surface_alt="#f3f4f6",
|
|
269
|
+
card_mid="#f3f4f6",
|
|
270
|
+
text="#111111",
|
|
271
|
+
text_dim="#374151",
|
|
272
|
+
accent="#111111",
|
|
273
|
+
cyan="#111111",
|
|
274
|
+
table_hdr="#111111",
|
|
275
|
+
table_bdr="#e5e7eb",
|
|
276
|
+
code_bg="#f3f4f6",
|
|
277
|
+
body_font="Times-Roman",
|
|
278
|
+
heading_font="Times-Bold",
|
|
279
|
+
)
|
|
280
|
+
TEXTBOOK = LIGHT.copy_with(
|
|
281
|
+
name="Textbook",
|
|
282
|
+
bg="#fafafa",
|
|
283
|
+
surface="#f4f4f5",
|
|
284
|
+
surface_alt="#e4e4e7",
|
|
285
|
+
card_mid="#e4e4e7",
|
|
286
|
+
text="#18181b",
|
|
287
|
+
text_dim="#52525b",
|
|
288
|
+
accent="#0f766e",
|
|
289
|
+
cyan="#0f766e",
|
|
290
|
+
table_hdr="#0f766e",
|
|
291
|
+
table_bdr="#e4e4e7",
|
|
292
|
+
code_bg="#f4f4f5",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
ALL_THEMES = [
|
|
296
|
+
DARK,
|
|
297
|
+
LIGHT,
|
|
298
|
+
OCEAN_DARK,
|
|
299
|
+
FOREST_DARK,
|
|
300
|
+
SUNSET_DARK,
|
|
301
|
+
MIDNIGHT_DARK,
|
|
302
|
+
OCEAN_LIGHT,
|
|
303
|
+
SEPIA,
|
|
304
|
+
CATPPUCCIN_LATTE,
|
|
305
|
+
CATPPUCCIN_MOCHA,
|
|
306
|
+
NOTION,
|
|
307
|
+
GITHUB,
|
|
308
|
+
LINEAR,
|
|
309
|
+
ACADEMIC,
|
|
310
|
+
TEXTBOOK,
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
DRACULA = "dracula"
|
|
314
|
+
MONOKAI = "monokai"
|
|
315
|
+
GITHUB_DARK = "github-dark"
|
|
316
|
+
|
|
317
|
+
_current_theme = DARK
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def set_theme(theme: NotesTheme) -> None:
|
|
321
|
+
global _current_theme
|
|
322
|
+
_current_theme = theme
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def get_theme() -> NotesTheme:
|
|
326
|
+
return _current_theme
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def EngineeringNotes(dark: bool = True) -> NotesTheme:
|
|
330
|
+
theme = (DARK if dark else LIGHT).copy_with(
|
|
331
|
+
name="Engineering Notes",
|
|
332
|
+
body_font="Helvetica",
|
|
333
|
+
heading_font="Helvetica-Bold",
|
|
334
|
+
size_body=10.0,
|
|
335
|
+
)
|
|
336
|
+
set_theme(theme)
|
|
337
|
+
return theme
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def QuestionBank(dark: bool = False) -> NotesTheme:
|
|
341
|
+
theme = (DARK if dark else LIGHT).copy_with(
|
|
342
|
+
name="Question Bank",
|
|
343
|
+
body_font="Times-Roman",
|
|
344
|
+
heading_font="Times-Bold",
|
|
345
|
+
size_body=9.5,
|
|
346
|
+
)
|
|
347
|
+
set_theme(theme)
|
|
348
|
+
return theme
|