uniword 1.2.4 → 1.2.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1517a752442fd3914efbcc8f94130cf6f4983c110807b0790f03bebf9424d875
4
- data.tar.gz: a88ecadccf094ffd2c1031d32e13ded47f361b98ca0d594c373bd48cc74f6898
3
+ metadata.gz: d8cdb6f45c08ae845ce242ca0a0140e7784413d9fe1b552b56eefd8040f9b03c
4
+ data.tar.gz: 6603afb7881e218ed635e77349cff132817086ec1399bd2a5157ce487907165f
5
5
  SHA512:
6
- metadata.gz: d728a6dc5a0df3560cc607281fb6ca8dd384c56d75247d7ca4b57a1791a15312b8fa8a2e5a8ae18c4ec60ff0574f76fafde2e68994c4b13b326b329cb5fd134e
7
- data.tar.gz: cd7339df777bb848a7ad69c09b3d44fc0478fd9ece6a9f4d9c79ebb3114fa205824487f9bab85753338f24ac8aa22345319a254fc6a841d9f54117d2c0f07945
6
+ metadata.gz: c4c71185ce70622298500cb9512e6e0ab5f5b4509783f3273cfe8ac8828ec44159b875d9bf06b3d8f0ac346791f5ce779050e3030858d2320477ee0e89d6c7ec
7
+ data.tar.gz: 849da67a5a82968042f85239b1b2a536f7f85056e657f9e8b7c0b3487141e956b8903232efa1478dc476174d51e11f7580557b8ee5bd0d8ac93a88eeb8fe723b
@@ -36,6 +36,8 @@ module Uniword
36
36
 
37
37
  attr_reader :chart_type, :title_text, :series_list
38
38
 
39
+ attr_reader :show_legend, :width, :height, :series_list
40
+
39
41
  def initialize(chart_type: :bar)
40
42
  @chart_type = chart_type
41
43
  @title_text = nil
@@ -17,7 +17,14 @@ module Uniword
17
17
  Properties::Border.new(color: value, style: "single",
18
18
  size: 4)
19
19
  end
20
- props.borders.public_send("#{side}=", border)
20
+ case side
21
+ when :top then props.borders.top = border
22
+ when :bottom then props.borders.bottom = border
23
+ when :left then props.borders.left = border
24
+ when :right then props.borders.right = border
25
+ when :between then props.borders.between = border
26
+ when :bar then props.borders.bar = border
27
+ end
21
28
  end
22
29
  self
23
30
  end
@@ -2,19 +2,6 @@
2
2
 
3
3
  require "thor"
4
4
  require "rainbow"
5
- require_relative "styleset_cli"
6
- require_relative "resources_cli"
7
- require_relative "theme_cli"
8
- require_relative "generate_cli"
9
- require_relative "review_cli"
10
- require_relative "template_cli"
11
- require_relative "diff_cli"
12
- require_relative "toc_cli"
13
- require_relative "images_cli"
14
- require_relative "spellcheck_cli"
15
- require_relative "headers_cli"
16
- require_relative "watermark_cli"
17
- require_relative "protect_cli"
18
5
 
19
6
  module Uniword
20
7
  # Command-line interface for Uniword.
@@ -77,12 +77,12 @@ module Uniword
77
77
 
78
78
  def alloc_para_id
79
79
  @para_counter += 1
80
- Digest::SHA256.hexdigest("para:#{@para_counter}").upcase[0, 12]
80
+ Digest::SHA256.hexdigest("para:#{@para_counter}").upcase[0, 8]
81
81
  end
82
82
 
83
83
  def alloc_rsid
84
84
  @rsid_counter += 1
85
- Digest::SHA256.hexdigest("rsid:#{@rsid_counter}").upcase[0, 12]
85
+ Digest::SHA256.hexdigest("rsid:#{@rsid_counter}").upcase[0, 8]
86
86
  end
87
87
 
88
88
  # Seed from a relationships collection — preserves existing rIds.
@@ -69,11 +69,11 @@ document_rels)
69
69
  end
70
70
  if app_properties
71
71
  content["docProps/app.xml"] =
72
- app_properties.to_xml(DOCX_PROPS_OPTIONS.dup)
72
+ add_standalone(app_properties.to_xml(DOCX_PROPS_OPTIONS.dup))
73
73
  end
74
74
  if custom_properties
75
75
  content["docProps/custom.xml"] =
76
- custom_properties.to_xml(DOCX_PROPS_OPTIONS.dup)
76
+ add_standalone(custom_properties.to_xml(DOCX_PROPS_OPTIONS.dup))
77
77
  end
78
78
 
79
79
  # Custom XML data items
@@ -161,14 +161,24 @@ document_rels)
161
161
  serialize_embeddings(content)
162
162
  end
163
163
 
164
- # Serialize an OOXML document part with standard encoding, single-line output
164
+ # Serialize an OOXML document part with standard encoding, single-line output.
165
+ # All DOCX parts require standalone="yes" in the XML declaration for Word compatibility.
165
166
  def serialize_part(model)
166
- model.to_xml(DOCX_PART_OPTIONS.dup)
167
+ add_standalone(model.to_xml(DOCX_PART_OPTIONS.dup))
167
168
  end
168
169
 
169
170
  # Serialize package infrastructure (rels, content types) with declaration, single-line output
170
171
  def serialize_infrastructure(model)
171
- model.to_xml(DOCX_INFRA_OPTIONS.dup)
172
+ add_standalone(model.to_xml(DOCX_INFRA_OPTIONS.dup))
173
+ end
174
+
175
+ # Ensure the XML declaration includes standalone="yes".
176
+ # lutaml-model omits this by default; Word's strict OPC validation requires it.
177
+ def add_standalone(xml)
178
+ xml.sub(
179
+ %r{<\?xml version="1.0" encoding="UTF-8"\?>},
180
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
181
+ )
172
182
  end
173
183
 
174
184
  private
@@ -98,12 +98,15 @@ module Uniword
98
98
  charset: Wordprocessingml::Charset.new(val: meta["charset"]),
99
99
  family: Wordprocessingml::Family.new(val: meta["family"]),
100
100
  pitch: Wordprocessingml::Pitch.new(val: meta["pitch"]),
101
- sig: Wordprocessingml::Sig.new(
101
+ )
102
+
103
+ if sig_data["usb0"] || sig_data["csb0"]
104
+ font.sig = Wordprocessingml::Sig.new(
102
105
  usb0: sig_data["usb0"], usb1: sig_data["usb1"],
103
106
  usb2: sig_data["usb2"], usb3: sig_data["usb3"],
104
107
  csb0: sig_data["csb0"], csb1: sig_data["csb1"]
105
- ),
106
- )
108
+ )
109
+ end
107
110
 
108
111
  font.alt_name = Wordprocessingml::AltName.new(val: meta["alt_name"]) if meta["alt_name"]
109
112
  font_table.fonts << font
@@ -111,7 +111,10 @@ module Uniword
111
111
  (package.document&.headers&.values || []).each { |h| parts << h }
112
112
  (package.document&.footers&.values || []).each { |f| parts << f }
113
113
 
114
- parts.each(&:clear_xml_parse_state!)
114
+ parts.each do |part|
115
+ part.import_declaration_plan = nil
116
+ part.pending_plan_root_element = nil
117
+ end
115
118
  end
116
119
  end
117
120
  end
@@ -331,7 +331,6 @@ module Uniword
331
331
  when :fol_hlink then fol_hlink
332
332
  end
333
333
  end
334
- private :color_by_name
335
334
 
336
335
  # Set a color by name
337
336
  #
@@ -98,7 +98,6 @@ module Uniword
98
98
  @theme_elements ||= ThemeElements.new
99
99
  @object_defaults ||= ObjectDefaults.new
100
100
  @extra_clr_scheme_lst ||= ExtraColorSchemeList.new
101
- @ext_lst ||= ExtensionList.new
102
101
  @variants = {}
103
102
  @source_file = nil
104
103
  @media_files ||= {}
@@ -301,7 +301,10 @@ module Uniword
301
301
  def get_attribute_value(element, attr_def)
302
302
  property_name = attr_def.property_name
303
303
 
304
- # Try to get value using property name
304
+ # public_send is the canonical Ruby idiom for schema-driven
305
+ # serialization: reading attribute values by name from any
306
+ # Lutaml::Model::Serializable subclass. The property_name comes
307
+ # from the schema definition, not user input.
305
308
  if element.is_a?(Lutaml::Model::Serializable) && element.class.attributes.key?(property_name)
306
309
  element.public_send(property_name)
307
310
  elsif element.is_a?(Hash) && element.key?(property_name)
@@ -87,7 +87,7 @@ lightness_shift: nil)
87
87
  fol_hlink]
88
88
 
89
89
  color_attrs.each do |attr|
90
- color_obj = color_scheme.public_send(attr)
90
+ color_obj = color_scheme.color_by_name(attr)
91
91
  next unless color_obj&.srgb_clr&.val
92
92
 
93
93
  original = color_obj.srgb_clr.val
@@ -109,6 +109,10 @@ module Uniword
109
109
  if object.is_a?(Hash)
110
110
  object[property.to_sym] || object[property]
111
111
  else
112
+ # public_send is the canonical Ruby idiom for template-driven
113
+ # property access on arbitrary user objects. The property name
114
+ # comes from template syntax and may reference any public
115
+ # reader method on the model.
112
116
  object.public_send(property.to_sym)
113
117
  end
114
118
  end
@@ -182,7 +182,7 @@ module Uniword
182
182
 
183
183
  colors = {}
184
184
  COLOR_KEYS.each do |key|
185
- if (color_ref = word_colors.public_send(key))
185
+ if (color_ref = word_colors.color_by_name(key))
186
186
  colors[key] = extract_hex_color(color_ref)
187
187
  end
188
188
  end
@@ -152,7 +152,10 @@ module Uniword
152
152
  collection_name = note_type == :endnote ? :endnotes : :footnotes
153
153
 
154
154
  if document.is_a?(Uniword::Wordprocessingml::DocumentRoot)
155
- collection = document.public_send(collection_name)
155
+ collection = case collection_name
156
+ when :footnotes then document.footnotes
157
+ when :endnotes then document.endnotes
158
+ end
156
159
 
157
160
  case collection
158
161
  when Hash
@@ -20,7 +20,7 @@ module Uniword
20
20
  RELS_NS = "http://schemas.openxmlformats.org/package/2006/relationships"
21
21
  CT_NS = "http://schemas.openxmlformats.org/package/2006/content-types"
22
22
 
23
- attr_reader :path
23
+ attr_reader :path, :parsed_parts
24
24
 
25
25
  # Initialize context for a DOCX file.
26
26
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uniword
4
- VERSION = "1.2.4"
4
+ VERSION = "1.2.5"
5
5
  end
@@ -218,7 +218,12 @@ module Uniword
218
218
 
219
219
  # Use Uniword logger if available
220
220
  if defined?(Uniword::Logger)
221
- Uniword::Logger.public_send(level, message)
221
+ case level
222
+ when :debug then Uniword::Logger.debug(message)
223
+ when :info then Uniword::Logger.info(message)
224
+ when :warn then Uniword::Logger.warn(message)
225
+ when :error then Uniword::Logger.error(message)
226
+ end
222
227
  elsif %i[warn error].include?(level)
223
228
  # Fall back to standard output
224
229
  puts message
@@ -113,7 +113,7 @@ module Uniword
113
113
  map_element "family", to: :family
114
114
  map_element "notTrueType", to: :not_true_type, render_nil: false
115
115
  map_element "pitch", to: :pitch
116
- map_element "sig", to: :sig
116
+ map_element "sig", to: :sig, render_nil: false
117
117
  end
118
118
  end
119
119
  end
@@ -121,73 +121,43 @@ module Uniword
121
121
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
122
122
  mixed_content
123
123
 
124
- # Style reference (wrapper object)
124
+ # ECMA-376 CT_RPr schema sequence order:
125
+ # rStyle, rFonts, b, bCs, i, iCs, caps, smallCaps, strike, dstrike,
126
+ # outline, shadow, emboss, imprint, noProof, snapToGrid, vanish, webHidden,
127
+ # color, spacing, w, kern, position, sz, szCs, highlight, u, effect, bdr,
128
+ # shd, fitText, vertAlign, rtl, cs, em, lang, eastAsianLayout, specVanish, oMath
125
129
  map_element "rStyle", to: :style, render_nil: false
126
-
127
- # Fonts (complex object)
128
130
  map_element "rFonts", to: :fonts, render_nil: false
129
-
130
- # Font sizes (wrapper objects)
131
- map_element "sz", to: :size, render_nil: false
132
- map_element "szCs", to: :size_cs, render_nil: false
133
-
134
- # Boolean formatting (wrapper objects)
135
131
  map_element "b", to: :bold, render_nil: false
136
132
  map_element "bCs", to: :bold_cs, render_nil: false
137
133
  map_element "i", to: :italic, render_nil: false
138
134
  map_element "iCs", to: :italic_cs, render_nil: false
135
+ map_element "caps", to: :caps, render_nil: false
136
+ map_element "smallCaps", to: :small_caps, render_nil: false
139
137
  map_element "strike", to: :strike, render_nil: false
140
138
  map_element "dstrike", to: :double_strike, render_nil: false
141
- map_element "smallCaps", to: :small_caps, render_nil: false
142
- map_element "caps", to: :caps, render_nil: false
143
- map_element "vanish", to: :hidden, render_nil: false
139
+ map_element "outline", to: :outline, render_nil: false
140
+ map_element "shadow", to: :shadow, render_nil: false
141
+ map_element "emboss", to: :emboss, render_nil: false
142
+ map_element "imprint", to: :imprint, render_nil: false
144
143
  map_element "noProof", to: :no_proof, render_nil: false
144
+ map_element "vanish", to: :hidden, render_nil: false
145
145
  map_element "webHidden", to: :web_hidden, render_nil: false
146
-
147
- # Color (wrapper object)
148
146
  map_element "color", to: :color, render_nil: false
149
-
150
- # Underline (wrapper object)
151
- map_element "u", to: :underline, render_nil: false
152
-
153
- # Highlight (wrapper object)
154
- map_element "highlight", to: :highlight, render_nil: false
155
-
156
- # Vertical alignment (wrapper object)
157
- map_element "vertAlign", to: :vertical_align, render_nil: false
158
-
159
- # Position (wrapper object)
160
- map_element "position", to: :position, render_nil: false
161
-
162
- # Character spacing (wrapper object)
163
147
  map_element "spacing", to: :character_spacing, render_nil: false
164
-
165
- # Kerning (wrapper object)
166
- map_element "kern", to: :kerning, render_nil: false
167
-
168
- # Width scale (wrapper object)
169
148
  map_element "w", to: :width_scale, render_nil: false
170
-
171
- # Emphasis mark (wrapper object)
172
- map_element "em", to: :emphasis_mark, render_nil: false
173
-
174
- # Shading (complex object)
149
+ map_element "kern", to: :kerning, render_nil: false
150
+ map_element "position", to: :position, render_nil: false
151
+ map_element "sz", to: :size, render_nil: false
152
+ map_element "szCs", to: :size_cs, render_nil: false
153
+ map_element "highlight", to: :highlight, render_nil: false
154
+ map_element "u", to: :underline, render_nil: false
175
155
  map_element "shd", to: :shading, render_nil: false
176
-
177
- # Language (complex object)
156
+ map_element "vertAlign", to: :vertical_align, render_nil: false
157
+ map_element "em", to: :emphasis_mark, render_nil: false
178
158
  map_element "lang", to: :language, render_nil: false
179
-
180
- # Text effects (complex objects - basic support)
181
159
  map_element "textFill", to: :text_fill, render_nil: false
182
160
  map_element "textOutline", to: :text_outline, render_nil: false
183
-
184
- # Additional boolean formatting
185
- map_element "shadow", to: :shadow, render_nil: false
186
- map_element "emboss", to: :emboss, render_nil: false
187
- map_element "imprint", to: :imprint, render_nil: false
188
- map_element "outline", to: :outline, render_nil: false
189
-
190
- # W14 namespace elements
191
161
  map_element "ligatures", to: :ligatures, render_nil: false
192
162
  end
193
163
  end
@@ -111,12 +111,12 @@ module Uniword
111
111
  value_map: { to: { true => true, false => :omitted } }
112
112
  map_element "name", to: :name, render_nil: false
113
113
  map_element "basedOn", to: :basedOn, render_nil: false
114
- map_element "next", to: :nextStyle, render_nil: false # Maps XML 'next' to nextStyle attribute
114
+ map_element "next", to: :nextStyle, render_nil: false
115
115
  map_element "link", to: :link, render_nil: false
116
116
  map_element "uiPriority", to: :uiPriority, render_nil: false
117
- map_element "qFormat", to: :qFormat, render_nil: false
118
117
  map_element "semiHidden", to: :semiHidden, render_nil: false
119
118
  map_element "unhideWhenUsed", to: :unhideWhenUsed, render_nil: false
119
+ map_element "qFormat", to: :qFormat, render_nil: false
120
120
  map_element "rsid", to: :rsid, render_nil: false
121
121
  map_element "pPr", to: :pPr, render_nil: false
122
122
  map_element "rPr", to: :rPr, render_nil: false
@@ -84,26 +84,21 @@ module Uniword
84
84
  namespace Uniword::Ooxml::Namespaces::WordProcessingML
85
85
  mixed_content
86
86
 
87
- # High-priority mappings (Phase 4 Session 1-2)
87
+ # ECMA-376 CT_TblPrBase schema sequence:
88
+ # tblStyle, tblpPr, tblOverlap, bidiVisual, tblStyleRowBandSize,
89
+ # tblStyleColBandSize, tblW, jc, tblCellSpacing, tblInd, tblBorders,
90
+ # shd, tblLayout, tblCellMar, tblLook, tblCaption, tblDescription
91
+ map_element "tblStyle", to: :style, render_nil: false
88
92
  map_element "tblW", to: :table_width, render_nil: false
93
+ map_element "jc", to: :alignment, render_nil: false
94
+ map_element "tblCellSpacing", to: :cell_spacing, render_nil: false
95
+ map_element "tblInd", to: :table_indent, render_nil: false
96
+ map_element "tblBorders", to: :table_borders, render_nil: false
89
97
  map_element "shd", to: :shading, render_nil: false
98
+ map_element "tblLayout", to: :table_layout, render_nil: false
90
99
  map_element "tblCellMar", to: :table_cell_margin, render_nil: false
91
100
  map_element "tblLook", to: :table_look, render_nil: false
92
101
  map_element "tblCaption", to: :caption, render_nil: false
93
-
94
- # Table indentation - critical for table styles
95
- map_element "tblInd", to: :table_indent, render_nil: false
96
- # Table cell spacing
97
- map_element "tblCellSpacing", to: :cell_spacing, render_nil: false
98
- # Table alignment
99
- map_element "jc", to: :alignment, render_nil: false
100
- # Table layout
101
- map_element "tblLayout", to: :table_layout, render_nil: false
102
- # Table style reference
103
- map_element "tblStyle", to: :style, render_nil: false
104
-
105
- # Table borders
106
- map_element "tblBorders", to: :table_borders, render_nil: false
107
102
  end
108
103
 
109
104
  def initialize(attrs = {})
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uniword
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-15 00:00:00.000000000 Z
11
+ date: 2026-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger