uniword 1.0.9 → 1.0.11
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/data/themes/office_format_scheme.xml +137 -0
- data/data/themes/office_theme.xml +2 -0
- data/lib/uniword/builder/footnote_builder.rb +4 -2
- data/lib/uniword/builder/run_builder.rb +5 -0
- data/lib/uniword/document_factory.rb +1 -0
- data/lib/uniword/docx/package.rb +18 -0
- data/lib/uniword/docx/package_defaults.rb +1 -0
- data/lib/uniword/docx/package_serialization.rb +38 -0
- data/lib/uniword/docx/reconciler.rb +195 -13
- data/lib/uniword/lazy_loader.rb +1 -1
- data/lib/uniword/properties/boolean_element_factory.rb +8 -15
- data/lib/uniword/schema/schema_loader.rb +1 -1
- data/lib/uniword/transformation/mhtml_style_builder.rb +9 -2
- data/lib/uniword/transformation/ooxml_to_mhtml_converter.rb +7 -15
- data/lib/uniword/transformation/yaml_css_generator.rb +815 -0
- data/lib/uniword/transformation.rb +2 -0
- data/lib/uniword/version.rb +1 -1
- data/lib/uniword/wordprocessingml/attached_template.rb +18 -0
- data/lib/uniword/wordprocessingml/body.rb +34 -34
- data/lib/uniword/wordprocessingml/brk_bin.rb +17 -0
- data/lib/uniword/wordprocessingml/brk_bin_sub.rb +17 -0
- data/lib/uniword/wordprocessingml/character_spacing_control.rb +17 -0
- data/lib/uniword/wordprocessingml/clr_scheme_mapping.rb +39 -0
- data/lib/uniword/wordprocessingml/compat.rb +16 -0
- data/lib/uniword/wordprocessingml/decimal_symbol.rb +17 -0
- data/lib/uniword/wordprocessingml/def_jc.rb +17 -0
- data/lib/uniword/wordprocessingml/default_tab_stop.rb +17 -0
- data/lib/uniword/wordprocessingml/disp_def.rb +14 -0
- data/lib/uniword/wordprocessingml/do_not_display_page_boundaries.rb +14 -0
- data/lib/uniword/wordprocessingml/do_not_include_subdocs_in_stats.rb +17 -0
- data/lib/uniword/wordprocessingml/doc_vars.rb +36 -0
- data/lib/uniword/wordprocessingml/document_root.rb +8 -5
- data/lib/uniword/wordprocessingml/endnote_pr.rb +18 -0
- data/lib/uniword/wordprocessingml/endnotes.rb +18 -0
- data/lib/uniword/wordprocessingml/even_and_odd_headers.rb +17 -0
- data/lib/uniword/wordprocessingml/footnote_pos.rb +17 -0
- data/lib/uniword/wordprocessingml/footnote_pr.rb +20 -0
- data/lib/uniword/wordprocessingml/footnotes.rb +18 -0
- data/lib/uniword/wordprocessingml/hdr_shape_defaults.rb +19 -0
- data/lib/uniword/wordprocessingml/hyphenation_zone.rb +20 -0
- data/lib/uniword/wordprocessingml/int_lim.rb +17 -0
- data/lib/uniword/wordprocessingml/l_margin.rb +17 -0
- data/lib/uniword/wordprocessingml/list_separator.rb +17 -0
- data/lib/uniword/wordprocessingml/math_font.rb +17 -0
- data/lib/uniword/wordprocessingml/math_pr.rb +49 -0
- data/lib/uniword/wordprocessingml/mirror_margins.rb +17 -0
- data/lib/uniword/wordprocessingml/nary_lim.rb +17 -0
- data/lib/uniword/wordprocessingml/proof_state.rb +19 -0
- data/lib/uniword/wordprocessingml/r_margin.rb +17 -0
- data/lib/uniword/wordprocessingml/rsid.rb +17 -0
- data/lib/uniword/wordprocessingml/rsid_root.rb +17 -0
- data/lib/uniword/wordprocessingml/rsids.rb +22 -0
- data/lib/uniword/wordprocessingml/settings.rb +45 -511
- data/lib/uniword/wordprocessingml/shape_defaults.rb +21 -0
- data/lib/uniword/wordprocessingml/small_frac.rb +17 -0
- data/lib/uniword/wordprocessingml/style_pane_format_filter.rb +50 -0
- data/lib/uniword/wordprocessingml/style_pane_sort_method.rb +20 -0
- data/lib/uniword/wordprocessingml/table_cell.rb +6 -0
- data/lib/uniword/wordprocessingml/table_row_properties.rb +2 -0
- data/lib/uniword/wordprocessingml/theme_font_lang.rb +19 -0
- data/lib/uniword/wordprocessingml/w14_doc_id.rb +17 -0
- data/lib/uniword/wordprocessingml/w15_chart_tracking_ref_based.rb +14 -0
- data/lib/uniword/wordprocessingml/w15_doc_id.rb +17 -0
- data/lib/uniword/wordprocessingml/wrap_indent.rb +17 -0
- data/lib/uniword/wordprocessingml.rb +42 -56
- data/lib/uniword.rb +12 -5
- metadata +50 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bdd8529445dab8a8008addcef94857f4dc453cea19ece485baaac0ef1c4701f2
|
|
4
|
+
data.tar.gz: cbba0e318b8fde04e96cf0717f82e1a4a827ac4c73e47b8c4af853ba4dbd77be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 92dc72fbc93219b74f58bb901aca4d1bda56786c761a04ceb724ffad3417406a13e92f962808613d495f8f68a0955278a9f9a2fcfef29848f6d803f88beab907
|
|
7
|
+
data.tar.gz: 59f335ab79d4cb3b72c80c9b07ffecaf3705285017ab494490c1d6f331fa310205a50ccc2b1f3bb2397c313cb392ee33fa99aec477edaac4cba0b11b4fed3f0f
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<a:fmtScheme name="Office">
|
|
2
|
+
<a:fillStyleLst>
|
|
3
|
+
<a:solidFill>
|
|
4
|
+
<a:schemeClr val="phClr"/>
|
|
5
|
+
</a:solidFill>
|
|
6
|
+
<a:gradFill rotWithShape="1">
|
|
7
|
+
<a:gsLst>
|
|
8
|
+
<a:gs pos="0">
|
|
9
|
+
<a:schemeClr val="phClr">
|
|
10
|
+
<a:lumMod val="110000"/>
|
|
11
|
+
<a:satMod val="105000"/>
|
|
12
|
+
<a:tint val="67000"/>
|
|
13
|
+
</a:schemeClr>
|
|
14
|
+
</a:gs>
|
|
15
|
+
<a:gs pos="50000">
|
|
16
|
+
<a:schemeClr val="phClr">
|
|
17
|
+
<a:lumMod val="105000"/>
|
|
18
|
+
<a:satMod val="103000"/>
|
|
19
|
+
<a:tint val="73000"/>
|
|
20
|
+
</a:schemeClr>
|
|
21
|
+
</a:gs>
|
|
22
|
+
<a:gs pos="100000">
|
|
23
|
+
<a:schemeClr val="phClr">
|
|
24
|
+
<a:lumMod val="105000"/>
|
|
25
|
+
<a:satMod val="109000"/>
|
|
26
|
+
<a:tint val="81000"/>
|
|
27
|
+
</a:schemeClr>
|
|
28
|
+
</a:gs>
|
|
29
|
+
</a:gsLst>
|
|
30
|
+
<a:lin ang="5400000" scaled="0"/>
|
|
31
|
+
</a:gradFill>
|
|
32
|
+
<a:gradFill rotWithShape="1">
|
|
33
|
+
<a:gsLst>
|
|
34
|
+
<a:gs pos="0">
|
|
35
|
+
<a:schemeClr val="phClr">
|
|
36
|
+
<a:satMod val="103000"/>
|
|
37
|
+
<a:lumMod val="102000"/>
|
|
38
|
+
<a:tint val="94000"/>
|
|
39
|
+
</a:schemeClr>
|
|
40
|
+
</a:gs>
|
|
41
|
+
<a:gs pos="50000">
|
|
42
|
+
<a:schemeClr val="phClr">
|
|
43
|
+
<a:satMod val="110000"/>
|
|
44
|
+
<a:lumMod val="100000"/>
|
|
45
|
+
<a:shade val="100000"/>
|
|
46
|
+
</a:schemeClr>
|
|
47
|
+
</a:gs>
|
|
48
|
+
<a:gs pos="100000">
|
|
49
|
+
<a:schemeClr val="phClr">
|
|
50
|
+
<a:lumMod val="99000"/>
|
|
51
|
+
<a:satMod val="120000"/>
|
|
52
|
+
<a:shade val="78000"/>
|
|
53
|
+
</a:schemeClr>
|
|
54
|
+
</a:gs>
|
|
55
|
+
</a:gsLst>
|
|
56
|
+
<a:lin ang="5400000" scaled="0"/>
|
|
57
|
+
</a:gradFill>
|
|
58
|
+
</a:fillStyleLst>
|
|
59
|
+
<a:lnStyleLst>
|
|
60
|
+
<a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
|
|
61
|
+
<a:solidFill>
|
|
62
|
+
<a:schemeClr val="phClr"/>
|
|
63
|
+
</a:solidFill>
|
|
64
|
+
<a:prstDash val="solid"/>
|
|
65
|
+
<a:miter lim="800000"/>
|
|
66
|
+
</a:ln>
|
|
67
|
+
<a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">
|
|
68
|
+
<a:solidFill>
|
|
69
|
+
<a:schemeClr val="phClr"/>
|
|
70
|
+
</a:solidFill>
|
|
71
|
+
<a:prstDash val="solid"/>
|
|
72
|
+
<a:miter lim="800000"/>
|
|
73
|
+
</a:ln>
|
|
74
|
+
<a:ln w="25400" cap="flat" cmpd="sng" algn="ctr">
|
|
75
|
+
<a:solidFill>
|
|
76
|
+
<a:schemeClr val="phClr"/>
|
|
77
|
+
</a:solidFill>
|
|
78
|
+
<a:prstDash val="solid"/>
|
|
79
|
+
<a:miter lim="800000"/>
|
|
80
|
+
</a:ln>
|
|
81
|
+
</a:lnStyleLst>
|
|
82
|
+
<a:effectStyleLst>
|
|
83
|
+
<a:effectStyle>
|
|
84
|
+
<a:effectLst/>
|
|
85
|
+
</a:effectStyle>
|
|
86
|
+
<a:effectStyle>
|
|
87
|
+
<a:effectLst/>
|
|
88
|
+
</a:effectStyle>
|
|
89
|
+
<a:effectStyle>
|
|
90
|
+
<a:effectLst>
|
|
91
|
+
<a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">
|
|
92
|
+
<a:srgbClr val="000000">
|
|
93
|
+
<a:alpha val="63000"/>
|
|
94
|
+
</a:srgbClr>
|
|
95
|
+
</a:outerShdw>
|
|
96
|
+
</a:effectLst>
|
|
97
|
+
</a:effectStyle>
|
|
98
|
+
</a:effectStyleLst>
|
|
99
|
+
<a:bgFillStyleLst>
|
|
100
|
+
<a:solidFill>
|
|
101
|
+
<a:schemeClr val="phClr"/>
|
|
102
|
+
</a:solidFill>
|
|
103
|
+
<a:solidFill>
|
|
104
|
+
<a:schemeClr val="phClr">
|
|
105
|
+
<a:tint val="95000"/>
|
|
106
|
+
<a:satMod val="170000"/>
|
|
107
|
+
</a:schemeClr>
|
|
108
|
+
</a:solidFill>
|
|
109
|
+
<a:gradFill rotWithShape="1">
|
|
110
|
+
<a:gsLst>
|
|
111
|
+
<a:gs pos="0">
|
|
112
|
+
<a:schemeClr val="phClr">
|
|
113
|
+
<a:tint val="93000"/>
|
|
114
|
+
<a:satMod val="150000"/>
|
|
115
|
+
<a:shade val="98000"/>
|
|
116
|
+
<a:lumMod val="102000"/>
|
|
117
|
+
</a:schemeClr>
|
|
118
|
+
</a:gs>
|
|
119
|
+
<a:gs pos="50000">
|
|
120
|
+
<a:schemeClr val="phClr">
|
|
121
|
+
<a:tint val="98000"/>
|
|
122
|
+
<a:satMod val="130000"/>
|
|
123
|
+
<a:shade val="90000"/>
|
|
124
|
+
<a:lumMod val="103000"/>
|
|
125
|
+
</a:schemeClr>
|
|
126
|
+
</a:gs>
|
|
127
|
+
<a:gs pos="100000">
|
|
128
|
+
<a:schemeClr val="phClr">
|
|
129
|
+
<a:shade val="63000"/>
|
|
130
|
+
<a:satMod val="120000"/>
|
|
131
|
+
</a:schemeClr>
|
|
132
|
+
</a:gs>
|
|
133
|
+
</a:gsLst>
|
|
134
|
+
<a:lin ang="5400000" scaled="0"/>
|
|
135
|
+
</a:gradFill>
|
|
136
|
+
</a:bgFillStyleLst>
|
|
137
|
+
</a:fmtScheme>
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
2
|
+
<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="0E2841"/></a:dk2><a:lt2><a:srgbClr val="E8E8E8"/></a:lt2><a:accent1><a:srgbClr val="156082"/></a:accent1><a:accent2><a:srgbClr val="E97132"/></a:accent2><a:accent3><a:srgbClr val="196B24"/></a:accent3><a:accent4><a:srgbClr val="0F9ED5"/></a:accent4><a:accent5><a:srgbClr val="A02B93"/></a:accent5><a:accent6><a:srgbClr val="4EA72E"/></a:accent6><a:hlink><a:srgbClr val="467886"/></a:hlink><a:folHlink><a:srgbClr val="96607D"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Aptos Display" panose="02110004020202020204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游ゴシック Light"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线 Light"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Angsana New"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:majorFont><a:minorFont><a:latin typeface="Aptos" panose="02110004020202020204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游明朝"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Cordia New"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:lumMod val="110000"/><a:satMod val="105000"/><a:tint val="67000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="103000"/><a:tint val="73000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="109000"/><a:tint val="81000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:satMod val="103000"/><a:lumMod val="102000"/><a:tint val="94000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:satMod val="110000"/><a:lumMod val="100000"/><a:shade val="100000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="99000"/><a:satMod val="120000"/><a:shade val="78000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="12700" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="19050" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="63000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:solidFill><a:schemeClr val="phClr"><a:tint val="95000"/><a:satMod val="170000"/></a:schemeClr></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="93000"/><a:satMod val="150000"/><a:shade val="98000"/><a:lumMod val="102000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:tint val="98000"/><a:satMod val="130000"/><a:shade val="90000"/><a:lumMod val="103000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="63000"/><a:satMod val="120000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:lnDef><a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style></a:lnDef></a:objectDefaults><a:extraClrSchemeLst/><a:extLst><a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}"><thm15:themeFamily xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main" name="Office Theme" id="{2E142A2C-CD16-42D6-873A-C26D2A0506FA}" vid="{1BDDFF52-6CD6-40A5-AB3C-68EB2F1E4D0A}"/></a:ext></a:extLst></a:theme>
|
|
@@ -75,7 +75,9 @@ module Uniword
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def create_footnote_entry(id, text, &block)
|
|
78
|
-
|
|
78
|
+
# OOXML spec: regular footnotes must NOT have w:type.
|
|
79
|
+
# Only separator/continuationSeparator use w:type.
|
|
80
|
+
entry = Wordprocessingml::Footnote.new(id: id.to_s)
|
|
79
81
|
para = ParagraphBuilder.new
|
|
80
82
|
if block_given?
|
|
81
83
|
block.call(para)
|
|
@@ -87,7 +89,7 @@ module Uniword
|
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
def create_endnote_entry(id, text, &block)
|
|
90
|
-
entry = Wordprocessingml::Endnote.new(id: id.to_s
|
|
92
|
+
entry = Wordprocessingml::Endnote.new(id: id.to_s)
|
|
91
93
|
para = ParagraphBuilder.new
|
|
92
94
|
if block_given?
|
|
93
95
|
block.call(para)
|
|
@@ -22,6 +22,11 @@ module Uniword
|
|
|
22
22
|
self
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def character_style(value)
|
|
26
|
+
ensure_properties.style = Properties::RunStyleReference.new(value: value)
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
25
30
|
def bold(value = true)
|
|
26
31
|
ensure_properties.bold = Properties::Bold.new(value: value)
|
|
27
32
|
self
|
data/lib/uniword/docx/package.rb
CHANGED
|
@@ -87,6 +87,7 @@ module Uniword
|
|
|
87
87
|
|
|
88
88
|
# Non-serialized attributes (DOCX packaging helpers)
|
|
89
89
|
attr_accessor :chart_parts, :bibliography_sources, :profile
|
|
90
|
+
attr_accessor :settings_rels, :embeddings
|
|
90
91
|
|
|
91
92
|
# Load DOCX package from file
|
|
92
93
|
#
|
|
@@ -194,6 +195,13 @@ module Uniword
|
|
|
194
195
|
)
|
|
195
196
|
end
|
|
196
197
|
|
|
198
|
+
if zip_content["word/_rels/settings.xml.rels"]
|
|
199
|
+
package.settings_rels =
|
|
200
|
+
Ooxml::Relationships::PackageRelationships.from_xml(
|
|
201
|
+
zip_content["word/_rels/settings.xml.rels"]
|
|
202
|
+
)
|
|
203
|
+
end
|
|
204
|
+
|
|
197
205
|
if zip_content["word/fontTable.xml"]
|
|
198
206
|
package.font_table = Uniword::Wordprocessingml::FontTable.from_xml(
|
|
199
207
|
zip_content["word/fontTable.xml"]
|
|
@@ -272,6 +280,16 @@ module Uniword
|
|
|
272
280
|
# Extract image parts from word/media/ directory
|
|
273
281
|
extract_image_parts(zip_content, package, zip_path)
|
|
274
282
|
|
|
283
|
+
# Extract OLE/embedded object binaries from word/embeddings/
|
|
284
|
+
embedding_files = zip_content.keys.grep(%r{^word/embeddings/.+$})
|
|
285
|
+
if embedding_files.any?
|
|
286
|
+
package.embeddings = {}
|
|
287
|
+
embedding_files.each do |emb_path|
|
|
288
|
+
target = emb_path.sub("word/", "")
|
|
289
|
+
package.embeddings[target] = zip_content[emb_path]
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
275
293
|
package
|
|
276
294
|
end
|
|
277
295
|
|
|
@@ -50,6 +50,7 @@ module Uniword
|
|
|
50
50
|
package.chart_parts = document.chart_parts if document.chart_parts
|
|
51
51
|
package.custom_xml_items = document.custom_xml_items if document.custom_xml_items
|
|
52
52
|
package.bibliography_sources = document.bibliography_sources if document.bibliography_sources
|
|
53
|
+
package.embeddings = document.embeddings if document.embeddings
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
# Create minimal content types for a valid DOCX
|
|
@@ -26,6 +26,7 @@ document_rels)
|
|
|
26
26
|
inject_notes(content_types, document_rels)
|
|
27
27
|
inject_theme(content_types, document_rels)
|
|
28
28
|
inject_numbering(content_types, document_rels)
|
|
29
|
+
inject_embeddings(content_types, document_rels)
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
# Serialize all package parts to XML and add to content hash
|
|
@@ -88,6 +89,10 @@ document_rels)
|
|
|
88
89
|
content["word/settings.xml"] =
|
|
89
90
|
serialize_part(settings)
|
|
90
91
|
end
|
|
92
|
+
if settings_rels
|
|
93
|
+
content["word/_rels/settings.xml.rels"] =
|
|
94
|
+
serialize_infrastructure(settings_rels)
|
|
95
|
+
end
|
|
91
96
|
if font_table
|
|
92
97
|
content["word/fontTable.xml"] =
|
|
93
98
|
serialize_part(font_table)
|
|
@@ -131,6 +136,9 @@ document_rels)
|
|
|
131
136
|
serialize_headers(content)
|
|
132
137
|
serialize_footers(content)
|
|
133
138
|
serialize_header_footer_parts(content)
|
|
139
|
+
|
|
140
|
+
# OLE/embedded object binaries
|
|
141
|
+
serialize_embeddings(content)
|
|
134
142
|
end
|
|
135
143
|
|
|
136
144
|
# Serialize an OOXML document part with standard encoding
|
|
@@ -409,6 +417,28 @@ document_rels)
|
|
|
409
417
|
)
|
|
410
418
|
end
|
|
411
419
|
|
|
420
|
+
def inject_embeddings(content_types, document_rels)
|
|
421
|
+
return unless embeddings && !embeddings.empty?
|
|
422
|
+
|
|
423
|
+
embeddings.each_with_index do |(target, _data), idx|
|
|
424
|
+
part_name = "/word/#{target}"
|
|
425
|
+
next if content_types.overrides.any? { |o| o.part_name == part_name }
|
|
426
|
+
|
|
427
|
+
content_types.overrides << Uniword::ContentTypes::Override.new(
|
|
428
|
+
part_name: part_name,
|
|
429
|
+
content_type: "application/vnd.openxmlformats-officedocument.oleObject",
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
next if document_rels.relationships.any? { |r| r.target == target }
|
|
433
|
+
|
|
434
|
+
document_rels.relationships << Ooxml::Relationships::Relationship.new(
|
|
435
|
+
id: "rIdEmbedding#{idx + 1}",
|
|
436
|
+
type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject",
|
|
437
|
+
target: target,
|
|
438
|
+
)
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
412
442
|
def wire_header_reference(type, r_id)
|
|
413
443
|
return unless document&.body
|
|
414
444
|
|
|
@@ -467,6 +497,14 @@ document_rels)
|
|
|
467
497
|
serialize_part(part[:content])
|
|
468
498
|
end
|
|
469
499
|
end
|
|
500
|
+
|
|
501
|
+
def serialize_embeddings(content)
|
|
502
|
+
return unless embeddings && !embeddings.empty?
|
|
503
|
+
|
|
504
|
+
embeddings.each do |target, data|
|
|
505
|
+
content["word/#{target}"] = data
|
|
506
|
+
end
|
|
507
|
+
end
|
|
470
508
|
end
|
|
471
509
|
end
|
|
472
510
|
end
|
|
@@ -17,6 +17,16 @@ module Uniword
|
|
|
17
17
|
class Reconciler
|
|
18
18
|
CONFIG_DIR = File.join(__dir__, "../../../config")
|
|
19
19
|
|
|
20
|
+
# All w1x/w16x extension namespace prefixes declared by namespace_scope
|
|
21
|
+
# on wordprocessingml parts. These MUST be listed in mc:Ignorable so
|
|
22
|
+
# Word doesn't reject them as unknown extensions.
|
|
23
|
+
IGNORABLE_PREFIXES = %w[
|
|
24
|
+
w14 w15 w16se w16cid w16 w16cex w16sdtdh w16sdtfl w16du
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
# Extension prefixes used in document.xml (adds wp14 for drawing)
|
|
28
|
+
IGNORABLE_PREFIXES_DOCUMENT = (IGNORABLE_PREFIXES + %w[wp14]).freeze
|
|
29
|
+
|
|
20
30
|
def initialize(package, profile: nil)
|
|
21
31
|
@package = package
|
|
22
32
|
@profile = profile
|
|
@@ -28,6 +38,7 @@ module Uniword
|
|
|
28
38
|
reconcile_section_properties
|
|
29
39
|
reconcile_footnotes
|
|
30
40
|
reconcile_endnotes
|
|
41
|
+
reconcile_note_references
|
|
31
42
|
repair_theme
|
|
32
43
|
|
|
33
44
|
# Group 2: Support parts (profile-dependent)
|
|
@@ -85,13 +96,11 @@ module Uniword
|
|
|
85
96
|
].compact
|
|
86
97
|
|
|
87
98
|
parts.each do |part|
|
|
88
|
-
part.pending_namespace_data = nil
|
|
89
99
|
part.import_declaration_plan = nil
|
|
90
100
|
part.pending_plan_root_element = nil
|
|
91
|
-
# TODO: @xml_input_namespaces has no public accessor in lutaml-model.
|
|
92
|
-
# Replace with public API once lutaml-model exposes one.
|
|
93
|
-
part.instance_variable_set(:@xml_input_namespaces, nil)
|
|
94
101
|
end
|
|
102
|
+
|
|
103
|
+
parts.each(&:clear_xml_parse_state!)
|
|
95
104
|
end
|
|
96
105
|
|
|
97
106
|
def reconcile_section_properties
|
|
@@ -174,6 +183,114 @@ module Uniword
|
|
|
174
183
|
ensure_separators(package.endnotes, :endnote) if package.endnotes
|
|
175
184
|
end
|
|
176
185
|
|
|
186
|
+
# -- Note reference consistency --
|
|
187
|
+
|
|
188
|
+
def reconcile_note_references
|
|
189
|
+
reconcile_footnote_references
|
|
190
|
+
reconcile_endnote_references
|
|
191
|
+
reconcile_note_definition_integrity
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def reconcile_footnote_references
|
|
195
|
+
return unless package.document&.body
|
|
196
|
+
|
|
197
|
+
referenced = collect_note_ids(:footnote)
|
|
198
|
+
return if referenced.empty?
|
|
199
|
+
|
|
200
|
+
ensure_footnotes_part
|
|
201
|
+
defined = package.footnotes.footnote_entries.each_with_object(Set.new) do |fn, s|
|
|
202
|
+
s << fn.id
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
missing = referenced.to_set - defined
|
|
206
|
+
return if missing.empty?
|
|
207
|
+
|
|
208
|
+
missing.each do |id|
|
|
209
|
+
package.footnotes.footnote_entries << Wordprocessingml::Footnote.new(
|
|
210
|
+
id: id, paragraphs: [Wordprocessingml::Paragraph.new],
|
|
211
|
+
)
|
|
212
|
+
end
|
|
213
|
+
record_fix("R10",
|
|
214
|
+
"Added #{missing.size} missing footnote definition(s) " \
|
|
215
|
+
"for orphaned footnoteReference IDs: #{missing.sort.join(', ')}")
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def reconcile_endnote_references
|
|
219
|
+
return unless package.document&.body
|
|
220
|
+
|
|
221
|
+
referenced = collect_note_ids(:endnote)
|
|
222
|
+
return if referenced.empty?
|
|
223
|
+
|
|
224
|
+
ensure_endnotes_part
|
|
225
|
+
defined = package.endnotes.endnote_entries.each_with_object(Set.new) do |en, s|
|
|
226
|
+
s << en.id
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
missing = referenced.to_set - defined
|
|
230
|
+
return if missing.empty?
|
|
231
|
+
|
|
232
|
+
missing.each do |id|
|
|
233
|
+
package.endnotes.endnote_entries << Wordprocessingml::Endnote.new(
|
|
234
|
+
id: id, paragraphs: [Wordprocessingml::Paragraph.new],
|
|
235
|
+
)
|
|
236
|
+
end
|
|
237
|
+
record_fix("R10",
|
|
238
|
+
"Added #{missing.size} missing endnote definition(s) " \
|
|
239
|
+
"for orphaned endnoteReference IDs: #{missing.sort.join(', ')}")
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Validates structural integrity of footnote/endnote definitions.
|
|
243
|
+
def reconcile_note_definition_integrity
|
|
244
|
+
strip_invalid_note_types(:footnote)
|
|
245
|
+
strip_invalid_note_types(:endnote)
|
|
246
|
+
deduplicate_note_ids(:footnote)
|
|
247
|
+
deduplicate_note_ids(:endnote)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# R15: Regular footnotes/endnotes must NOT have w:type.
|
|
251
|
+
# Only separator (id=-1) and continuationSeparator (id=0) use w:type.
|
|
252
|
+
def strip_invalid_note_types(type)
|
|
253
|
+
notes = package.public_send(:"#{type}s")
|
|
254
|
+
return unless notes
|
|
255
|
+
|
|
256
|
+
entries = notes.public_send(:"#{type}_entries")
|
|
257
|
+
invalid = entries.select do |e|
|
|
258
|
+
e.type && e.id != "-1" && e.id != "0"
|
|
259
|
+
end
|
|
260
|
+
return if invalid.empty?
|
|
261
|
+
|
|
262
|
+
invalid.each { |e| e.type = nil }
|
|
263
|
+
record_fix("R15",
|
|
264
|
+
"Removed invalid w:type from #{invalid.size} " \
|
|
265
|
+
"regular #{type} definition(s): " \
|
|
266
|
+
"IDs #{invalid.map(&:id).sort.join(', ')}")
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# R16: Duplicate IDs in footnotes.xml/endnotes.xml are invalid.
|
|
270
|
+
# Keeps the first occurrence, removes subsequent duplicates.
|
|
271
|
+
def deduplicate_note_ids(type)
|
|
272
|
+
notes = package.public_send(:"#{type}s")
|
|
273
|
+
return unless notes
|
|
274
|
+
|
|
275
|
+
entries = notes.public_send(:"#{type}_entries")
|
|
276
|
+
seen = Set.new
|
|
277
|
+
dupes = []
|
|
278
|
+
entries.reject! do |e|
|
|
279
|
+
if seen.include?(e.id)
|
|
280
|
+
dupes << e
|
|
281
|
+
true
|
|
282
|
+
else
|
|
283
|
+
seen << e.id
|
|
284
|
+
false
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
return if dupes.empty?
|
|
288
|
+
|
|
289
|
+
record_fix("R16",
|
|
290
|
+
"Removed #{dupes.size} duplicate #{type} ID(s): " \
|
|
291
|
+
"#{dupes.map(&:id).sort.join(', ')}")
|
|
292
|
+
end
|
|
293
|
+
|
|
177
294
|
# -- Builders --
|
|
178
295
|
|
|
179
296
|
def minimal_footnotes
|
|
@@ -216,6 +333,53 @@ module Uniword
|
|
|
216
333
|
entries.unshift(continuation_entry(type)) unless ids.include?("0")
|
|
217
334
|
end
|
|
218
335
|
|
|
336
|
+
def collect_note_ids(type)
|
|
337
|
+
ref_attr = type == :footnote ? :footnote_reference : :endnote_reference
|
|
338
|
+
ids = []
|
|
339
|
+
collect_note_ids_from_element(package.document.body, ref_attr, ids)
|
|
340
|
+
ids
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def collect_note_ids_from_element(element, ref_attr, ids)
|
|
344
|
+
return unless element
|
|
345
|
+
|
|
346
|
+
collect_note_ids_from_paragraphs(element.paragraphs, ref_attr, ids)
|
|
347
|
+
|
|
348
|
+
tables = element.tables
|
|
349
|
+
return unless tables
|
|
350
|
+
tables.each do |tbl|
|
|
351
|
+
tbl.rows.each do |row|
|
|
352
|
+
row.cells.each do |cell|
|
|
353
|
+
collect_note_ids_from_paragraphs(cell.paragraphs, ref_attr, ids)
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def collect_note_ids_from_paragraphs(paragraphs, ref_attr, ids)
|
|
360
|
+
return unless paragraphs
|
|
361
|
+
paragraphs.each do |p|
|
|
362
|
+
(p.runs || []).each do |r|
|
|
363
|
+
ref = r.public_send(ref_attr)
|
|
364
|
+
ids << ref.id if ref&.id
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def ensure_footnotes_part
|
|
370
|
+
return if package.footnotes
|
|
371
|
+
|
|
372
|
+
package.footnotes = minimal_footnotes
|
|
373
|
+
record_fix("R9", "Created footnotes.xml for orphaned references")
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def ensure_endnotes_part
|
|
377
|
+
return if package.endnotes
|
|
378
|
+
|
|
379
|
+
package.endnotes = minimal_endnotes
|
|
380
|
+
record_fix("R9", "Created endnotes.xml for orphaned references")
|
|
381
|
+
end
|
|
382
|
+
|
|
219
383
|
# -- Group 2: Support parts (profile-dependent) --
|
|
220
384
|
|
|
221
385
|
def reconcile_theme
|
|
@@ -353,11 +517,16 @@ module Uniword
|
|
|
353
517
|
|
|
354
518
|
rsid = generate_rsid
|
|
355
519
|
|
|
520
|
+
# Only inject settings defaults for newly created documents.
|
|
521
|
+
# If settings already has substantial content (zoom + compat + rsids),
|
|
522
|
+
# the document was loaded from a real DOCX and defaults would alter
|
|
523
|
+
# its round-trip fidelity.
|
|
524
|
+
loaded_doc = settings.zoom && settings.compat && settings.rsids
|
|
525
|
+
|
|
356
526
|
settings.zoom ||= Wordprocessingml::Zoom.new(percent: 100)
|
|
357
|
-
settings.do_not_display_page_boundaries ||= Wordprocessingml::DoNotDisplayPageBoundaries.new
|
|
358
527
|
settings.proof_state ||= Wordprocessingml::ProofState.new(
|
|
359
528
|
spelling: "clean", grammar: "clean",
|
|
360
|
-
)
|
|
529
|
+
) unless loaded_doc
|
|
361
530
|
settings.default_tab_stop ||= Wordprocessingml::DefaultTabStop.new(val: "720")
|
|
362
531
|
settings.character_spacing_control ||= Wordprocessingml::CharacterSpacingControl.new(
|
|
363
532
|
val: "doNotCompress",
|
|
@@ -391,7 +560,9 @@ module Uniword
|
|
|
391
560
|
record_fix("R2", "Generated w15:docId in GUID format")
|
|
392
561
|
end
|
|
393
562
|
|
|
394
|
-
settings.mc_ignorable =
|
|
563
|
+
settings.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
564
|
+
IGNORABLE_PREFIXES.join(" "),
|
|
565
|
+
)
|
|
395
566
|
end
|
|
396
567
|
|
|
397
568
|
def reconcile_font_table
|
|
@@ -432,7 +603,9 @@ module Uniword
|
|
|
432
603
|
font_table.fonts << font
|
|
433
604
|
end
|
|
434
605
|
|
|
435
|
-
font_table.mc_ignorable =
|
|
606
|
+
font_table.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
607
|
+
IGNORABLE_PREFIXES.join(" "),
|
|
608
|
+
)
|
|
436
609
|
record_fix("R13",
|
|
437
610
|
"Populated font table with profile fonts and signatures")
|
|
438
611
|
end
|
|
@@ -451,7 +624,9 @@ module Uniword
|
|
|
451
624
|
|
|
452
625
|
ensure_default_styles(styles)
|
|
453
626
|
|
|
454
|
-
styles.mc_ignorable =
|
|
627
|
+
styles.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
628
|
+
IGNORABLE_PREFIXES.join(" "),
|
|
629
|
+
)
|
|
455
630
|
record_fix("R10",
|
|
456
631
|
"Ensured styles have docDefaults, latentStyles, and default styles")
|
|
457
632
|
end
|
|
@@ -460,7 +635,9 @@ module Uniword
|
|
|
460
635
|
return unless profile
|
|
461
636
|
return unless package.numbering
|
|
462
637
|
|
|
463
|
-
package.numbering.mc_ignorable =
|
|
638
|
+
package.numbering.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
639
|
+
IGNORABLE_PREFIXES.join(" "),
|
|
640
|
+
)
|
|
464
641
|
|
|
465
642
|
# Validate instance → definition references
|
|
466
643
|
package.numbering.instances.each do |inst|
|
|
@@ -486,8 +663,11 @@ module Uniword
|
|
|
486
663
|
package.web_settings
|
|
487
664
|
end
|
|
488
665
|
|
|
489
|
-
ws.mc_ignorable =
|
|
490
|
-
|
|
666
|
+
ws.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
667
|
+
IGNORABLE_PREFIXES.join(" "),
|
|
668
|
+
)
|
|
669
|
+
ws.allow_png ||= Wordprocessingml::AllowPng.new
|
|
670
|
+
record_fix("R1", "Set mc:Ignorable and allowPNG on webSettings")
|
|
491
671
|
end
|
|
492
672
|
|
|
493
673
|
def reconcile_app_properties
|
|
@@ -581,7 +761,9 @@ module Uniword
|
|
|
581
761
|
return unless package.document&.body
|
|
582
762
|
|
|
583
763
|
doc = package.document
|
|
584
|
-
doc.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
764
|
+
doc.mc_ignorable = Ooxml::Types::McIgnorable.new(
|
|
765
|
+
IGNORABLE_PREFIXES_DOCUMENT.join(" "),
|
|
766
|
+
)
|
|
585
767
|
|
|
586
768
|
record_fix("R1", "Added mc:Ignorable to document body")
|
|
587
769
|
record_fix("R12", "Assigned rsid and paraId to paragraphs")
|