uniword 1.0.10 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/config/font_metadata.yml +56 -0
  3. data/lib/uniword/accessibility/rules/descriptive_headings_rule.rb +1 -1
  4. data/lib/uniword/assembly/toc.rb +4 -14
  5. data/lib/uniword/assembly/variable_substitutor.rb +3 -4
  6. data/lib/uniword/batch/stages/normalize_styles_stage.rb +4 -2
  7. data/lib/uniword/builder/base_builder.rb +25 -0
  8. data/lib/uniword/builder/chart_builder.rb +33 -14
  9. data/lib/uniword/builder/deterministic_id.rb +17 -0
  10. data/lib/uniword/builder/document_builder.rb +129 -34
  11. data/lib/uniword/builder/footnote_builder.rb +22 -23
  12. data/lib/uniword/builder/header_footer_builder.rb +10 -10
  13. data/lib/uniword/builder/image_builder.rb +24 -16
  14. data/lib/uniword/builder/list_builder.rb +2 -1
  15. data/lib/uniword/builder/paragraph_builder.rb +95 -20
  16. data/lib/uniword/builder/run_utils.rb +97 -0
  17. data/lib/uniword/builder/section_builder.rb +40 -67
  18. data/lib/uniword/builder/table_builder.rb +32 -13
  19. data/lib/uniword/builder/table_cell_builder.rb +19 -0
  20. data/lib/uniword/builder.rb +27 -19
  21. data/lib/uniword/cli/diff_cli.rb +0 -1
  22. data/lib/uniword/cli/generate_cli.rb +0 -1
  23. data/lib/uniword/cli/headers_cli.rb +0 -1
  24. data/lib/uniword/cli/images_cli.rb +0 -1
  25. data/lib/uniword/cli/main.rb +6 -7
  26. data/lib/uniword/cli/protect_cli.rb +0 -1
  27. data/lib/uniword/cli/resources_cli.rb +0 -1
  28. data/lib/uniword/cli/review_cli.rb +0 -1
  29. data/lib/uniword/cli/spellcheck_cli.rb +0 -1
  30. data/lib/uniword/cli/styleset_cli.rb +0 -1
  31. data/lib/uniword/cli/template_cli.rb +0 -1
  32. data/lib/uniword/cli/theme_cli.rb +0 -1
  33. data/lib/uniword/cli/toc_cli.rb +0 -1
  34. data/lib/uniword/cli/watermark_cli.rb +0 -1
  35. data/lib/uniword/cli.rb +6 -17
  36. data/lib/uniword/diff/document_differ.rb +23 -5
  37. data/lib/uniword/diff/package_differ.rb +0 -1
  38. data/lib/uniword/diff.rb +4 -0
  39. data/lib/uniword/document_factory.rb +16 -24
  40. data/lib/uniword/docx/document_statistics.rb +42 -54
  41. data/lib/uniword/docx/id_allocator.rb +143 -0
  42. data/lib/uniword/docx/package.rb +42 -6
  43. data/lib/uniword/docx/package_defaults.rb +16 -25
  44. data/lib/uniword/docx/package_serialization.rb +131 -127
  45. data/lib/uniword/docx/reconciler/body.rb +197 -0
  46. data/lib/uniword/docx/reconciler/fix_codes.rb +74 -0
  47. data/lib/uniword/docx/reconciler/helpers.rb +337 -0
  48. data/lib/uniword/docx/reconciler/notes.rb +301 -0
  49. data/lib/uniword/docx/reconciler/package_structure.rb +322 -0
  50. data/lib/uniword/docx/reconciler/parts.rb +484 -0
  51. data/lib/uniword/docx/reconciler/referential_integrity.rb +449 -0
  52. data/lib/uniword/docx/reconciler/tables.rb +162 -0
  53. data/lib/uniword/docx/reconciler/theme.rb +141 -0
  54. data/lib/uniword/docx/reconciler.rb +44 -1069
  55. data/lib/uniword/docx.rb +3 -0
  56. data/lib/uniword/drawingml/color_scheme.rb +38 -5
  57. data/lib/uniword/hyperlink.rb +27 -26
  58. data/lib/uniword/infrastructure/zip_packager.rb +41 -38
  59. data/lib/uniword/lazy_loader.rb +36 -62
  60. data/lib/uniword/math.rb +3 -86
  61. data/lib/uniword/mhtml/document.rb +1 -3
  62. data/lib/uniword/model_attribute_access.rb +27 -0
  63. data/lib/uniword/ooxml/namespaces.rb +62 -2
  64. data/lib/uniword/ooxml/relationships/package_relationships.rb +7 -0
  65. data/lib/uniword/presentationml/slide_id.rb +0 -1
  66. data/lib/uniword/presentationml/slide_master_id.rb +0 -1
  67. data/lib/uniword/properties/bold.rb +0 -2
  68. data/lib/uniword/properties/boolean_formatting.rb +0 -2
  69. data/lib/uniword/properties/borders.rb +1 -1
  70. data/lib/uniword/properties/italic.rb +0 -2
  71. data/lib/uniword/properties/numbering_properties.rb +1 -1
  72. data/lib/uniword/properties/style_reference.rb +13 -0
  73. data/lib/uniword/quality/rules/heading_hierarchy_rule.rb +1 -1
  74. data/lib/uniword/quality/rules/style_consistency_rule.rb +1 -1
  75. data/lib/uniword/review/review_manager.rb +0 -2
  76. data/lib/uniword/template/helpers/loop_helper.rb +2 -2
  77. data/lib/uniword/template/variable_resolver.rb +14 -1
  78. data/lib/uniword/theme/theme_xml_parser.rb +1 -1
  79. data/lib/uniword/toc/toc_generator.rb +3 -14
  80. data/lib/uniword/transformation/mhtml_element_renderer.rb +94 -37
  81. data/lib/uniword/transformation/mhtml_metadata_builder.rb +1 -1
  82. data/lib/uniword/transformation/mhtml_style_builder.rb +9 -2
  83. data/lib/uniword/transformation/ooxml_to_html_converter.rb +3 -5
  84. data/lib/uniword/transformation/ooxml_to_mhtml_converter.rb +7 -15
  85. data/lib/uniword/transformation/yaml_css_generator.rb +815 -0
  86. data/lib/uniword/transformation.rb +2 -0
  87. data/lib/uniword/validation/checkers/internal_link_checker.rb +2 -3
  88. data/lib/uniword/version.rb +1 -1
  89. data/lib/uniword/visitor/text_extractor.rb +2 -1
  90. data/lib/uniword/watermark/manager.rb +2 -2
  91. data/lib/uniword/wordprocessingml/allow_png.rb +14 -0
  92. data/lib/uniword/wordprocessingml/body.rb +53 -18
  93. data/lib/uniword/wordprocessingml/body_div.rb +17 -0
  94. data/lib/uniword/wordprocessingml/div_border.rb +23 -0
  95. data/lib/uniword/wordprocessingml/div_borders.rb +24 -0
  96. data/lib/uniword/wordprocessingml/divs_child.rb +17 -0
  97. data/lib/uniword/wordprocessingml/document_root.rb +6 -3
  98. data/lib/uniword/wordprocessingml/endnote.rb +1 -1
  99. data/lib/uniword/wordprocessingml/endnotes.rb +4 -0
  100. data/lib/uniword/wordprocessingml/footer.rb +4 -0
  101. data/lib/uniword/wordprocessingml/footer_reference.rb +0 -1
  102. data/lib/uniword/wordprocessingml/footnote.rb +1 -1
  103. data/lib/uniword/wordprocessingml/footnotes.rb +4 -0
  104. data/lib/uniword/wordprocessingml/header.rb +4 -0
  105. data/lib/uniword/wordprocessingml/header_reference.rb +0 -1
  106. data/lib/uniword/wordprocessingml/hyperlink.rb +2 -2
  107. data/lib/uniword/wordprocessingml/instr_text.rb +20 -5
  108. data/lib/uniword/wordprocessingml/level.rb +2 -0
  109. data/lib/uniword/wordprocessingml/mar_bottom.rb +17 -0
  110. data/lib/uniword/wordprocessingml/mar_left.rb +17 -0
  111. data/lib/uniword/wordprocessingml/mar_right.rb +17 -0
  112. data/lib/uniword/wordprocessingml/mar_top.rb +17 -0
  113. data/lib/uniword/wordprocessingml/num.rb +4 -0
  114. data/lib/uniword/wordprocessingml/numbering.rb +1 -22
  115. data/lib/uniword/wordprocessingml/optimize_for_browser.rb +14 -0
  116. data/lib/uniword/wordprocessingml/page_defaults.rb +39 -0
  117. data/lib/uniword/wordprocessingml/paragraph.rb +16 -13
  118. data/lib/uniword/wordprocessingml/paragraph_properties.rb +12 -8
  119. data/lib/uniword/wordprocessingml/run.rb +32 -36
  120. data/lib/uniword/wordprocessingml/run_properties/merging.rb +45 -0
  121. data/lib/uniword/wordprocessingml/run_properties.rb +8 -5
  122. data/lib/uniword/wordprocessingml/section_properties.rb +3 -3
  123. data/lib/uniword/wordprocessingml/separator_char.rb +21 -0
  124. data/lib/uniword/wordprocessingml/settings.rb +19 -17
  125. data/lib/uniword/wordprocessingml/styles/style_definition.rb +1 -1
  126. data/lib/uniword/wordprocessingml/styles/style_library.rb +16 -0
  127. data/lib/uniword/wordprocessingml/table_defaults.rb +44 -0
  128. data/lib/uniword/wordprocessingml/text.rb +8 -2
  129. data/lib/uniword/wordprocessingml/web_div.rb +41 -0
  130. data/lib/uniword/wordprocessingml/web_divs.rb +18 -0
  131. data/lib/uniword/wordprocessingml/web_encoding.rb +17 -0
  132. data/lib/uniword/wordprocessingml/web_settings.rb +5 -21
  133. data/lib/uniword/wordprocessingml/zoom.rb +2 -0
  134. data/lib/uniword/wordprocessingml.rb +23 -0
  135. data/lib/uniword.rb +27 -0
  136. metadata +47 -70
  137. data/lib/uniword/math/accent.rb +0 -25
  138. data/lib/uniword/math/accent_properties.rb +0 -25
  139. data/lib/uniword/math/argument_properties.rb +0 -22
  140. data/lib/uniword/math/bar.rb +0 -25
  141. data/lib/uniword/math/bar_properties.rb +0 -25
  142. data/lib/uniword/math/begin_char.rb +0 -22
  143. data/lib/uniword/math/border_box.rb +0 -25
  144. data/lib/uniword/math/border_box_properties.rb +0 -39
  145. data/lib/uniword/math/box.rb +0 -25
  146. data/lib/uniword/math/box_properties.rb +0 -33
  147. data/lib/uniword/math/char.rb +0 -22
  148. data/lib/uniword/math/control_properties.rb +0 -27
  149. data/lib/uniword/math/degree.rb +0 -26
  150. data/lib/uniword/math/delimiter.rb +0 -25
  151. data/lib/uniword/math/delimiter_properties.rb +0 -33
  152. data/lib/uniword/math/denominator.rb +0 -26
  153. data/lib/uniword/math/element.rb +0 -61
  154. data/lib/uniword/math/end_char.rb +0 -22
  155. data/lib/uniword/math/equation_array.rb +0 -25
  156. data/lib/uniword/math/equation_array_properties.rb +0 -33
  157. data/lib/uniword/math/fraction.rb +0 -27
  158. data/lib/uniword/math/fraction_properties.rb +0 -25
  159. data/lib/uniword/math/function.rb +0 -27
  160. data/lib/uniword/math/function_name.rb +0 -26
  161. data/lib/uniword/math/function_properties.rb +0 -23
  162. data/lib/uniword/math/group_char.rb +0 -25
  163. data/lib/uniword/math/group_char_properties.rb +0 -29
  164. data/lib/uniword/math/lim.rb +0 -26
  165. data/lib/uniword/math/lower_limit.rb +0 -27
  166. data/lib/uniword/math/lower_limit_properties.rb +0 -23
  167. data/lib/uniword/math/math_break.rb +0 -22
  168. data/lib/uniword/math/math_font.rb +0 -22
  169. data/lib/uniword/math/math_properties.rb +0 -53
  170. data/lib/uniword/math/math_run.rb +0 -42
  171. data/lib/uniword/math/math_run_properties.rb +0 -37
  172. data/lib/uniword/math/math_simple_int_val.rb +0 -24
  173. data/lib/uniword/math/math_simple_val.rb +0 -24
  174. data/lib/uniword/math/math_style.rb +0 -22
  175. data/lib/uniword/math/math_text.rb +0 -23
  176. data/lib/uniword/math/matrix.rb +0 -25
  177. data/lib/uniword/math/matrix_column.rb +0 -23
  178. data/lib/uniword/math/matrix_column_properties.rb +0 -24
  179. data/lib/uniword/math/matrix_columns.rb +0 -23
  180. data/lib/uniword/math/matrix_properties.rb +0 -37
  181. data/lib/uniword/math/matrix_row.rb +0 -23
  182. data/lib/uniword/math/nary.rb +0 -29
  183. data/lib/uniword/math/nary_properties.rb +0 -33
  184. data/lib/uniword/math/numerator.rb +0 -26
  185. data/lib/uniword/math/o_math.rb +0 -65
  186. data/lib/uniword/math/o_math_para.rb +0 -25
  187. data/lib/uniword/math/o_math_para_properties.rb +0 -22
  188. data/lib/uniword/math/phantom.rb +0 -25
  189. data/lib/uniword/math/phantom_properties.rb +0 -33
  190. data/lib/uniword/math/pre_sub_superscript.rb +0 -29
  191. data/lib/uniword/math/pre_sub_superscript_properties.rb +0 -23
  192. data/lib/uniword/math/radical.rb +0 -27
  193. data/lib/uniword/math/radical_properties.rb +0 -25
  194. data/lib/uniword/math/separator_char.rb +0 -22
  195. data/lib/uniword/math/sub.rb +0 -26
  196. data/lib/uniword/math/sub_superscript.rb +0 -29
  197. data/lib/uniword/math/sub_superscript_properties.rb +0 -25
  198. data/lib/uniword/math/subscript.rb +0 -27
  199. data/lib/uniword/math/subscript_properties.rb +0 -23
  200. data/lib/uniword/math/sup.rb +0 -26
  201. data/lib/uniword/math/superscript.rb +0 -27
  202. data/lib/uniword/math/superscript_properties.rb +0 -23
  203. data/lib/uniword/math/upper_limit.rb +0 -27
  204. data/lib/uniword/math/upper_limit_properties.rb +0 -23
@@ -34,5 +34,7 @@ module Uniword
34
34
  "#{__dir__}/transformation/mhtml_element_renderer"
35
35
  autoload :MhtmlMetadataBuilder,
36
36
  "#{__dir__}/transformation/mhtml_metadata_builder"
37
+ autoload :YamlCssGenerator,
38
+ "#{__dir__}/transformation/yaml_css_generator"
37
39
  end
38
40
  end
@@ -133,10 +133,9 @@ module Uniword
133
133
  return [] unless document.is_a?(Uniword::Wordprocessingml::DocumentRoot)
134
134
 
135
135
  document.paragraphs.select do |p|
136
- p.is_a?(Lutaml::Model::Serializable) && p.class.attributes.key?(:style) && p.style&.match?(/^Heading/)
136
+ p.style&.to_s&.match?(/^Heading/)
137
137
  end.filter_map do |p|
138
- # Generate bookmark from heading text
139
- p.is_a?(Lutaml::Model::Serializable) && p.class.attributes.key?(:text) ? heading_to_bookmark(p.text) : nil
138
+ heading_to_bookmark(p.text)
140
139
  end
141
140
  end
142
141
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uniword
4
- VERSION = "1.0.10"
4
+ VERSION = "1.2.4"
5
5
  end
@@ -103,7 +103,8 @@ module Uniword
103
103
  # @param run [Run] The run to visit
104
104
  # @return [void]
105
105
  def visit_run(run)
106
- @text_parts << run.text if run.text
106
+ text = run.text_string
107
+ @text_parts << text unless text.empty?
107
108
  end
108
109
 
109
110
  # Visit an image element.
@@ -108,11 +108,11 @@ module Uniword
108
108
  return false unless paragraph.properties
109
109
  return false unless paragraph.properties.is_a?(Uniword::Wordprocessingml::ParagraphProperties)
110
110
 
111
- paragraph.properties.style.to_s == "UniwordWatermark"
111
+ paragraph.style == "UniwordWatermark"
112
112
  end
113
113
 
114
114
  def extract_watermark_text(paragraph)
115
- paragraph.runs.map { |r| r.text.to_s }.join
115
+ paragraph.runs.map(&:text_string).join
116
116
  end
117
117
  end
118
118
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class AllowPng < Lutaml::Model::Serializable
8
+ xml do
9
+ element "allowPNG"
10
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
11
+ end
12
+ end
13
+ end
14
+ end
@@ -66,35 +66,70 @@ module Uniword
66
66
  sync_element_order
67
67
  end
68
68
 
69
+ # Record a programmatically-added element in element_order.
70
+ # Called by DocumentBuilder to preserve insertion order when
71
+ # interleaving paragraphs, tables, and SDTs.
72
+ def append_to_element_order(element_name)
73
+ entry = Lutaml::Xml::Element.new("Element", element_name)
74
+ if element_order.nil? || element_order.empty?
75
+ self.element_order = [entry]
76
+ else
77
+ self.element_order = element_order + [entry]
78
+ end
79
+ end
80
+
69
81
  private
70
82
 
71
83
  def sync_element_order
72
84
  return if element_order.nil? || element_order.empty?
73
85
 
74
- counts = element_order.each_with_object(Hash.new(0)) do |e, h|
75
- h[e.name] += 1
86
+ # lutaml-model freezes element_order after XML parsing.
87
+ # Build a mutable copy to append missing elements.
88
+ new_entries = []
89
+
90
+ # Count how many p/tbl/sdt entries exist in element_order
91
+ ordered_p_count = element_order.count { |e| e.name == "p" }
92
+ ordered_tbl_count = element_order.count { |e| e.name == "tbl" }
93
+ ordered_sdt_count = element_order.count { |e| e.name == "sdt" }
94
+ ordered_bookmark_start_count = element_order.count do |e|
95
+ e.name == "bookmarkStart"
96
+ end
97
+ ordered_bookmark_end_count = element_order.count do |e|
98
+ e.name == "bookmarkEnd"
76
99
  end
77
100
 
78
- append_missing_elements("p", paragraphs.size - counts["p"])
79
- append_missing_elements("tbl", tables.size - counts["tbl"])
80
- append_missing_elements("sdt",
81
- structured_document_tags.size - counts["sdt"])
82
- append_missing_elements("bookmarkStart",
83
- bookmark_starts.size - counts["bookmarkStart"])
84
- append_missing_elements("bookmarkEnd",
85
- bookmark_ends.size - counts["bookmarkEnd"])
101
+ # Collect missing paragraphs
102
+ (paragraphs.size - ordered_p_count).times do
103
+ new_entries << Lutaml::Xml::Element.new("Element", "p")
104
+ end
86
105
 
87
- return unless section_properties && counts["sectPr"].zero?
106
+ # Collect missing tables
107
+ (tables.size - ordered_tbl_count).times do
108
+ new_entries << Lutaml::Xml::Element.new("Element", "tbl")
109
+ end
88
110
 
89
- element_order << build_order_element("sectPr")
90
- end
111
+ # Collect missing structured document tags
112
+ (structured_document_tags.size - ordered_sdt_count).times do
113
+ new_entries << Lutaml::Xml::Element.new("Element", "sdt")
114
+ end
91
115
 
92
- def append_missing_elements(name, count)
93
- count.times { element_order << build_order_element(name) }
94
- end
116
+ # Collect missing bookmark starts
117
+ (bookmark_starts.size - ordered_bookmark_start_count).times do
118
+ new_entries << Lutaml::Xml::Element.new("Element", "bookmarkStart")
119
+ end
120
+
121
+ # Collect missing bookmark ends
122
+ (bookmark_ends.size - ordered_bookmark_end_count).times do
123
+ new_entries << Lutaml::Xml::Element.new("Element", "bookmarkEnd")
124
+ end
125
+
126
+ # Ensure section_properties is in element_order if present
127
+ if section_properties && element_order.none? { |e| e.name == "sectPr" }
128
+ new_entries << Lutaml::Xml::Element.new("Element", "sectPr")
129
+ end
95
130
 
96
- def build_order_element(name)
97
- Lutaml::Xml::Element.new("Element", name)
131
+ # Replace frozen array with mutable copy containing new entries
132
+ self.element_order = element_order + new_entries unless new_entries.empty?
98
133
  end
99
134
  end
100
135
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class BodyDiv < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+
10
+ xml do
11
+ element "bodyDiv"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ map_attribute "val", to: :val
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class DivBorder < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+ attribute :sz, :string
10
+ attribute :space, :string
11
+ attribute :color, :string
12
+
13
+ xml do
14
+ element "border"
15
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
16
+ map_attribute "val", to: :val
17
+ map_attribute "sz", to: :sz
18
+ map_attribute "space", to: :space
19
+ map_attribute "color", to: :color
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class DivBorders < Lutaml::Model::Serializable
8
+ attribute :top, DivBorder
9
+ attribute :left, DivBorder
10
+ attribute :bottom, DivBorder
11
+ attribute :right, DivBorder
12
+
13
+ xml do
14
+ element "divBdr"
15
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
16
+ mixed_content
17
+ map_element "top", to: :top, render_nil: false
18
+ map_element "left", to: :left, render_nil: false
19
+ map_element "bottom", to: :bottom, render_nil: false
20
+ map_element "right", to: :right, render_nil: false
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ # Defined as a stub first to break the WebDiv ↔ DivsChild mutual recursion.
8
+ # The :div attribute is added after WebDiv is defined.
9
+ class DivsChild < Lutaml::Model::Serializable
10
+ xml do
11
+ element "divsChild"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ mixed_content
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,9 +2,6 @@
2
2
 
3
3
  require "lutaml/model"
4
4
 
5
- require_relative "../document_input"
6
- require_relative "document_root/feature_facade"
7
-
8
5
  module Uniword
9
6
  module Wordprocessingml
10
7
  # Root element of a WordprocessingML document
@@ -12,6 +9,8 @@ module Uniword
12
9
  # Generated from OOXML schema: wordprocessingml.yml
13
10
  # Element: <w:document>
14
11
  class DocumentRoot < Lutaml::Model::Serializable
12
+ autoload :FeatureFacade, "#{__dir__}/document_root/feature_facade"
13
+
15
14
  include FeatureFacade
16
15
  include Uniword::DocumentInput
17
16
 
@@ -112,9 +111,13 @@ module Uniword
112
111
  attr_accessor :chart_parts
113
112
  # Bibliography sources for sources.xml
114
113
  attr_accessor :bibliography_sources
114
+ # OLE/embedded object binaries (word/embeddings/*)
115
+ attr_accessor :embeddings
115
116
  # Round-trip parts (copied from DocxPackage during load)
116
117
  attr_accessor :settings, :font_table, :web_settings, :document_rels, :theme_rels,
117
118
  :package_rels, :content_types, :custom_properties, :custom_xml_items
119
+ # Central ID allocator — preserves IDs across build/save cycle
120
+ attr_accessor :allocator
118
121
 
119
122
  # Writers for properties that have lazy-initialized getters
120
123
  # (removing from attr_accessor to avoid shadowing custom getters)
@@ -19,7 +19,7 @@ module Uniword
19
19
  mixed_content
20
20
 
21
21
  map_attribute "id", to: :id
22
- map_attribute "type", to: :type
22
+ map_attribute "type", to: :type, render_nil: false
23
23
  map_element "p", to: :paragraphs, render_nil: false
24
24
  end
25
25
  end
@@ -9,6 +9,7 @@ module Uniword
9
9
  # Generated from OOXML schema: wordprocessingml.yml
10
10
  # Element: <w:endnotes>
11
11
  class Endnotes < Lutaml::Model::Serializable
12
+ attribute :mc_ignorable, Uniword::Ooxml::Types::McIgnorable
12
13
  attribute :endnote_entries, Endnote, collection: true,
13
14
  initialize_empty: true
14
15
 
@@ -17,6 +18,9 @@ module Uniword
17
18
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
18
19
  mixed_content
19
20
 
21
+ namespace_scope Uniword::Ooxml::Namespaces::DOCUMENT_PART_SCOPES
22
+
23
+ map_attribute "Ignorable", to: :mc_ignorable, render_nil: false
20
24
  map_element "endnote", to: :endnote_entries, render_nil: false
21
25
  end
22
26
 
@@ -9,6 +9,7 @@ module Uniword
9
9
  # Generated from OOXML schema: wordprocessingml.yml
10
10
  # Element: <w:ftr>
11
11
  class Footer < Lutaml::Model::Serializable
12
+ attribute :mc_ignorable, Uniword::Ooxml::Types::McIgnorable
12
13
  attribute :paragraphs, Paragraph, collection: true, initialize_empty: true
13
14
  attribute :tables, Table, collection: true, initialize_empty: true
14
15
 
@@ -17,6 +18,9 @@ module Uniword
17
18
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
18
19
  mixed_content
19
20
 
21
+ namespace_scope Uniword::Ooxml::Namespaces::DOCUMENT_PART_SCOPES
22
+
23
+ map_attribute "Ignorable", to: :mc_ignorable, render_nil: false
20
24
  map_element "p", to: :paragraphs, render_nil: false
21
25
  map_element "tbl", to: :tables, render_nil: false
22
26
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require_relative "../properties/relationship_id"
5
4
 
6
5
  module Uniword
7
6
  module Wordprocessingml
@@ -19,7 +19,7 @@ module Uniword
19
19
  mixed_content
20
20
 
21
21
  map_attribute "id", to: :id
22
- map_attribute "type", to: :type
22
+ map_attribute "type", to: :type, render_nil: false
23
23
  map_element "p", to: :paragraphs, render_nil: false
24
24
  end
25
25
  end
@@ -9,6 +9,7 @@ module Uniword
9
9
  # Generated from OOXML schema: wordprocessingml.yml
10
10
  # Element: <w:footnotes>
11
11
  class Footnotes < Lutaml::Model::Serializable
12
+ attribute :mc_ignorable, Uniword::Ooxml::Types::McIgnorable
12
13
  attribute :footnote_entries, Footnote, collection: true,
13
14
  initialize_empty: true
14
15
 
@@ -17,6 +18,9 @@ module Uniword
17
18
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
18
19
  mixed_content
19
20
 
21
+ namespace_scope Uniword::Ooxml::Namespaces::DOCUMENT_PART_SCOPES
22
+
23
+ map_attribute "Ignorable", to: :mc_ignorable, render_nil: false
20
24
  map_element "footnote", to: :footnote_entries, render_nil: false
21
25
  end
22
26
 
@@ -9,6 +9,7 @@ module Uniword
9
9
  # Generated from OOXML schema: wordprocessingml.yml
10
10
  # Element: <w:hdr>
11
11
  class Header < Lutaml::Model::Serializable
12
+ attribute :mc_ignorable, Uniword::Ooxml::Types::McIgnorable
12
13
  attribute :paragraphs, Paragraph, collection: true, initialize_empty: true
13
14
  attribute :tables, Table, collection: true, initialize_empty: true
14
15
 
@@ -17,6 +18,9 @@ module Uniword
17
18
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
18
19
  mixed_content
19
20
 
21
+ namespace_scope Uniword::Ooxml::Namespaces::DOCUMENT_PART_SCOPES
22
+
23
+ map_attribute "Ignorable", to: :mc_ignorable, render_nil: false
20
24
  map_element "p", to: :paragraphs, render_nil: false
21
25
  map_element "tbl", to: :tables, render_nil: false
22
26
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require_relative "../properties/relationship_id"
5
4
 
6
5
  module Uniword
7
6
  module Wordprocessingml
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require_relative "../has_run_position"
4
+ require "uniword/ooxml/types/relationship_id"
5
5
 
6
6
  module Uniword
7
7
  module Wordprocessingml
@@ -12,7 +12,7 @@ module Uniword
12
12
  class Hyperlink < Lutaml::Model::Serializable
13
13
  include Uniword::HasRunPosition
14
14
 
15
- attribute :id, :string
15
+ attribute :id, Ooxml::Types::RelationshipId
16
16
  attribute :anchor, :string
17
17
  attribute :tooltip, :string
18
18
  attribute :history, Uniword::Properties::HistoryValue
@@ -9,7 +9,7 @@ module Uniword
9
9
  # Generated from OOXML schema: wordprocessingml.yml
10
10
  # Element: <w:instrText>
11
11
  class InstrText < Lutaml::Model::Serializable
12
- attribute :text, :string
12
+ attribute :content, :string, collection: true, initialize_empty: true
13
13
  attribute :xml_space, :string
14
14
 
15
15
  xml do
@@ -17,17 +17,32 @@ module Uniword
17
17
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
18
18
  mixed_content
19
19
 
20
+ map_content to: :content
20
21
  map_attribute "xml:space", to: :xml_space
21
- map_element "text", to: :text, render_nil: false
22
22
  end
23
23
 
24
24
  def initialize(attrs = {})
25
- if attrs[:text].is_a?(String) && (attrs[:text].start_with?(" ") || attrs[:text].end_with?(" ") || attrs[:text].include?("\t"))
26
- attrs[:xml_space] =
27
- "preserve"
25
+ if attrs.is_a?(Hash)
26
+ text_val = attrs.delete(:text) || attrs[:content]
27
+ if text_val.is_a?(String)
28
+ attrs[:xml_space] = "preserve" if Text.preserve_whitespace?(text_val)
29
+ attrs[:content] = [text_val] unless attrs.key?(:content)
30
+ end
28
31
  end
29
32
  super
30
33
  end
34
+
35
+ def text
36
+ content&.join
37
+ end
38
+
39
+ def text=(value)
40
+ self.content = value.is_a?(Array) ? value : [value.to_s]
41
+ end
42
+
43
+ def to_s
44
+ text.to_s
45
+ end
31
46
  end
32
47
  end
33
48
  end
@@ -66,6 +66,7 @@ module Uniword
66
66
  class Level < Lutaml::Model::Serializable
67
67
  attribute :ilvl, :integer
68
68
  attribute :tentative, :string
69
+ attribute :tplc, :string
69
70
  attribute :start, Start
70
71
  attribute :numFmt, NumFmt
71
72
  attribute :pStyle, PStyle
@@ -85,6 +86,7 @@ module Uniword
85
86
 
86
87
  map_attribute "ilvl", to: :ilvl
87
88
  map_attribute "tentative", to: :tentative, render_nil: false
89
+ map_attribute "tplc", to: :tplc, render_nil: false
88
90
  map_element "start", to: :start, render_nil: false
89
91
  map_element "numFmt", to: :numFmt, render_nil: false
90
92
  map_element "pStyle", to: :pStyle, render_nil: false
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class MarBottom < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+
10
+ xml do
11
+ element "marBottom"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ map_attribute "val", to: :val
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class MarLeft < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+
10
+ xml do
11
+ element "marLeft"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ map_attribute "val", to: :val
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class MarRight < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+
10
+ xml do
11
+ element "marRight"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ map_attribute "val", to: :val
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class MarTop < Lutaml::Model::Serializable
8
+ attribute :val, :string
9
+
10
+ xml do
11
+ element "marTop"
12
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
13
+ map_attribute "val", to: :val
14
+ end
15
+ end
16
+ end
17
+ end
@@ -10,6 +10,7 @@ module Uniword
10
10
  # Element: <w:num>
11
11
  class Num < Lutaml::Model::Serializable
12
12
  attribute :numId, :integer
13
+ attribute :durable_id, :string
13
14
  attribute :abstractNumId, AbstractNumId
14
15
  attribute :lvlOverrides, LevelOverride, collection: true,
15
16
  initialize_empty: true
@@ -20,6 +21,9 @@ module Uniword
20
21
  mixed_content
21
22
 
22
23
  map_attribute "numId", to: :numId
24
+ map_attribute "durableId", to: :durable_id,
25
+ namespace: Uniword::Ooxml::Namespaces::Word2016Cid,
26
+ render_nil: false
23
27
  map_element "abstractNumId", to: :abstractNumId, render_nil: false
24
28
  map_element "lvlOverride", to: :lvlOverrides, render_nil: false
25
29
  end
@@ -18,28 +18,7 @@ module Uniword
18
18
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
19
19
  mixed_content
20
20
 
21
- # Force namespace declarations on root for mc:Ignorable prefixes
22
- namespace_scope [
23
- { namespace: Uniword::Ooxml::Namespaces::MarkupCompatibility,
24
- declare: :always },
25
- { namespace: Uniword::Ooxml::Namespaces::Word2010, declare: :always },
26
- { namespace: Uniword::Ooxml::Namespaces::Word2012, declare: :always },
27
- { namespace: Uniword::Ooxml::Namespaces::Word2015Symex,
28
- declare: :always },
29
- { namespace: Uniword::Ooxml::Namespaces::Word2016Cid,
30
- declare: :always },
31
- { namespace: Uniword::Ooxml::Namespaces::Word2018, declare: :always },
32
- { namespace: Uniword::Ooxml::Namespaces::Word2018Cex,
33
- declare: :always },
34
- { namespace: Uniword::Ooxml::Namespaces::Word2020SdtDataHash,
35
- declare: :always },
36
- { namespace: Uniword::Ooxml::Namespaces::Word2024SdtFormatLock,
37
- declare: :always },
38
- { namespace: Uniword::Ooxml::Namespaces::Word2023Du,
39
- declare: :always },
40
- { namespace: Uniword::Ooxml::Namespaces::Word2010Drawing,
41
- declare: :always },
42
- ]
21
+ namespace_scope Uniword::Ooxml::Namespaces::DOCUMENT_PART_SCOPES
43
22
 
44
23
  map_element "abstractNum", to: :abstractNums, render_nil: false
45
24
  map_element "num", to: :nums, render_nil: false
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Uniword
6
+ module Wordprocessingml
7
+ class OptimizeForBrowser < Lutaml::Model::Serializable
8
+ xml do
9
+ element "optimizeForBrowser"
10
+ namespace Uniword::Ooxml::Namespaces::WordProcessingML
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uniword
4
+ module Wordprocessingml
5
+ # Shared page layout defaults.
6
+ #
7
+ # Provides canonical values for page size, margins, columns, and docGrid
8
+ # used by both builder and reconciler.
9
+ module PageDefaults
10
+ LETTER_WIDTH = 12_240
11
+ LETTER_HEIGHT = 15_840
12
+
13
+ DEFAULT_MARGINS = {
14
+ top: 1440, right: 1440, bottom: 1440, left: 1440,
15
+ header: 720, footer: 720, gutter: 0,
16
+ }.freeze
17
+
18
+ DEFAULT_COL_SPACE = 720
19
+ DEFAULT_LINE_PITCH = 360
20
+
21
+ def self.default_page_size
22
+ Wordprocessingml::PageSize.new(width: LETTER_WIDTH,
23
+ height: LETTER_HEIGHT)
24
+ end
25
+
26
+ def self.default_page_margins
27
+ Wordprocessingml::PageMargins.new(**DEFAULT_MARGINS)
28
+ end
29
+
30
+ def self.default_columns
31
+ Wordprocessingml::Columns.new(space: DEFAULT_COL_SPACE)
32
+ end
33
+
34
+ def self.default_doc_grid
35
+ Wordprocessingml::DocGrid.new(line_pitch: DEFAULT_LINE_PITCH)
36
+ end
37
+ end
38
+ end
39
+ end