Dash-math_Database / components /render_utils.py
Mochi0622's picture
initial deploy
e66cfb4
Raw
History Blame Contribute Delete
3.22 kB
"""
components/render_utils.py
--------------------------
純渲染工具函式,不依賴任何 Dash callback 或 app 狀態。
供 cards.py、dashTest.py(未來統一後)等元件共用。
公開 API:
_inline_math(latex, style=None) → Dash element
_block_math(latex, style=None) → Dash element
_runs_to_children(runs) → List[Dash element]
"""
from __future__ import annotations
from typing import Any
from dash import html, dcc
import dash_mantine_components as dmc
try:
from dash_latex import DashLatex
except Exception:
DashLatex = None
# ---------------------------------------------------------------------------
# 數學渲染
# ---------------------------------------------------------------------------
def _inline_math(latex: str, style: dict | None = None) -> Any:
"""行內數學式。優先使用 DashLatex(KaTeX),退回 dcc.Markdown MathJax。"""
merged = {"display": "inline-block", "margin": "0 2px", **(style or {})}
if DashLatex:
return html.Span(DashLatex(latex, displayMode=False), style=merged)
src = latex if latex.strip().startswith("$") else f"${latex}$"
return dcc.Markdown(src, mathjax=True, style=merged)
def _block_math(latex: str, style: dict | None = None) -> Any:
"""區塊數學式。優先使用 DashLatex(KaTeX),退回 dcc.Markdown MathJax。"""
merged = {"margin": "8px 0", **(style or {})}
if DashLatex:
return html.Div(DashLatex(latex, displayMode=True), style=merged)
src = latex.strip()
if not (src.startswith("$$") and src.endswith("$$")):
src = f"$$\n{src}\n$$"
return dcc.Markdown(src, mathjax=True, style=merged)
# ---------------------------------------------------------------------------
# Run 列表轉 Dash 元素
# ---------------------------------------------------------------------------
def _runs_to_children(runs: list[dict] | None) -> list[Any]:
"""
把 JSON block 中的 runs 陣列轉成 Dash 子元素清單。
Run 格式:
{"kind": "math", "latex": "..."} → 行內數學
{"text": "...", "style": "bold|italic|bold-italic",
"color_light": "#xxx", "color_dark": "#xxx"} → 文字 span
"""
out: list[Any] = []
for r in runs or []:
# 數學 run
if r.get("kind") == "math" and "latex" in r:
out.append(_inline_math(r["latex"]))
continue
# 文字 run
sty: dict[str, Any] = {}
s = r.get("style", "")
if s == "bold":
sty["fontWeight"] = 700
elif s == "italic":
sty["fontStyle"] = "italic"
elif s == "bold-italic":
sty.update({"fontWeight": 700, "fontStyle": "italic"})
# 主題雙色(light / dark)
cls = None
if r.get("color_light") or r.get("color_dark"):
if r.get("color_light"):
sty["--tc-light"] = r["color_light"]
if r.get("color_dark"):
sty["--tc-dark"] = r["color_dark"]
sty["color"] = "var(--tc, var(--tc-light))"
cls = "themed-color"
out.append(html.Span(r.get("text", ""), style=sty, className=cls))
return out