@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.
Files changed (110) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +16 -0
  3. package/jest.config.js +23 -0
  4. package/package.json +59 -0
  5. package/schema.json +1 -0
  6. package/scripts/export-schema.js +16 -0
  7. package/src/bibliography/common.js +92 -0
  8. package/src/bibliography/csl_bib.js +139 -0
  9. package/src/citations/citeproc_sys.js +42 -0
  10. package/src/citations/format.js +194 -0
  11. package/src/common/blob.js +10 -0
  12. package/src/common/file.js +25 -0
  13. package/src/common/index.js +12 -0
  14. package/src/common/network.js +79 -0
  15. package/src/common/text.js +44 -0
  16. package/src/editor/e2ee/encryptor.js +228 -0
  17. package/src/exporter/docx/citations.js +177 -0
  18. package/src/exporter/docx/comments.js +165 -0
  19. package/src/exporter/docx/footnotes.js +240 -0
  20. package/src/exporter/docx/images.js +101 -0
  21. package/src/exporter/docx/index.js +185 -0
  22. package/src/exporter/docx/lists.js +260 -0
  23. package/src/exporter/docx/math.js +46 -0
  24. package/src/exporter/docx/metadata.js +289 -0
  25. package/src/exporter/docx/rels.js +193 -0
  26. package/src/exporter/docx/render.js +941 -0
  27. package/src/exporter/docx/richtext.js +1182 -0
  28. package/src/exporter/docx/tables.js +112 -0
  29. package/src/exporter/docx/tools.js +50 -0
  30. package/src/exporter/epub/index.js +142 -0
  31. package/src/exporter/epub/templates.js +140 -0
  32. package/src/exporter/epub/tools.js +96 -0
  33. package/src/exporter/html/citations.js +121 -0
  34. package/src/exporter/html/convert.js +813 -0
  35. package/src/exporter/html/index.js +192 -0
  36. package/src/exporter/html/templates.js +34 -0
  37. package/src/exporter/html/tools.js +50 -0
  38. package/src/exporter/jats/bibliography.js +183 -0
  39. package/src/exporter/jats/citations.js +109 -0
  40. package/src/exporter/jats/convert.js +871 -0
  41. package/src/exporter/jats/index.js +92 -0
  42. package/src/exporter/jats/templates.js +35 -0
  43. package/src/exporter/jats/text.js +72 -0
  44. package/src/exporter/latex/convert.js +934 -0
  45. package/src/exporter/latex/escape_latex.js +21 -0
  46. package/src/exporter/latex/index.js +74 -0
  47. package/src/exporter/latex/readme.js +22 -0
  48. package/src/exporter/native/shrink.js +132 -0
  49. package/src/exporter/odt/citations.js +101 -0
  50. package/src/exporter/odt/footnotes.js +147 -0
  51. package/src/exporter/odt/images.js +115 -0
  52. package/src/exporter/odt/index.js +156 -0
  53. package/src/exporter/odt/math.js +57 -0
  54. package/src/exporter/odt/metadata.js +251 -0
  55. package/src/exporter/odt/render.js +806 -0
  56. package/src/exporter/odt/richtext.js +865 -0
  57. package/src/exporter/odt/styles.js +387 -0
  58. package/src/exporter/odt/track.js +68 -0
  59. package/src/exporter/pandoc/citations.js +98 -0
  60. package/src/exporter/pandoc/convert.js +1017 -0
  61. package/src/exporter/pandoc/index.js +92 -0
  62. package/src/exporter/pandoc/readme.js +8 -0
  63. package/src/exporter/pandoc/tools.js +51 -0
  64. package/src/exporter/print/index.js +177 -0
  65. package/src/exporter/tools/doc_content.js +144 -0
  66. package/src/exporter/tools/file.js +9 -0
  67. package/src/exporter/tools/json.js +73 -0
  68. package/src/exporter/tools/svg.js +29 -0
  69. package/src/exporter/tools/xml.js +531 -0
  70. package/src/exporter/tools/xml_zip.js +95 -0
  71. package/src/exporter/tools/zip.js +90 -0
  72. package/src/exporter/tools/zotero_csl.js +93 -0
  73. package/src/importer/citations.js +129 -0
  74. package/src/importer/docx/citations.js +123 -0
  75. package/src/importer/docx/convert.js +1427 -0
  76. package/src/importer/docx/helpers.js +9 -0
  77. package/src/importer/docx/omml2mathml.js +1448 -0
  78. package/src/importer/docx/parse.js +735 -0
  79. package/src/importer/native/get_images.js +76 -0
  80. package/src/importer/native/update.js +29 -0
  81. package/src/importer/odt/citations.js +87 -0
  82. package/src/importer/odt/convert.js +1855 -0
  83. package/src/importer/pandoc/convert.js +884 -0
  84. package/src/importer/pandoc/helpers.js +84 -0
  85. package/src/importer/zip_analyzer.js +102 -0
  86. package/src/index.js +1 -0
  87. package/src/mathlive/opf_includes.js +24 -0
  88. package/src/schema/common/annotate.js +76 -0
  89. package/src/schema/common/base.js +118 -0
  90. package/src/schema/common/citation.js +62 -0
  91. package/src/schema/common/equation.js +31 -0
  92. package/src/schema/common/figure.js +190 -0
  93. package/src/schema/common/heading.js +43 -0
  94. package/src/schema/common/index.js +40 -0
  95. package/src/schema/common/list.js +95 -0
  96. package/src/schema/common/reference.js +100 -0
  97. package/src/schema/common/table.js +103 -0
  98. package/src/schema/common/track.js +190 -0
  99. package/src/schema/const.js +58 -0
  100. package/src/schema/convert.js +1272 -0
  101. package/src/schema/document/content.js +187 -0
  102. package/src/schema/document/index.js +117 -0
  103. package/src/schema/document/structure.js +452 -0
  104. package/src/schema/export.js +21 -0
  105. package/src/schema/footnotes.js +126 -0
  106. package/src/schema/footnotes_convert.js +31 -0
  107. package/src/schema/i18n.js +595 -0
  108. package/src/schema/index.js +5 -0
  109. package/src/schema/mini_json.js +61 -0
  110. package/src/schema/text.js +22 -0
@@ -0,0 +1,43 @@
1
+ import {addTracks, parseTracks} from "./track.js"
2
+
3
+ export const randomHeadingId = () => {
4
+ return `H${Math.round(Math.random() * 10000000) + 1}`
5
+ }
6
+
7
+ const createHeading = level => ({
8
+ group: "block heading",
9
+ content: "inline*",
10
+ marks: "_",
11
+ defining: true,
12
+ attrs: {
13
+ id: {
14
+ default: false
15
+ },
16
+ track: {
17
+ default: []
18
+ }
19
+ },
20
+ parseDOM: [
21
+ {
22
+ tag: `h${level}`,
23
+ getAttrs(dom) {
24
+ return {
25
+ id: dom.id,
26
+ track: parseTracks(dom.dataset.track)
27
+ }
28
+ }
29
+ }
30
+ ],
31
+ toDOM(node) {
32
+ const attrs = {id: node.attrs.id}
33
+ addTracks(node, attrs)
34
+ return [`h${level}`, attrs, 0]
35
+ }
36
+ })
37
+
38
+ export const heading1 = createHeading(1)
39
+ export const heading2 = createHeading(2)
40
+ export const heading3 = createHeading(3)
41
+ export const heading4 = createHeading(4)
42
+ export const heading5 = createHeading(5)
43
+ export const heading6 = createHeading(6)
@@ -0,0 +1,40 @@
1
+ export {annotation_tag, comment, randomCommentId} from "./annotate.js"
2
+ export {
3
+ paragraph,
4
+ blockquote,
5
+ horizontal_rule,
6
+ underline,
7
+ sup,
8
+ sub,
9
+ code
10
+ } from "./base.js"
11
+ export {citation} from "./citation.js"
12
+ export {equation} from "./equation.js"
13
+ export {
14
+ figure,
15
+ image,
16
+ figure_equation,
17
+ figure_caption,
18
+ randomFigureId
19
+ } from "./figure.js"
20
+ export {
21
+ heading1,
22
+ heading2,
23
+ heading3,
24
+ heading4,
25
+ heading5,
26
+ heading6,
27
+ randomHeadingId
28
+ } from "./heading.js"
29
+ export {ordered_list, bullet_list, list_item, randomListId} from "./list.js"
30
+ export {cross_reference, anchor, link, randomAnchorId} from "./reference.js"
31
+ export {
32
+ table,
33
+ table_caption,
34
+ table_body,
35
+ table_row,
36
+ table_cell,
37
+ table_header,
38
+ randomTableId
39
+ } from "./table.js"
40
+ export {deletion, insertion, format_change, parseTracks} from "./track.js"
@@ -0,0 +1,95 @@
1
+ import {addTracks, parseTracks} from "./track.js"
2
+
3
+ // :: NodeSpec
4
+ // An ordered list [node spec](#model.NodeSpec). Has a single
5
+ // attribute, `order`, which determines the number at which the list
6
+ // starts counting, and defaults to 1. Represented as an `<ol>`
7
+ // element.
8
+ export const ordered_list = {
9
+ group: "block",
10
+ content: "list_item+",
11
+ attrs: {
12
+ id: {default: false},
13
+ order: {default: 1},
14
+ track: {default: []}
15
+ },
16
+ parseDOM: [
17
+ {
18
+ tag: "ol",
19
+ getAttrs(dom) {
20
+ return {
21
+ id: dom.id,
22
+ order: dom.hasAttribute("start")
23
+ ? +dom.getAttribute("start")
24
+ : 1,
25
+ track: parseTracks(dom.dataset.track)
26
+ }
27
+ }
28
+ }
29
+ ],
30
+ toDOM(node) {
31
+ const attrs = {id: node.attrs.id}
32
+ if (node.attrs.order !== 1) {
33
+ attrs.start = node.attrs.order
34
+ }
35
+ addTracks(node, attrs)
36
+ return ["ol", attrs, 0]
37
+ }
38
+ }
39
+
40
+ export function randomListId() {
41
+ return "L" + Math.round(Math.random() * 10000000) + 1
42
+ }
43
+
44
+ // :: NodeSpec
45
+ // A bullet list node spec, represented in the DOM as `<ul>`.
46
+ export const bullet_list = {
47
+ group: "block",
48
+ content: "list_item+",
49
+ attrs: {
50
+ id: {default: false},
51
+ track: {default: []}
52
+ },
53
+ parseDOM: [
54
+ {
55
+ tag: "ul",
56
+ getAttrs(dom) {
57
+ return {
58
+ id: dom.id,
59
+ track: parseTracks(dom.dataset.track)
60
+ }
61
+ }
62
+ }
63
+ ],
64
+ toDOM(node) {
65
+ const attrs = {id: node.attrs.id}
66
+ addTracks(node, attrs)
67
+ return ["ul", attrs, 0]
68
+ }
69
+ }
70
+
71
+ // :: NodeSpec
72
+ // A list item (`<li>`) spec.
73
+ export const list_item = {
74
+ content: "block+",
75
+ marks: "annotation",
76
+ attrs: {
77
+ track: {default: []}
78
+ },
79
+ parseDOM: [
80
+ {
81
+ tag: "li",
82
+ getAttrs(dom) {
83
+ return {
84
+ track: parseTracks(dom.dataset.track)
85
+ }
86
+ }
87
+ }
88
+ ],
89
+ toDOM(node) {
90
+ const attrs = {}
91
+ addTracks(node, attrs)
92
+ return ["li", attrs, 0]
93
+ },
94
+ defining: true
95
+ }
@@ -0,0 +1,100 @@
1
+ export const cross_reference = {
2
+ inline: true,
3
+ group: "inline",
4
+ attrs: {
5
+ id: {
6
+ default: false
7
+ },
8
+ title: {
9
+ default: null // title === null means that the target is gone
10
+ }
11
+ },
12
+ parseDOM: [
13
+ {
14
+ tag: "span.cross-reference[data-id][data-title]",
15
+ getAttrs(dom) {
16
+ return {
17
+ id: dom.dataset.id,
18
+ title: dom.dataset.title
19
+ }
20
+ }
21
+ }
22
+ ],
23
+ toDOM(node) {
24
+ return [
25
+ "span",
26
+ {
27
+ class: `cross-reference${node.attrs.title ? "" : " missing-target"}`,
28
+ "data-id": node.attrs.id,
29
+ "data-title": node.attrs.title
30
+ },
31
+ node.attrs.title ? node.attrs.title : gettext("Missing Target")
32
+ ]
33
+ }
34
+ }
35
+
36
+ export const link = {
37
+ attrs: {
38
+ href: {},
39
+ title: {
40
+ default: ""
41
+ }
42
+ },
43
+ inclusive: false,
44
+ parseDOM: [
45
+ {
46
+ tag: "a[href]",
47
+ getAttrs(dom) {
48
+ return {
49
+ href: dom.getAttribute("href"),
50
+ title: dom.getAttribute("title")
51
+ }
52
+ }
53
+ }
54
+ ],
55
+ toDOM(node) {
56
+ const {href, title} = node.attrs
57
+ const attrs =
58
+ title || href.charAt(0) !== "#"
59
+ ? {href, title}
60
+ : {
61
+ href,
62
+ title: gettext("Missing target"),
63
+ class: "missing-target"
64
+ }
65
+ return ["a", attrs, 0]
66
+ }
67
+ }
68
+
69
+ export const randomAnchorId = () => {
70
+ return `A${Math.round(Math.random() * 10000000) + 1}`
71
+ }
72
+
73
+ export const anchor = {
74
+ attrs: {
75
+ id: {
76
+ default: false
77
+ }
78
+ },
79
+ inclusive: false,
80
+ group: "annotation",
81
+ parseDOM: [
82
+ {
83
+ tag: "span.anchor[data-id]",
84
+ getAttrs(dom) {
85
+ return {
86
+ id: dom.dataset.id
87
+ }
88
+ }
89
+ }
90
+ ],
91
+ toDOM(node) {
92
+ return [
93
+ "span",
94
+ {
95
+ class: "anchor",
96
+ "data-id": node.attrs.id
97
+ }
98
+ ]
99
+ }
100
+ }
@@ -0,0 +1,103 @@
1
+ import {tableNodes} from "prosemirror-tables"
2
+
3
+ import {parseTracks} from "./track.js"
4
+
5
+ export const table = {
6
+ inline: false,
7
+ group: "block",
8
+ tableRole: "table",
9
+ attrs: {
10
+ id: {default: false},
11
+ track: {default: []},
12
+ width: {default: "100"},
13
+ aligned: {default: "center"},
14
+ layout: {default: "fixed"},
15
+ category: {default: "none"},
16
+ caption: {default: false}
17
+ },
18
+ content: "table_caption table_body",
19
+ parseDOM: [
20
+ {
21
+ tag: "table",
22
+ getAttrs(dom) {
23
+ const track = parseTracks(dom.dataset.track),
24
+ width = dom.dataset.width,
25
+ aligned = width === "100" ? "center" : dom.dataset.aligned,
26
+ layout = dom.dataset.layout,
27
+ id = dom.id || dom.dataset.id
28
+ return {
29
+ track,
30
+ width,
31
+ aligned,
32
+ layout,
33
+ id,
34
+ category: dom.dataset.category,
35
+ caption: !!dom.dataset.captionHidden
36
+ }
37
+ }
38
+ }
39
+ ],
40
+ toDOM(node) {
41
+ const attrs = {
42
+ id: node.attrs.id,
43
+ class: `table-${node.attrs.width} table-${node.attrs.aligned} table-${node.attrs.layout}`,
44
+ "data-width": node.attrs.width,
45
+ "data-aligned": node.attrs.aligned,
46
+ "data-layout": node.attrs.layout,
47
+ "data-category": node.attrs.category
48
+ }
49
+ if (node.attrs.track.length) {
50
+ attrs["data-track"] = JSON.stringify(node.attrs.track)
51
+ }
52
+ if (!node.attrs.caption) {
53
+ attrs["data-caption-hidden"] = true
54
+ }
55
+ return ["table", attrs, 0]
56
+ }
57
+ }
58
+
59
+ export const table_caption = {
60
+ content: "inline*",
61
+ parseDOM: [{tag: "caption span.text"}],
62
+ toDOM() {
63
+ return [
64
+ "caption",
65
+ ["span", {class: "label"}],
66
+ ["span", {class: "text"}, 0]
67
+ ]
68
+ }
69
+ }
70
+
71
+ const origTableNodes = tableNodes({
72
+ cellContent: "block+"
73
+ })
74
+
75
+ export const table_body = Object.assign({}, origTableNodes["table"], {
76
+ parseDOM: [{tag: "tbody"}],
77
+ toDOM() {
78
+ return ["tbody", 0]
79
+ }
80
+ })
81
+
82
+ export const table_row = {
83
+ content: "(table_cell | table_header)+",
84
+ tableRole: "row",
85
+ parseDOM: [{tag: "tr"}],
86
+ toDOM() {
87
+ return ["tr", 0]
88
+ }
89
+ }
90
+
91
+ export const table_header = Object.assign(
92
+ {marks: "annotation"},
93
+ origTableNodes["table_header"]
94
+ )
95
+
96
+ export const table_cell = Object.assign(
97
+ {marks: "annotation"},
98
+ origTableNodes["table_cell"]
99
+ )
100
+
101
+ export function randomTableId() {
102
+ return "T" + Math.round(Math.random() * 10000000) + 1
103
+ }
@@ -0,0 +1,190 @@
1
+ export function parseTracks(str) {
2
+ if (!str) {
3
+ return []
4
+ }
5
+ let tracks
6
+ try {
7
+ tracks = JSON.parse(str)
8
+ } catch (_error) {
9
+ return []
10
+ }
11
+ if (!Array.isArray(tracks)) {
12
+ return []
13
+ }
14
+ return tracks.filter(
15
+ (
16
+ track // ensure required fields are present
17
+ ) =>
18
+ track.hasOwnProperty("user") &&
19
+ track.hasOwnProperty("username") &&
20
+ track.hasOwnProperty("date")
21
+ )
22
+ }
23
+
24
+ export function addTracks(node, attrs) {
25
+ if (node.attrs.track?.length) {
26
+ attrs["data-track"] = JSON.stringify(node.attrs.track)
27
+ }
28
+ }
29
+
30
+ export const deletion = {
31
+ attrs: {
32
+ user: {
33
+ default: 0
34
+ },
35
+ username: {
36
+ default: ""
37
+ },
38
+ date: {
39
+ default: 0
40
+ }
41
+ },
42
+ inclusive: false,
43
+ group: "track",
44
+ parseDOM: [
45
+ {
46
+ tag: "span.deletion",
47
+ getAttrs(dom) {
48
+ return {
49
+ user: Number.parseInt(dom.dataset.user),
50
+ username: dom.dataset.username,
51
+ date: Number.parseInt(dom.dataset.date)
52
+ }
53
+ }
54
+ }
55
+ ],
56
+ toDOM(node) {
57
+ return [
58
+ "span",
59
+ {
60
+ class: `deletion user-${node.attrs.user}`,
61
+ "data-user": node.attrs.user,
62
+ "data-username": node.attrs.username,
63
+ "data-date": node.attrs.date
64
+ }
65
+ ]
66
+ }
67
+ }
68
+
69
+ function parseFormatList(str) {
70
+ if (!str) {
71
+ return []
72
+ }
73
+ let formatList
74
+ try {
75
+ formatList = JSON.parse(str)
76
+ } catch (_error) {
77
+ return []
78
+ }
79
+ if (!Array.isArray(formatList)) {
80
+ return []
81
+ }
82
+ return formatList.filter(format => typeof format === "string") // ensure there are only strings in list
83
+ }
84
+
85
+ export const format_change = {
86
+ attrs: {
87
+ user: {
88
+ default: 0
89
+ },
90
+ username: {
91
+ default: ""
92
+ },
93
+ date: {
94
+ default: 0
95
+ },
96
+ before: {
97
+ default: []
98
+ },
99
+ after: {
100
+ default: []
101
+ }
102
+ },
103
+ inclusive: false,
104
+ group: "track",
105
+ parseDOM: [
106
+ {
107
+ tag: "span.format-change",
108
+ getAttrs(dom) {
109
+ return {
110
+ user: Number.parseInt(dom.dataset.user),
111
+ username: dom.dataset.username,
112
+ date: Number.parseInt(dom.dataset.date),
113
+ before: parseFormatList(dom.dataset.before),
114
+ after: parseFormatList(dom.dataset.after)
115
+ }
116
+ }
117
+ }
118
+ ],
119
+ toDOM(node) {
120
+ return [
121
+ "span",
122
+ {
123
+ class: `format-change user-${node.attrs.user}`,
124
+ "data-user": node.attrs.user,
125
+ "data-username": node.attrs.username,
126
+ "data-date": node.attrs.date,
127
+ "data-before": JSON.stringify(node.attrs.before),
128
+ "data-after": JSON.stringify(node.attrs.after)
129
+ }
130
+ ]
131
+ }
132
+ }
133
+
134
+ export const insertion = {
135
+ attrs: {
136
+ user: {
137
+ default: 0
138
+ },
139
+ username: {
140
+ default: ""
141
+ },
142
+ date: {
143
+ default: 0
144
+ },
145
+ approved: {
146
+ default: true
147
+ }
148
+ },
149
+ inclusive: false,
150
+ group: "track",
151
+ parseDOM: [
152
+ {
153
+ tag: "span.insertion",
154
+ getAttrs(dom) {
155
+ return {
156
+ user: Number.parseInt(dom.dataset.user),
157
+ username: dom.dataset.username,
158
+ date: Number.parseInt(dom.dataset.date),
159
+ inline: true,
160
+ approved: false
161
+ }
162
+ }
163
+ },
164
+ {
165
+ tag: "span.approved-insertion",
166
+ getAttrs(dom) {
167
+ return {
168
+ user: Number.parseInt(dom.dataset.user),
169
+ username: dom.dataset.username,
170
+ date: Number.parseInt(dom.dataset.date),
171
+ inline: true,
172
+ approved: true
173
+ }
174
+ }
175
+ }
176
+ ],
177
+ toDOM(node) {
178
+ return [
179
+ "span",
180
+ {
181
+ class: node.attrs.approved
182
+ ? "approved-insertion"
183
+ : `insertion user-${node.attrs.user}`,
184
+ "data-user": node.attrs.user,
185
+ "data-username": node.attrs.username,
186
+ "data-date": node.attrs.date
187
+ }
188
+ ]
189
+ }
190
+ }
@@ -0,0 +1,58 @@
1
+ export const LANGUAGES = [
2
+ ["af-ZA", gettext("Afrikaans"), "ltr"],
3
+ ["sq-AL", gettext("Albanian"), "ltr"],
4
+ ["ar", gettext("Arabic"), "rtl"],
5
+ ["ast", gettext("Asturian"), "ltr"],
6
+ ["be", gettext("Belarusian"), "ltr"],
7
+ ["br", gettext("Breton"), "ltr"],
8
+ ["bg", gettext("Bulgarian"), "ltr"],
9
+ ["ca", gettext("Catalan"), "ltr"],
10
+ ["ca-ES-Valencia", gettext("Catalan (Valencia)"), "ltr"],
11
+ ["zh-CN", gettext("Chinese (Simplified)"), "ltr"],
12
+ ["da", gettext("Danish"), "ltr"],
13
+ ["nl", gettext("Dutch"), "ltr"],
14
+ ["en-AU", gettext("English (Australia)"), "ltr"],
15
+ ["en-CA", gettext("English (Canada)"), "ltr"],
16
+ ["en-NZ", gettext("English (New Zealand)"), "ltr"],
17
+ ["en-ZA", gettext("English (South Africa)"), "ltr"],
18
+ ["en-GB", gettext("English (United Kingdom)"), "ltr"],
19
+ ["en-US", gettext("English (United States)"), "ltr"],
20
+ ["eo", gettext("Esperanto"), "ltr"],
21
+ ["fr", gettext("French"), "ltr"],
22
+ ["gl", gettext("Galician"), "ltr"],
23
+ ["de-DE", gettext("German (Germany)"), "ltr"],
24
+ ["de-AU", gettext("German (Austria)"), "ltr"],
25
+ ["de-CH", gettext("German (Switzerland)"), "ltr"],
26
+ ["el", gettext("Greek"), "ltr"],
27
+ ["he", gettext("Hebrew"), "rtl"],
28
+ ["is", gettext("Icelandic"), "ltr"],
29
+ ["it", gettext("Italian"), "ltr"],
30
+ ["ja", gettext("Japanese"), "ltr"],
31
+ ["km", gettext("Khmer"), "ltr"],
32
+ ["lt", gettext("Lithuanian"), "ltr"],
33
+ ["ml", gettext("Malayalam"), "ltr"],
34
+ ["nb-NO", gettext("Norwegian (bokmål)"), "ltr"],
35
+ ["nn-NO", gettext("Norwegian (nynorsk)"), "ltr"],
36
+ ["fa", gettext("Persian"), "rtl"],
37
+ ["pl", gettext("Polish"), "ltr"],
38
+ ["pt-BR", gettext("Portuguese (Brazil)"), "ltr"],
39
+ ["pt-PT", gettext("Portuguese (Portugal)"), "ltr"],
40
+ ["ro", gettext("Romanian"), "ltr"],
41
+ ["ru", gettext("Russian"), "ltr"],
42
+ ["tr", gettext("Turkish"), "ltr"],
43
+ ["sr-SP-Cy", gettext("Serbian (Cyrillic)"), "ltr"],
44
+ ["sr-SP-Lt", gettext("Serbian (Latin)"), "ltr"],
45
+ ["sk", gettext("Slovak"), "ltr"],
46
+ ["sl", gettext("Slovenian"), "ltr"],
47
+ ["es", gettext("Spanish"), "ltr"],
48
+ ["sv", gettext("Swedish"), "ltr"],
49
+ ["ta", gettext("Tamil"), "ltr"],
50
+ ["tl", gettext("Tagalog"), "ltr"],
51
+ ["uk", gettext("Ukrainian"), "ltr"]
52
+ ]
53
+
54
+ export const PAPER_SIZES = [
55
+ /* [Fidus Writer value, CSS value]*/
56
+ ["A4", "A4"],
57
+ ["US Letter", "letter"]
58
+ ]