@coco-vexel/coco-office-oojson 0.0.0-stage → 1.0.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.
- package/LICENSE +202 -0
- package/README.md +99 -2
- package/THIRD_PARTY_NOTICES.md +1188 -0
- package/dist/oojson.global.js +30 -0
- package/package.json +45 -3
- package/src/color.mjs +38 -0
- package/src/extra.mjs +37 -0
- package/src/flat-opc.mjs +394 -0
- package/src/index.mjs +39 -0
- package/src/json-to-ooxml.mjs +605 -0
- package/src/long-tail-parts.mjs +424 -0
- package/src/numbering-to-ooxml.mjs +120 -0
- package/src/ooxml-drawing-to-json.mjs +209 -0
- package/src/ooxml-to-json.mjs +305 -0
- package/src/ppt-content.mjs +346 -0
- package/src/ppt-deck.mjs +248 -0
- package/src/styles-to-ooxml.mjs +302 -0
- package/src/writeback.mjs +1082 -0
- package/src/xml.mjs +66 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// Tool 3: ONLYOFFICE style definitions -> OOXML styles.xml.
|
|
2
|
+
// Stable source: Api.GetDocument().ToJSON(false, true, true, true, true, true).
|
|
3
|
+
// The sixth argument exports the native styles map keyed by ONLYOFFICE numeric styleId.
|
|
4
|
+
import { esc, attrStr } from "./xml.mjs";
|
|
5
|
+
import { colorToOoxml, autoRgbAttr, highlightToOoxml } from "./color.mjs";
|
|
6
|
+
import { extraAttr } from "./extra.mjs";
|
|
7
|
+
|
|
8
|
+
function shdXml(shd) {
|
|
9
|
+
if (!shd) return "";
|
|
10
|
+
const fill = shd.fill ? ` w:fill="${colorToOoxml(shd.fill)}"${autoRgbAttr("oo:frgb", shd.fill)}` : "";
|
|
11
|
+
return `<w:shd w:val="${shd.val || "clear"}" w:color="${colorToOoxml(shd.color)}"${autoRgbAttr("oo:crgb", shd.color)}${fill}${extraAttr(shd, ["val", "color", "fill"])}/>`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function bdrElXml(tag, b) {
|
|
15
|
+
if (!b) return "";
|
|
16
|
+
const a = {};
|
|
17
|
+
const v = b.val != null ? b.val : b.value;
|
|
18
|
+
if (v != null) a["w:val"] = v;
|
|
19
|
+
if (b.sz != null) a["w:sz"] = b.sz;
|
|
20
|
+
if (b.space != null) a["w:space"] = b.space;
|
|
21
|
+
if (b.color) a["w:color"] = colorToOoxml(b.color);
|
|
22
|
+
return `<w:${tag}${attrStr(a)}${b.color ? autoRgbAttr("oo:rgb", b.color) : ""}${extraAttr(b, ["color", "sz", "space", "value", "val"])}/>`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const BDR_SIDES = ["top", "left", "bottom", "right", "insideH", "insideV", "start", "end", "between", "bar", "tl2br", "tr2bl"];
|
|
26
|
+
function bordersXml(tag, o) {
|
|
27
|
+
if (!o) return "";
|
|
28
|
+
let x = "";
|
|
29
|
+
for (const side of BDR_SIDES) if (o[side]) x += bdrElXml(side, o[side]);
|
|
30
|
+
return Object.keys(o).length ? `<w:${tag}>${x}</w:${tag}>` : `<w:${tag}/>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function widthXml(tag, w) {
|
|
34
|
+
if (!w) return "";
|
|
35
|
+
const a = {};
|
|
36
|
+
if (w.type != null) a["w:type"] = w.type;
|
|
37
|
+
const v = w.w != null ? w.w : w.value;
|
|
38
|
+
if (v != null) a["w:w"] = v;
|
|
39
|
+
return `<w:${tag}${attrStr(a)}${extraAttr(w, ["type", "w", "value"])}/>`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function marXml(tag, m) {
|
|
43
|
+
if (!m) return "";
|
|
44
|
+
let x = "";
|
|
45
|
+
for (const side of ["top", "left", "bottom", "right", "start", "end"]) if (m[side]) x += widthXml(side, m[side]);
|
|
46
|
+
return x ? `<w:${tag}>${x}</w:${tag}>` : "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function valOf(v) {
|
|
50
|
+
return typeof v === "object" && v !== null ? v.val ?? v.value ?? v.type : v;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function ooOutlineToOoxml(lvl) {
|
|
54
|
+
if (lvl == null) return null;
|
|
55
|
+
const n = Number(lvl);
|
|
56
|
+
if (!Number.isFinite(n)) return null;
|
|
57
|
+
const z = n - 1;
|
|
58
|
+
if (z < 0) return 0;
|
|
59
|
+
if (z > 9) return 9;
|
|
60
|
+
return z;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function numPrXml(numPr) {
|
|
64
|
+
if (!numPr) return "";
|
|
65
|
+
let x = "";
|
|
66
|
+
const ilvl = valOf(numPr.ilvl);
|
|
67
|
+
const numId = valOf(numPr.numId);
|
|
68
|
+
if (ilvl != null) x += `<w:ilvl w:val="${esc(String(ilvl))}"/>`;
|
|
69
|
+
if (numId != null) x += `<w:numId w:val="${esc(String(numId))}"/>`;
|
|
70
|
+
return x || extraAttr(numPr, ["ilvl", "numId"]) ? `<w:numPr${extraAttr(numPr, ["ilvl", "numId"])}>${x}</w:numPr>` : "";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function tabsXml(tabs) {
|
|
74
|
+
if (!tabs) return "";
|
|
75
|
+
const list = Array.isArray(tabs) ? tabs : Array.isArray(tabs.tabs) ? tabs.tabs : Array.isArray(tabs.list) ? tabs.list : [];
|
|
76
|
+
let x = "";
|
|
77
|
+
for (const tab of list) {
|
|
78
|
+
if (!tab) continue;
|
|
79
|
+
const a = {};
|
|
80
|
+
const val = tab.val ?? tab.value ?? tab.type;
|
|
81
|
+
if (val != null) a["w:val"] = val;
|
|
82
|
+
if (tab.pos != null) a["w:pos"] = tab.pos;
|
|
83
|
+
if (tab.leader != null) a["w:leader"] = tab.leader;
|
|
84
|
+
x += `<w:tab${attrStr(a)}${extraAttr(tab, ["val", "value", "type", "pos", "leader"])}/>`;
|
|
85
|
+
}
|
|
86
|
+
return x ? `<w:tabs>${x}</w:tabs>` : "";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function ppInnerXml(pPr, options = {}) {
|
|
90
|
+
if (!pPr) return "";
|
|
91
|
+
let x = "";
|
|
92
|
+
if (options.includeStyleRef && pPr.pStyle != null) x += `<w:pStyle w:val="${esc(String(pPr.pStyle))}"/>`;
|
|
93
|
+
for (const t of ["keepNext", "keepLines", "pageBreakBefore", "widowControl", "contextualSpacing", "suppressLineNumbers"])
|
|
94
|
+
if (pPr[t] === true) x += `<w:${t}/>`;
|
|
95
|
+
x += numPrXml(pPr.numPr);
|
|
96
|
+
x += tabsXml(pPr.tabs);
|
|
97
|
+
x += bordersXml("pBdr", pPr.pBdr);
|
|
98
|
+
x += shdXml(pPr.shd);
|
|
99
|
+
if (pPr.spacing) {
|
|
100
|
+
const s = pPr.spacing, a = {};
|
|
101
|
+
if (s.before != null) a["w:before"] = s.before;
|
|
102
|
+
if (s.after != null) a["w:after"] = s.after;
|
|
103
|
+
if (s.line != null) a["w:line"] = s.line;
|
|
104
|
+
if (s.lineRule != null) a["w:lineRule"] = s.lineRule;
|
|
105
|
+
if (s.beforeAutoSpacing != null) a["w:beforeAutospacing"] = s.beforeAutoSpacing === "off" ? 0 : 1;
|
|
106
|
+
if (s.afterAutoSpacing != null) a["w:afterAutospacing"] = s.afterAutoSpacing === "off" ? 0 : 1;
|
|
107
|
+
x += `<w:spacing${attrStr(a)}${extraAttr(s, ["before", "after", "line", "lineRule", "beforeAutoSpacing", "afterAutoSpacing"])}/>`;
|
|
108
|
+
}
|
|
109
|
+
if (pPr.ind) {
|
|
110
|
+
const d = pPr.ind, a = {};
|
|
111
|
+
for (const k of ["left", "right", "firstLine", "hanging", "start", "end", "firstLineChars", "hangingChars"])
|
|
112
|
+
if (d[k] != null) a["w:" + k] = d[k];
|
|
113
|
+
x += `<w:ind${attrStr(a)}${extraAttr(d, Object.keys(a).map((k) => k.slice(2)))}/>`;
|
|
114
|
+
}
|
|
115
|
+
if (pPr.jc != null) x += `<w:jc w:val="${esc(String(pPr.jc))}"/>`;
|
|
116
|
+
if (pPr.textAlignment != null) x += `<w:textAlignment w:val="${esc(String(valOf(pPr.textAlignment)))}"/>`;
|
|
117
|
+
if (pPr.bidi === true) x += `<w:bidi/>`;
|
|
118
|
+
const olv = ooOutlineToOoxml(pPr.outlineLvl);
|
|
119
|
+
if (olv != null) x += `<w:outlineLvl w:val="${olv}"/>`;
|
|
120
|
+
return x;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function stylePpToXml(pPr) {
|
|
124
|
+
const inner = ppInnerXml(pPr);
|
|
125
|
+
const ex = pPr ? extraAttr(pPr, ["pStyle", "keepNext", "keepLines", "pageBreakBefore", "widowControl", "contextualSpacing", "suppressLineNumbers", "numPr", "tabs", "pBdr", "shd", "spacing", "ind", "jc", "textAlignment", "bidi", "outlineLvl", "type", "bFromDocument"]) : "";
|
|
126
|
+
return inner || ex ? `<w:pPr${ex}>${inner}</w:pPr>` : "";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function underlineXml(u) {
|
|
130
|
+
if (u == null) return "";
|
|
131
|
+
if (u === false) return `<w:u w:val="none"/>`;
|
|
132
|
+
if (u === true) return `<w:u w:val="single"/>`;
|
|
133
|
+
if (typeof u !== "object") return `<w:u w:val="${esc(String(u))}"/>`;
|
|
134
|
+
const a = {};
|
|
135
|
+
const val = u.val ?? u.value ?? u.type;
|
|
136
|
+
if (val != null) a["w:val"] = val;
|
|
137
|
+
if (u.color) a["w:color"] = colorToOoxml(u.color);
|
|
138
|
+
return `<w:u${attrStr(a)}${u.color ? autoRgbAttr("oo:rgb", u.color) : ""}${extraAttr(u, ["val", "value", "type", "color"])}/>`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function rpInnerXml(rPr) {
|
|
142
|
+
if (!rPr) return "";
|
|
143
|
+
let x = "";
|
|
144
|
+
if (rPr.rFonts) {
|
|
145
|
+
const f = rPr.rFonts, a = {};
|
|
146
|
+
for (const k of ["ascii", "hAnsi", "eastAsia", "cs", "hint", "asciiTheme", "hAnsiTheme", "eastAsiaTheme", "cstheme", "csTheme"])
|
|
147
|
+
if (f[k] != null) a["w:" + k] = f[k];
|
|
148
|
+
x += `<w:rFonts${attrStr(a)}${extraAttr(f, Object.keys(a).map((k) => k.slice(2)))}/>`;
|
|
149
|
+
}
|
|
150
|
+
const tgl = (name, v) => (v === true ? `<w:${name}/>` : v === false ? `<w:${name} w:val="false"/>` : "");
|
|
151
|
+
for (const name of ["b", "bCs", "i", "iCs", "strike", "dstrike", "caps", "smallCaps", "vanish", "rtl", "noProof"])
|
|
152
|
+
x += tgl(name, rPr[name]);
|
|
153
|
+
x += underlineXml(rPr.u);
|
|
154
|
+
if (rPr.color) x += `<w:color w:val="${colorToOoxml(rPr.color)}"${autoRgbAttr("oo:rgb", rPr.color)}/>`;
|
|
155
|
+
if (rPr.spacing != null) x += `<w:spacing w:val="${rPr.spacing}"/>`;
|
|
156
|
+
if (rPr.position != null) x += `<w:position w:val="${rPr.position}"/>`;
|
|
157
|
+
if (rPr.kern != null) x += `<w:kern w:val="${rPr.kern}"/>`;
|
|
158
|
+
if (rPr.sz != null) x += `<w:sz w:val="${rPr.sz}"/>`;
|
|
159
|
+
if (rPr.szCs != null) x += `<w:szCs w:val="${rPr.szCs}"/>`;
|
|
160
|
+
if (rPr.highlight) {
|
|
161
|
+
const h = highlightToOoxml(rPr.highlight);
|
|
162
|
+
if (h) x += `<w:highlight w:val="${h}"/>`;
|
|
163
|
+
}
|
|
164
|
+
if (rPr.vertAlign != null) x += `<w:vertAlign w:val="${esc(String(valOf(rPr.vertAlign)))}"/>`;
|
|
165
|
+
x += shdXml(rPr.shd);
|
|
166
|
+
if (rPr.lang) {
|
|
167
|
+
const a = {};
|
|
168
|
+
for (const k of ["val", "eastAsia", "bidi"]) if (rPr.lang[k] != null) a["w:" + k] = rPr.lang[k];
|
|
169
|
+
x += `<w:lang${attrStr(a)}${extraAttr(rPr.lang, ["val", "eastAsia", "bidi"])}/>`;
|
|
170
|
+
}
|
|
171
|
+
return x;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function styleRpToXml(rPr) {
|
|
175
|
+
const inner = rpInnerXml(rPr);
|
|
176
|
+
const ex = rPr ? extraAttr(rPr, ["rFonts", "b", "bCs", "i", "iCs", "strike", "dstrike", "caps", "smallCaps", "vanish", "rtl", "noProof", "u", "color", "spacing", "position", "kern", "sz", "szCs", "highlight", "vertAlign", "shd", "lang", "type", "bFromDocument"]) : "";
|
|
177
|
+
return inner || ex ? `<w:rPr${ex}>${inner}</w:rPr>` : "";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function tblPrXml(t) {
|
|
181
|
+
if (!t) return "";
|
|
182
|
+
let x = "";
|
|
183
|
+
if (t.tblStyle != null) x += `<w:tblStyle w:val="${esc(String(t.tblStyle))}"/>`;
|
|
184
|
+
x += widthXml("tblW", t.tblW);
|
|
185
|
+
if (t.jc != null) x += `<w:jc w:val="${esc(String(t.jc))}"/>`;
|
|
186
|
+
x += bordersXml("tblBorders", t.tblBorders);
|
|
187
|
+
x += shdXml(t.shd);
|
|
188
|
+
x += marXml("tblCellMar", t.tblCellMar);
|
|
189
|
+
if (t.tblLayout != null) x += `<w:tblLayout w:type="${esc(String(valOf(t.tblLayout)))}"/>`;
|
|
190
|
+
if (t.tblLook != null && typeof t.tblLook === "object") {
|
|
191
|
+
const a = {};
|
|
192
|
+
for (const k of Object.keys(t.tblLook)) if (k !== "type") a["w:" + k] = t.tblLook[k] === true ? 1 : t.tblLook[k] === false ? 0 : t.tblLook[k];
|
|
193
|
+
x += `<w:tblLook${attrStr(a)}/>`;
|
|
194
|
+
}
|
|
195
|
+
const ex = extraAttr(t, ["tblStyle", "tblW", "jc", "tblBorders", "shd", "tblCellMar", "tblLayout", "tblLook", "type"]);
|
|
196
|
+
return x || ex ? `<w:tblPr${ex}>${x}</w:tblPr>` : "";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function trPrXml(p) {
|
|
200
|
+
if (!p) return "";
|
|
201
|
+
let x = "";
|
|
202
|
+
if (p.tblHeader === true) x += `<w:tblHeader/>`;
|
|
203
|
+
if (p.cantSplit === true) x += `<w:cantSplit/>`;
|
|
204
|
+
if (p.jc != null) x += `<w:jc w:val="${esc(String(p.jc))}"/>`;
|
|
205
|
+
if (p.trHeight) x += `<w:trHeight${attrStr({ "w:val": p.trHeight.value != null ? p.trHeight.value : p.trHeight.val, "w:hRule": p.trHeight.hRule })}${extraAttr(p.trHeight, ["value", "val", "hRule"])}/>`;
|
|
206
|
+
const ex = extraAttr(p, ["tblHeader", "cantSplit", "jc", "trHeight", "type"]);
|
|
207
|
+
return x || ex ? `<w:trPr${ex}>${x}</w:trPr>` : "";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function tcPrXml(p) {
|
|
211
|
+
if (!p) return "";
|
|
212
|
+
let x = "";
|
|
213
|
+
x += widthXml("tcW", p.tcW);
|
|
214
|
+
if (p.gridSpan != null) x += `<w:gridSpan w:val="${p.gridSpan}"/>`;
|
|
215
|
+
if (p.vMerge != null) x += `<w:vMerge${p.vMerge && p.vMerge !== "continue" ? ` w:val="${esc(String(p.vMerge))}"` : ""}/>`;
|
|
216
|
+
x += bordersXml("tcBorders", p.tcBorders);
|
|
217
|
+
x += shdXml(p.shd);
|
|
218
|
+
x += marXml("tcMar", p.tcMar);
|
|
219
|
+
if (p.vAlign != null) x += `<w:vAlign w:val="${esc(String(valOf(p.vAlign)))}"/>`;
|
|
220
|
+
if (p.noWrap === true) x += `<w:noWrap/>`;
|
|
221
|
+
const ex = extraAttr(p, ["tcW", "gridSpan", "vMerge", "tcBorders", "shd", "tcMar", "vAlign", "noWrap", "type"]);
|
|
222
|
+
return x || ex ? `<w:tcPr${ex}>${x}</w:tcPr>` : "";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function styleType(t) {
|
|
226
|
+
switch (t) {
|
|
227
|
+
case "paragraphStyle": return "paragraph";
|
|
228
|
+
case "characterStyle": return "character";
|
|
229
|
+
case "tableStyle": return "table";
|
|
230
|
+
case "numberingStyle": return "numbering";
|
|
231
|
+
case "character": case "table": case "numbering": case "paragraph": return t;
|
|
232
|
+
default: return "paragraph";
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function tableStyleType(t) {
|
|
237
|
+
switch (t) {
|
|
238
|
+
case "topLeftCell": return "nwCell";
|
|
239
|
+
case "topRightCell": return "neCell";
|
|
240
|
+
case "bottomLeftCell": return "swCell";
|
|
241
|
+
case "bottomRightCell": return "seCell";
|
|
242
|
+
default: return t;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function tableStylePrXml(type, pr) {
|
|
247
|
+
if (!pr) return "";
|
|
248
|
+
const wType = tableStyleType(pr.styleType ?? type);
|
|
249
|
+
if (!wType) return "";
|
|
250
|
+
const inner = stylePpToXml(pr.pPr) + styleRpToXml(pr.rPr) + tblPrXml(pr.tblPr) + trPrXml(pr.trPr) + tcPrXml(pr.tcPr);
|
|
251
|
+
const ex = extraAttr(pr, ["styleType", "pPr", "rPr", "tblPr", "trPr", "tcPr", "type"]);
|
|
252
|
+
return inner || ex ? `<w:tblStylePr w:type="${esc(String(wType))}"${ex}>${inner}</w:tblStylePr>` : "";
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function tableStylePrListXml(tblStylePr) {
|
|
256
|
+
if (!tblStylePr || typeof tblStylePr !== "object") return "";
|
|
257
|
+
let x = "";
|
|
258
|
+
for (const key of Object.keys(tblStylePr)) x += tableStylePrXml(key, tblStylePr[key]);
|
|
259
|
+
return x;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function styleToXml(styleId, s) {
|
|
263
|
+
if (!s || styleId == null) return "";
|
|
264
|
+
const type = styleType(s.styleType ?? s.type);
|
|
265
|
+
const attrs = { "w:type": type, "w:styleId": String(styleId) };
|
|
266
|
+
if (s.default === true) attrs["w:default"] = "1";
|
|
267
|
+
if (s.customStyle === true) attrs["w:customStyle"] = "1";
|
|
268
|
+
let inner = "";
|
|
269
|
+
if (s.name != null) inner += `<w:name w:val="${esc(String(s.name))}"/>`;
|
|
270
|
+
if (s.basedOn != null && s.basedOn !== "") inner += `<w:basedOn w:val="${esc(String(s.basedOn))}"/>`;
|
|
271
|
+
if (s.next != null && s.next !== "") inner += `<w:next w:val="${esc(String(s.next))}"/>`;
|
|
272
|
+
if (s.link != null && s.link !== "") inner += `<w:link w:val="${esc(String(s.link))}"/>`;
|
|
273
|
+
if (s.hidden === true) inner += `<w:hidden/>`;
|
|
274
|
+
if (s.uiPriority != null) inner += `<w:uiPriority w:val="${s.uiPriority}"/>`;
|
|
275
|
+
if (s.semiHidden === true) inner += `<w:semiHidden/>`;
|
|
276
|
+
if (s.unhideWhenUsed === true) inner += `<w:unhideWhenUsed/>`;
|
|
277
|
+
if (s.qFormat === true) inner += `<w:qFormat/>`;
|
|
278
|
+
inner += stylePpToXml(s.pPr);
|
|
279
|
+
inner += styleRpToXml(s.rPr);
|
|
280
|
+
inner += tblPrXml(s.tblPr);
|
|
281
|
+
inner += trPrXml(s.trPr);
|
|
282
|
+
inner += tcPrXml(s.tcPr);
|
|
283
|
+
inner += tableStylePrListXml(s.tblStylePr);
|
|
284
|
+
return `<w:style${attrStr(attrs)}>${inner}</w:style>`;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function buildStylesXml(styles, docDefaults) {
|
|
288
|
+
let dd = "";
|
|
289
|
+
if (docDefaults && (docDefaults.paraPr || docDefaults.textPr)) {
|
|
290
|
+
const rpr = styleRpToXml(docDefaults.textPr);
|
|
291
|
+
const ppr = stylePpToXml(docDefaults.paraPr);
|
|
292
|
+
dd = `<w:docDefaults><w:rPrDefault>${rpr}</w:rPrDefault><w:pPrDefault>${ppr}</w:pPrDefault></w:docDefaults>`;
|
|
293
|
+
}
|
|
294
|
+
const body = (styles || []).map((it) => styleToXml(it.styleId, it.def)).join("");
|
|
295
|
+
return (
|
|
296
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
297
|
+
`<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:oo="urn:coco:oojson">` +
|
|
298
|
+
dd +
|
|
299
|
+
body +
|
|
300
|
+
`</w:styles>`
|
|
301
|
+
);
|
|
302
|
+
}
|