eidosui 0.4.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 +296 -55
- 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.4.0.dist-info/METADATA +0 -127
- eidosui-0.4.0.dist-info/RECORD +0 -22
- {eidosui-0.4.0.dist-info → eidosui-0.5.0.dist-info}/WHEEL +0 -0
- {eidosui-0.4.0.dist-info → eidosui-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1 +1 @@
|
|
1
|
-
# Markdown plugin extensions
|
1
|
+
# Markdown plugin extensions
|
@@ -1,134 +1,124 @@
|
|
1
1
|
"""GitHub-style alerts extension for markdown"""
|
2
2
|
|
3
3
|
import re
|
4
|
-
from markdown.extensions import Extension
|
5
|
-
from markdown.blockprocessors import BlockProcessor
|
6
4
|
import xml.etree.ElementTree as etree
|
7
5
|
from xml.etree.ElementTree import SubElement
|
8
6
|
|
7
|
+
from markdown.blockprocessors import BlockProcessor
|
8
|
+
from markdown.extensions import Extension
|
9
|
+
|
9
10
|
|
10
11
|
class AlertBlockProcessor(BlockProcessor):
|
11
12
|
"""Process GitHub-style alert blocks"""
|
12
|
-
|
13
|
+
|
13
14
|
# Pattern to match > [!TYPE] at the start of a blockquote
|
14
|
-
RE_ALERT = re.compile(r
|
15
|
-
|
15
|
+
RE_ALERT = re.compile(r"^> \[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]", re.MULTILINE)
|
16
|
+
|
16
17
|
# Alert type configurations
|
17
18
|
ALERT_TYPES = {
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
"NOTE": {"class": "eidos-alert eidos-alert-info", "icon": "ℹ️", "title": "Note"},
|
20
|
+
"TIP": {
|
21
|
+
"class": "eidos-alert eidos-alert-success",
|
22
|
+
"icon": "💡",
|
23
|
+
"title": "Tip",
|
22
24
|
},
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
"IMPORTANT": {
|
26
|
+
"class": "eidos-alert eidos-alert-warning",
|
27
|
+
"icon": "❗",
|
28
|
+
"title": "Important",
|
27
29
|
},
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
"WARNING": {
|
31
|
+
"class": "eidos-alert eidos-alert-warning",
|
32
|
+
"icon": "⚠️",
|
33
|
+
"title": "Warning",
|
32
34
|
},
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
"CAUTION": {
|
36
|
+
"class": "eidos-alert eidos-alert-error",
|
37
|
+
"icon": "🔴",
|
38
|
+
"title": "Caution",
|
37
39
|
},
|
38
|
-
'CAUTION': {
|
39
|
-
'class': 'eidos-alert eidos-alert-error',
|
40
|
-
'icon': '🔴',
|
41
|
-
'title': 'Caution'
|
42
|
-
}
|
43
40
|
}
|
44
|
-
|
41
|
+
|
45
42
|
def test(self, parent, block):
|
46
43
|
"""Test if the block is a GitHub-style alert"""
|
47
44
|
return bool(self.RE_ALERT.match(block))
|
48
|
-
|
45
|
+
|
49
46
|
def run(self, parent, blocks):
|
50
47
|
"""Process the alert block"""
|
51
48
|
block = blocks.pop(0)
|
52
|
-
|
49
|
+
|
53
50
|
# Extract alert type
|
54
51
|
match = self.RE_ALERT.match(block)
|
55
52
|
if not match:
|
56
53
|
return False
|
57
|
-
|
54
|
+
|
58
55
|
alert_type = match.group(1)
|
59
|
-
alert_config = self.ALERT_TYPES.get(alert_type, self.ALERT_TYPES[
|
60
|
-
|
56
|
+
alert_config = self.ALERT_TYPES.get(alert_type, self.ALERT_TYPES["NOTE"])
|
57
|
+
|
61
58
|
# Create the alert container
|
62
|
-
alert_div = SubElement(parent,
|
63
|
-
alert_div.set(
|
64
|
-
|
59
|
+
alert_div = SubElement(parent, "div")
|
60
|
+
alert_div.set("class", alert_config["class"])
|
61
|
+
|
65
62
|
# Add the header with icon and title
|
66
|
-
header = SubElement(alert_div,
|
67
|
-
header.set(
|
68
|
-
|
69
|
-
icon_span = SubElement(header,
|
70
|
-
icon_span.set(
|
71
|
-
icon_span.text = alert_config[
|
72
|
-
|
73
|
-
title_span = SubElement(header,
|
74
|
-
title_span.set(
|
75
|
-
title_span.text = alert_config[
|
76
|
-
|
77
|
-
|
78
|
-
content_div
|
79
|
-
|
80
|
-
|
63
|
+
header = SubElement(alert_div, "div")
|
64
|
+
header.set("class", "eidos-alert-header")
|
65
|
+
|
66
|
+
icon_span = SubElement(header, "span")
|
67
|
+
icon_span.set("class", "eidos-alert-icon")
|
68
|
+
icon_span.text = alert_config["icon"]
|
69
|
+
|
70
|
+
title_span = SubElement(header, "span")
|
71
|
+
title_span.set("class", "eidos-alert-title")
|
72
|
+
title_span.text = alert_config["title"]
|
73
|
+
|
74
|
+
content_div = SubElement(alert_div, "div")
|
75
|
+
content_div.set("class", "eidos-alert-content")
|
76
|
+
|
81
77
|
# Remove the alert marker and process the remaining content
|
82
|
-
content = self.RE_ALERT.sub(
|
83
|
-
|
84
|
-
|
85
|
-
lines = content.split('\n')
|
78
|
+
content = self.RE_ALERT.sub("", block)
|
79
|
+
|
80
|
+
lines = content.split("\n")
|
86
81
|
processed_lines = []
|
87
|
-
|
82
|
+
|
88
83
|
for line in lines:
|
89
84
|
# Remove leading '>' from each line
|
90
|
-
if line.startswith(
|
85
|
+
if line.startswith(">"):
|
91
86
|
line = line[1:].lstrip()
|
92
87
|
processed_lines.append(line)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
88
|
+
|
89
|
+
content_text = "\n".join(processed_lines).strip()
|
90
|
+
|
97
91
|
# Parse the content as markdown
|
98
92
|
if content_text:
|
99
|
-
|
100
|
-
temp_element = etree.Element('div')
|
93
|
+
temp_element = etree.Element("div")
|
101
94
|
self.parser.parseBlocks(temp_element, [content_text])
|
102
|
-
|
103
|
-
# Move all children to our content div
|
95
|
+
|
104
96
|
for child in temp_element:
|
105
97
|
content_div.append(child)
|
106
|
-
|
107
|
-
# If no children were added, add the text directly
|
98
|
+
|
108
99
|
if len(content_div) == 0:
|
109
|
-
p = SubElement(content_div,
|
100
|
+
p = SubElement(content_div, "p")
|
110
101
|
p.text = content_text
|
111
|
-
|
102
|
+
|
112
103
|
# Continue processing subsequent blocks that might be part of the alert
|
113
|
-
while blocks and blocks[0].startswith(
|
104
|
+
while blocks and blocks[0].startswith(">"):
|
114
105
|
continuation = blocks.pop(0)
|
115
|
-
|
116
|
-
|
117
|
-
|
106
|
+
continuation_text = continuation[1:].lstrip() if continuation.startswith(">") else continuation
|
107
|
+
|
118
108
|
if continuation_text:
|
119
|
-
p = SubElement(content_div,
|
109
|
+
p = SubElement(content_div, "p")
|
120
110
|
p.text = continuation_text
|
121
|
-
|
111
|
+
|
122
112
|
return True
|
123
113
|
|
124
114
|
|
125
115
|
class AlertExtension(Extension):
|
126
116
|
"""Add GitHub-style alerts to markdown"""
|
127
|
-
|
117
|
+
|
128
118
|
def extendMarkdown(self, md):
|
129
119
|
"""Add the alert processor to the markdown instance"""
|
130
120
|
md.parser.blockprocessors.register(
|
131
121
|
AlertBlockProcessor(md.parser),
|
132
|
-
|
133
|
-
175 # Priority - process before blockquote
|
134
|
-
)
|
122
|
+
"github_alerts",
|
123
|
+
175, # Priority - process before blockquote
|
124
|
+
)
|
@@ -1,58 +1,53 @@
|
|
1
1
|
"""Core markdown rendering with theme integration"""
|
2
2
|
|
3
3
|
import markdown
|
4
|
-
|
4
|
+
|
5
5
|
from .extensions.alerts import AlertExtension
|
6
6
|
|
7
7
|
|
8
8
|
class MarkdownRenderer:
|
9
9
|
"""Core markdown rendering with theme integration"""
|
10
|
-
|
11
|
-
def __init__(self, extensions:
|
10
|
+
|
11
|
+
def __init__(self, extensions: list[str | markdown.Extension] | None = None):
|
12
12
|
"""Initialize the renderer with optional extensions.
|
13
|
-
|
13
|
+
|
14
14
|
Args:
|
15
15
|
extensions: List of markdown extension names or instances to enable
|
16
16
|
"""
|
17
17
|
self.extensions = extensions or []
|
18
18
|
# Add some useful default extensions
|
19
19
|
default_extensions = [
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
AlertExtension() #
|
20
|
+
"fenced_code",
|
21
|
+
"tables",
|
22
|
+
"nl2br",
|
23
|
+
"sane_lists",
|
24
|
+
AlertExtension(), # GitHub-style alerts
|
25
25
|
]
|
26
26
|
self.extensions.extend(default_extensions)
|
27
|
-
|
28
|
-
# Initialize the markdown processor
|
27
|
+
|
29
28
|
self.md = markdown.Markdown(extensions=self.extensions)
|
30
|
-
|
29
|
+
|
31
30
|
def render(self, markdown_text: str) -> str:
|
32
31
|
"""Convert markdown to themed HTML.
|
33
|
-
|
32
|
+
|
34
33
|
Args:
|
35
34
|
markdown_text: Raw markdown text to render
|
36
|
-
|
35
|
+
|
37
36
|
Returns:
|
38
37
|
HTML string wrapped with eidos-md class for styling
|
39
38
|
"""
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
# Convert markdown to HTML
|
39
|
+
self.md.reset() # TODO: this is a hack to clear the state of the markdown processor
|
40
|
+
|
44
41
|
html_content = self.md.convert(markdown_text)
|
45
|
-
|
46
|
-
# Wrap in a div with our markdown class for styling
|
42
|
+
|
47
43
|
return f'<div class="eidos-md">{html_content}</div>'
|
48
|
-
|
44
|
+
|
49
45
|
def add_extension(self, extension: str) -> None:
|
50
46
|
"""Add a markdown extension.
|
51
|
-
|
47
|
+
|
52
48
|
Args:
|
53
49
|
extension: Name of the markdown extension to add
|
54
50
|
"""
|
55
51
|
if extension not in self.extensions:
|
56
52
|
self.extensions.append(extension)
|
57
|
-
|
58
|
-
self.md = markdown.Markdown(extensions=self.extensions)
|
53
|
+
self.md = markdown.Markdown(extensions=self.extensions)
|
eidos/styles.py
CHANGED
@@ -6,16 +6,19 @@ Only includes classes that are actually defined in the CSS file.
|
|
6
6
|
|
7
7
|
from typing import Final
|
8
8
|
|
9
|
+
|
9
10
|
class Theme:
|
10
11
|
"""Theme-related CSS classes from styles.css."""
|
12
|
+
|
11
13
|
body: Final[str] = "eidos-body"
|
12
14
|
|
15
|
+
|
13
16
|
class Buttons:
|
14
17
|
"""Button-related CSS classes from styles.css."""
|
15
|
-
|
18
|
+
|
16
19
|
# Base button class (required for all buttons)
|
17
20
|
base: Final[str] = "eidos-btn"
|
18
|
-
|
21
|
+
|
19
22
|
# Button variants
|
20
23
|
primary: Final[str] = "eidos-btn-primary"
|
21
24
|
secondary: Final[str] = "eidos-btn-secondary"
|
@@ -25,6 +28,7 @@ class Buttons:
|
|
25
28
|
error: Final[str] = "eidos-btn-error"
|
26
29
|
cta: Final[str] = "eidos-btn-cta"
|
27
30
|
|
31
|
+
|
28
32
|
class Typography:
|
29
33
|
"""Typography-related CSS classes from styles.css."""
|
30
34
|
|
@@ -35,9 +39,10 @@ class Typography:
|
|
35
39
|
h5: Final[str] = "eidos-h5"
|
36
40
|
h6: Final[str] = "eidos-h6"
|
37
41
|
|
42
|
+
|
38
43
|
class Semantic:
|
39
44
|
"""Semantic HTML element CSS classes from styles.css."""
|
40
|
-
|
45
|
+
|
41
46
|
# Text formatting
|
42
47
|
strong: Final[str] = "eidos-strong"
|
43
48
|
i: Final[str] = "eidos-i"
|
@@ -47,34 +52,53 @@ class Semantic:
|
|
47
52
|
var: Final[str] = "eidos-var"
|
48
53
|
mark: Final[str] = "eidos-mark"
|
49
54
|
time: Final[str] = "eidos-time"
|
50
|
-
|
55
|
+
|
51
56
|
# Code elements
|
52
57
|
code: Final[str] = "eidos-code"
|
53
58
|
pre: Final[str] = "eidos-pre"
|
54
59
|
kbd: Final[str] = "eidos-kbd"
|
55
60
|
samp: Final[str] = "eidos-samp"
|
56
|
-
|
61
|
+
|
57
62
|
# Structural elements
|
58
63
|
blockquote: Final[str] = "eidos-blockquote"
|
59
64
|
cite: Final[str] = "eidos-cite"
|
60
65
|
address: Final[str] = "eidos-address"
|
61
66
|
hr: Final[str] = "eidos-hr"
|
62
|
-
|
67
|
+
|
63
68
|
# Interactive elements
|
64
69
|
details: Final[str] = "eidos-details"
|
65
70
|
summary: Final[str] = "eidos-summary"
|
66
71
|
details_content: Final[str] = "eidos-details-content"
|
67
|
-
|
72
|
+
|
68
73
|
# Definition list
|
69
74
|
dl: Final[str] = "eidos-dl"
|
70
75
|
dt: Final[str] = "eidos-dt"
|
71
76
|
dd: Final[str] = "eidos-dd"
|
72
|
-
|
77
|
+
|
73
78
|
# Figure
|
74
79
|
figure: Final[str] = "eidos-figure"
|
75
80
|
figcaption: Final[str] = "eidos-figcaption"
|
76
81
|
|
82
|
+
|
83
|
+
class Tables:
|
84
|
+
"""Table-related CSS classes from styles.css."""
|
85
|
+
|
86
|
+
# Base table class
|
87
|
+
table: Final[str] = "eidos-table"
|
88
|
+
|
89
|
+
# Table sections
|
90
|
+
thead: Final[str] = "eidos-thead"
|
91
|
+
tbody: Final[str] = "eidos-tbody"
|
92
|
+
tfoot: Final[str] = "eidos-tfoot"
|
93
|
+
|
94
|
+
# Table elements
|
95
|
+
tr: Final[str] = "eidos-tr"
|
96
|
+
th: Final[str] = "eidos-th"
|
97
|
+
td: Final[str] = "eidos-td"
|
98
|
+
|
99
|
+
|
77
100
|
# Create singleton instance for easy access
|
78
101
|
buttons = Buttons()
|
79
102
|
typography = Typography()
|
80
|
-
semantic = Semantic()
|
103
|
+
semantic = Semantic()
|
104
|
+
tables = Tables()
|