Class: Uniword::Ooxml::PartDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/uniword/ooxml/part_definition.rb

Overview

Declarative description of one OOXML package part kind.

A PartDefinition is the single source of truth for a part's package path, content type, relationship type, the form its [Content_Types].xml entry takes (Default by extension or Override by part name), how it is loaded from extracted ZIP content, and where it lives on both Wordprocessingml::DocumentRoot and Docx::Package. Instances are immutable value objects registered in PartRegistry; consumers derive every literal from them.

Parts with instance-numbered paths (headers, footers, charts, customXml items) carry a +path_pattern+/+target_pattern+ with +format+-style placeholders (e.g. "word/header%d.xml") instead of a fixed path.

Load behavior beyond this data (parse rules for special part kinds) lives in named Docx::PartLoader strategy classes selected by loader; the definition itself stays a value object.

Examples:

Fixed part

PartDefinition.new(
  key: :styles, path: "word/styles.xml", target: "styles.xml",
  content_type: "...styles+xml",
  rel_type: ".../relationships/styles",
  required: true, kind: :override, rels_scope: :document,
  loader: :xml_model,
  loader_model: Uniword::Wordprocessingml::StylesConfiguration,
  load_priority: 50,
  package_attribute: :styles,
  document_attribute: :styles_configuration,
)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key:, kind:, path: nil, path_pattern: nil, target: nil, target_pattern: nil, content_type: nil, rel_type: nil, extension: nil, required: false, rels_scope: nil, standard: false, loader: nil, loader_model: nil, path_resolution: nil, load_priority: nil, document_attribute: nil, package_attribute: nil, copy_to_document: true, to_package_guard: nil, to_package_type: nil) ⇒ PartDefinition

rubocop:disable Metrics/ParameterLists, Metrics/MethodLength rubocop:disable Metrics/AbcSize



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/uniword/ooxml/part_definition.rb', line 125

def initialize(key:, kind:, path: nil, path_pattern: nil,
               target: nil, target_pattern: nil,
               content_type: nil, rel_type: nil, extension: nil,
               required: false, rels_scope: nil, standard: false,
               loader: nil, loader_model: nil, path_resolution: nil,
               load_priority: nil, document_attribute: nil,
               package_attribute: nil, copy_to_document: true,
               to_package_guard: nil, to_package_type: nil)
  @key = key.to_sym
  @kind = kind
  @path = path
  @path_pattern = path_pattern
  @target = target || path
  @target_pattern = target_pattern
  @content_type = content_type
  @rel_type = rel_type
  @extension = extension
  @required = required
  @rels_scope = rels_scope
  @standard = standard
  @loader = loader
  @loader_model = loader_model
  @path_resolution = path_resolution
  @load_priority = load_priority
  @document_attribute = document_attribute
  @package_attribute = package_attribute
  @copy_to_document = copy_to_document
  @to_package_guard = to_package_guard
  @to_package_type = to_package_type
end

Instance Attribute Details

#content_typeString? (readonly)

Returns MIME content type (nil when dynamic, e.g. images whose type depends on the file extension).

Returns:

  • (String, nil)

    MIME content type (nil when dynamic, e.g. images whose type depends on the file extension)



55
56
57
# File 'lib/uniword/ooxml/part_definition.rb', line 55

def content_type
  @content_type
end

#copy_to_documentBoolean (readonly)

Returns whether the package→document copy includes this part (false when the loader already places the part on the document, or the part is never read from ZIP content).

Returns:

  • (Boolean)

    whether the package→document copy includes this part (false when the loader already places the part on the document, or the part is never read from ZIP content)



111
112
113
# File 'lib/uniword/ooxml/part_definition.rb', line 111

def copy_to_document
  @copy_to_document
end

#document_attributeSymbol? (readonly)

Returns attribute (reader/writer) holding this part on Wordprocessingml::DocumentRoot.

Returns:

  • (Symbol, nil)

    attribute (reader/writer) holding this part on Wordprocessingml::DocumentRoot



102
103
104
# File 'lib/uniword/ooxml/part_definition.rb', line 102

def document_attribute
  @document_attribute
end

#extensionString? (readonly)

Returns file extension for Default entries.

Returns:

  • (String, nil)

    file extension for Default entries



62
63
64
# File 'lib/uniword/ooxml/part_definition.rb', line 62

def extension
  @extension
end

#keySymbol (readonly)

Returns unique registry key (e.g. :styles).

Returns:

  • (Symbol)

    unique registry key (e.g. :styles)



38
39
40
# File 'lib/uniword/ooxml/part_definition.rb', line 38

def key
  @key
end

#kindSymbol (readonly)

Returns :override, :default, or :none (no [Content_Types].xml entry of its own).

Returns:

  • (Symbol)

    :override, :default, or :none (no [Content_Types].xml entry of its own)



69
70
71
# File 'lib/uniword/ooxml/part_definition.rb', line 69

def kind
  @kind
end

#load_priorityInteger? (readonly)

Returns load ordering weight — lower loads first; entries sharing a priority load in registration order.

Returns:

  • (Integer, nil)

    load ordering weight — lower loads first; entries sharing a priority load in registration order



98
99
100
# File 'lib/uniword/ooxml/part_definition.rb', line 98

def load_priority
  @load_priority
end

#loaderSymbol? (readonly)

Returns Docx::PartLoader strategy key (:xml_model, :custom_xml, :header_footer, :chart, :image, :embedding, :theme_media); nil when the part is not loaded from ZIP content.

Returns:

  • (Symbol, nil)

    Docx::PartLoader strategy key (:xml_model, :custom_xml, :header_footer, :chart, :image, :embedding, :theme_media); nil when the part is not loaded from ZIP content



83
84
85
# File 'lib/uniword/ooxml/part_definition.rb', line 83

def loader
  @loader
end

#loader_modelClass? (readonly)

Returns model class parsing the part's XML (responds to .from_xml); used by loaders that parse.

Returns:

  • (Class, nil)

    model class parsing the part's XML (responds to .from_xml); used by loaders that parse



87
88
89
# File 'lib/uniword/ooxml/part_definition.rb', line 87

def loader_model
  @loader_model
end

#package_attributeSymbol? (readonly)

Returns attribute (reader/writer) holding this part on Docx::Package.

Returns:

  • (Symbol, nil)

    attribute (reader/writer) holding this part on Docx::Package



106
107
108
# File 'lib/uniword/ooxml/part_definition.rb', line 106

def package_attribute
  @package_attribute
end

#pathString? (readonly)

Returns package-relative path ("word/styles.xml").

Returns:

  • (String, nil)

    package-relative path ("word/styles.xml")



41
42
43
# File 'lib/uniword/ooxml/part_definition.rb', line 41

def path
  @path
end

#path_patternString? (readonly)

Returns path template for instance-numbered parts.

Returns:

  • (String, nil)

    path template for instance-numbered parts



44
45
46
# File 'lib/uniword/ooxml/part_definition.rb', line 44

def path_pattern
  @path_pattern
end

#path_resolutionSymbol? (readonly)

Returns dynamic path resolution rule: :office_document (resolve the main document path from the package-level officeDocument relationship) or :office_document_rels (sidecar .rels of the resolved main document); nil for fixed paths.

Returns:

  • (Symbol, nil)

    dynamic path resolution rule: :office_document (resolve the main document path from the package-level officeDocument relationship) or :office_document_rels (sidecar .rels of the resolved main document); nil for fixed paths



94
95
96
# File 'lib/uniword/ooxml/part_definition.rb', line 94

def path_resolution
  @path_resolution
end

#rel_typeString? (readonly)

Returns relationship type URI (nil when the part is not referenced by a relationship).

Returns:

  • (String, nil)

    relationship type URI (nil when the part is not referenced by a relationship)



59
60
61
# File 'lib/uniword/ooxml/part_definition.rb', line 59

def rel_type
  @rel_type
end

#rels_scopeSymbol? (readonly)

Returns :package or :document — which .rels part the relationship lives in (nil when rel_type is nil).

Returns:

  • (Symbol, nil)

    :package or :document — which .rels part the relationship lives in (nil when rel_type is nil)



73
74
75
# File 'lib/uniword/ooxml/part_definition.rb', line 73

def rels_scope
  @rels_scope
end

#requiredBoolean (readonly)

Returns whether a minimal valid package carries it.

Returns:

  • (Boolean)

    whether a minimal valid package carries it



65
66
67
# File 'lib/uniword/ooxml/part_definition.rb', line 65

def required
  @required
end

#standardBoolean (readonly)

Returns whether ContentTypes.generate includes it in the comprehensive [Content_Types].xml for new DOCX packages.

Returns:

  • (Boolean)

    whether ContentTypes.generate includes it in the comprehensive [Content_Types].xml for new DOCX packages



77
78
79
# File 'lib/uniword/ooxml/part_definition.rb', line 77

def standard
  @standard
end

#targetString? (readonly)

Returns relationship Target as written in .rels (relative to the owning part; defaults to path).

Returns:

  • (String, nil)

    relationship Target as written in .rels (relative to the owning part; defaults to path)



48
49
50
# File 'lib/uniword/ooxml/part_definition.rb', line 48

def target
  @target
end

#target_patternString? (readonly)

Returns Target template for numbered parts.

Returns:

  • (String, nil)

    Target template for numbered parts



51
52
53
# File 'lib/uniword/ooxml/part_definition.rb', line 51

def target_pattern
  @target_pattern
end

#to_package_guardSymbol? (readonly)

Returns predicate on the document guarding the document→package copy (e.g. :numbering_configuration_loaded? for the lazily-initialized numbering configuration).

Returns:

  • (Symbol, nil)

    predicate on the document guarding the document→package copy (e.g. :numbering_configuration_loaded? for the lazily-initialized numbering configuration)



116
117
118
# File 'lib/uniword/ooxml/part_definition.rb', line 116

def to_package_guard
  @to_package_guard
end

#to_package_typeClass? (readonly)

Returns class the value must be an instance of for the document→package copy (e.g. CommentsPart, since DocumentRoot#comments can hold non-part values).

Returns:

  • (Class, nil)

    class the value must be an instance of for the document→package copy (e.g. CommentsPart, since DocumentRoot#comments can hold non-part values)



121
122
123
# File 'lib/uniword/ooxml/part_definition.rb', line 121

def to_package_type
  @to_package_type
end

Instance Method Details

#==(other) ⇒ Object

Two definitions are equal when every field matches.



266
267
268
# File 'lib/uniword/ooxml/part_definition.rb', line 266

def ==(other)
  other.is_a?(PartDefinition) && fields == other.fields
end

#copy_to_document?Boolean

Returns true when the package→document copy mirrors this part onto Wordprocessingml::DocumentRoot.

Returns:

  • (Boolean)

    true when the package→document copy mirrors this part onto Wordprocessingml::DocumentRoot



190
191
192
# File 'lib/uniword/ooxml/part_definition.rb', line 190

def copy_to_document?
  !!copy_to_document
end

#default?Boolean

Returns true for [Content_Types].xml Default entries.

Returns:

  • (Boolean)

    true for [Content_Types].xml Default entries



164
165
166
# File 'lib/uniword/ooxml/part_definition.rb', line 164

def default?
  kind == :default
end

#emitted_paths(package) ⇒ Array<String>

Package paths this part kind emits for the given package.

Single-instance kinds emit their fixed path when the backing model is present; collection families emit each stored part's own paths (each part object answers package_paths).

Parameters:

Returns:

  • (Array<String>)

    emitted package paths (possibly empty)



258
259
260
261
262
263
# File 'lib/uniword/ooxml/part_definition.rb', line 258

def emitted_paths(package)
  source = attribute_source(package)
  return [] if source.nil?

  collection? ? collection_paths(source) : [path]
end

#loadable?Boolean

Returns true when the part loads from ZIP content.

Returns:

  • (Boolean)

    true when the part loads from ZIP content



184
185
186
# File 'lib/uniword/ooxml/part_definition.rb', line 184

def loadable?
  !loader.nil?
end

#match_path?(candidate) ⇒ Boolean

Whether a package path matches this definition's fixed path or path pattern. Accepts both "word/styles.xml" and "/word/styles.xml" forms, and matches numbered paths against the pattern ("word/header2.xml" → :header).

Parameters:

  • candidate (String)

    package-relative path

Returns:

  • (Boolean)


201
202
203
204
205
206
207
# File 'lib/uniword/ooxml/part_definition.rb', line 201

def match_path?(candidate)
  normalized = candidate.to_s.delete_prefix("/")
  return true if path == normalized
  return false unless path_pattern

  normalized.match?(template_regex(path_pattern))
end

#override?Boolean

Returns true for [Content_Types].xml Override entries.

Returns:

  • (Boolean)

    true for [Content_Types].xml Override entries



159
160
161
# File 'lib/uniword/ooxml/part_definition.rb', line 159

def override?
  kind == :override
end

#package_rel?Boolean

Returns true when the relationship lives in _rels/.rels.

Returns:

  • (Boolean)

    true when the relationship lives in _rels/.rels



179
180
181
# File 'lib/uniword/ooxml/part_definition.rb', line 179

def package_rel?
  rels_scope == :package
end

#part_nameString?

Fixed-path Override part name (leading slash).

Returns:

  • (String, nil)

    e.g. "/word/styles.xml"



246
247
248
# File 'lib/uniword/ooxml/part_definition.rb', line 246

def part_name
  path && "/#{path}"
end

#part_name_for(**vars) ⇒ String?

Resolve the content-type Override part name (leading slash).

Parameters:

  • vars (Hash)

    placeholder values for numbered parts

Returns:

  • (String, nil)

    e.g. "/word/header1.xml"



230
231
232
233
# File 'lib/uniword/ooxml/part_definition.rb', line 230

def part_name_for(**vars)
  resolved = path_for(**vars)
  resolved && "/#{resolved}"
end

#path_for(**vars) ⇒ String?

Resolve the package-relative path, interpolating pattern placeholders for instance-numbered parts.

Parameters:

  • vars (Hash)

    placeholder values (e.g. counter: 1)

Returns:

  • (String, nil)

    e.g. "word/header1.xml"



222
223
224
# File 'lib/uniword/ooxml/part_definition.rb', line 222

def path_for(**vars)
  expand(path_pattern || path, vars)
end

#pattern_prefixString?

Static prefix of the path pattern up to the first placeholder (e.g. "word/theme/media/" for "word/theme/media/%s").

Returns:

  • (String, nil)

    nil for fixed-path definitions



213
214
215
# File 'lib/uniword/ooxml/part_definition.rb', line 213

def pattern_prefix
  path_pattern&.split(/%<\w+>[ds]/)&.first
end

#required?Boolean

Returns true when a minimal valid package carries it.

Returns:

  • (Boolean)

    true when a minimal valid package carries it



169
170
171
# File 'lib/uniword/ooxml/part_definition.rb', line 169

def required?
  !!required
end

#standard?Boolean

Returns true when ContentTypes.generate includes it.

Returns:

  • (Boolean)

    true when ContentTypes.generate includes it



174
175
176
# File 'lib/uniword/ooxml/part_definition.rb', line 174

def standard?
  !!standard
end

#target_for(**vars) ⇒ String?

Resolve the relationship Target attribute.

Parameters:

  • vars (Hash)

    placeholder values for numbered parts

Returns:

  • (String, nil)

    e.g. "header1.xml"



239
240
241
# File 'lib/uniword/ooxml/part_definition.rb', line 239

def target_for(**vars)
  expand(target_pattern || target, vars)
end