Documentation
How to open, validate, search and cite SPDF files in Rust, TypeScript, Python, Swift, Kotlin, Go, C#, PHP, Ruby, R, Julia and C.
Reviewed Markdown
Every implementation offers the same operations with the names and habits of its language. Pick yours; each page has the install line, a first example and the full README of the library.
- Rust
cargo add spdfReference implementation; also provides the C ABI. - TypeScript
npm install spdf-formatNode (node:sqlite), Bun and the browser (sqlite-wasm). Powers the validator on this site. - Python
pip install spdf-formatStandard library sqlite3 only; imported as spdf. - Swift
.package(url: "https://github.com/joseluissaorin/spdf", from: "5.0.0")Swift Package Manager, from the repository. Apple platforms and Linux. - Kotlin / JVM
implementation("io.github.joseluissaorin:spdf:5.0.0")Kotlin and Java on the JVM and Android. - Go
go get github.com/joseluissaorin/spdf/goGo module in the monorepo. - C# / .NET
dotnet add package Spdf.Format.NET with Microsoft.Data.Sqlite.CI failing - PHP
composer require joseluissaorin/spdfPDO SQLite. - Ruby
gem install spdf-formatOn the sqlite3 gem. - R
remotes::install_github("joseluissaorin/spdf", subdir = "r")On RSQLite; fragments as data frames. - Julia
pkg> add SPDFOn SQLite.jl. - C
#include "spdf.h" /* link with -lspdf */C ABI over the Rust core, for C, C++ and any FFI.
The same operations everywhere
| Operation | What it returns |
|---|---|
| open | A read-only handle on a 5.0 or legacy 4.x file, opened safely |
| validate | {valid, version, profile, errors, warnings} with the codes of the specification |
| dump | The canonical JSON of the file (RFC 8785) |
| search (lexical, vector, hybrid) | {fragment_id, score, via, anchor, anchor_uri} items |
| anchor URI | Format and parse spdf: URIs, byte for byte |
| cite | (Family, Year, locator) in English or Spanish |
| export | CSL-JSON and BibTeX |
| write | A new, valid SPDF built from your own data |
Without any library
An SPDF file is a SQLite database. Any tool that speaks SQLite reads it; only the safety rules and the anchors need care.
sqlite3 -readonly darwin-origin.spdf "SELECT key, value FROM spdf_meta"
sqlite3 -readonly darwin-origin.spdf \
"SELECT f.id, u.printed, substr(f.text, 1, 80)
FROM fragments_fts JOIN fragments f ON f.n = fragments_fts.rowid
JOIN units u ON u.id = f.unit
WHERE fragments_fts MATCH 'selection' LIMIT 5"Legacy 4.x files from Scholaris are gzip-wrapped: gzip -dc old.spdf > old.sqlite first.