URP (urp v0.9.1)
Copy MarkdownPure Elixir client for document conversion via LibreOffice's UNO Remote Protocol.
Talks directly to a soffice process over TCP.
No Python, no unoserver, no Gotenberg.
Setup
Add :urp to your dependencies — that's it. A default connection pool
starts automatically, connecting to localhost:2002.
# config/runtime.exs (optional — defaults shown)
config :urp, :default,
host: "soffice",
port: 2002,
pool_size: 1See convert/2 for usage examples and options.
Diagnostics
Query soffice state without converting anything:
{:ok, "26.2.0.3"} = URP.version()
{:ok, services} = URP.services()
{:ok, filters} = URP.filters()
{:ok, types} = URP.types()
{:ok, locale} = URP.locale()Named pools
For multiple soffice instances, configure named pools:
config :urp, :pools,
spreadsheets: [host: "soffice-2", port: 2002, pool_size: 3]
{:ok, pdf} = URP.convert({:binary, bytes}, filter: "calc_pdf_Export", pool: :spreadsheets)Named pools are started on first use.
Testing
URP.Test.stub(fn _input, _opts -> {:ok, "/tmp/fake.pdf"} end)
{:ok, _} = URP.convert({:binary, docx_bytes}, filter: "writer_pdf_Export")See URP.Test for details.
Summary
Functions
Convert a document via LibreOffice.
Like convert/2 but raises on error.
List all export filter names registered in soffice.
Like filters/1 but raises on error.
Query the soffice locale string.
Like locale/1 but raises on error.
List all service names registered in the UNO service manager.
Like services/1 but raises on error.
List all document type names registered in soffice.
Like types/1 but raises on error.
Query the soffice version string over URP.
Like version/1 but raises on error.
Types
Functions
@spec convert(binary() | {:binary, binary()} | Enumerable.t(), [opt()]) :: {:ok, Path.t()} | {:ok, binary()} | :ok | {:error, String.t()}
Convert a document via LibreOffice.
Input types
path(binary) — local file path, loaded via file-backed streaming{:binary, bytes}— raw document bytes- enumerable — any
Enumerable(e.g.File.stream!/2), streamed lazily
Options
:filter— export filter name (required). See moduledoc for common filters.:filter_data— keyword list of filter-specific export options. Values can be booleans, integers, or strings. For PDF filters, see PDF export options (e.g.[UseLosslessCompression: true, ExportFormFields: false]).:output— where to write converted output:- path string — write to file, returns
{:ok, path} :binary— return bytes, returns{:ok, bytes}fun/1— call with each chunk, returns:ok- not set — write to temp file, returns
{:ok, tmp_path}
- path string — write to file, returns
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Examples
File path input with various output modes:
{:ok, pdf_path} = URP.convert("/tmp/report.docx", filter: "writer_pdf_Export")
{:ok, "/tmp/out.pdf"} = URP.convert("/tmp/report.docx", filter: "writer_pdf_Export", output: "/tmp/out.pdf")
{:ok, pdf_bytes} = URP.convert("/tmp/report.docx", filter: "writer_pdf_Export", output: :binary)Raw bytes:
{:ok, pdf_bytes} = URP.convert({:binary, docx_bytes}, filter: "writer_pdf_Export", output: :binary)Enumerable (e.g. streaming a large file):
{:ok, pdf_path} = URP.convert(File.stream!("huge.docx", 65_536), filter: "writer_pdf_Export")The :filter option is required:
iex> URP.convert({:binary, "bytes"}, output: :binary)
** (ArgumentError) URP.convert/2 requires the :filter option. Common filters: "writer_pdf_Export", "calc_pdf_Export", "impress_pdf_Export", "Markdown"With a test stub (see URP.Test):
iex> URP.Test.stub(fn _input, _opts -> {:ok, "/tmp/fake.pdf"} end)
:ok
iex> URP.convert("/tmp/test.docx", filter: "writer_pdf_Export")
{:ok, "/tmp/fake.pdf"}
@spec convert!(binary() | {:binary, binary()} | Enumerable.t(), [opt()]) :: Path.t() | binary() | :ok
Like convert/2 but raises on error.
List all export filter names registered in soffice.
Returns a list of filter name strings like "writer_pdf_Export".
Useful for discovering which filters are available on the connected soffice.
Examples
{:ok, filters} = URP.filters()
"writer_pdf_Export" in filters
# => trueOptions
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Like filters/1 but raises on error.
Query the soffice locale string.
Returns the locale string (e.g. "en-US") or "" if not configured.
Examples
{:ok, locale} = URP.locale()
# => "en-US"Options
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Like locale/1 but raises on error.
List all service names registered in the UNO service manager.
Returns a list of service name strings like "com.sun.star.frame.Desktop".
Examples
{:ok, services} = URP.services()
"com.sun.star.frame.Desktop" in services
# => trueOptions
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Like services/1 but raises on error.
List all document type names registered in soffice.
Returns a list of type name strings like "writer8".
These are the internal names soffice uses for file format detection.
Examples
{:ok, types} = URP.types()
"writer8" in types
# => trueOptions
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Like types/1 but raises on error.
Query the soffice version string over URP.
Returns the raw version string (e.g. "26.2.0.3"). Callers can use
Version.parse/1 if needed.
Examples
{:ok, version} = URP.version()
# => "26.2.0.3"Options
:pool— named pool to use (default: the auto-started pool):timeout— checkout timeout in ms (default120_000)
Like version/1 but raises on error.