@kerebron/extension-odt 0.0.13 → 0.1.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.
Files changed (38) hide show
  1. package/esm/editor/src/CoreEditor.d.ts +3 -8
  2. package/esm/editor/src/CoreEditor.d.ts.map +1 -1
  3. package/esm/editor/src/CoreEditor.js +12 -30
  4. package/esm/editor/src/Extension.d.ts +1 -1
  5. package/esm/editor/src/Extension.d.ts.map +1 -1
  6. package/esm/editor/src/Extension.js +1 -1
  7. package/esm/editor/src/ExtensionManager.js +2 -2
  8. package/esm/editor/src/mod.d.ts +1 -0
  9. package/esm/editor/src/mod.d.ts.map +1 -1
  10. package/esm/editor/src/mod.js +1 -0
  11. package/esm/editor/src/nodeToTreeString.d.ts +4 -0
  12. package/esm/editor/src/nodeToTreeString.d.ts.map +1 -0
  13. package/esm/editor/src/nodeToTreeString.js +53 -0
  14. package/esm/editor/src/utilities/createNodeFromContent.d.ts +2 -6
  15. package/esm/editor/src/utilities/createNodeFromContent.d.ts.map +1 -1
  16. package/esm/editor/src/utilities/createNodeFromContent.js +5 -90
  17. package/esm/extension-odt/src/ExtensionOdt.d.ts +7 -2
  18. package/esm/extension-odt/src/ExtensionOdt.d.ts.map +1 -1
  19. package/esm/extension-odt/src/ExtensionOdt.js +23 -5
  20. package/esm/extension-odt/src/OdtParser.d.ts +72 -3
  21. package/esm/extension-odt/src/OdtParser.d.ts.map +1 -1
  22. package/esm/extension-odt/src/OdtParser.js +375 -113
  23. package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.d.ts +3 -0
  24. package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.d.ts.map +1 -0
  25. package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.js +72 -0
  26. package/esm/extension-odt/src/postprocess/fixContinuedLists.d.ts +3 -0
  27. package/esm/extension-odt/src/postprocess/fixContinuedLists.d.ts.map +1 -0
  28. package/esm/extension-odt/src/postprocess/fixContinuedLists.js +83 -0
  29. package/esm/extension-odt/src/postprocess/postProcess.d.ts +3 -0
  30. package/esm/extension-odt/src/postprocess/postProcess.d.ts.map +1 -0
  31. package/esm/extension-odt/src/postprocess/postProcess.js +10 -0
  32. package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.d.ts +3 -0
  33. package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.d.ts.map +1 -0
  34. package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.js +27 -0
  35. package/package.json +4 -4
  36. package/esm/editor/src/debugDoc.d.ts +0 -3
  37. package/esm/editor/src/debugDoc.d.ts.map +0 -1
  38. package/esm/editor/src/debugDoc.js +0 -33
@@ -1,4 +1,5 @@
1
1
  import { Mark, } from 'prosemirror-model';
2
+ const COURIER_FONTS = ['Courier New', 'Courier', 'Roboto Mono'];
2
3
  function attrs(spec, token, style) {
3
4
  if (spec.getAttrs)
4
5
  return spec.getAttrs(token, style);
@@ -24,11 +25,16 @@ function resolveStyle(stylesTree, automaticStyles, name) {
24
25
  }
25
26
  style['styles'] = [name];
26
27
  if (style['@parent-style-name']) {
27
- const parenStyle = resolveStyle(stylesTree, automaticStyles, style['@parent-style-name']);
28
- if (parenStyle) {
29
- const styles = [...style['styles'], ...parenStyle['styles']];
28
+ const parentStyle = resolveStyle(stylesTree, automaticStyles, style['@parent-style-name']);
29
+ if (parentStyle) {
30
+ const styles = [...style['styles'], ...parentStyle['styles']];
31
+ for (const key in style) {
32
+ if (typeof style[key] === 'undefined') {
33
+ delete style[key];
34
+ }
35
+ }
30
36
  style = {
31
- ...parenStyle,
37
+ ...parentStyle,
32
38
  ...style,
33
39
  styles,
34
40
  };
@@ -37,13 +43,19 @@ function resolveStyle(stylesTree, automaticStyles, name) {
37
43
  return style;
38
44
  }
39
45
  class OdtParseState {
40
- constructor(schema, stylesTree, automaticStyles) {
46
+ constructor(schema, tokens, stylesTree, automaticStyles) {
41
47
  Object.defineProperty(this, "schema", {
42
48
  enumerable: true,
43
49
  configurable: true,
44
50
  writable: true,
45
51
  value: schema
46
52
  });
53
+ Object.defineProperty(this, "tokens", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: tokens
58
+ });
47
59
  Object.defineProperty(this, "stylesTree", {
48
60
  enumerable: true,
49
61
  configurable: true,
@@ -62,6 +74,18 @@ class OdtParseState {
62
74
  writable: true,
63
75
  value: void 0
64
76
  });
77
+ Object.defineProperty(this, "textMarks", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: new Set()
82
+ });
83
+ Object.defineProperty(this, "nextTextMarks", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: new Set()
88
+ });
65
89
  this.stack = [];
66
90
  this.openNode(schema.topNodeType, null);
67
91
  }
@@ -78,17 +102,26 @@ class OdtParseState {
78
102
  if (!text)
79
103
  return;
80
104
  let top = this.top(), nodes = top.content, last = nodes[nodes.length - 1];
81
- let node = this.schema.text(text, top.marks), merged;
82
- // if (last && (merged = maybeMerge(last, node))) {
83
- // nodes[nodes.length - 1] = merged;
84
- // } else
85
- // console.log('addtext', top.type.name, "'" + text + "'");
105
+ let marks = top.marks;
106
+ for (const textMark of this.textMarks) {
107
+ const markType = this.schema.marks[textMark.markName];
108
+ const mark = markType.create(textMark.markAttributes || {});
109
+ marks = mark.addToSet(marks);
110
+ }
111
+ for (const textMark of this.nextTextMarks) {
112
+ const markType = this.schema.marks[textMark.markName];
113
+ const mark = markType.create(textMark.markAttributes || {});
114
+ marks = mark.addToSet(marks);
115
+ }
116
+ this.nextTextMarks.clear();
117
+ let node = this.schema.text(text, marks), merged;
86
118
  nodes.push(node);
87
119
  }
88
120
  // Adds the given mark to the set of active marks.
89
121
  openMark(mark) {
90
122
  let top = this.top();
91
123
  top.marks = mark.addToSet(top.marks);
124
+ return mark.type;
92
125
  }
93
126
  // Removes the given mark from the set of active marks.
94
127
  closeMark(mark) {
@@ -96,9 +129,12 @@ class OdtParseState {
96
129
  top.marks = mark.removeFromSet(top.marks);
97
130
  }
98
131
  // Add a node at the current position.
99
- addNode(type, attrs, content) {
132
+ addNode(type, attrs, content, marks = Mark.none) {
100
133
  let top = this.top();
101
- let node = type.createAndFill(attrs, content, top ? top.marks : []);
134
+ if (top?.marks) {
135
+ marks = [...top.marks, ...marks];
136
+ }
137
+ let node = type.createAndFill(attrs, content, marks);
102
138
  if (!node)
103
139
  return null;
104
140
  this.push(node);
@@ -106,37 +142,58 @@ class OdtParseState {
106
142
  }
107
143
  // Wrap subsequent content in a node of the given type.
108
144
  openNode(type, attrs) {
109
- // console.log('openNode', type.name, attrs);
110
145
  this.stack.push({
111
146
  type: type,
112
147
  attrs: attrs,
113
148
  content: [],
114
- marks: Mark.none,
149
+ marks: Mark.none
115
150
  });
116
151
  }
117
152
  // Close and return the node that is currently on top of the stack.
118
- closeNode() {
153
+ closeNode(marks = Mark.none) {
119
154
  let info = this.stack.pop();
120
- // console.log('closeNode', info.type.name, info.attrs);
121
- return this.addNode(info.type, info.attrs, info.content);
155
+ return this.addNode(info.type, info.attrs, info.content, marks);
122
156
  }
123
157
  handleElement(nodeType, element) {
124
- const spec = tokens[nodeType];
158
+ const spec = this.tokens[nodeType];
125
159
  if (!spec) {
126
160
  console.warn('No spec for:', nodeType, element, this.stack.map((item) => item.type.name));
127
161
  return;
128
162
  }
129
- // console.log('handleElement', nodeType, this.stack.length);
163
+ if (spec.custom) {
164
+ spec.custom(this, element);
165
+ return;
166
+ }
130
167
  const children = spec.children ? spec.children(element) : [];
131
- // console.log('ccc', nodeType, children);
132
- let style;
133
- if ('object' === typeof element && element['@style-name']) {
134
- style = resolveStyle(this.stylesTree, this.automaticStyles, element['@style-name']);
168
+ const style = ('object' === typeof element && element['@style-name']) ? resolveStyle(this.stylesTree, this.automaticStyles, element['@style-name']) : {};
169
+ const markToClose = [];
170
+ const textProperties = style && style['text-properties'] || {};
171
+ const marks = [];
172
+ if (COURIER_FONTS.indexOf(textProperties['@font-name'] || '') > -1) {
173
+ this.textMarks.add({
174
+ markName: 'code',
175
+ markAttributes: {}
176
+ });
177
+ const markType = this.schema.mark('code');
178
+ marks.push(markType);
179
+ }
180
+ // if (style.textProperties?.fontStyle === 'italic' && style.textProperties?.fontWeight === 'bold') {
181
+ // const block = this.chunks.createNode('BI');
182
+ // this.chunks.append(currentTagNode, block);
183
+ // currentTagNode = block;
184
+ // } else
185
+ if (textProperties['@font-style'] === 'italic') {
186
+ const markType = this.schema.marks['em'];
187
+ markToClose.push(this.openMark(markType.create(attrs(spec, element, style))));
188
+ }
189
+ else if (textProperties['@font-weight'] === 'bold') {
190
+ const markType = this.schema.marks['strong'];
191
+ markToClose.push(this.openMark(markType.create(attrs(spec, element, style))));
135
192
  }
136
193
  if (spec.block) {
137
194
  let block = spec.block;
138
195
  if ('string' !== typeof block) {
139
- block = block(element, style);
196
+ block = block(element, style)[0];
140
197
  }
141
198
  let nodeType = this.schema.nodeType(block);
142
199
  this.openNode(nodeType, attrs(spec, element, style));
@@ -146,12 +203,12 @@ class OdtParseState {
146
203
  });
147
204
  }
148
205
  // this.addText(withoutTrailingNewline(tok.content));
149
- this.closeNode();
206
+ this.closeNode(marks);
150
207
  }
151
208
  else if (spec.node) {
152
209
  }
153
210
  else if (spec.mark) {
154
- let markType = this.schema.marks[spec.mark];
211
+ const markType = this.schema.marks[spec.mark];
155
212
  this.openMark(markType.create(attrs(spec, element, style)));
156
213
  if (children) {
157
214
  iterateChildren(children, (nodeType, node) => {
@@ -170,6 +227,13 @@ class OdtParseState {
170
227
  });
171
228
  }
172
229
  }
230
+ while (markToClose.length > 0) {
231
+ const markType = markToClose.pop();
232
+ this.closeMark(markType);
233
+ }
234
+ if (COURIER_FONTS.indexOf(textProperties['@font-name'] || '') > -1) {
235
+ this.textMarks.forEach(x => x.markName === 'code' ? this.textMarks.delete(x) : x);
236
+ }
173
237
  }
174
238
  }
175
239
  function iterateChildren(nodes, callback) {
@@ -207,105 +271,303 @@ function iterateEnum($value) {
207
271
  return item;
208
272
  });
209
273
  }
210
- const tokens = {
211
- 'body': {
212
- children: (odtElement) => iterateEnum(odtElement.text?.$value),
213
- },
214
- 'p': {
215
- block: (odtElement, style) => {
216
- if (style.styles.find((item) => item.startsWith('Heading_20_'))) {
217
- return 'heading';
218
- }
219
- return 'paragraph';
220
- },
221
- getAttrs: (odtElement, style) => {
222
- const heading = style.styles.find((item) => item.startsWith('Heading_20_'));
223
- if (heading) {
224
- return {
225
- level: parseInt(heading.substring('Heading_20_'.length)),
226
- };
227
- }
228
- },
229
- children: (odtElement) => iterateEnum(odtElement.$value),
230
- },
231
- 'span': {
232
- children: (odtElement) => iterateEnum(odtElement.$value),
233
- },
234
- 'list': {
235
- block: 'ordered_list',
236
- children: (odtElement) => odtElement['list-item'].map((item) => ({ 'list-item': item })),
237
- },
238
- 'list-item': {
239
- block: 'list_item',
240
- children: (odtElement) => iterateEnum(odtElement.$value),
241
- },
242
- 'table': {
243
- block: 'table',
244
- children: (odtElement) => odtElement['table-row'].map((item) => ({ 'table-row': item })),
245
- },
246
- 'table-row': {
247
- block: 'table_row',
248
- children: (odtElement) => odtElement['table-cell'].map((item) => ({ 'table-cell': item })),
249
- },
250
- 'table-cell': {
251
- block: 'table_cell',
252
- children: (odtElement) => iterateEnum(odtElement.$value),
253
- },
254
- 'a': {
255
- mark: 'link',
256
- getAttrs: (tok) => ({
257
- href: tok['@href'],
258
- // title: tok.attrGet('title') || null,
259
- }),
260
- children: (odtElement) => odtElement['span'].map(item => ({ 'span': item }))
261
- },
262
- '$value': {
263
- children: (odtElement) => iterateEnum(odtElement),
264
- },
265
- '$text': {
266
- // TODO: fix trimming: https://github.com/tafia/quick-xml/issues/285
267
- text: (odtElement) => String(odtElement || ''),
268
- },
269
- 's': {
270
- text: (odtElement) => {
271
- const chars = odtElement['@c'] || 1;
272
- return ' '.substring(0, chars);
273
- },
274
- },
275
- 'tab': {
276
- text: (odtElement) => '\t',
277
- },
278
- 'table-of-content': {
279
- block: 'paragraph',
280
- children: (odtElement) => odtElement['index-body']['p'] || [],
281
- },
282
- 'frame': {
283
- ignore: true,
284
- },
285
- 'rect': {
286
- ignore: true,
287
- },
288
- 'bookmark': {
289
- ignore: true,
290
- },
291
- 'annotation': {
292
- ignore: true,
293
- },
294
- };
274
+ class ListNumbering {
275
+ constructor() {
276
+ Object.defineProperty(this, "levels", {
277
+ enumerable: true,
278
+ configurable: true,
279
+ writable: true,
280
+ value: {}
281
+ });
282
+ Object.defineProperty(this, "levelNodes", {
283
+ enumerable: true,
284
+ configurable: true,
285
+ writable: true,
286
+ value: {}
287
+ });
288
+ for (let i = 0; i < 20; i++) {
289
+ this.levels[i] = 1;
290
+ }
291
+ }
292
+ clearAbove(level) {
293
+ for (let i = level + 1; i < 20; i++) {
294
+ this.levels[i] = 1;
295
+ }
296
+ }
297
+ setLevelNode(level, node) {
298
+ this.levelNodes[level] = node;
299
+ }
300
+ }
295
301
  export class OdtParser {
296
- constructor(schema) {
302
+ constructor(schema, config = {}) {
297
303
  Object.defineProperty(this, "schema", {
298
304
  enumerable: true,
299
305
  configurable: true,
300
306
  writable: true,
301
307
  value: schema
302
308
  });
309
+ Object.defineProperty(this, "config", {
310
+ enumerable: true,
311
+ configurable: true,
312
+ writable: true,
313
+ value: config
314
+ });
315
+ Object.defineProperty(this, "listStack", {
316
+ enumerable: true,
317
+ configurable: true,
318
+ writable: true,
319
+ value: []
320
+ });
321
+ Object.defineProperty(this, "listNumberings", {
322
+ enumerable: true,
323
+ configurable: true,
324
+ writable: true,
325
+ value: new Map()
326
+ });
327
+ Object.defineProperty(this, "lastNumbering", {
328
+ enumerable: true,
329
+ configurable: true,
330
+ writable: true,
331
+ value: void 0
332
+ });
333
+ Object.defineProperty(this, "preserveMinLevel", {
334
+ enumerable: true,
335
+ configurable: true,
336
+ writable: true,
337
+ value: 999
338
+ });
303
339
  // this.tokenHandlers = tokenHandlers(schema, tokens);
304
340
  }
305
341
  parse(files) {
306
342
  const contentTree = files.contentTree;
307
343
  const stylesTree = files.stylesTree;
308
- const state = new OdtParseState(this.schema, stylesTree, contentTree['automatic-styles']);
344
+ const automaticStyles = contentTree['automatic-styles'];
345
+ const tokens = {
346
+ 'body': {
347
+ children: (odtElement) => iterateEnum(odtElement.text?.$value),
348
+ },
349
+ 'p': {
350
+ block: (odtElement, style) => {
351
+ if (style.styles.find((item) => item.startsWith('Heading_20_'))) {
352
+ return ['heading'];
353
+ }
354
+ return ['paragraph'];
355
+ },
356
+ getAttrs: (odtElement, style) => {
357
+ const heading = style.styles.find((item) => item.startsWith('Heading_20_'));
358
+ if (heading) {
359
+ return {
360
+ level: parseInt(heading.substring('Heading_20_'.length)),
361
+ };
362
+ }
363
+ },
364
+ children: (odtElement) => iterateEnum(odtElement.$value),
365
+ },
366
+ 'span': {
367
+ children: (odtElement) => iterateEnum(odtElement.$value),
368
+ },
369
+ 'list': {
370
+ custom: (state, odtElement) => {
371
+ const list = {
372
+ level: this.listStack.length + 1,
373
+ odtElement
374
+ };
375
+ this.listStack.push(list);
376
+ let style = {};
377
+ let listId = null;
378
+ for (let i = this.listStack.length - 1; i >= 0; i--) {
379
+ const element = this.listStack[i].odtElement;
380
+ if (!listId) {
381
+ if (element['@id']) {
382
+ listId = element['@id'];
383
+ }
384
+ }
385
+ if (!style['@style-name']) {
386
+ style = ('object' === typeof element && element['@style-name']) ? resolveStyle(stylesTree, automaticStyles, element['@style-name']) : {};
387
+ }
388
+ }
389
+ let nodeTypeName = 'bullet_list';
390
+ const attrs = {};
391
+ if (style) {
392
+ const numLevelStyle = style['list-level-style-number'].find(levelStyle => parseInt(levelStyle['@level']) === list.level);
393
+ if (numLevelStyle) {
394
+ attrs['type'] = numLevelStyle['@num-format'] || '1';
395
+ nodeTypeName = 'ordered_list';
396
+ }
397
+ }
398
+ let listNumbering = null;
399
+ if (listId && this.listNumberings.has(listId)) {
400
+ listNumbering = this.listNumberings.get(listId);
401
+ }
402
+ let isContinue = false;
403
+ if (odtElement['@continue-list'] && this.listNumberings.has(odtElement['@continue-list'])) {
404
+ listNumbering = this.listNumberings.get(odtElement['@continue-list']);
405
+ isContinue = true;
406
+ }
407
+ if (odtElement['@continue-numbering']) {
408
+ listNumbering = this.lastNumbering;
409
+ isContinue = true;
410
+ }
411
+ if (!listNumbering) {
412
+ listNumbering = new ListNumbering();
413
+ }
414
+ if (isContinue) {
415
+ this.preserveMinLevel = 999;
416
+ }
417
+ if (listId) {
418
+ this.listNumberings.set(listId, listNumbering);
419
+ }
420
+ this.lastNumbering = listNumbering;
421
+ if (this.preserveMinLevel <= list.level) {
422
+ listNumbering.clearAbove(list.level - 1);
423
+ }
424
+ if (nodeTypeName === 'ordered_list') {
425
+ attrs['start'] = listNumbering.levels[list.level] || 1;
426
+ }
427
+ let nodeType = this.schema.nodeType(nodeTypeName);
428
+ state.openNode(nodeType, attrs);
429
+ const children = odtElement['list-item'].map((item) => ({ 'list-item': item }));
430
+ if (children) {
431
+ iterateChildren(children, (nodeType, node) => {
432
+ state.handleElement(nodeType, node);
433
+ });
434
+ listNumbering.levels[list.level] += children.length;
435
+ }
436
+ state.closeNode();
437
+ if (this.preserveMinLevel >= list.level) {
438
+ this.preserveMinLevel = list.level;
439
+ }
440
+ this.listStack.pop();
441
+ }
442
+ },
443
+ 'list-item': {
444
+ block: 'list_item',
445
+ children: (odtElement) => iterateEnum(odtElement.$value),
446
+ },
447
+ 'table': {
448
+ block: 'table',
449
+ children: (odtElement) => odtElement['table-row'].map((item) => ({ 'table-row': item })),
450
+ },
451
+ 'table-row': {
452
+ block: 'table_row',
453
+ children: (odtElement) => odtElement['table-cell'].map((item) => ({ 'table-cell': item })),
454
+ },
455
+ 'table-cell': {
456
+ block: 'table_cell',
457
+ children: (odtElement) => iterateEnum(odtElement.$value),
458
+ },
459
+ 'a': {
460
+ mark: 'link',
461
+ getAttrs: (tok) => {
462
+ let href = tok['@href'];
463
+ if (this.config.linkFromRewriter) {
464
+ href = this.config.linkFromRewriter(href);
465
+ }
466
+ return {
467
+ href,
468
+ // title: tok.attrGet('title') || null,
469
+ };
470
+ },
471
+ children: (odtElement) => iterateEnum(odtElement.$value),
472
+ },
473
+ '$value': {
474
+ children: (odtElement) => iterateEnum(odtElement),
475
+ },
476
+ '$text': {
477
+ // TODO: fix trimming: https://github.com/tafia/quick-xml/issues/285
478
+ text: (odtElement) => String(odtElement || ''),
479
+ },
480
+ 's': {
481
+ text: (odtElement) => {
482
+ const chars = odtElement['@c'] || 1;
483
+ return ' '.substring(0, chars);
484
+ },
485
+ },
486
+ 'tab': {
487
+ text: (odtElement) => '\t',
488
+ },
489
+ 'line-break': {
490
+ block: 'br'
491
+ },
492
+ 'soft-page-break': {
493
+ block: 'br'
494
+ },
495
+ 'table-of-content': {
496
+ block: 'paragraph',
497
+ children: (odtElement) => odtElement['index-body']['p'] || [],
498
+ },
499
+ 'change-start': {
500
+ custom(state) {
501
+ state.textMarks.add({
502
+ markName: 'change',
503
+ markAttributes: {}
504
+ });
505
+ }
506
+ },
507
+ 'change-end': {
508
+ custom(state) {
509
+ state.textMarks.forEach(x => x.markName === 'change' ? state.textMarks.delete(x) : x);
510
+ }
511
+ },
512
+ 'frame': {
513
+ custom: (state, odtElement) => {
514
+ if (odtElement.object && odtElement.object['@href']) { // TODO MathML
515
+ // const fileName= drawFrame.object.href.replace(/\s/g, '_').replace(/^\.\//, '') + '.xml';
516
+ // try {
517
+ // const mathMl = this.xmlMap[fileName];
518
+ // if (mathMl && mathMl.indexOf('<math ') > -1) {
519
+ // const node = this.chunks.createNode('MATHML');
520
+ // const latex = MathMLToLaTeX.convert(mathMl);
521
+ // this.chunks.appendText(node, latex);
522
+ // this.chunks.append(currentTagNode, node);
523
+ // }
524
+ // } catch (err) {
525
+ // console.warn(err);
526
+ // }
527
+ }
528
+ if (odtElement.image && odtElement.image['@href']) { // TODO links rewrite
529
+ const nodeType = this.schema.nodeType('image');
530
+ const alt = odtElement.description?.value || '';
531
+ state.addNode(nodeType, {
532
+ src: odtElement.image['@href'],
533
+ alt
534
+ }, []);
535
+ }
536
+ }
537
+ },
538
+ 'rect': {
539
+ ignore: true,
540
+ },
541
+ 'bookmark': {
542
+ custom(state, element) {
543
+ state.nextTextMarks.add({
544
+ markName: 'bookmark',
545
+ markAttributes: {
546
+ id: element['@name']
547
+ }
548
+ });
549
+ }
550
+ },
551
+ 'bookmark-start': {
552
+ custom(state, element) {
553
+ state.textMarks.add({
554
+ markName: 'bookmark',
555
+ markAttributes: {
556
+ id: element['@name']
557
+ }
558
+ });
559
+ }
560
+ },
561
+ 'bookmark-end': {
562
+ custom(state, element) {
563
+ state.textMarks.forEach(x => x.markName === 'bookmark' && x.markAttributes.id === element['@name'] ? state.textMarks.delete(x) : x);
564
+ }
565
+ },
566
+ 'annotation': {
567
+ ignore: true,
568
+ },
569
+ };
570
+ const state = new OdtParseState(this.schema, tokens, stylesTree, contentTree['automatic-styles']);
309
571
  state.handleElement('body', contentTree.body);
310
572
  let doc;
311
573
  do {
@@ -0,0 +1,3 @@
1
+ import { Command } from 'prosemirror-state';
2
+ export declare const convertCodeParagraphsToCodeBlocks: Command;
3
+ //# sourceMappingURL=convertCodeParagraphsToCodeBlocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convertCodeParagraphsToCodeBlocks.d.ts","sourceRoot":"","sources":["../../../../src/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,OAAO,EAER,MAAM,mBAAmB,CAAC;AAqB3B,eAAO,MAAM,iCAAiC,EAAE,OA2E/C,CAAA"}
@@ -0,0 +1,72 @@
1
+ function onlyHasCodeMarkedText(paragraph, codeMarkType) {
2
+ if (paragraph.content.size === 0) {
3
+ return paragraph.marks.some(mark => mark.type.name === codeMarkType.name);
4
+ }
5
+ let allAreCodeMarked = true;
6
+ paragraph.content.forEach(child => {
7
+ if (!child.isText ||
8
+ !child.marks.some(mark => mark.type.name === codeMarkType.name)) {
9
+ allAreCodeMarked = false;
10
+ }
11
+ });
12
+ return allAreCodeMarked;
13
+ }
14
+ export const convertCodeParagraphsToCodeBlocks = (state, dispatch) => {
15
+ const doc = state.doc;
16
+ const schema = state.schema;
17
+ let tr = state.tr;
18
+ let paragraphsToMerge = null;
19
+ function flushCodeBlock() {
20
+ if (paragraphsToMerge === null) {
21
+ return;
22
+ }
23
+ const textNode = schema.text(paragraphsToMerge.innerText);
24
+ const codeBlock = schema.nodes.code_block.createAndFill(null, [textNode]);
25
+ const startPos = tr.mapping.map(paragraphsToMerge.startPos);
26
+ const endPos = tr.mapping.map(paragraphsToMerge.endPos);
27
+ tr.replaceRangeWith(startPos, endPos, codeBlock);
28
+ paragraphsToMerge = null;
29
+ }
30
+ function nodesToText(fragment) {
31
+ if (fragment.content.length === 0) {
32
+ return '';
33
+ }
34
+ let retVal = '';
35
+ fragment.content.forEach(node => {
36
+ if (node.isText) {
37
+ retVal += node.text;
38
+ }
39
+ else {
40
+ retVal = '@TODO: node.type ' + node.type;
41
+ }
42
+ });
43
+ return retVal;
44
+ }
45
+ doc.forEach((node, pos) => {
46
+ if (node.type.name === 'paragraph') {
47
+ const isCodeOnly = onlyHasCodeMarkedText(node, schema.marks.code);
48
+ const isEmpty = node.content.size === 0;
49
+ if (isCodeOnly) {
50
+ if (paragraphsToMerge === null) {
51
+ paragraphsToMerge = { startPos: pos, endPos: pos + node.nodeSize, innerText: nodesToText(node.content) };
52
+ }
53
+ else {
54
+ paragraphsToMerge = { startPos: paragraphsToMerge.startPos, endPos: pos + node.nodeSize,
55
+ innerText: paragraphsToMerge.innerText + '\n' + nodesToText(node.content)
56
+ };
57
+ }
58
+ return;
59
+ }
60
+ }
61
+ if (paragraphsToMerge !== null) {
62
+ flushCodeBlock();
63
+ }
64
+ });
65
+ if (paragraphsToMerge !== null) {
66
+ flushCodeBlock();
67
+ }
68
+ if (dispatch) {
69
+ dispatch(tr);
70
+ }
71
+ return tr.steps.length > 0;
72
+ };