eidosui 0.3.0__py3-none-any.whl → 0.5.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.
- eidos/__init__.py +270 -0
- eidos/components/__init__.py +10 -0
- eidos/components/headers.py +16 -14
- eidos/components/navigation.py +44 -35
- eidos/components/table.py +84 -0
- eidos/css/styles.css +48 -0
- eidos/plugins/__init__.py +1 -1
- eidos/plugins/markdown/__init__.py +3 -3
- eidos/plugins/markdown/components.py +10 -22
- eidos/plugins/markdown/extensions/__init__.py +1 -1
- eidos/plugins/markdown/extensions/alerts.py +68 -78
- eidos/plugins/markdown/renderer.py +19 -24
- eidos/styles.py +33 -9
- eidos/tags.py +369 -33
- eidos/utils.py +42 -38
- eidosui-0.5.0.dist-info/METADATA +113 -0
- eidosui-0.5.0.dist-info/RECORD +24 -0
- eidosui-0.3.0.dist-info/METADATA +0 -127
- eidosui-0.3.0.dist-info/RECORD +0 -22
- {eidosui-0.3.0.dist-info → eidosui-0.5.0.dist-info}/WHEEL +0 -0
- {eidosui-0.3.0.dist-info → eidosui-0.5.0.dist-info}/licenses/LICENSE +0 -0
eidos/__init__.py
CHANGED
@@ -0,0 +1,270 @@
|
|
1
|
+
"""EidosUI - A modern, flexible Tailwind CSS-based UI library for Python web frameworks.
|
2
|
+
|
3
|
+
Quick start:
|
4
|
+
>>> from eidos import *
|
5
|
+
>>> DataTable.from_lists([["A", "B"], ["C", "D"]], headers=["Col1", "Col2"])
|
6
|
+
|
7
|
+
Or use explicit imports:
|
8
|
+
>>> from eidos import DataTable, Button, H1, Table
|
9
|
+
>>> from eidos import styles
|
10
|
+
"""
|
11
|
+
|
12
|
+
# Import all styled HTML tags
|
13
|
+
# Import style namespaces
|
14
|
+
from . import styles
|
15
|
+
|
16
|
+
# Import components
|
17
|
+
from .components import DataTable, EidosHeaders, NavBar
|
18
|
+
from .styles import buttons, semantic, tables, typography
|
19
|
+
from .tags import (
|
20
|
+
# Headings
|
21
|
+
H1,
|
22
|
+
H2,
|
23
|
+
H3,
|
24
|
+
H4,
|
25
|
+
H5,
|
26
|
+
H6,
|
27
|
+
# Pass-through HTML tags
|
28
|
+
A,
|
29
|
+
Abbr,
|
30
|
+
Address,
|
31
|
+
Area,
|
32
|
+
Article,
|
33
|
+
Aside,
|
34
|
+
Audio,
|
35
|
+
B,
|
36
|
+
Base,
|
37
|
+
Bdi,
|
38
|
+
Bdo,
|
39
|
+
Blockquote,
|
40
|
+
# Body
|
41
|
+
Body,
|
42
|
+
Br,
|
43
|
+
# Buttons
|
44
|
+
Button,
|
45
|
+
Canvas,
|
46
|
+
Caption,
|
47
|
+
Cite,
|
48
|
+
Code,
|
49
|
+
Col,
|
50
|
+
Colgroup,
|
51
|
+
Data,
|
52
|
+
Datalist,
|
53
|
+
Dd,
|
54
|
+
Del,
|
55
|
+
Details,
|
56
|
+
Dfn,
|
57
|
+
Dialog,
|
58
|
+
Div,
|
59
|
+
Dl,
|
60
|
+
Dt,
|
61
|
+
Em,
|
62
|
+
Embed,
|
63
|
+
Fieldset,
|
64
|
+
Figcaption,
|
65
|
+
Figure,
|
66
|
+
Footer,
|
67
|
+
Form,
|
68
|
+
Head,
|
69
|
+
Header,
|
70
|
+
Hgroup,
|
71
|
+
Hr,
|
72
|
+
Html,
|
73
|
+
I,
|
74
|
+
Iframe,
|
75
|
+
Img,
|
76
|
+
Input,
|
77
|
+
Ins,
|
78
|
+
Kbd,
|
79
|
+
Label,
|
80
|
+
Legend,
|
81
|
+
Li,
|
82
|
+
Link,
|
83
|
+
Main,
|
84
|
+
Map,
|
85
|
+
Mark,
|
86
|
+
Menu,
|
87
|
+
Meta,
|
88
|
+
Meter,
|
89
|
+
Nav,
|
90
|
+
Noscript,
|
91
|
+
Object,
|
92
|
+
Ol,
|
93
|
+
Optgroup,
|
94
|
+
Option,
|
95
|
+
Output,
|
96
|
+
P,
|
97
|
+
Param,
|
98
|
+
Picture,
|
99
|
+
Pre,
|
100
|
+
Progress,
|
101
|
+
Q,
|
102
|
+
Rp,
|
103
|
+
Rt,
|
104
|
+
Ruby,
|
105
|
+
S,
|
106
|
+
Samp,
|
107
|
+
Script,
|
108
|
+
Search,
|
109
|
+
Section,
|
110
|
+
Select,
|
111
|
+
Small,
|
112
|
+
Source,
|
113
|
+
Span,
|
114
|
+
# Semantic typography
|
115
|
+
Strong,
|
116
|
+
Style,
|
117
|
+
Sub,
|
118
|
+
Summary,
|
119
|
+
Sup,
|
120
|
+
# Table elements
|
121
|
+
Table,
|
122
|
+
Tbody,
|
123
|
+
Td,
|
124
|
+
Template,
|
125
|
+
Textarea,
|
126
|
+
Tfoot,
|
127
|
+
Th,
|
128
|
+
Thead,
|
129
|
+
Time,
|
130
|
+
Title,
|
131
|
+
Tr,
|
132
|
+
Track,
|
133
|
+
U,
|
134
|
+
Ul,
|
135
|
+
Var,
|
136
|
+
Video,
|
137
|
+
Wbr,
|
138
|
+
)
|
139
|
+
|
140
|
+
# Version info
|
141
|
+
__version__ = "0.4.0"
|
142
|
+
|
143
|
+
# Define what's available with "from eidos import *"
|
144
|
+
__all__ = [
|
145
|
+
# Version
|
146
|
+
"__version__",
|
147
|
+
# Style namespaces
|
148
|
+
"styles",
|
149
|
+
"buttons",
|
150
|
+
"typography",
|
151
|
+
"semantic",
|
152
|
+
"tables",
|
153
|
+
# Components
|
154
|
+
"DataTable",
|
155
|
+
"NavBar",
|
156
|
+
"EidosHeaders",
|
157
|
+
# HTML Tags
|
158
|
+
"H1",
|
159
|
+
"H2",
|
160
|
+
"H3",
|
161
|
+
"H4",
|
162
|
+
"H5",
|
163
|
+
"H6",
|
164
|
+
"Body",
|
165
|
+
"Button",
|
166
|
+
"Strong",
|
167
|
+
"I",
|
168
|
+
"Small",
|
169
|
+
"Del",
|
170
|
+
"Abbr",
|
171
|
+
"Var",
|
172
|
+
"Mark",
|
173
|
+
"Time",
|
174
|
+
"Code",
|
175
|
+
"Pre",
|
176
|
+
"Kbd",
|
177
|
+
"Samp",
|
178
|
+
"Blockquote",
|
179
|
+
"Cite",
|
180
|
+
"Address",
|
181
|
+
"Hr",
|
182
|
+
"Details",
|
183
|
+
"Summary",
|
184
|
+
"Dl",
|
185
|
+
"Dt",
|
186
|
+
"Dd",
|
187
|
+
"Figure",
|
188
|
+
"Figcaption",
|
189
|
+
"Table",
|
190
|
+
"Thead",
|
191
|
+
"Tbody",
|
192
|
+
"Tfoot",
|
193
|
+
"Tr",
|
194
|
+
"Th",
|
195
|
+
"Td",
|
196
|
+
"A",
|
197
|
+
"Area",
|
198
|
+
"Article",
|
199
|
+
"Aside",
|
200
|
+
"Audio",
|
201
|
+
"B",
|
202
|
+
"Base",
|
203
|
+
"Bdi",
|
204
|
+
"Bdo",
|
205
|
+
"Br",
|
206
|
+
"Canvas",
|
207
|
+
"Caption",
|
208
|
+
"Col",
|
209
|
+
"Colgroup",
|
210
|
+
"Data",
|
211
|
+
"Datalist",
|
212
|
+
"Dfn",
|
213
|
+
"Dialog",
|
214
|
+
"Div",
|
215
|
+
"Em",
|
216
|
+
"Embed",
|
217
|
+
"Fieldset",
|
218
|
+
"Footer",
|
219
|
+
"Form",
|
220
|
+
"Head",
|
221
|
+
"Header",
|
222
|
+
"Hgroup",
|
223
|
+
"Html",
|
224
|
+
"Iframe",
|
225
|
+
"Img",
|
226
|
+
"Input",
|
227
|
+
"Ins",
|
228
|
+
"Label",
|
229
|
+
"Legend",
|
230
|
+
"Li",
|
231
|
+
"Link",
|
232
|
+
"Main",
|
233
|
+
"Map",
|
234
|
+
"Menu",
|
235
|
+
"Meta",
|
236
|
+
"Meter",
|
237
|
+
"Nav",
|
238
|
+
"Noscript",
|
239
|
+
"Object",
|
240
|
+
"Ol",
|
241
|
+
"Optgroup",
|
242
|
+
"Option",
|
243
|
+
"Output",
|
244
|
+
"P",
|
245
|
+
"Param",
|
246
|
+
"Picture",
|
247
|
+
"Progress",
|
248
|
+
"Q",
|
249
|
+
"Rp",
|
250
|
+
"Rt",
|
251
|
+
"Ruby",
|
252
|
+
"S",
|
253
|
+
"Script",
|
254
|
+
"Search",
|
255
|
+
"Section",
|
256
|
+
"Select",
|
257
|
+
"Source",
|
258
|
+
"Span",
|
259
|
+
"Style",
|
260
|
+
"Sub",
|
261
|
+
"Sup",
|
262
|
+
"Template",
|
263
|
+
"Textarea",
|
264
|
+
"Title",
|
265
|
+
"Track",
|
266
|
+
"U",
|
267
|
+
"Ul",
|
268
|
+
"Video",
|
269
|
+
"Wbr",
|
270
|
+
]
|
eidos/components/headers.py
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
from air import Meta, Script, Link
|
2
|
-
from ..tags import Body
|
3
1
|
from typing import Literal
|
4
2
|
|
3
|
+
from air import Link, Meta, Script
|
4
|
+
|
5
|
+
|
5
6
|
def get_css_urls():
|
6
7
|
"""Return list of CSS URLs for EidosUI."""
|
7
8
|
return [
|
8
9
|
"/eidos/css/styles.css",
|
9
|
-
"/eidos/css/themes/eidos-variables.css",
|
10
|
+
"/eidos/css/themes/eidos-variables.css",
|
10
11
|
"/eidos/css/themes/light.css",
|
11
|
-
"/eidos/css/themes/dark.css"
|
12
|
+
"/eidos/css/themes/dark.css",
|
12
13
|
]
|
13
14
|
|
15
|
+
|
14
16
|
def EidosHeaders(
|
15
17
|
include_tailwind: bool = True,
|
16
18
|
include_lucide: bool = True,
|
@@ -18,7 +20,7 @@ def EidosHeaders(
|
|
18
20
|
theme: Literal["light", "dark"] = "light",
|
19
21
|
):
|
20
22
|
"""Complete EidosUI headers with EidosUI JavaScript support.
|
21
|
-
|
23
|
+
|
22
24
|
Args:
|
23
25
|
include_tailwind: Include Tailwind CSS CDN
|
24
26
|
include_lucide: Include Lucide Icons CDN
|
@@ -29,28 +31,28 @@ def EidosHeaders(
|
|
29
31
|
Meta(charset="UTF-8"),
|
30
32
|
Meta(name="viewport", content="width=device-width, initial-scale=1.0"),
|
31
33
|
]
|
32
|
-
|
34
|
+
|
33
35
|
# Core libraries
|
34
36
|
if include_tailwind:
|
35
37
|
headers.append(Script(src="https://cdn.tailwindcss.com"))
|
36
|
-
|
38
|
+
|
37
39
|
if include_lucide:
|
38
40
|
headers.append(Script(src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"))
|
39
|
-
|
41
|
+
|
40
42
|
# EidosUI CSS
|
41
43
|
for css_url in get_css_urls():
|
42
44
|
headers.append(Link(rel="stylesheet", href=css_url))
|
43
|
-
|
45
|
+
|
44
46
|
# EidosUI JavaScript
|
45
47
|
if include_eidos_js:
|
46
48
|
headers.append(Script(src="/eidos/js/eidos.js", defer=True))
|
47
|
-
|
49
|
+
|
48
50
|
# Initialization script
|
49
51
|
init_script = f"""
|
50
52
|
// Set theme
|
51
53
|
document.documentElement.setAttribute('data-theme', '{theme}');
|
52
54
|
"""
|
53
|
-
|
55
|
+
|
54
56
|
if include_lucide:
|
55
57
|
init_script += """
|
56
58
|
// Initialize Lucide icons
|
@@ -62,7 +64,7 @@ def EidosHeaders(
|
|
62
64
|
if (window.lucide) lucide.createIcons();
|
63
65
|
}
|
64
66
|
"""
|
65
|
-
|
67
|
+
|
66
68
|
headers.append(Script(init_script))
|
67
|
-
|
68
|
-
return headers
|
69
|
+
|
70
|
+
return headers
|
eidos/components/navigation.py
CHANGED
@@ -1,35 +1,44 @@
|
|
1
|
-
from
|
1
|
+
from typing import Any, Final
|
2
|
+
from uuid import uuid4
|
3
|
+
|
4
|
+
from air import A, Div, I, Tag
|
5
|
+
|
2
6
|
from ..tags import *
|
3
7
|
from ..utils import stringify
|
4
|
-
|
5
|
-
from uuid import uuid4
|
8
|
+
|
6
9
|
|
7
10
|
class ScrollspyT:
|
8
|
-
underline: Final[str] =
|
9
|
-
bold: Final[str] =
|
11
|
+
underline: Final[str] = "navbar-underline"
|
12
|
+
bold: Final[str] = "navbar-bold"
|
13
|
+
|
10
14
|
|
11
|
-
def NavBar(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
def NavBar(
|
16
|
+
*c: Any,
|
17
|
+
lcontents: Tag | None = None,
|
18
|
+
right_cls: str = "items-center space-x-4",
|
19
|
+
mobile_cls: str = "",
|
20
|
+
sticky: bool = False,
|
21
|
+
scrollspy: bool = False,
|
22
|
+
cls: str = "p-4",
|
23
|
+
scrollspy_cls: str = ScrollspyT.underline,
|
24
|
+
menu_id: str | None = None,
|
25
|
+
) -> Tag:
|
21
26
|
"""Pure Tailwind responsive navigation bar with optional scrollspy.
|
22
|
-
|
27
|
+
|
23
28
|
Mobile menu uses best practice dropdown with:
|
24
29
|
- Centered text links
|
25
30
|
- Large touch targets
|
26
31
|
- Auto-close on selection
|
27
32
|
- Smooth animations
|
28
33
|
"""
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
if lcontents is None:
|
35
|
+
lcontents = Div()
|
36
|
+
|
37
|
+
if menu_id is None:
|
38
|
+
menu_id = f"menu-{uuid4().hex[:8]}"
|
39
|
+
|
40
|
+
sticky_cls = "sticky top-0 eidos-navbar-sticky z-50" if sticky else ""
|
41
|
+
|
33
42
|
# Mobile toggle button with hamburger/close icon
|
34
43
|
mobile_icon = A(
|
35
44
|
I(data_lucide="menu", class_="w-6 h-6", data_menu_icon="open"),
|
@@ -38,30 +47,30 @@ def NavBar(*c: Any,
|
|
38
47
|
data_toggle=f"#{menu_id}",
|
39
48
|
role="button",
|
40
49
|
aria_label="Toggle navigation",
|
41
|
-
aria_expanded="false"
|
50
|
+
aria_expanded="false",
|
42
51
|
)
|
43
|
-
|
52
|
+
|
44
53
|
# Desktop navigation
|
45
54
|
desktop_nav = Div(
|
46
55
|
*c,
|
47
|
-
class_=stringify(right_cls,
|
48
|
-
data_scrollspy="true" if scrollspy else None
|
56
|
+
class_=stringify(right_cls, "hidden md:flex"),
|
57
|
+
data_scrollspy="true" if scrollspy else None,
|
49
58
|
)
|
50
|
-
|
59
|
+
|
51
60
|
# Mobile navigation
|
52
61
|
mobile_nav = Div(
|
53
62
|
*c,
|
54
63
|
class_=stringify(
|
55
|
-
mobile_cls,
|
56
|
-
|
57
|
-
|
58
|
-
scrollspy_cls
|
64
|
+
mobile_cls,
|
65
|
+
"hidden md:hidden absolute top-full left-0 right-0 eidos-navbar-mobile shadow-lg border-t",
|
66
|
+
"flex flex-col eidos-navbar-mobile-divider" if not mobile_cls else "",
|
67
|
+
scrollspy_cls,
|
59
68
|
),
|
60
69
|
id=menu_id,
|
61
70
|
data_scrollspy="true" if scrollspy else None,
|
62
|
-
data_mobile_menu="true"
|
71
|
+
data_mobile_menu="true",
|
63
72
|
)
|
64
|
-
|
73
|
+
|
65
74
|
return Div(
|
66
75
|
# Main navbar container with relative positioning for mobile dropdown
|
67
76
|
Div(
|
@@ -69,10 +78,10 @@ def NavBar(*c: Any,
|
|
69
78
|
lcontents,
|
70
79
|
mobile_icon,
|
71
80
|
desktop_nav,
|
72
|
-
class_=
|
81
|
+
class_="flex items-center justify-between",
|
73
82
|
),
|
74
83
|
mobile_nav,
|
75
|
-
class_=stringify(
|
84
|
+
class_=stringify("eidos-navbar relative", cls, scrollspy_cls),
|
76
85
|
),
|
77
|
-
class_=sticky_cls
|
78
|
-
)
|
86
|
+
class_=sticky_cls,
|
87
|
+
)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from ..tags import Table as BaseTable
|
4
|
+
from ..tags import Tbody, Td, Th, Thead, Tr
|
5
|
+
|
6
|
+
|
7
|
+
class DataTable:
|
8
|
+
"""DataTable component that provides convenient methods for creating tables from data."""
|
9
|
+
|
10
|
+
@classmethod
|
11
|
+
def from_lists(
|
12
|
+
cls,
|
13
|
+
data: list[list],
|
14
|
+
headers: list[str] | None = None,
|
15
|
+
class_: str | list[str] | None = None,
|
16
|
+
**kwargs: Any,
|
17
|
+
) -> Any:
|
18
|
+
"""Create table from list of lists.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
data: List of lists where each inner list is a row
|
22
|
+
headers: Optional list of header strings
|
23
|
+
class_: Optional CSS classes to add to the table
|
24
|
+
**kwargs: Additional attributes to pass to the table element
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
A rendered table element
|
28
|
+
|
29
|
+
Example:
|
30
|
+
Table.from_lists([["A", "B"], ["C", "D"]], headers=["Col1", "Col2"])
|
31
|
+
"""
|
32
|
+
content = []
|
33
|
+
|
34
|
+
if headers:
|
35
|
+
thead = Thead(Tr(*[Th(header) for header in headers]))
|
36
|
+
content.append(thead)
|
37
|
+
|
38
|
+
tbody_rows = []
|
39
|
+
for row_data in data:
|
40
|
+
tbody_rows.append(Tr(*[Td(cell) for cell in row_data]))
|
41
|
+
tbody = Tbody(*tbody_rows)
|
42
|
+
content.append(tbody)
|
43
|
+
|
44
|
+
return BaseTable(*content, class_=class_, **kwargs)
|
45
|
+
|
46
|
+
@classmethod
|
47
|
+
def from_dicts(
|
48
|
+
cls,
|
49
|
+
data: list[dict],
|
50
|
+
headers: list[str] | None = None,
|
51
|
+
class_: str | list[str] | None = None,
|
52
|
+
**kwargs: Any,
|
53
|
+
) -> Any:
|
54
|
+
"""Create table from list of dictionaries.
|
55
|
+
|
56
|
+
Args:
|
57
|
+
data: List of dictionaries where each dict is a row
|
58
|
+
headers: Optional list of header strings. If not provided, uses keys from first dict
|
59
|
+
class_: Optional CSS classes to add to the table
|
60
|
+
**kwargs: Additional attributes to pass to the table element
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
A rendered table element
|
64
|
+
|
65
|
+
Example:
|
66
|
+
Table.from_dicts([{"name": "John", "age": 25}], headers=["name", "age"])
|
67
|
+
"""
|
68
|
+
if headers is None and data:
|
69
|
+
headers = list(data[0].keys())
|
70
|
+
|
71
|
+
content = []
|
72
|
+
|
73
|
+
if headers:
|
74
|
+
thead = Thead(Tr(*[Th(header) for header in headers]))
|
75
|
+
content.append(thead)
|
76
|
+
|
77
|
+
tbody_rows = []
|
78
|
+
if data and headers:
|
79
|
+
for row in data:
|
80
|
+
tbody_rows.append(Tr(*[Td(row.get(key, "")) for key in headers]))
|
81
|
+
tbody = Tbody(*tbody_rows)
|
82
|
+
content.append(tbody)
|
83
|
+
|
84
|
+
return BaseTable(*content, class_=class_, **kwargs)
|
eidos/css/styles.css
CHANGED
@@ -339,6 +339,54 @@
|
|
339
339
|
margin: var(--space-xl) 0;
|
340
340
|
}
|
341
341
|
|
342
|
+
/* Table styles */
|
343
|
+
.eidos-table {
|
344
|
+
width: 100%;
|
345
|
+
border-collapse: collapse;
|
346
|
+
font-size: var(--font-size-base);
|
347
|
+
background-color: var(--color-background);
|
348
|
+
}
|
349
|
+
|
350
|
+
.eidos-thead {
|
351
|
+
background-color: var(--color-surface);
|
352
|
+
border-bottom: var(--border-2) solid var(--color-border);
|
353
|
+
}
|
354
|
+
|
355
|
+
.eidos-tbody {
|
356
|
+
background-color: var(--color-background);
|
357
|
+
}
|
358
|
+
|
359
|
+
.eidos-tfoot {
|
360
|
+
background-color: var(--color-surface);
|
361
|
+
border-top: var(--border-2) solid var(--color-border);
|
362
|
+
}
|
363
|
+
|
364
|
+
.eidos-tr {
|
365
|
+
border-bottom: var(--border) solid var(--color-border);
|
366
|
+
transition: background-color var(--transition-fast);
|
367
|
+
}
|
368
|
+
|
369
|
+
.eidos-tbody .eidos-tr:hover {
|
370
|
+
background-color: var(--color-surface);
|
371
|
+
}
|
372
|
+
|
373
|
+
.eidos-tbody .eidos-tr:last-child {
|
374
|
+
border-bottom: none;
|
375
|
+
}
|
376
|
+
|
377
|
+
.eidos-th {
|
378
|
+
padding: var(--space-sm) var(--space-md);
|
379
|
+
text-align: left;
|
380
|
+
font-weight: var(--font-weight-semibold);
|
381
|
+
color: var(--color-text);
|
382
|
+
}
|
383
|
+
|
384
|
+
.eidos-td {
|
385
|
+
padding: var(--space-sm) var(--space-md);
|
386
|
+
text-align: left;
|
387
|
+
color: var(--color-text);
|
388
|
+
}
|
389
|
+
|
342
390
|
/* Navigation base styles */
|
343
391
|
.eidos-navbar {
|
344
392
|
width: 100%;
|
eidos/plugins/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
# EidosUI plugins package
|
1
|
+
# EidosUI plugins package
|
@@ -5,10 +5,10 @@ EidosUI themes through CSS variables.
|
|
5
5
|
|
6
6
|
Basic usage:
|
7
7
|
from eidos.plugins.markdown import Markdown, MarkdownCSS
|
8
|
-
|
8
|
+
|
9
9
|
# In your document head
|
10
10
|
MarkdownCSS()
|
11
|
-
|
11
|
+
|
12
12
|
# In your content
|
13
13
|
Markdown("# Hello World\\n\\nThis is **markdown**!")
|
14
14
|
"""
|
@@ -18,4 +18,4 @@ from .renderer import MarkdownRenderer
|
|
18
18
|
|
19
19
|
__all__ = ["Markdown", "MarkdownCSS", "MarkdownRenderer"]
|
20
20
|
|
21
|
-
__version__ = "0.1.0"
|
21
|
+
__version__ = "0.1.0"
|
@@ -1,53 +1,41 @@
|
|
1
1
|
"""Markdown components for EidosUI"""
|
2
2
|
|
3
3
|
import air
|
4
|
-
from typing import Optional
|
5
|
-
from .renderer import MarkdownRenderer
|
6
4
|
|
5
|
+
from .renderer import MarkdownRenderer
|
7
6
|
|
8
7
|
# Global renderer instance for reuse
|
9
8
|
_renderer = MarkdownRenderer()
|
10
9
|
|
11
10
|
|
12
|
-
def Markdown(content: str, class_:
|
11
|
+
def Markdown(content: str, class_: str | None = None, **kwargs) -> air.Div:
|
13
12
|
"""Main markdown component that renders markdown content with theme integration.
|
14
|
-
|
13
|
+
|
15
14
|
Args:
|
16
15
|
content: Markdown text to render
|
17
16
|
class_: Additional CSS classes to apply
|
18
17
|
**kwargs: Additional attributes to pass to the wrapper div
|
19
|
-
|
18
|
+
|
20
19
|
Returns:
|
21
20
|
air.Div containing the rendered markdown HTML
|
22
21
|
"""
|
23
22
|
# Render the markdown content
|
24
23
|
html_content = _renderer.render(content)
|
25
|
-
|
26
|
-
|
27
|
-
if class_:
|
28
|
-
return air.Div(
|
29
|
-
air.RawHTML(html_content),
|
30
|
-
class_=class_,
|
31
|
-
**kwargs
|
32
|
-
)
|
33
|
-
else:
|
34
|
-
return air.Div(
|
35
|
-
air.RawHTML(html_content),
|
36
|
-
**kwargs
|
37
|
-
)
|
24
|
+
|
25
|
+
return air.Div(air.RawHTML(html_content), class_=class_, **kwargs)
|
38
26
|
|
39
27
|
|
40
28
|
def MarkdownCSS() -> air.Link:
|
41
29
|
"""Returns a link tag to include the markdown CSS.
|
42
|
-
|
30
|
+
|
43
31
|
This should be included in the head of your document to ensure
|
44
32
|
markdown styling is available.
|
45
|
-
|
33
|
+
|
46
34
|
Returns:
|
47
35
|
air.Link element pointing to the markdown CSS file
|
48
36
|
"""
|
49
37
|
return air.Link(
|
50
38
|
rel="stylesheet",
|
51
39
|
href="/eidos/plugins/markdown/css/markdown.css",
|
52
|
-
type="text/css"
|
53
|
-
)
|
40
|
+
type="text/css",
|
41
|
+
)
|