MarsDawn

Crea un tema con tu agente

Una referencia para un agente de IA que crea un tema de vista previa de MarsDawn. El agente escribe un único theme.json, lo comprueba y lo renderiza con la herramienta de línea de comandos marsdawn y te da un enlace. Tú lo afinas a ojo en la página Crear un tema y lo envías. Las tablas de campos de abajo se leen del código fuente del kit, y una comprobación las mantiene iguales.

Escribe un theme.json, ejecuta marsdawn theme validate theme.json --require-complete --json hasta que termine con código 0, renderízalo con marsdawn theme preview en claro y en oscuro y después dale un enlace a la persona. Un tema son solo parámetros. Nunca contiene CSS.

Qué es un tema

Una clave que no está en las tablas de abajo es un error, y también lo es una clave escrita dos veces. El archivo pesa como máximo 16 384 bytes.

Comprobar y renderizar

Ejecuta estos comandos en la carpeta que contiene theme.json. Necesitan la herramienta marsdawn: consulta marsdawn para agentes.

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

Partir de un tema integrado

Copia uno de los cuatro temas integrados y cámbialo. Cada uno es un archivo completo y válido:

Ejemplo: Dawn

Este es dawn.json, byte por byte. Su única opción de estilo es una línea fina del color de acento para 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 } }
  }
}

Campos

Cada objeto de abajo se lee de la misma manera. required significa que la clave debe estar presente, y una clave que no figura en la lista es un error.

Tipos: string, integer, number, boolean, map (etiqueta de idioma a texto), enum (uno de los valores listados), role (un rol de la paleta) y object (la tabla a la que enlaza). Un [] después de un tipo significa una lista.

theme.json

CampoTipoPresenciaValores y notas
schemaVersionintegerrequiredSiempre 1.
idstringrequiredDe 1 a 32 caracteres: letras minúsculas y dígitos, en tramos unidos por guiones simples, como calm-green.
versionstringrequiredMAJOR.MINOR.PATCH, como 1.0.0.
namemaprequiredEtiqueta de idioma a texto. en es obligatoria; las demás claves son etiquetas de idioma como zh-Hant. Cada texto tiene como máximo 48 caracteres, sin enlaces ni saltos de línea.
summarymaprequiredLa misma forma que name, con un máximo de 120 caracteres por texto.
fontDesignenumrequiredsans, serif, rounded
scenariosenum[]requiredagent-review, technical-docs, formal-output, notes-sharing — Uno o dos, sin repetir. Fijan cuánto contraste debe alcanzar el tema.
authorobjectoptionalauthor
licensestringoptionalUn identificador SPDX, como Apache-2.0. Los temas enviados se publican bajo Apache-2.0.
lightobjectrequiredlight, dark
darkobjectrequiredlight, dark
styleobjectoptionalstyle

author

CampoTipoPresenciaValores y notas
namestringrequiredComo máximo 64 caracteres, sin enlaces.
githubstringoptionalUn usuario de GitHub. En un envío, pon el de quien lo envía.

light, dark

CampoTipoPresenciaValores y notas
backgroundstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
surfacestringrequired# y seis dígitos hexadecimales, como #1C1C1C.
textstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
mutedstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
borderstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
headingstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
accentstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
linkstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
quotestringrequired# y seis dígitos hexadecimales, como #1C1C1C.
syntaxobjectoptional (obligatorio para publicar, con --require-complete)syntax
diagramobjectoptional (obligatorio para publicar, con --require-complete)diagram

syntax

CampoTipoPresenciaValores y notas
keywordstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
stringstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
commentstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
numberstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
functionstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
typestringrequired# y seis dígitos hexadecimales, como #1C1C1C.

diagram

CampoTipoPresenciaValores y notas
nodestringrequired# y seis dígitos hexadecimales, como #1C1C1C.
nodeBorderstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
textstringrequired# y seis dígitos hexadecimales, como #1C1C1C.
linestringrequired# y seis dígitos hexadecimales, como #1C1C1C.
secondarystringrequired# y seis dígitos hexadecimales, como #1C1C1C.
tertiarystringrequired# y seis dígitos hexadecimales, como #1C1C1C.
notestringrequired# y seis dígitos hexadecimales, como #1C1C1C.

style

CampoTipoPresenciaValores y notas
bodySizenumberoptionalrango
lineHeightnumberoptionalrango
headingWeightnumberoptionalrango
radiusnumberoptionalrango
maxWidthnumberoptionalrango
h1objectoptionalstyle.h1
h2objectoptionalstyle.h2
blockquoteobjectoptionalstyle.blockquote
hrobjectoptionalstyle.hr
tableobjectoptionalstyle.table
listMarkerroleoptionalun rol de la paleta
inlineCoderoleoptionalun rol de la paleta — Solo text o un rol de sintaxis: keyword, string, comment, number, function o type.
linkobjectoptionalstyle.link
syntaxobjectoptionalstyle.syntax

style.h1

CampoTipoPresenciaValores y notas
sizenumberoptionalrango
letterSpacingnumberoptionalrango
alignenumoptionalleft, center
decorationobjectoptionaltype

style.h2

CampoTipoPresenciaValores y notas
letterSpacingnumberoptionalrango
decorationobjectoptionaltype
italicbooleanoptionaltrue, false

style.blockquote

CampoTipoPresenciaValores y notas
styleobjectoptionaltype
italicbooleanoptionaltrue, false

style.hr

CampoTipoPresenciaValores y notas
styleobjectoptionaltype

style.table

CampoTipoPresenciaValores y notas
headerobjectoptionaltype
verticalRulesbooleanoptionaltrue, false
roundedbooleanoptionaltrue, false
CampoTipoPresenciaValores y notas
underlinebooleanoptionaltrue, false

style.syntax

CampoTipoPresenciaValores y notas
boldKeywordsbooleanoptionaltrue, false

Opciones con un tipo

Estas opciones de estilo son objetos con un type. Cada type admite los campos listados para él y ningún otro.

OpcióntypeCampoPresenciaTipo
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 rango
style.blockquote.stylepanel———
style.hr.stylelinecoloroptionalrole
style.hr.stylelinethicknessoptionalnumber rango
style.hr.styleshortCenteredcolorrequiredrole
style.hr.stylegradientcolorsrequiredrole[] Dos o tres roles.
style.table.headersurface———
style.table.headeraccentRulecolorrequiredrole
style.table.headerfilledbackgroundrequiredrole
style.table.headerfilledtextrequiredrole
style.table.headerfilledborderoptionalrole

Roles de la paleta

Un rol de la paleta es uno de estos nombres:

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

Números

Un número se ajusta al múltiplo más cercano de su paso y después debe estar entre el mínimo y el máximo. Si no, la regla es number.range.

CampoMín.Máx.Paso
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

Qué más se comprueba

La página Crear un tema abre un tema desde un enlace, para que la persona pueda afinarlo a ojo. El enlace es la dirección de esa página, luego #theme= y luego los bytes del archivo en base64url sin relleno. El archivo puede pesar como máximo 16 384 bytes. Esta única línea construye el enlace en zsh y en bash, en macOS y en Linux:

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

El tema viaja detrás de un #, que el navegador no envía al sitio, y el sitio no lo envía a ninguna parte. Eso sí, el enlace queda en el historial de tu shell y en el del navegador, y cualquiera a quien se lo pegues puede leer el tema.

Envíalo

El agente prepara el archivo y el enlace. La persona lo envía. Las dos vías piden el Developer Certificate of Origin y la publicación bajo Apache-2.0, y esa certificación la hace la persona: el agente no marca la casilla ni firma por ella.

El nombre del autor, el nombre, el resumen y el usuario de GitHub de un tema enviado pasan a ser públicos de forma permanente, así que pon en author.name un nombre que la persona esté contenta de publicar.

Temas publicados

Para ver cómo son los temas publicados, explora la galería de temas.