Module: Uniword::Docx::Reconciler::PackageStructure

Included in:
Uniword::Docx::Reconciler
Defined in:
lib/uniword/docx/reconciler/package_structure.rb

Overview

Package-level consistency enforcement.

Rebuilds content types and relationships for standard parts, preserving non-standard entries from the source document. All part metadata (paths, content types, rel types) comes from Ooxml::PartRegistry; this module only declares which parts go where, in which order.

Constant Summary collapse

UNSUPPORTED_REL_TYPES =

Relationship types for parts we don't model or serialize. Exception: stylesWithEffects is a Microsoft extension never written by uniword, so it is not in Ooxml::PartRegistry.

Set[
  "http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects",
].freeze
PACKAGE_LEVEL_REL_TYPES =

Rel types that belong in package-level _rels/.rels, not document.xml.rels.

Ooxml::PartRegistry.package_rel_types.to_set.freeze
PACKAGE_REL_PARTS =

Standard package-level parts, in _rels/.rels emission order.

%i[document core_properties app_properties].freeze

Instance Method Summary collapse

Instance Method Details

#reconcile_content_typesObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/uniword/docx/reconciler/package_structure.rb', line 28

def reconcile_content_types
  ct = package.content_types
  return unless ct

  ct.defaults = %i[rels xml].map do |key|
    defn = Ooxml::PartRegistry.find_by_key(key)
    Uniword::ContentTypes::Default.new(
      extension: defn.extension,
      content_type: defn.content_type,
    )
  end

  standard = content_type_overrides_for_present_parts
  standard_parts = standard.to_set(&:part_name)
  non_standard = ct.overrides.reject do |o|
    standard_parts.include?(o.part_name)
  end

  ct.overrides = standard + non_standard
  record_fix(FixCodes::CONTENT_TYPES_ASSEMBLED,
             "Rebuilt content types for standard parts",
             part: "[Content_Types].xml")
end

#reconcile_document_relsObject



87
88
89
90
91
92
# File 'lib/uniword/docx/reconciler/package_structure.rb', line 87

def reconcile_document_rels
  rels = package.document_rels
  return unless rels

  assemble_document_rels(rels, document_rel_defs)
end

#reconcile_package_relsObject



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/uniword/docx/reconciler/package_structure.rb', line 52

def reconcile_package_rels
  rels = package.package_rels
  return unless rels

  # Preserve-first: existing rels keep their position and rId;
  # only genuinely missing standard parts are appended, with
  # rIds allocated by the allocator (seeded from these rels).
  # A later rel whose rId duplicates an already-kept one is
  # dropped — duplicates are impossible by construction.
  kept = []
  seen_ids = Set.new
  rels.relationships.each do |rel|
    next if rel.id && seen_ids.include?(rel.id)

    kept << rel
    seen_ids << rel.id if rel.id
  end

  PACKAGE_REL_PARTS.each do |key|
    defn = Ooxml::PartRegistry.find_by_key(key)
    next if kept.any? { |r| r.target == defn.target }

    kept << build_rel(
      allocator.alloc_rid(target: defn.target, type: defn.rel_type,
                          scope: :package),
      defn.rel_type, defn.target,
    )
  end

  rels.relationships = kept
  record_fix(FixCodes::RELATIONSHIPS_ASSEMBLED,
             "Assembled package relationships (preserve-first)",
             part: "_rels/.rels")
end