diff --git a/bun.lock b/bun.lock index 42b0699..8997571 100644 --- a/bun.lock +++ b/bun.lock @@ -8,6 +8,7 @@ "zod": "^4.3.6", }, "devDependencies": { + "@atproto/lex-schema": "^0.0.19", "@types/bun": "^1.3.12", "@typescript/native-preview": "^7.0.0-dev.20260420.1", "oxfmt": "^0.46.0", diff --git a/lexicons/app/offprint/block/blockquote.json b/lexicons/app/offprint/block/blockquote.json new file mode 100644 index 0000000..6744597 --- /dev/null +++ b/lexicons/app/offprint/block/blockquote.json @@ -0,0 +1,27 @@ +{ + "id": "app.offprint.block.blockquote", + "defs": { + "main": { + "type": "object", + "required": [ + "content" + ], + "properties": { + "content": { + "type": "array", + "items": { + "refs": [ + "app.offprint.block.text", + "app.offprint.block.heading" + ], + "type": "union" + }, + "required": true, + "description": "Nested content blocks within the blockquote" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/blueskyPost.json b/lexicons/app/offprint/block/blueskyPost.json new file mode 100644 index 0000000..9b98f21 --- /dev/null +++ b/lexicons/app/offprint/block/blueskyPost.json @@ -0,0 +1,21 @@ +{ + "id": "app.offprint.block.blueskyPost", + "defs": { + "main": { + "type": "object", + "required": [ + "post" + ], + "properties": { + "post": { + "ref": "com.atproto.repo.strongRef", + "type": "ref", + "required": true, + "description": "Strong reference to the Bluesky post" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/bulletList.json b/lexicons/app/offprint/block/bulletList.json new file mode 100644 index 0000000..5945e05 --- /dev/null +++ b/lexicons/app/offprint/block/bulletList.json @@ -0,0 +1,46 @@ +{ + "id": "app.offprint.block.bulletList", + "defs": { + "main": { + "type": "object", + "required": [ + "children" + ], + "properties": { + "children": { + "type": "array", + "items": { + "ref": "#listItem", + "type": "ref" + }, + "required": true, + "description": "List items" + } + } + }, + "listItem": { + "type": "object", + "required": [ + "content" + ], + "properties": { + "content": { + "ref": "app.offprint.block.text", + "type": "ref", + "required": true, + "description": "Text content of the list item" + }, + "children": { + "type": "array", + "items": { + "ref": "#listItem", + "type": "ref" + }, + "description": "Nested list items" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/button.json b/lexicons/app/offprint/block/button.json new file mode 100644 index 0000000..3126054 --- /dev/null +++ b/lexicons/app/offprint/block/button.json @@ -0,0 +1,31 @@ +{ + "id": "app.offprint.block.button", + "defs": { + "main": { + "type": "object", + "required": [ + "text", + "href" + ], + "properties": { + "href": { + "type": "string", + "format": "uri", + "required": true, + "description": "The URL the button links to" + }, + "text": { + "type": "string", + "required": true, + "description": "The button label text" + }, + "caption": { + "type": "string", + "description": "Optional caption text displayed above the button" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/callout.json b/lexicons/app/offprint/block/callout.json new file mode 100644 index 0000000..9f6f42b --- /dev/null +++ b/lexicons/app/offprint/block/callout.json @@ -0,0 +1,37 @@ +{ + "id": "app.offprint.block.callout", + "defs": { + "main": { + "type": "object", + "required": [ + "plaintext" + ], + "properties": { + "color": { + "type": "string", + "description": "Background color (CSS color value)" + }, + "emoji": { + "type": "string", + "default": "💡", + "description": "Emoji icon for the callout" + }, + "facets": { + "type": "array", + "items": { + "ref": "app.offprint.richtext.facet", + "type": "ref" + }, + "description": "Facets for text formatting" + }, + "plaintext": { + "type": "string", + "required": true, + "description": "The callout text content" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/codeBlock.json b/lexicons/app/offprint/block/codeBlock.json new file mode 100644 index 0000000..1ddb293 --- /dev/null +++ b/lexicons/app/offprint/block/codeBlock.json @@ -0,0 +1,29 @@ +{ + "id": "app.offprint.block.codeBlock", + "defs": { + "main": { + "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "required": true, + "description": "The code content" + }, + "language": { + "type": "string", + "description": "Programming language for syntax highlighting" + }, + "showLineNumbers": { + "type": "boolean", + "default": false, + "description": "Whether to display line numbers" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/heading.json b/lexicons/app/offprint/block/heading.json new file mode 100644 index 0000000..ed27185 --- /dev/null +++ b/lexicons/app/offprint/block/heading.json @@ -0,0 +1,45 @@ +{ + "id": "app.offprint.block.heading", + "defs": { + "main": { + "type": "object", + "required": [ + "plaintext", + "level" + ], + "properties": { + "level": { + "type": "integer", + "maximum": 3, + "minimum": 1, + "required": true, + "description": "Heading level (1-3)" + }, + "facets": { + "type": "array", + "items": { + "ref": "app.offprint.richtext.facet", + "type": "ref" + }, + "description": "Facets for text formatting" + }, + "plaintext": { + "type": "string", + "required": true, + "description": "The heading text content" + }, + "textAlign": { + "enum": [ + "left", + "center", + "right" + ], + "type": "string", + "description": "Text alignment" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/horizontalRule.json b/lexicons/app/offprint/block/horizontalRule.json new file mode 100644 index 0000000..57a9ba0 --- /dev/null +++ b/lexicons/app/offprint/block/horizontalRule.json @@ -0,0 +1,11 @@ +{ + "id": "app.offprint.block.horizontalRule", + "defs": { + "main": { + "type": "object", + "properties": {} + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} diff --git a/lexicons/app/offprint/block/image.json b/lexicons/app/offprint/block/image.json new file mode 100644 index 0000000..aff93ba --- /dev/null +++ b/lexicons/app/offprint/block/image.json @@ -0,0 +1,73 @@ +{ + "id": "app.offprint.block.image", + "defs": { + "main": { + "type": "object", + "properties": { + "alt": { + "type": "string", + "description": "Alt text for accessibility", + "maxGraphemes": 300 + }, + "blob": { + "type": "blob", + "accept": [ + "image/*" + ], + "maxSize": 1000000, + "description": "The image blob" + }, + "width": { + "type": "string", + "description": "CSS width value (e.g., \"50%\", \"300px\")" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "alignment": { + "enum": [ + "left", + "center", + "right" + ], + "type": "string", + "description": "Horizontal alignment" + }, + "aspectRatio": { + "ref": "#aspectRatio", + "type": "ref" + }, + "captionFacets": { + "type": "array", + "items": { + "ref": "app.offprint.richtext.facet", + "type": "ref" + }, + "description": "Facets for caption formatting" + } + } + }, + "aspectRatio": { + "type": "object", + "required": [ + "width", + "height" + ], + "properties": { + "width": { + "type": "integer", + "minimum": 1, + "required": true + }, + "height": { + "type": "integer", + "minimum": 1, + "required": true + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/imageCarousel.json b/lexicons/app/offprint/block/imageCarousel.json new file mode 100644 index 0000000..77ba645 --- /dev/null +++ b/lexicons/app/offprint/block/imageCarousel.json @@ -0,0 +1,30 @@ +{ + "id": "app.offprint.block.imageCarousel", + "defs": { + "main": { + "type": "object", + "required": [ + "images" + ], + "properties": { + "images": { + "type": "array", + "items": { + "ref": "app.offprint.block.imageGrid#gridImage", + "type": "ref" + }, + "required": true, + "maxLength": 6, + "minLength": 2, + "description": "Array of images in the carousel (2-6)" + }, + "caption": { + "type": "string", + "description": "Carousel caption" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/imageDiff.json b/lexicons/app/offprint/block/imageDiff.json new file mode 100644 index 0000000..f671fd3 --- /dev/null +++ b/lexicons/app/offprint/block/imageDiff.json @@ -0,0 +1,43 @@ +{ + "id": "app.offprint.block.imageDiff", + "defs": { + "main": { + "type": "object", + "required": [ + "images" + ], + "properties": { + "width": { + "type": "string", + "description": "CSS width value" + }, + "images": { + "type": "array", + "items": { + "ref": "app.offprint.block.imageGrid#gridImage", + "type": "ref" + }, + "required": true, + "maxLength": 2, + "minLength": 2, + "description": "Exactly 2 images for comparison [before, after]" + }, + "caption": { + "type": "string", + "description": "Comparison caption" + }, + "alignment": { + "enum": [ + "left", + "center", + "right" + ], + "type": "string", + "description": "Horizontal alignment" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/imageGrid.json b/lexicons/app/offprint/block/imageGrid.json new file mode 100644 index 0000000..eaf7cd2 --- /dev/null +++ b/lexicons/app/offprint/block/imageGrid.json @@ -0,0 +1,66 @@ +{ + "id": "app.offprint.block.imageGrid", + "defs": { + "main": { + "type": "object", + "required": [ + "images" + ], + "properties": { + "images": { + "type": "array", + "items": { + "ref": "#gridImage", + "type": "ref" + }, + "required": true, + "maxLength": 6, + "minLength": 2, + "description": "Array of images in the grid (2-6)" + }, + "caption": { + "type": "string", + "description": "Grid caption" + }, + "gridRows": { + "type": "integer", + "maximum": 2, + "minimum": 1, + "description": "Number of rows in the grid" + }, + "aspectRatio": { + "enum": [ + "landscape", + "portrait", + "square", + "mosaic" + ], + "type": "string", + "description": "Aspect ratio mode" + } + } + }, + "gridImage": { + "type": "object", + "properties": { + "alt": { + "type": "string", + "maxGraphemes": 300 + }, + "blob": { + "type": "blob", + "accept": [ + "image/*" + ], + "maxSize": 1000000 + }, + "aspectRatio": { + "ref": "app.offprint.block.image#aspectRatio", + "type": "ref" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/mathBlock.json b/lexicons/app/offprint/block/mathBlock.json new file mode 100644 index 0000000..ad5b146 --- /dev/null +++ b/lexicons/app/offprint/block/mathBlock.json @@ -0,0 +1,20 @@ +{ + "id": "app.offprint.block.mathBlock", + "defs": { + "main": { + "type": "object", + "required": [ + "tex" + ], + "properties": { + "tex": { + "type": "string", + "required": true, + "description": "LaTeX/TeX source for the equation" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/orderedList.json b/lexicons/app/offprint/block/orderedList.json new file mode 100644 index 0000000..1285012 --- /dev/null +++ b/lexicons/app/offprint/block/orderedList.json @@ -0,0 +1,51 @@ +{ + "id": "app.offprint.block.orderedList", + "defs": { + "main": { + "type": "object", + "required": [ + "children" + ], + "properties": { + "start": { + "type": "integer", + "default": 1, + "description": "Starting number for the list" + }, + "children": { + "type": "array", + "items": { + "ref": "#listItem", + "type": "ref" + }, + "required": true, + "description": "List items" + } + } + }, + "listItem": { + "type": "object", + "required": [ + "content" + ], + "properties": { + "content": { + "ref": "app.offprint.block.text", + "type": "ref", + "required": true, + "description": "Text content of the list item" + }, + "children": { + "type": "array", + "items": { + "ref": "#listItem", + "type": "ref" + }, + "description": "Nested list items" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/taskList.json b/lexicons/app/offprint/block/taskList.json new file mode 100644 index 0000000..11c6460 --- /dev/null +++ b/lexicons/app/offprint/block/taskList.json @@ -0,0 +1,52 @@ +{ + "id": "app.offprint.block.taskList", + "defs": { + "main": { + "type": "object", + "required": [ + "children" + ], + "properties": { + "children": { + "type": "array", + "items": { + "ref": "#taskItem", + "type": "ref" + }, + "required": true, + "description": "Task items" + } + } + }, + "taskItem": { + "type": "object", + "required": [ + "content", + "checked" + ], + "properties": { + "checked": { + "type": "boolean", + "required": true, + "description": "Whether the task is completed" + }, + "content": { + "ref": "app.offprint.block.text", + "type": "ref", + "required": true, + "description": "Text content of the task item" + }, + "children": { + "type": "array", + "items": { + "ref": "#taskItem", + "type": "ref" + }, + "description": "Nested task items" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/text.json b/lexicons/app/offprint/block/text.json new file mode 100644 index 0000000..885befc --- /dev/null +++ b/lexicons/app/offprint/block/text.json @@ -0,0 +1,38 @@ +{ + "id": "app.offprint.block.text", + "defs": { + "main": { + "type": "object", + "required": [ + "plaintext" + ], + "properties": { + "facets": { + "type": "array", + "items": { + "ref": "app.offprint.richtext.facet", + "type": "ref" + }, + "description": "Facets for text formatting" + }, + "plaintext": { + "type": "string", + "required": true, + "description": "The plain text content" + }, + "textAlign": { + "enum": [ + "left", + "center", + "right", + "justify" + ], + "type": "string", + "description": "Text alignment" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/webBookmark.json b/lexicons/app/offprint/block/webBookmark.json new file mode 100644 index 0000000..4c064c2 --- /dev/null +++ b/lexicons/app/offprint/block/webBookmark.json @@ -0,0 +1,46 @@ +{ + "id": "app.offprint.block.webBookmark", + "defs": { + "main": { + "type": "object", + "required": [ + "href", + "title" + ], + "properties": { + "href": { + "type": "string", + "format": "uri", + "required": true, + "description": "The URL of the bookmarked page" + }, + "title": { + "type": "string", + "required": true, + "description": "Page title", + "maxGraphemes": 300 + }, + "preview": { + "type": "blob", + "accept": [ + "image/*" + ], + "maxSize": 1000000, + "description": "Open Graph image for the page" + }, + "siteName": { + "type": "string", + "description": "Name of the website", + "maxGraphemes": 100 + }, + "description": { + "type": "string", + "description": "Page description/excerpt", + "maxGraphemes": 1000 + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/block/webEmbed.json b/lexicons/app/offprint/block/webEmbed.json new file mode 100644 index 0000000..dc9417a --- /dev/null +++ b/lexicons/app/offprint/block/webEmbed.json @@ -0,0 +1,72 @@ +{ + "id": "app.offprint.block.webEmbed", + "defs": { + "main": { + "type": "object", + "required": [ + "href" + ], + "properties": { + "href": { + "type": "string", + "format": "uri", + "required": true, + "description": "The URL of the embedded page" + }, + "title": { + "type": "string", + "description": "Page title", + "maxGraphemes": 300 + }, + "width": { + "type": "string", + "description": "CSS width value (e.g., \"100%\", \"75%\". \"50%\" minimum)" + }, + "preview": { + "type": "blob", + "accept": [ + "image/*" + ], + "maxSize": 1000000, + "description": "Screenshot of the embedded content (1280×720px)" + }, + "embedUrl": { + "type": "string", + "format": "uri", + "description": "oEmbed URL for iframe embedding" + }, + "siteName": { + "type": "string", + "description": "Name of the website", + "maxGraphemes": 100 + }, + "alignment": { + "enum": [ + "left", + "center", + "right" + ], + "type": "string", + "description": "Horizontal alignment" + }, + "embedWidth": { + "type": "integer", + "minimum": 1, + "description": "Native embed width in pixels" + }, + "description": { + "type": "string", + "description": "Page description/excerpt", + "maxGraphemes": 1000 + }, + "embedHeight": { + "type": "integer", + "minimum": 1, + "description": "Native embed height in pixels" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/content.json b/lexicons/app/offprint/content.json new file mode 100644 index 0000000..39d4d96 --- /dev/null +++ b/lexicons/app/offprint/content.json @@ -0,0 +1,43 @@ +{ + "id": "app.offprint.content", + "defs": { + "main": { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "refs": [ + "app.offprint.block.text", + "app.offprint.block.heading", + "app.offprint.block.blockquote", + "app.offprint.block.callout", + "app.offprint.block.bulletList", + "app.offprint.block.orderedList", + "app.offprint.block.taskList", + "app.offprint.block.codeBlock", + "app.offprint.block.horizontalRule", + "app.offprint.block.image", + "app.offprint.block.imageGrid", + "app.offprint.block.imageCarousel", + "app.offprint.block.imageDiff", + "app.offprint.block.webBookmark", + "app.offprint.block.webEmbed", + "app.offprint.block.button", + "app.offprint.block.mathBlock", + "app.offprint.block.blueskyPost" + ], + "type": "union" + }, + "required": true, + "description": "Array of content blocks" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/publication.json b/lexicons/app/offprint/publication.json new file mode 100644 index 0000000..3f9510e --- /dev/null +++ b/lexicons/app/offprint/publication.json @@ -0,0 +1,25 @@ +{ + "id": "app.offprint.publication", + "defs": { + "main": { + "key": "tid", + "type": "record", + "record": { + "type": "object", + "required": [ + "publication" + ], + "properties": { + "publication": { + "type": "string", + "format": "at-uri", + "required": true, + "description": "Required AT-URI to a `site.standard.publication` compatible record." + } + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/app/offprint/richtext/facet.json b/lexicons/app/offprint/richtext/facet.json new file mode 100644 index 0000000..8de4614 --- /dev/null +++ b/lexicons/app/offprint/richtext/facet.json @@ -0,0 +1,146 @@ +{ + "id": "app.offprint.richtext.facet", + "defs": { + "bold": { + "type": "object", + "properties": {} + }, + "code": { + "type": "object", + "properties": {} + }, + "link": { + "type": "object", + "required": [ + "uri" + ], + "properties": { + "uri": { + "type": "string", + "format": "uri", + "required": true + } + } + }, + "main": { + "type": "object", + "required": [ + "index", + "features" + ], + "properties": { + "index": { + "ref": "#byteSlice", + "type": "ref", + "required": true + }, + "features": { + "type": "array", + "items": { + "refs": [ + "#bold", + "#italic", + "#underline", + "#strikethrough", + "#code", + "#highlight", + "#link", + "#mention", + "#webMention" + ], + "type": "union" + }, + "required": true + } + } + }, + "italic": { + "type": "object", + "properties": {} + }, + "mention": { + "type": "object", + "required": [ + "did" + ], + "properties": { + "did": { + "type": "string", + "format": "did", + "required": true + }, + "handle": { + "type": "string", + "format": "handle", + "description": "Optional cached handle for display" + } + } + }, + "byteSlice": { + "type": "object", + "required": [ + "byteStart", + "byteEnd" + ], + "properties": { + "byteEnd": { + "type": "integer", + "minimum": 0, + "required": true, + "description": "End index (exclusive), zero-indexed byte offset in UTF-8 encoded text." + }, + "byteStart": { + "type": "integer", + "minimum": 0, + "required": true, + "description": "Start index (inclusive), zero-indexed byte offset in UTF-8 encoded text." + } + } + }, + "highlight": { + "type": "object", + "properties": { + "color": { + "type": "string", + "description": "Optional highlight color (hex or CSS color)" + } + } + }, + "underline": { + "type": "object", + "properties": {} + }, + "webMention": { + "type": "object", + "required": [ + "uri", + "title" + ], + "properties": { + "uri": { + "type": "string", + "format": "uri", + "required": true, + "description": "The URL being mentioned" + }, + "title": { + "type": "string", + "required": true, + "description": "Page title for display", + "maxGraphemes": 100 + }, + "siteName": { + "type": "string", + "description": "Name of the website", + "maxGraphemes": 50 + } + } + }, + "strikethrough": { + "type": "object", + "properties": {} + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} diff --git a/lexicons/app/offprint/theme.json b/lexicons/app/offprint/theme.json new file mode 100644 index 0000000..01af26b --- /dev/null +++ b/lexicons/app/offprint/theme.json @@ -0,0 +1,220 @@ +{ + "id": "app.offprint.theme", + "defs": { + "main": { + "type": "object", + "required": [ + "colorScheme", + "colors" + ], + "properties": { + "colors": { + "ref": "#colors", + "type": "ref", + "required": true, + "description": "Full color palette for the theme." + }, + "sizing": { + "ref": "#sizing", + "type": "ref", + "description": "Border radius, component sizing, and border width values." + }, + "effects": { + "ref": "#effects", + "type": "ref", + "description": "Visual effects like depth shadows and noise texture." + }, + "typography": { + "ref": "#typography", + "type": "ref", + "description": "Font configuration for headings and body text." + }, + "colorScheme": { + "enum": [ + "light", + "dark" + ], + "type": "string", + "required": true, + "description": "Whether the theme is light or dark." + } + } + }, + "colors": { + "type": "object", + "required": [ + "base100", + "base200", + "base300", + "baseContent", + "primary", + "primaryContent" + ], + "properties": { + "info": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Informational status color." + }, + "error": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Error status color." + }, + "accent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Accent color for highlights and emphasis." + }, + "base100": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Primary background color." + }, + "base200": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Secondary background color (e.g. cards, sidebars)." + }, + "base300": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Tertiary background color (e.g. borders, dividers)." + }, + "neutral": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Neutral color for muted UI elements." + }, + "primary": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Primary action color (buttons, links)." + }, + "success": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Success status color." + }, + "warning": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Warning status color." + }, + "secondary": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Secondary action color." + }, + "baseContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Default text color on base backgrounds." + }, + "infoContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on info backgrounds." + }, + "errorContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on error backgrounds." + }, + "accentContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on accent backgrounds." + }, + "neutralContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on neutral backgrounds." + }, + "primaryContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "required": true, + "description": "Text color on primary backgrounds." + }, + "successContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on success backgrounds." + }, + "warningContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on warning backgrounds." + }, + "secondaryContent": { + "ref": "site.standard.theme.color#rgb", + "type": "ref", + "description": "Text color on secondary backgrounds." + } + } + }, + "sizing": { + "type": "object", + "properties": { + "border": { + "type": "string", + "description": "Default border width (e.g. \"1px\")." + }, + "radiusBox": { + "type": "string", + "description": "Border radius for cards and containers (e.g. \"1rem\")." + }, + "sizeField": { + "type": "string", + "description": "Height for input fields (e.g. \"0.25rem\")." + }, + "radiusField": { + "type": "string", + "description": "Border radius for input fields (e.g. \"0.5rem\")." + }, + "sizeSelector": { + "type": "string", + "description": "Height for small interactive elements (e.g. \"0.25rem\")." + }, + "radiusSelector": { + "type": "string", + "description": "Border radius for small interactive elements (e.g. \"0.5rem\")." + } + } + }, + "effects": { + "type": "object", + "properties": { + "depth": { + "type": "boolean", + "description": "Whether to show depth shadows on elevated elements." + }, + "noise": { + "type": "boolean", + "description": "Whether to apply a noise texture to backgrounds." + } + } + }, + "typography": { + "type": "object", + "properties": { + "bodyFont": { + "type": "string", + "description": "Font slug for body text (e.g. \"inter\")." + }, + "headingFont": { + "type": "string", + "description": "Font slug for headings (e.g. \"playfair-display\")." + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/com/atproto/label/defs.json b/lexicons/com/atproto/label/defs.json new file mode 100644 index 0000000..34f4bbf --- /dev/null +++ b/lexicons/com/atproto/label/defs.json @@ -0,0 +1,190 @@ +{ + "id": "com.atproto.label.defs", + "defs": { + "label": { + "type": "object", + "required": [ + "src", + "uri", + "val", + "cts" + ], + "properties": { + "cid": { + "type": "string", + "format": "cid", + "description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to." + }, + "cts": { + "type": "string", + "format": "datetime", + "description": "Timestamp when this label was created." + }, + "exp": { + "type": "string", + "format": "datetime", + "description": "Timestamp at which this label expires (no longer applies)." + }, + "neg": { + "type": "boolean", + "description": "If true, this is a negation label, overwriting a previous label." + }, + "sig": { + "type": "bytes", + "description": "Signature of dag-cbor encoded label." + }, + "src": { + "type": "string", + "format": "did", + "description": "DID of the actor who created this label." + }, + "uri": { + "type": "string", + "format": "uri", + "description": "AT URI of the record, repository (account), or other resource that this label applies to." + }, + "val": { + "type": "string", + "maxLength": 128, + "description": "The short string name of the value or type of this label." + }, + "ver": { + "type": "integer", + "description": "The AT Protocol version of the label object." + } + }, + "description": "Metadata tag on an atproto resource (eg, repo or record)." + }, + "selfLabel": { + "type": "object", + "required": [ + "val" + ], + "properties": { + "val": { + "type": "string", + "maxLength": 128, + "description": "The short string name of the value or type of this label." + } + }, + "description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel." + }, + "labelValue": { + "type": "string", + "knownValues": [ + "!hide", + "!warn", + "!no-unauthenticated", + "porn", + "sexual", + "nudity", + "graphic-media", + "bot" + ] + }, + "selfLabels": { + "type": "object", + "required": [ + "values" + ], + "properties": { + "values": { + "type": "array", + "items": { + "ref": "#selfLabel", + "type": "ref" + }, + "maxLength": 10 + } + }, + "description": "Metadata tags on an atproto record, published by the author within the record." + }, + "labelValueDefinition": { + "type": "object", + "required": [ + "identifier", + "severity", + "blurs", + "locales" + ], + "properties": { + "blurs": { + "type": "string", + "description": "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.", + "knownValues": [ + "content", + "media", + "none" + ] + }, + "locales": { + "type": "array", + "items": { + "ref": "#labelValueDefinitionStrings", + "type": "ref" + } + }, + "severity": { + "type": "string", + "description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", + "knownValues": [ + "inform", + "alert", + "none" + ] + }, + "adultOnly": { + "type": "boolean", + "description": "Does the user need to have adult content enabled in order to configure this label?" + }, + "identifier": { + "type": "string", + "maxLength": 100, + "description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", + "maxGraphemes": 100 + }, + "defaultSetting": { + "type": "string", + "default": "warn", + "description": "The default setting for this label.", + "knownValues": [ + "ignore", + "warn", + "hide" + ] + } + }, + "description": "Declares a label value and its expected interpretations and behaviors." + }, + "labelValueDefinitionStrings": { + "type": "object", + "required": [ + "lang", + "name", + "description" + ], + "properties": { + "lang": { + "type": "string", + "format": "language", + "description": "The code of the language these strings are written in." + }, + "name": { + "type": "string", + "maxLength": 640, + "description": "A short human-readable name for the label.", + "maxGraphemes": 64 + }, + "description": { + "type": "string", + "maxLength": 100000, + "description": "A longer description of what the label means and why it might be applied.", + "maxGraphemes": 10000 + } + }, + "description": "Strings which describe the label in the UI, localized into a specific language." + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/com/atproto/repo/strongRef.json b/lexicons/com/atproto/repo/strongRef.json new file mode 100644 index 0000000..51bb61c --- /dev/null +++ b/lexicons/com/atproto/repo/strongRef.json @@ -0,0 +1,25 @@ +{ + "id": "com.atproto.repo.strongRef", + "defs": { + "main": { + "type": "object", + "required": [ + "uri", + "cid" + ], + "properties": { + "cid": { + "type": "string", + "format": "cid" + }, + "uri": { + "type": "string", + "format": "at-uri" + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1, + "description": "A URI with a content-hash fingerprint." +} \ No newline at end of file diff --git a/lexicons/site/standard/document.json b/lexicons/site/standard/document.json new file mode 100644 index 0000000..44e1c9d --- /dev/null +++ b/lexicons/site/standard/document.json @@ -0,0 +1,126 @@ +{ + "id": "site.standard.document", + "defs": { + "main": { + "key": "tid", + "type": "record", + "record": { + "type": "object", + "required": [ + "site", + "title", + "publishedAt" + ], + "properties": { + "path": { + "type": "string", + "description": "Combine with site or publication url to construct a canonical URL to the document. Prepend with a leading slash." + }, + "site": { + "type": "string", + "format": "uri", + "description": "Points to a publication record (at://) or a publication url (https://) for loose documents. Avoid trailing slashes." + }, + "tags": { + "type": "array", + "items": { + "type": "string", + "maxLength": 1280, + "maxGraphemes": 128 + }, + "description": "Array of strings used to tag or categorize the document. Avoid prepending tags with hashtags." + }, + "links": { + "refs": [], + "type": "union", + "description": "Array of values describing relationships between this document and external resources" + }, + "title": { + "type": "string", + "maxLength": 5000, + "description": "Title of the document.", + "maxGraphemes": 500 + }, + "labels": { + "refs": [ + "com.atproto.label.defs#selfLabels" + ], + "type": "union", + "description": "Self-label values for this post. Effectively content warnings." + }, + "content": { + "refs": [], + "type": "union", + "closed": false, + "description": "Open union used to define the record's content. Each entry must specify a $type and may be extended with other lexicons to support additional content formats." + }, + "updatedAt": { + "type": "string", + "format": "datetime", + "description": "Timestamp of the documents last edit." + }, + "coverImage": { + "type": "blob", + "accept": [ + "image/*" + ], + "maxSize": 1000000, + "description": "Image to used for thumbnail or cover image. Less than 1MB is size." + }, + "bskyPostRef": { + "ref": "com.atproto.repo.strongRef", + "type": "ref", + "description": "Strong reference to a Bluesky post. Useful to keep track of comments off-platform." + }, + "description": { + "type": "string", + "maxLength": 30000, + "description": "A brief description or excerpt from the document.", + "maxGraphemes": 3000 + }, + "publishedAt": { + "type": "string", + "format": "datetime", + "description": "Timestamp of the documents publish time." + }, + "textContent": { + "type": "string", + "description": "Plaintext representation of the documents contents. Should not contain markdown or other formatting." + }, + "contributors": { + "type": "array", + "items": { + "ref": "#contributor", + "type": "ref" + } + } + } + }, + "description": "A document record representing a published article, blog post, or other content. Documents can belong to a publication or exist independently." + }, + "contributor": { + "type": "object", + "required": [ + "did" + ], + "properties": { + "did": { + "type": "string", + "format": "did" + }, + "role": { + "type": "string", + "maxLength": 1000, + "maxGraphemes": 100 + }, + "displayName": { + "type": "string", + "maxLength": 1000, + "maxGraphemes": 100 + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/lexicons/site/standard/theme/color.json b/lexicons/site/standard/theme/color.json new file mode 100644 index 0000000..930eaf5 --- /dev/null +++ b/lexicons/site/standard/theme/color.json @@ -0,0 +1,63 @@ +{ + "id": "site.standard.theme.color", + "defs": { + "rgb": { + "type": "object", + "required": [ + "r", + "g", + "b" + ], + "properties": { + "b": { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + "g": { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + "r": { + "type": "integer", + "maximum": 255, + "minimum": 0 + } + } + }, + "rgba": { + "type": "object", + "required": [ + "r", + "g", + "b", + "a" + ], + "properties": { + "a": { + "type": "integer", + "maximum": 100, + "minimum": 0 + }, + "b": { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + "g": { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + "r": { + "type": "integer", + "maximum": 255, + "minimum": 0 + } + } + } + }, + "$type": "com.atproto.lexicon.schema", + "lexicon": 1 +} \ No newline at end of file diff --git a/package.json b/package.json index 648c94f..1697b04 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,16 @@ "fmt": "oxfmt", "fmt:check": "oxfmt --check", "lint": "oxlint", - "lint:fix": "oxlint --fix" + "lint:fix": "oxlint --fix", + "gen": "lex build --clear", + "postinstall": "bun gen" }, "dependencies": { "zod": "^4.3.6" }, "devDependencies": { "@atproto/lex-json": "^0.0.16", + "@atproto/lex-schema": "^0.0.19", "@types/bun": "^1.3.12", "@typescript/native-preview": "^7.0.0-dev.20260420.1", "oxfmt": "^0.46.0",