Class: Uniword::Builder::DocumentBuilder
- Inherits:
-
BaseBuilder
- Object
- BaseBuilder
- Uniword::Builder::DocumentBuilder
- Defined in:
- lib/uniword/builder/document_builder.rb
Overview
Builds and configures DocumentRoot objects.
Top-level builder for creating Word documents.
Instance Attribute Summary collapse
-
#allocator ⇒ Object
readonly
Returns the value of attribute allocator.
Attributes inherited from BaseBuilder
Class Method Summary collapse
- .default_model_class ⇒ Object
-
.from_file(path) ⇒ DocumentBuilder
Load a document from file for manipulation.
-
.from_template(path) ⇒ DocumentBuilder
Load a DOCX as a template, reset its body to a clean state, and seed the IdAllocator from the template's existing relationships.
Instance Method Summary collapse
-
#<<(element) ⇒ self
Append a top-level element (paragraph or table).
-
#apply_styleset(name, strategy: :keep_existing) ⇒ self
Apply a bundled styleset to the document.
- #author(value) ⇒ Object
-
#bibliography(style: "APA") {|BibliographyBuilder| ... } ⇒ BibliographyBuilder
Create and configure bibliography sources.
-
#bibliography_placeholder ⇒ self
Insert a bibliography placeholder (SDT content control).
-
#bookmark(name) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create a bookmark wrapping the next content.
-
#bullet_list {|ListBuilder| ... } ⇒ ListBuilder
Shorthand: create a bullet list.
-
#chart(type: :bar, width: nil, height: nil) {|ChartBuilder| ... } ⇒ ChartBuilder
Insert a chart into the document.
-
#comment(author:, text: nil, initials: nil) {|CommentBuilder| ... } ⇒ Comment
Create a comment and store it in the document's comments collection.
-
#content_control(tag: nil, alias_name: nil, placeholder_text: nil) ⇒ SdtBuilder
Create a text content control paragraph.
- #created(value) ⇒ Object
-
#date_field(format: "M/d/yyyy") ⇒ self
Insert a date paragraph.
-
#define_style(name, base_on: "Normal") {|StyleBuilder| ... } ⇒ StyleBuilder
Define a paragraph style.
- #description(value) ⇒ Object
-
#endnote(text = nil) {|ParagraphBuilder| ... } ⇒ Wordprocessingml::Run
Create an endnote and return a Run with an endnoteReference.
-
#floating_image(path, width: nil, height: nil, alt_text: nil, align: nil, vertical_align: nil, wrap: :square, behind_text: false) ⇒ self
Insert a floating image paragraph.
-
#footer(type: "default") {|HeaderFooterBuilder| ... } ⇒ HeaderFooterBuilder
Configure a footer.
-
#footnote(text = nil) {|ParagraphBuilder| ... } ⇒ Wordprocessingml::Run
Create a footnote and return a Run with a footnoteReference.
-
#header(type: "default") {|HeaderFooterBuilder| ... } ⇒ HeaderFooterBuilder
Configure a header.
-
#heading(text, level: 1) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create and add a heading paragraph.
-
#horizontal_rule(style: "single", color: "auto", size: 6) ⇒ self
Insert a horizontal rule (paragraph with bottom border).
-
#image(path, width: nil, height: nil, alt_text: nil) ⇒ self
Insert an inline image paragraph.
-
#initialize(model = nil, allocator: nil) ⇒ DocumentBuilder
constructor
A new instance of DocumentBuilder.
- #keywords(value) ⇒ Object
-
#list(type: :bullet) {|ListBuilder| ... } ⇒ ListBuilder
Create a list (bulleted or numbered).
- #modified(value) ⇒ Object
-
#numbered_list {|ListBuilder| ... } ⇒ ListBuilder
Shorthand: create a numbered list.
-
#page_break ⇒ self
Insert a page break.
-
#page_number ⇒ self
Insert a page number paragraph.
-
#paragraph(text = nil) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create and add a paragraph to the document.
-
#save(path) ⇒ Object
Save document to file.
-
#section(type: "nextPage") {|SectionBuilder| ... } ⇒ SectionBuilder
Configure section properties.
- #subject(value) ⇒ Object
-
#table {|TableBuilder| ... } ⇒ TableBuilder
Create and add a table to the document.
-
#theme(name = nil) {|ThemeBuilder| ... } ⇒ ThemeBuilder
Apply or configure a document theme.
-
#time_field(format: "h:mm:ss am/pm") ⇒ self
Insert a time paragraph.
- #title(value) ⇒ Object
-
#toc(title: "Table of Contents", styles: nil) ⇒ self
Insert a Table of Contents.
-
#total_pages ⇒ self
Insert a total pages paragraph.
-
#watermark(text, font: "Calibri", size: 60, color: nil, opacity: "0.3", angle: -45)) ⇒ self
Add a watermark to the document header.
Methods inherited from BaseBuilder
Constructor Details
#initialize(model = nil, allocator: nil) ⇒ DocumentBuilder
Returns a new instance of DocumentBuilder.
38 39 40 41 42 43 |
# File 'lib/uniword/builder/document_builder.rb', line 38 def initialize(model = nil, allocator: nil) super(model) @allocator = allocator @model.allocator = allocator if allocator @footnote_builder = FootnoteBuilder.new(self, allocator: @allocator) end |
Instance Attribute Details
#allocator ⇒ Object (readonly)
Returns the value of attribute allocator.
32 33 34 |
# File 'lib/uniword/builder/document_builder.rb', line 32 def allocator @allocator end |
Class Method Details
.default_model_class ⇒ Object
34 35 36 |
# File 'lib/uniword/builder/document_builder.rb', line 34 def self.default_model_class Wordprocessingml::DocumentRoot end |
.from_file(path) ⇒ DocumentBuilder
Load a document from file for manipulation
49 50 51 |
# File 'lib/uniword/builder/document_builder.rb', line 49 def self.from_file(path) new(Uniword.load(path)) end |
.from_template(path) ⇒ DocumentBuilder
Load a DOCX as a template, reset its body to a clean state, and seed the IdAllocator from the template's existing relationships.
Use this when you want the template's OOXML scaffolding (settings, fonts, styles, theme, content_types, namespace declarations) but will replace the document body with new content. This is the recommended path to producing Word-valid output: starting from a known-good DOCX preserves mc:Ignorable prefixes, rsid values, and other structural guarantees that Word expects.
Resets performed:
- Body content cleared (paragraphs, tables, SDTs, bookmarks, element_order, section_properties)
- User footnotes/endnotes cleared (separator/continuation kept)
- custom_properties and custom_xml_items cleared
- Stale image and customXml relationships removed
- IdAllocator seeded from document_rels and package_rels
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/uniword/builder/document_builder.rb', line 74 def self.from_template(path) raise ArgumentError, "Template not found: #{path}" unless File.exist?(path) root = Uniword.load(path) reset_template_body(root) clear_user_notes(root) root.custom_properties = nil root.custom_xml_items = nil remove_stale_relationships(root) seed_allocator(root) new(root, allocator: root.allocator) end |
Instance Method Details
#<<(element) ⇒ self
Append a top-level element (paragraph or table)
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/uniword/builder/document_builder.rb', line 141 def <<(element) case element when Wordprocessingml::Paragraph @model.body.paragraphs << element @model.body.append_to_element_order("p") when Wordprocessingml::Table @model.body.tables << element @model.body.append_to_element_order("tbl") when ParagraphBuilder @model.body.paragraphs << element.build @model.body.append_to_element_order("p") when TableBuilder @model.body.tables << element.build @model.body.append_to_element_order("tbl") else raise ArgumentError, "Cannot add #{element.class} to document" end self end |
#apply_styleset(name, strategy: :keep_existing) ⇒ self
Apply a bundled styleset to the document
388 389 390 391 |
# File 'lib/uniword/builder/document_builder.rb', line 388 def apply_styleset(name, strategy: :keep_existing) @model.apply_styleset(name, strategy: strategy) self end |
#author(value) ⇒ Object
353 354 355 356 |
# File 'lib/uniword/builder/document_builder.rb', line 353 def (value) @model.core_properties.creator = value self end |
#bibliography(style: "APA") {|BibliographyBuilder| ... } ⇒ BibliographyBuilder
Create and configure bibliography sources
521 522 523 524 525 526 |
# File 'lib/uniword/builder/document_builder.rb', line 521 def bibliography(style: "APA", &block) bib = BibliographyBuilder.new(style: style) block.call(bib) if block_given? bib.attach(self) bib end |
#bibliography_placeholder ⇒ self
Insert a bibliography placeholder (SDT content control)
531 532 533 534 535 536 537 |
# File 'lib/uniword/builder/document_builder.rb', line 531 def bibliography_placeholder sdt = SdtBuilder.bibliography.build para = Wordprocessingml::Paragraph.new para.sdts << sdt self << para self end |
#bookmark(name) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create a bookmark wrapping the next content
290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/uniword/builder/document_builder.rb', line 290 def bookmark(name, &block) id = @allocator ? @allocator.alloc_bookmark_id : begin @bookmark_counter ||= 0 @bookmark_counter += 1 @bookmark_counter.to_s end para = ParagraphBuilder.new(allocator: @allocator) para << Wordprocessingml::BookmarkStart.new(id: id, name: name) block.call(para) if block_given? para << Wordprocessingml::BookmarkEnd.new(id: id) self << para para end |
#bullet_list {|ListBuilder| ... } ⇒ ListBuilder
Shorthand: create a bullet list
281 282 283 |
# File 'lib/uniword/builder/document_builder.rb', line 281 def bullet_list(&) list(type: :bullet, &) end |
#chart(type: :bar, width: nil, height: nil) {|ChartBuilder| ... } ⇒ ChartBuilder
Insert a chart into the document
546 547 548 549 550 551 552 553 554 555 556 557 558 |
# File 'lib/uniword/builder/document_builder.rb', line 546 def chart(type: :bar, width: nil, height: nil, &block) cb = ChartBuilder.new(chart_type: type) cb.dimensions(width: width, height: height) if width || height block.call(cb) if block_given? drawing = cb.build_drawing(self) run = Wordprocessingml::Run.new run.drawings << drawing para = Wordprocessingml::Paragraph.new para.runs << run self << para cb end |
#comment(author:, text: nil, initials: nil) {|CommentBuilder| ... } ⇒ Comment
Create a comment and store it in the document's comments collection.
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'lib/uniword/builder/document_builder.rb', line 482 def comment(author:, text: nil, initials: nil, &block) comment_id = @allocator ? @allocator.alloc_comment_id : begin @comment_counter ||= 0 @comment_counter += 1 @comment_counter.to_s end cb = CommentBuilder.new( author: , comment_id: comment_id, initials: initials ) cb << text if text block.call(cb) if block_given? comment_obj = cb.build @model.comments ||= [] @model.comments << comment_obj comment_obj end |
#content_control(tag: nil, alias_name: nil, placeholder_text: nil) ⇒ SdtBuilder
Create a text content control paragraph
507 508 509 510 511 512 513 514 |
# File 'lib/uniword/builder/document_builder.rb', line 507 def content_control(tag: nil, alias_name: nil, placeholder_text: nil) sdt = SdtBuilder.text( tag: tag, alias_name: alias_name, placeholder_text: placeholder_text ) @model.body.paragraphs.last&.sdts&.<<(sdt.build) sdt end |
#created(value) ⇒ Object
373 374 375 376 |
# File 'lib/uniword/builder/document_builder.rb', line 373 def created(value) @model.core_properties.created = value self end |
#date_field(format: "M/d/yyyy") ⇒ self
Insert a date paragraph
580 581 582 583 |
# File 'lib/uniword/builder/document_builder.rb', line 580 def date_field(format: "M/d/yyyy") self << Builder.date_field(format: format) self end |
#define_style(name, base_on: "Normal") {|StyleBuilder| ... } ⇒ StyleBuilder
Define a paragraph style
341 342 343 344 345 346 |
# File 'lib/uniword/builder/document_builder.rb', line 341 def define_style(name, base_on: "Normal", &block) style = StyleBuilder.new(name, base_on: base_on) block.call(style) if block_given? @model.styles_configuration.add_style(style.build) style end |
#description(value) ⇒ Object
358 359 360 361 |
# File 'lib/uniword/builder/document_builder.rb', line 358 def description(value) @model.core_properties.description = value self end |
#endnote(text = nil) {|ParagraphBuilder| ... } ⇒ Wordprocessingml::Run
Create an endnote and return a Run with an endnoteReference.
319 320 321 |
# File 'lib/uniword/builder/document_builder.rb', line 319 def endnote(text = nil, &) @footnote_builder.endnote(text, &) end |
#floating_image(path, width: nil, height: nil, alt_text: nil, align: nil, vertical_align: nil, wrap: :square, behind_text: false) ⇒ self
Insert a floating image paragraph
436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/uniword/builder/document_builder.rb', line 436 def floating_image(path, width: nil, height: nil, alt_text: nil, align: nil, vertical_align: nil, wrap: :square, behind_text: false) para = Wordprocessingml::Paragraph.new para.runs << ImageBuilder.create_floating_run( self, path, width: width, height: height, alt_text: alt_text, align: align, wrap: wrap, behind_text: behind_text ) self << para self end |
#footer(type: "default") {|HeaderFooterBuilder| ... } ⇒ HeaderFooterBuilder
Configure a footer
239 240 241 242 243 244 |
# File 'lib/uniword/builder/document_builder.rb', line 239 def (type: "default", &block) hf = HeaderFooterBuilder.new(:footer, type: type, allocator: @allocator) block.call(hf) if block_given? (@model. ||= {})[type] = hf.build hf end |
#footnote(text = nil) {|ParagraphBuilder| ... } ⇒ Wordprocessingml::Run
Create a footnote and return a Run with a footnoteReference.
310 311 312 |
# File 'lib/uniword/builder/document_builder.rb', line 310 def footnote(text = nil, &) @footnote_builder.footnote(text, &) end |
#header(type: "default") {|HeaderFooterBuilder| ... } ⇒ HeaderFooterBuilder
Configure a header
227 228 229 230 231 232 |
# File 'lib/uniword/builder/document_builder.rb', line 227 def header(type: "default", &block) hf = HeaderFooterBuilder.new(:header, type: type, allocator: @allocator) block.call(hf) if block_given? (@model.headers ||= {})[type] = hf.build hf end |
#heading(text, level: 1) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create and add a heading paragraph
180 181 182 183 184 185 186 |
# File 'lib/uniword/builder/document_builder.rb', line 180 def heading(text, level: 1) para = ParagraphBuilder.new(allocator: @allocator) para.style = "Heading#{level}" para << text self << para para end |
#horizontal_rule(style: "single", color: "auto", size: 6) ⇒ self
Insert a horizontal rule (paragraph with bottom border)
399 400 401 402 403 404 405 406 407 |
# File 'lib/uniword/builder/document_builder.rb', line 399 def horizontal_rule(style: "single", color: "auto", size: 6) para = ParagraphBuilder.new(allocator: @allocator) para.borders( bottom: { style: style, color: color, size: size } ) para.spacing(after: 0) self << para self end |
#image(path, width: nil, height: nil, alt_text: nil) ⇒ self
Insert an inline image paragraph
416 417 418 419 420 421 422 423 |
# File 'lib/uniword/builder/document_builder.rb', line 416 def image(path, width: nil, height: nil, alt_text: nil) para = Wordprocessingml::Paragraph.new para.runs << ImageBuilder.create_run( self, path, width: width, height: height, alt_text: alt_text ) self << para self end |
#keywords(value) ⇒ Object
368 369 370 371 |
# File 'lib/uniword/builder/document_builder.rb', line 368 def keywords(value) @model.core_properties.keywords = value self end |
#list(type: :bullet) {|ListBuilder| ... } ⇒ ListBuilder
Create a list (bulleted or numbered)
263 264 265 266 267 |
# File 'lib/uniword/builder/document_builder.rb', line 263 def list(type: :bullet, &block) lb = ListBuilder.new(self, type: type) block.call(lb) if block_given? lb end |
#modified(value) ⇒ Object
378 379 380 381 |
# File 'lib/uniword/builder/document_builder.rb', line 378 def modified(value) @model.core_properties.modified = value self end |
#numbered_list {|ListBuilder| ... } ⇒ ListBuilder
Shorthand: create a numbered list
273 274 275 |
# File 'lib/uniword/builder/document_builder.rb', line 273 def numbered_list(&) list(type: :decimal, &) end |
#page_break ⇒ self
Insert a page break
191 192 193 194 195 196 |
# File 'lib/uniword/builder/document_builder.rb', line 191 def page_break self << Wordprocessingml::Paragraph.new( runs: [Builder.page_break] ) self end |
#page_number ⇒ self
Insert a page number paragraph
563 564 565 566 |
# File 'lib/uniword/builder/document_builder.rb', line 563 def page_number self << Builder.page_number_field self end |
#paragraph(text = nil) {|ParagraphBuilder| ... } ⇒ ParagraphBuilder
Create and add a paragraph to the document
166 167 168 169 170 171 172 |
# File 'lib/uniword/builder/document_builder.rb', line 166 def paragraph(text = nil, &block) para = ParagraphBuilder.new(allocator: @allocator) para << text if text block.call(para) if block_given? self << para para end |
#save(path) ⇒ Object
Save document to file
597 598 599 |
# File 'lib/uniword/builder/document_builder.rb', line 597 def save(path) @model.to_file(path) end |
#section(type: "nextPage") {|SectionBuilder| ... } ⇒ SectionBuilder
Configure section properties
214 215 216 217 218 219 220 |
# File 'lib/uniword/builder/document_builder.rb', line 214 def section(type: "nextPage", &block) sec = SectionBuilder.new sec.type = type block.call(sec) if block_given? @model.body.section_properties ||= sec.build sec end |
#subject(value) ⇒ Object
363 364 365 366 |
# File 'lib/uniword/builder/document_builder.rb', line 363 def subject(value) @model.core_properties.subject = value self end |
#table {|TableBuilder| ... } ⇒ TableBuilder
Create and add a table to the document
202 203 204 205 206 207 |
# File 'lib/uniword/builder/document_builder.rb', line 202 def table(&block) tbl = TableBuilder.new block.call(tbl) if block_given? self << tbl tbl end |
#theme(name = nil) {|ThemeBuilder| ... } ⇒ ThemeBuilder
Apply or configure a document theme
328 329 330 331 332 333 |
# File 'lib/uniword/builder/document_builder.rb', line 328 def theme(name = nil, &block) tb = ThemeBuilder.new(self) tb.apply(name) if name block.call(tb) if block_given? tb end |
#time_field(format: "h:mm:ss am/pm") ⇒ self
Insert a time paragraph
589 590 591 592 |
# File 'lib/uniword/builder/document_builder.rb', line 589 def time_field(format: "h:mm:ss am/pm") self << Builder.time_field(format: format) self end |
#title(value) ⇒ Object
348 349 350 351 |
# File 'lib/uniword/builder/document_builder.rb', line 348 def title(value) @model.core_properties.title = value self end |
#toc(title: "Table of Contents", styles: nil) ⇒ self
Insert a Table of Contents
251 252 253 254 255 256 |
# File 'lib/uniword/builder/document_builder.rb', line 251 def toc(title: "Table of Contents", styles: nil) TocBuilder.build(title: title, styles: styles).each do |para| self << para end self end |
#total_pages ⇒ self
Insert a total pages paragraph
571 572 573 574 |
# File 'lib/uniword/builder/document_builder.rb', line 571 def total_pages self << Builder.total_pages_field self end |
#watermark(text, font: "Calibri", size: 60, color: nil, opacity: "0.3", angle: -45)) ⇒ self
Add a watermark to the document header
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/uniword/builder/document_builder.rb', line 457 def watermark(text, font: "Calibri", size: 60, color: nil, opacity: "0.3", angle: -45) if text.nil? (@model.headers ||= {}).delete("default") return self end para = WatermarkBuilder.build_paragraph( text, font: font, size: size, color: color, opacity: opacity, angle: angle ) header = Wordprocessingml::Header.new header.paragraphs << para (@model.headers ||= {})["default"] = header self end |