v0.1.21
单一主题:让写进 wiki 的数字自己说话——观澜经 MCP 接入结构化数据库后,Agent 取到的结果行
此前只能以表格或裸 JSON 落盘。P4.20 把最后一公里补上:```flint 规格块在浏览器内编译成图表,
而同一段 markdown 在 CLI / 纯文本回退里仍是 honest 的规格源码(规格与数据都在块里,零信息损失)。
服务端零改、无接口破坏、无新退出码、无新依赖。全量 1231 passed / 1 skipped。
新增
- Web 里的
```flint围栏块被编译渲染成数据图表(P4.20,见
docs/P4.20-Web-flint图表渲染.md) —— wiki 页与对话答案里的
flint 图表规格 JSON 不再显示成一坨源码,而是在浏览器内编译成柱/线/散点/热力等图(37 种图型)。
承 P4.13(mermaid)/ P4.14(数学·化学·代码)同一骨架:服务端零改(render.py一个字节没动)、
vendored 运行时、懒加载、安全闸硬编码、失败保留源码。P4.14 的enhanceContent编排器让七个注入点
一个字不动,本相位只在编排器里加一行。存在的理由是观澜经 MCP 接入用户的结构化数据库后有了可视化需求——
Agent 取数 → 把结果行写成数据整体内联的 flint 块 → 浏览器成图。- 图是快照,浏览器永不出网(决策P4.20-5/-12):只认内联
data.values,拒data.url;
刷新数据 = 重新问答产出新块,不是让前端去查库。于是图 100% 可从那段 markdown 重建,
check/graph/search全部原样复用。 - 安全闸:入口白名单(只五个顶层键)→ flint 生成式编译(不 merge 用户私货)→ 键域出口断言 →
renderer:'svg'+tooltip.renderMode:'richText'(tooltip 不走 HTML 通道)。输入是纯 JSON、
没有函数,ECharts 的回调注入面天然不存在——这正是选 flint 而非让模型直接写 ECharts option 的理由。 - 资源闸三条(结构化库接入独有的问题):块源 64 K 字符、
data.values1000 行、画布尺寸有限数且
在范围内。超限不渲染、保留源码 + 「数据过大」徽标,不静默截断——截断出的图会说谎,比裸 JSON 更坏。 - 闸子不只要「拦得住」,还要「不乱拒」(决策P4.20-16):把 37 个图型 × 各自正确的数据形状逐个跑完整链,
一次揪出四例误杀——Waterfall Chart的renderItem是 flint 自己造的函数、Sankey/Network Graph
的links[].target是节点名、Sunburst Chart缺color时 flint 静默回吐非 ECharts 中间态
(会被尺寸闸误报成「数据过大」,把作者引向删数据这条错路)。⇒target移出黑名单、renderItem改判
「必须是函数」、加not-echarts-option形态守门。这条全集扫描已设为常驻冒烟场景 + 升级复核项:
打桩只能证「该拒的拒得住」,「不该拒的不乱拒」只能靠把全集跑一遍。 - 前端第一个有状态渲染器(决策P4.20-7):ECharts 实例挂在它自己的全局注册表上,切语言/切预览会让旧
<figure>脱树——每次增强前先清扫并dispose,否则每切一次泄漏一份。mermaid/KaTeX/hljs 都是一次性
DOM 变换、没有这个义务。 - 渲染是对 DOM 的事务(决策P4.20-15):整条链在
<pre>还挂在树上时跑完,replaceWith是最后一步。
反过来做会漏掉一整类失败——setOption抛错时源码已脱树,既贴不上徽标也回不去,页面留一个空白。 - 配套独立作者 skill
flint-chart-author(决策P4.20-11):mermaid/LaTeX 模型本就会写,flint 不会,
没有作者侧供给渲染器就是「通了电没有灯」。它不进guanlan-wiki——作图与 wiki 维护(页型/frontmatter/
wikilink/索引)是两条正交的轴,且本仓已有pdf-to-markdown这个同形态先例。图型×通道表由 vendored 资产
确定性生成,升级重跑即可、不与钉版漂移。 - vendored 两枚资产:
flint-chart@0.4.1(531,443 B,MIT)+echarts@6.1.0(1,121,883 B,Apache-2.0),
合计 1.65 MB、不到既有mermaid.min.js的一半,钉版 + SHA256 记vendor/README.md。flint dist 是
自包含单文件 ESM,经动态import()加载——本仓唯一走 ESM 的 vendored 资产,仍无 npm、无构建。 - 对编译产物的「事后改写」被收紧成一条原则(决策P4.20-19,实现后 xhigh 评审的主要收敛):
能让 flint 自己算的,绝不在事后改。按栏宽收窄改为拿chart_spec.canvasSize重编译——
此前是编译完再改画布尺寸,而 flint 把legend.left等按自己算出的宽度烤成绝对像素,
缩画布会把整个图例画到视口之外(图还在、没有徽标,读者却分不清哪条线是哪个模型)。
剩下的三类事后改写各自限定到能讲清楚:逐槽换色(映射表从产物自身的color现造,语义色图型
整张跳过——否则 Waterfall 的「跌」会被画成绿的)、tooltip 的 HTML 串压成纯文本(flint 的 formatter
返回<br/>,而richText不解析 HTML,不压就会画出字面标签)、补viewBox。 - 三档失败文案,各归各的:「数据过大」(行数/体积/画布)、「数据被截断」(flint 自己超预算整批
丢掉类别,color通道尤其无声)、「渲染失败」(其余)。修法完全不同——前者减行、中者减类别数、
后者改规格;合并任意两条都会把作者引向错路。画布闸同时去掉了下界:小画布不消耗资源,
而 flint 按语义定尺寸时小图很常见(两周的 Calendar Heatmap 只有 114px),拒它纯属误伤。 - 无接口破坏、无新退出码、无新依赖(两枚资产随既有
webextra 的静态资源打包)。
16 条服务端契约用例(tests/test_web.py)+ 真浏览器冒烟 18/18(scripts/smoke_p420.py,
新增的三条都做过反向对照:摘掉对应修复后用例确实变红)。
- 图是快照,浏览器永不出网(决策P4.20-5/-12):只认内联
修复
docs/发布到-PyPI.md的「验证」段改为 uv 口径——原来那条命令跑不通:uv venv不带 pip
(除非--seed),故<venv>/bin/pip install …必然no such file;且 uv 用--no-cache
而 pip 用--no-cache-dir、--python不显式给会装进开发树的.venv。v0.1.20 发版实操中撞上,
已按实际可跑的口径改写,并补上「装[web,mcp]extra 才覆盖到guanlan/web/、guanlan/mcp/
随包内容」这一条。
Full Changelog: v0.1.20...v0.1.21