MarsDawn

和你的代理一起做主题

给制作 MarsDawn 预览主题的 AI 代理的参考。代理写出一个 theme.json,用 marsdawn 命令行工具检查并渲染,再把链接交给你。你在打造一个主题页面用眼睛调整,然后投稿。下面的字段表直接读自 kit 的源代码,并有检查确保两者一致。

写出一个 theme.json,反复运行 marsdawn theme validate theme.json --require-complete --json 直到退出代码为 0,用 marsdawn theme preview 分别渲染浅色与深色,再把链接交给用户。主题只有参数,不含任何 CSS。

主题是什么

不在下面表格里的键是错误,同一个键写两次也是。文件最大 16,384 字节。

检查与渲染

在放有 theme.json 的文件夹里运行这些命令。需要 marsdawn 工具:见给 AI 代理的 marsdawn 参考。

marsdawn theme validate theme.json --require-complete --json
marsdawn theme css theme.json --json
marsdawn theme preview theme.json --appearance light -o light.png
marsdawn theme preview theme.json --appearance dark -o dark.png

从内置主题开始

复制四个内置主题之一再修改。每一个都是完整且有效的文件:

范例:Dawn

这是 dawn.json,一个字节都没改。它唯一的样式选项是 hr 的一条细的强调色分隔线。

{
  "schemaVersion": 1,
  "id": "dawn",
  "version": "1.0.0",
  "name": { "en": "Dawn" },
  "summary": { "en": "Warm Martian sunrise" },
  "fontDesign": "sans",
  "scenarios": ["agent-review"],
  "light": {
    "background": "#FFFDFB", "surface": "#F6F0EC", "text": "#26211F", "muted": "#6F6660",
    "border": "#EADFD8", "heading": "#26211F", "accent": "#C8471B", "link": "#B03C0C", "quote": "#D97A4A",
    "syntax": { "keyword": "#B03C0C", "string": "#2F6F5E", "comment": "#746B66", "number": "#9A5B00", "function": "#5B3E8C", "type": "#1F6FB2" },
    "diagram": { "node": "#FBE9E0", "nodeBorder": "#CA6C3C", "text": "#26211F", "line": "#8A6A5C", "secondary": "#E6F1EE", "tertiary": "#FFF6F1", "note": "#FFF1D6" }
  },
  "dark": {
    "background": "#1C1A1F", "surface": "#262229", "text": "#EBE4DF", "muted": "#A39992",
    "border": "#3A343A", "heading": "#F4EEEA", "accent": "#FF8A50", "link": "#FF9E6B", "quote": "#E08A5C",
    "syntax": { "keyword": "#FF9E6B", "string": "#7FD1B9", "comment": "#938A84", "number": "#F2C572", "function": "#C7A6F5", "type": "#6CB6FF" },
    "diagram": { "node": "#3A2A26", "nodeBorder": "#E08A5C", "text": "#EBE4DF", "line": "#B8A69C", "secondary": "#23332F", "tertiary": "#2B2427", "note": "#3D3322" }
  },
  "style": {
    "hr": { "style": { "type": "line", "color": "accent", "thickness": 1 } }
  }
}

字段

下面每个对象都用同样的方式读取。required 表示这个键必须存在,没有列出的键都是错误。

类型:string、integer、number、boolean、map(语言标签对应文字)、enum(列出的值之一)、role(色板角色)和 object(连到它的表格)。类型后面的 [] 表示列表。

theme.json

字段类型必填与否值与备注
schemaVersionintegerrequired固定是 1。
idstringrequired1 到 32 个字符:小写字母与数字,以单一连字符连接成段,例如 calm-green。
versionstringrequiredMAJOR.MINOR.PATCH,例如 1.0.0。
namemaprequired语言标签对应文字。en 必填,其他键是像 zh-Hant 的语言标签。每段文字最多 48 个字符,不可含链接或换行。
summarymaprequired和 name 的形式相同,每段文字最多 120 个字符。
fontDesignenumrequiredsans, serif, rounded
scenariosenum[]requiredagent-review, technical-docs, formal-output, notes-sharing — 一个或两个,不可重复。它们决定主题必须达到多高的对比。
authorobjectoptionalauthor
licensestringoptionalSPDX 标识符,例如 Apache-2.0。投稿的主题以 Apache-2.0 发布。
lightobjectrequiredlight, dark
darkobjectrequiredlight, dark
styleobjectoptionalstyle

author

字段类型必填与否值与备注
namestringrequired最多 64 个字符,不可含链接。
githubstringoptionalGitHub 账号。投稿时请填投稿者自己的账号。

light, dark

字段类型必填与否值与备注
backgroundstringrequired# 加六个十六进制数字,例如 #1C1C1C。
surfacestringrequired# 加六个十六进制数字,例如 #1C1C1C。
textstringrequired# 加六个十六进制数字,例如 #1C1C1C。
mutedstringrequired# 加六个十六进制数字,例如 #1C1C1C。
borderstringrequired# 加六个十六进制数字,例如 #1C1C1C。
headingstringrequired# 加六个十六进制数字,例如 #1C1C1C。
accentstringrequired# 加六个十六进制数字,例如 #1C1C1C。
linkstringrequired# 加六个十六进制数字,例如 #1C1C1C。
quotestringrequired# 加六个十六进制数字,例如 #1C1C1C。
syntaxobjectoptional (发布时必填,用 --require-complete 检查)syntax
diagramobjectoptional (发布时必填,用 --require-complete 检查)diagram

syntax

字段类型必填与否值与备注
keywordstringrequired# 加六个十六进制数字,例如 #1C1C1C。
stringstringrequired# 加六个十六进制数字,例如 #1C1C1C。
commentstringrequired# 加六个十六进制数字,例如 #1C1C1C。
numberstringrequired# 加六个十六进制数字,例如 #1C1C1C。
functionstringrequired# 加六个十六进制数字,例如 #1C1C1C。
typestringrequired# 加六个十六进制数字,例如 #1C1C1C。

diagram

字段类型必填与否值与备注
nodestringrequired# 加六个十六进制数字,例如 #1C1C1C。
nodeBorderstringrequired# 加六个十六进制数字,例如 #1C1C1C。
textstringrequired# 加六个十六进制数字,例如 #1C1C1C。
linestringrequired# 加六个十六进制数字,例如 #1C1C1C。
secondarystringrequired# 加六个十六进制数字,例如 #1C1C1C。
tertiarystringrequired# 加六个十六进制数字,例如 #1C1C1C。
notestringrequired# 加六个十六进制数字,例如 #1C1C1C。

style

字段类型必填与否值与备注
bodySizenumberoptional范围
lineHeightnumberoptional范围
headingWeightnumberoptional范围
radiusnumberoptional范围
maxWidthnumberoptional范围
h1objectoptionalstyle.h1
h2objectoptionalstyle.h2
blockquoteobjectoptionalstyle.blockquote
hrobjectoptionalstyle.hr
tableobjectoptionalstyle.table
listMarkerroleoptional色板角色
inlineCoderoleoptional色板角色 — 只能是 text 或语法角色:keyword、string、comment、number、function 或 type。
linkobjectoptionalstyle.link
syntaxobjectoptionalstyle.syntax

style.h1

字段类型必填与否值与备注
sizenumberoptional范围
letterSpacingnumberoptional范围
alignenumoptionalleft, center
decorationobjectoptionaltype

style.h2

字段类型必填与否值与备注
letterSpacingnumberoptional范围
decorationobjectoptionaltype
italicbooleanoptionaltrue, false

style.blockquote

字段类型必填与否值与备注
styleobjectoptionaltype
italicbooleanoptionaltrue, false

style.hr

字段类型必填与否值与备注
styleobjectoptionaltype

style.table

字段类型必填与否值与备注
headerobjectoptionaltype
verticalRulesbooleanoptionaltrue, false
roundedbooleanoptionaltrue, false
字段类型必填与否值与备注
underlinebooleanoptionaltrue, false

style.syntax

字段类型必填与否值与备注
boldKeywordsbooleanoptionaltrue, false

带 type 的选项

这些样式选项是带有 type 的对象。每个 type 只接受为它列出的字段,其他都不行。

选项type字段必填与否类型
style.h1.decorationrule———
style.h1.decorationnone———
style.h1.decorationshortRulecolorrequiredrole
style.h1.decorationgradientBarfromrequiredrole
style.h1.decorationgradientBartorequiredrole
style.h2.decorationrule———
style.h2.decorationnone———
style.h2.decorationdotcolorrequiredrole
style.blockquote.stylebarwidthoptionalnumber 范围
style.blockquote.stylepanel———
style.hr.stylelinecoloroptionalrole
style.hr.stylelinethicknessoptionalnumber 范围
style.hr.styleshortCenteredcolorrequiredrole
style.hr.stylegradientcolorsrequiredrole[] 两个或三个角色。
style.table.headersurface———
style.table.headeraccentRulecolorrequiredrole
style.table.headerfilledbackgroundrequiredrole
style.table.headerfilledtextrequiredrole
style.table.headerfilledborderoptionalrole

色板角色

色板角色是下列名称之一:

background, surface, text, muted, border, heading, accent, link, quote, keyword, string, comment, number, function, type

数字

数字会先对齐到最接近的间隔倍数,再检查是否落在最小值与最大值之间,否则规则是 number.range。

字段最小值最大值间隔
style.bodySize14181
style.lineHeight1.41.90.05
style.headingWeight40090050
style.radius0161
style.maxWidth60010001
style.h1.size1.82.40.1
style.h1.letterSpacing-0.030.030.005
style.h2.letterSpacing-0.030.030.005
style.blockquote.style.width241
style.hr.style.thickness141

还会检查什么

打造一个主题页面可以从链接打开主题,让人用眼睛调整。链接是该页的网址,接着 #theme=,再接文件字节的 base64url(不含补位)。文件最大 16,384 字节。下面这一行命令在 macOS 与 Linux 的 zsh 和 bash 都能生成链接:

printf 'https://marsdawn.southern-light.dev/zh-hans/themes/new/#theme=%s\n' "$(base64 < theme.json | tr -d '\n=' | tr '+/' '-_')"

主题跟在 # 后面,浏览器不会把它发送给网站,网站也不会把它发送到任何地方。链接确实会留在你的 shell 历史与浏览器历史里,你贴给谁,谁就能读到这个主题。

投稿

代理准备文件与链接,由人来投稿。两条路都会要求 Developer Certificate of Origin 与 Apache-2.0 许可声明,这个声明由人本人做出:代理不会替他勾选方框或签署。

投稿主题的作者名称、名称、摘要与 GitHub 账号会永久公开,所以请把 author.name 设成人愿意公开的名字。

已发布的主题

想看已发布的主题长什么样子,可以逛逛主题图库。