@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,156 @@
|
|
|
1
|
+
import download from "downloadjs"
|
|
2
|
+
|
|
3
|
+
import {shortFileTitle} from "../../common/index.js"
|
|
4
|
+
|
|
5
|
+
import {fixTables, removeHidden, textContent} from "../tools/doc_content.js"
|
|
6
|
+
import {createSlug} from "../tools/file.js"
|
|
7
|
+
import {XmlZip} from "../tools/xml_zip.js"
|
|
8
|
+
|
|
9
|
+
import {ODTExporterCitations} from "./citations.js"
|
|
10
|
+
import {ODTExporterFootnotes} from "./footnotes.js"
|
|
11
|
+
import {ODTExporterImages} from "./images.js"
|
|
12
|
+
import {ODTExporterMath} from "./math.js"
|
|
13
|
+
import {ODTExporterMetadata} from "./metadata.js"
|
|
14
|
+
import {ODTExporterRender} from "./render.js"
|
|
15
|
+
import {ODTExporterRichtext} from "./richtext.js"
|
|
16
|
+
import {ODTExporterStyles} from "./styles.js"
|
|
17
|
+
import {ODTExporterTracks} from "./track.js"
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
Exporter to Open Document Text (LibreOffice)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
TODO:
|
|
25
|
+
* - Export tracked changes of block changes and inline format changes
|
|
26
|
+
* (this feature is lacking in ODT files created with LibreOffice 7.6.7.2)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export class ODTExporter {
|
|
30
|
+
constructor(doc, templateUrl, bibDB, imageDB, csl) {
|
|
31
|
+
this.doc = doc
|
|
32
|
+
this.templateUrl = templateUrl
|
|
33
|
+
this.bibDB = bibDB
|
|
34
|
+
this.imageDB = imageDB
|
|
35
|
+
this.csl = csl
|
|
36
|
+
|
|
37
|
+
this.pmCits = false
|
|
38
|
+
this.docContent = fixTables(removeHidden(this.doc.content))
|
|
39
|
+
this.docTitle = shortFileTitle(this.doc.title, this.doc.path)
|
|
40
|
+
this.mimeType = "application/vnd.oasis.opendocument.text"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
init() {
|
|
44
|
+
const xml = new XmlZip(this.templateUrl, this.mimeType)
|
|
45
|
+
const styles = new ODTExporterStyles(xml)
|
|
46
|
+
const math = new ODTExporterMath(xml)
|
|
47
|
+
const tracks = new ODTExporterTracks(xml)
|
|
48
|
+
|
|
49
|
+
const metadata = new ODTExporterMetadata(
|
|
50
|
+
xml,
|
|
51
|
+
styles,
|
|
52
|
+
this.getBaseMetadata(),
|
|
53
|
+
this.csl
|
|
54
|
+
)
|
|
55
|
+
const citations = new ODTExporterCitations(
|
|
56
|
+
this.docContent,
|
|
57
|
+
this.doc.settings,
|
|
58
|
+
styles,
|
|
59
|
+
this.bibDB,
|
|
60
|
+
this.csl
|
|
61
|
+
)
|
|
62
|
+
const footnotes = new ODTExporterFootnotes(
|
|
63
|
+
this.docContent,
|
|
64
|
+
this.doc.settings,
|
|
65
|
+
xml,
|
|
66
|
+
citations,
|
|
67
|
+
styles,
|
|
68
|
+
this.bibDB,
|
|
69
|
+
this.imageDB,
|
|
70
|
+
this.csl
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const images = new ODTExporterImages(this.docContent, xml, this.imageDB)
|
|
74
|
+
|
|
75
|
+
const richtext = new ODTExporterRichtext(
|
|
76
|
+
this.doc.comments,
|
|
77
|
+
this.doc.settings,
|
|
78
|
+
styles,
|
|
79
|
+
tracks,
|
|
80
|
+
footnotes,
|
|
81
|
+
citations,
|
|
82
|
+
math,
|
|
83
|
+
images
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
const render = new ODTExporterRender(xml)
|
|
87
|
+
return xml
|
|
88
|
+
.init()
|
|
89
|
+
.then(() => styles.init())
|
|
90
|
+
.then(() => tracks.init())
|
|
91
|
+
.then(() => math.init())
|
|
92
|
+
.then(() => metadata.init())
|
|
93
|
+
.then(() => citations.init())
|
|
94
|
+
.then(() => render.init())
|
|
95
|
+
.then(() => images.init())
|
|
96
|
+
.then(() => footnotes.init())
|
|
97
|
+
.then(() => {
|
|
98
|
+
const pmBib = footnotes.pmBib || citations.pmBib
|
|
99
|
+
render.render(
|
|
100
|
+
this.docContent,
|
|
101
|
+
pmBib,
|
|
102
|
+
this.doc.settings,
|
|
103
|
+
richtext,
|
|
104
|
+
citations
|
|
105
|
+
)
|
|
106
|
+
return xml.prepareBlob()
|
|
107
|
+
})
|
|
108
|
+
.then(blob => this.download(blob))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getBaseMetadata() {
|
|
112
|
+
const contributors = this.docContent.content.reduce(
|
|
113
|
+
(contributors, part) => {
|
|
114
|
+
if (
|
|
115
|
+
part.type === "contributors_part" &&
|
|
116
|
+
part.attrs.metadata &&
|
|
117
|
+
part.content
|
|
118
|
+
) {
|
|
119
|
+
return contributors.concat(
|
|
120
|
+
part.content.map(node => ({
|
|
121
|
+
...node.attrs,
|
|
122
|
+
role: part.attrs.metadata
|
|
123
|
+
}))
|
|
124
|
+
)
|
|
125
|
+
} else {
|
|
126
|
+
return contributors
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
[]
|
|
130
|
+
)
|
|
131
|
+
return {
|
|
132
|
+
authors: contributors.filter(c => c.role === "authors"),
|
|
133
|
+
contributors,
|
|
134
|
+
keywords: this.docContent.content.reduce((keywords, part) => {
|
|
135
|
+
if (
|
|
136
|
+
part.type === "tags_part" &&
|
|
137
|
+
part.attrs.metadata === "keywords" &&
|
|
138
|
+
part.content
|
|
139
|
+
) {
|
|
140
|
+
return keywords.concat(
|
|
141
|
+
part.content.map(keywordNode => keywordNode.attrs.tag)
|
|
142
|
+
)
|
|
143
|
+
} else {
|
|
144
|
+
return keywords
|
|
145
|
+
}
|
|
146
|
+
}, []),
|
|
147
|
+
title: textContent(this.docContent.content[0]),
|
|
148
|
+
language: this.doc.settings.language,
|
|
149
|
+
citationStyle: this.doc.settings.citationstyle
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
download(blob) {
|
|
154
|
+
return download(blob, createSlug(this.docTitle) + ".odt", this.mimeType)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class ODTExporterMath {
|
|
2
|
+
constructor(xml) {
|
|
3
|
+
this.xml = xml
|
|
4
|
+
this.objectCounter = 1
|
|
5
|
+
this.manifestXml = false
|
|
6
|
+
this.domParser = new DOMParser()
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
init() {
|
|
10
|
+
return this.xml
|
|
11
|
+
.getXml("META-INF/manifest.xml")
|
|
12
|
+
.then(manifestXml => {
|
|
13
|
+
this.manifestXml = manifestXml
|
|
14
|
+
this.checkObjectCounter()
|
|
15
|
+
return Promise.resolve()
|
|
16
|
+
})
|
|
17
|
+
.then(() => import("mathlive"))
|
|
18
|
+
.then(MathLive => (this.mathLive = MathLive))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
checkObjectCounter() {
|
|
22
|
+
const manifestEl = this.manifestXml.query("manifest:manifest")
|
|
23
|
+
const fileEntries = manifestEl.queryAll("manifest:file-entry")
|
|
24
|
+
|
|
25
|
+
fileEntries.forEach(fileEntry => {
|
|
26
|
+
const fullPath = fileEntry.getAttribute("manifest:full-path")
|
|
27
|
+
const dir = fullPath.split("/")[0]
|
|
28
|
+
const dirParts = dir.split(" ")
|
|
29
|
+
if (dirParts.length === 2 && dirParts[0] === "Object") {
|
|
30
|
+
const objectNumber = Number.parseInt(dirParts[1])
|
|
31
|
+
if (objectNumber >= this.objectCounter) {
|
|
32
|
+
this.objectCounter = objectNumber + 1
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
latexToMathML(latex) {
|
|
39
|
+
return this.mathLive.convertLatexToMathMl(latex)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
addMath(latex) {
|
|
43
|
+
const objectNumber = this.objectCounter++
|
|
44
|
+
this.xml.addExtraFile(
|
|
45
|
+
`Object ${objectNumber}/content.xml`,
|
|
46
|
+
`<math xmlns="http://www.w3.org/1998/Math/MathML">${this.latexToMathML(
|
|
47
|
+
latex
|
|
48
|
+
)}</math>`
|
|
49
|
+
)
|
|
50
|
+
const manifestEl = this.manifestXml.query("manifest:manifest")
|
|
51
|
+
const stringOne = `<manifest:file-entry manifest:full-path="Object ${objectNumber}/content.xml" manifest:media-type="text/xml"/>`
|
|
52
|
+
manifestEl.appendXML(stringOne)
|
|
53
|
+
const stringTwo = `<manifest:file-entry manifest:full-path="Object ${objectNumber}/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.formula"/>`
|
|
54
|
+
manifestEl.appendXML(stringTwo)
|
|
55
|
+
return objectNumber
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import {escapeText} from "../../common/index.js"
|
|
2
|
+
|
|
3
|
+
export class ODTExporterMetadata {
|
|
4
|
+
constructor(xml, styles, metadata, csl = null) {
|
|
5
|
+
this.xml = xml
|
|
6
|
+
this.styles = styles
|
|
7
|
+
this.metadata = metadata
|
|
8
|
+
this.csl = csl
|
|
9
|
+
this.metaXml = false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
init() {
|
|
13
|
+
return this.xml.getXml("meta.xml").then(metaXml => {
|
|
14
|
+
this.metaXml = metaXml
|
|
15
|
+
this.addMetadata()
|
|
16
|
+
this.addContributorMetadata()
|
|
17
|
+
return this.addZoteroPrefs()
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async hasBibliography() {
|
|
22
|
+
if (!this.csl || !this.metadata.citationStyle) {
|
|
23
|
+
return "0"
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const style = await this.csl.getStyle(this.metadata.citationStyle)
|
|
27
|
+
// Check if the style has a bibliography section
|
|
28
|
+
const hasBib = style.children.some(
|
|
29
|
+
section => section.name === "bibliography"
|
|
30
|
+
)
|
|
31
|
+
return hasBib ? "1" : "0"
|
|
32
|
+
} catch (_error) {
|
|
33
|
+
return "0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addMetadata() {
|
|
38
|
+
const metaEl = this.metaXml.query("office:meta")
|
|
39
|
+
|
|
40
|
+
// Title
|
|
41
|
+
const titleEl = this.metaXml.query("dc:title")
|
|
42
|
+
if (titleEl) {
|
|
43
|
+
titleEl.innerXML = escapeText(this.metadata.title)
|
|
44
|
+
} else {
|
|
45
|
+
metaEl.appendXML(
|
|
46
|
+
`<dc:title>${escapeText(this.metadata.title)}</dc:title>`
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Authors
|
|
51
|
+
const authors = this.metadata.authors.map(author => {
|
|
52
|
+
const nameParts = []
|
|
53
|
+
if (author.firstname) {
|
|
54
|
+
nameParts.push(author.firstname)
|
|
55
|
+
}
|
|
56
|
+
if (author.lastname) {
|
|
57
|
+
nameParts.push(author.lastname)
|
|
58
|
+
}
|
|
59
|
+
if (!nameParts.length && author.institution) {
|
|
60
|
+
// We have an institution but no names. Use institution as name.
|
|
61
|
+
nameParts.push(author.institution)
|
|
62
|
+
}
|
|
63
|
+
return nameParts.join(" ")
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const initialAuthor = authors.length
|
|
67
|
+
? escapeText(authors[0])
|
|
68
|
+
: gettext("Unknown")
|
|
69
|
+
// TODO: We likely want to differentiate between first and last author.
|
|
70
|
+
const lastAuthor = initialAuthor
|
|
71
|
+
|
|
72
|
+
const lastAuthorEl = this.metaXml.query("dc:creator")
|
|
73
|
+
if (lastAuthorEl) {
|
|
74
|
+
lastAuthorEl.innerXML = lastAuthor
|
|
75
|
+
} else {
|
|
76
|
+
metaEl.appendXML(`<dc:creator>${lastAuthor}</dc:creator>`)
|
|
77
|
+
}
|
|
78
|
+
const initialAuthorEl = this.metaXml.query("meta:initial-creator")
|
|
79
|
+
if (initialAuthorEl) {
|
|
80
|
+
initialAuthorEl.innerXML = initialAuthor
|
|
81
|
+
} else {
|
|
82
|
+
metaEl.appendXML(
|
|
83
|
+
`<meta:initial-creator>${initialAuthor}</meta:initial-creator>`
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Keywords
|
|
88
|
+
// Remove all existing keywords
|
|
89
|
+
const keywordEls = this.metaXml.queryAll("meta:keywords")
|
|
90
|
+
keywordEls.forEach(keywordEl =>
|
|
91
|
+
keywordEl.parentElement.removeChild(keywordEl)
|
|
92
|
+
)
|
|
93
|
+
// Add new keywords
|
|
94
|
+
const keywords = this.metadata.keywords
|
|
95
|
+
keywords.forEach(keyword =>
|
|
96
|
+
metaEl.appendXML(
|
|
97
|
+
`<meta:keyword>${escapeText(keyword)}</meta:keyword>`
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
// language
|
|
102
|
+
// LibreOffice seems to ignore the value set in metadata and instead uses
|
|
103
|
+
// the one set in default styles. So we set both.
|
|
104
|
+
this.styles.setLanguage(this.metadata.language)
|
|
105
|
+
const languageEl = this.metaXml.query("dc:language")
|
|
106
|
+
if (languageEl) {
|
|
107
|
+
languageEl.innerXML = this.metadata.language
|
|
108
|
+
} else {
|
|
109
|
+
metaEl.appendXML(
|
|
110
|
+
`<dc:language>${this.metadata.language}</dc:language>`
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
// time
|
|
114
|
+
const date = new Date()
|
|
115
|
+
const dateString = date.toISOString().split(".")[0]
|
|
116
|
+
const createdEl = metaEl.query("meta:creation-date")
|
|
117
|
+
createdEl.innerXML = dateString
|
|
118
|
+
const dateEl = this.metaXml.query("dc:date")
|
|
119
|
+
if (dateEl) {
|
|
120
|
+
dateEl.innerXML = `${dateString}.000000000`
|
|
121
|
+
} else {
|
|
122
|
+
metaEl.appendXML(`<dc:date>${dateString}.000000000</dc:date>`)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async addZoteroPrefs() {
|
|
127
|
+
// Add citation style property to meta.xml
|
|
128
|
+
if (!this.metadata.citationStyle) {
|
|
129
|
+
return Promise.resolve()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const metaEl = this.metaXml.query("office:meta")
|
|
133
|
+
|
|
134
|
+
// Remove any existing ZOTERO_PREF_ properties
|
|
135
|
+
const existingZoteroProps = this.metaXml
|
|
136
|
+
.queryAll("meta:user-defined")
|
|
137
|
+
.filter(
|
|
138
|
+
prop =>
|
|
139
|
+
prop.getAttribute("meta:name") &&
|
|
140
|
+
prop.getAttribute("meta:name").startsWith("ZOTERO_PREF_")
|
|
141
|
+
)
|
|
142
|
+
existingZoteroProps.forEach(prop =>
|
|
143
|
+
prop.parentElement.removeChild(prop)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
// Determine if the citation style has a bibliography
|
|
147
|
+
const hasBib = await this.hasBibliography()
|
|
148
|
+
|
|
149
|
+
// Create the data content
|
|
150
|
+
const citationStyleUrl = `http://www.zotero.org/styles/${escapeText(this.metadata.citationStyle)}`
|
|
151
|
+
const dataContent = escapeText(
|
|
152
|
+
`<data data-version="3" zotero-version="8.0.2"><session id=""/><style id="${citationStyleUrl}" locale="${escapeText(this.metadata.language || "en-US")}" hasBibliography="${hasBib}" bibliographyStyleHasBeenSet="1"/><prefs><pref name="fieldType" value="ReferenceMark"/><pref name="automaticJournalAbbreviations" value="true"/></prefs></data>`
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
// Split content into chunks of 378 characters (ODT limit)
|
|
156
|
+
const chunkSize = 378
|
|
157
|
+
const chunks = []
|
|
158
|
+
for (let i = 0; i < dataContent.length; i += chunkSize) {
|
|
159
|
+
chunks.push(dataContent.substring(i, i + chunkSize))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Create meta:user-defined elements for each chunk
|
|
163
|
+
chunks.forEach((chunk, index) => {
|
|
164
|
+
const propName = `ZOTERO_PREF_${index + 1}`
|
|
165
|
+
const userDefinedEl = `<meta:user-defined meta:name="${propName}">${chunk}</meta:user-defined>`
|
|
166
|
+
metaEl.appendXML(userDefinedEl)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return Promise.resolve()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
addContributorMetadata() {
|
|
173
|
+
if (!this.metadata.contributors || !this.metadata.contributors.length) {
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const metaEl = this.metaXml.query("office:meta")
|
|
178
|
+
|
|
179
|
+
// Remove any existing fidus_contributor_ properties
|
|
180
|
+
const existingContributorProps = this.metaXml
|
|
181
|
+
.queryAll("meta:user-defined")
|
|
182
|
+
.filter(
|
|
183
|
+
prop =>
|
|
184
|
+
prop.getAttribute("meta:name") &&
|
|
185
|
+
prop
|
|
186
|
+
.getAttribute("meta:name")
|
|
187
|
+
.startsWith("fidus_contributor_")
|
|
188
|
+
)
|
|
189
|
+
existingContributorProps.forEach(prop =>
|
|
190
|
+
prop.parentElement.removeChild(prop)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
const contributors = this.metadata.contributors
|
|
194
|
+
|
|
195
|
+
// Add contributor count
|
|
196
|
+
metaEl.appendXML(
|
|
197
|
+
`<meta:user-defined meta:name="fidus_contributor_count" meta:value-type="float">${contributors.length}</meta:user-defined>`
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
// Add metadata for each contributor
|
|
201
|
+
contributors.forEach((contributor, index) => {
|
|
202
|
+
const num = index + 1
|
|
203
|
+
const nameParts = []
|
|
204
|
+
if (contributor.firstname) {
|
|
205
|
+
nameParts.push(contributor.firstname)
|
|
206
|
+
}
|
|
207
|
+
if (contributor.lastname) {
|
|
208
|
+
nameParts.push(contributor.lastname)
|
|
209
|
+
}
|
|
210
|
+
const fullName =
|
|
211
|
+
nameParts.join(" ") || contributor.institution || ""
|
|
212
|
+
|
|
213
|
+
const fields = [
|
|
214
|
+
{
|
|
215
|
+
name: `fidus_contributor_${num}_role`,
|
|
216
|
+
value: contributor.role || ""
|
|
217
|
+
},
|
|
218
|
+
{name: `fidus_contributor_${num}_name`, value: fullName},
|
|
219
|
+
{
|
|
220
|
+
name: `fidus_contributor_${num}_firstname`,
|
|
221
|
+
value: contributor.firstname || ""
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: `fidus_contributor_${num}_lastname`,
|
|
225
|
+
value: contributor.lastname || ""
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: `fidus_contributor_${num}_institution`,
|
|
229
|
+
value: contributor.institution || ""
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: `fidus_contributor_${num}_email`,
|
|
233
|
+
value: contributor.email || ""
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: `fidus_contributor_${num}_id_type`,
|
|
237
|
+
value: contributor.id_type || ""
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: `fidus_contributor_${num}_id_value`,
|
|
241
|
+
value: contributor.id_value || ""
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
fields.forEach(field => {
|
|
246
|
+
const userDefinedEl = `<meta:user-defined meta:name="${field.name}">${escapeText(field.value)}</meta:user-defined>`
|
|
247
|
+
metaEl.appendXML(userDefinedEl)
|
|
248
|
+
})
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
}
|