uniword 1.2.5 → 1.3.0
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 +223 -0
- data/CONTRIBUTING.md +1 -1
- data/config/ooxml/schemas/shared_types.yml +5 -4
- data/data/schemas/ecma/dc.xsd +118 -0
- data/data/schemas/ecma/dcmitype.xsd +50 -0
- data/data/schemas/ecma/dcterms.xsd +331 -0
- data/data/schemas/ecma/opc-coreProperties.xsd +2 -2
- data/data/schemas/ecma/xml.xsd +117 -0
- data/lib/uniword/builder/bibliography_builder.rb +1 -1
- data/lib/uniword/builder/chart_builder.rb +19 -9
- data/lib/uniword/builder/comment_anchorer.rb +221 -0
- data/lib/uniword/builder/document_builder.rb +97 -6
- data/lib/uniword/builder/image_builder.rb +6 -5
- data/lib/uniword/builder/run_utils.rb +2 -0
- data/lib/uniword/builder.rb +1 -0
- data/lib/uniword/cli/fonts_cli.rb +52 -0
- data/lib/uniword/cli/main.rb +110 -11
- data/lib/uniword/cli/page_cli.rb +85 -0
- data/lib/uniword/cli/styles_cli.rb +204 -0
- data/lib/uniword/cli/theme_cli.rb +88 -0
- data/lib/uniword/cli/toc_cli.rb +22 -2
- data/lib/uniword/comment.rb +20 -15
- data/lib/uniword/comment_range.rb +3 -3
- data/lib/uniword/comments_part.rb +51 -19
- data/lib/uniword/configuration/configuration_loader.rb +5 -3
- data/lib/uniword/configuration.rb +93 -1
- data/lib/uniword/content_types.rb +19 -39
- data/lib/uniword/document_factory.rb +9 -1
- data/lib/uniword/document_writer.rb +16 -5
- data/lib/uniword/docx/chart_part.rb +34 -0
- data/lib/uniword/docx/custom_xml_item.rb +83 -0
- data/lib/uniword/docx/header_footer_part.rb +140 -0
- data/lib/uniword/docx/header_footer_part_collection.rb +135 -0
- data/lib/uniword/docx/header_footer_view.rb +225 -0
- data/lib/uniword/docx/id_allocator.rb +130 -36
- data/lib/uniword/docx/package.rb +223 -35
- data/lib/uniword/docx/package_defaults.rb +58 -78
- data/lib/uniword/docx/package_integrity_checker.rb +312 -0
- data/lib/uniword/docx/package_serialization.rb +103 -231
- data/lib/uniword/docx/part.rb +106 -0
- data/lib/uniword/docx/part_collection.rb +123 -0
- data/lib/uniword/docx/reconciler/body.rb +59 -68
- data/lib/uniword/docx/reconciler/fix.rb +46 -0
- data/lib/uniword/docx/reconciler/fix_codes.rb +37 -30
- data/lib/uniword/docx/reconciler/helpers.rb +9 -1
- data/lib/uniword/docx/reconciler/notes.rb +17 -8
- data/lib/uniword/docx/reconciler/package_structure.rb +169 -221
- data/lib/uniword/docx/reconciler/parts.rb +36 -13
- data/lib/uniword/docx/reconciler/referential_integrity.rb +297 -123
- data/lib/uniword/docx/reconciler/tables.rb +78 -16
- data/lib/uniword/docx/reconciler/theme.rb +7 -4
- data/lib/uniword/docx/reconciler.rb +36 -14
- data/lib/uniword/docx.rb +10 -0
- data/lib/uniword/drawingml/blip.rb +0 -1
- data/lib/uniword/drawingml/color_scheme.rb +5 -6
- data/lib/uniword/drawingml/font_scheme.rb +4 -8
- data/lib/uniword/drawingml/theme.rb +12 -6
- data/lib/uniword/errors.rb +8 -1
- data/lib/uniword/footer.rb +4 -0
- data/lib/uniword/header.rb +4 -0
- data/lib/uniword/hyperlink.rb +1 -1
- data/lib/uniword/image.rb +6 -6
- data/lib/uniword/lazy_loader.rb +1 -2
- data/lib/uniword/model_attribute_access.rb +20 -4
- data/lib/uniword/ooxml/dotx_package.rb +42 -2
- data/lib/uniword/ooxml/part_definition.rb +171 -0
- data/lib/uniword/ooxml/part_registry.rb +311 -0
- data/lib/uniword/ooxml/relationships/image_relationship.rb +1 -1
- data/lib/uniword/ooxml/relationships/package_relationships.rb +20 -22
- data/lib/uniword/ooxml/schema/element_serializer.rb +8 -7
- data/lib/uniword/ooxml/types/hex_color_value.rb +38 -0
- data/lib/uniword/ooxml/types/ooxml_boolean.rb +27 -14
- data/lib/uniword/ooxml/types/ooxml_boolean_optional.rb +21 -16
- data/lib/uniword/ooxml/types/theme_color_value.rb +22 -0
- data/lib/uniword/ooxml/types/unsigned_decimal_number.rb +30 -0
- data/lib/uniword/ooxml/types.rb +10 -0
- data/lib/uniword/ooxml.rb +2 -0
- data/lib/uniword/properties/alignment.rb +8 -3
- data/lib/uniword/properties/border.rb +52 -6
- data/lib/uniword/properties/cell_vertical_align.rb +4 -1
- data/lib/uniword/properties/color_value.rb +8 -3
- data/lib/uniword/properties/highlight.rb +9 -5
- data/lib/uniword/properties/shading.rb +4 -3
- data/lib/uniword/properties/tab_stop.rb +6 -1
- data/lib/uniword/properties/table_justification.rb +4 -1
- data/lib/uniword/properties/underline.rb +4 -2
- data/lib/uniword/properties/vertical_align.rb +6 -3
- data/lib/uniword/review/review_manager.rb +23 -9
- data/lib/uniword/revision.rb +9 -9
- data/lib/uniword/schema/model_generator.rb +31 -15
- data/lib/uniword/shared_types/hex_color.rb +4 -1
- data/lib/uniword/shared_types/pixel_measure.rb +4 -1
- data/lib/uniword/shared_types/point_measure.rb +4 -1
- data/lib/uniword/shared_types/text_alignment.rb +6 -1
- data/lib/uniword/shared_types/twips_measure.rb +4 -1
- data/lib/uniword/spreadsheetml/phonetic_pr.rb +1 -1
- data/lib/uniword/spreadsheetml/shared_string_table.rb +2 -2
- data/lib/uniword/spreadsheetml/table_formula.rb +1 -1
- data/lib/uniword/template/variable_resolver.rb +40 -7
- data/lib/uniword/themes/theme_transformation.rb +55 -41
- data/lib/uniword/toc/toc_generator.rb +2 -0
- data/lib/uniword/validation/engine.rb +35 -0
- data/lib/uniword/validation/link_checker.rb +1 -1
- data/lib/uniword/validation/opc_validator.rb +0 -1
- data/lib/uniword/validation/report/layer_result.rb +0 -1
- data/lib/uniword/validation/report/terminal_formatter.rb +0 -1
- data/lib/uniword/validation/report/verification_report.rb +0 -2
- data/lib/uniword/validation/report.rb +20 -0
- data/lib/uniword/validation/rules/base.rb +10 -2
- data/lib/uniword/validation/rules/bookmark_pairing_rule.rb +38 -0
- data/lib/uniword/validation/rules/bookmark_uniqueness_rule.rb +48 -0
- data/lib/uniword/validation/rules/bookmarks_rule.rb +0 -2
- data/lib/uniword/validation/rules/content_types_coverage_rule.rb +0 -2
- data/lib/uniword/validation/rules/core_properties_namespace_rule.rb +0 -2
- data/lib/uniword/validation/rules/document_body_rule.rb +25 -0
- data/lib/uniword/validation/rules/document_context.rb +7 -0
- data/lib/uniword/validation/rules/empty_paragraphs_rule.rb +27 -0
- data/lib/uniword/validation/rules/font_table_signature_rule.rb +0 -2
- data/lib/uniword/validation/rules/fonts_rule.rb +0 -2
- data/lib/uniword/validation/rules/footnotes_rule.rb +0 -2
- data/lib/uniword/validation/rules/headers_footers_rule.rb +0 -2
- data/lib/uniword/validation/rules/images_rule.rb +0 -2
- data/lib/uniword/validation/rules/mc_ignorable_namespace_rule.rb +0 -2
- data/lib/uniword/validation/rules/model_context.rb +32 -0
- data/lib/uniword/validation/rules/model_rule.rb +34 -0
- data/lib/uniword/validation/rules/numbering_preservation_rule.rb +0 -2
- data/lib/uniword/validation/rules/numbering_rule.rb +0 -2
- data/lib/uniword/validation/rules/relationship_integrity_rule.rb +0 -1
- data/lib/uniword/validation/rules/rsid_rule.rb +0 -2
- data/lib/uniword/validation/rules/section_properties_rule.rb +0 -2
- data/lib/uniword/validation/rules/settings_rule.rb +0 -2
- data/lib/uniword/validation/rules/settings_values_rule.rb +0 -2
- data/lib/uniword/validation/rules/style_references_rule.rb +0 -2
- data/lib/uniword/validation/rules/table_grid_rule.rb +27 -0
- data/lib/uniword/validation/rules/table_properties_rule.rb +27 -0
- data/lib/uniword/validation/rules/tables_rule.rb +0 -2
- data/lib/uniword/validation/rules/theme_completeness_rule.rb +0 -2
- data/lib/uniword/validation/rules/theme_rule.rb +0 -2
- data/lib/uniword/validation/rules.rb +61 -23
- data/lib/uniword/validation/schema_registry.rb +11 -0
- data/lib/uniword/validation/validators/document_semantics_validator.rb +1 -9
- data/lib/uniword/validation/validators/xml_schema_validator.rb +0 -2
- data/lib/uniword/validation/validators.rb +0 -9
- data/lib/uniword/validation/verify_orchestrator.rb +0 -7
- data/lib/uniword/validation.rb +7 -2
- data/lib/uniword/version.rb +1 -1
- data/lib/uniword/vml/imagedata.rb +0 -1
- data/lib/uniword/wordprocessingml/attached_template.rb +0 -1
- data/lib/uniword/wordprocessingml/deleted_text.rb +1 -1
- data/lib/uniword/wordprocessingml/document_root.rb +211 -21
- data/lib/uniword/wordprocessingml/endnotes.rb +4 -0
- data/lib/uniword/wordprocessingml/font_replacer.rb +147 -0
- data/lib/uniword/wordprocessingml/footnotes.rb +4 -0
- data/lib/uniword/wordprocessingml/hdr_shape_defaults.rb +0 -1
- data/lib/uniword/wordprocessingml/hyperlink.rb +0 -1
- data/lib/uniword/wordprocessingml/level.rb +6 -20
- data/lib/uniword/wordprocessingml/math_pr.rb +0 -11
- data/lib/uniword/wordprocessingml/numbering_definition.rb +16 -8
- data/lib/uniword/wordprocessingml/page_setup.rb +181 -0
- data/lib/uniword/wordprocessingml/paragraph_properties.rb +33 -28
- data/lib/uniword/wordprocessingml/rsids.rb +0 -2
- data/lib/uniword/wordprocessingml/run.rb +3 -0
- data/lib/uniword/wordprocessingml/section_properties.rb +2 -2
- data/lib/uniword/wordprocessingml/settings.rb +8 -34
- data/lib/uniword/wordprocessingml/shape_defaults.rb +0 -1
- data/lib/uniword/wordprocessingml/style.rb +2 -1
- data/lib/uniword/wordprocessingml/style_cleanup.rb +198 -0
- data/lib/uniword/wordprocessingml/table_cell_properties.rb +6 -6
- data/lib/uniword/wordprocessingml/update_fields.rb +27 -0
- data/lib/uniword/wordprocessingml/w14_attributes.rb +30 -2
- data/lib/uniword/wordprocessingml.rb +4 -0
- data/lib/uniword.rb +27 -2
- metadata +38 -19
- data/config/validation_rules.yml +0 -60
- data/config/warning_rules.yml +0 -57
- data/lib/uniword/validation/document_validator.rb +0 -272
- data/lib/uniword/validation/structural_validator.rb +0 -116
- data/lib/uniword/validation/validators/content_type_validator.rb +0 -165
- data/lib/uniword/validation/validators/file_structure_validator.rb +0 -104
- data/lib/uniword/validation/validators/ooxml_part_validator.rb +0 -128
- data/lib/uniword/validation/validators/relationship_validator.rb +0 -147
- data/lib/uniword/validation/validators/zip_integrity_validator.rb +0 -110
- data/lib/uniword/validators/element_validator.rb +0 -93
- data/lib/uniword/validators/paragraph_validator.rb +0 -116
- data/lib/uniword/validators/table_validator.rb +0 -134
- data/lib/uniword/validators.rb +0 -9
- data/lib/uniword/warnings/warning.rb +0 -130
- data/lib/uniword/warnings/warning_collector.rb +0 -234
- data/lib/uniword/warnings/warning_report.rb +0 -159
- data/lib/uniword/warnings.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c28f3b26ea127104f901589ebdb8752163be6f9e963c11eca94a26c86bdbd0df
|
|
4
|
+
data.tar.gz: d8fbe7de4f8f005d78d10acd4f6c1f7459d06385b419c487732e0398470d2c23
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 807f859be7a5b6b45512ea946e4a4b1bd12a8e9df975e9dd9e06dd75c0842d916e5f811e9ac10062873426402b0a3526fa5301a0634e15062fb3f65696f3bd03
|
|
7
|
+
data.tar.gz: 3d6d287a816d2c2cc42a59b5da669dc92026774b0a2e27ff02e33a916367a63336e390338e556d1688b6cb7bbf78676dd5f200b47e8fdcd5c1509e0ebd238f90
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.3.0] - 2026-07-19
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
#### Comment Authoring and Round-Trip Preservation
|
|
16
|
+
- `DocumentBuilder#comment` now anchors the comment around the preceding
|
|
17
|
+
body paragraph (`w:commentRangeStart`/`w:commentRangeEnd` plus a
|
|
18
|
+
`w:commentReference` run styled with the `CommentReference` character
|
|
19
|
+
style, auto-registered in styles.xml) in addition to registering it in
|
|
20
|
+
the document's comments collection
|
|
21
|
+
- Saving a document with comments emits `word/comments.xml` with its
|
|
22
|
+
`[Content_Types].xml` override and `document.xml.rels` relationship
|
|
23
|
+
(part metadata registered in `Ooxml::PartRegistry` under `:comments`);
|
|
24
|
+
loading parses the part into the document's comments collection, so
|
|
25
|
+
comments (ids, authors, dates, text) and their body anchors survive
|
|
26
|
+
load → save round-trips
|
|
27
|
+
- `Builder::CommentAnchorer`: anchor placement for fresh and parsed
|
|
28
|
+
paragraphs (nested anchors on the same paragraph match Word's output)
|
|
29
|
+
- `Wordprocessingml::Run` maps `w:commentReference`
|
|
30
|
+
- `CommentsPart` is the single comments collection for both
|
|
31
|
+
`DocumentBuilder` and `Review::ReviewManager`; it gains Array-style
|
|
32
|
+
access (`size`/`[]`/`each`) and collision-safe sequential ID
|
|
33
|
+
assignment (OOXML `ST_DecimalNumber`)
|
|
34
|
+
|
|
35
|
+
#### Validation Engine Consolidation
|
|
36
|
+
- `Validation::Engine`: single validation engine running the rules of
|
|
37
|
+
`Rules::Registry` against a validation context, with two front-ends
|
|
38
|
+
sharing one result model (`Report::ValidationIssue`)
|
|
39
|
+
- `Rules::ModelContext`: in-memory validation context wrapping a
|
|
40
|
+
`Wordprocessingml::DocumentRoot` (pre-save invocation)
|
|
41
|
+
- `Rules::ModelRule`: base class for in-memory model-level rules;
|
|
42
|
+
`Rules::Base#context_type` (`:package`/`:model`) selects the rule set
|
|
43
|
+
- Model-level rules: DOC-200 (document requires body), DOC-201 (bookmark
|
|
44
|
+
pairing), DOC-202 (bookmark name uniqueness), DOC-203 (empty
|
|
45
|
+
paragraphs), DOC-204 (`tbl` requires `tblGrid` per wml.xsd CT_Tbl),
|
|
46
|
+
DOC-205 (`tbl` requires `tblPr` per wml.xsd CT_Tbl)
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- `DocumentRoot#valid?`, `#validation_errors`, `#validation_warnings` are
|
|
51
|
+
now powered by `Validation::Engine` over the model-level rules instead
|
|
52
|
+
of the deleted `Validation::StructuralValidator`
|
|
53
|
+
- `uniword validate` runs the same engine on the in-memory model, prints
|
|
54
|
+
rule-coded issues, and exits 1 on error-severity issues (aligned with
|
|
55
|
+
`uniword verify`); it previously always exited 0
|
|
56
|
+
- `Validators::DocumentSemanticsValidator` (verify layer 3) runs through
|
|
57
|
+
`Validation::Engine` like every other front-end
|
|
58
|
+
|
|
59
|
+
### Removed
|
|
60
|
+
|
|
61
|
+
- Dead validation code (no production callers):
|
|
62
|
+
`Validation::DocumentValidator` (7-layer pipeline),
|
|
63
|
+
`Validation::StructuralValidator`, the `validation/validators/` layer
|
|
64
|
+
validators unused by `VerifyOrchestrator` (`FileStructureValidator`,
|
|
65
|
+
`ZipIntegrityValidator`, `OoxmlPartValidator`, `RelationshipValidator`,
|
|
66
|
+
`ContentTypeValidator`), the `Uniword::Validators` stub namespace
|
|
67
|
+
(`ElementValidator`/`ParagraphValidator`/`TableValidator`), the
|
|
68
|
+
`Uniword::Warnings` module (`Warning`/`WarningCollector`/
|
|
69
|
+
`WarningReport`), and the orphaned `config/validation_rules.yml` and
|
|
70
|
+
`config/warning_rules.yml`
|
|
71
|
+
|
|
11
72
|
### Added
|
|
12
73
|
|
|
13
74
|
#### Open-Source Resource System (April 2025)
|
|
@@ -41,8 +102,140 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
41
102
|
- Injects missing separator (id=-1) and continuation (id=0) entries
|
|
42
103
|
- Runs during `Docx::Package#to_zip_content` before serialization
|
|
43
104
|
|
|
105
|
+
#### Write-Time Validation and Reconciler Transparency (July 2026)
|
|
106
|
+
- `Docx::PackageIntegrityChecker`: write-time OPC integrity gate invoked on
|
|
107
|
+
every save after reconciliation, before packaging; refuses invalid output
|
|
108
|
+
(missing content types, unresolvable relationship targets, dangling
|
|
109
|
+
`r:id`/`r:embed`/`r:link` references, duplicate rIds, malformed XML)
|
|
110
|
+
- Saves raise `Uniword::ValidationError` with structured `issues` (code,
|
|
111
|
+
part, message) when the gate rejects the package
|
|
112
|
+
- Escape hatch: `save(path, validate: false)` threaded through
|
|
113
|
+
`DocumentRoot#save`/`#to_file`, `DocumentWriter`, `Docx::Package.to_file`
|
|
114
|
+
and `Ooxml::DotxPackage.to_file`; default from
|
|
115
|
+
`Uniword.configuration.validate_on_save` (default `true`)
|
|
116
|
+
- `Uniword.configuration.log_save_fixes` (default `true`): log each repair
|
|
117
|
+
the Reconciler applies during save
|
|
118
|
+
- `Docx::Package#applied_fixes`: reconciliation report (Fix value objects
|
|
119
|
+
with code, message, part) exposed after save
|
|
120
|
+
- Reconciler now repairs dangling `r:embed` image references by removing
|
|
121
|
+
the drawing, and strips relationships whose target part the package does
|
|
122
|
+
not carry (e.g. unmodelled parts dropped on load) — recorded as fixes
|
|
123
|
+
- Allocator (builder) and legacy (template) save paths now apply identical
|
|
124
|
+
referential repairs (previously the builder path only logged warnings)
|
|
125
|
+
- `SchemaRegistry` now maps `word/webSettings.xml` and the docProps
|
|
126
|
+
core/app/custom parts to their XSDs; `docProps/core.xml` validates
|
|
127
|
+
offline (Dublin Core XSD imports bundled with relative schemaLocations)
|
|
128
|
+
- Integration spec now XSD-validates real library output end-to-end
|
|
129
|
+
(Builder corpus + fixture round-trips) via `uniword verify --xsd`
|
|
130
|
+
semantics
|
|
131
|
+
- `uniword theme fonts INPUT OUTPUT --name X` and `uniword theme colors
|
|
132
|
+
INPUT OUTPUT --name Y`: apply a bundled font scheme (25) or color
|
|
133
|
+
scheme (23) to an existing document — Word's Design → Fonts / Colors
|
|
134
|
+
galleries as CLI commands, replacing only the targeted theme element
|
|
135
|
+
(`--list` shows available schemes); also available as
|
|
136
|
+
`DocumentRoot#apply_font_scheme` / `#apply_color_scheme`
|
|
137
|
+
- `uniword fonts replace INPUT OUTPUT --from X --to Y`: Word's
|
|
138
|
+
Replace Fonts dialog as a one-shot CLI command — rewrites rFonts
|
|
139
|
+
references across styles and defaults, body content, headers/footers,
|
|
140
|
+
notes, comments, and numbering (also `DocumentRoot#replace_font`)
|
|
141
|
+
- `w:updateFields` support: `uniword toc insert` / `toc update` now set
|
|
142
|
+
it by default (`--no-update-fields` to opt out), so Word refreshes
|
|
143
|
+
the TOC and all fields when the document is opened — no manual F9
|
|
144
|
+
- Comments can now target an arbitrary paragraph:
|
|
145
|
+
`doc.comment(author:, text:, on: paragraph_or_index)` — anchor around
|
|
146
|
+
any existing paragraph object or body index, including paragraphs
|
|
147
|
+
inside table cells (default remains the last paragraph)
|
|
148
|
+
- `uniword page setup INPUT OUTPUT`: Word's Layout dialog as a CLI
|
|
149
|
+
command — paper size presets (letter/legal/a4/a5/executive),
|
|
150
|
+
orientation with Word-style dimension swap, and margins in
|
|
151
|
+
in/cm/mm/twips units, applied to every section (also
|
|
152
|
+
`DocumentRoot#apply_page_setup`)
|
|
153
|
+
- `uniword styles list FILE [--type T] [--verbose]`: Word's Styles
|
|
154
|
+
pane as a terminal listing — style id, type, base style, and key
|
|
155
|
+
formatting details
|
|
156
|
+
- `uniword styles remove FILE OUTPUT [--id X | --unused] [--dry-run]`:
|
|
157
|
+
Styles-pane management as a one-shot command — delete a style by id,
|
|
158
|
+
or declutter every style that no content references (directly or via
|
|
159
|
+
basedOn/link/next chains); default styles are always kept (also
|
|
160
|
+
`DocumentRoot#remove_style` / `#remove_unused_styles`)
|
|
161
|
+
- `uniword styles rename FILE OUTPUT --id X --name Y`: Word's style
|
|
162
|
+
rename — updates the display name while the styleId (and every
|
|
163
|
+
reference to it) stays intact (also `DocumentRoot#rename_style`)
|
|
164
|
+
- `uniword repair INPUT OUTPUT`: load a document, run the save-time
|
|
165
|
+
Reconciler over it, and write a repaired copy — dangling references
|
|
166
|
+
stripped, missing parts rebuilt — with every repair reported by code
|
|
167
|
+
(substantive repairs vs routine normalization); exits non-zero when
|
|
168
|
+
the write-time gate rejects what the Reconciler cannot fix
|
|
169
|
+
|
|
170
|
+
### Fixed
|
|
171
|
+
|
|
172
|
+
- `w:lvl` no longer emits `w:ind`/`w:tabs` as direct children (invalid per
|
|
173
|
+
ECMA-376 CT_Lvl); numbering level indentation is now written via the
|
|
174
|
+
level's `w:pPr` — previously every Builder-generated list produced
|
|
175
|
+
schema-invalid `numbering.xml`
|
|
176
|
+
- Dangling image drawings and their relationships are now removed in a
|
|
177
|
+
single reconcile pass: a drawing whose `r:embed` rel exists but points
|
|
178
|
+
at a part the package does not carry is treated as dangling (previously
|
|
179
|
+
the first pass kept the drawing and stripped the rel, leaving a new
|
|
180
|
+
dangling reference for the next save)
|
|
181
|
+
- `word/_rels/settings.xml.rels`, `word/_rels/footnotes.xml.rels` and
|
|
182
|
+
`word/_rels/endnotes.xml.rels` now survive load → save round-trips on
|
|
183
|
+
both save paths (previously dropped, leaving dangling `r:id`
|
|
184
|
+
references in the saved package)
|
|
185
|
+
- Saving no longer crashes with FrozenError when the Reconciler injects
|
|
186
|
+
missing footnote/endnote separator entries into a parsed document
|
|
187
|
+
- Theme application no longer produces invalid `theme1.xml`:
|
|
188
|
+
`Drawingml::Theme#dup` silently dropped the format scheme (fill/line/
|
|
189
|
+
effect lists), so every `theme apply` emitted a `fillStyleLst` Word
|
|
190
|
+
rejects as "unreadable content"; the save-time fill repair also used
|
|
191
|
+
a wrong attribute kwarg (`scheme_color:` for `scheme_clr:`), creating
|
|
192
|
+
color-less fills. Both fixed — applied themes now carry the complete
|
|
193
|
+
format scheme. Same family fixed in `FontScheme#dup` (per-script
|
|
194
|
+
font entries were dropped) and `ColorScheme#dup` (system-color
|
|
195
|
+
entries like windowText were lost)
|
|
196
|
+
- Tables whose `gridCol` columns lack widths now get even shares of the
|
|
197
|
+
section content width (page width minus margins) at save time —
|
|
198
|
+
matching Word's fallback — instead of emitting width-less `gridCol`
|
|
199
|
+
elements and warning; explicit widths are preserved and the remainder
|
|
200
|
+
is shared
|
|
201
|
+
- `uniword verify`-style integration spec hang: `soffice --view` example
|
|
202
|
+
no longer blocks the LibreOffice integration spec indefinitely
|
|
203
|
+
- Header/footer dual path: adding a header/footer via the Builder to a
|
|
204
|
+
loaded document no longer drops the new part, duplicates
|
|
205
|
+
relationships or content-type overrides, or points two sectPr
|
|
206
|
+
references at the same rId. Round-trips that previously re-added a
|
|
207
|
+
stale relationship with the original rId (duplicate target rels, e.g.
|
|
208
|
+
on the APA paper template) now emit exactly one rel per part
|
|
209
|
+
- `uniword headers list` now reports headers/footers of loaded
|
|
210
|
+
documents, and `headers add-header` / watermark managers no longer
|
|
211
|
+
crash when saving (both used to bypass the round-trip storage)
|
|
212
|
+
- rId stability through round-trip: `Docx::IdAllocator` is now the single
|
|
213
|
+
rId authority for all relationships parts. Loaded documents round-trip
|
|
214
|
+
with their original rIds preserved verbatim (previously the reconciler
|
|
215
|
+
renumbered every rId on save, e.g. `r:embed="rId8"` becoming
|
|
216
|
+
`"rId9"`); only genuinely new relationships (builder-added images,
|
|
217
|
+
hyperlinks, charts, headers/footers) receive fresh allocations.
|
|
218
|
+
The 3 long-skipped `docx_roundtrip_spec.rb` round-trip examples
|
|
219
|
+
(APA template, two ISO fixtures) now pass unskipped
|
|
220
|
+
- Loaded image parts are now keyed by their actual document relationship
|
|
221
|
+
rId, so `r:embed` references resolve correctly in MHTML conversion and
|
|
222
|
+
the image manager; theme-only media no longer gains a spurious
|
|
223
|
+
document-level relationship on save
|
|
224
|
+
- Adding the same image file twice now stores one part with one
|
|
225
|
+
relationship shared by both drawings (previously produced a dangling
|
|
226
|
+
duplicate rId reference)
|
|
227
|
+
|
|
44
228
|
### Changed
|
|
45
229
|
|
|
230
|
+
- `Uniword::Ooxml::Relationships::PackageRelationships.next_available_rid`
|
|
231
|
+
removed: all rId assignment flows through `Docx::IdAllocator` (scoped
|
|
232
|
+
per rels part — `:document`/`:package` — with `seed_from_rels`
|
|
233
|
+
preserving loaded rIds verbatim). The reconciler's legacy renumbering
|
|
234
|
+
path, the serializer-side `next_rid`, and `ChartBuilder`'s literal
|
|
235
|
+
`rIdChartN` ids are gone; chart relationship ids are now allocator
|
|
236
|
+
numerics. The reconciler's light-touch vs full normalization choice is
|
|
237
|
+
now explicit (`builder_managed`) instead of inferred from allocator
|
|
238
|
+
presence
|
|
46
239
|
- `Uniword::Ooxml::DocxPackage` renamed to `Uniword::Docx::Package`
|
|
47
240
|
- All references in lib/ and spec/ updated (~20 files)
|
|
48
241
|
- `lib/uniword/ooxml/docx_package.rb` moved to `lib/uniword/docx/package.rb`
|
|
@@ -52,6 +245,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
52
245
|
- All 12 stylesets reauthored with OFL-licensed fonts (Calibri references fixed)
|
|
53
246
|
- `uniword.gemspec` updated to include `data/**/*.yml` and `data/**/*.xsd` in gem
|
|
54
247
|
- Added `rainbow ~> 3.1` gem dependency
|
|
248
|
+
- Single `Uniword::Ooxml::PartRegistry` now owns the part↔content-type↔
|
|
249
|
+
relationship-type mapping for every DOCX part kind the library writes
|
|
250
|
+
- New `Ooxml::PartDefinition` value class (key, path/pattern, content
|
|
251
|
+
type, relationship type, extension, required, default-vs-override)
|
|
252
|
+
- `ContentTypes.generate`, `Docx::PackageDefaults.minimal_*`,
|
|
253
|
+
`Reconciler::PackageStructure`, and the `PackageSerialization`
|
|
254
|
+
`inject_*` methods derive from the registry instead of holding
|
|
255
|
+
string literals; `IdAllocator` and builder rel-type constants also
|
|
256
|
+
derive from it
|
|
257
|
+
- Open/closed: register a `PartDefinition` to add a part kind —
|
|
258
|
+
consumers need no changes
|
|
259
|
+
- No behavior change: saved packages are byte-identical
|
|
260
|
+
- Package-held parts are now model objects instead of raw hashes
|
|
261
|
+
- New `Uniword::Docx::Part` value object (definition, rId, target,
|
|
262
|
+
content, verbatim rel-type/content-type overrides) with `ChartPart`
|
|
263
|
+
and `HeaderFooterPart` subclasses and `CustomXmlItem`;
|
|
264
|
+
`Docx::PartCollection` backs `chart_parts` (keyed by rId) and
|
|
265
|
+
`embeddings` (keyed by target)
|
|
266
|
+
- Single header/footer storage path: `DocumentRoot#header_footer_parts`
|
|
267
|
+
is a `Docx::HeaderFooterPartCollection` fed identically by the loader
|
|
268
|
+
(original rIds/targets, sectPr-derived types) and the Builder;
|
|
269
|
+
`document.headers`/`document.footers` are delegating
|
|
270
|
+
`Docx::HeaderFooterView`s over that store (Hash-style by sectPr type,
|
|
271
|
+
Array-style over parts) — public API preserved
|
|
272
|
+
- Single wiring implementation: the Reconciler wires fresh
|
|
273
|
+
header/footer parts into `document.xml.rels` and sectPr
|
|
274
|
+
(`IdAllocator` on the builder path, `find_or_create_rel` on the
|
|
275
|
+
legacy path); the serializer's duplicate rel/sectPr wiring and its
|
|
276
|
+
divergent rId strategy are deleted — it now only emits one part
|
|
277
|
+
file and one content-type override per store entry
|
|
55
278
|
|
|
56
279
|
#### StylesetPackage Implementation (December 4, 2024)
|
|
57
280
|
- **StylesetPackage**: Proper MODEL-DRIVEN package for .dotx files
|
data/CONTRIBUTING.md
CHANGED
|
@@ -226,7 +226,7 @@ After adding any class (autoload or require_relative):
|
|
|
226
226
|
**Good (autoload)**:
|
|
227
227
|
```ruby
|
|
228
228
|
# New utility class with no dependencies
|
|
229
|
-
autoload :
|
|
229
|
+
autoload :DocumentFactory, 'uniword/document_factory'
|
|
230
230
|
```
|
|
231
231
|
|
|
232
232
|
**Good (require_relative with documentation)**:
|
|
@@ -46,7 +46,7 @@ elements:
|
|
|
46
46
|
description: 'Hexadecimal color value (RGB)'
|
|
47
47
|
attributes:
|
|
48
48
|
- name: val
|
|
49
|
-
type:
|
|
49
|
+
type: Uniword::Ooxml::Types::HexColorValue
|
|
50
50
|
xml_name: val
|
|
51
51
|
xml_attribute: true
|
|
52
52
|
required: true
|
|
@@ -57,7 +57,7 @@ elements:
|
|
|
57
57
|
description: 'Measurement in twips (1/20th of a point)'
|
|
58
58
|
attributes:
|
|
59
59
|
- name: val
|
|
60
|
-
type:
|
|
60
|
+
type: Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
61
61
|
xml_name: val
|
|
62
62
|
xml_attribute: true
|
|
63
63
|
required: true
|
|
@@ -79,7 +79,7 @@ elements:
|
|
|
79
79
|
description: 'Measurement in points'
|
|
80
80
|
attributes:
|
|
81
81
|
- name: val
|
|
82
|
-
type:
|
|
82
|
+
type: Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
83
83
|
xml_name: val
|
|
84
84
|
xml_attribute: true
|
|
85
85
|
required: true
|
|
@@ -90,7 +90,7 @@ elements:
|
|
|
90
90
|
description: 'Measurement in pixels'
|
|
91
91
|
attributes:
|
|
92
92
|
- name: val
|
|
93
|
-
type:
|
|
93
|
+
type: Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
94
94
|
xml_name: val
|
|
95
95
|
xml_attribute: true
|
|
96
96
|
required: true
|
|
@@ -135,6 +135,7 @@ elements:
|
|
|
135
135
|
attributes:
|
|
136
136
|
- name: val
|
|
137
137
|
type: :string
|
|
138
|
+
values: [top, center, baseline, bottom, auto]
|
|
138
139
|
xml_name: val
|
|
139
140
|
xml_attribute: true
|
|
140
141
|
required: true
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
3
|
+
xmlns="http://purl.org/dc/elements/1.1/"
|
|
4
|
+
targetNamespace="http://purl.org/dc/elements/1.1/"
|
|
5
|
+
elementFormDefault="qualified"
|
|
6
|
+
attributeFormDefault="unqualified">
|
|
7
|
+
|
|
8
|
+
<xs:annotation>
|
|
9
|
+
<xs:documentation xml:lang="en">
|
|
10
|
+
DCMES 1.1 XML Schema
|
|
11
|
+
XML Schema for http://purl.org/dc/elements/1.1/ namespace
|
|
12
|
+
|
|
13
|
+
Created 2003-04-02
|
|
14
|
+
|
|
15
|
+
Created by
|
|
16
|
+
|
|
17
|
+
Tim Cole (t-cole3@uiuc.edu)
|
|
18
|
+
Tom Habing (thabing@uiuc.edu)
|
|
19
|
+
Jane Hunter (jane@dstc.edu.au)
|
|
20
|
+
Pete Johnston (p.johnston@ukoln.ac.uk),
|
|
21
|
+
Carl Lagoze (lagoze@cs.cornell.edu)
|
|
22
|
+
|
|
23
|
+
This schema declares XML elements for the 15 DC elements from the
|
|
24
|
+
http://purl.org/dc/elements/1.1/ namespace.
|
|
25
|
+
|
|
26
|
+
It defines a complexType SimpleLiteral which permits mixed content
|
|
27
|
+
and makes the xml:lang attribute available. It disallows child elements by
|
|
28
|
+
use of minOcccurs/maxOccurs.
|
|
29
|
+
|
|
30
|
+
However, this complexType does permit the derivation of other complexTypes
|
|
31
|
+
which would permit child elements.
|
|
32
|
+
|
|
33
|
+
All elements are declared as substitutable for the abstract element any,
|
|
34
|
+
which means that the default type for all elements is dc:SimpleLiteral.
|
|
35
|
+
|
|
36
|
+
</xs:documentation>
|
|
37
|
+
|
|
38
|
+
</xs:annotation>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
|
|
42
|
+
schemaLocation="xml.xsd">
|
|
43
|
+
</xs:import>
|
|
44
|
+
|
|
45
|
+
<xs:complexType name="SimpleLiteral">
|
|
46
|
+
<xs:annotation>
|
|
47
|
+
<xs:documentation xml:lang="en">
|
|
48
|
+
This is the default type for all of the DC elements.
|
|
49
|
+
It permits text content only with optional
|
|
50
|
+
xml:lang attribute.
|
|
51
|
+
Text is allowed because mixed="true", but sub-elements
|
|
52
|
+
are disallowed because minOccurs="0" and maxOccurs="0"
|
|
53
|
+
are on the xs:any tag.
|
|
54
|
+
|
|
55
|
+
This complexType allows for restriction or extension permitting
|
|
56
|
+
child elements.
|
|
57
|
+
</xs:documentation>
|
|
58
|
+
</xs:annotation>
|
|
59
|
+
|
|
60
|
+
<xs:complexContent mixed="true">
|
|
61
|
+
<xs:restriction base="xs:anyType">
|
|
62
|
+
<xs:sequence>
|
|
63
|
+
<xs:any processContents="lax" minOccurs="0" maxOccurs="0"/>
|
|
64
|
+
</xs:sequence>
|
|
65
|
+
<xs:attribute ref="xml:lang" use="optional"/>
|
|
66
|
+
</xs:restriction>
|
|
67
|
+
</xs:complexContent>
|
|
68
|
+
</xs:complexType>
|
|
69
|
+
|
|
70
|
+
<xs:element name="any" type="SimpleLiteral" abstract="true"/>
|
|
71
|
+
|
|
72
|
+
<xs:element name="title" substitutionGroup="any"/>
|
|
73
|
+
<xs:element name="creator" substitutionGroup="any"/>
|
|
74
|
+
<xs:element name="subject" substitutionGroup="any"/>
|
|
75
|
+
<xs:element name="description" substitutionGroup="any"/>
|
|
76
|
+
<xs:element name="publisher" substitutionGroup="any"/>
|
|
77
|
+
<xs:element name="contributor" substitutionGroup="any"/>
|
|
78
|
+
<xs:element name="date" substitutionGroup="any"/>
|
|
79
|
+
<xs:element name="type" substitutionGroup="any"/>
|
|
80
|
+
<xs:element name="format" substitutionGroup="any"/>
|
|
81
|
+
<xs:element name="identifier" substitutionGroup="any"/>
|
|
82
|
+
<xs:element name="source" substitutionGroup="any"/>
|
|
83
|
+
<xs:element name="language" substitutionGroup="any"/>
|
|
84
|
+
<xs:element name="relation" substitutionGroup="any"/>
|
|
85
|
+
<xs:element name="coverage" substitutionGroup="any"/>
|
|
86
|
+
<xs:element name="rights" substitutionGroup="any"/>
|
|
87
|
+
|
|
88
|
+
<xs:group name="elementsGroup">
|
|
89
|
+
<xs:annotation>
|
|
90
|
+
<xs:documentation xml:lang="en">
|
|
91
|
+
This group is included as a convenience for schema authors
|
|
92
|
+
who need to refer to all the elements in the
|
|
93
|
+
http://purl.org/dc/elements/1.1/ namespace.
|
|
94
|
+
</xs:documentation>
|
|
95
|
+
</xs:annotation>
|
|
96
|
+
|
|
97
|
+
<xs:sequence>
|
|
98
|
+
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
|
99
|
+
<xs:element ref="any"/>
|
|
100
|
+
</xs:choice>
|
|
101
|
+
</xs:sequence>
|
|
102
|
+
</xs:group>
|
|
103
|
+
|
|
104
|
+
<xs:complexType name="elementContainer">
|
|
105
|
+
<xs:annotation>
|
|
106
|
+
<xs:documentation xml:lang="en">
|
|
107
|
+
This complexType is included as a convenience for schema authors who need to define a root
|
|
108
|
+
or container element for all of the DC elements.
|
|
109
|
+
</xs:documentation>
|
|
110
|
+
</xs:annotation>
|
|
111
|
+
|
|
112
|
+
<xs:choice>
|
|
113
|
+
<xs:group ref="elementsGroup"/>
|
|
114
|
+
</xs:choice>
|
|
115
|
+
</xs:complexType>
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
</xs:schema>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
3
|
+
xmlns="http://purl.org/dc/dcmitype/"
|
|
4
|
+
targetNamespace="http://purl.org/dc/dcmitype/"
|
|
5
|
+
elementFormDefault="qualified"
|
|
6
|
+
attributeFormDefault="unqualified">
|
|
7
|
+
|
|
8
|
+
<xs:annotation>
|
|
9
|
+
<xs:documentation xml:lang="en">
|
|
10
|
+
DCMI Type Vocabulary XML Schema
|
|
11
|
+
XML Schema for http://purl.org/dc/dcmitype/ namespace
|
|
12
|
+
|
|
13
|
+
Created 2003-04-02
|
|
14
|
+
|
|
15
|
+
Created by
|
|
16
|
+
|
|
17
|
+
Tim Cole (t-cole3@uiuc.edu)
|
|
18
|
+
Tom Habing (thabing@uiuc.edu)
|
|
19
|
+
Jane Hunter (jane@dstc.edu.au)
|
|
20
|
+
Pete Johnston (p.johnston@ukoln.ac.uk),
|
|
21
|
+
Carl Lagoze (lagoze@cs.cornell.edu)
|
|
22
|
+
|
|
23
|
+
This schema defines a simpleType which enumerates
|
|
24
|
+
the allowable values for the DCMI Type Vocabulary.
|
|
25
|
+
</xs:documentation>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
</xs:annotation>
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
<xs:simpleType name="DCMIType">
|
|
32
|
+
<xs:union>
|
|
33
|
+
<xs:simpleType>
|
|
34
|
+
<xs:restriction base="xs:Name">
|
|
35
|
+
<xs:enumeration value="Collection"/>
|
|
36
|
+
<xs:enumeration value="Dataset"/>
|
|
37
|
+
<xs:enumeration value="Event"/>
|
|
38
|
+
<xs:enumeration value="Image"/>
|
|
39
|
+
<xs:enumeration value="InteractiveResource"/>
|
|
40
|
+
<xs:enumeration value="Service"/>
|
|
41
|
+
<xs:enumeration value="Software"/>
|
|
42
|
+
<xs:enumeration value="Sound"/>
|
|
43
|
+
<xs:enumeration value="Text"/>
|
|
44
|
+
<xs:enumeration value="PhysicalObject"/>
|
|
45
|
+
</xs:restriction>
|
|
46
|
+
</xs:simpleType>
|
|
47
|
+
</xs:union>
|
|
48
|
+
</xs:simpleType>
|
|
49
|
+
|
|
50
|
+
</xs:schema>
|