uniword 1.5.2 → 1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/lib/uniword/batch/operation/file_result.rb +39 -0
- data/lib/uniword/batch/operation/repair_task.rb +34 -0
- data/lib/uniword/batch/operation/report.rb +66 -0
- data/lib/uniword/batch/operation/runner.rb +30 -0
- data/lib/uniword/batch/operation/task.rb +40 -0
- data/lib/uniword/batch/operation/verify_task.rb +27 -0
- data/lib/uniword/batch/operation.rb +22 -0
- data/lib/uniword/batch.rb +1 -0
- data/lib/uniword/builder/image_builder.rb +1 -1
- data/lib/uniword/caption/caption_builder.rb +120 -0
- data/lib/uniword/caption/counter.rb +61 -0
- data/lib/uniword/caption/cross_reference.rb +44 -0
- data/lib/uniword/caption.rb +24 -0
- data/lib/uniword/diff/semantic/change.rb +66 -0
- data/lib/uniword/diff/semantic/engine.rb +31 -0
- data/lib/uniword/diff/semantic/paragraph_comparator.rb +195 -0
- data/lib/uniword/diff/semantic/result.rb +53 -0
- data/lib/uniword/diff/semantic.rb +26 -0
- data/lib/uniword/diff.rb +1 -0
- data/lib/uniword/docx/package_defaults.rb +1 -1
- data/lib/uniword/docx/package_serialization.rb +1 -1
- data/lib/uniword/docx/reconciler/helpers.rb +1 -1
- data/lib/uniword/docx/reconciler/referential_integrity.rb +1 -1
- data/lib/uniword/find_replace/scope.rb +9 -11
- data/lib/uniword/ooxml/package_file.rb +1 -1
- data/lib/uniword/picture/fill_rect.rb +2 -2
- data/lib/uniword/picture/picture_source_rect.rb +3 -2
- data/lib/uniword/picture/picture_stretch.rb +3 -2
- data/lib/uniword/picture/tile.rb +3 -2
- data/lib/uniword/plugin/cli_command.rb +30 -0
- data/lib/uniword/plugin/loader.rb +43 -0
- data/lib/uniword/plugin/registry.rb +83 -0
- data/lib/uniword/plugin/transformer.rb +50 -0
- data/lib/uniword/plugin/validator.rb +34 -0
- data/lib/uniword/plugin.rb +25 -0
- data/lib/uniword/properties/word2010_id_value.rb +2 -2
- data/lib/uniword/version.rb +1 -1
- data/lib/uniword/wordprocessingml/body.rb +54 -6
- data/lib/uniword/wordprocessingml/document_styling.rb +40 -0
- data/lib/uniword/wordprocessingml/styles_configuration.rb +1 -1
- data/lib/uniword.rb +6 -0
- metadata +26 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uniword
|
|
4
|
+
module Plugin
|
|
5
|
+
# Base class for plugin-provided validation rules. Subclasses
|
|
6
|
+
# implement `#check(document)` (yields findings).
|
|
7
|
+
#
|
|
8
|
+
# Open/closed: adding a new validator = subclassing + calling
|
|
9
|
+
# `Registry.register_validator`.
|
|
10
|
+
class Validator
|
|
11
|
+
# @return [Symbol] validator name (matches the registry key)
|
|
12
|
+
attr_reader :name
|
|
13
|
+
|
|
14
|
+
# @return [Symbol] default severity (:error, :warning, :info)
|
|
15
|
+
attr_reader :severity
|
|
16
|
+
|
|
17
|
+
# @param name [Symbol]
|
|
18
|
+
# @param severity [Symbol]
|
|
19
|
+
def initialize(name:, severity: :warning)
|
|
20
|
+
@name = name
|
|
21
|
+
@severity = severity
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Walk the document and yield each finding as a hash.
|
|
25
|
+
#
|
|
26
|
+
# @param document [Wordprocessingml::DocumentRoot]
|
|
27
|
+
# @yieldparam finding [Hash] { message:, path: }
|
|
28
|
+
# @return [void]
|
|
29
|
+
def check(document)
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uniword
|
|
4
|
+
# Plugin system: extend uniword without forking.
|
|
5
|
+
#
|
|
6
|
+
# Three extension surfaces, each with a base class:
|
|
7
|
+
#
|
|
8
|
+
# - `Plugin::Validator` — register custom validation rules
|
|
9
|
+
# - `Plugin::Transformer` — mutate documents at defined pipeline
|
|
10
|
+
# stages (load, pre-save, post-reconcile)
|
|
11
|
+
# - `Plugin::CliCommand` — register new Thor subcommands
|
|
12
|
+
#
|
|
13
|
+
# Discovery: `Plugin::Loader.load_all` walks installed gems via
|
|
14
|
+
# `Gem.find_files("uniword/plugin/*.rb")` and loads each.
|
|
15
|
+
#
|
|
16
|
+
# Configuration: `Uniword.configuration.plugins = [:my_plugin]`
|
|
17
|
+
# (default `:all`).
|
|
18
|
+
module Plugin
|
|
19
|
+
autoload :Registry, "#{__dir__}/plugin/registry"
|
|
20
|
+
autoload :Validator, "#{__dir__}/plugin/validator"
|
|
21
|
+
autoload :Transformer, "#{__dir__}/plugin/transformer"
|
|
22
|
+
autoload :CliCommand, "#{__dir__}/plugin/cli_command"
|
|
23
|
+
autoload :Loader, "#{__dir__}/plugin/loader"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -4,13 +4,13 @@ require "lutaml/model"
|
|
|
4
4
|
|
|
5
5
|
module Uniword
|
|
6
6
|
module Properties
|
|
7
|
-
# Namespaced custom type for Word 2010 (wp14) attributes
|
|
7
|
+
# Namespaced custom type for Word 2010 Drawing (wp14) attributes
|
|
8
8
|
# Used for wp14:anchorId and wp14:editId attributes
|
|
9
9
|
class Word2010IdValue < Lutaml::Model::Type::String
|
|
10
10
|
include Lutaml::Xml::Type::Configurable
|
|
11
11
|
|
|
12
12
|
xml do
|
|
13
|
-
namespace Uniword::Ooxml::Namespaces::
|
|
13
|
+
namespace Uniword::Ooxml::Namespaces::Word2010Drawing
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
data/lib/uniword/version.rb
CHANGED
|
@@ -32,15 +32,54 @@ module Uniword
|
|
|
32
32
|
map_element "bookmarkEnd", to: :bookmark_ends, render_nil: false
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
# Get all elements in body
|
|
35
|
+
# Get all elements in body, in document order.
|
|
36
36
|
#
|
|
37
|
-
#
|
|
37
|
+
# Walks `element_order` (populated by lutaml-model when mixed_content
|
|
38
|
+
# is parsed) and dispatches each tag to its typed collection —
|
|
39
|
+
# `p` -> paragraphs, `tbl` -> tables, `sdt` -> structured_document_tags,
|
|
40
|
+
# `bookmarkStart` -> bookmark_starts, `bookmarkEnd` -> bookmark_ends,
|
|
41
|
+
# `sectPr` -> section_properties. Whitespace/comment entries are
|
|
42
|
+
# skipped. Elements not represented in `element_order` are appended
|
|
43
|
+
# at the end in collection order (the only order available when
|
|
44
|
+
# `element_order` is empty or nil).
|
|
45
|
+
#
|
|
46
|
+
# @return [Array] Block-level content in document order
|
|
38
47
|
def elements
|
|
48
|
+
return concatenate_typed_collections if element_order.nil? || element_order.empty?
|
|
49
|
+
|
|
39
50
|
result = []
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
counters = Hash.new(0)
|
|
52
|
+
sectpr_seen = false
|
|
53
|
+
collections = {
|
|
54
|
+
"p" => paragraphs,
|
|
55
|
+
"tbl" => tables,
|
|
56
|
+
"sdt" => structured_document_tags,
|
|
57
|
+
"bookmarkStart" => bookmark_starts,
|
|
58
|
+
"bookmarkEnd" => bookmark_ends,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
element_order.each do |entry|
|
|
62
|
+
name = entry.name
|
|
63
|
+
if collections.key?(name)
|
|
64
|
+
collection = collections[name]
|
|
65
|
+
index = counters[name]
|
|
66
|
+
if collection && index < collection.size
|
|
67
|
+
result << collection[index]
|
|
68
|
+
counters[name] = index + 1
|
|
69
|
+
end
|
|
70
|
+
elsif name == "sectPr"
|
|
71
|
+
sectpr_seen = true
|
|
72
|
+
result << section_properties if section_properties
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
collections.each do |name, collection|
|
|
77
|
+
next unless collection && counters[name] < collection.size
|
|
78
|
+
|
|
79
|
+
result.concat(collection[counters[name]..])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
result << section_properties if section_properties && !sectpr_seen
|
|
44
83
|
result
|
|
45
84
|
end
|
|
46
85
|
|
|
@@ -80,6 +119,15 @@ module Uniword
|
|
|
80
119
|
|
|
81
120
|
private
|
|
82
121
|
|
|
122
|
+
def concatenate_typed_collections
|
|
123
|
+
result = []
|
|
124
|
+
result.concat(paragraphs || [])
|
|
125
|
+
result.concat(structured_document_tags || [])
|
|
126
|
+
result.concat(tables || [])
|
|
127
|
+
result << section_properties if section_properties
|
|
128
|
+
result
|
|
129
|
+
end
|
|
130
|
+
|
|
83
131
|
def sync_element_order
|
|
84
132
|
return if element_order.nil? || element_order.empty?
|
|
85
133
|
|
|
@@ -195,6 +195,46 @@ module Uniword
|
|
|
195
195
|
Lint::Engine.new(document: self, ruleset: ruleset).run
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
+
# Counter for auto-numbered captions. Persisted across the
|
|
199
|
+
# document's lifetime; reset on document load.
|
|
200
|
+
#
|
|
201
|
+
# @return [Caption::Counter]
|
|
202
|
+
def caption_counter
|
|
203
|
+
@caption_counter ||= Caption::Counter.new
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Add an auto-numbered caption paragraph to the body and
|
|
207
|
+
# return the bookmark name (for use in cross-references).
|
|
208
|
+
#
|
|
209
|
+
# The caption is appended as a new paragraph with style
|
|
210
|
+
# "Caption" and a SEQ field. The bookmark wraps the entire
|
|
211
|
+
# paragraph so cross-references resolve to the caption text.
|
|
212
|
+
#
|
|
213
|
+
# @param label [String] "Figure", "Table", "Equation", or any
|
|
214
|
+
# other category — each gets its own counter
|
|
215
|
+
# @param text [String] caption body
|
|
216
|
+
# @param separator [String] between the label/number and the
|
|
217
|
+
# body (default ": ")
|
|
218
|
+
# @return [String] bookmark name (e.g. "_Figure1")
|
|
219
|
+
def add_caption(label:, text:, separator: ": ")
|
|
220
|
+
builder = Caption::CaptionBuilder.new(caption_counter)
|
|
221
|
+
paragraph, bookmark_name = builder.build(label: label,
|
|
222
|
+
text: text,
|
|
223
|
+
separator: separator)
|
|
224
|
+
body.paragraphs << paragraph
|
|
225
|
+
bookmark_name
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Build a cross-reference run targeting a bookmark. Returns a
|
|
229
|
+
# Run containing a SimpleField with a REF instruction. The
|
|
230
|
+
# caller decides where to place it.
|
|
231
|
+
#
|
|
232
|
+
# @param bookmark_name [String] target bookmark
|
|
233
|
+
# @return [Wordprocessingml::SimpleField]
|
|
234
|
+
def cross_reference_to(bookmark_name)
|
|
235
|
+
Caption::CrossReference.new(bookmark_name).build
|
|
236
|
+
end
|
|
237
|
+
|
|
198
238
|
# Apply uniform page setup to every section of the document
|
|
199
239
|
#
|
|
200
240
|
# Mirrors Word's Layout dialog: named paper sizes, orientation
|
data/lib/uniword.rb
CHANGED
|
@@ -140,6 +140,12 @@ module Uniword
|
|
|
140
140
|
# Document lint (style-guide enforcement).
|
|
141
141
|
autoload :Lint, "uniword/lint"
|
|
142
142
|
|
|
143
|
+
# Auto-numbered captions + cross-references.
|
|
144
|
+
autoload :Caption, "uniword/caption"
|
|
145
|
+
|
|
146
|
+
# Plugin system (validators, transformers, CLI commands).
|
|
147
|
+
autoload :Plugin, "uniword/plugin"
|
|
148
|
+
|
|
143
149
|
# CLI
|
|
144
150
|
autoload :CLI, "uniword/cli/main"
|
|
145
151
|
autoload :GenerateCLI, "uniword/cli/generate_cli"
|
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.5.
|
|
4
|
+
version: 1.5.4
|
|
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-
|
|
11
|
+
date: 2026-09-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: logger
|
|
@@ -92,14 +92,14 @@ dependencies:
|
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
95
|
+
version: '3.4'
|
|
96
96
|
type: :runtime
|
|
97
97
|
prerelease: false
|
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
100
|
- - "~>"
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '
|
|
102
|
+
version: '3.4'
|
|
103
103
|
- !ruby/object:Gem::Dependency
|
|
104
104
|
name: thor
|
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -592,6 +592,13 @@ files:
|
|
|
592
592
|
- lib/uniword/batch.rb
|
|
593
593
|
- lib/uniword/batch/batch_result.rb
|
|
594
594
|
- lib/uniword/batch/document_processor.rb
|
|
595
|
+
- lib/uniword/batch/operation.rb
|
|
596
|
+
- lib/uniword/batch/operation/file_result.rb
|
|
597
|
+
- lib/uniword/batch/operation/repair_task.rb
|
|
598
|
+
- lib/uniword/batch/operation/report.rb
|
|
599
|
+
- lib/uniword/batch/operation/runner.rb
|
|
600
|
+
- lib/uniword/batch/operation/task.rb
|
|
601
|
+
- lib/uniword/batch/operation/verify_task.rb
|
|
595
602
|
- lib/uniword/batch/processing_stage.rb
|
|
596
603
|
- lib/uniword/batch/stages/compress_images_stage.rb
|
|
597
604
|
- lib/uniword/batch/stages/convert_format_stage.rb
|
|
@@ -656,6 +663,10 @@ files:
|
|
|
656
663
|
- lib/uniword/builder/theme_builder.rb
|
|
657
664
|
- lib/uniword/builder/toc_builder.rb
|
|
658
665
|
- lib/uniword/builder/watermark_builder.rb
|
|
666
|
+
- lib/uniword/caption.rb
|
|
667
|
+
- lib/uniword/caption/caption_builder.rb
|
|
668
|
+
- lib/uniword/caption/counter.rb
|
|
669
|
+
- lib/uniword/caption/cross_reference.rb
|
|
659
670
|
- lib/uniword/chart.rb
|
|
660
671
|
- lib/uniword/chart/area3_d_chart.rb
|
|
661
672
|
- lib/uniword/chart/area_chart.rb
|
|
@@ -800,6 +811,11 @@ files:
|
|
|
800
811
|
- lib/uniword/diff/formatter.rb
|
|
801
812
|
- lib/uniword/diff/package_diff_result.rb
|
|
802
813
|
- lib/uniword/diff/package_differ.rb
|
|
814
|
+
- lib/uniword/diff/semantic.rb
|
|
815
|
+
- lib/uniword/diff/semantic/change.rb
|
|
816
|
+
- lib/uniword/diff/semantic/engine.rb
|
|
817
|
+
- lib/uniword/diff/semantic/paragraph_comparator.rb
|
|
818
|
+
- lib/uniword/diff/semantic/result.rb
|
|
803
819
|
- lib/uniword/document_factory.rb
|
|
804
820
|
- lib/uniword/document_input.rb
|
|
805
821
|
- lib/uniword/document_variables.rb
|
|
@@ -1205,6 +1221,12 @@ files:
|
|
|
1205
1221
|
- lib/uniword/picture/picture_source_rect.rb
|
|
1206
1222
|
- lib/uniword/picture/picture_stretch.rb
|
|
1207
1223
|
- lib/uniword/picture/tile.rb
|
|
1224
|
+
- lib/uniword/plugin.rb
|
|
1225
|
+
- lib/uniword/plugin/cli_command.rb
|
|
1226
|
+
- lib/uniword/plugin/loader.rb
|
|
1227
|
+
- lib/uniword/plugin/registry.rb
|
|
1228
|
+
- lib/uniword/plugin/transformer.rb
|
|
1229
|
+
- lib/uniword/plugin/validator.rb
|
|
1208
1230
|
- lib/uniword/presentationml.rb
|
|
1209
1231
|
- lib/uniword/presentationml/audio.rb
|
|
1210
1232
|
- lib/uniword/presentationml/body_properties.rb
|