Workspace overview

Updated Jul 01, 2026
  • tei-core now models the top-level TeiDocument together with its TeiHeader and body-aware TeiText. The text model records ordered paragraphs (P), utterances with optional speaker references, and structural divisions (Div) containing paragraphs, utterances, lists (List/Item, where each Item may carry an optional inline Label), and nested subdivisions. Each Div keeps a required @type (DivType), an optional @subtype, an optional @xml:id, and an optional Head wrapper for a single leading <head> element in the Episodic profile. Each block stores a sequence of Inline nodes, allowing clients to mix plain text with emphasized <hi> spans and <pause/> cues without hand-rolling XML. Plain strings flow through P::from_text_segments, Utterance::from_text_segments, Item::from_text_segments, Label::from_text, and Head::from_text; the older new constructors remain as deprecated shims for existing callers where applicable. TeiDocument now exposes validate() to enforce document-wide rules: it rejects duplicate xml:id values across annotation systems, paragraphs, utterances, divisions, lists, and items, including nested divisions, and ensures utterance speakers appear in the profile cast when it exists. An empty cast still counts as declared, so every who fails until the speakers are populated, whereas the absence of a cast allows speaker references, so drafts can be validated incrementally. Identifier checks span the header as well, catching clashes between annotation systems and body blocks. Violations surface as TeiError::Validation. Utterances and list items now also carry local provenance and citation attributes where applicable, and XML deserialization remains strict for <u> and <item>: misspelt or unsupported attributes are rejected instead of being silently discarded.
  • tei-xml depends on the core crate and now covers both directions of XML flow. serialize_document_title(raw_title) still emits a <title> snippet, parse_xml(xml) wraps quick-xml to materialize full TeiDocument values, and emit_xml(&document) now uses a hybrid emitter: header and stand-off sections are serialized via quick_xml, while body content is handwritten so mixed inline content and structural divisions round-trip correctly. All helpers return TeiError, so callers see consistent diagnostics whether parsing malformed input or attempting to emit control characters that XML forbids.
  • tei-serde centralizes JSON and MessagePack serialization, allowing the rest of the workspace to depend on a stable wrapper API (tei_serde::json, tei_serde::msgpack) instead of taking direct dependencies on serde_json and rmp-serde. It also publishes a versioned JSON Schema snapshot for TeiDocument under schemas/tei-document.schema.vX.Y.Z.json (with schemas/tei-document.schema.json tracking the latest snapshot), generated from the tei-core Rust types via schemars. Schema generation is gated behind the optional tei-core Cargo feature json-schema so consumers that do not need schema publication can avoid pulling in schemars.
  • tei-py now ships the tei_rapporteur PyO3 module. The exported Document class wraps TeiDocument, validates titles via the Rust constructors, and exposes a title getter plus an emit_title_markup convenience method. The module also surfaces a top-level emit_title_markup function so Python callers mirror the Rust helper without reimplementing validation rules. The MessagePack bridge exposes both from_msgpack and to_msgpack for binary interchange. Dictionary exchange is available via from_dict/to_dict, powered by pyo3-serde, so Python built-ins can cross the FFI boundary without detouring through JSON text. Phase 2.2 adds parse_xml/emit_xml bindings that forward TEI strings directly to the tei-xml helpers. Python can now parse canonical TEI without detouring through MessagePack, and emission always routes through the same forbidden-character guardrails as the Rust callers. Python-facing errors are surfaced as ValueError for content issues and TypeError when callers pass the wrong objects to the bindings.
  • tei-test-helpers captures assertion helpers that multiple crates reuse in their unit and behaviour-driven tests.
  • pyproject.toml configures maturin to build tei-py, allowing maturin develop or maturin build to work from the workspace root without additional arguments.