staticdash 2026.1__py3-none-any.whl → 2026.3__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.
@@ -153,6 +153,16 @@ body {
153
153
  width: 100%;
154
154
  }
155
155
 
156
+ /* Ensure Plotly SVG text inherits a robust font stack so glyphs (e.g., minus) render */
157
+ .plotly {
158
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
159
+ }
160
+ .plotly svg text,
161
+ .plotly .main-svg text {
162
+ font-family: inherit;
163
+ -webkit-font-smoothing: antialiased;
164
+ }
165
+
156
166
  .plot-container .plotly-graph-div {
157
167
  width: 100% !important;
158
168
  height: auto !important;
staticdash/dashboard.py CHANGED
@@ -10,8 +10,38 @@ from dominate.util import raw as raw_util
10
10
  import html
11
11
  import io
12
12
  import base64
13
+ import matplotlib
13
14
  from matplotlib import rc_context
14
15
 
16
+ def split_paragraphs_preserving_math(text):
17
+ """
18
+ Split text into paragraphs on double newlines, preserving math expressions.
19
+ Assumes math is in $...$ (inline) or $$...$$ (display) format.
20
+ """
21
+ math_blocks = []
22
+
23
+ # Replace math with placeholders
24
+ def replace_math(match):
25
+ math_blocks.append(match.group(0))
26
+ return f"__MATH_BLOCK_{len(math_blocks)-1}__"
27
+
28
+ # Handle display math first ($$...$$), then inline ($...$)
29
+ text = re.sub(r'\$\$([^$]+)\$\$', replace_math, text, flags=re.DOTALL)
30
+ text = re.sub(r'\$([^$]+)\$', replace_math, text, flags=re.DOTALL)
31
+
32
+ # Split on double newlines
33
+ paragraphs = text.split('\n\n')
34
+
35
+ # Restore math in each paragraph
36
+ restored_paragraphs = []
37
+ for para in paragraphs:
38
+ for i, block in enumerate(math_blocks):
39
+ para = para.replace(f"__MATH_BLOCK_{i}__", block)
40
+ restored_paragraphs.append(para.strip())
41
+
42
+ # Filter out empty paragraphs
43
+ return [para for para in restored_paragraphs if para]
44
+
15
45
  class AbstractPage:
16
46
  def __init__(self):
17
47
  self.elements = []
@@ -111,7 +141,11 @@ class Page(AbstractPage):
111
141
  outer_style = "display: flex; justify-content: center; margin: 0 auto;"
112
142
  elem = None
113
143
  if kind == "text":
114
- elem = p(content)
144
+ paragraphs = split_paragraphs_preserving_math(content)
145
+ if paragraphs:
146
+ elem = div(*[p(para) for para in paragraphs])
147
+ else:
148
+ elem = p(content)
115
149
  elif kind == "header":
116
150
  text, level = content
117
151
  header_tag = {1: h1, 2: h2, 3: h3, 4: h4}[level]
@@ -135,15 +169,11 @@ class Page(AbstractPage):
135
169
  # to avoid rendering issues when a user's font lacks the U+2212 glyph.
136
170
  try:
137
171
  plotly_html = fig.to_html(full_html=False, include_plotlyjs=False, config={'responsive': True})
138
- if '\u2212' in plotly_html or '−' in plotly_html:
139
- plotly_html = plotly_html.replace('−', '-')
140
172
  elem = div(raw_util(plotly_html))
141
173
  except Exception as e:
142
174
  elem = div(f"Plotly figure could not be rendered: {e}")
143
175
  else:
144
176
  try:
145
- buf = io.BytesIO()
146
- # Ensure we use ASCII hyphen-minus for negative ticks when saving
147
177
  with rc_context({"axes.unicode_minus": False}):
148
178
  fig.savefig(buf, format="png", bbox_inches="tight")
149
179
  buf.seek(0)
@@ -215,7 +245,11 @@ class MiniPage(AbstractPage):
215
245
  outer_style = "display: flex; justify-content: center; margin: 0 auto;"
216
246
  elem = None
217
247
  if kind == "text":
218
- elem = p(content)
248
+ paragraphs = split_paragraphs_preserving_math(content)
249
+ if paragraphs:
250
+ elem = div(*[p(para) for para in paragraphs])
251
+ else:
252
+ elem = p(content)
219
253
  elif kind == "header":
220
254
  text, level = content
221
255
  header_tag = {1: h1, 2: h2, 3: h3, 4: h4}[level]
@@ -236,15 +270,13 @@ class MiniPage(AbstractPage):
236
270
  pass
237
271
  try:
238
272
  plotly_html = fig.to_html(full_html=False, include_plotlyjs=False, config={'responsive': True})
239
- if '\u2212' in plotly_html or '−' in plotly_html:
240
- plotly_html = plotly_html.replace('−', '-')
241
273
  elem = div(raw_util(plotly_html))
242
274
  except Exception as e:
243
275
  elem = div(f"Plotly figure could not be rendered: {e}")
244
276
  else:
245
277
  try:
246
278
  buf = io.BytesIO()
247
- # Ensure we use ASCII hyphen-minus for negative ticks when saving
279
+ # Matplotlib may not be installed in minimal installs; import lazily
248
280
  with rc_context({"axes.unicode_minus": False}):
249
281
  fig.savefig(buf, format="png", bbox_inches="tight")
250
282
  buf.seek(0)
@@ -351,6 +383,9 @@ class Dashboard:
351
383
  shutil.copytree(assets_src, assets_dst, dirs_exist_ok=True)
352
384
 
353
385
  def _add_head_assets(head, rel_prefix, effective_width):
386
+ # Ensure pages declare UTF-8 to avoid character misinterpretation
387
+ head.add(raw_util('<meta charset="utf-8" />'))
388
+ head.add(raw_util('<meta name="viewport" content="width=device-width, initial-scale=1" />'))
354
389
  # Your CSS/JS
355
390
  head.add(link(rel="stylesheet", href=f"{rel_prefix}assets/css/style.css"))
356
391
  head.add(script(type="text/javascript", src=f"{rel_prefix}assets/js/script.js"))
@@ -568,6 +603,8 @@ class Directory:
568
603
 
569
604
  # Add CSS and basic styling
570
605
  with doc.head:
606
+ # Ensure charset is declared for the landing page too
607
+ doc.head.add(raw_util('<meta charset="utf-8" />'))
571
608
  link(rel="stylesheet", href="assets/css/style.css")
572
609
  raw_util("""
573
610
  <style>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staticdash
3
- Version: 2026.1
3
+ Version: 2026.3
4
4
  Summary: A lightweight static HTML dashboard generator with Plotly and pandas support.
5
5
  Author-email: Brian Day <brian.day1@gmail.com>
6
6
  License: CC0-1.0
@@ -11,9 +11,11 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: plotly
12
12
  Requires-Dist: pandas
13
13
  Requires-Dist: dominate
14
- Requires-Dist: reportlab
15
- Requires-Dist: kaleido
16
14
  Requires-Dist: matplotlib
15
+ Provides-Extra: images
16
+ Requires-Dist: kaleido; extra == "images"
17
+ Provides-Extra: all
18
+ Requires-Dist: kaleido; extra == "all"
17
19
 
18
20
  # staticdash
19
21
 
@@ -1,6 +1,6 @@
1
1
  staticdash/__init__.py,sha256=MQGR6LAqx2aFEA64MZz1ADxwpXLPn3VYNVIyjt9qx4Q,268
2
- staticdash/dashboard.py,sha256=9FqhqQmVu_siq_UxAPzyCZ6BLp1MtDKOU3JOjw83C8A,29381
3
- staticdash/assets/css/style.css,sha256=eZX2-pNVUesRWR9ssR63cfmMjJEQkeZqQTU_f93FJGE,6697
2
+ staticdash/dashboard.py,sha256=37OQ_cpJEAsM-syAzGAz-CCR2zLPVnsN8hBKNPI9VsU,30766
3
+ staticdash/assets/css/style.css,sha256=AOYdkw-nK_WvV6im_Y34gz4rJZWifk5o-mRmCKwMP60,7014
4
4
  staticdash/assets/js/script.js,sha256=7xBRlz_19wybbNVwAcfuKNXtDEojGB4EB0Yj4klsoTA,6998
5
5
  staticdash/assets/vendor/mathjax/tex-mml-chtml.js,sha256=MASABpB4tYktI2Oitl4t-78w_lyA-D7b_s9GEP0JOGI,1173007
6
6
  staticdash/assets/vendor/plotly/plotly.min.js,sha256=ChdxmnJ1FwSGEhXaDlxc2z-ajVDv9cuEy2-LgHhmgrA,3632287
@@ -13,7 +13,7 @@ staticdash/assets/vendor/prism/components/prism-json.min.js,sha256=lW2GuqWufsQQZ
13
13
  staticdash/assets/vendor/prism/components/prism-markup.min.js,sha256=h5_J0lbDUtmA4FOFf6cHMwhTuL-2fOKE6mYaJN7FdW4,2850
14
14
  staticdash/assets/vendor/prism/components/prism-python.min.js,sha256=7UOFaFvPLUk1yNu6tL3hZgPaEyngktK_NsPa3WfpqFw,2113
15
15
  staticdash/assets/vendor/prism/components/prism-sql.min.js,sha256=P8X4zmmVDsc63JcvBh30Kq6nj6pIZHCRNOoq3Ag_OjM,3261
16
- staticdash-2026.1.dist-info/METADATA,sha256=wJ5uhhemiHd8BoxyktkpBxZQOBiqv2km8-eSHUKOTsk,2445
17
- staticdash-2026.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- staticdash-2026.1.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
19
- staticdash-2026.1.dist-info/RECORD,,
16
+ staticdash-2026.3.dist-info/METADATA,sha256=XOU934A9XFnn2IqZuHLKp1bo7mA9ShE6UkifQ7G6dWw,2521
17
+ staticdash-2026.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ staticdash-2026.3.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
19
+ staticdash-2026.3.dist-info/RECORD,,