Metabase 国家代码文档模板深度解析:country-codes-template.md 与地图数据文档生成流水线
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
本篇以 country-codes-template.md 这一文档模板文件为主体,拆解它的占位符结构、配套生成脚本 generate-country-code-docs.bb 的完整填充流程,以及模板产物最终如何服务于 Metabase 默认世界地图可视化中的 ISO 3166-1 alpha-2 国家编码匹配。读完本篇,你将掌握该模板的三个占位符含义、数据源与校验规则,并能独立理解(或在本地重新执行)整条「GeoJSON → 模板 → 参考文档」的生成链路。
模板文件本体:一个三占位符的 Markdown 骨架
模板文件位于 bin/templates/country-codes-template.md,全文只有 11 行,结构非常紧凑。它由两部分组成:
- YAML Frontmatter:文件头部的
---围栏内声明title: {{title}},用于生成文档的标题元数据; - 正文骨架:包含一级标题
# {{title}}、两段固定说明文字,以及一个表格占位符{{countries_table}}。
正文中固定说明文字的核心内容是:
This reference lists all country codes and their corresponding country names used in Metabase's default world map visualizations. The data comes from the GeoJSON world map file and includes {{country_count}} countries, territories, and administrative regions.
Use these ISO 3166-1 alpha-2 country codes and country names when working with geographic data in Metabase.
也就是说,模板把「不变的说明文案」和「随数据变化的表格」分离开了——这正是模板化设计的目的:文案改一处即可全局生效,表格则由脚本按数据动态填充。
三个占位符的完整清单
| 占位符 | 出现位置 | 填充值来源 | 生成产物中的实际值 |
|---|---|---|---|
{{title}} | frontmatter 的title:与正文一级标题 | 脚本配置项:markdown-title | Country codes |
{{country_count}} | 说明段落中的国家/地区总数 | extract-countries返回结果的计数 | 250 |
{{countries_table}} | 正文末尾 | format-markdown-table生成的 Markdown 表格文本 | 250 行的国家代码对照表 |
这三个占位符正是生成脚本中replace-template-placeholders函数所处理的全部目标——它依次执行{{title}}、{{country_count}}、{{countries_table}}三个字符串替换,没有任何遗漏项,模板与脚本在此处严格对齐。
填充引擎:generate-country-code-docs.bb 的配置与执行顺序
模板不是被手工编辑的,而是由 babashka 脚本 bin/generate-country-code-docs.bb 消费。脚本顶部的config映射定义了整条流水线的关键路径参数:
(def ^:private config {:geojson-path "resources/frontend_client/app/assets/geojson/world.json" :template-path "bin/templates/country-codes-template.md" :output-path "docs/questions/visualizations/country-codes.md" :markdown-title "Country codes" :table-headers {:code "Country code" :name "Country name"}})各配置项含义如下:
:geojson-path:数据源,指向 world.json——Metabase 内置的世界地图 GeoJSON 文件(约 150 KB 的FeatureCollection)。这个路径同时就是前端默认地图设置中引用的资源路径app/assets/geojson/world.json,即文档生成与地图渲染共用同一份底层数据;:template-path:本模板文件;:output-path:生成物写入位置,即 country-codes.md;:markdown-title:填充{{title}}的值;:table-headers:表格列头,即表头Country code | Country name。
-main函数的文档注释明确列出了 8 步执行顺序:读取 world.json → 提取国家名与 ISO 码 → 校验数据质量 → 生成 Markdown 表格 → 读取本模板 → 替换占位符 → 写出文档文件 → 用 prettier 格式化(若可用)。脚本在文件末尾通过babashka.file属性判断是否为直接执行,是则自动调用-main,因此本地重放只需运行:
bb bin/generate-country-code-docs.bb数据提取与校验:模板表格的行从何而来
表格内容并非直接取自任意字段,而是经过严格的提取与过滤。extract-countries函数从 GeoJSON 的:features中逐个取出:properties,只保留NAME与ISO_A2两个字段:
(map (fn [{:keys [NAME ISO_A2]}] {:name NAME :code ISO_A2}))随后由validate-country逐条校验,一条记录必须同时满足以下条件才会进入模板表格:
name是非空字符串;code是字符串,长度恰好为 2;code完全匹配正则"[A-Z]{2}"(两个大写字母),即标准的 ISO 3166-1 alpha-2 形态。
校验不通过的条目会被静默跳过,脚本打印Skipped %d entries with invalid or missing data告知跳过了多少条;若最终没有任何有效国家,则抛出:no-valid-countries异常终止。有效条目最后按:code字典序排序,这保证了生成的表格(以及最终文档)是稳定、可重复的——这也是产物 country-codes.md 中表格从AD Andorra一路排到ZM Zambia的原因。
format-markdown-table则将排序后的列表拼成标准 Markdown 表格:首行为| Country code | Country name |,第二行为分隔行|----|----|,其后每行一个| XX | 国家名 |。
关键步骤的容错策略
脚本对每一步 I/O 都做了 try/catch 包装,并以带:type的结构化异常上抛:文件不存在抛:file-not-found/:template-not-found,JSON 解析失败抛:parse-error,结构非法(非 map、缺少:features)分别抛:invalid-structure/:invalid-features,写盘失败抛:write-error。-main捕获后打印异常类型与路径并以退出码 1 结束。唯一的「软失败」是 prettier 格式化环节:若npx prettier --write不可用或失败,脚本仅打印警告而不视为错误——模板填充与文件写出已成功,格式只是锦上添花。
模板产物:250 条目的国家代码参考表
经过上述流水线,模板生成的最终文档 docs/questions/visualizations/country-codes.md 共 262 行,包含 250 个国家、属地与行政区域的代码对照表。其开头正是模板中固定文案填充后的样子:
This reference lists all country codes and their corresponding country names used in Metabase's default world map visualizations. The data comes from the GeoJSON world map file and includes 250 countries, territories, and administrative regions.
表格节选(节选自生成产物,非模板原文):
| Country code | Country name |
|---|---|
| AD | Andorra |
| AQ | Antarctica |
| BL | St-Barthélemy |
| BQ | Caribbean Netherlands |
| CC | Cocos Is. |
| CD | Dem. Rep. Congo |
| CH | Switzerland |
需要注意两点:其一,表中存在AQ(南极洲)、BQ(加勒比荷兰)等非常规条目,说明数据完全以 world.json 的properties为准,而不是以某份官方 ISO 列表为准;其二,国家名保留 GeoJSON 中的原始缩写形态(如Dem. Rep. Congo、St-Barthélemy),这保证了与地图着色时按名称/代码匹配的行为完全一致——用户看到的参考表就是地图实际能识别的值。
这些代码在地图可视化中如何被消费
模板文档中强调「Use these ISO 3166-1 alpha-2 country codes and country names when working with geographic data in Metabase」,其依据直接来自前端实现。从源码结构看,Metabase 的着色地图(Choropleth)使用 GeoJSON 中每个 feature 的properties做数据匹配,且内置世界地图的字段约定正好是生成脚本所依赖的那两个字段:
- 前端测试 ChoroplethMap.unit.spec.tsx 中,内置地图 URL 为
app/assets/geojson/world.json(经代理访问时为/api/geojson/world.json),且地图区域字段配置为region_key: "ISO_A2"、region_name: "NAME"; - 静态可视化示例数据 stories-data.ts 同样声明
geoJsonDetails: { region_key: "ISO_A2", region_name: "NAME" }; - 后端由 geojson/api.clj 提供
/api/geojson端点,负责把内置 world.json 与自定义地图的 GeoJSON 资源对外服务。
因此整条链路是自洽的:world.json 的properties.NAME/properties.ISO_A2→ 脚本提取并写入模板 → 模板生成参考文档 → 用户在配置地图区域字段时按文档给出的代码/名称做匹配。模板存在的意义,就是让「文档里的值」永远等于「地图能匹配的值」,避免文档与内置数据漂移——当 world.json 更新后,只需重新运行生成脚本,模板骨架不变、表格自动重建。
小结:模板化文档生成的工程取舍
从 country-codes-template.md 这个 11 行的小文件可以看出 Metabase 文档工程化的一条清晰路线:把易变的数据(250 行表格)与不变的表述(标题文案、使用说明)解耦;用 generate-country-code-docs.bb 中的校验、排序与容错逻辑保证产物确定性和可重放性;用 prettier 统一格式;产物落入文档站点 docs/questions/visualizations/country-codes.md 供用户查阅。对于「参考表类」文档(代码表、枚举表、地域表),这种「模板 + 数据源 + 单一事实来源脚本」的组合,是避免手写表格随上游数据腐化的务实做法,值得在维护类似文档时参照。
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考