@fiduswriter/document 0.1.0-alpha.1
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 +661 -0
- package/README.md +16 -0
- package/jest.config.js +23 -0
- package/package.json +59 -0
- package/schema.json +1 -0
- package/scripts/export-schema.js +16 -0
- package/src/bibliography/common.js +92 -0
- package/src/bibliography/csl_bib.js +139 -0
- package/src/citations/citeproc_sys.js +42 -0
- package/src/citations/format.js +194 -0
- package/src/common/blob.js +10 -0
- package/src/common/file.js +25 -0
- package/src/common/index.js +12 -0
- package/src/common/network.js +79 -0
- package/src/common/text.js +44 -0
- package/src/editor/e2ee/encryptor.js +228 -0
- package/src/exporter/docx/citations.js +177 -0
- package/src/exporter/docx/comments.js +165 -0
- package/src/exporter/docx/footnotes.js +240 -0
- package/src/exporter/docx/images.js +101 -0
- package/src/exporter/docx/index.js +185 -0
- package/src/exporter/docx/lists.js +260 -0
- package/src/exporter/docx/math.js +46 -0
- package/src/exporter/docx/metadata.js +289 -0
- package/src/exporter/docx/rels.js +193 -0
- package/src/exporter/docx/render.js +941 -0
- package/src/exporter/docx/richtext.js +1182 -0
- package/src/exporter/docx/tables.js +112 -0
- package/src/exporter/docx/tools.js +50 -0
- package/src/exporter/epub/index.js +142 -0
- package/src/exporter/epub/templates.js +140 -0
- package/src/exporter/epub/tools.js +96 -0
- package/src/exporter/html/citations.js +121 -0
- package/src/exporter/html/convert.js +813 -0
- package/src/exporter/html/index.js +192 -0
- package/src/exporter/html/templates.js +34 -0
- package/src/exporter/html/tools.js +50 -0
- package/src/exporter/jats/bibliography.js +183 -0
- package/src/exporter/jats/citations.js +109 -0
- package/src/exporter/jats/convert.js +871 -0
- package/src/exporter/jats/index.js +92 -0
- package/src/exporter/jats/templates.js +35 -0
- package/src/exporter/jats/text.js +72 -0
- package/src/exporter/latex/convert.js +934 -0
- package/src/exporter/latex/escape_latex.js +21 -0
- package/src/exporter/latex/index.js +74 -0
- package/src/exporter/latex/readme.js +22 -0
- package/src/exporter/native/shrink.js +132 -0
- package/src/exporter/odt/citations.js +101 -0
- package/src/exporter/odt/footnotes.js +147 -0
- package/src/exporter/odt/images.js +115 -0
- package/src/exporter/odt/index.js +156 -0
- package/src/exporter/odt/math.js +57 -0
- package/src/exporter/odt/metadata.js +251 -0
- package/src/exporter/odt/render.js +806 -0
- package/src/exporter/odt/richtext.js +865 -0
- package/src/exporter/odt/styles.js +387 -0
- package/src/exporter/odt/track.js +68 -0
- package/src/exporter/pandoc/citations.js +98 -0
- package/src/exporter/pandoc/convert.js +1017 -0
- package/src/exporter/pandoc/index.js +92 -0
- package/src/exporter/pandoc/readme.js +8 -0
- package/src/exporter/pandoc/tools.js +51 -0
- package/src/exporter/print/index.js +177 -0
- package/src/exporter/tools/doc_content.js +144 -0
- package/src/exporter/tools/file.js +9 -0
- package/src/exporter/tools/json.js +73 -0
- package/src/exporter/tools/svg.js +29 -0
- package/src/exporter/tools/xml.js +531 -0
- package/src/exporter/tools/xml_zip.js +95 -0
- package/src/exporter/tools/zip.js +90 -0
- package/src/exporter/tools/zotero_csl.js +93 -0
- package/src/importer/citations.js +129 -0
- package/src/importer/docx/citations.js +123 -0
- package/src/importer/docx/convert.js +1427 -0
- package/src/importer/docx/helpers.js +9 -0
- package/src/importer/docx/omml2mathml.js +1448 -0
- package/src/importer/docx/parse.js +735 -0
- package/src/importer/native/get_images.js +76 -0
- package/src/importer/native/update.js +29 -0
- package/src/importer/odt/citations.js +87 -0
- package/src/importer/odt/convert.js +1855 -0
- package/src/importer/pandoc/convert.js +884 -0
- package/src/importer/pandoc/helpers.js +84 -0
- package/src/importer/zip_analyzer.js +102 -0
- package/src/index.js +1 -0
- package/src/mathlive/opf_includes.js +24 -0
- package/src/schema/common/annotate.js +76 -0
- package/src/schema/common/base.js +118 -0
- package/src/schema/common/citation.js +62 -0
- package/src/schema/common/equation.js +31 -0
- package/src/schema/common/figure.js +190 -0
- package/src/schema/common/heading.js +43 -0
- package/src/schema/common/index.js +40 -0
- package/src/schema/common/list.js +95 -0
- package/src/schema/common/reference.js +100 -0
- package/src/schema/common/table.js +103 -0
- package/src/schema/common/track.js +190 -0
- package/src/schema/const.js +58 -0
- package/src/schema/convert.js +1272 -0
- package/src/schema/document/content.js +187 -0
- package/src/schema/document/index.js +117 -0
- package/src/schema/document/structure.js +452 -0
- package/src/schema/export.js +21 -0
- package/src/schema/footnotes.js +126 -0
- package/src/schema/footnotes_convert.js +31 -0
- package/src/schema/i18n.js +595 -0
- package/src/schema/index.js +5 -0
- package/src/schema/mini_json.js +61 -0
- package/src/schema/text.js +22 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
const GRAPHIC_STYLES = {
|
|
2
|
+
Formula: `
|
|
3
|
+
<style:style style:name="Formula" style:family="graphic">
|
|
4
|
+
<style:graphic-properties text:anchor-type="as-char" svg:y="0in" fo:margin-left="0.0791in" fo:margin-right="0.0791in" style:vertical-pos="middle" style:vertical-rel="text"/>
|
|
5
|
+
</style:style>`,
|
|
6
|
+
Graphics: `
|
|
7
|
+
<style:style style:name="Graphics" style:family="graphic">
|
|
8
|
+
<style:graphic-properties text:anchor-type="paragraph" svg:x="0in" svg:y="0in" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
|
|
9
|
+
</style:style>`,
|
|
10
|
+
Frame: `
|
|
11
|
+
<style:style style:name="Frame" style:family="graphic">
|
|
12
|
+
<style:graphic-properties text:anchor-type="paragraph" svg:x="0in" svg:y="0in" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
|
|
13
|
+
</style:style>`
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const PAR_STYLES = {
|
|
17
|
+
Bibliography_20_Heading: `<style:style style:name="Bibliography_20_Heading" style:display-name="Bibliography Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index">
|
|
18
|
+
<style:paragraph-properties fo:margin-left="0in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/>
|
|
19
|
+
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/>
|
|
20
|
+
</style:style>`,
|
|
21
|
+
Caption: `<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
|
22
|
+
<style:paragraph-properties fo:margin-top="0.0835in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" text:number-lines="false" text:line-number="0" />
|
|
23
|
+
<style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" />
|
|
24
|
+
</style:style>`,
|
|
25
|
+
Figure: '<style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" />',
|
|
26
|
+
Standard:
|
|
27
|
+
'<style:style style:name="Standard" style:family="paragraph" style:class="text" />'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class ODTExporterStyles {
|
|
31
|
+
constructor(xml) {
|
|
32
|
+
this.xml = xml
|
|
33
|
+
|
|
34
|
+
this.contentXml = false
|
|
35
|
+
this.stylesXml = false
|
|
36
|
+
this.boldStyleId = false
|
|
37
|
+
this.italicStyleId = false
|
|
38
|
+
this.boldItalicStyleId = false
|
|
39
|
+
this.inlineStyleIds = {}
|
|
40
|
+
this.tableStyleIds = {}
|
|
41
|
+
this.graphicStyleIds = {}
|
|
42
|
+
this.bulletListStyleId = [false, false]
|
|
43
|
+
this.inlineStyleCounter = 0
|
|
44
|
+
this.tableStyleCounter = 0
|
|
45
|
+
this.blockStyleCounter = 0
|
|
46
|
+
this.listStyleCounter = 0
|
|
47
|
+
this.graphicStyleCounter = 0
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
init() {
|
|
51
|
+
return this.xml
|
|
52
|
+
.getXml("styles.xml")
|
|
53
|
+
.then(stylesXml => {
|
|
54
|
+
this.stylesXml = stylesXml
|
|
55
|
+
return this.xml.getXml("content.xml")
|
|
56
|
+
})
|
|
57
|
+
.then(contentXml => {
|
|
58
|
+
this.contentXml = contentXml
|
|
59
|
+
this.getStyleCounters()
|
|
60
|
+
return Promise.resolve()
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getStyleCounters() {
|
|
65
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
66
|
+
const styles = autoStylesEl.queryAll("style:style")
|
|
67
|
+
styles.forEach(style => {
|
|
68
|
+
const styleNumber = Number.parseInt(
|
|
69
|
+
style.getAttribute("style:name").replace(/\D/g, "")
|
|
70
|
+
)
|
|
71
|
+
const styleFamily = style.getAttribute("style:family")
|
|
72
|
+
if (styleFamily === "text") {
|
|
73
|
+
if (styleNumber > this.inlineStyleCounter) {
|
|
74
|
+
this.inlineStyleCounter = styleNumber
|
|
75
|
+
}
|
|
76
|
+
} else if (styleFamily === "table") {
|
|
77
|
+
if (styleNumber > this.tableStyleCounter) {
|
|
78
|
+
this.tableStyleCounter = styleNumber
|
|
79
|
+
}
|
|
80
|
+
} else if (styleFamily === "paragraph") {
|
|
81
|
+
if (styleNumber > this.blockStyleCounter) {
|
|
82
|
+
this.blockStyleCounter = styleNumber
|
|
83
|
+
}
|
|
84
|
+
} else if (styleFamily === "graphic") {
|
|
85
|
+
if (styleNumber > this.graphicStyleCounter) {
|
|
86
|
+
this.graphicStyleCounter = styleNumber
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
const listStyles = autoStylesEl.queryAll("text:list-style")
|
|
91
|
+
listStyles.forEach(style => {
|
|
92
|
+
const styleNumber = Number.parseInt(
|
|
93
|
+
style.getAttribute("style:name").replace(/\D/g, "")
|
|
94
|
+
)
|
|
95
|
+
if (styleNumber > this.listStyleCounter) {
|
|
96
|
+
this.listStyleCounter = styleNumber
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
attributes is a string that consists of these characters (in this order).
|
|
103
|
+
Only one of super/sub possible.
|
|
104
|
+
e = italic/em
|
|
105
|
+
s = bold/strong
|
|
106
|
+
u = underline
|
|
107
|
+
c = small caps
|
|
108
|
+
p = super
|
|
109
|
+
b = sub
|
|
110
|
+
t = code (monospace)
|
|
111
|
+
*/
|
|
112
|
+
getInlineStyleId(attributes) {
|
|
113
|
+
if (this.inlineStyleIds[attributes]) {
|
|
114
|
+
return this.inlineStyleIds[attributes]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let styleProperties = ""
|
|
118
|
+
if (attributes.includes("e")) {
|
|
119
|
+
styleProperties +=
|
|
120
|
+
' fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"'
|
|
121
|
+
}
|
|
122
|
+
if (attributes.includes("s")) {
|
|
123
|
+
styleProperties +=
|
|
124
|
+
' fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"'
|
|
125
|
+
}
|
|
126
|
+
if (attributes.includes("u")) {
|
|
127
|
+
styleProperties +=
|
|
128
|
+
' style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"'
|
|
129
|
+
}
|
|
130
|
+
if (attributes.includes("c")) {
|
|
131
|
+
styleProperties += ' fo:font-variant="small-caps"'
|
|
132
|
+
}
|
|
133
|
+
if (attributes.includes("p")) {
|
|
134
|
+
styleProperties += ' style:text-position="super 58%"'
|
|
135
|
+
} else if (attributes.includes("b")) {
|
|
136
|
+
styleProperties += ' style:text-position="sub 58%"'
|
|
137
|
+
}
|
|
138
|
+
if (attributes.includes("t")) {
|
|
139
|
+
styleProperties +=
|
|
140
|
+
' style:font-name="Courier New" fo:font-family="Courier New"'
|
|
141
|
+
}
|
|
142
|
+
const styleCounter = ++this.inlineStyleCounter
|
|
143
|
+
this.inlineStyleIds[attributes] = styleCounter
|
|
144
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
145
|
+
autoStylesEl.appendXML(`
|
|
146
|
+
<style:style style:name="T${styleCounter}" style:family="text">
|
|
147
|
+
<style:text-properties${styleProperties}/>
|
|
148
|
+
</style:style>
|
|
149
|
+
`)
|
|
150
|
+
return styleCounter
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/*
|
|
154
|
+
aligned: left/center/right
|
|
155
|
+
width: '75'/'50'/'25' = percentage width - 100% doesn't need any style
|
|
156
|
+
*/
|
|
157
|
+
getTableStyleId(aligned, width) {
|
|
158
|
+
if (this.tableStyleIds[aligned + width]) {
|
|
159
|
+
return this.tableStyleIds[aligned + width]
|
|
160
|
+
}
|
|
161
|
+
const styleCounter = ++this.tableStyleCounter
|
|
162
|
+
this.tableStyleIds[aligned + width] = styleCounter
|
|
163
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
164
|
+
autoStylesEl.appendXML(`
|
|
165
|
+
<style:style style:name="Table${styleCounter}" style:family="table">
|
|
166
|
+
<style:table-properties style:rel-width="${width}%" table:align="${aligned}"/>
|
|
167
|
+
</style:style>
|
|
168
|
+
`)
|
|
169
|
+
return styleCounter
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
checkParStyle(styleName) {
|
|
173
|
+
const stylesParStyle = this.stylesXml.query("style:style", {
|
|
174
|
+
"style:name": styleName
|
|
175
|
+
})
|
|
176
|
+
const contentParStyle = this.contentXml.query("style:style", {
|
|
177
|
+
"style:name": styleName
|
|
178
|
+
})
|
|
179
|
+
if (!stylesParStyle && !contentParStyle) {
|
|
180
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
181
|
+
const displayName = styleName.split("_20_").join(" ")
|
|
182
|
+
stylesEl.appendXML(
|
|
183
|
+
PAR_STYLES[styleName] ||
|
|
184
|
+
`<style:style style:name="${styleName}" style:display-name="${displayName}" style:family="paragraph" style:parent-style-name="Standard" style:class="text" />`
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
checkGraphicStyle(styleName) {
|
|
190
|
+
const stylesParStyle = this.stylesXml.query("style:style", {
|
|
191
|
+
"style:name": styleName
|
|
192
|
+
})
|
|
193
|
+
const contentParStyle = this.contentXml.query("style:style", {
|
|
194
|
+
"style:name": styleName
|
|
195
|
+
})
|
|
196
|
+
if (!stylesParStyle && !contentParStyle) {
|
|
197
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
198
|
+
stylesEl.appendXML(GRAPHIC_STYLES[styleName])
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
checkSectionStyle(styleName) {
|
|
203
|
+
const stylesSection = this.stylesXml.query("style:style", {
|
|
204
|
+
"style:name": styleName,
|
|
205
|
+
"style:family": "section"
|
|
206
|
+
})
|
|
207
|
+
const contentSection = this.contentXml.query("style:style", {
|
|
208
|
+
"style:name": styleName,
|
|
209
|
+
"style:family": "section"
|
|
210
|
+
})
|
|
211
|
+
if (!stylesSection && !contentSection) {
|
|
212
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
213
|
+
// Add a basic section style if it doesn't exist
|
|
214
|
+
stylesEl.appendXML(
|
|
215
|
+
`<style:style style:name="${styleName}" style:family="section">
|
|
216
|
+
<style:section-properties text:dont-balance-text-columns="false" fo:background-color="transparent">
|
|
217
|
+
<style:columns fo:column-count="1" fo:column-gap="0in"/>
|
|
218
|
+
</style:section-properties>
|
|
219
|
+
</style:style>`
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/*
|
|
225
|
+
styleName: Frame/Formula/Graphics
|
|
226
|
+
aligned: left/center/right (not used for Formula)
|
|
227
|
+
*/
|
|
228
|
+
getGraphicStyleId(styleName, aligned = "") {
|
|
229
|
+
if (this.graphicStyleIds[styleName + aligned]) {
|
|
230
|
+
return this.graphicStyleIds[styleName + aligned]
|
|
231
|
+
}
|
|
232
|
+
this.checkGraphicStyle(styleName)
|
|
233
|
+
|
|
234
|
+
const styleCounter = ++this.graphicStyleCounter
|
|
235
|
+
this.graphicStyleIds[styleName + aligned] = styleCounter
|
|
236
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
237
|
+
autoStylesEl.appendXML(`
|
|
238
|
+
<style:style style:name="fr${styleCounter}" style:family="graphic" style:parent-style-name="${styleName}">
|
|
239
|
+
${
|
|
240
|
+
styleName === "Formula"
|
|
241
|
+
? '<style:graphic-properties style:vertical-pos="from-top" style:horizontal-pos="from-left" style:horizontal-rel="paragraph-content" draw:ole-draw-aspect="1" />'
|
|
242
|
+
: `<style:graphic-properties fo:margin-left="0in" fo:margin-right="0in" fo:margin-top="0in" fo:margin-bottom="0in" ${aligned === "center" ? 'style:wrap="none"' : 'style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit"'} style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="${aligned}" style:horizontal-rel="paragraph" fo:padding="0in" fo:border="none" loext:rel-width-rel="paragraph" />`
|
|
243
|
+
} style:number-wrapped-paragraphs="no-limit"
|
|
244
|
+
</style:style>`)
|
|
245
|
+
return styleCounter
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
addReferenceStyle(bibInfo) {
|
|
249
|
+
// The style called "Bibliography_20_1" will override any previous style
|
|
250
|
+
// of the same name.
|
|
251
|
+
const stylesParStyle = this.stylesXml.query("style:style", {
|
|
252
|
+
"style:name": "Bibliography_20_1"
|
|
253
|
+
})
|
|
254
|
+
if (stylesParStyle) {
|
|
255
|
+
stylesParStyle.parentElement.removeChild(stylesParStyle)
|
|
256
|
+
}
|
|
257
|
+
const contentParStyle = this.contentXml.query("style:style", {
|
|
258
|
+
"style:name": "Bibliography_20_1"
|
|
259
|
+
})
|
|
260
|
+
if (contentParStyle) {
|
|
261
|
+
contentParStyle.parentElement.removeChild(contentParStyle)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this.checkParStyle("Index")
|
|
265
|
+
|
|
266
|
+
const lineHeight = `${0.1665 * bibInfo.linespacing}in`
|
|
267
|
+
const marginBottom = `${0.1667 * bibInfo.entryspacing}in`
|
|
268
|
+
let marginLeft = "0in",
|
|
269
|
+
textIndent = "0in",
|
|
270
|
+
tabStops = "<style:tab-stops/>"
|
|
271
|
+
|
|
272
|
+
if (bibInfo.hangingindent) {
|
|
273
|
+
marginLeft = "0.5in"
|
|
274
|
+
textIndent = "-0.5in"
|
|
275
|
+
} else if (bibInfo["second-field-align"]) {
|
|
276
|
+
// We calculate 0.55em as roughly equivalent to one letter width.
|
|
277
|
+
const firstFieldWidth = `${(bibInfo.maxoffset + 1) * 0.55}em`
|
|
278
|
+
if (bibInfo["second-field-align"] === "margin") {
|
|
279
|
+
textIndent = `-${firstFieldWidth}`
|
|
280
|
+
tabStops =
|
|
281
|
+
'<style:tab-stops><style:tab-stop style:position="0in"/></style:tab-stops>'
|
|
282
|
+
} else {
|
|
283
|
+
textIndent = `-${firstFieldWidth}`
|
|
284
|
+
marginLeft = `${firstFieldWidth}`
|
|
285
|
+
tabStops = `<style:tab-stops><style:tab-stop style:position="${firstFieldWidth}"/></style:tab-stops>`
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const styleDef = `
|
|
289
|
+
<style:style style:name="Bibliography_20_1" style:display-name="Bibliography 1" style:family="paragraph" style:parent-style-name="Index" style:class="index">
|
|
290
|
+
<style:paragraph-properties fo:margin-left="${marginLeft}" fo:margin-right="0in" fo:margin-top="0in" fo:margin-bottom="${marginBottom}" loext:contextual-spacing="false" fo:text-indent="${textIndent}" style:line-height-at-least="${lineHeight}" style:auto-text-indent="false">
|
|
291
|
+
${tabStops}
|
|
292
|
+
</style:paragraph-properties>
|
|
293
|
+
</style:style>`
|
|
294
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
295
|
+
stylesEl.appendXML(styleDef)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
getBulletListStyleId() {
|
|
299
|
+
if (this.bulletListStyleId[0]) {
|
|
300
|
+
return this.bulletListStyleId
|
|
301
|
+
}
|
|
302
|
+
this.bulletListStyleId[0] = ++this.listStyleCounter
|
|
303
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
304
|
+
autoStylesEl.appendXML(`
|
|
305
|
+
<text:list-style style:name="L${this.bulletListStyleId[0]}">
|
|
306
|
+
</text:list-style>
|
|
307
|
+
`)
|
|
308
|
+
const listStyleEl =
|
|
309
|
+
autoStylesEl.children[autoStylesEl.children.length - 1]
|
|
310
|
+
// ODT files seem to contain ten levels of lists (1-10)
|
|
311
|
+
for (let level = 1; level < 11; level++) {
|
|
312
|
+
listStyleEl.appendXML(`
|
|
313
|
+
<text:list-level-style-bullet text:level="${level}" text:style-name="Bullet_20_Symbols" text:bullet-char="•">
|
|
314
|
+
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
|
|
315
|
+
<style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="${(level + 1) * 0.25}in" fo:text-indent="-0.25in" fo:margin-left="${(level + 1) * 0.25}in" />
|
|
316
|
+
</style:list-level-properties>
|
|
317
|
+
</text:list-level-style-bullet>
|
|
318
|
+
`)
|
|
319
|
+
}
|
|
320
|
+
this.bulletListStyleId[1] = this.addListParStyle(
|
|
321
|
+
this.bulletListStyleId[0]
|
|
322
|
+
)
|
|
323
|
+
return this.bulletListStyleId
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
getOrderedListStyleId(start) {
|
|
327
|
+
const orderedListStyleId = ++this.listStyleCounter
|
|
328
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
329
|
+
autoStylesEl.appendXML(`
|
|
330
|
+
<text:list-style style:name="L${orderedListStyleId}">
|
|
331
|
+
</text:list-style>
|
|
332
|
+
`)
|
|
333
|
+
const listStyleEl =
|
|
334
|
+
autoStylesEl.children[autoStylesEl.children.length - 1]
|
|
335
|
+
// ODT files seem to contain ten levels of lists (1-10)
|
|
336
|
+
for (let level = 1; level < 11; level++) {
|
|
337
|
+
listStyleEl.appendXML(`
|
|
338
|
+
<text:list-level-style-number text:level="${level}" text:style-name="Numbering_20_Symbols" style:num-suffix="." style:num-format="1"${start > 1 ? ` text:start-value="${start}"` : ""}>
|
|
339
|
+
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
|
|
340
|
+
<style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="${(level + 1) * 0.25}in" fo:text-indent="-0.25in" fo:margin-left="${(level + 1) * 0.25}in" />
|
|
341
|
+
</style:list-level-properties>
|
|
342
|
+
</text:list-level-style-number>
|
|
343
|
+
`)
|
|
344
|
+
}
|
|
345
|
+
return [orderedListStyleId, this.addListParStyle(orderedListStyleId)]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Add a paragraph style for either paragraph in bullet or numeric list
|
|
349
|
+
addListParStyle(_listId) {
|
|
350
|
+
const parStyleId = ++this.blockStyleCounter
|
|
351
|
+
const autoStylesEl = this.contentXml.query("office:automatic-styles")
|
|
352
|
+
autoStylesEl.appendXML(
|
|
353
|
+
`<style:style style:name="P${parStyleId}" style:family="paragraph" style:parent-style-name="Standard" text:list-style-name="L1" />`
|
|
354
|
+
)
|
|
355
|
+
return parStyleId
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
addPageBreakStyle() {
|
|
359
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
360
|
+
stylesEl.queryAll("style:style").forEach(style => {
|
|
361
|
+
if (style.getAttribute("style:name") === "PageBreak") {
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
})
|
|
365
|
+
stylesEl.appendXML(
|
|
366
|
+
'<style:style style:name="PageBreak" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"><style:paragraph-properties fo:break-before="page"/></style:style>'
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
setLanguage(langCode) {
|
|
371
|
+
const langCodes = langCode.split("-"),
|
|
372
|
+
[language] = langCodes
|
|
373
|
+
|
|
374
|
+
let [, country] = langCodes
|
|
375
|
+
|
|
376
|
+
if (!country) {
|
|
377
|
+
country = "none"
|
|
378
|
+
}
|
|
379
|
+
const stylesEl = this.stylesXml.query("office:styles")
|
|
380
|
+
stylesEl.queryAll("style:default-style").forEach(el => {
|
|
381
|
+
el.queryAll("style:text-properties").forEach(el => {
|
|
382
|
+
el.setAttribute("fo:language", language)
|
|
383
|
+
el.setAttribute("fo:country", country)
|
|
384
|
+
})
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {escapeText} from "../../common/index.js"
|
|
2
|
+
|
|
3
|
+
export class ODTExporterTracks {
|
|
4
|
+
constructor(xml) {
|
|
5
|
+
this.xml = xml
|
|
6
|
+
|
|
7
|
+
this.contentXml = false
|
|
8
|
+
this.trackChangesSection = false
|
|
9
|
+
this.counter = 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
init() {
|
|
13
|
+
return this.xml.getXml("content.xml").then(contentXml => {
|
|
14
|
+
this.contentXml = contentXml
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
checkTrackedChangesSection() {
|
|
19
|
+
if (this.trackChangesSection) {
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
const trackChangesSection = this.contentXml.query(
|
|
23
|
+
"text:tracked-changes"
|
|
24
|
+
)
|
|
25
|
+
if (trackChangesSection) {
|
|
26
|
+
this.trackChangesSection = trackChangesSection
|
|
27
|
+
} else {
|
|
28
|
+
const textElement = this.contentXml.query("office:text")
|
|
29
|
+
if (!textElement) {
|
|
30
|
+
throw new Error("No text element found in content.xml")
|
|
31
|
+
}
|
|
32
|
+
textElement.prependXML(
|
|
33
|
+
"<text:tracked-changes></text:tracked-changes>"
|
|
34
|
+
)
|
|
35
|
+
this.trackChangesSection = textElement.firstElementChild
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
addChange(trackInfo, deletionString = "") {
|
|
40
|
+
if (!this.trackChangesSection) {
|
|
41
|
+
this.checkTrackedChangesSection()
|
|
42
|
+
}
|
|
43
|
+
const trackId = `ct${Date.now() + this.counter++}`
|
|
44
|
+
const changeXml = `
|
|
45
|
+
<text:changed-region xml:id="${trackId}" text:id="${trackId}">
|
|
46
|
+
${
|
|
47
|
+
trackInfo.type === "deletion"
|
|
48
|
+
? `<text:deletion>
|
|
49
|
+
<office:change-info>
|
|
50
|
+
<dc:creator>${escapeText(trackInfo.username)}</dc:creator>
|
|
51
|
+
<dc:date>${new Date(trackInfo.date * 60000).toISOString().slice(0, 19)}</dc:date>
|
|
52
|
+
</office:change-info>
|
|
53
|
+
${deletionString}
|
|
54
|
+
</text:deletion>`
|
|
55
|
+
: trackInfo.type === "insertion"
|
|
56
|
+
? `<text:insertion>
|
|
57
|
+
<office:change-info>
|
|
58
|
+
<dc:creator>${escapeText(trackInfo.username)}</dc:creator>
|
|
59
|
+
<dc:date>${new Date(trackInfo.date * 60000).toISOString().slice(0, 19)}</dc:date>
|
|
60
|
+
</office:change-info>
|
|
61
|
+
</text:insertion>`
|
|
62
|
+
: ""
|
|
63
|
+
}
|
|
64
|
+
</text:changed-region>`
|
|
65
|
+
this.trackChangesSection.appendXML(changeXml)
|
|
66
|
+
return trackId
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {DOMParser, DOMSerializer} from "prosemirror-model"
|
|
2
|
+
|
|
3
|
+
import {cslBibSchema} from "../../bibliography/csl_bib.js"
|
|
4
|
+
import {FormatCitations} from "../../citations/format.js"
|
|
5
|
+
import {fnSchema} from "../../schema/footnotes.js"
|
|
6
|
+
import {descendantNodes} from "../tools/doc_content.js"
|
|
7
|
+
|
|
8
|
+
export class PandocExporterCitations {
|
|
9
|
+
constructor(exporter, bibDB, csl, docContent, origCitInfos = []) {
|
|
10
|
+
this.exporter = exporter
|
|
11
|
+
this.bibDB = bibDB
|
|
12
|
+
this.csl = csl
|
|
13
|
+
this.docContent = docContent
|
|
14
|
+
// If citInfos were found in a previous run, they are stored here
|
|
15
|
+
// (for example: first citations in main document, then in footnotes)
|
|
16
|
+
this.origCitInfos = origCitInfos
|
|
17
|
+
this.citInfos = []
|
|
18
|
+
this.citationTexts = []
|
|
19
|
+
this.pmCits = []
|
|
20
|
+
this.citFm = false
|
|
21
|
+
this.pmBib = false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
init() {
|
|
25
|
+
return this.formatCitations()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Citations are highly interdependent -- so we need to format them all
|
|
29
|
+
// together before laying out the document.
|
|
30
|
+
formatCitations() {
|
|
31
|
+
if (this.origCitInfos.length) {
|
|
32
|
+
// Initial citInfos are taken from a previous run to include in
|
|
33
|
+
// bibliography, and they are removed before spitting out the
|
|
34
|
+
// citation entries for the given document.
|
|
35
|
+
// That way the bibliography should contain information from both.
|
|
36
|
+
this.citInfos = this.citInfos.concat(this.origCitInfos)
|
|
37
|
+
}
|
|
38
|
+
descendantNodes(this.docContent).forEach(node => {
|
|
39
|
+
if (node.type === "citation") {
|
|
40
|
+
this.citInfos.push(JSON.parse(JSON.stringify(node.attrs)))
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
this.citFm = new FormatCitations(
|
|
44
|
+
this.csl,
|
|
45
|
+
this.citInfos,
|
|
46
|
+
this.exporter.doc.settings.citationstyle,
|
|
47
|
+
"",
|
|
48
|
+
this.bibDB,
|
|
49
|
+
false,
|
|
50
|
+
this.exporter.doc.settings.language
|
|
51
|
+
)
|
|
52
|
+
return this.citFm.init().then(() => {
|
|
53
|
+
this.citationTexts = this.citFm.citationTexts
|
|
54
|
+
if (this.origCitInfos.length) {
|
|
55
|
+
// Remove all citation texts originating from original starting citInfos
|
|
56
|
+
this.citationTexts.splice(0, this.origCitInfos.length)
|
|
57
|
+
}
|
|
58
|
+
this.convertCitations()
|
|
59
|
+
return Promise.resolve()
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
convertCitations() {
|
|
64
|
+
// There could be some formatting in the citations, so we parse them through the PM schema for final formatting.
|
|
65
|
+
// We need to put the citations each in a paragraph so that it works with
|
|
66
|
+
// the fiduswriter schema and so that the converter doesn't mash them together.
|
|
67
|
+
if (this.citationTexts.length) {
|
|
68
|
+
let citationsHTML = ""
|
|
69
|
+
this.citationTexts.forEach(ct => {
|
|
70
|
+
citationsHTML += `<p>${ct}</p>`
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// We create a standard footnote container DOM node,
|
|
74
|
+
// add the citations into it, and parse it back.
|
|
75
|
+
const fnNode = fnSchema.nodeFromJSON({type: "footnotecontainer"})
|
|
76
|
+
const serializer = DOMSerializer.fromSchema(fnSchema)
|
|
77
|
+
const dom = serializer.serializeNode(fnNode)
|
|
78
|
+
dom.innerHTML = citationsHTML
|
|
79
|
+
this.pmCits = DOMParser.fromSchema(fnSchema)
|
|
80
|
+
.parse(dom, {topNode: fnNode})
|
|
81
|
+
.toJSON().content
|
|
82
|
+
} else {
|
|
83
|
+
this.pmCits = []
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Now we do the same for the bibliography.
|
|
87
|
+
const cslBib = this.citFm.bibliography
|
|
88
|
+
if (cslBib && cslBib[1].length > 0) {
|
|
89
|
+
const bibNode = cslBibSchema.nodeFromJSON({type: "cslbib"})
|
|
90
|
+
const serializer = DOMSerializer.fromSchema(cslBibSchema)
|
|
91
|
+
const dom = serializer.serializeNode(bibNode)
|
|
92
|
+
dom.innerHTML = cslBib[1].join("")
|
|
93
|
+
this.pmBib = DOMParser.fromSchema(cslBibSchema)
|
|
94
|
+
.parse(dom, {topNode: bibNode})
|
|
95
|
+
.toJSON()
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|