{title}{badge_html}
{description}
{metadata_html} {tags_html} {details_html} {links_html}from PWF.Convention.Runtime.Config import * from PWF.CoreModules.plugin_interface import PluginInterface from PWF.CoreModules.flags import * from PWF.Convention.Runtime.Architecture import Architecture from PWF.Convention.Runtime.GlobalConfig import ProjectConfig from PWF.Convention.Runtime.Web import ToolURL from PWF.Convention.Runtime.String import LimitStringLength from fastapi.responses import HTMLResponse from dataclasses import dataclass, field import httpx import re logger: ProjectConfig = Architecture.Get(ProjectConfig) MAIN_WEBHOOK_URL = logger.FindItem("main_webhook_url", "") logger.SaveProperties() class GuideEntry(TypedDict, total=False): """单条图鉴信息。""" title: str identifier: str description: str category: str metadata: Dict[str, str] icon: str badge: str links: Sequence[Dict[str, str]] tags: Sequence[str] details: Sequence[Union[str, Dict[str, Any]]] group: str @dataclass(frozen=True) class GuideSection: """图鉴章节。""" title: str entries: Sequence[GuideEntry] = field(default_factory=tuple) description: str = "" layout: str = "grid" section_id: str | None = None @dataclass(frozen=True) class GuidePage: """完整图鉴页面。""" title: str sections: Sequence[GuideSection] = field(default_factory=tuple) subtitle: str = "" metadata: Dict[str, str] = field(default_factory=dict) related_links: Dict[str, Sequence[Dict[str, str]]] = field(default_factory=dict) def render_markdown_page(page: GuidePage) -> str: """保留 Markdown 渲染(备用)。""" def _render_section(section: GuideSection) -> str: lines: List[str] = [f"## {section.title}"] if section.description: lines.append(section.description) if not section.entries: lines.append("> 暂无内容。") return "\n".join(lines) for entry in section.entries: title = entry.get("title", "未命名") identifier = entry.get("identifier") desc = entry.get("description", "") category = entry.get("category") metadata = entry.get("metadata", {}) bullet = f"- **{title}**" if identifier: bullet += f"|`{identifier}`" if category: bullet += f"|{category}" lines.append(bullet) if desc: lines.append(f" - {desc}") for meta_key, meta_value in metadata.items(): lines.append(f" - {meta_key}:{meta_value}") return "\n".join(lines) lines: List[str] = [f"# {page.title}"] if page.subtitle: lines.append(page.subtitle) if page.metadata: lines.append("") for key, value in page.metadata.items(): lines.append(f"- {key}:{value}") for section in page.sections: lines.append("") lines.append(_render_section(section)) return "\n".join(lines) def render_html_page(page: GuidePage) -> str: """渲染 Apple Store 风格的 HTML 页面。""" def escape(text: Optional[str]) -> str: if not text: return "" return ( text.replace("&", "&") .replace("<", "<") .replace(">", ">") .replace('"', """) ) def render_metadata(metadata: Dict[str, str]) -> str: if not metadata: return "" cards = [] for key, value in metadata.items(): cards.append( f"""
""" ) return f'' def render_links(links: Optional[Sequence[Dict[str, str]]]) -> str: if not links: return "" items = [] for link in links: href = escape(link.get("href", "#")) label = escape(link.get("label", "前往")) items.append(f'{label}') return "".join(items) def render_tags(tags: Optional[Sequence[str]]) -> str: if not tags: return "" chips = "".join(f'{escape(tag)}' for tag in tags) return f'' def render_details(details: Optional[Sequence[Union[str, Dict[str, Any]]]]) -> str: if not details: return "" blocks: List[str] = [] for detail in details: if isinstance(detail, str): blocks.append(f'{escape(detail)}
') elif isinstance(detail, dict): kind = detail.get("type") if kind == "list": items = "".join( f'{identifier}' if identifier else ""
category_html = f'{category}' if category else ""
badge_html = f'{badge}' if badge else ""
icon_html = f'' if icon else ""
links_html = render_links(entry.get("links"))
tags_html = render_tags(entry.get("tags"))
details_html = render_details(entry.get("details"))
group = escape(entry.get("group"))
group_attr = f' data-group="{group}"' if group else ""
return f"""
{description}
{metadata_html} {tags_html} {details_html} {links_html}{escape(section.description)}
' if section.description else "" ) if not cards: cards = '{escape(page.subtitle)}
' if page.subtitle else "" return f"""