### Run Concurrent Gemini API Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/examples/gemini-async-verify/README.md To run the experiment, you need to provide your Gemini API key and execute the provided cargo command. This command builds and runs the `gemini-async-verify` example. ```bash GEMINI_API_KEY= cargo run --example gemini-async-verify ``` -------------------------------- ### Install AnytoMD CLI Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Install the AnytoMD command-line interface tool using Cargo. ```sh cargo install anytomd ``` -------------------------------- ### Install AnytoMD with npm (WASM) Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Install the anytomd WebAssembly package using npm. ```sh npm install anytomd ``` -------------------------------- ### CSV Conversion Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Demonstrates the conversion of a simple CSV file with multilingual data into a Markdown table. ```csv Name,Age,City Alice,30,Seoul Bob,25,東京 Charlie,35,New York 다영,28,서울 ``` ```markdown | Name | Age | City | |---|---|---| | Alice | 30 | Seoul | | Bob | 25 | 東京 | | Charlie | 35 | New York | | 다영 | 28 | 서울 | ``` -------------------------------- ### Rust Library Quick Start Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Basic usage of the AnytoMD Rust library for converting files and raw bytes. Demonstrates using `convert_file` with auto-detection and `convert_bytes` with an explicit format. ```rust use anytomd::{convert_file, convert_bytes, ConversionOptions}; // Convert a file (format auto-detected from extension and magic bytes) let options = ConversionOptions::default(); let result = convert_file("document.docx", &options).unwrap(); println!("{}", result.markdown); // Convert raw bytes with an explicit format let csv_data = b"Name,Age\nAlice,30\nBob,25"; let result = convert_bytes(csv_data, "csv", &options).unwrap(); println!("{}", result.markdown); ``` -------------------------------- ### PPTX Conversion Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Shows the Markdown representation of a PowerPoint presentation, including slides, tables, speaker notes, and multilingual content. ```markdown ## Slide 1: Sample Presentation Welcome to the presentation. --- ## Slide 2 Data Overview | Name | Value | Status | |---|---|---| | Alpha | 100 | Active | | Beta | 200 | Inactive | | Gamma | 300 | Active | > Note: Remember to explain the data table. --- ## Slide 3: Multilingual 한국어 테스트 🚀✨🌍 > Note: Test multilingual rendering. ``` -------------------------------- ### AnytoMD CLI Usage Examples Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Demonstrates various ways to use the AnytoMD CLI for document conversion, including single/multiple file conversion, output redirection, stdin usage, format overriding, strict mode, and plain text output. ```sh # Convert a single file anytomd document.docx > output.md # Convert multiple files (separated by comments) anytomd report.docx data.csv slides.pptx > combined.md # Write output to a file anytomd document.docx -o output.md # Read from stdin (--format is required) cat data.csv | anytomd --format csv # Override format detection anytomd --format html page.dat # Strict mode: treat recoverable errors as hard errors anytomd --strict document.docx # Plain text output (Markdown formatting stripped) anytomd --plain-text document.docx # Plain text from stdin echo "Name,Age" | anytomd --format csv --plain-text # Extract comments (DOCX/PPTX) into an appended Comments section anytomd --extract-comments document.docx # Image descriptions via Gemini (requires GEMINI_API_KEY env var) export GEMINI_API_KEY=your-key anytomd --gemini presentation.pptx # Use a specific Gemini model anytomd --gemini --gemini-model gemini-2.5-flash-lite presentation.pptx # Resource limits (defaults: 8GiB input, 4GiB images, 16GiB zip) anytomd --max-input-size 500MB document.docx anytomd --max-zip-size 2GiB archive.xlsx ``` -------------------------------- ### Install AnytoMD with Cargo Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Add the anytomd library to your Rust project using Cargo. ```sh cargo add anytomd ``` -------------------------------- ### DOCX Conversion Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Illustrates the Markdown output from a Word document containing headings, links, Korean text, and emoji. ```markdown # Sample Document This is a simple paragraph. ## Section One Visit [Example](https://example.com) for more info. Korean: 한국어 테스트 Emoji: 🚀✨🌍 ### Subsection Final paragraph with mixed content. ``` -------------------------------- ### Markdown Image Reference Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Shows how binary image data extracted from documents is referenced in Markdown using standard image syntax. ```markdown ![image_1](image_1.png) ``` -------------------------------- ### Convert DOCX to Markdown Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Automatically detects the DOCX format and converts the file to Markdown. Requires basic setup. ```rust let result = anytomd::convert_file("document.docx", &ConversionOptions::default())?; println!("{}", result.markdown); ``` -------------------------------- ### Plain Text Output Convention Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Demonstrates the expected plain text output for various document elements, such as code blocks and tables, when markdown formatting is stripped. ```markdown | Converter | Plain text behavior | |-----------|-------------------| | Plain Text | Identical to markdown (decoded text passthrough) | | Code | Raw source code without fenced code block markers | | JSON | Pretty-printed JSON without code fences | | XML | Pretty-printed XML without code fences | | CSV | Tab-separated values (no pipes or separator rows) | | HTML | Text content only (no heading markers, bold/italic, link syntax) | | DOCX | Text content only (no heading markers, bold/italic, link syntax) | | PPTX | Slide content without `## Slide N:` prefixes, tab-separated tables | | XLSX | Sheet names without `##`, tab-separated tables | | Jupyter | Markdown cells as-is, code/raw cells without fenced code blocks | | Images | Alt text / LLM description only (no `![](...)` syntax) ``` -------------------------------- ### Python Data Processing Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/tests/fixtures/sample.ipynb Processes a list of numbers to calculate their sum using Python. ```python data = [1, 2, 3, 4, 5] total = sum(data) print(f"Total: {total}") ``` -------------------------------- ### Markdown Table Format Example Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Illustrates the pipe-delimited format used for tables in Markdown output, including header separators and cell content trimming. ```markdown | Column A | Column B | Column C | |----------|----------|----------| | value 1 | value 2 | value 3 | ``` -------------------------------- ### WASM Tests Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Execute WASM integration tests using wasm-pack. Ensure you have wasm-pack installed. ```bash wasm-pack test --node --no-default-features --features wasm ``` -------------------------------- ### Convert DOCX to Markdown in WASM Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Example of converting a DOCX file to Markdown using the anytomd WASM bindings in JavaScript. Requires initializing the library and fetching the file content as bytes. ```js import init, { convertBytes } from 'anytomd'; await init(); const response = await fetch('document.docx'); const bytes = new Uint8Array(await response.arrayBuffer()); const result = convertBytes(bytes, 'docx'); console.log(result.markdown); ``` -------------------------------- ### Get Plain Text Output Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Retrieves the plain text content from the conversion result, excluding any Markdown syntax. Useful for simple text extraction. ```rust println!("{}", result.plain_text); ``` -------------------------------- ### Synchronous Image Description Trait Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Defines the interface for describing image content synchronously. Implement this trait to provide custom image analysis, for example, using an LLM. ```rust use std::sync::Arc; pub trait ImageDescriber: Send + Sync { fn describe( &self, image_bytes: &[u8], mime_type: &str, prompt: &str, ) -> Result; } pub enum WarningCode { SkippedElement, UnsupportedFeature, ResourceLimitReached, MalformedSegment, } pub struct ConversionWarning { pub code: WarningCode, pub message: String, pub location: Option, } pub struct ConversionOptions { /// Extract embedded images into `ConversionResult.images` pub extract_images: bool, /// Extract comments (DOCX/PPTX) into an appended `# Comments` section pub extract_comments: bool, /// Hard cap for total extracted image bytes per document pub max_total_image_bytes: usize, /// If true, return an error on recoverable parse failures pub strict: bool, /// Maximum input file size in bytes. Files larger than this are rejected. pub max_input_bytes: usize, /// Maximum total uncompressed size of entries in a ZIP-based document. pub max_uncompressed_zip_bytes: usize, /// Optional image describer for LLM-based alt text generation. pub image_describer: Option>, } pub struct ConversionResult { /// Converted Markdown content pub markdown: String, /// Plain text extracted directly from the source document (no markdown syntax). /// Each converter populates this alongside `markdown` during conversion. pub plain_text: String, /// Document title (if detected) pub title: Option, /// Extracted images as (filename, bytes) pairs pub images: Vec<(String, Vec) >, /// Recoverable issues encountered during conversion pub warnings: Vec, } pub trait Converter { /// Returns supported file extensions (e.g., ["docx"]) fn supported_extensions(&self) -> &[&str]; /// Check if this converter can handle the given bytes/extension fn can_convert(&self, extension: &str, _header_bytes: &[u8]) -> bool { self.supported_extensions().contains(&extension) } /// Convert file bytes to Markdown with conversion options fn convert( &self, data: &[u8], options: &ConversionOptions, ) -> Result; } ``` -------------------------------- ### JavaScript WASM Usage Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Import and use the `convertBytes` function from the WASM module in JavaScript. This example fetches a document, converts its bytes, and logs the markdown, plain text, title, and warnings. ```js import init, { convertBytes } from './pkg/anytomd.js'; await init(); const response = await fetch('document.docx'); const bytes = new Uint8Array(await response.arrayBuffer()); const result = convertBytes(bytes, 'docx'); console.log(result.markdown); console.log(result.plainText); console.log(result.title); // string or null console.log(result.warnings); // string[] ``` -------------------------------- ### Rust Library Extracting Embedded Images Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Example of configuring AnytoMD in Rust to extract embedded images during conversion. The extracted images are stored in a map of filenames to byte arrays. ```rust use anytomd::{convert_file, ConversionOptions}; let options = ConversionOptions { extract_images: true, ..Default::default() }; let result = convert_file("presentation.pptx", &options).unwrap(); for (filename, bytes) in &result.images { std::fs::write(filename, bytes).unwrap(); } ``` -------------------------------- ### Concurrent Gemini API Request Timing Source: https://github.com/developer0hye/anytomd-rs/blob/main/examples/gemini-async-verify/README.md This output shows the start and end times for individual concurrent requests to the Gemini API. It confirms that requests are initiated almost simultaneously and that the total wall time is determined by the longest-running request, not the sum of all request durations. ```text [0] start=45.29us end=1.20s (1.20s) [1] start=85.25us end=1.28s (1.28s) [2] start=125.08us end=1.47s (1.47s) [3] start=756.13us end=1.93s (1.93s) [4] start=155.88us end=1.14s (1.14s) [5] start=215.71us end=1.14s (1.14s) [6] start=231.58us end=1.42s (1.42s) [7] start=252.38us end=1.14s (1.14s) [8] start=268.04us end=1.24s (1.24s) [9] start=766.04us end=1.42s (1.42s) ``` -------------------------------- ### Run All Development Checks Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Execute build, test, and linting commands. Ensure all steps pass before proceeding with development. ```bash cargo build && cargo test && cargo clippy -- -D warnings ``` -------------------------------- ### Initialize AsyncGeminiDescriber (Async) Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Construct an asynchronous Gemini image describer using an API key or from environment variables. Optionally specify a custom model. Requires the `async-gemini` feature. ```rust // Async (requires `async-gemini` feature) impl AsyncGeminiDescriber { pub fn new(api_key: String) -> Self { ... } pub fn from_env() -> Result { ... } pub fn with_model(self, model: String) -> Self { ... } } ``` -------------------------------- ### Initialize GeminiDescriber (Sync) Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Construct a synchronous Gemini image describer using an API key or from environment variables. Optionally specify a custom model. ```rust // Sync (always available) impl GeminiDescriber { pub fn new(api_key: String) -> Self { ... } pub fn from_env() -> Result { ... } pub fn with_model(self, model: String) -> Self { ... } } ``` -------------------------------- ### Print Hello World in Rust Source: https://github.com/developer0hye/anytomd-rs/blob/main/tests/fixtures/expected/sample.html.md A basic Rust main function that prints a greeting to the console. ```rust fn main() { println!("Hello, world!"); } ``` -------------------------------- ### Convert with LLM Image Description (Sync) Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Performs file conversion while using an LLM for image descriptions. Requires the `gemini` feature and environment variables for authentication. ```rust use anytomd::gemini::GeminiDescriber; let describer = GeminiDescriber::from_env()?; let options = ConversionOptions { image_describer: Some(Arc::new(describer)), ..Default::default() }; let result = anytomd::convert_file("slides.pptx", &options)?; ``` -------------------------------- ### Define ImageDescriber Trait Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Implement this trait to provide a custom image description logic. The library calls this trait to get descriptions for images. ```rust pub trait ImageDescriber: Send + Sync { fn describe( &self, image_bytes: &[u8], mime_type: &str, prompt: &str, ) -> Result; } ``` -------------------------------- ### ConversionOptions with Image Describer Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Configure document conversion options to include an optional LLM-based image describer. ```rust pub struct ConversionOptions { // ... existing fields ... /// Optional LLM-based image describer. pub image_describer: Option>, } ``` -------------------------------- ### Convert with Async LLM Image Description Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Handles file conversion asynchronously with LLM-based image descriptions. Requires `async` and `async-gemini` features enabled. ```rust #[cfg(feature = "async-gemini")] { use anytomd::gemini::AsyncGeminiDescriber; use anytomd::{AsyncConversionOptions, convert_file_async}; let describer = AsyncGeminiDescriber::from_env()?; let options = AsyncConversionOptions { async_image_describer: Some(Arc::new(describer)), ..Default::default() }; let result = convert_file_async("slides.pptx", &options).await?; } ``` -------------------------------- ### Create GitHub Release and Publish Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Create a GitHub release which triggers automated publishing to crates.io and npm. This command should be run from the main branch at the merge commit of the release PR. ```bash gh release create vX.Y.Z --title "vX.Y.Z" --generate-notes --latest ``` -------------------------------- ### Build WASM for Web Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Build the WebAssembly module for web targets. Use `--features wasm` for basic functionality or `--features wasm,async-gemini` to include asynchronous Gemini image descriptions. ```sh # Basic WASM build (sync conversion only) wasm-pack build --target web --no-default-features --features wasm # With Gemini async image descriptions wasm-pack build --target web --no-default-features --features wasm,async-gemini ``` -------------------------------- ### AsyncConversionOptions with Async Image Describer Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Configure asynchronous document conversion options to include an optional async image describer. ```rust pub struct AsyncConversionOptions { pub base: ConversionOptions, pub async_image_describer: Option>, } ``` -------------------------------- ### Docker Compose Commands for Development Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Commands to manage the Docker environment for reproducible builds and testing. Includes options for a full build loop, running tests, checking linting, and accessing an interactive shell. ```sh docker compose run --rm verify # Full loop: fmt + clippy + test + release build ``` ```sh docker compose run --rm test # Run all tests ``` ```sh docker compose run --rm lint # clippy + fmt check ``` ```sh docker compose run --rm shell # Interactive bash ``` -------------------------------- ### Async Image Descriptions with Gemini Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Utilize the async API for concurrent image description resolution, significantly speeding up processing for documents with multiple images. Requires an async runtime like tokio. ```rust use std::sync::Arc; use anytomd::{convert_file_async, AsyncConversionOptions, AsyncImageDescriber, ConvertError}; use anytomd::gemini::AsyncGeminiDescriber; #[tokio::main] async fn main() { let describer = AsyncGeminiDescriber::from_env().unwrap(); let options = AsyncConversionOptions { async_image_describer: Some(Arc::new(describer)), ..Default::default() }; let result = convert_file_async("presentation.pptx", &options).await.unwrap(); println!("{}", result.markdown); // All images described concurrently — significant speedup for multi-image documents } ``` -------------------------------- ### Core Dependencies for AnytoMD-RS Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Lists the essential Rust crates required for the core functionality of AnytoMD-RS, including archive reading, XML parsing, spreadsheet handling, and HTTP requests. ```toml [dependencies] zip = "2" # ZIP archive reading (DOCX, PPTX, XLSX) quick-xml = "0.37" # XML parsing (OOXML, XML converter) calamine = { version = "0.26", features = ["dates"] } # XLSX/XLS reading chrono = { version = "0.4", default-features = false } # Date formatting for spreadsheets csv = "1" # CSV parsing serde_json = "1" # JSON pretty-printing scraper = "0.22" # HTML DOM parsing ego-tree = "0.10" # Tree traversal (used with scraper) encoding_rs = "0.8" # Non-UTF-8 encoding detection and conversion clap = { version = "4", features = ["derive"] } # CLI argument parsing thiserror = "2" # Error types ureq = "3" # HTTP client (sync Gemini API calls) base64 = "0.22" # Base64 encoding for Gemini image payloads ``` -------------------------------- ### Optional Dependencies for AnytoMD-RS Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Details feature-gated dependencies that can be included based on specific project needs, such as asynchronous operations. ```toml futures-util = { version = "0.3", optional = true } # async image resolution (async feature) reqwest = { version = "0.12", optional = true } # async HTTP client (async-gemini feature) ``` -------------------------------- ### ConversionOptions Struct Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Configuration options for the document conversion process. ```APIDOC ## Struct ConversionOptions ### Description Configuration options for the document conversion process. ### Fields - **`extract_images`** (bool) - Required - If true, embedded images will be extracted into `ConversionResult.images`. - **`extract_comments`** (bool) - Required - If true, comments (from DOCX/PPTX) will be extracted into an appended `# Comments` section. - **`max_total_image_bytes`** (usize) - Required - A hard cap for the total extracted image bytes per document. - **`strict`** (bool) - Required - If true, the conversion will return an error on recoverable parse failures. - **`max_input_bytes`** (usize) - Required - The maximum input file size in bytes. Files larger than this limit are rejected. - **`max_uncompressed_zip_bytes`** (usize) - Required - The maximum total uncompressed size of entries in a ZIP-based document. - **`image_describer`** (Option>) - Optional - An optional image describer for LLM-based alt text generation. ``` -------------------------------- ### convert_file_async Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Asynchronously converts a file to Markdown, with support for concurrent image description resolution. ```APIDOC ## `convert_file_async` ### Description Converts a file at the given path to Markdown with async image description. If an `async_image_describer` is set, all image descriptions are resolved concurrently. ### Signature ```rust pub async fn convert_file_async( path: impl AsRef, options: &AsyncConversionOptions, ) -> Result ``` ### Parameters - `path`: A reference to the path of the file to convert. - `options`: A reference to `AsyncConversionOptions` to customize the async conversion process, including image describer settings. ``` -------------------------------- ### AnyToMD Rust Crate Directory Structure Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md This tree shows the organization of the AnyToMD Rust crate's source files, indicating the purpose of each module. ```text src/ ├── lib.rs # Public API: convert_file(), convert_bytes(), async variants ├── main.rs # CLI binary (clap-based) ├── error.rs # ConvertError enum ├── detection.rs # File format detection (magic bytes + extension + ZIP introspection) ├── markdown.rs # Markdown generation utilities (tables, headings, lists) ├── zip_utils.rs # Shared ZIP reading helpers (crate-internal) └── converter/ ├── mod.rs # Converter trait, ImageDescriber, AsyncImageDescriber, options, types ├── docx.rs # DOCX → Markdown ├── pptx.rs # PPTX → Markdown ├── xlsx.rs # XLSX/XLS → Markdown ├── csv.rs # CSV → Markdown ├── json.rs # JSON → Markdown ├── xml.rs # XML → Markdown ├── html.rs # HTML → Markdown ├── plain_text.rs # Plain text passthrough (with encoding detection) ├── image.rs # Image metadata extraction + optional LLM description ├── gemini.rs # GeminiDescriber (sync) + AsyncGeminiDescriber (async-gemini feature) └── ooxml_utils.rs # Shared OOXML helpers (image extraction, async placeholder resolution) ``` -------------------------------- ### Build Release Version Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Compiles the project in release mode. This is a required check in the CI pipeline. ```bash cargo build --release ``` -------------------------------- ### Run Live Gemini API Test Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Executes a live test against the Gemini API. This test is allowed to fail and depends on the GEMINI_API_KEY secret. ```bash cargo test --test test_gemini_live ``` -------------------------------- ### Convert File Synchronously Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md The `convert_file` function automatically detects the file format from magic bytes and extension to convert it to Markdown. ```rust /// Convert a file at the given path to Markdown. /// Format is auto-detected from magic bytes and file extension. pub fn convert_file( path: impl AsRef, options: &ConversionOptions, ) -> Result ``` -------------------------------- ### Run Unit Tests Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Executes all unit tests to ensure code correctness. This is a required check in the CI pipeline. ```bash cargo test ``` -------------------------------- ### convert_bytes_async Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Asynchronously converts raw bytes to Markdown, supporting concurrent image descriptions. ```APIDOC ## `convert_bytes_async` ### Description Converts raw bytes to Markdown with async image description. ### Signature ```rust pub async fn convert_bytes_async( data: &[u8], extension: &str, options: &AsyncConversionOptions, ) -> Result ``` ### Parameters - `data`: A slice of bytes representing the document content. - `extension`: The file extension to explicitly specify the document format. - `options`: A reference to `AsyncConversionOptions` to customize the async conversion process, including image describer settings. ``` -------------------------------- ### AsyncConversionOptions Struct (Async Feature) Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Asynchronous conversion options, extending `ConversionOptions` when the `async` feature is enabled. ```APIDOC ## Struct AsyncConversionOptions (requires `async` feature) ### Description Asynchronous conversion options, extending `ConversionOptions` when the `async` feature is enabled. ### Fields - **`base`** (ConversionOptions) - Required - The base synchronous conversion options. - **`async_image_describer`** (Option>) - Optional - An optional asynchronous image describer for LLM-based alt text generation. ``` -------------------------------- ### Build WASM Package Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Build the WASM package for web distribution using wasm-pack. This command targets the web and excludes default features while including the 'wasm' feature. ```bash wasm-pack build --target web --no-default-features --features wasm ``` -------------------------------- ### Run Docker Compose Service Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Execute a specific service defined in the docker-compose.yml file. This is used for tasks like running tests, linting, or building within a reproducible environment. ```bash docker compose run --rm ``` -------------------------------- ### Convert File Asynchronously Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md The `convert_file_async` function converts a file to Markdown asynchronously, enabling concurrent image description resolution if an `async_image_describer` is provided. ```rust /// Convert a file at the given path to Markdown with async image description. /// If an async_image_describer is set, all image descriptions are resolved concurrently. pub async fn convert_file_async( path: impl AsRef, options: &AsyncConversionOptions, ) -> Result ``` -------------------------------- ### Define a Greeting Function in Python Source: https://github.com/developer0hye/anytomd-rs/blob/main/tests/fixtures/sample.ipynb Defines a simple Python function to greet a user. Supports CJK characters in comments. ```python def greet(name): # CJK comment: 한국어 中文 日本語 return f"Hello, {name}! 🚀" ``` -------------------------------- ### Implement Custom Image Describer Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Implement the `ImageDescriber` trait to integrate any LLM backend for image description generation. ```rust struct MyDescriber; impl ImageDescriber for MyDescriber { fn describe( &self, image_bytes: &[u8], mime_type: &str, prompt: &str, ) -> Result { // Call your preferred LLM API here Ok("description of the image".to_string()) } } ``` -------------------------------- ### Check for Warnings with Clippy Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Uses Clippy to lint the code and enforce a strict policy against warnings. This is a required check in the CI pipeline. ```bash cargo clippy -- -D warnings ``` -------------------------------- ### Rust Library Plain Text Output Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Illustrates how to access both Markdown and plain text output from AnytoMD conversions in Rust. The plain text is the raw extracted content without any formatting. ```rust use anytomd::{convert_file, ConversionOptions}; let result = convert_file("document.docx", &ConversionOptions::default()).unwrap(); // Markdown output println!("{}", result.markdown); // Plain text output (no headings, bold, tables, code fences, etc.) println!("{}", result.plain_text); ``` -------------------------------- ### Check Code Formatting Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Ensures the code adheres to the project's formatting standards. This is a required check in the CI pipeline. ```bash cargo fmt --check ``` -------------------------------- ### Inspect Conversion Warnings Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Logs any recoverable conversion warnings encountered during the process. Warnings are stored in the `warnings` field of the result. ```rust for warning in &result.warnings { eprintln!("[{{:?}}] {{}}", warning.code, warning.message); } ``` -------------------------------- ### Create Pull Request Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Create a new pull request using the GitHub CLI. This command is used within the worktree. ```bash gh pr create ``` -------------------------------- ### Run Async Tests Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Executes tests that utilize the 'async' feature. This is an asynchronous feature check. ```bash cargo test --features async ``` -------------------------------- ### Test DOCX Headings Normalization Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Verifies that headings in DOCX files are correctly converted and normalized to Markdown. Asserts that the generated Markdown matches the expected normalized output. ```rust #[test] fn test_docx_headings_normalized_output() { let result = anytomd::convert_file( "tests/fixtures/simple.docx", &ConversionOptions::default(), ) .unwrap(); let actual = normalize_markdown(&result.markdown); let expected = include_str!("expected/simple.normalized.md"); assert_eq!(actual, expected); } ``` -------------------------------- ### Live Gemini API Test Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md This Rust test verifies the GeminiDescriber by making a live API call. It reads the GEMINI_API_KEY from environment variables and skips execution if the key is not found. The test asserts that a non-empty description is returned for a given image. ```rust #[test] fn test_gemini_live_describe_image() { let api_key = match std::env::var("GEMINI_API_KEY") { Ok(key) => key, Err(_) => { eprintln!("GEMINI_API_KEY not set, skipping live test"); return; } }; let describer = GeminiDescriber::new(api_key).with_model("gemini-2.5-flash-lite".to_string()); let image_bytes = include_bytes!("../tests/fixtures/sample_image.png"); let result = describer.describe(image_bytes, "image/png", "Describe this image."); assert!(result.is_ok()); assert!(!result.unwrap().is_empty()); } ``` -------------------------------- ### Audit Package Contents for Sensitive Files Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Run this command to check for sensitive files like environment variables, secrets, or credentials within the package contents. The grep command must return no output. ```bash cargo package --list | grep -E '\.env|\.omc|\.claude|secret|credential|token|key|password' ``` -------------------------------- ### HTML to Markdown Conversion Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Converts HTML content to Markdown using the `scraper` crate for DOM parsing and a custom converter. It handles common HTML elements like headings, paragraphs, tables, lists, links, images, and code blocks. ```rust // HTML → Markdown using `scraper` for DOM parsing + custom converter // Handle: headings, paragraphs, tables, lists, links, images, code blocks // Similar to Python's markdownify but in Rust ``` -------------------------------- ### Generate LLM Image Descriptions with Gemini Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Use `ImageDescriber` trait with a built-in `GeminiDescriber` for LLM-generated alt text. Reads GEMINI_API_KEY from environment and allows specifying the model. ```rust use std::sync::Arc; use anytomd::{convert_file, ConversionOptions, ImageDescriber, ConvertError}; use anytomd::gemini::GeminiDescriber; // Option 1: Use the built-in Gemini describer let describer = GeminiDescriber::from_env() // reads GEMINI_API_KEY .unwrap() .with_model("gemini-3-flash-preview".to_string()); let options = ConversionOptions { image_describer: Some(Arc::new(describer)), ..Default::default() }; let result = convert_file("document.docx", &options).unwrap(); // Images now have LLM-generated alt text: ![A chart showing quarterly revenue](chart.png) ``` -------------------------------- ### JavaScript WASM Usage with Gemini Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Use `convertBytesWithGemini` for WASM conversions that include Gemini-based image descriptions. Requires the `wasm` and `async-gemini` features to be enabled during the build. ```js import init, { convertBytesWithGemini } from './pkg/anytomd.js'; await init(); const response = await fetch('presentation.pptx'); const bytes = new Uint8Array(await response.arrayBuffer()); // Images are described concurrently via the Gemini API const result = await convertBytesWithGemini(bytes, 'pptx', 'your-gemini-api-key'); console.log(result.markdown); // images have LLM-generated alt text ``` -------------------------------- ### WASM Compilation Checks Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Run these commands to check WASM compilation without default features and with the 'wasm' feature enabled. Clippy checks are also included for the WASM target. ```bash cargo check --lib --target wasm32-unknown-unknown --no-default-features ``` ```bash cargo check --lib --target wasm32-unknown-unknown --no-default-features --features wasm ``` ```bash cargo clippy --lib --target wasm32-unknown-unknown --no-default-features --features wasm -- -D warnings ``` -------------------------------- ### Convert Bytes Asynchronously Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md The `convert_bytes_async` function converts raw byte data to Markdown asynchronously, supporting concurrent image description resolution. ```rust /// Convert raw bytes to Markdown with async image description. pub async fn convert_bytes_async( data: &[u8], extension: &str, options: &AsyncConversionOptions, ) -> Result ``` -------------------------------- ### Plain Text to Markdown Passthrough Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Directly passes through plain text content as-is. It reads the content as a UTF-8 string. Optional encoding detection using the `encoding_rs` crate is supported. ```rust // Direct passthrough — read as UTF-8 string, return as-is // Detect encoding if not UTF-8 (optional: `encoding_rs` crate) ``` -------------------------------- ### Convert DOCX from Bytes Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Converts a DOCX file from a byte slice, explicitly specifying the format. Ensure bytes are correctly read from the file. ```rust let bytes = std::fs::read("document.docx")?; let result = anytomd::convert_bytes(&bytes, "docx", &ConversionOptions::default())?; ``` -------------------------------- ### convert_file Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Converts a file to Markdown. The format is automatically detected from magic bytes and the file extension. Supports custom conversion options. ```APIDOC ## `convert_file` ### Description Converts a file at the given path to Markdown. Format is auto-detected from magic bytes and file extension. ### Signature ```rust pub fn convert_file( path: impl AsRef, options: &ConversionOptions, ) -> Result ``` ### Parameters - `path`: A reference to the path of the file to convert. - `options`: A reference to `ConversionOptions` to customize the conversion process. ``` -------------------------------- ### Convert Bytes Synchronously Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md The `convert_bytes` function converts raw byte data to Markdown, requiring an explicit file extension to determine the format. ```rust /// Convert raw bytes to Markdown with an explicit format extension. pub fn convert_bytes( data: &[u8], extension: &str, options: &ConversionOptions, ) -> Result ``` -------------------------------- ### Run Async Gemini Tests Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Executes tests that utilize the 'async-gemini' feature. This is an asynchronous feature check. ```bash cargo test --features async-gemini ``` -------------------------------- ### Rebuild Docker Images Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Force a rebuild of Docker images without using the cache. This is useful when changes in the Dockerfile or base images require a fresh build. ```bash docker compose build --no-cache ``` -------------------------------- ### Display raw text block Source: https://github.com/developer0hye/anytomd-rs/blob/main/tests/fixtures/expected/sample.ipynb.md A plain text block used for testing raw content conversion. ```text This is raw text that should be in a plain fenced block. ``` -------------------------------- ### Create Git Worktree Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Use this command to create a new worktree for a feature branch. This is a mandatory step for making changes on PR branches. ```git git worktree add ../anytomd-rs- -b / ``` -------------------------------- ### Check Async Gemini Feature with Clippy Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Lints the code with the 'async-gemini' feature enabled, enforcing a strict policy against warnings. This is an asynchronous feature check. ```bash cargo clippy --features async-gemini -- -D warnings ``` -------------------------------- ### Asynchronous Image Description Trait Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Defines the asynchronous interface for describing image content. This trait is available when the `async` feature is enabled and is suitable for non-blocking image analysis. ```rust // Requires the `async` feature #[cfg(feature = "async")] pub trait AsyncImageDescriber: Send + Sync { fn describe<'a>( &'a self, image_bytes: &'a [u8], mime_type: &'a str, prompt: &'a str, ) -> Pin> + Send + 'a>>; } // Requires the `async` feature #[cfg(feature = "async")] pub struct AsyncConversionOptions { pub base: ConversionOptions, pub async_image_describer: Option>, } ``` -------------------------------- ### convert_bytes Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Converts raw bytes to Markdown, requiring an explicit format extension. Useful for in-memory data. ```APIDOC ## `convert_bytes` ### Description Converts raw bytes to Markdown with an explicit format extension. ### Signature ```rust pub fn convert_bytes( data: &[u8], extension: &str, options: &ConversionOptions, ) -> Result ``` ### Parameters - `data`: A slice of bytes representing the document content. - `extension`: The file extension to explicitly specify the document format. - `options`: A reference to `ConversionOptions` to customize the conversion process. ``` -------------------------------- ### Access Extracted Images Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Iterates through the extracted images from the conversion result and writes them to files. Ensure the output directory exists. ```rust for (filename, image_bytes) in &result.images { std::fs::write(format!("output/{}", filename), image_bytes)?; } ``` -------------------------------- ### Stop and Remove Docker Compose Resources Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Stop and remove all containers, networks, and volumes associated with a docker-compose project. Use the '-v' flag to remove named volumes. ```bash docker compose down -v ``` -------------------------------- ### Disable Default Features Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Configure your Cargo.toml to exclude default features for the anytomd crate, allowing for selective feature inclusion. ```toml anytomd = { version = "1", default-features = false } ``` -------------------------------- ### Extract Comments from DOCX/PPTX Source: https://github.com/developer0hye/anytomd-rs/blob/main/README.md Enable comment extraction by setting `extract_comments` to true in `ConversionOptions`. This appends a '# Comments' section to the output, detailing author, comment body, and source. ```rust use anytomd::{convert_file, ConversionOptions}; let options = ConversionOptions { extract_comments: true, ..Default::default() }; let result = convert_file("document.docx", &options).unwrap(); println!("{}", result.markdown); ``` -------------------------------- ### CSV to Markdown Table Conversion Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Converts CSV data into a pipe-delimited Markdown table. It utilizes the `csv` crate for robust parsing, handling quoting and escaping. ```rust // CSV → Markdown table (pipe-delimited) // Uses `csv` crate for robust parsing (handles quoting, escaping) ``` -------------------------------- ### Check Async Feature with Clippy Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md Lints the code with the 'async' feature enabled, enforcing a strict policy against warnings. This is an asynchronous feature check. ```bash cargo clippy --features async -- -D warnings ``` -------------------------------- ### Test Resource Limit Warning Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Validates that a warning is generated when the total image bytes exceed the configured maximum limit. Sets a specific `max_total_image_bytes` option and checks for the `ResourceLimitReached` warning code. ```rust #[test] fn test_resource_limit_adds_warning() { let options = ConversionOptions { max_total_image_bytes: 1024, ..Default::default() }; let result = anytomd::convert_file("tests/fixtures/images.docx", &options).unwrap(); assert!(result.warnings.iter().any(|w| matches!(w.code, WarningCode::ResourceLimitReached))); } ``` -------------------------------- ### XLSX to Markdown Table Conversion Source: https://github.com/developer0hye/anytomd-rs/blob/main/TECH_SPEC.md Converts an XLSX file to a Markdown table. It iterates through sheets, extracts ranges, and formats rows as a pipe-delimited Markdown table. Assumes the first row is a header. ```rust use calamine::{Reader, open_workbook, Xlsx}; fn convert_xlsx(data: &[u8]) -> Result { let cursor = std::io::Cursor::new(data); let mut workbook: Xlsx<_> = Xlsx::new(cursor)?; let mut markdown = String::new(); for sheet_name in workbook.sheet_names().to_owned() { markdown.push_str(&format!("## {}\\n\\n", sheet_name)); if let Ok(range) = workbook.worksheet_range(&sheet_name) { // First row as header // Remaining rows as table body // → Pipe-delimited Markdown table } } Ok(ConversionResult { markdown, ..Default::default() }) } ``` -------------------------------- ### Update Local Main Branch Source: https://github.com/developer0hye/anytomd-rs/blob/main/CLAUDE.md After merging a PR, update the local 'main' branch to reflect the latest changes. This command should be run from the main repository directory. ```bash cd /Users/yhkwon/Documents/Projects/anytomd-rs && git pull ```