Releases: 3leaps/docprims
Release list
v0.1.4
docprims v0.1.4
Release Date: 2026-01-31
Status: Patch Release (Go rpath + TypeScript OIDC fixes)
Summary
This release improves Go shared library developer experience and applies npm OIDC publishing fixes learned from sysprims.
Highlights
- Go shared library rpath: Local builds no longer require
LD_LIBRARY_PATH/DYLD_LIBRARY_PATH - TypeScript npm OIDC fixes: Workflow now correctly uses OIDC trusted publishing
- ADR-0006: Documents TypeScript npm publishing standard
Go Shared Library Improvement
The Change
v0.1.4 embeds -Wl,-rpath entries in cgo LDFLAGS for shared library builds on darwin-arm64, linux-amd64, and linux-arm64. This embeds the vendored lib-shared/ directories in the binary's library search path.
Before v0.1.4
# Required environment variable for local development
DYLD_LIBRARY_PATH=./lib-shared/darwin-arm64 go run . # macOS
LD_LIBRARY_PATH=./lib-shared/linux-amd64 go run . # Linuxv0.1.4+
# Just works - rpath is embedded
go run .
go build -tags docprims_shared .Distribution Guidance
For distributing binaries, prefer bundling the shared library next to your executable and embedding a platform-appropriate rpath:
| Platform | Rpath Pattern |
|---|---|
| macOS | @executable_path |
| Linux | $ORIGIN |
Example:
# Build with custom rpath for distribution
go build -ldflags="-r @executable_path" -tags docprims_shared .TypeScript npm OIDC Publishing Fixes
Issues Addressed
The npm publish workflow had several issues preventing OIDC trusted publishing from working:
- npm CLI too old: Ubuntu runners with Node 20 ship npm ~10.x, which lacks OIDC support
- Token interference:
actions/setup-nodewithregistry-urlcreates.npmrcthat can interfere with OIDC - git fetch conflict:
fetch-tags: truecauses errors when running from a tag ref - Transient failures: Artifact downloads occasionally fail on GitHub-hosted runners
Fixes Applied
# 1. Upgrade npm to version with OIDC support
- name: Ensure npm CLI supports OIDC
run: npm install -g npm@11.5.1
# 2. Force OIDC mode in publish steps
- name: Publish
run: |
unset NODE_AUTH_TOKEN NPM_TOKEN
export NPM_CONFIG_USERCONFIG="$RUNNER_TEMP/npmrc-oidc"
printf '%s\n' 'registry=https://registry.npmjs.org/' 'always-auth=false' > "$NPM_CONFIG_USERCONFIG"
npm publish --access public
# 3. Remove fetch-tags from checkout
- uses: actions/checkout@v4 # No fetch-tags option
# 4. Add retry logic for artifact download
for attempt in 1 2 3 4 5; do
if gh run download "${RUN_ID}" --name ts-npm-dir --dir npm-packages; then
break
fi
sleep $((attempt * attempt))
doneADR-0006
This release adds ADR-0006 documenting the TypeScript npm publishing standard, including:
- OIDC trusted publishing configuration
- Force OIDC mode pattern
- Release workflow order requirements
- First-publish manual bootstrap process
See docs/decisions/ADR-0006-typescript-npm-publishing.md for details.
Changelog
See CHANGELOG.md for detailed changes.
v0.1.3
docprims v0.1.3
Release Date: 2026-01-31
Status: Patch Release (TypeScript CI/CD)
Summary
This release adds CI/CD automation for TypeScript bindings, enabling cross-platform prebuilds and npm trusted publishing.
Highlights
- Cross-platform prebuilds workflow: Builds native addons for all supported platforms via GitHub Actions
- npm trusted publishing: OIDC-based workflow for secure, automated npm releases
- Platform packages: Optional dependencies for seamless
npm installwithout local Rust toolchain
CI/CD Workflows
TypeScript N-API Prebuilds (typescript-napi-prebuilds.yml)
Builds .node native addons for all supported platforms:
| Platform | Runner | Method |
|---|---|---|
| linux-x64-gnu | ubuntu-latest | zig cross-compile (glibc 2.17 baseline) |
| linux-x64-musl | ubuntu-latest | zig cross-compile |
| linux-arm64-gnu | ubuntu-latest-arm64-s | native build |
| linux-arm64-musl | ubuntu-latest | zig cross-compile |
| darwin-arm64 | macos-14 | native build |
| win32-x64-msvc | windows-latest | native build |
Outputs:
- Per-platform artifacts with
.nodefiles - Combined
ts-npm-dirartifact with platform package structure
TypeScript npm Publish (typescript-npm-publish.yml)
Publishes to npm using OIDC trusted publishing:
- Validates workflow runs from a release tag
- Verifies VERSION file and package.json match the tag
- Downloads prebuilds from a matching workflow run
- Publishes platform packages first, then root package
Features:
- Dry-run mode for validation
- Explicit prebuilds run ID input (or auto-selects latest for commit)
- Post-publish verification
Package Structure
The TypeScript package now uses optional dependencies for platform binaries:
{
"optionalDependencies": {
"@3leaps/docprims-linux-x64-gnu": "0.1.3",
"@3leaps/docprims-linux-x64-musl": "0.1.3",
"@3leaps/docprims-linux-arm64-gnu": "0.1.3",
"@3leaps/docprims-linux-arm64-musl": "0.1.3",
"@3leaps/docprims-darwin-arm64": "0.1.3",
"@3leaps/docprims-win32-x64-msvc": "0.1.3"
}
}The native loader (src/native.ts) now:
- First checks for local build (git checkout / local path installs)
- Falls back to platform package (npm optional dependency)
Installation
From npm (after publish)
npm install @3leaps/docprimsPlatform-specific binaries install automatically.
From git checkout
cd bindings/typescript/docprims
npm install
npm run build:nativeUnsupported Platforms
The following platforms are not supported:
- darwin-x64 (Intel Mac) - no demand, easily added if needed
- win32-arm64 - no Go bindings support either
Changelog
See CHANGELOG.md for detailed changes.
v0.1.2
docprims v0.1.2
Release Date: 2026-01-30
Status: Patch Release (Go dynamic libs + TypeScript validation)
Summary
This release fixes Go shared library distribution on macOS and validates TypeScript bindings for both Node.js and Bun runtimes.
Highlights
- Darwin dylib install_name fix: macOS shared library now uses
@rpathfor proper runtime linking - CI musl handling: musl targets correctly skip shared library builds (static-only)
- TypeScript Bun support: Both Node.js and Bun runtimes now work with napi-rs native addon
- TypeScript npm prep: dry-run validated; cross-platform prebuild workflow planned for future release
Go Shared Library Fix (darwin)
Issue
The macOS shared library had a hardcoded CI build path in its install_name:
/Users/runner/work/docprims/docprims/target/.../libdocprims_ffi.dylib
This caused runtime linking failures for Go docprims_shared consumers.
Fix
Post-build install_name_tool in CI:
install_name_tool -id "@rpath/libdocprims_ffi.dylib" libdocprims_ffi.dylibConsumer Usage
# Development (DYLD_LIBRARY_PATH)
DYLD_LIBRARY_PATH=./lib-shared/darwin-arm64 go run .
# Production (rpath at link time)
go build -ldflags="-r /path/to/lib-shared/darwin-arm64" .TypeScript Runtime Support
Validated Runtimes
| Runtime | Version | Status |
|---|---|---|
| Node.js | v22.x | Validated |
| Bun | v1.3.x | Validated |
Consumer Validation
Validated from external consumer project using file: protocol linking:
- Markdown, HTML, DOCX extraction all work
- Real-world 147KB DOCX successfully extracted (7,314 chars, 65 blocks)
- Error handling (
DocprimsError) works correctly - TypeScript types match runtime shape
Fix: Bun Runtime Guard Removed
The initial TypeScript bindings included a conservative guard that blocked Bun runtime. Testing confirmed napi-rs native addons work correctly in Bun, so the guard was removed.
TypeScript npm Publishing Learnings
Dry-run Results
npm notice 📦 @3leaps/docprims@0.1.1
npm notice package size: 961.4 kB
npm notice total files: 26
Only local platform binary (docprims.darwin-arm64.node) would be published.
Path Forward
npm publishing requires cross-platform prebuilds via napi-rs:
- Platform-specific optional packages (
@3leaps/docprims-linux-x64-gnu, etc.) - CI workflow to build all platforms
- First publish must be manual from pristine checkout
See .plans/active/v0.1.2/npm-publish.md for detailed implementation plan.
CI Changes
go-bindings-prep.yml: Addedinstall_name_toolpost-build for darwingo-bindings-prep.yml: musl targets skip.sopackaging (static-only)release.yml: musl platforms skip shared lib validation
Changelog
See CHANGELOG.md for detailed changes.
v0.1.1
docprims v0.1.1
Release Date: 2026-01-29
Status: Patch Release (TypeScript bindings preview)
Summary
This release adds a first-cut TypeScript/Node.js binding (Node-API via napi-rs) intended for validation from a git checkout. npm publishing will follow in v0.1.2 once the trusted OIDC publishing workflow lands.
Highlights
- TypeScript bindings:
bindings/typescript/docprimswithextractFile/extractBytes(+*Jsonvariants) - CI coverage: TypeScript tests on linux/macos/windows + Alpine/musl; validate-release can build/test from a tag
- Stable goldens: CLI golden fixtures ignore
generator.versionacross patch bumps - Go bindings (shared lib opt-in):
docprims_sharedbuild tag + vendored shared libraries to avoid Ruststaticlibcollisions
TypeScript (from git checkout)
cd bindings/typescript/docprims
npm install
npm run test:ciChangelog
See CHANGELOG.md for detailed changes.
v0.1.0
docprims v0.1.0
Release Date: 2026-01-28
Status: Initial Release
Summary
GPL-free document text extraction primitives for Rust with Go bindings. Extract text from DOCX, XLSX, PPTX, Markdown, HTML, and XML with provenance tracking and schema-validated output.
Highlights
- Schema-Validated Output: All extractors emit
DocprimsExtractJSON conforming to versioned schemas - Provenance Tracking: Every text block includes locators back to source (paragraph index, cell ref, etc.)
- Defensive Parsing: Built for untrusted input with configurable resource limits
- GPL-Free: All dependencies permissively licensed (MIT/Apache-2.0)
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Consumers │
├─────────────┬─────────────┬─────────────┬──────────────────┤
│ Rust API │ Go Binding │ CLI User │ Future: TS/Py │
└──────┬──────┴──────┬──────┴──────┬──────┴──────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ docprims crates │
├─────────────┬─────────────┬─────────────┬──────────────────┤
│ docprims- │ docprims- │ docprims- │ docprims-cli │
│ core │ text │ ooxml │ │
└─────────────┴─────────────┴─────────────┴──────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DocprimsExtract │
│ { schema_version, source, document: { text, blocks } } │
└─────────────────────────────────────────────────────────────┘
Supported Formats
| Format | Crate | Block Kinds | Locator Type |
|---|---|---|---|
| Markdown | docprims-text |
markdown:heading, markdown:paragraph, markdown:code, markdown:list_item |
markdown:locator |
| HTML | docprims-text |
html:block |
html:locator |
| XML | docprims-text |
xml:text |
xml:locator |
| DOCX | docprims-ooxml |
docx:paragraph, docx:table_cell |
docx:locator |
| XLSX | docprims-ooxml |
xlsx:cell |
xlsx:locator |
| PPTX | docprims-ooxml |
pptx:shape_text |
pptx:locator |
Installation
Rust
[dependencies]
docprims-core = "0.1.0"
docprims-text = "0.1.0"
docprims-ooxml = "0.1.0"CLI
cargo install --path crates/docprims-cliGo
go get github.com/3leaps/docprims/bindings/go/docprims@v0.1.0Usage
CLI
# Plain text extraction
docprims extract document.docx
# JSON with structured blocks
docprims extract document.md --format json --include-blocks
# Multi-file NDJSON
docprims extract *.docx --format json
# With logging
docprims --log-level debug extract document.xlsxRust API
use docprims_text::extract_markdown_v0;
use docprims_core::ExtractLimits;
let limits = ExtractLimits::default();
let extract = extract_markdown_v0("README.md", limits)?;
println!("Text: {}", extract.document.text);
for block in &extract.document.blocks {
println!("Block {}: {}", block.id, block.text);
}Go API
package main
import (
"fmt"
"log"
"github.com/3leaps/docprims/bindings/go/docprims"
)
func main() {
limits := docprims.ExtractLimits{
MaxInputBytes: 100 * 1024 * 1024, // 100MB
}
result, err := docprims.ExtractMarkdownV0("README.md", limits)
if err != nil {
log.Fatal(err)
}
fmt.Println("Text:", result.Document.Text)
for _, block := range result.Document.Blocks {
fmt.Printf("Block %s: %s\n", block.ID, block.Text)
}
}Output Schema
DocprimsExtract
{
"schema_id": "https://schemas.3leaps.dev/docprims/extract/v0/docprims-extract.schema.json",
"schema_version": "1.0.0",
"generator": {
"name": "docprims",
"version": "0.1.0"
},
"source": {
"uri": "./document.md",
"format": {
"family": "text",
"kind": "markdown"
},
"sha256": "abc123..."
},
"document": {
"quality": {
"status": "complete"
},
"text": "Full extracted text joined from blocks...",
"blocks": [
{
"id": "markdown:heading:0",
"kind": "markdown:heading",
"text": "Document Title",
"doc_text_range": {
"start_byte": 0,
"end_byte": 14
},
"attrs": {
"level": 1
},
"loc": {
"kind": "markdown:locator",
"container": {
"kind": "file",
"path": "./document.md"
},
"hints": {
"block_index": 0
}
}
}
]
}
}Security
docprims is designed for untrusted input:
| Threat | Mitigation |
|---|---|
| Zip bombs | Decompression ratio limits |
| XML bombs (billion laughs) | Entity expansion disabled |
| Path traversal | Archive path validation |
| Memory exhaustion | Configurable max_input_bytes, max_output_bytes |
| Excessive blocks | Configurable max_blocks |
Resource Limits
pub struct ExtractLimits {
pub max_input_bytes: usize, // Default: 100MB
pub max_output_bytes: usize, // Default: 50MB
pub max_blocks: usize, // Default: 100000
}Platform Support
Go Bindings
| Platform | Architecture | Library | Build |
|---|---|---|---|
| macOS | arm64 | Prebuilt | Vendored |
| Linux | amd64 | Prebuilt | glibc 2.17+ |
| Linux | arm64 | Prebuilt | glibc 2.17+ |
| Linux | amd64-musl | Prebuilt | Alpine |
| Linux | arm64-musl | Prebuilt | Alpine |
| Windows | amd64 | Prebuilt | MinGW/GNU |
Rust
- MSRV: Rust 1.85.0
- Tested on: Linux, macOS, Windows
Dependencies
All dependencies are permissively licensed (MIT or Apache-2.0):
| Crate | Version | License | Purpose |
|---|---|---|---|
quick-xml |
0.39 | MIT | XML parsing |
zip |
2.x | MIT | ZIP archive handling |
pulldown-cmark |
0.13 | MIT | Markdown parsing |
scraper |
0.25 | MIT | HTML parsing |
encoding_rs |
0.8 | MIT/Apache-2.0 | Character encoding |
Known Limitations
- PDF extraction not supported (planned for v0.2)
- OOXML table structure (row/column indices) not yet in blocks
- Span annotations (bold/italic/links) planned for future release
- RTF format not supported
Related Documentation
- Architecture Overview
- ADR-0001: License Policy
- ADR-0002: Crate Structure
- ADR-0003: Input Validation Policy
Changelog
See CHANGELOG.md for detailed changes.