The Ruby API is the primary interface for working with Uniword. It provides four layers of abstraction for creating, reading, and modifying OOXML documents.
1. Document lifecycle
Every Uniword workflow follows one of two paths:
Create from scratch — Build a new document using Document.new or the
fluent Builder API, then save it.
Load and modify — Open an existing DOCX or MHTML file with
DocumentFactory.from_file, modify the content, and save it back.
# Create
doc = Uniword::Document.new
doc.add_paragraph("Hello World")
doc.save("output.docx")
# Load and modify
doc = Uniword::DocumentFactory.from_file("input.docx")
doc.add_paragraph("Appended paragraph")
doc.save("modified.docx")
2. Builder API
The Builder provides a fluent, declarative interface for constructing documents. Each method returns the builder, allowing method chaining.
doc = Uniword::Builder.new
.add_heading("My Document", level: 1)
.add_paragraph("Introduction paragraph")
.add_table do
row do
cell "Header 1", bold: true
cell "Header 2", bold: true
end
row do
cell "Data 1"
cell "Data 2"
end
end
.build
See Builder API for the full reference.
3. Model classes
Beneath the Builder, Uniword exposes a complete set of OOXML model classes
representing 760 elements across 22 namespaces. Every class inherits from
Lutaml::Model::Serializable and supports automatic XML serialization.
# Direct model manipulation
para = Uniword::Paragraph.new
para.add_text("Bold text", bold: true)
table = Uniword::Table.new
row = Uniword::TableRow.new
cell = Uniword::TableCell.new
cell.add_paragraph("Cell content")
row.add_cell(cell)
table.add_row(row)
4. Resource system
Uniword ships with open-source resources that replace proprietary Microsoft Word assets:
-
Themes — 29 bundled color and font schemes (
.thmxor YAML) -
StyleSets — 12 bundled style definitions (
.dotxor YAML) -
Document elements — 240 templates across 30 locales
# Apply a theme and styleset
doc.apply_theme("celestial")
doc.apply_styleset("distinctive")
5. Feature API
DocumentRoot provides convenience methods for common document operations. All mutator methods return self for chaining.
5.1. Review (comments & tracked changes)
doc.list_comments # => Array<Comment>
doc.add_comment(text: "Fix", author: "Al") # => self
doc.accept_all_changes # => self
doc.reject_all_changes # => self
doc.clear_comments # => self
5.2. Document comparison
# Document-level: content, formatting, structure, metadata, styles
result = doc.diff(other_doc)
result = doc.diff(other_doc, text_only: true)
# => DiffResult with text_changes, format_changes, structure_changes,
# metadata_changes, style_changes
# Package-level: ZIP parts, XML content, OPC validation
require "uniword/diff/package_differ"
result = Uniword::Diff::PackageDiffer.new("old.docx", "new.docx",
canon: true).diff
# => PackageDiffResult with added/removed/modified parts,
# zip_metadata_changes, opc_issues, canon equivalence
5.3. Spell and grammar checking
result = doc.spellcheck # default: en_US
result = doc.spellcheck(language: "en_GB")
# => SpellcheckResult with misspellings, grammar_issues, clean?
5.4. Image management
doc.list_images # => Array<ImageInfo>
doc.extract_images("/tmp/imgs") # => Integer (count)
doc.insert_image("photo.png",
width: "6in", height: "4in") # => self
doc.remove_image("image1.png") # => self
5.5. Watermarks
doc.add_watermark("DRAFT",
color: "#FF0000", font_size: 96) # => self
doc.remove_watermark # => self
doc.watermark? # => true/false
doc.list_watermarks # => Array<String>
5.6. Table of Contents
entries = doc.generate_toc(max_level: 3)
# => Array<TocEntry> with level, text, style_name, paragraph_index
doc.insert_toc(position: 0, max_level: 3) # => self
doc.update_toc(max_level: 6) # => self
5.7. Headers & footers
doc.list_headers # => Array<Hash>
doc.list_footers # => Array<Hash>
doc.add_header("Confidential",
type: "default") # => self
doc.add_footer("Page 1") # => self
doc.remove_headers(type: "first") # => self
doc.remove_footers(type: "even") # => self
6. Document styling API
These methods on DocumentRoot (extracted to Wordprocessingml::DocumentStyling
internally in 1.4.0; signatures unchanged) apply themes, StyleSets, and
scheme-level font and color replacements:
doc.apply_theme("meridian") # full theme (colors + fonts + formats)
doc.apply_theme_file("Atlas.thmx") # from a .thmx file
doc.apply_styleset("signature") # StyleSet (paragraph/char/table styles)
doc.apply_color_scheme("emerald") # Design → Colors gallery
doc.apply_font_scheme("carlito_sans") # Design → Fonts gallery
doc.auto_transition_theme # MS theme → Uniword equivalent
7. Styles API
Inspect and manage the document’s styles. The CLI surfaces these via
uniword styles (see styles command).
doc.styles_configuration.styles.each do |style|
puts "#{style.styleId} (#{style.type})"
end
doc.rename_style("Heading1", "Chapter Title") # returns true / false
doc.remove_style("ObsoleteStyle") # returns the Style or nil (1.4+)
cleanup = Uniword::Wordprocessingml::StyleCleanup.new(doc)
cleanup.unused_ids # => Array<String> of unreferenced style ids
cleanup.remove_unused # removes them; returns the removed ids
8. Find-and-replace API
| Method | Replaces |
|---|---|
|
One font family throughout body, styles, headers/footers, notes, comments, numbering (Word’s Replace Fonts) |
|
Page size, orientation, and margins on every section (Word’s Page Setup dialog) |
doc.replace_font(from: "Calibri", to: "Carlito")
doc.apply_page_setup(
size: "a4",
orientation: "landscape",
margins: "1in",
top: "1.5in"
)
9. Comments API (1.3+)
Comments are anchored to a paragraph and round-trip through word/comments.xml.
doc.add_comment(text: "Fix this", author: "Al") # at end of body
doc.list_comments # => Array<Comment>
doc.clear_comments # remove all
# Anchored comments via Builder
builder.add_paragraph("Claim").comment(
text: "Citation needed", author: "QA", on: :paragraph
)
10. Verification, validation, and repair
Three layers of correctness checking, all scriptable:
# In-memory model rules -- DOC-200/201/202/203/204/205
issues = Uniword::Validation::Engine.run(
Uniword::Validation::Rules::ModelContext.new(doc)
)
issues.each { |i| puts "#{i.code}: #{i.message}" }
# Three-layer pipeline: OPC + XSD + semantic
result = Uniword::Verification.verify("report.docx", xsd: true)
puts result.valid?
puts result.issues.count
The Reconciler runs automatically on every save. To see what was repaired:
# Saves always reconcile; capture issues by hooking save:
begin
doc.save("output.docx")
rescue Uniword::ValidationError => e
e.issues.each { |i| puts "#{i.code}: #{i.message}" }
end
11. Topics
-
Document Lifecycle — Create, open, save, modify documents
-
Builder API — Fluent document construction
-
Configuration — Logging, format detection
-
review — Comments and tracked changes
-
diff — Document comparison
-
spellcheck — Spell and grammar checking
-
images — Image management
-
toc — Table of Contents
-
headers — Headers and footers
-
watermark — Watermarks
-
protect — Document protection
-
generate — DOCX generation
-
styles — Styles pane operations
-
fonts — Replace Fonts
-
page — Page Setup dialog
-
Word for the command line — the master Word UI → CLI / API mapping