Class: Uniword::Docx::Package
- Inherits:
-
Lutaml::Model::Serializable
- Object
- Lutaml::Model::Serializable
- Uniword::Docx::Package
- Includes:
- PackageDefaults, PackageSerialization
- Defined in:
- lib/uniword/docx/package.rb
Overview
DOCX Package - Complete DOCX file format model
Represents the entire .docx file structure as a lutaml-model object. Each XML file within the ZIP is a separate lutaml-model class.
A DOCX package CONTAINS OOXML markup wrapped in an OPC ZIP container. This class lives in Uniword::Docx, not Uniword::Ooxml, because DOCX is a file format that uses OOXML, not the other way around.
Constant Summary
Constants included from PackageSerialization
Uniword::Docx::PackageSerialization::DOCX_INFRA_OPTIONS, Uniword::Docx::PackageSerialization::DOCX_PART_OPTIONS, Uniword::Docx::PackageSerialization::DOCX_PROPS_OPTIONS, Uniword::Docx::PackageSerialization::DOCX_XML_OPTIONS
Instance Attribute Summary collapse
-
#allocator ⇒ Object
Central ID allocator — owns all rId, footnote, bookmark, etc.
-
#custom_xml_items ⇒ Array<CustomXmlItem>?
Custom XML data items (customXml/item*.xml).
-
#endnotes_rels ⇒ Object
Returns the value of attribute endnotes_rels.
-
#footnotes_rels ⇒ Object
Returns the value of attribute footnotes_rels.
-
#modified_part_paths ⇒ Object
Paths that have been modified and should not use raw XML passthrough.
-
#profile ⇒ Object
Non-serialized attributes (DOCX packaging helpers).
-
#raw_xml_parts ⇒ Object
Raw XML from template ZIP for unmodified parts.
-
#settings_rels ⇒ Object
Returns the value of attribute settings_rels.
Class Method Summary collapse
-
.from_file(path) ⇒ Package
Load DOCX package from file.
-
.from_zip_content(zip_content, zip_path = nil) ⇒ Package
Create package from extracted ZIP content.
-
.to_file(document, path, profile: nil, validate: nil) ⇒ void
Save document to file (class method for DocumentWriter compatibility).
Instance Method Summary collapse
-
#applied_fixes ⇒ Array<Reconciler::Fix>
Audit trail of repairs applied by the Reconciler during the most recent save (to_zip_content).
- #body ⇒ Object
- #charts ⇒ Object
- #each_paragraph ⇒ Object
-
#embeddings ⇒ PartCollection
OLE/embedded object binaries (word/embeddings/*), keyed by target.
-
#embeddings=(value) ⇒ Object
Bulk-assign embeddings (Hash of target => Part/binary; nil clears).
-
#paragraphs ⇒ Object
Delegate common DocumentRoot methods for API compatibility.
-
#populate_allocator ⇒ Object
Populate the allocator from all existing template data.
-
#prepare_allocator ⇒ Object
Guarantee the single rId authority before reconciliation: reuse the package's allocator (loaded/builder-seeded) or start one, then seed it from the package's current relationships.
-
#raw_parts ⇒ PartCollection
Raw passthrough parts no registry definition models, keyed by package path ("docProps/meta.xml", "word/glossary/document.xml", ...).
-
#raw_parts=(value) ⇒ Object
Bulk-assign raw parts (Hash of path => RawPart/hash; nil clears).
-
#reorder_content_hash(content) ⇒ Object
Ensure [Content_Types].xml is first, _rels/.rels is second.
- #styles_configuration ⇒ Object
- #tables ⇒ Object
- #text ⇒ Object
-
#to_file(path, validate: nil) ⇒ void
(also: #save)
Save package to file.
-
#to_zip_content(validate: nil) ⇒ Hash
Generate ZIP content hash.
Methods included from PackageSerialization
#add_standalone, #inject_part_relationships, #serialize_infrastructure, #serialize_package_parts, #serialize_part
Methods included from PackageDefaults
Instance Attribute Details
#allocator ⇒ Object
Central ID allocator — owns all rId, footnote, bookmark, etc. assignment. Seeded from template rels on load; used by builders during construction.
130 131 132 |
# File 'lib/uniword/docx/package.rb', line 130 def allocator @allocator end |
#custom_xml_items ⇒ Array<CustomXmlItem>?
Custom XML data items (customXml/item*.xml)
49 50 51 |
# File 'lib/uniword/docx/package.rb', line 49 def custom_xml_items @custom_xml_items end |
#endnotes_rels ⇒ Object
Returns the value of attribute endnotes_rels.
98 99 100 |
# File 'lib/uniword/docx/package.rb', line 98 def endnotes_rels @endnotes_rels end |
#footnotes_rels ⇒ Object
Returns the value of attribute footnotes_rels.
98 99 100 |
# File 'lib/uniword/docx/package.rb', line 98 def footnotes_rels @footnotes_rels end |
#modified_part_paths ⇒ Object
Paths that have been modified and should not use raw XML passthrough.
138 139 140 |
# File 'lib/uniword/docx/package.rb', line 138 def modified_part_paths @modified_part_paths end |
#profile ⇒ Object
Non-serialized attributes (DOCX packaging helpers)
97 98 99 |
# File 'lib/uniword/docx/package.rb', line 97 def profile @profile end |
#raw_xml_parts ⇒ Object
Raw XML from template ZIP for unmodified parts. When present, these are used verbatim instead of re-serializing through lutaml-model (which drops unmapped elements).
135 136 137 |
# File 'lib/uniword/docx/package.rb', line 135 def raw_xml_parts @raw_xml_parts end |
#settings_rels ⇒ Object
Returns the value of attribute settings_rels.
98 99 100 |
# File 'lib/uniword/docx/package.rb', line 98 def settings_rels @settings_rels end |
Class Method Details
.from_file(path) ⇒ Package
Load DOCX package from file
153 154 155 156 157 158 159 |
# File 'lib/uniword/docx/package.rb', line 153 def self.from_file(path) extractor = Infrastructure::ZipExtractor.new zip_content = extractor.extract(path) package = from_zip_content(zip_content, path) package.populate_allocator package end |
.from_zip_content(zip_content, zip_path = nil) ⇒ Package
Create package from extracted ZIP content
Parts load by iterating Ooxml::PartRegistry.loadable and dispatching each definition to its Docx::PartLoader strategy — see PartLoader for the load order and strategy registry.
170 171 172 173 174 |
# File 'lib/uniword/docx/package.rb', line 170 def self.from_zip_content(zip_content, zip_path = nil) package = new PartLoader.load(zip_content, package, zip_path: zip_path) package end |
.to_file(document, path, profile: nil, validate: nil) ⇒ void
This method returns an undefined value.
Save document to file (class method for DocumentWriter compatibility)
184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/uniword/docx/package.rb', line 184 def self.to_file(document, path, profile: nil, validate: nil) package = new package.document = document package.profile = profile || Profile.defaults copy_document_parts_to_package(document, package) package.content_types ||= minimal_content_types package.package_rels ||= minimal_package_rels package.document_rels ||= minimal_document_rels package.settings ||= Uniword::Wordprocessingml::Settings.new package.font_table ||= Uniword::Wordprocessingml::FontTable.new package.web_settings ||= Uniword::Wordprocessingml::WebSettings.new package.to_file(path, validate: validate) end |
Instance Method Details
#applied_fixes ⇒ Array<Reconciler::Fix>
Audit trail of repairs applied by the Reconciler during the most recent save (to_zip_content). Empty before the first save and when the package needed no repairs.
145 146 147 |
# File 'lib/uniword/docx/package.rb', line 145 def applied_fixes @applied_fixes ||= [] end |
#body ⇒ Object
297 298 299 |
# File 'lib/uniword/docx/package.rb', line 297 def body document&.body end |
#charts ⇒ Object
311 312 313 |
# File 'lib/uniword/docx/package.rb', line 311 def charts document&.charts || [] end |
#each_paragraph ⇒ Object
305 306 307 |
# File 'lib/uniword/docx/package.rb', line 305 def each_paragraph(&) paragraphs.each(&) end |
#embeddings ⇒ PartCollection
OLE/embedded object binaries (word/embeddings/*), keyed by target.
103 104 105 |
# File 'lib/uniword/docx/package.rb', line 103 def @embeddings ||= PartCollection.new(:target, Part) end |
#embeddings=(value) ⇒ Object
Bulk-assign embeddings (Hash of target => Part/binary; nil clears).
108 109 110 |
# File 'lib/uniword/docx/package.rb', line 108 def (value) .replace_all(value) end |
#paragraphs ⇒ Object
Delegate common DocumentRoot methods for API compatibility
289 290 291 |
# File 'lib/uniword/docx/package.rb', line 289 def paragraphs document&.paragraphs || [] end |
#populate_allocator ⇒ Object
Populate the allocator from all existing template data. Must be called BEFORE any builder runs (populate-first principle).
200 201 202 |
# File 'lib/uniword/docx/package.rb', line 200 def populate_allocator @allocator = IdAllocator.populate_from_package(self) end |
#prepare_allocator ⇒ Object
Guarantee the single rId authority before reconciliation: reuse the package's allocator (loaded/builder-seeded) or start one, then seed it from the package's current relationships. Seeding preserves loaded rIds verbatim; earlier builder allocations keep their ids — a seeded rel whose id collides is reallocated deterministically (IdAllocator#seed_from_rels).
210 211 212 213 214 215 216 |
# File 'lib/uniword/docx/package.rb', line 210 def prepare_allocator self.allocator ||= IdAllocator.new allocator.seed_from_rels(package_rels&.relationships, scope: :package) allocator.seed_from_rels(document_rels&.relationships) allocator end |
#raw_parts ⇒ PartCollection
Raw passthrough parts no registry definition models, keyed by package path ("docProps/meta.xml", "word/glossary/document.xml", ...). Carried byte-for-byte from load to save — see PartLoader::RawPartLoader for claiming and PackageSerialization#serialize_raw_parts for emission.
119 120 121 |
# File 'lib/uniword/docx/package.rb', line 119 def raw_parts @raw_parts ||= PartCollection.new(:path, RawPart) end |
#raw_parts=(value) ⇒ Object
Bulk-assign raw parts (Hash of path => RawPart/hash; nil clears).
124 125 126 |
# File 'lib/uniword/docx/package.rb', line 124 def raw_parts=(value) raw_parts.replace_all(value) end |
#reorder_content_hash(content) ⇒ Object
Ensure [Content_Types].xml is first, _rels/.rels is second.
280 281 282 283 284 285 |
# File 'lib/uniword/docx/package.rb', line 280 def reorder_content_hash(content) priority = {} priority["[Content_Types].xml"] = content.delete("[Content_Types].xml") if content.key?("[Content_Types].xml") priority["_rels/.rels"] = content.delete("_rels/.rels") if content.key?("_rels/.rels") content.replace(priority.merge(content)) end |
#styles_configuration ⇒ Object
315 316 317 |
# File 'lib/uniword/docx/package.rb', line 315 def styles_configuration document&.styles_configuration end |
#tables ⇒ Object
293 294 295 |
# File 'lib/uniword/docx/package.rb', line 293 def tables document&.tables || [] end |
#text ⇒ Object
301 302 303 |
# File 'lib/uniword/docx/package.rb', line 301 def text document&.text || "" end |
#to_file(path, validate: nil) ⇒ void Also known as: save
This method returns an undefined value.
Save package to file
226 227 228 229 230 |
# File 'lib/uniword/docx/package.rb', line 226 def to_file(path, validate: nil) zip_content = to_zip_content(validate: validate) packager = Infrastructure::ZipPackager.new packager.package(zip_content, path) end |
#to_zip_content(validate: nil) ⇒ Hash
Generate ZIP content hash
Runs the Reconciler (the only mutating pass), records its repair report on #applied_fixes, and — unless validation is disabled — refuses invalid output via the PackageIntegrityChecker gate.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/uniword/docx/package.rb', line 243 def to_zip_content(validate: nil) content = {} self.content_types ||= self.class.minimal_content_types self.package_rels ||= self.class.minimal_package_rels self.document_rels ||= self.class.minimal_document_rels self.settings ||= Uniword::Wordprocessingml::Settings.new self.font_table ||= Uniword::Wordprocessingml::FontTable.new self.web_settings ||= Uniword::Wordprocessingml::WebSettings.new # An allocator carried into the save (builder-managed document # or loaded package) selects light-touch repairs; documents # without one get the full normalization repertoire. rIds flow # through the allocator either way. builder_managed = !allocator.nil? prepare_allocator reconciler = Reconciler.new(self, profile: profile || Profile.defaults, allocator: allocator, builder_managed: builder_managed) reconciler.reconcile @applied_fixes = reconciler.applied_fixes log_applied_fixes inject_part_relationships(content, content_types, package_rels, document_rels) serialize_package_parts(content, content_types, package_rels, document_rels) # OOXML requires [Content_Types].xml as the first ZIP entry. reorder_content_hash(content) enforce_package_integrity(content, validate) content end |