Skip to content

Repository files navigation

SpeechMarkdown Rust

High-performance SpeechMarkdown parser written in Rust. Converts SpeechMarkdown syntax to platform-specific SSML for Amazon Alexa, Google Assistant, Microsoft Azure, and more.

Repository Structure

This repository contains the core Rust SpeechMarkdown parser with bindings for multiple languages:

speechmarkdown-rust/
├── src/ # Core Rust library (language-agnostic)
├── bindings/ # Language-specific bindings
│ ├── python/ # Python bindings via PyO3
│ ├── nodejs/ # Node.js bindings via napi-rs
│ ├── dotnet/ # .NET bindings via rust-cpp
│ └── swift/ # Swift bindings via C API + SPM
├── Package.swift # Swift Package Manager configuration (Swift-only)
├── build-swift-package.sh # Swift package build script (Swift-only)
└── Cargo.toml # Rust package configuration

Important Notes for Non-Swift Users:

  • Swift-specific files are ignored by other build systems: Package.swift, build-swift-package.sh, and swift-package-dist/ are only used by Swift Package Manager. They do not affect Rust, Python, Node.js, or .NET builds.
  • Core Rust library unchanged: The src/ directory and Cargo.toml remain the single source of truth for the SpeechMarkdown parser across all languages.
  • Isolated language bindings: Each language in bindings/ has its own build configuration and doesn't interfere with others.

For Rust/.NET/Python/Node.js Developers: You can safely ignore Swift-specific files. Your respective package managers (Cargo, NuGet, PyPI, npm) only use the core library and your language's binding directory.

Install

LanguagePackageInstall
Rustspeechmarkdown-rustcargo add speechmarkdown-rust
Pythonspeechmarkdown-rustpip install speechmarkdown-rust
Node.jsspeechmarkdownnpm install speechmarkdown
.NETSpeechMarkdowndotnet add package SpeechMarkdown
SwiftRelease assetSee Swift section below

Supported Platforms

PlatformString ID
Amazon Alexa"amazon-alexa" or "alexa"
Google Assistant"google-assistant" or "google"
Microsoft Azure"microsoft-azure" or "azure"
Apple"apple"
W3C"w3c"
Samsung Bixby"samsung-bixby" or "bixby"
ElevenLabs"elevenlabs"
IBM Watson"ibm-watson" or "watson"

API

All bindings expose the same core methods:

MethodReturnsDescription
to_ssml(input, platform)stringConvert SpeechMarkdown to SSML for the given platform
to_text(input)stringConvert SpeechMarkdown to plain text (strips all markup)
to_smd(ssml)stringConvert SSML to SpeechMarkdown (best-effort, lossy for unsupported elements)
parse(input)string (JSON)Parse SpeechMarkdown and return the AST as JSON
is_speech_markdown(input)boolCheck if a string contains SpeechMarkdown syntax
validate(input)boolValidate that SpeechMarkdown parses without errors
supported_ssml(platform)string (JSON)Get supported SSML elements for a platform

Usage

Rust

use speechmarkdown_rust::{SpeechMarkdownParser,Platform};// Convert to SSMLlet ssml = SpeechMarkdownParser::to_ssml("Hello (world)[emphasis:\"strong\"]",Platform::AmazonAlexa,)?;// Convert to plain textlet text = SpeechMarkdownParser::to_text("Hello (world)[emphasis:\"strong\"]")?;// Parse to AST (JSON string)let ast = SpeechMarkdownParser::parse("Hello world")?;// Check if input contains SpeechMarkdown syntaxifSpeechMarkdownParser::is_speech_markdown(&input){// ...}// Validate inputSpeechMarkdownParser::validate(&input)?;// Convert SSML back to SpeechMarkdown (best-effort)let smd = SpeechMarkdownParser::to_smd(r#"<speak><emphasis level="strong">word</emphasis></speak>"#)?;// Returns: ++word++

Python

fromspeechmarkdown_rustimportto_ssml, to_text, parse, is_speech_markdown, validatessml=to_ssml('Hello (world)[emphasis:"strong"]', 'amazon-alexa')
text=to_text('Hello (world)[emphasis:"strong"]')
ast=parse('Hello world')
is_smd=is_speech_markdown('Hello (world)[emphasis:"strong"]') # Trueis_smd=is_speech_markdown('Hello world') # Falsevalidate('Hello (world)[emphasis:"strong"]') # raises ValueError if invalid# Convert SSML to SpeechMarkdown (best-effort)smd=to_smd('<speak><emphasis level="strong">word</emphasis></speak>')
# Returns: ++word++

Node.js

const{ to_ssml, to_text, parse, is_speech_markdown, validate }=require('speechmarkdown')constssml=to_ssml('Hello (world)[emphasis:"strong"]','amazon-alexa')consttext=to_text('Hello (world)[emphasis:"strong"]')constast=parse('Hello world')is_speech_markdown('Hello (world)[emphasis:"strong"]')// trueis_speech_markdown('Hello world')// falsevalidate('Hello (world)[emphasis:"strong"]')// throws if invalid// Convert SSML to SpeechMarkdown (best-effort)constsmd=to_smd('<speak><emphasis level="strong">word</emphasis></speak>')// Returns: ++word++

.NET (C#)

usingSpeechMarkdown;varparser=newSpeechMarkdownParser();stringssml=parser.ToSsml("Hello (world)[emphasis:\"strong\"]",Platform.AmazonAlexa);stringtext=parser.ToText("Hello (world)[emphasis:\"strong\"]");stringjson=parser.ParseToJson("Hello world");boolisSmd=parser.IsSpeechMarkdown("Hello (world)[emphasis:\"strong\"]");// trueparser.Validate("Hello (world)[emphasis:\"strong\"]");// throws on invalid// Convert SSML to SpeechMarkdown (best-effort)stringsmd=parser.ToSmd("<speak><emphasis level=\"strong\">word</emphasis></speak>");// Returns: ++word++

Swift

The repo root contains a Package.swift with a binary target pointing to a pre-built XCFramework. This enables both local development and Swift Package Index integration.

Option 1 — SPM (recommended):

// In your Package.swift:
.package(url:"https://github.com/AACTools/speechmarkdown-rust", branch:"spm")

Option 2 — Local package: Download speechmarkdown-swift-package.zip from the latest release, unzip, and add as a local package in Xcode (File > Add Packages > Add Local).

Includes macOS (arm64 + x86_64), iOS device (arm64), and iOS simulator (arm64) slices.

To build from source: ./build-swift-package.sh

import SpeechMarkdown
letparser=SpeechMarkdownParser()letssml=try parser.toSsml(input:"Hello (world)[emphasis:\"strong\"]", platform:"amazon-alexa")lettext=try parser.toText(input:"Hello (world)[emphasis:\"strong\"]")letjson=try parser.parseToJson(input:"Hello world")letisSmd= parser.isSpeechMarkdown(input:"Hello (world)[emphasis:\"strong\"]") // true
try parser.validate(input:"Hello (world)[emphasis:\"strong\"]") // throws on invalid
// Convert SSML to SpeechMarkdown (best-effort)
letsmd=try parser.toSmd(ssml:"<speak><emphasis level=\"strong\">word</emphasis></speak>")
// Returns: ++word++

C API

#include"speechmarkdown.h"// Convert to SSMLconstchar*ssml=speechmarkdown_to_ssml("Hello (world)[emphasis:\"strong\"]", "amazon-alexa");
speechmarkdown_free((char*)ssml);
// Convert to plain textconstchar*text=speechmarkdown_to_text("Hello (world)[emphasis:\"strong\"]");
speechmarkdown_free((char*)text);
// Parse to JSONconstchar*json=speechmarkdown_parse("Hello world");
speechmarkdown_free((char*)json);
// Check for SpeechMarkdown syntaxboolis_smd=speechmarkdown_is_speech_markdown("Hello (world)[emphasis:\"strong\"]");
// Validateboolvalid=speechmarkdown_validate("Hello (world)[emphasis:\"strong\"]");
// Convert SSML to SpeechMarkdown (best-effort)constchar*smd=speechmarkdown_to_smd("<speak><emphasis level=\"strong\">word</emphasis></speak>");
speechmarkdown_free((char*)smd);
// Get last error (thread-local)constchar*err=speechmarkdown_get_error();

Building from Source

Core Rust Library

The core Rust parser is built with:

cargo build --release

This produces:

  • Windows: target/release/speechmarkdown_rust.dll
  • macOS: target/release/libspeechmarkdown_rust.dylib
  • Linux: target/release/libspeechmarkdown_rust.so

Language-Specific Builds

Each language binding has its own build process:

Python:

cd bindings/python
maturin develop
# or for release: maturin build --release

Node.js:

cd bindings/nodejs
npm install
npm run build

.NET:

cd bindings/dotnet
dotnet build

Swift:

# Uses pre-built XCFramework from releases# Or build from source:
./build-swift-package.sh

Development Workflow

The repository follows a unified development model where all language bindings share the same core Rust parser:

  1. Core changes: Modify src/ for parser logic changes
  2. Language changes: Modify bindings/<language>/ for binding-specific changes
  3. Testing: Each language has its own test suite
  4. Releases: All packages are released together with version synchronization

For Contributors:

  • Rust developers: Work in src/ and test with cargo test
  • Python developers: Work in bindings/python/ and test with pytest
  • Node.js developers: Work in bindings/nodejs/ and test with npm test
  • .NET developers: Work in bindings/dotnet/ and test with dotnet test
  • Swift developers: Work in bindings/swift/ and use SPM for testing

License

MIT

About

rust SMD AST

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages