From 1715331091e407c6ab43f4877ba07eb01d06d599 Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Tue, 24 Mar 2026 12:15:34 -0600 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20RFC0003=20-=20Simpl?= =?UTF-8?q?e=20node=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/schema/block.md | 2 +- docs/schema/code.md | 31 +++ docs/schema/inline.md | 2 +- docs/schema/inlinecode.md | 31 +++ docs/schema/subscript.md | 28 +++ docs/schema/superscript.md | 28 +++ docs/schema/thematicbreak.md | 23 +++ .../oxa-types-py/src/oxa_types/__init__.py | 154 +++++++++------ packages/oxa-types-rs/src/lib.rs | 99 ++++++++++ packages/oxa-types-ts/src/index.ts | 144 +++++++++++++- schema/Block.yaml | 2 + schema/Code.yaml | 30 +++ schema/Inline.yaml | 3 + schema/InlineCode.yaml | 30 +++ schema/Subscript.yaml | 29 +++ schema/Superscript.yaml | 29 +++ schema/ThematicBreak.yaml | 23 +++ schema/schema.json | 185 ++++++++++++++++++ 18 files changed, 807 insertions(+), 66 deletions(-) create mode 100644 docs/schema/code.md create mode 100644 docs/schema/inlinecode.md create mode 100644 docs/schema/subscript.md create mode 100644 docs/schema/superscript.md create mode 100644 docs/schema/thematicbreak.md create mode 100644 schema/Code.yaml create mode 100644 schema/InlineCode.yaml create mode 100644 schema/Subscript.yaml create mode 100644 schema/Superscript.yaml create mode 100644 schema/ThematicBreak.yaml diff --git a/docs/schema/block.md b/docs/schema/block.md index 256ceb1..a99fba7 100644 --- a/docs/schema/block.md +++ b/docs/schema/block.md @@ -6,4 +6,4 @@ Union of all block content types. -Union of: @oxa:heading, @oxa:paragraph +Union of: @oxa:code, @oxa:heading, @oxa:paragraph, @oxa:thematicbreak diff --git a/docs/schema/code.md b/docs/schema/code.md new file mode 100644 index 0000000..7676427 --- /dev/null +++ b/docs/schema/code.md @@ -0,0 +1,31 @@ +(oxa:code)= + +## Code + + +A block of preformatted text, typically source code. + + +__type__: _string_, ("Code") + +: The type discriminator for Code nodes. + +__id__: __string__ + +: A unique identifier for the node. + +__classes__: __array__ ("string") + +: A list of class names for styling or semantics. + +__data__: __object__ + +: Arbitrary key-value data attached to the node. + +__language__: __string__ + +: The programming language of the code content. + +__value__: __string__ + +: The code content. diff --git a/docs/schema/inline.md b/docs/schema/inline.md index 02a505d..d456fad 100644 --- a/docs/schema/inline.md +++ b/docs/schema/inline.md @@ -6,4 +6,4 @@ Union of all inline content types. -Union of: @oxa:text, @oxa:emphasis, @oxa:strong +Union of: @oxa:text, @oxa:emphasis, @oxa:inlinecode, @oxa:strong, @oxa:subscript, @oxa:superscript diff --git a/docs/schema/inlinecode.md b/docs/schema/inlinecode.md new file mode 100644 index 0000000..b242d6d --- /dev/null +++ b/docs/schema/inlinecode.md @@ -0,0 +1,31 @@ +(oxa:inlinecode)= + +## InlineCode + + +Short fragments of code appearing within prose. + + +__type__: _string_, ("InlineCode") + +: The type discriminator for InlineCode nodes. + +__id__: __string__ + +: A unique identifier for the node. + +__classes__: __array__ ("string") + +: A list of class names for styling or semantics. + +__data__: __object__ + +: Arbitrary key-value data attached to the node. + +__language__: __string__ + +: The programming language of the code content. + +__value__: __string__ + +: The code content. diff --git a/docs/schema/subscript.md b/docs/schema/subscript.md new file mode 100644 index 0000000..3dce0aa --- /dev/null +++ b/docs/schema/subscript.md @@ -0,0 +1,28 @@ +(oxa:subscript)= + +## Subscript + + +Content rendered below the baseline (e.g. chemical formulae, variable indices). + + +__type__: _string_, ("Subscript") + +: The type discriminator for Subscript nodes. + +__id__: __string__ + +: A unique identifier for the node. + +__classes__: __array__ ("string") + +: A list of class names for styling or semantics. + +__data__: __object__ + +: Arbitrary key-value data attached to the node. + +__children__: __array__ ("Inline") + +: The inline content to render as subscript. +: See @oxa:inline diff --git a/docs/schema/superscript.md b/docs/schema/superscript.md new file mode 100644 index 0000000..fd539a1 --- /dev/null +++ b/docs/schema/superscript.md @@ -0,0 +1,28 @@ +(oxa:superscript)= + +## Superscript + + +Content rendered above the baseline (e.g. exponents, ordinal suffixes). + + +__type__: _string_, ("Superscript") + +: The type discriminator for Superscript nodes. + +__id__: __string__ + +: A unique identifier for the node. + +__classes__: __array__ ("string") + +: A list of class names for styling or semantics. + +__data__: __object__ + +: Arbitrary key-value data attached to the node. + +__children__: __array__ ("Inline") + +: The inline content to render as superscript. +: See @oxa:inline diff --git a/docs/schema/thematicbreak.md b/docs/schema/thematicbreak.md new file mode 100644 index 0000000..30df4a1 --- /dev/null +++ b/docs/schema/thematicbreak.md @@ -0,0 +1,23 @@ +(oxa:thematicbreak)= + +## ThematicBreak + + +A thematic or structural division between sections of content. + + +__type__: _string_, ("ThematicBreak") + +: The type discriminator for ThematicBreak nodes. + +__id__: __string__ + +: A unique identifier for the node. + +__classes__: __array__ ("string") + +: A list of class names for styling or semantics. + +__data__: __object__ + +: Arbitrary key-value data attached to the node. diff --git a/packages/oxa-types-py/src/oxa_types/__init__.py b/packages/oxa-types-py/src/oxa_types/__init__.py index 254ca85..ddae659 100644 --- a/packages/oxa-types-py/src/oxa_types/__init__.py +++ b/packages/oxa-types-py/src/oxa_types/__init__.py @@ -11,6 +11,18 @@ from pydantic import BaseModel, ConfigDict, Field +class Code(BaseModel): + """A block of preformatted text, typically source code.""" + + model_config = ConfigDict(strict=True) + + type: Literal["Code"] = "Code" + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + language: str | None = Field(default=None, description="The programming language of the code content.") + value: str = Field(description="The code content.") + class Document(BaseModel): """A document with metadata, title, and block content.""" @@ -18,21 +30,11 @@ class Document(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Document"] = "Document" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) - metadata: dict[str, Any] | None = Field( - default=None, description="Arbitrary document metadata." - ) - title: list["Inline"] | None = Field( - default=None, description="The document title as inline content." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + metadata: dict[str, Any] | None = Field(default=None, description="Arbitrary document metadata.") + title: list["Inline"] | None = Field(default=None, description="The document title as inline content.") children: list["Block"] = Field(description="The block content of the document.") @@ -42,15 +44,9 @@ class Emphasis(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Emphasis"] = "Emphasis" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") children: list["Inline"] = Field(description="The inline content to emphasize.") @@ -60,34 +56,35 @@ class Heading(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Heading"] = "Heading" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") level: int = Field(description="The heading level (1-6).") children: list["Inline"] = Field(description="The inline content of the heading.") +class InlineCode(BaseModel): + """Short fragments of code appearing within prose.""" + + model_config = ConfigDict(strict=True) + + type: Literal["InlineCode"] = "InlineCode" + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + language: str | None = Field(default=None, description="The programming language of the code content.") + value: str = Field(description="The code content.") + + class Paragraph(BaseModel): """A paragraph of inline content.""" model_config = ConfigDict(strict=True) type: Literal["Paragraph"] = "Paragraph" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") children: list["Inline"] = Field(description="The inline content of the paragraph.") @@ -97,60 +94,93 @@ class Strong(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Strong"] = "Strong" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") children: list["Inline"] = Field(description="The inline content to emphasize.") +class Subscript(BaseModel): + """Content rendered below the baseline (e.g. chemical formulae, variable indices).""" + + model_config = ConfigDict(strict=True) + + type: Literal["Subscript"] = "Subscript" + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + children: list["Inline"] = Field(description="The inline content to render as subscript.") + + +class Superscript(BaseModel): + """Content rendered above the baseline (e.g. exponents, ordinal suffixes).""" + + model_config = ConfigDict(strict=True) + + type: Literal["Superscript"] = "Superscript" + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + children: list["Inline"] = Field(description="The inline content to render as superscript.") + + class Text(BaseModel): """A text node containing a string value.""" model_config = ConfigDict(strict=True) type: Literal["Text"] = "Text" - id: str | None = Field( - default=None, description="A unique identifier for the node." - ) - classes: list[str] | None = Field( - default=None, description="A list of class names for styling or semantics." - ) - data: dict[str, Any] | None = Field( - default=None, description="Arbitrary key-value data attached to the node." - ) + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") value: str = Field(description="The text content.") +class ThematicBreak(BaseModel): + """A thematic or structural division between sections of content.""" + + model_config = ConfigDict(strict=True) + + type: Literal["ThematicBreak"] = "ThematicBreak" + id: str | None = Field(default=None, description="A unique identifier for the node.") + classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") + data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + + # Union of all block content types. -Block = Annotated[Union[Heading, Paragraph], Field(discriminator="type")] +Block = Annotated[Union[Code, Heading, Paragraph, ThematicBreak], Field(discriminator="type")] # Union of all inline content types. -Inline = Annotated[Union[Text, Emphasis, Strong], Field(discriminator="type")] +Inline = Annotated[Union[Text, Emphasis, InlineCode, Strong, Subscript, Superscript], Field(discriminator="type")] # Rebuild models to resolve forward references +Code.model_rebuild() Document.model_rebuild() Emphasis.model_rebuild() Heading.model_rebuild() +InlineCode.model_rebuild() Paragraph.model_rebuild() Strong.model_rebuild() +Subscript.model_rebuild() +Superscript.model_rebuild() Text.model_rebuild() +ThematicBreak.model_rebuild() __all__ = [ "Block", + "Code", "Document", "Emphasis", "Heading", "Inline", + "InlineCode", "Paragraph", "Strong", + "Subscript", + "Superscript", "Text", + "ThematicBreak", ] diff --git a/packages/oxa-types-rs/src/lib.rs b/packages/oxa-types-rs/src/lib.rs index ca3d749..8baaa4f 100644 --- a/packages/oxa-types-rs/src/lib.rs +++ b/packages/oxa-types-rs/src/lib.rs @@ -9,6 +9,27 @@ use monostate::MustBe; use serde::{Deserialize, Serialize}; +/// A block of preformatted text, typically source code. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Code { + /// The type discriminator for Code nodes. + pub r#type: MustBe!("Code"), + /// A unique identifier for the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// A list of class names for styling or semantics. + #[serde(skip_serializing_if = "Option::is_none")] + pub classes: Option>, + /// Arbitrary key-value data attached to the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + /// The programming language of the code content. + #[serde(skip_serializing_if = "Option::is_none")] + pub language: Option, + /// The code content. + pub value: String, +} + /// A document with metadata, title, and block content. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Document { @@ -71,6 +92,27 @@ pub struct Heading { pub children: Vec, } +/// Short fragments of code appearing within prose. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct InlineCode { + /// The type discriminator for InlineCode nodes. + pub r#type: MustBe!("InlineCode"), + /// A unique identifier for the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// A list of class names for styling or semantics. + #[serde(skip_serializing_if = "Option::is_none")] + pub classes: Option>, + /// Arbitrary key-value data attached to the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + /// The programming language of the code content. + #[serde(skip_serializing_if = "Option::is_none")] + pub language: Option, + /// The code content. + pub value: String, +} + /// A paragraph of inline content. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Paragraph { @@ -107,6 +149,42 @@ pub struct Strong { pub children: Vec, } +/// Content rendered below the baseline (e.g. chemical formulae, variable indices). +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Subscript { + /// The type discriminator for Subscript nodes. + pub r#type: MustBe!("Subscript"), + /// A unique identifier for the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// A list of class names for styling or semantics. + #[serde(skip_serializing_if = "Option::is_none")] + pub classes: Option>, + /// Arbitrary key-value data attached to the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + /// The inline content to render as subscript. + pub children: Vec, +} + +/// Content rendered above the baseline (e.g. exponents, ordinal suffixes). +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Superscript { + /// The type discriminator for Superscript nodes. + pub r#type: MustBe!("Superscript"), + /// A unique identifier for the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// A list of class names for styling or semantics. + #[serde(skip_serializing_if = "Option::is_none")] + pub classes: Option>, + /// Arbitrary key-value data attached to the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + /// The inline content to render as superscript. + pub children: Vec, +} + /// A text node containing a string value. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Text { @@ -125,12 +203,30 @@ pub struct Text { pub value: String, } +/// A thematic or structural division between sections of content. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ThematicBreak { + /// The type discriminator for ThematicBreak nodes. + pub r#type: MustBe!("ThematicBreak"), + /// A unique identifier for the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// A list of class names for styling or semantics. + #[serde(skip_serializing_if = "Option::is_none")] + pub classes: Option>, + /// Arbitrary key-value data attached to the node. + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, +} + /// Union of all block content types. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum Block { + Code(Code), Heading(Heading), Paragraph(Paragraph), + ThematicBreak(ThematicBreak), } /// Union of all inline content types. @@ -139,5 +235,8 @@ pub enum Block { pub enum Inline { Text(Text), Emphasis(Emphasis), + InlineCode(InlineCode), Strong(Strong), + Subscript(Subscript), + Superscript(Superscript), } diff --git a/packages/oxa-types-ts/src/index.ts b/packages/oxa-types-ts/src/index.ts index e2f2b80..ec47e2d 100644 --- a/packages/oxa-types-ts/src/index.ts +++ b/packages/oxa-types-ts/src/index.ts @@ -5,6 +5,36 @@ * in the schema/ directory and run `pnpm codegen ts`. */ +/** + * A block of preformatted text, typically source code. + */ +export interface Code { + /** + * The type discriminator for Code nodes. + */ + type: "Code"; + /** + * A unique identifier for the node. + */ + id?: string; + /** + * A list of class names for styling or semantics. + */ + classes?: string[]; + /** + * Arbitrary key-value data attached to the node. + */ + data?: Record; + /** + * The programming language of the code content. + */ + language?: string; + /** + * The code content. + */ + value: string; +} + /** * A document with metadata, title, and block content. */ @@ -95,6 +125,36 @@ export interface Heading { children: Inline[]; } +/** + * Short fragments of code appearing within prose. + */ +export interface InlineCode { + /** + * The type discriminator for InlineCode nodes. + */ + type: "InlineCode"; + /** + * A unique identifier for the node. + */ + id?: string; + /** + * A list of class names for styling or semantics. + */ + classes?: string[]; + /** + * Arbitrary key-value data attached to the node. + */ + data?: Record; + /** + * The programming language of the code content. + */ + language?: string; + /** + * The code content. + */ + value: string; +} + /** * A paragraph of inline content. */ @@ -147,6 +207,58 @@ export interface Strong { children: Inline[]; } +/** + * Content rendered below the baseline (e.g. chemical formulae, variable indices). + */ +export interface Subscript { + /** + * The type discriminator for Subscript nodes. + */ + type: "Subscript"; + /** + * A unique identifier for the node. + */ + id?: string; + /** + * A list of class names for styling or semantics. + */ + classes?: string[]; + /** + * Arbitrary key-value data attached to the node. + */ + data?: Record; + /** + * The inline content to render as subscript. + */ + children: Inline[]; +} + +/** + * Content rendered above the baseline (e.g. exponents, ordinal suffixes). + */ +export interface Superscript { + /** + * The type discriminator for Superscript nodes. + */ + type: "Superscript"; + /** + * A unique identifier for the node. + */ + id?: string; + /** + * A list of class names for styling or semantics. + */ + classes?: string[]; + /** + * Arbitrary key-value data attached to the node. + */ + data?: Record; + /** + * The inline content to render as superscript. + */ + children: Inline[]; +} + /** * A text node containing a string value. */ @@ -173,12 +285,40 @@ export interface Text { value: string; } +/** + * A thematic or structural division between sections of content. + */ +export interface ThematicBreak { + /** + * The type discriminator for ThematicBreak nodes. + */ + type: "ThematicBreak"; + /** + * A unique identifier for the node. + */ + id?: string; + /** + * A list of class names for styling or semantics. + */ + classes?: string[]; + /** + * Arbitrary key-value data attached to the node. + */ + data?: Record; +} + /** * Union of all block content types. */ -export type Block = Heading | Paragraph; +export type Block = Code | Heading | Paragraph | ThematicBreak; /** * Union of all inline content types. */ -export type Inline = Text | Emphasis | Strong; +export type Inline = + | Text + | Emphasis + | InlineCode + | Strong + | Subscript + | Superscript; diff --git a/schema/Block.yaml b/schema/Block.yaml index 90468b0..7b0250f 100644 --- a/schema/Block.yaml +++ b/schema/Block.yaml @@ -3,5 +3,7 @@ $id: Block title: Block description: Union of all block content types. anyOf: + - $ref: "./Code.yaml" - $ref: "./Heading.yaml" - $ref: "./Paragraph.yaml" + - $ref: "./ThematicBreak.yaml" diff --git a/schema/Code.yaml b/schema/Code.yaml new file mode 100644 index 0000000..09fa6b6 --- /dev/null +++ b/schema/Code.yaml @@ -0,0 +1,30 @@ +$schema: "http://json-schema.org/draft-07/schema#" +$id: Code +title: Code +description: A block of preformatted text, typically source code. +type: object +properties: + type: + description: The type discriminator for Code nodes. + enum: [Code] + id: + description: A unique identifier for the node. + type: string + classes: + description: A list of class names for styling or semantics. + type: array + items: + type: string + data: + description: Arbitrary key-value data attached to the node. + type: object + additionalProperties: true + language: + description: The programming language of the code content. + type: string + value: + description: The code content. + type: string +required: + - type + - value diff --git a/schema/Inline.yaml b/schema/Inline.yaml index b2bb034..8fbc330 100644 --- a/schema/Inline.yaml +++ b/schema/Inline.yaml @@ -5,4 +5,7 @@ description: Union of all inline content types. anyOf: - $ref: "./Text.yaml" - $ref: "./Emphasis.yaml" + - $ref: "./InlineCode.yaml" - $ref: "./Strong.yaml" + - $ref: "./Subscript.yaml" + - $ref: "./Superscript.yaml" diff --git a/schema/InlineCode.yaml b/schema/InlineCode.yaml new file mode 100644 index 0000000..52b9583 --- /dev/null +++ b/schema/InlineCode.yaml @@ -0,0 +1,30 @@ +$schema: "http://json-schema.org/draft-07/schema#" +$id: InlineCode +title: InlineCode +description: Short fragments of code appearing within prose. +type: object +properties: + type: + description: The type discriminator for InlineCode nodes. + enum: [InlineCode] + id: + description: A unique identifier for the node. + type: string + classes: + description: A list of class names for styling or semantics. + type: array + items: + type: string + data: + description: Arbitrary key-value data attached to the node. + type: object + additionalProperties: true + language: + description: The programming language of the code content. + type: string + value: + description: The code content. + type: string +required: + - type + - value diff --git a/schema/Subscript.yaml b/schema/Subscript.yaml new file mode 100644 index 0000000..f202750 --- /dev/null +++ b/schema/Subscript.yaml @@ -0,0 +1,29 @@ +$schema: "http://json-schema.org/draft-07/schema#" +$id: Subscript +title: Subscript +description: Content rendered below the baseline (e.g. chemical formulae, variable indices). +type: object +properties: + type: + description: The type discriminator for Subscript nodes. + enum: [Subscript] + id: + description: A unique identifier for the node. + type: string + classes: + description: A list of class names for styling or semantics. + type: array + items: + type: string + data: + description: Arbitrary key-value data attached to the node. + type: object + additionalProperties: true + children: + description: The inline content to render as subscript. + type: array + items: + $ref: "./Inline.yaml" +required: + - type + - children diff --git a/schema/Superscript.yaml b/schema/Superscript.yaml new file mode 100644 index 0000000..2fbe2d0 --- /dev/null +++ b/schema/Superscript.yaml @@ -0,0 +1,29 @@ +$schema: "http://json-schema.org/draft-07/schema#" +$id: Superscript +title: Superscript +description: Content rendered above the baseline (e.g. exponents, ordinal suffixes). +type: object +properties: + type: + description: The type discriminator for Superscript nodes. + enum: [Superscript] + id: + description: A unique identifier for the node. + type: string + classes: + description: A list of class names for styling or semantics. + type: array + items: + type: string + data: + description: Arbitrary key-value data attached to the node. + type: object + additionalProperties: true + children: + description: The inline content to render as superscript. + type: array + items: + $ref: "./Inline.yaml" +required: + - type + - children diff --git a/schema/ThematicBreak.yaml b/schema/ThematicBreak.yaml new file mode 100644 index 0000000..4c3891a --- /dev/null +++ b/schema/ThematicBreak.yaml @@ -0,0 +1,23 @@ +$schema: "http://json-schema.org/draft-07/schema#" +$id: ThematicBreak +title: ThematicBreak +description: A thematic or structural division between sections of content. +type: object +properties: + type: + description: The type discriminator for ThematicBreak nodes. + enum: [ThematicBreak] + id: + description: A unique identifier for the node. + type: string + classes: + description: A list of class names for styling or semantics. + type: array + items: + type: string + data: + description: Arbitrary key-value data attached to the node. + type: object + additionalProperties: true +required: + - type diff --git a/schema/schema.json b/schema/schema.json index db84d07..97a723d 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -9,14 +9,56 @@ "title": "Block", "description": "Union of all block content types.", "anyOf": [ + { + "$ref": "#/definitions/Code" + }, { "$ref": "#/definitions/Heading" }, { "$ref": "#/definitions/Paragraph" + }, + { + "$ref": "#/definitions/ThematicBreak" } ] }, + "Code": { + "title": "Code", + "description": "A block of preformatted text, typically source code.", + "type": "object", + "properties": { + "type": { + "description": "The type discriminator for Code nodes.", + "enum": ["Code"] + }, + "id": { + "description": "A unique identifier for the node.", + "type": "string" + }, + "classes": { + "description": "A list of class names for styling or semantics.", + "type": "array", + "items": { + "type": "string" + } + }, + "data": { + "description": "Arbitrary key-value data attached to the node.", + "type": "object", + "additionalProperties": true + }, + "language": { + "description": "The programming language of the code content.", + "type": "string" + }, + "value": { + "description": "The code content.", + "type": "string" + } + }, + "required": ["type", "value"] + }, "Document": { "title": "Document", "description": "A document with metadata, title, and block content.", @@ -150,11 +192,56 @@ { "$ref": "#/definitions/Emphasis" }, + { + "$ref": "#/definitions/InlineCode" + }, { "$ref": "#/definitions/Strong" + }, + { + "$ref": "#/definitions/Subscript" + }, + { + "$ref": "#/definitions/Superscript" } ] }, + "InlineCode": { + "title": "InlineCode", + "description": "Short fragments of code appearing within prose.", + "type": "object", + "properties": { + "type": { + "description": "The type discriminator for InlineCode nodes.", + "enum": ["InlineCode"] + }, + "id": { + "description": "A unique identifier for the node.", + "type": "string" + }, + "classes": { + "description": "A list of class names for styling or semantics.", + "type": "array", + "items": { + "type": "string" + } + }, + "data": { + "description": "Arbitrary key-value data attached to the node.", + "type": "object", + "additionalProperties": true + }, + "language": { + "description": "The programming language of the code content.", + "type": "string" + }, + "value": { + "description": "The code content.", + "type": "string" + } + }, + "required": ["type", "value"] + }, "Paragraph": { "title": "Paragraph", "description": "A paragraph of inline content.", @@ -225,6 +312,76 @@ }, "required": ["type", "children"] }, + "Subscript": { + "title": "Subscript", + "description": "Content rendered below the baseline (e.g. chemical formulae, variable indices).", + "type": "object", + "properties": { + "type": { + "description": "The type discriminator for Subscript nodes.", + "enum": ["Subscript"] + }, + "id": { + "description": "A unique identifier for the node.", + "type": "string" + }, + "classes": { + "description": "A list of class names for styling or semantics.", + "type": "array", + "items": { + "type": "string" + } + }, + "data": { + "description": "Arbitrary key-value data attached to the node.", + "type": "object", + "additionalProperties": true + }, + "children": { + "description": "The inline content to render as subscript.", + "type": "array", + "items": { + "$ref": "#/definitions/Inline" + } + } + }, + "required": ["type", "children"] + }, + "Superscript": { + "title": "Superscript", + "description": "Content rendered above the baseline (e.g. exponents, ordinal suffixes).", + "type": "object", + "properties": { + "type": { + "description": "The type discriminator for Superscript nodes.", + "enum": ["Superscript"] + }, + "id": { + "description": "A unique identifier for the node.", + "type": "string" + }, + "classes": { + "description": "A list of class names for styling or semantics.", + "type": "array", + "items": { + "type": "string" + } + }, + "data": { + "description": "Arbitrary key-value data attached to the node.", + "type": "object", + "additionalProperties": true + }, + "children": { + "description": "The inline content to render as superscript.", + "type": "array", + "items": { + "$ref": "#/definitions/Inline" + } + } + }, + "required": ["type", "children"] + }, "Text": { "title": "Text", "description": "A text node containing a string value.", @@ -256,6 +413,34 @@ } }, "required": ["type", "value"] + }, + "ThematicBreak": { + "title": "ThematicBreak", + "description": "A thematic or structural division between sections of content.", + "type": "object", + "properties": { + "type": { + "description": "The type discriminator for ThematicBreak nodes.", + "enum": ["ThematicBreak"] + }, + "id": { + "description": "A unique identifier for the node.", + "type": "string" + }, + "classes": { + "description": "A list of class names for styling or semantics.", + "type": "array", + "items": { + "type": "string" + } + }, + "data": { + "description": "Arbitrary key-value data attached to the node.", + "type": "object", + "additionalProperties": true + } + }, + "required": ["type"] } }, "$ref": "#/definitions/Document" From d4f81c317f72fa617113525a7a54df33d8460cfa Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Tue, 24 Mar 2026 18:16:18 +0000 Subject: [PATCH 2/3] chore(*): update formatted/generated files [skip ci] --- .../oxa-types-py/src/oxa_types/__init__.py | 166 +++++++++++++----- 1 file changed, 125 insertions(+), 41 deletions(-) diff --git a/packages/oxa-types-py/src/oxa_types/__init__.py b/packages/oxa-types-py/src/oxa_types/__init__.py index ddae659..1a21899 100644 --- a/packages/oxa-types-py/src/oxa_types/__init__.py +++ b/packages/oxa-types-py/src/oxa_types/__init__.py @@ -11,16 +11,25 @@ from pydantic import BaseModel, ConfigDict, Field + class Code(BaseModel): """A block of preformatted text, typically source code.""" model_config = ConfigDict(strict=True) type: Literal["Code"] = "Code" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") - language: str | None = Field(default=None, description="The programming language of the code content.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) + language: str | None = Field( + default=None, description="The programming language of the code content." + ) value: str = Field(description="The code content.") @@ -30,11 +39,21 @@ class Document(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Document"] = "Document" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") - metadata: dict[str, Any] | None = Field(default=None, description="Arbitrary document metadata.") - title: list["Inline"] | None = Field(default=None, description="The document title as inline content.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) + metadata: dict[str, Any] | None = Field( + default=None, description="Arbitrary document metadata." + ) + title: list["Inline"] | None = Field( + default=None, description="The document title as inline content." + ) children: list["Block"] = Field(description="The block content of the document.") @@ -44,9 +63,15 @@ class Emphasis(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Emphasis"] = "Emphasis" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) children: list["Inline"] = Field(description="The inline content to emphasize.") @@ -56,9 +81,15 @@ class Heading(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Heading"] = "Heading" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) level: int = Field(description="The heading level (1-6).") children: list["Inline"] = Field(description="The inline content of the heading.") @@ -69,10 +100,18 @@ class InlineCode(BaseModel): model_config = ConfigDict(strict=True) type: Literal["InlineCode"] = "InlineCode" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") - language: str | None = Field(default=None, description="The programming language of the code content.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) + language: str | None = Field( + default=None, description="The programming language of the code content." + ) value: str = Field(description="The code content.") @@ -82,9 +121,15 @@ class Paragraph(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Paragraph"] = "Paragraph" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) children: list["Inline"] = Field(description="The inline content of the paragraph.") @@ -94,9 +139,15 @@ class Strong(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Strong"] = "Strong" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) children: list["Inline"] = Field(description="The inline content to emphasize.") @@ -106,10 +157,18 @@ class Subscript(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Subscript"] = "Subscript" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") - children: list["Inline"] = Field(description="The inline content to render as subscript.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) + children: list["Inline"] = Field( + description="The inline content to render as subscript." + ) class Superscript(BaseModel): @@ -118,10 +177,18 @@ class Superscript(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Superscript"] = "Superscript" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") - children: list["Inline"] = Field(description="The inline content to render as superscript.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) + children: list["Inline"] = Field( + description="The inline content to render as superscript." + ) class Text(BaseModel): @@ -130,9 +197,15 @@ class Text(BaseModel): model_config = ConfigDict(strict=True) type: Literal["Text"] = "Text" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) value: str = Field(description="The text content.") @@ -142,17 +215,28 @@ class ThematicBreak(BaseModel): model_config = ConfigDict(strict=True) type: Literal["ThematicBreak"] = "ThematicBreak" - id: str | None = Field(default=None, description="A unique identifier for the node.") - classes: list[str] | None = Field(default=None, description="A list of class names for styling or semantics.") - data: dict[str, Any] | None = Field(default=None, description="Arbitrary key-value data attached to the node.") + id: str | None = Field( + default=None, description="A unique identifier for the node." + ) + classes: list[str] | None = Field( + default=None, description="A list of class names for styling or semantics." + ) + data: dict[str, Any] | None = Field( + default=None, description="Arbitrary key-value data attached to the node." + ) # Union of all block content types. -Block = Annotated[Union[Code, Heading, Paragraph, ThematicBreak], Field(discriminator="type")] +Block = Annotated[ + Union[Code, Heading, Paragraph, ThematicBreak], Field(discriminator="type") +] # Union of all inline content types. -Inline = Annotated[Union[Text, Emphasis, InlineCode, Strong, Subscript, Superscript], Field(discriminator="type")] +Inline = Annotated[ + Union[Text, Emphasis, InlineCode, Strong, Subscript, Superscript], + Field(discriminator="type"), +] # Rebuild models to resolve forward references From 32524d5b6d5191368899a0c451f4dc594b839b1a Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Tue, 24 Mar 2026 12:18:22 -0600 Subject: [PATCH 3/3] changeset --- .changeset/short-areas-spend.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-areas-spend.md diff --git a/.changeset/short-areas-spend.md b/.changeset/short-areas-spend.md new file mode 100644 index 0000000..6d5faa5 --- /dev/null +++ b/.changeset/short-areas-spend.md @@ -0,0 +1,5 @@ +--- +"oxa-types": patch +--- + +Add initial node types using RFC0003 (Code, InlineCode, Subscript, Superscript, ThematicBreak).