Examples

Use the strict SSMD 0.9 examples below for new documents. Complete documents declare ssmd_version: '0.9', use canonical long-form attributes and fenced ::: directives for block-aligned scopes. Runnable examples live in the examples directory on GitHub.

Canonical SSMD 0.9 document

Save complete documents with an .ssmd.md filename when an SSMD-specific suffix is useful. This example covers front matter, paragraphs, emphasis, pauses, language, voice, marks, and prosody:

---
ssmd_version: '0.9'
title: Welcome
---
# Welcome

*Hello* and **welcome** to SSMD ...500ms.

[Bonjour]{lang="fr-FR"} tout le monde!

:::{voice="host" voice-languages="en-US"}
Welcome to the show.
:::
:::{voice="guest" voice-languages="en-US"}
Thanks for having me.
:::

:::{volume="loud" rate="fast" pitch="high"}
This passage is loud, fast, and high-pitched.
:::

I always wanted a @marker cat as a pet.

Adjacent fenced directives with no blank line between them belong to the same semantic paragraph. Their clean text receives ordinary inline separation and no paragraph event. A blank line between sibling directives creates a paragraph boundary; canonical formatting preserves this distinction. A voice change does not by itself create a paragraph pause.

Use inline voice annotations for genuinely short, mixed-flow spans:

The host said [hello]{voice="host"}, then the guest replied.

Parse strict 0.9 structure

parse_structure() is the sentence-neutral API for strict 0.9 documents. It returns clean text, annotation ranges, structural events, front matter, and source-aware diagnostics without running sentence detection:

from pathlib import Path

from ssmd.parser import lint, parse_structure

source = Path("story.ssmd.md").read_text(encoding="utf-8")
structure = parse_structure(source, dialect="0.9")
issues = lint(source, dialect="0.9")

print(structure.clean_text)
print(structure.annotations)
print(structure.events)
print(structure.header)
print(issues)

Annotation ranges are half-open offsets into clean_text. Break, mark, heading, and paragraph events use clean-text boundary positions. Paragraph events represent document structure; they do not prescribe a pause duration. A downstream TTS pipeline may normalize the clean text and then supply explicit sentence spans to rendering.

Render for a TTS target

Use Document for complete-document rendering and capability adaptation. Do not use its sentence/list APIs for strict 0.9 documents; those are compatibility APIs for legacy input.

from ssmd import Document

source = """\
---
ssmd_version: '0.9'
---
# Announcement

Hello *world*! [Bonjour]{lang="fr"} everyone ...300ms.
"""
document = Document(source, config={"dialect": "0.9"}, capabilities="espeak")
print(document.to_text())
print(document.to_ssml())

For runnable structural, story-rendering, capability, and provider-extension examples, see:

Google style annotations require explicitly registered trusted extension handlers; they are provider-specific, not part of the portable all-features example.

Legacy 0.8 sentence-parser compatibility

The following snippet intentionally demonstrates an unversioned legacy 0.8 input and the sentence-oriented compatibility API. It is not a strict 0.9 authoring example. New documents should use fenced directives and parse_structure() instead.

from ssmd import parse_sentences

legacy_script = """\
<div voice="host">
Welcome to the show.
</div>

<div voice="guest">
Thanks for having me.
</div>
"""

for sentence in parse_sentences(legacy_script):
    voice = sentence.voice.name if sentence.voice else "default"
    print(f"[{voice}] {''.join(segment.text for segment in sentence.segments)}")

For conversion of existing files, use the semantic migration command and review any manual actions before replacing the source:

ssmd --json migrate legacy.ssmd --to 0.9 -o story-09.ssmd.md

See the syntax reference, parser API, and span API for more detail.