uniword 1.0.9 → 1.0.10
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/docx/package.rb +18 -0
- data/lib/uniword/docx/package_serialization.rb +38 -0
- data/lib/uniword/docx/reconciler.rb +158 -4
- 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/version.rb +1 -1
- data/lib/uniword/wordprocessingml/attached_template.rb +18 -0
- data/lib/uniword/wordprocessingml/body.rb +18 -36
- 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 +6 -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 +49 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7feae85851d80946524005c3cc6419419d492c717e559628093494ee7532cd9
|
|
4
|
+
data.tar.gz: eba8d3d3d433aa158b5a4214659e6afd0e12d74e3fada13997da066021a78f9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 940e11bb305505cd3e6acdc6e9cca98e002d151a0f75e7c8872d613353b4c5d85b424062a661572b14474c342b62db3072d2cc081cb9e924f95bb8fdf80e6c39
|
|
7
|
+
data.tar.gz: 3ca3c9bea8133f7a18e64897b687ef8dd10843c85aa2e4422dabceed5152ae5a5f9cce56fdff8999f03e734f8510b919732f9f5b5b0d5ac0e9470c8dd0db11fb
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -28,6 +28,7 @@ module Uniword
|
|
|
28
28
|
reconcile_section_properties
|
|
29
29
|
reconcile_footnotes
|
|
30
30
|
reconcile_endnotes
|
|
31
|
+
reconcile_note_references
|
|
31
32
|
repair_theme
|
|
32
33
|
|
|
33
34
|
# Group 2: Support parts (profile-dependent)
|
|
@@ -85,13 +86,11 @@ module Uniword
|
|
|
85
86
|
].compact
|
|
86
87
|
|
|
87
88
|
parts.each do |part|
|
|
88
|
-
part.pending_namespace_data = nil
|
|
89
89
|
part.import_declaration_plan = nil
|
|
90
90
|
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
91
|
end
|
|
92
|
+
|
|
93
|
+
parts.each(&:clear_xml_parse_state!)
|
|
95
94
|
end
|
|
96
95
|
|
|
97
96
|
def reconcile_section_properties
|
|
@@ -174,6 +173,114 @@ module Uniword
|
|
|
174
173
|
ensure_separators(package.endnotes, :endnote) if package.endnotes
|
|
175
174
|
end
|
|
176
175
|
|
|
176
|
+
# -- Note reference consistency --
|
|
177
|
+
|
|
178
|
+
def reconcile_note_references
|
|
179
|
+
reconcile_footnote_references
|
|
180
|
+
reconcile_endnote_references
|
|
181
|
+
reconcile_note_definition_integrity
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def reconcile_footnote_references
|
|
185
|
+
return unless package.document&.body
|
|
186
|
+
|
|
187
|
+
referenced = collect_note_ids(:footnote)
|
|
188
|
+
return if referenced.empty?
|
|
189
|
+
|
|
190
|
+
ensure_footnotes_part
|
|
191
|
+
defined = package.footnotes.footnote_entries.each_with_object(Set.new) do |fn, s|
|
|
192
|
+
s << fn.id
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
missing = referenced.to_set - defined
|
|
196
|
+
return if missing.empty?
|
|
197
|
+
|
|
198
|
+
missing.each do |id|
|
|
199
|
+
package.footnotes.footnote_entries << Wordprocessingml::Footnote.new(
|
|
200
|
+
id: id, paragraphs: [Wordprocessingml::Paragraph.new],
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
record_fix("R10",
|
|
204
|
+
"Added #{missing.size} missing footnote definition(s) " \
|
|
205
|
+
"for orphaned footnoteReference IDs: #{missing.sort.join(', ')}")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def reconcile_endnote_references
|
|
209
|
+
return unless package.document&.body
|
|
210
|
+
|
|
211
|
+
referenced = collect_note_ids(:endnote)
|
|
212
|
+
return if referenced.empty?
|
|
213
|
+
|
|
214
|
+
ensure_endnotes_part
|
|
215
|
+
defined = package.endnotes.endnote_entries.each_with_object(Set.new) do |en, s|
|
|
216
|
+
s << en.id
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
missing = referenced.to_set - defined
|
|
220
|
+
return if missing.empty?
|
|
221
|
+
|
|
222
|
+
missing.each do |id|
|
|
223
|
+
package.endnotes.endnote_entries << Wordprocessingml::Endnote.new(
|
|
224
|
+
id: id, paragraphs: [Wordprocessingml::Paragraph.new],
|
|
225
|
+
)
|
|
226
|
+
end
|
|
227
|
+
record_fix("R10",
|
|
228
|
+
"Added #{missing.size} missing endnote definition(s) " \
|
|
229
|
+
"for orphaned endnoteReference IDs: #{missing.sort.join(', ')}")
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Validates structural integrity of footnote/endnote definitions.
|
|
233
|
+
def reconcile_note_definition_integrity
|
|
234
|
+
strip_invalid_note_types(:footnote)
|
|
235
|
+
strip_invalid_note_types(:endnote)
|
|
236
|
+
deduplicate_note_ids(:footnote)
|
|
237
|
+
deduplicate_note_ids(:endnote)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# R15: Regular footnotes/endnotes must NOT have w:type.
|
|
241
|
+
# Only separator (id=-1) and continuationSeparator (id=0) use w:type.
|
|
242
|
+
def strip_invalid_note_types(type)
|
|
243
|
+
notes = package.public_send(:"#{type}s")
|
|
244
|
+
return unless notes
|
|
245
|
+
|
|
246
|
+
entries = notes.public_send(:"#{type}_entries")
|
|
247
|
+
invalid = entries.select do |e|
|
|
248
|
+
e.type && e.id != "-1" && e.id != "0"
|
|
249
|
+
end
|
|
250
|
+
return if invalid.empty?
|
|
251
|
+
|
|
252
|
+
invalid.each { |e| e.type = nil }
|
|
253
|
+
record_fix("R15",
|
|
254
|
+
"Removed invalid w:type from #{invalid.size} " \
|
|
255
|
+
"regular #{type} definition(s): " \
|
|
256
|
+
"IDs #{invalid.map(&:id).sort.join(', ')}")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# R16: Duplicate IDs in footnotes.xml/endnotes.xml are invalid.
|
|
260
|
+
# Keeps the first occurrence, removes subsequent duplicates.
|
|
261
|
+
def deduplicate_note_ids(type)
|
|
262
|
+
notes = package.public_send(:"#{type}s")
|
|
263
|
+
return unless notes
|
|
264
|
+
|
|
265
|
+
entries = notes.public_send(:"#{type}_entries")
|
|
266
|
+
seen = Set.new
|
|
267
|
+
dupes = []
|
|
268
|
+
entries.reject! do |e|
|
|
269
|
+
if seen.include?(e.id)
|
|
270
|
+
dupes << e
|
|
271
|
+
true
|
|
272
|
+
else
|
|
273
|
+
seen << e.id
|
|
274
|
+
false
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
return if dupes.empty?
|
|
278
|
+
|
|
279
|
+
record_fix("R16",
|
|
280
|
+
"Removed #{dupes.size} duplicate #{type} ID(s): " \
|
|
281
|
+
"#{dupes.map(&:id).sort.join(', ')}")
|
|
282
|
+
end
|
|
283
|
+
|
|
177
284
|
# -- Builders --
|
|
178
285
|
|
|
179
286
|
def minimal_footnotes
|
|
@@ -216,6 +323,53 @@ module Uniword
|
|
|
216
323
|
entries.unshift(continuation_entry(type)) unless ids.include?("0")
|
|
217
324
|
end
|
|
218
325
|
|
|
326
|
+
def collect_note_ids(type)
|
|
327
|
+
ref_attr = type == :footnote ? :footnote_reference : :endnote_reference
|
|
328
|
+
ids = []
|
|
329
|
+
collect_note_ids_from_element(package.document.body, ref_attr, ids)
|
|
330
|
+
ids
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def collect_note_ids_from_element(element, ref_attr, ids)
|
|
334
|
+
return unless element
|
|
335
|
+
|
|
336
|
+
collect_note_ids_from_paragraphs(element.paragraphs, ref_attr, ids)
|
|
337
|
+
|
|
338
|
+
tables = element.tables
|
|
339
|
+
return unless tables
|
|
340
|
+
tables.each do |tbl|
|
|
341
|
+
tbl.rows.each do |row|
|
|
342
|
+
row.cells.each do |cell|
|
|
343
|
+
collect_note_ids_from_paragraphs(cell.paragraphs, ref_attr, ids)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def collect_note_ids_from_paragraphs(paragraphs, ref_attr, ids)
|
|
350
|
+
return unless paragraphs
|
|
351
|
+
paragraphs.each do |p|
|
|
352
|
+
(p.runs || []).each do |r|
|
|
353
|
+
ref = r.public_send(ref_attr)
|
|
354
|
+
ids << ref.id if ref&.id
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def ensure_footnotes_part
|
|
360
|
+
return if package.footnotes
|
|
361
|
+
|
|
362
|
+
package.footnotes = minimal_footnotes
|
|
363
|
+
record_fix("R9", "Created footnotes.xml for orphaned references")
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def ensure_endnotes_part
|
|
367
|
+
return if package.endnotes
|
|
368
|
+
|
|
369
|
+
package.endnotes = minimal_endnotes
|
|
370
|
+
record_fix("R9", "Created endnotes.xml for orphaned references")
|
|
371
|
+
end
|
|
372
|
+
|
|
219
373
|
# -- Group 2: Support parts (profile-dependent) --
|
|
220
374
|
|
|
221
375
|
def reconcile_theme
|
data/lib/uniword/lazy_loader.rb
CHANGED
|
@@ -14,23 +14,16 @@ module Uniword
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Helper to define val= override after attribute declaration.
|
|
17
|
-
# Uses alias_method to save the generated setter, then overrides it.
|
|
18
17
|
module BooleanValSetter
|
|
19
18
|
def self.included(base)
|
|
20
|
-
base.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
nil
|
|
29
|
-
else
|
|
30
|
-
v
|
|
31
|
-
end
|
|
32
|
-
value_set_for(:val)
|
|
33
|
-
end
|
|
19
|
+
base.define_method(:val=) do |v|
|
|
20
|
+
@val = case v
|
|
21
|
+
when nil then nil
|
|
22
|
+
when false, "false" then "false"
|
|
23
|
+
when true, "true" then nil
|
|
24
|
+
else v
|
|
25
|
+
end
|
|
26
|
+
value_set_for(:val)
|
|
34
27
|
end
|
|
35
28
|
end
|
|
36
29
|
end
|
data/lib/uniword/version.rb
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "../properties/relationship_id"
|
|
5
|
+
|
|
6
|
+
module Uniword
|
|
7
|
+
module Wordprocessingml
|
|
8
|
+
class AttachedTemplate < Lutaml::Model::Serializable
|
|
9
|
+
attribute :r_id, Properties::RelationshipIdValue
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
element "attachedTemplate"
|
|
13
|
+
namespace Uniword::Ooxml::Namespaces::WordProcessingML
|
|
14
|
+
map_attribute "id", to: :r_id
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -71,48 +71,30 @@ module Uniword
|
|
|
71
71
|
def sync_element_order
|
|
72
72
|
return if element_order.nil? || element_order.empty?
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
ordered_tbl_count = element_order.count { |e| e.name == "tbl" }
|
|
77
|
-
ordered_sdt_count = element_order.count { |e| e.name == "sdt" }
|
|
78
|
-
ordered_bookmark_start_count = element_order.count do |e|
|
|
79
|
-
e.name == "bookmarkStart"
|
|
80
|
-
end
|
|
81
|
-
ordered_bookmark_end_count = element_order.count do |e|
|
|
82
|
-
e.name == "bookmarkEnd"
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Add missing paragraphs
|
|
86
|
-
(paragraphs.size - ordered_p_count).times do
|
|
87
|
-
element_order << Lutaml::Xml::Element.new("Element", "p")
|
|
74
|
+
counts = element_order.each_with_object(Hash.new(0)) do |e, h|
|
|
75
|
+
h[e.name] += 1
|
|
88
76
|
end
|
|
89
77
|
|
|
90
|
-
|
|
91
|
-
(tables.size -
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
append_missing_elements("p", paragraphs.size - counts["p"])
|
|
79
|
+
append_missing_elements("tbl", tables.size - counts["tbl"])
|
|
80
|
+
append_missing_elements("sdt",
|
|
81
|
+
structured_document_tags.size - counts["sdt"])
|
|
82
|
+
append_missing_elements("bookmarkStart",
|
|
83
|
+
bookmark_starts.size - counts["bookmarkStart"])
|
|
84
|
+
append_missing_elements("bookmarkEnd",
|
|
85
|
+
bookmark_ends.size - counts["bookmarkEnd"])
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
(structured_document_tags.size - ordered_sdt_count).times do
|
|
97
|
-
element_order << Lutaml::Xml::Element.new("Element", "sdt")
|
|
98
|
-
end
|
|
87
|
+
return unless section_properties && counts["sectPr"].zero?
|
|
99
88
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
element_order << Lutaml::Xml::Element.new("Element", "bookmarkStart")
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Add missing bookmark ends
|
|
106
|
-
(bookmark_ends.size - ordered_bookmark_end_count).times do
|
|
107
|
-
element_order << Lutaml::Xml::Element.new("Element", "bookmarkEnd")
|
|
108
|
-
end
|
|
89
|
+
element_order << build_order_element("sectPr")
|
|
90
|
+
end
|
|
109
91
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
end
|
|
92
|
+
def append_missing_elements(name, count)
|
|
93
|
+
count.times { element_order << build_order_element(name) }
|
|
94
|
+
end
|
|
114
95
|
|
|
115
|
-
|
|
96
|
+
def build_order_element(name)
|
|
97
|
+
Lutaml::Xml::Element.new("Element", name)
|
|
116
98
|
end
|
|
117
99
|
end
|
|
118
100
|
end
|