defmodule LangelicEpub do @moduledoc """ EPUB read and write for Elixir. ## Reading {:ok, doc} = LangelicEpub.parse(File.read!("book.epub")) doc.title # => "The Hobbit" doc.language # => "en" Enum.count(doc.spine) # => 23 ## Writing doc = %LangelicEpub.Document{ title: "Translated Title", language: "th", creators: ["Original Author"], identifier: "urn:uuid:...", spine: [ %LangelicEpub.Chapter{ id: "ch1", file_name: "ch1.xhtml", title: "บทที่ 1", media_type: "application/xhtml+xml", data: chapter_xhtml } ] } {:ok, bytes} = LangelicEpub.build(doc) File.write!("translated.epub", bytes) """ alias LangelicEpub.{Document, Error} @doc """ Parse EPUB bytes into a `LangelicEpub.Document`. Accepts the raw bytes of an EPUB file. All chapters and assets are loaded into memory; do not call this on documents larger than your available memory. ## Errors Returns `{:error, %LangelicEpub.Error{}}` for: * `:invalid_zip` — bytes are not a valid ZIP archive * `:invalid_mimetype` — `mimetype` entry is missing or its content (after trimming a UTF-8 BOM and surrounding whitespace) is not `application/epub+zip` * `:missing_container` — no `META-INF/container.xml` * `:missing_opf` — OPF file referenced in `container.xml` not found * `:malformed_opf` — OPF could not be parsed * `:io` — internal I/O failure * `:panic` — Rust side panicked (should never happen; report a bug) """ @spec parse(binary()) :: {:ok, Document.t()} | {:error, Error.t()} def parse(epub_bytes) when is_binary(epub_bytes) do LangelicEpub.Native.parse(epub_bytes) end @doc """ Build a `LangelicEpub.Document` into EPUB bytes. The generated EPUB is always EPUB 3 with a backward-compatible `toc.ncx`. ## Errors Returns `{:error, %LangelicEpub.Error{}}` for: * `:missing_required_field` — title, identifier, or language is missing * `:invalid_chapter` — a chapter's `data` is not valid UTF-8 XHTML * `:duplicate_id` — two chapters or assets share the same `id` * `:invalid_page_direction` — `page_progression_direction` is not `"rtl"`, `"ltr"`, or `nil` * `:panic` — Rust side panicked (report a bug) """ @spec build(Document.t()) :: {:ok, binary()} | {:error, Error.t()} def build(%Document{} = doc) do LangelicEpub.Native.build(doc) end end