[package]
name = "inkhaven"
version = "1.2.4"
edition = "2024"
# Rust 1.85 stabilised edition 2024. Bump alongside any toolchain-only
# feature usage (let-else / chained-comparisons / etc. are already stable).
rust-version = "1.85"
license = "Apache-2.0 AND MIT"
description = "Inkhaven — TUI literary work editor for Typst books"
authors = ["Vladimir Ulogov <vulogov@gmail.com>"]
repository = "https://github.com/vulogov/blackInkhaven"
homepage = "https://github.com/vulogov/blackInkhaven"
documentation = "https://github.com/vulogov/blackInkhaven/tree/main/Documentation"
readme = "README.md"
keywords = ["tui", "editor", "typst", "writing", "ai"]
categories = ["command-line-utilities", "text-editors", "text-processing"]

# Distribution model: binary releases via GitHub Actions
# (`.github/workflows/release.yml`) on tag push. Users install with:
#   * `cargo install --git https://github.com/vulogov/blackInkhaven`
#   * `cargo binstall inkhaven` (prebuilts; see [package.metadata.binstall])
#   * Direct download from https://github.com/vulogov/blackInkhaven/releases
#
# `cargo-binstall` metadata: tells `cargo binstall inkhaven` where to
# fetch a prebuilt for the current host triple. The asset filenames
# below must match what `.github/workflows/release.yml` uploads.
[package.metadata.binstall]
pkg-url = "{repo}/releases/download/v{version}/{name}-{target}{archive-suffix}"
bin-dir = "{name}-{target}/{bin}{binary-ext}"
pkg-fmt = "tgz"

# Windows override kept commented so it's a one-line revert when the
# windows-latest matrix entry comes back in release.yml. While disabled,
# `cargo binstall inkhaven` on a Windows host correctly errors with
# "no prebuilt for target" — users on Windows can still
# `cargo install --git`.
# [package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
# pkg-fmt = "zip"

[[bin]]
name = "inkhaven"
path = "src/main.rs"

[dependencies]
# Storage / search. Inkhaven owns its own slim storage layer at
# `src/storage/` — DuckDB-backed metadata + blob stores, an HNSW vector
# index via `vecstore`, and a fastembed wrapper for multilingual
# embeddings. This module replaces what used to be a dependency on
# `bdslib` (vendored at vendor/bdslib/), shedding ~300+ transitive
# crates that inkhaven never reached (Tantivy, augurs, axum, …).
duckdb = { version = "1", features = ["bundled", "r2d2"] }
fastembed = "5"
vecstore = "1"
r2d2 = "0.8"
parking_lot = "0.12"

# CLI
clap = { version = "4", features = ["derive", "wrap_help"] }

# Config (HJSON requirement)
serde-hjson = "1.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

# Async runtime (required by genai)
tokio = { version = "1", features = [
  "macros",
  "rt-multi-thread",
  "fs",
  "io-util",
  "signal",
  "sync",
  "time",
] }
tokio-stream = "0.1"
futures-util = "0.3"

# TUI — pinned to ratatui 0.29 because tui-textarea 0.7 hasn't bumped to 0.30 yet
ratatui = "0.29"
crossterm = "0.28"
tui-textarea = { version = "0.7", default-features = false, features = [
  "crossterm",
  "ratatui",
  "search",
] }

# Syntax highlighting. Pinned to 0.20 because the in-tree Typst grammar
# under `src/grammar/` is generated against tree-sitter 0.20's parser
# ABI, and the `Language` type is ABI-incompatible across major
# versions. Bump alongside any grammar refresh.
tree-sitter = "0.20"
tree-sitter-highlight = "0.20"

# AI clients (one crate covers Gemini, DeepSeek, OpenAI, Anthropic, …)
genai = "=0.6.0-beta.20"

# Bund scripting language (Vladimir's own VM stack). Exact-pinned to
# the versions inkhaven was built against — bump in lockstep when
# refreshing the scripting surface. See `src/scripting/`.
bundcore = "=0.7.0"
bund_language_parser = "=0.14.0"
rust_multistackvm = "=0.38.0"
rust_dynamic = "=0.49.0"
# bundcore / rust_multistackvm use easy_error for their function-pointer
# `Result<_, Error>` signatures; we need a direct dep to construct that
# error type at the FFI boundary in `scripting::stdlib::ink`.
easy-error = "1"

# Misc
anyhow = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
directories = "6"
uuid = { version = "1", features = ["v7", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
arboard = "3"
slug = "0.1"
walkdir = "2"
regex = "1"
# Snowball stemmers (English, Russian, and 17 other languages). Used by the
# editor's Place/Character highlight overlay so a paragraph named
# "Москва" lights up "Москве", "Москвою", etc.
rust-stemmers = "1.2"
unicode-segmentation = "1"
# Markdown parsing for the AI pane's rendered output, plus the
# markdown→Typst translator that runs when the user applies an AI result to
# a paragraph via r/i/t/b.
pulldown-cmark = { version = "0.13", default-features = false }
# Zip backup / restore commands and the TUI auto-backup-on-exit path.
# Also reused by the `inkhaven export epub` pipeline to assemble the
# EPUB3 container — same `deflate` feature flag, no extra dep cost.
zip = { version = "2", default-features = false, features = ["deflate"] }
# Pure-Rust Typst→LaTeX converter for `inkhaven export tex` and the
# Ctrl+B O extra-format pipeline. `default-features = false` drops
# the bundled clap CLI; we only consume the library API
# (`tylax::typst_document_to_latex` / `typst_to_latex`).
tylax = { version = "0.3", default-features = false }
# Line diff for the F6 snapshot-diff view (press `V` on a row in
# the snapshot picker). Pure Rust, Apache-2.0 — uses Myers + LCS
# under the hood. `text` feature is what exposes `TextDiff` (its
# default-features pull in unicode + bytes which we don't need).
similar = { version = "2", default-features = false, features = ["text"] }
# Scrivener import pipeline (1.2.4+).
# `quick-xml` parses the `.scrivx` binder XML (MIT).
# `rtf-parser-tt` is a maintained fork of rtf-parser with
# smart-quote / em-dash support that's essential for prose
# imports (MIT). Both pure Rust — single binary stays single.
quick-xml = "0.36"
rtf-parser-tt = "0.5"
# Human-friendly duration parsing for the auto-backup `max_age` config knob.
humantime = "2"
humantime-serde = "1"
# Typewriter sounds (Enter / focus-out). The output stream is initialised
# lazily and silently skipped when the host has no audio device, so a
# headless build (CI, SSH session without audio forwarding) still works.
# Linux release builds need `libasound2-dev` at build time.
rodio = { version = "0.20", default-features = false }
# Image preview in the editor pane. The Picker is created lazily by
# querying the host terminal's graphics-protocol support; on terminals
# that don't speak kitty / sixel / iterm2 the half-block backend is the
# fallback. Disabled at the application level by `images.preview_enabled`.
ratatui-image = "5"
# In-memory decoder for the image bytes we feed to ratatui-image.
# Limit codecs to the formats we accept on import to keep the binary
# from pulling in TIFF / OpenEXR / etc.
image = { version = "0.25", default-features = false, features = [
  "png",
  "jpeg",
  "gif",
  "webp",
] }

[build-dependencies]
# Compiles the in-tree Typst tree-sitter grammar (`src/grammar/`)
# during `cargo build`. See `build.rs`.
cc = "1"

[dev-dependencies]
tempfile = "3"

[profile.release]
lto = "thin"
codegen-units = 1
strip = "symbols"

# Single-crate workspace. Kept explicit so any future vendored-source
# experiments under `vendor/` don't accidentally become workspace
# members. The grammar itself lives in-tree at `src/grammar/`.
[workspace]
members = ["."]
