Packages
Converts Microsoft Word (.docx) documents to HTML with Tailwind CSS styling. Preserves formatting (bold, italic, underline, font sizes, colors, alignments) and list structures. Provides both programmatic API and Mix task CLI. Generates clean, responsive HTML ready for web applications.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/docxir.ex
defmodule Mix.Tasks.Docxir do
@moduledoc """
Converts DOCX files to HTML with Tailwind CSS styling.
## Usage
mix docxir INPUT_FILE OUTPUT_FILE [OPTIONS]
## Arguments
* `INPUT_FILE` - Path to the input DOCX file
* `OUTPUT_FILE` - Path where the HTML file should be written
## Options
* `--title TITLE` - Set the document title (default: "Document")
* `--lang LANG` - Set the HTML language code (default: "zh-TW")
## Examples
# Basic conversion
mix docxir contract.docx contract.html
# With custom title
mix docxir contract.docx output.html --title "Rental Agreement"
# With custom language
mix docxir document.docx output.html --lang en --title "My Document"
"""
use Mix.Task
@shortdoc "Converts DOCX to HTML with Tailwind CSS"
@switches [
title: :string,
lang: :string
]
@spec run([binary()]) :: :ok | no_return()
@impl Mix.Task
def run(args) do
{opts, files, invalid} = OptionParser.parse(args, switches: @switches)
cond do
invalid != [] ->
invalid_opts = Enum.map(invalid, &elem(&1, 0)) |> Enum.join(", ")
Mix.shell().error("Invalid options: #{invalid_opts}")
print_usage()
exit({:shutdown, 1})
length(files) < 2 ->
Mix.shell().error("Error: Missing required arguments")
print_usage()
exit({:shutdown, 1})
length(files) > 2 ->
Mix.shell().error("Error: Too many arguments")
print_usage()
exit({:shutdown, 1})
true ->
[input_file, output_file] = files
perform_conversion(input_file, output_file, opts)
end
end
defp perform_conversion(input_file, output_file, opts) do
# Ensure the application is started
Mix.Task.run("app.start")
Mix.shell().info("Converting #{input_file}...")
case Docxir.convert(input_file, output_file, opts) do
{:ok, path} ->
file_size = File.stat!(path).size
Mix.shell().info("✓ Conversion complete!")
Mix.shell().info(" Output: #{path} (#{format_bytes(file_size)})")
{:error, :enoent} ->
Mix.shell().error("✗ Error: File '#{input_file}' not found")
exit({:shutdown, 1})
{:error, :document_xml_not_found} ->
Mix.shell().error("✗ Error: Invalid DOCX file (document.xml not found)")
exit({:shutdown, 1})
{:error, reason} ->
Mix.shell().error("✗ Conversion failed: #{inspect(reason)}")
exit({:shutdown, 1})
end
end
defp print_usage do
Mix.shell().info("""
Usage: mix docxir INPUT_FILE OUTPUT_FILE [OPTIONS]
Arguments:
INPUT_FILE Path to the input DOCX file
OUTPUT_FILE Path where the HTML file should be written
Options:
--title TITLE Set the document title (default: "Document")
--lang LANG Set the HTML language code (default: "zh-TW")
Examples:
mix docxir contract.docx contract.html
mix docxir contract.docx output.html --title "Rental Agreement"
""")
end
defp format_bytes(bytes) when bytes < 1024, do: "#{bytes} bytes"
defp format_bytes(bytes) when bytes < 1024 * 1024, do: "#{div(bytes, 1024)} KB"
defp format_bytes(bytes),
do: "#{Float.round(bytes / 1024 / 1024, 2)} MB"
end