Mit deinem Agenten ein Thema erstellen
Eine Referenz für einen KI-Agenten, der ein MarsDawn-Vorschau-Thema erstellt. Der Agent schreibt eine theme.json, prüft und rendert sie mit dem Befehlszeilenwerkzeug marsdawn und gibt dir einen Link. Du stimmst sie auf der Seite Ein Thema erstellen nach Augenmaß ab und reichst sie ein. Die Feldtabellen unten sind direkt aus dem Quelltext des Kits gelesen, und eine Prüfung hält sie damit gleich.
Schreibe eine theme.json, führe marsdawn theme validate theme.json --require-complete --json aus, bis der Exit-Code 0 ist, rendere sie mit marsdawn theme preview in hell und dunkel und gib der Person dann einen Link. Ein Thema besteht nur aus Parametern. Es enthält nie CSS.
Was ein Thema ist
- Farben für hell und für dunkel: eine Basispalette sowie optionale Syntax- und Diagrammfarben. Jede ist
#RRGGBB. - Ein Schriftdesign:
sans,serifoderrounded. - Ein geschlossener Satz von Stiloptionen: Zahlen in festen Bereichen und Auswahlen aus festen Listen. Eine Farbe in einer Stiloption ist immer eine Palettenrolle wie
accent, nie eine feste Farbe. - Anzeigetexte: ein Name und eine Zusammenfassung, optional ein Autor und eine Lizenz.
Ein Schlüssel, der nicht in den Tabellen unten steht, ist ein Fehler, ebenso ein doppelt geschriebener Schlüssel. Die Datei darf höchstens 16.384 Bytes groß sein.
Prüfen und rendern
Führe diese Befehle in dem Ordner aus, der theme.json enthält. Sie brauchen das Werkzeug marsdawn: siehe marsdawn für Agenten.
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
- Exit-Codes: 0 gültig, 1 ungültig mit Regel-IDs, 2 Datei nicht gefunden, 64 falsche Verwendung.
previewkennt zusätzlich 4, wenn die PNG-Datei schon existiert (--forceübergeben oder einen anderen Namen wählen), und 5, wenn das Rendern fehlschlägt. - Mit
--jsonlistet ein ungültiges Thema seine Probleme unterissuesauf, jedes mit einerrule-ID, einempathund einermessage. Behebe sie und führe den Befehl erneut aus. --require-completeist die Prüfung für ein Thema, das veröffentlicht werden soll: Es verlangt zusätzlich die Farbensyntaxunddiagramin beiden Paletten.cssgibt das CSS aus, das die Vorschau verwendet.previewrendert ein Beispieldokument als PNG. Beide prüfen zuerst, ein ungültiges Thema wird also nicht gerendert.- Sieh dir das helle und das dunkle PNG an, bevor du das Thema übergibst.
Mit einem eingebauten Thema beginnen
Kopiere eines der vier eingebauten Themen und ändere es. Jedes ist eine vollständige, gültige Datei:
/assets/theme-sim/kit/themes/dawn.json: der Standard und das Beispiel unten/assets/theme-sim/kit/themes/classic.json: eine schlichtere, dokumentartige Palette/assets/theme-sim/kit/themes/modern.json: eine kühlere, zeitgemäßere Palette/assets/theme-sim/kit/themes/vivid.json: eine hellere Palette mit mehr Kontrast
Beispiel: Dawn
Das ist dawn.json, Byte für Byte. Ihre einzige Stiloption ist eine dünne Linie in der Akzentfarbe für 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 } }
}
}
Felder
Jedes Objekt unten wird auf dieselbe Weise gelesen. required heißt, der Schlüssel muss vorhanden sein, und ein Schlüssel, der nicht aufgeführt ist, ist ein Fehler.
Typen: string, integer, number, boolean, map (Sprach-Tag auf Text), enum (einer der aufgeführten Werte), role (eine Palettenrolle) und object (die Tabelle, auf die verlinkt wird). Ein [] hinter einem Typ bedeutet eine Liste.
theme.json
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
schemaVersion | integer | required | Immer 1. |
id | string | required | 1 bis 32 Zeichen: Kleinbuchstaben und Ziffern, in Abschnitten, die durch einzelne Bindestriche verbunden sind, etwa calm-green. |
version | string | required | MAJOR.MINOR.PATCH, etwa 1.0.0. |
name | map | required | Sprach-Tag auf Text. en ist erforderlich; andere Schlüssel sind Sprach-Tags wie zh-Hant. Jeder Text hat höchstens 48 Zeichen, ohne Links und Zeilenumbrüche. |
summary | map | required | Dieselbe Form wie name, höchstens 120 Zeichen pro Text. |
fontDesign | enum | required | sans, serif, rounded |
scenarios | enum[] | required | agent-review, technical-docs, formal-output, notes-sharing — Eins oder zwei, ohne Wiederholung. Sie legen fest, wie viel Kontrast das Thema erreichen muss. |
author | object | optional | author |
license | string | optional | Eine SPDX-Kennung, etwa Apache-2.0. Eingereichte Themen werden unter Apache-2.0 veröffentlicht. |
light | object | required | light, dark |
dark | object | required | light, dark |
style | object | optional | style |
author
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
name | string | required | Höchstens 64 Zeichen, ohne Links. |
github | string | optional | Ein GitHub-Login. Bei einer Einreichung trägst du den der einreichenden Person ein. |
light, dark
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
background | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
surface | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
text | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
muted | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
border | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
heading | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
accent | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
link | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
quote | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
syntax | object | optional (zum Veröffentlichen erforderlich, mit --require-complete) | syntax |
diagram | object | optional (zum Veröffentlichen erforderlich, mit --require-complete) | diagram |
syntax
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
keyword | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
string | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
comment | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
number | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
function | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
type | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
diagram
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
node | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
nodeBorder | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
text | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
line | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
secondary | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
tertiary | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
note | string | required | # und sechs Hexziffern, etwa #1C1C1C. |
style
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
bodySize | number | optional | Bereich |
lineHeight | number | optional | Bereich |
headingWeight | number | optional | Bereich |
radius | number | optional | Bereich |
maxWidth | number | optional | Bereich |
h1 | object | optional | style.h1 |
h2 | object | optional | style.h2 |
blockquote | object | optional | style.blockquote |
hr | object | optional | style.hr |
table | object | optional | style.table |
listMarker | role | optional | eine Palettenrolle |
inlineCode | role | optional | eine Palettenrolle — Nur text oder eine Syntaxrolle: keyword, string, comment, number, function oder type. |
link | object | optional | style.link |
syntax | object | optional | style.syntax |
style.h1
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
size | number | optional | Bereich |
letterSpacing | number | optional | Bereich |
align | enum | optional | left, center |
decoration | object | optional | type |
style.h2
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
letterSpacing | number | optional | Bereich |
decoration | object | optional | type |
italic | boolean | optional | true, false |
style.blockquote
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
style | object | optional | type |
italic | boolean | optional | true, false |
style.hr
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
style | object | optional | type |
style.table
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
header | object | optional | type |
verticalRules | boolean | optional | true, false |
rounded | boolean | optional | true, false |
style.link
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
underline | boolean | optional | true, false |
style.syntax
| Feld | Typ | Pflicht | Werte und Hinweise |
|---|---|---|---|
boldKeywords | boolean | optional | true, false |
Optionen mit einem Typ
Diese Stiloptionen sind Objekte mit einem type. Jeder type nimmt genau die für ihn aufgeführten Felder und keine anderen.
| Option | type | Feld | Pflicht | Typ |
|---|---|---|---|---|
style.h1.decoration | rule | — | — | — |
style.h1.decoration | none | — | — | — |
style.h1.decoration | shortRule | color | required | role |
style.h1.decoration | gradientBar | from | required | role |
style.h1.decoration | gradientBar | to | required | role |
style.h2.decoration | rule | — | — | — |
style.h2.decoration | none | — | — | — |
style.h2.decoration | dot | color | required | role |
style.blockquote.style | bar | width | optional | number Bereich |
style.blockquote.style | panel | — | — | — |
style.hr.style | line | color | optional | role |
style.hr.style | line | thickness | optional | number Bereich |
style.hr.style | shortCentered | color | required | role |
style.hr.style | gradient | colors | required | role[] Zwei oder drei Rollen. |
style.table.header | surface | — | — | — |
style.table.header | accentRule | color | required | role |
style.table.header | filled | background | required | role |
style.table.header | filled | text | required | role |
style.table.header | filled | border | optional | role |
Palettenrollen
Eine Palettenrolle ist einer dieser Namen:
background, surface, text, muted, border, heading, accent, link, quote, keyword, string, comment, number, function, type
Zahlen
Eine Zahl wird auf das nächste Vielfache ihres Schritts gerundet und muss dann zwischen Min und Max liegen. Sonst lautet die Regel number.range.
| Feld | Min | Max | Schritt |
|---|---|---|---|
style.bodySize | 14 | 18 | 1 |
style.lineHeight | 1.4 | 1.9 | 0.05 |
style.headingWeight | 400 | 900 | 50 |
style.radius | 0 | 16 | 1 |
style.maxWidth | 600 | 1000 | 1 |
style.h1.size | 1.8 | 2.4 | 0.1 |
style.h1.letterSpacing | -0.03 | 0.03 | 0.005 |
style.h2.letterSpacing | -0.03 | 0.03 | 0.005 |
style.blockquote.style.width | 2 | 4 | 1 |
style.hr.style.thickness | 1 | 4 | 1 |
Was sonst noch geprüft wird
- Kontrast. Jedes Farbpaar, das die Vorschau zeichnet, etwa
textaufbackground, muss für Text 4,5:1 und für Linien und anderes Nicht-Text 3:1 erreichen. Die Szenarien, die du angibst, heben manche Farben auf 4,5:1. Die Meldung nennt das Paar, sein Verhältnis und das geforderte. - Texte. Ein Name, eine Zusammenfassung oder ein Autorenname, der leer oder zu lang ist oder einen Link, ein Steuerzeichen oder ein unsichtbares oder bidirektionales Formatzeichen enthält, wird abgelehnt.
- Regel-IDs. Jedes Problem trägt eine, etwa
contrast.pair,color.hex,number.range,id.pattern,schema.unknownKeyoderpalette.incomplete. Korrigiere die Datei nach dem, was die ID und derpathsagen.
Als Link übergeben
Die Seite Ein Thema erstellen öffnet ein Thema aus einem Link, damit die Person es nach Augenmaß abstimmen kann. Der Link besteht aus der Adresse der Seite, dann #theme=, dann den Bytes der Datei als base64url ohne Auffüllzeichen. Die Datei darf höchstens 16.384 Bytes groß sein. Diese eine Zeile baut den Link in zsh und in bash, auf macOS und Linux:
printf 'https://marsdawn.southern-light.dev/de/themes/new/#theme=%s\n' "$(base64 < theme.json | tr -d '\n=' | tr '+/' '-_')"
Das Thema steht hinter einem #, das ein Browser nicht an die Website sendet, und die Website leitet es nirgendwohin weiter. Der Link bleibt aber im Verlauf deiner Shell und des Browsers, und jede Person, der du ihn schickst, kann das Thema lesen.
Einreichen
Der Agent bereitet die Datei und den Link vor. Die Person reicht ein. Beide Wege verlangen das Developer Certificate of Origin und die Veröffentlichung unter Apache-2.0, und diese Bestätigung gibt die Person ab: Der Agent setzt das Häkchen nicht und unterschreibt nicht für sie.
- Issue. Die Person öffnet den Link und klickt auf der Seite „Ein Thema erstellen“ auf Submit oder öffnet das Issue-Formular und fügt das JSON in Theme ein. Ein Workflow prüft das Thema und antwortet.
- Pull Request. Ändere nur
themes/<id>/theme.json, setzeauthor.githubauf den Login des Pull-Request-Autors und signiere jeden Commit mitgit commit -s(Sign-off). Die Regeln stehen in CONTRIBUTING.md.
Autorenname, Name, Zusammenfassung und GitHub-Login eines eingereichten Themas werden dauerhaft öffentlich. Setze author.name daher auf einen Namen, den die Person gern veröffentlicht.
Veröffentlichte Themen
Wie veröffentlichte Themen aussehen, siehst du in der Themengalerie.