uniword 1.0.8 → 1.0.9
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 +4 -4
- data/lib/uniword/builder/comment_builder.rb +2 -1
- data/lib/uniword/document_input.rb +7 -0
- data/lib/uniword/document_writer.rb +1 -5
- data/lib/uniword/docx/reconciler.rb +1 -0
- data/lib/uniword/format_converter.rb +4 -19
- data/lib/uniword/has_run_position.rb +9 -0
- data/lib/uniword/math/o_math.rb +3 -0
- data/lib/uniword/mhtml/document.rb +18 -0
- data/lib/uniword/properties/bold.rb +3 -33
- data/lib/uniword/properties/boolean_element_factory.rb +73 -0
- data/lib/uniword/properties/boolean_formatting.rb +15 -215
- data/lib/uniword/properties/italic.rb +3 -33
- data/lib/uniword/properties.rb +8 -3
- data/lib/uniword/transformation/mhtml_element_renderer.rb +1 -1
- data/lib/uniword/version.rb +1 -1
- data/lib/uniword/wordprocessingml/document_root.rb +11 -0
- data/lib/uniword/wordprocessingml/hyperlink.rb +3 -0
- metadata +5 -3
- data/lib/uniword/ooxml/types/on_off_type.rb +0 -64
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8b3b37b9a1642f94a634c42b754630ca35cd7167ddc1415223dd65848a379c48
|
|
4
|
+
data.tar.gz: 011ddc8e381521e2d161cd0cf9fd0dd9eee791e9f28026fd63e89cf9386bfa03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1c6c8785a7fe56480f0d7bdda19ec56e50704653016d4146c561e401c8e98b856cf99a1205411521b78cd19b701e794dfbc75c4d4c844b87e2b8fe3d44fb514e
|
|
7
|
+
data.tar.gz: 9275ea155ee7af2ee9cd0e24d6534a0124f0f8501583206fb98eb3c63e7736c280552336a47bad97a31e50b235805c5fba904d1a80c0cee9bbe6f216f7e49f02
|
|
@@ -11,7 +11,8 @@ module Uniword
|
|
|
11
11
|
class CommentBuilder
|
|
12
12
|
attr_reader :model
|
|
13
13
|
|
|
14
|
-
def initialize(model: nil, author: nil, comment_id: nil, date: nil,
|
|
14
|
+
def initialize(model: nil, author: nil, comment_id: nil, date: nil,
|
|
15
|
+
initials: nil)
|
|
15
16
|
@model = model || Comment.new(
|
|
16
17
|
author: author,
|
|
17
18
|
comment_id: comment_id,
|
|
@@ -136,11 +136,7 @@ module Uniword
|
|
|
136
136
|
# @raise [ArgumentError] if document is invalid
|
|
137
137
|
def validate_document(doc)
|
|
138
138
|
raise ArgumentError, "Document cannot be nil" if doc.nil?
|
|
139
|
-
|
|
140
|
-
# Accept OOXML Document
|
|
141
|
-
return if doc.is_a?(Uniword::Wordprocessingml::DocumentRoot)
|
|
142
|
-
# Accept MHTML Document
|
|
143
|
-
return if doc.is_a?(Uniword::Mhtml::Document)
|
|
139
|
+
return if doc.is_a?(Uniword::DocumentInput)
|
|
144
140
|
|
|
145
141
|
raise ArgumentError, "Must be a Document instance"
|
|
146
142
|
end
|
|
@@ -277,30 +277,15 @@ module Uniword
|
|
|
277
277
|
# @param document [Object] Document (OOXML or MHTML)
|
|
278
278
|
# @return [Hash] Statistics hash
|
|
279
279
|
def document_stats(document)
|
|
280
|
-
|
|
281
|
-
if document.is_a?(Uniword::Wordprocessingml::DocumentRoot) || document.is_a?(Uniword::Wordprocessingml::Body)
|
|
280
|
+
if document.is_a?(Uniword::Wordprocessingml::Body)
|
|
282
281
|
return {
|
|
283
282
|
paragraphs: document.paragraphs.count,
|
|
284
|
-
tables:
|
|
285
|
-
images:
|
|
283
|
+
tables: 0,
|
|
284
|
+
images: 0
|
|
286
285
|
}
|
|
287
286
|
end
|
|
288
287
|
|
|
289
|
-
|
|
290
|
-
html = if document.is_a?(Mhtml::Document) && document.raw_html
|
|
291
|
-
document.raw_html
|
|
292
|
-
elsif document.is_a?(Mhtml::Document) && document.html_content
|
|
293
|
-
document.html_content
|
|
294
|
-
end
|
|
295
|
-
if html
|
|
296
|
-
{
|
|
297
|
-
paragraphs: html.scan(/<p[\s>]/i).count,
|
|
298
|
-
tables: html.scan(/<table/i).count,
|
|
299
|
-
images: html.scan(/<img/i).count
|
|
300
|
-
}
|
|
301
|
-
else
|
|
302
|
-
{ paragraphs: 0, tables: 0, images: 0 }
|
|
303
|
-
end
|
|
288
|
+
document.document_stats
|
|
304
289
|
end
|
|
305
290
|
|
|
306
291
|
# Validate conversion parameters
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uniword
|
|
4
|
+
# Tagging module for elements that track their position among sibling runs.
|
|
5
|
+
# Used by the MHTML renderer to interleave hyperlinks and math objects
|
|
6
|
+
# at the correct position within a paragraph.
|
|
7
|
+
module HasRunPosition
|
|
8
|
+
end
|
|
9
|
+
end
|
data/lib/uniword/math/o_math.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
|
+
require_relative "../has_run_position"
|
|
4
5
|
|
|
5
6
|
module Uniword
|
|
6
7
|
module Math
|
|
@@ -9,6 +10,8 @@ module Uniword
|
|
|
9
10
|
# Generated from OOXML schema: math.yml
|
|
10
11
|
# Element: <m:oMath>
|
|
11
12
|
class OMath < Lutaml::Model::Serializable
|
|
13
|
+
include Uniword::HasRunPosition
|
|
14
|
+
|
|
12
15
|
# Pattern 0: Attributes BEFORE xml mappings
|
|
13
16
|
attribute :runs, MathRun, collection: true, initialize_empty: true
|
|
14
17
|
attribute :functions, Function, collection: true, initialize_empty: true
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
4
|
|
|
5
|
+
require_relative "../document_input"
|
|
6
|
+
|
|
5
7
|
module Uniword
|
|
6
8
|
module Mhtml
|
|
7
9
|
# MHTML Document — top-level model for .mht/.mhtml/.doc files.
|
|
@@ -17,6 +19,8 @@ module Uniword
|
|
|
17
19
|
# ├── word_document_settings (Metadata::WordDocumentSettings)
|
|
18
20
|
# └── filelist_xml (String)
|
|
19
21
|
class Document < Lutaml::Model::Serializable
|
|
22
|
+
include Uniword::DocumentInput
|
|
23
|
+
|
|
20
24
|
# MIME headers
|
|
21
25
|
attribute :mime_version, :string, default: -> { "1.0" }
|
|
22
26
|
attribute :boundary, :string
|
|
@@ -161,6 +165,20 @@ module Uniword
|
|
|
161
165
|
"#<#{self.class} parts=#{parts.length} images=#{image_parts.length} " \
|
|
162
166
|
"xml=#{xml_parts.length} theme=#{theme_part ? 'yes' : 'no'}>"
|
|
163
167
|
end
|
|
168
|
+
|
|
169
|
+
# @return [Hash] Document statistics (paragraphs, tables, images)
|
|
170
|
+
def document_stats
|
|
171
|
+
html = raw_html || html_content
|
|
172
|
+
if html
|
|
173
|
+
{
|
|
174
|
+
paragraphs: html.scan(/<p[\s>]/i).count,
|
|
175
|
+
tables: html.scan(/<table/i).count,
|
|
176
|
+
images: html.scan(/<img/i).count,
|
|
177
|
+
}
|
|
178
|
+
else
|
|
179
|
+
{ paragraphs: 0, tables: 0, images: 0 }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
164
182
|
end
|
|
165
183
|
end
|
|
166
184
|
end
|
|
@@ -1,40 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative "boolean_element_factory"
|
|
4
4
|
|
|
5
5
|
module Uniword
|
|
6
6
|
module Properties
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# OOXML: <w:b/> means bold=true (absence of val= means true)
|
|
10
|
-
# <w:b w:val="false"/> means bold=false
|
|
11
|
-
#
|
|
12
|
-
# Model: nil = true (no val attribute), 'false' = explicit false
|
|
13
|
-
class Bold < Lutaml::Model::Serializable
|
|
14
|
-
include Uniword::Properties::BooleanElement
|
|
15
|
-
|
|
16
|
-
attribute :val, :string, default: nil
|
|
17
|
-
include Uniword::Properties::BooleanValSetter
|
|
18
|
-
|
|
19
|
-
xml do
|
|
20
|
-
element "b"
|
|
21
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
22
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Complex script bold
|
|
27
|
-
class BoldCs < Lutaml::Model::Serializable
|
|
28
|
-
include Uniword::Properties::BooleanElement
|
|
29
|
-
|
|
30
|
-
attribute :val, :string, default: nil
|
|
31
|
-
include Uniword::Properties::BooleanValSetter
|
|
32
|
-
|
|
33
|
-
xml do
|
|
34
|
-
element "bCs"
|
|
35
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
36
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
37
|
-
end
|
|
38
|
-
end
|
|
7
|
+
BooleanElementFactory.define("b", "Bold")
|
|
8
|
+
BooleanElementFactory.define("bCs", "BoldCs")
|
|
39
9
|
end
|
|
40
10
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Uniword
|
|
6
|
+
module Properties
|
|
7
|
+
# OOXML boolean element mixin for value/val getter logic only.
|
|
8
|
+
# The val= setter must be defined AFTER attribute :val to override
|
|
9
|
+
# the generated setter.
|
|
10
|
+
module BooleanElement
|
|
11
|
+
def value
|
|
12
|
+
val != "false"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Helper to define val= override after attribute declaration.
|
|
17
|
+
# Uses alias_method to save the generated setter, then overrides it.
|
|
18
|
+
module BooleanValSetter
|
|
19
|
+
def self.included(base)
|
|
20
|
+
base.class_eval do
|
|
21
|
+
alias_method :__original_val_setter=, :val= if method_defined?(:val=)
|
|
22
|
+
define_method(:val=) do |v|
|
|
23
|
+
@val = if v.nil?
|
|
24
|
+
nil
|
|
25
|
+
elsif v == false || v.to_s == "false"
|
|
26
|
+
"false"
|
|
27
|
+
elsif v == true || v.to_s == "true"
|
|
28
|
+
nil
|
|
29
|
+
else
|
|
30
|
+
v
|
|
31
|
+
end
|
|
32
|
+
value_set_for(:val)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Factory for OOXML boolean element classes.
|
|
39
|
+
#
|
|
40
|
+
# Generates a lutaml-model class that maps to an XML element like
|
|
41
|
+
# <w:b/> (true) or <w:b w:val="false"/> (false).
|
|
42
|
+
#
|
|
43
|
+
# @param element_name [String] XML element name (e.g. "b", "i", "strike")
|
|
44
|
+
# @param class_name [String] Ruby class name (e.g. "Bold", "Italic")
|
|
45
|
+
# @return [Class] The generated class, also assigned as a constant
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# BooleanElementFactory.define("b", "Bold")
|
|
49
|
+
# BooleanElementFactory.define("bCs", "BoldCs")
|
|
50
|
+
module BooleanElementFactory
|
|
51
|
+
WML_NS = Uniword::Ooxml::Namespaces::WordProcessingML
|
|
52
|
+
|
|
53
|
+
def self.define(element_name, class_name)
|
|
54
|
+
klass = Class.new(Lutaml::Model::Serializable) do
|
|
55
|
+
include BooleanElement
|
|
56
|
+
|
|
57
|
+
attribute :val, :string, default: nil
|
|
58
|
+
include BooleanValSetter
|
|
59
|
+
|
|
60
|
+
xml do
|
|
61
|
+
element element_name
|
|
62
|
+
namespace WML_NS
|
|
63
|
+
map_attribute "val", to: :val, render_nil: false,
|
|
64
|
+
render_default: false
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
Properties.const_set(class_name, klass)
|
|
69
|
+
klass
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -1,224 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative "boolean_element_factory"
|
|
4
4
|
|
|
5
5
|
module Uniword
|
|
6
6
|
module Properties
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
module BooleanValSetter
|
|
19
|
-
def self.included(base)
|
|
20
|
-
base.class_eval do
|
|
21
|
-
# Save the generated val= method
|
|
22
|
-
alias_method :__original_val_setter=, :val= if method_defined?(:val=)
|
|
23
|
-
# Override val= with our custom logic
|
|
24
|
-
define_method(:val=) do |v|
|
|
25
|
-
@val = if v.nil?
|
|
26
|
-
nil
|
|
27
|
-
elsif v == false || v.to_s == "false"
|
|
28
|
-
"false"
|
|
29
|
-
elsif v == true || v.to_s == "true"
|
|
30
|
-
nil
|
|
31
|
-
else
|
|
32
|
-
v
|
|
33
|
-
end
|
|
34
|
-
value_set_for(:val)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Strike-through formatting
|
|
41
|
-
class Strike < Lutaml::Model::Serializable
|
|
42
|
-
include BooleanElement
|
|
43
|
-
|
|
44
|
-
attribute :val, :string, default: nil
|
|
45
|
-
include BooleanValSetter
|
|
46
|
-
|
|
47
|
-
xml do
|
|
48
|
-
element "strike"
|
|
49
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
50
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Double strike-through formatting
|
|
55
|
-
class DoubleStrike < Lutaml::Model::Serializable
|
|
56
|
-
include BooleanElement
|
|
57
|
-
|
|
58
|
-
attribute :val, :string, default: nil
|
|
59
|
-
include BooleanValSetter
|
|
60
|
-
|
|
61
|
-
xml do
|
|
62
|
-
element "dstrike"
|
|
63
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
64
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Small caps formatting
|
|
69
|
-
class SmallCaps < Lutaml::Model::Serializable
|
|
70
|
-
include BooleanElement
|
|
71
|
-
|
|
72
|
-
attribute :val, :string, default: nil
|
|
73
|
-
include BooleanValSetter
|
|
74
|
-
|
|
75
|
-
xml do
|
|
76
|
-
element "smallCaps"
|
|
77
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
78
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# All caps formatting
|
|
83
|
-
class Caps < Lutaml::Model::Serializable
|
|
84
|
-
include BooleanElement
|
|
85
|
-
|
|
86
|
-
attribute :val, :string, default: nil
|
|
87
|
-
include BooleanValSetter
|
|
88
|
-
|
|
89
|
-
xml do
|
|
90
|
-
element "caps"
|
|
91
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
92
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Hidden text
|
|
97
|
-
class Vanish < Lutaml::Model::Serializable
|
|
98
|
-
include BooleanElement
|
|
99
|
-
|
|
100
|
-
attribute :val, :string, default: nil
|
|
101
|
-
include BooleanValSetter
|
|
102
|
-
|
|
103
|
-
xml do
|
|
104
|
-
element "vanish"
|
|
105
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
106
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Web hidden text (hidden from web view)
|
|
111
|
-
class WebHidden < Lutaml::Model::Serializable
|
|
112
|
-
include BooleanElement
|
|
113
|
-
|
|
114
|
-
attribute :val, :string, default: nil
|
|
115
|
-
include BooleanValSetter
|
|
116
|
-
|
|
117
|
-
xml do
|
|
118
|
-
element "webHidden"
|
|
119
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
120
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# No proofing (disable spell/grammar check)
|
|
125
|
-
class NoProof < Lutaml::Model::Serializable
|
|
126
|
-
include BooleanElement
|
|
127
|
-
|
|
128
|
-
attribute :val, :string, default: nil
|
|
129
|
-
include BooleanValSetter
|
|
130
|
-
|
|
131
|
-
xml do
|
|
132
|
-
element "noProof"
|
|
133
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
134
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Shadow formatting
|
|
139
|
-
class Shadow < Lutaml::Model::Serializable
|
|
140
|
-
include BooleanElement
|
|
141
|
-
|
|
142
|
-
attribute :val, :string, default: nil
|
|
143
|
-
include BooleanValSetter
|
|
144
|
-
|
|
145
|
-
xml do
|
|
146
|
-
element "shadow"
|
|
147
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
148
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# Emboss formatting
|
|
153
|
-
class Emboss < Lutaml::Model::Serializable
|
|
154
|
-
include BooleanElement
|
|
155
|
-
|
|
156
|
-
attribute :val, :string, default: nil
|
|
157
|
-
include BooleanValSetter
|
|
158
|
-
|
|
159
|
-
xml do
|
|
160
|
-
element "emboss"
|
|
161
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
162
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Imprint formatting
|
|
167
|
-
class Imprint < Lutaml::Model::Serializable
|
|
168
|
-
include BooleanElement
|
|
169
|
-
|
|
170
|
-
attribute :val, :string, default: nil
|
|
171
|
-
include BooleanValSetter
|
|
172
|
-
|
|
173
|
-
xml do
|
|
174
|
-
element "imprint"
|
|
175
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
176
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
177
|
-
end
|
|
178
|
-
end
|
|
7
|
+
# Run-level boolean formatting elements
|
|
8
|
+
BooleanElementFactory.define("strike", "Strike")
|
|
9
|
+
BooleanElementFactory.define("dstrike", "DoubleStrike")
|
|
10
|
+
BooleanElementFactory.define("smallCaps", "SmallCaps")
|
|
11
|
+
BooleanElementFactory.define("caps", "Caps")
|
|
12
|
+
BooleanElementFactory.define("vanish", "Vanish")
|
|
13
|
+
BooleanElementFactory.define("webHidden", "WebHidden")
|
|
14
|
+
BooleanElementFactory.define("noProof", "NoProof")
|
|
15
|
+
BooleanElementFactory.define("shadow", "Shadow")
|
|
16
|
+
BooleanElementFactory.define("emboss", "Emboss")
|
|
17
|
+
BooleanElementFactory.define("imprint", "Imprint")
|
|
179
18
|
|
|
180
19
|
# Style-level boolean elements
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
include BooleanElement
|
|
185
|
-
|
|
186
|
-
attribute :val, :string, default: nil
|
|
187
|
-
include BooleanValSetter
|
|
188
|
-
|
|
189
|
-
xml do
|
|
190
|
-
element "qFormat"
|
|
191
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
192
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
# Keep with next paragraph
|
|
197
|
-
class KeepNext < Lutaml::Model::Serializable
|
|
198
|
-
include BooleanElement
|
|
199
|
-
|
|
200
|
-
attribute :val, :string, default: nil
|
|
201
|
-
include BooleanValSetter
|
|
202
|
-
|
|
203
|
-
xml do
|
|
204
|
-
element "keepNext"
|
|
205
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
206
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Keep lines together
|
|
211
|
-
class KeepLines < Lutaml::Model::Serializable
|
|
212
|
-
include BooleanElement
|
|
213
|
-
|
|
214
|
-
attribute :val, :string, default: nil
|
|
215
|
-
include BooleanValSetter
|
|
216
|
-
|
|
217
|
-
xml do
|
|
218
|
-
element "keepLines"
|
|
219
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
220
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
221
|
-
end
|
|
222
|
-
end
|
|
20
|
+
BooleanElementFactory.define("qFormat", "QuickFormat")
|
|
21
|
+
BooleanElementFactory.define("keepNext", "KeepNext")
|
|
22
|
+
BooleanElementFactory.define("keepLines", "KeepLines")
|
|
223
23
|
end
|
|
224
24
|
end
|
|
@@ -1,40 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative "boolean_element_factory"
|
|
4
4
|
|
|
5
5
|
module Uniword
|
|
6
6
|
module Properties
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# OOXML: <w:i/> means italic=true (absence of val= means true)
|
|
10
|
-
# <w:i w:val="false"/> means italic=false
|
|
11
|
-
#
|
|
12
|
-
# Model: nil = true (no val attribute), 'false' = explicit false
|
|
13
|
-
class Italic < Lutaml::Model::Serializable
|
|
14
|
-
include Uniword::Properties::BooleanElement
|
|
15
|
-
|
|
16
|
-
attribute :val, :string, default: nil
|
|
17
|
-
include Uniword::Properties::BooleanValSetter
|
|
18
|
-
|
|
19
|
-
xml do
|
|
20
|
-
element "i"
|
|
21
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
22
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Complex script italic
|
|
27
|
-
class ItalicCs < Lutaml::Model::Serializable
|
|
28
|
-
include Uniword::Properties::BooleanElement
|
|
29
|
-
|
|
30
|
-
attribute :val, :string, default: nil
|
|
31
|
-
include Uniword::Properties::BooleanValSetter
|
|
32
|
-
|
|
33
|
-
xml do
|
|
34
|
-
element "iCs"
|
|
35
|
-
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
36
|
-
map_attribute "val", to: :val, render_nil: false, render_default: false
|
|
37
|
-
end
|
|
38
|
-
end
|
|
7
|
+
BooleanElementFactory.define("i", "Italic")
|
|
8
|
+
BooleanElementFactory.define("iCs", "ItalicCs")
|
|
39
9
|
end
|
|
40
10
|
end
|
data/lib/uniword/properties.rb
CHANGED
|
@@ -23,10 +23,13 @@ module Uniword
|
|
|
23
23
|
autoload :NumberingProperties, "uniword/properties/numbering_properties"
|
|
24
24
|
autoload :Tabs, "uniword/properties/tabs"
|
|
25
25
|
|
|
26
|
+
# Boolean element infrastructure
|
|
27
|
+
autoload :BooleanElement, "uniword/properties/boolean_element_factory"
|
|
28
|
+
autoload :BooleanValSetter, "uniword/properties/boolean_element_factory"
|
|
29
|
+
autoload :BooleanElementFactory,
|
|
30
|
+
"uniword/properties/boolean_element_factory"
|
|
31
|
+
|
|
26
32
|
# Boolean formatting classes (from boolean_formatting.rb)
|
|
27
|
-
# Note: BooleanElement and BooleanValSetter are also in boolean_formatting.rb
|
|
28
|
-
autoload :BooleanElement, "uniword/properties/boolean_formatting"
|
|
29
|
-
autoload :BooleanValSetter, "uniword/properties/boolean_formatting"
|
|
30
33
|
autoload :Strike, "uniword/properties/boolean_formatting"
|
|
31
34
|
autoload :DoubleStrike, "uniword/properties/boolean_formatting"
|
|
32
35
|
autoload :SmallCaps, "uniword/properties/boolean_formatting"
|
|
@@ -49,7 +52,9 @@ module Uniword
|
|
|
49
52
|
|
|
50
53
|
# Bold and Italic (from bold.rb and italic.rb)
|
|
51
54
|
autoload :Bold, "uniword/properties/bold"
|
|
55
|
+
autoload :BoldCs, "uniword/properties/bold"
|
|
52
56
|
autoload :Italic, "uniword/properties/italic"
|
|
57
|
+
autoload :ItalicCs, "uniword/properties/italic"
|
|
53
58
|
|
|
54
59
|
# Complex objects
|
|
55
60
|
autoload :Spacing, "uniword/properties/spacing"
|
|
@@ -547,7 +547,7 @@ module Uniword
|
|
|
547
547
|
def build_position_map(elements, fallback_pos)
|
|
548
548
|
by_pos = {}
|
|
549
549
|
elements.each do |el|
|
|
550
|
-
pos = el.run_position if el.is_a?(Uniword::
|
|
550
|
+
pos = el.run_position if el.is_a?(Uniword::HasRunPosition)
|
|
551
551
|
pos ||= fallback_pos
|
|
552
552
|
by_pos[pos] ||= []
|
|
553
553
|
by_pos[pos] << el
|
data/lib/uniword/version.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
4
|
|
|
5
|
+
require_relative "../document_input"
|
|
5
6
|
require_relative "document_root/feature_facade"
|
|
6
7
|
|
|
7
8
|
module Uniword
|
|
@@ -12,6 +13,7 @@ module Uniword
|
|
|
12
13
|
# Element: <w:document>
|
|
13
14
|
class DocumentRoot < Lutaml::Model::Serializable
|
|
14
15
|
include FeatureFacade
|
|
16
|
+
include Uniword::DocumentInput
|
|
15
17
|
|
|
16
18
|
attribute :mc_ignorable, Uniword::Ooxml::Types::McIgnorable
|
|
17
19
|
attribute :body, Body, default: -> { Body.new }
|
|
@@ -210,6 +212,15 @@ module Uniword
|
|
|
210
212
|
end.compact
|
|
211
213
|
end
|
|
212
214
|
|
|
215
|
+
# @return [Hash] Document statistics (paragraphs, tables, images)
|
|
216
|
+
def document_stats
|
|
217
|
+
{
|
|
218
|
+
paragraphs: paragraphs.count,
|
|
219
|
+
tables: tables.count,
|
|
220
|
+
images: images.count,
|
|
221
|
+
}
|
|
222
|
+
end
|
|
223
|
+
|
|
213
224
|
# Check if document structure is valid.
|
|
214
225
|
# Runs structural checks via Validation::StructuralValidator.
|
|
215
226
|
# Use the verify CLI command for full OPC + XSD + semantic validation.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
|
+
require_relative "../has_run_position"
|
|
4
5
|
|
|
5
6
|
module Uniword
|
|
6
7
|
module Wordprocessingml
|
|
@@ -9,6 +10,8 @@ module Uniword
|
|
|
9
10
|
# Generated from OOXML schema: wordprocessingml.yml
|
|
10
11
|
# Element: <w:hyperlink>
|
|
11
12
|
class Hyperlink < Lutaml::Model::Serializable
|
|
13
|
+
include Uniword::HasRunPosition
|
|
14
|
+
|
|
12
15
|
attribute :id, :string
|
|
13
16
|
attribute :anchor, :string
|
|
14
17
|
attribute :tooltip, :string
|
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.0.
|
|
4
|
+
version: 1.0.9
|
|
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-05-
|
|
11
|
+
date: 2026-05-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: logger
|
|
@@ -771,6 +771,7 @@ files:
|
|
|
771
771
|
- lib/uniword/diff/package_diff_result.rb
|
|
772
772
|
- lib/uniword/diff/package_differ.rb
|
|
773
773
|
- lib/uniword/document_factory.rb
|
|
774
|
+
- lib/uniword/document_input.rb
|
|
774
775
|
- lib/uniword/document_variables.rb
|
|
775
776
|
- lib/uniword/document_variables/data_type.rb
|
|
776
777
|
- lib/uniword/document_variables/default_value.rb
|
|
@@ -966,6 +967,7 @@ files:
|
|
|
966
967
|
- lib/uniword/glossary/glossary_document.rb
|
|
967
968
|
- lib/uniword/glossary/style_id.rb
|
|
968
969
|
- lib/uniword/glossary/text_box.rb
|
|
970
|
+
- lib/uniword/has_run_position.rb
|
|
969
971
|
- lib/uniword/header.rb
|
|
970
972
|
- lib/uniword/headers_footers.rb
|
|
971
973
|
- lib/uniword/headers_footers/manager.rb
|
|
@@ -1157,7 +1159,6 @@ files:
|
|
|
1157
1159
|
- lib/uniword/ooxml/types/dcterms_modified_type.rb
|
|
1158
1160
|
- lib/uniword/ooxml/types/dcterms_w3cdtf_type.rb
|
|
1159
1161
|
- lib/uniword/ooxml/types/mc_ignorable_type.rb
|
|
1160
|
-
- lib/uniword/ooxml/types/on_off_type.rb
|
|
1161
1162
|
- lib/uniword/ooxml/types/ooxml_boolean.rb
|
|
1162
1163
|
- lib/uniword/ooxml/types/ooxml_boolean_optional.rb
|
|
1163
1164
|
- lib/uniword/ooxml/types/relationship_id.rb
|
|
@@ -1232,6 +1233,7 @@ files:
|
|
|
1232
1233
|
- lib/uniword/properties/auto_space_de.rb
|
|
1233
1234
|
- lib/uniword/properties/auto_space_dn.rb
|
|
1234
1235
|
- lib/uniword/properties/bold.rb
|
|
1236
|
+
- lib/uniword/properties/boolean_element_factory.rb
|
|
1235
1237
|
- lib/uniword/properties/boolean_formatting.rb
|
|
1236
1238
|
- lib/uniword/properties/border.rb
|
|
1237
1239
|
- lib/uniword/properties/borders.rb
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
|
|
5
|
-
module Uniword
|
|
6
|
-
module Ooxml
|
|
7
|
-
module Types
|
|
8
|
-
# OOXML On/Off (boolean) type for attributes.
|
|
9
|
-
#
|
|
10
|
-
# OOXML uses "0" and "1" for boolean attribute values, not "false"/"true".
|
|
11
|
-
# When an attribute is not present (nil), it should remain nil, not be
|
|
12
|
-
# serialized as "0". This preserves the original document structure.
|
|
13
|
-
#
|
|
14
|
-
# @example Serialize a boolean attribute
|
|
15
|
-
# # Ruby true → XML "1"
|
|
16
|
-
# # Ruby false → XML "0"
|
|
17
|
-
# # Ruby nil → attribute not rendered
|
|
18
|
-
class OnOffType < Lutaml::Model::Type::String
|
|
19
|
-
# Bypass parent's initialize to avoid infinite recursion.
|
|
20
|
-
# Parent calls self.class.cast(value) which calls self.new(value).
|
|
21
|
-
def initialize(value)
|
|
22
|
-
@value = value
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Cast value to OnOffType instance (for attribute serialization).
|
|
26
|
-
# nil remains nil (not present in source), preserving original structure.
|
|
27
|
-
# Already-wrapped OnOffType instances are returned as-is.
|
|
28
|
-
def self.cast(value, _options = {})
|
|
29
|
-
return nil if value.nil?
|
|
30
|
-
return value if value.is_a?(OnOffType)
|
|
31
|
-
|
|
32
|
-
raw = case value
|
|
33
|
-
when true, "true", "1", 1
|
|
34
|
-
true
|
|
35
|
-
when false, "false", "0", 0
|
|
36
|
-
false
|
|
37
|
-
else
|
|
38
|
-
false
|
|
39
|
-
end
|
|
40
|
-
new(raw)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Convert stored boolean to OOXML "1" or "0"
|
|
44
|
-
def to_xml
|
|
45
|
-
return nil if @value.nil?
|
|
46
|
-
|
|
47
|
-
@value == true ? "1" : "0"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Fallback to_s also returns "1"/"0" for compatibility
|
|
51
|
-
def to_s
|
|
52
|
-
return "" if @value.nil?
|
|
53
|
-
|
|
54
|
-
to_xml
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Return the raw boolean value for Ruby comparisons
|
|
58
|
-
def to_bool
|
|
59
|
-
@value == true
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|