@kerebron/extension-odt 0.0.13 → 0.1.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/esm/editor/src/CoreEditor.d.ts +3 -8
- package/esm/editor/src/CoreEditor.d.ts.map +1 -1
- package/esm/editor/src/CoreEditor.js +12 -30
- package/esm/editor/src/Extension.d.ts +1 -1
- package/esm/editor/src/Extension.d.ts.map +1 -1
- package/esm/editor/src/Extension.js +1 -1
- package/esm/editor/src/ExtensionManager.js +2 -2
- package/esm/editor/src/mod.d.ts +1 -0
- package/esm/editor/src/mod.d.ts.map +1 -1
- package/esm/editor/src/mod.js +1 -0
- package/esm/editor/src/nodeToTreeString.d.ts +4 -0
- package/esm/editor/src/nodeToTreeString.d.ts.map +1 -0
- package/esm/editor/src/nodeToTreeString.js +53 -0
- package/esm/editor/src/utilities/createNodeFromContent.d.ts +2 -6
- package/esm/editor/src/utilities/createNodeFromContent.d.ts.map +1 -1
- package/esm/editor/src/utilities/createNodeFromContent.js +5 -90
- package/esm/extension-odt/src/ExtensionOdt.d.ts +7 -2
- package/esm/extension-odt/src/ExtensionOdt.d.ts.map +1 -1
- package/esm/extension-odt/src/ExtensionOdt.js +23 -5
- package/esm/extension-odt/src/OdtParser.d.ts +72 -3
- package/esm/extension-odt/src/OdtParser.d.ts.map +1 -1
- package/esm/extension-odt/src/OdtParser.js +375 -113
- package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.d.ts +3 -0
- package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.d.ts.map +1 -0
- package/esm/extension-odt/src/postprocess/convertCodeParagraphsToCodeBlocks.js +72 -0
- package/esm/extension-odt/src/postprocess/fixContinuedLists.d.ts +3 -0
- package/esm/extension-odt/src/postprocess/fixContinuedLists.d.ts.map +1 -0
- package/esm/extension-odt/src/postprocess/fixContinuedLists.js +83 -0
- package/esm/extension-odt/src/postprocess/postProcess.d.ts +3 -0
- package/esm/extension-odt/src/postprocess/postProcess.d.ts.map +1 -0
- package/esm/extension-odt/src/postprocess/postProcess.js +10 -0
- package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.d.ts +3 -0
- package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.d.ts.map +1 -0
- package/esm/extension-odt/src/postprocess/removeUnusedBookmarks.js +27 -0
- package/package.json +4 -4
- package/esm/editor/src/debugDoc.d.ts +0 -3
- package/esm/editor/src/debugDoc.d.ts.map +0 -1
- package/esm/editor/src/debugDoc.js +0 -33
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { EditorView } from 'prosemirror-view';
|
|
2
|
-
import {
|
|
2
|
+
import { Node as ProseMirrorNode, type Schema } from 'prosemirror-model';
|
|
3
3
|
import type { EditorOptions, JSONContent } from './types.js';
|
|
4
4
|
import { EditorState, Transaction } from 'prosemirror-state';
|
|
5
5
|
import { ChainedCommands } from './commands/CommandManager.js';
|
|
6
|
-
export declare function getHTMLFromFragment(fragment: Fragment, schema: Schema): string;
|
|
7
6
|
export declare class CoreEditor extends EventTarget {
|
|
8
7
|
readonly options: Partial<EditorOptions>;
|
|
9
8
|
private extensionManager;
|
|
@@ -17,13 +16,9 @@ export declare class CoreEditor extends EventTarget {
|
|
|
17
16
|
private createView;
|
|
18
17
|
dispatchTransaction(transaction: Transaction): void;
|
|
19
18
|
private setupPlugins;
|
|
20
|
-
getJSON(): JSONContent;
|
|
21
|
-
/**
|
|
22
|
-
* Get the document as HTML.
|
|
23
|
-
*/
|
|
24
|
-
getHTML(): string;
|
|
25
19
|
setDocument(content?: any, mediaType?: string): void;
|
|
26
|
-
getDocument(mediaType?: string): void | ProseMirrorNode;
|
|
20
|
+
getDocument(mediaType?: string): void | ProseMirrorNode | JSONContent;
|
|
21
|
+
getJSON(): JSONContent;
|
|
27
22
|
clone(options?: Partial<EditorOptions>): CoreEditor;
|
|
28
23
|
debug(doc?: ProseMirrorNode): void;
|
|
29
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,IAAI,IAAI,eAAe,EACvB,KAAK,MAAM,EACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAkB,MAAM,8BAA8B,CAAC;AAgC/E,qBAAa,UAAW,SAAQ,WAAW;IACzC,SAAgB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAG7C;IACF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IAChC,IAAI,EAAG,UAAU,CAAC;IAClB,KAAK,EAAG,WAAW,CAAC;gBAEf,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;IAyBhD,IAAW,MAAM,qBAEhB;IAEM,KAAK,IAAI,eAAe;IAIxB,GAAG,IAAI,eAAe;IAI7B,OAAO,CAAC,UAAU;IAaX,mBAAmB,CAAC,WAAW,EAAE,WAAW;IAcnD,OAAO,CAAC,YAAY;IAcb,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM;IAwC7C,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM;IAkB9B,OAAO,IAAI,WAAW;IAItB,KAAK,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,UAAU;IAOvD,KAAK,CAAC,GAAG,CAAC,EAAE,eAAe;CAMnC"}
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { EditorView } from 'prosemirror-view';
|
|
2
|
-
import {
|
|
2
|
+
import { Node as ProseMirrorNode, } from 'prosemirror-model';
|
|
3
3
|
import { ExtensionManager } from './ExtensionManager.js';
|
|
4
4
|
import { EditorState } from 'prosemirror-state';
|
|
5
5
|
import { createNodeFromContent } from './utilities/createNodeFromContent.js';
|
|
6
6
|
import { CommandManager } from './commands/CommandManager.js';
|
|
7
|
-
import {
|
|
8
|
-
export function getHTMLFromFragment(fragment, schema) {
|
|
9
|
-
const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
10
|
-
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
11
|
-
const container = temporaryDocument.createElement('div');
|
|
12
|
-
container.appendChild(documentFragment);
|
|
13
|
-
return container.innerHTML;
|
|
14
|
-
}
|
|
15
|
-
function createDocument(content, schema, parseOptions = {}, options = {}) {
|
|
16
|
-
return createNodeFromContent(content, schema, {
|
|
17
|
-
slice: false,
|
|
18
|
-
parseOptions,
|
|
19
|
-
errorOnInvalidContent: options.errorOnInvalidContent,
|
|
20
|
-
});
|
|
21
|
-
}
|
|
7
|
+
import { nodeToTreeString } from './nodeToTreeString.js';
|
|
22
8
|
function ensureDocSchema(doc, schema) {
|
|
23
9
|
if (doc.type.schema != schema) {
|
|
24
10
|
const findNode = (nodeName) => {
|
|
@@ -108,7 +94,7 @@ export class CoreEditor extends EventTarget {
|
|
|
108
94
|
return this.commandManager.can();
|
|
109
95
|
}
|
|
110
96
|
createView(content) {
|
|
111
|
-
|
|
97
|
+
const doc = createNodeFromContent(content, this.schema);
|
|
112
98
|
this.state = EditorState.create({ doc });
|
|
113
99
|
if (this.options.element) {
|
|
114
100
|
this.view = new EditorView(this.options.element, {
|
|
@@ -141,21 +127,11 @@ export class CoreEditor extends EventTarget {
|
|
|
141
127
|
});
|
|
142
128
|
}
|
|
143
129
|
}
|
|
144
|
-
getJSON() {
|
|
145
|
-
return this.state.doc.toJSON();
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Get the document as HTML.
|
|
149
|
-
*/
|
|
150
|
-
getHTML() {
|
|
151
|
-
return getHTMLFromFragment(this.state.doc.content, this.schema);
|
|
152
|
-
}
|
|
153
130
|
setDocument(content, mediaType) {
|
|
154
|
-
if (!content) {
|
|
131
|
+
if (!content) {
|
|
155
132
|
content = {
|
|
156
133
|
type: this.extensionManager.schema.topNodeType.name,
|
|
157
134
|
content: this.extensionManager.schema.topNodeType.spec.EMPTY_DOC.content,
|
|
158
|
-
// content: this.extensionManager.schema.topNodeType.createAndFill(),
|
|
159
135
|
};
|
|
160
136
|
mediaType = undefined;
|
|
161
137
|
}
|
|
@@ -167,7 +143,7 @@ export class CoreEditor extends EventTarget {
|
|
|
167
143
|
}
|
|
168
144
|
}
|
|
169
145
|
else {
|
|
170
|
-
doc =
|
|
146
|
+
doc = createNodeFromContent(content, this.schema);
|
|
171
147
|
}
|
|
172
148
|
ensureDocSchema(doc, this.schema);
|
|
173
149
|
this.state = EditorState.create({
|
|
@@ -194,9 +170,15 @@ export class CoreEditor extends EventTarget {
|
|
|
194
170
|
const clonedDoc = ProseMirrorNode.fromJSON(this.state.schema, json);
|
|
195
171
|
return converter.fromDoc(clonedDoc);
|
|
196
172
|
}
|
|
173
|
+
if (mediaType === 'text/json') {
|
|
174
|
+
return this.getJSON();
|
|
175
|
+
}
|
|
197
176
|
}
|
|
198
177
|
return this.state.doc;
|
|
199
178
|
}
|
|
179
|
+
getJSON() {
|
|
180
|
+
return this.state.doc.toJSON();
|
|
181
|
+
}
|
|
200
182
|
clone(options = {}) {
|
|
201
183
|
return new CoreEditor({
|
|
202
184
|
...options,
|
|
@@ -207,6 +189,6 @@ export class CoreEditor extends EventTarget {
|
|
|
207
189
|
if (!doc) {
|
|
208
190
|
doc = this.state.doc;
|
|
209
191
|
}
|
|
210
|
-
|
|
192
|
+
console.debug(nodeToTreeString(doc));
|
|
211
193
|
}
|
|
212
194
|
}
|
|
@@ -20,7 +20,7 @@ export declare abstract class Extension {
|
|
|
20
20
|
getProseMirrorPlugins(editor: CoreEditor, schema: Schema): Plugin[];
|
|
21
21
|
getCommands(editor: CoreEditor): Partial<Commands>;
|
|
22
22
|
getKeyboardShortcuts(): Partial<CommandShortcuts>;
|
|
23
|
-
getConverters(): Record<string, Converter>;
|
|
23
|
+
getConverters(editor: CoreEditor, schema: Schema): Record<string, Converter>;
|
|
24
24
|
setupSpec(spec: SchemaSpec): void;
|
|
25
25
|
}
|
|
26
26
|
//# sourceMappingURL=Extension.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Extension.d.ts","sourceRoot":"","sources":["../../../src/editor/src/Extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,WAAW,eAAe;IAE9B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB,QAAQ,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAAC;CAC9B;AAED,8BAAsB,SAAS;IAIP,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC;IAHhE,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,aAAuB,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAGrE,aAAa,IAAI,SAAS,EAAE;IAI5B,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAInE,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIlD,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIjD,aAAa,
|
|
1
|
+
{"version":3,"file":"Extension.d.ts","sourceRoot":"","sources":["../../../src/editor/src/Extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,WAAW,eAAe;IAE9B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB,QAAQ,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAAC;CAC9B;AAED,8BAAsB,SAAS;IAIP,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC;IAHhE,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,aAAuB,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAGrE,aAAa,IAAI,SAAS,EAAE;IAI5B,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAInE,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIlD,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIjD,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAI5E,SAAS,CAAC,IAAI,EAAE,UAAU;CAE3B"}
|
|
@@ -133,7 +133,7 @@ export class ExtensionManager {
|
|
|
133
133
|
mergeShortcuts(extension.getKeyboardShortcuts(this.editor), extension.name);
|
|
134
134
|
converters = {
|
|
135
135
|
...converters,
|
|
136
|
-
...extension.getConverters(this.schema),
|
|
136
|
+
...extension.getConverters(this.editor, this.schema),
|
|
137
137
|
};
|
|
138
138
|
const nodeView = extension.getNodeView();
|
|
139
139
|
if (nodeView) {
|
|
@@ -152,7 +152,7 @@ export class ExtensionManager {
|
|
|
152
152
|
mergeShortcuts(extension.getKeyboardShortcuts(this.editor), extension.name);
|
|
153
153
|
converters = {
|
|
154
154
|
...converters,
|
|
155
|
-
...extension.getConverters(this.schema),
|
|
155
|
+
...extension.getConverters(this.editor, this.schema),
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
}
|
package/esm/editor/src/mod.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../src/editor/src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../src/editor/src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,uBAAuB,CAAC"}
|
package/esm/editor/src/mod.js
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Node } from 'prosemirror-model';
|
|
2
|
+
export declare function nodeToTreeString(node: Node | Node[] | readonly Node[], level?: number, currentPos?: number): string;
|
|
3
|
+
export declare function debugNode(node: Node | Node[]): void;
|
|
4
|
+
//# sourceMappingURL=nodeToTreeString.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeToTreeString.d.ts","sourceRoot":"","sources":["../../../src/editor/src/nodeToTreeString.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,mBAAmB,CAAC;AAYvC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,SAAS,IAAI,EAAE,EAAE,KAAK,SAAI,EAAE,UAAU,SAAI,UAmDhG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,QAE5C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function trimText(str, maxLen = 20) {
|
|
2
|
+
str = str.replaceAll('\n', '\\n');
|
|
3
|
+
if (str.length <= maxLen) {
|
|
4
|
+
return str;
|
|
5
|
+
}
|
|
6
|
+
return str.slice(0, maxLen) + '...';
|
|
7
|
+
}
|
|
8
|
+
export function nodeToTreeString(node, level = 0, currentPos = 0) {
|
|
9
|
+
let delim = '';
|
|
10
|
+
for (let i = 0; i < level; i++) {
|
|
11
|
+
delim += ' ';
|
|
12
|
+
}
|
|
13
|
+
let output = '';
|
|
14
|
+
if (Array.isArray(node)) {
|
|
15
|
+
for (const child of node) {
|
|
16
|
+
output += delim + nodeToTreeString(child, level + 1, currentPos).replace(/\s+$/gm, '') + '\n';
|
|
17
|
+
}
|
|
18
|
+
return output;
|
|
19
|
+
}
|
|
20
|
+
// https://prosemirror.net/docs/guide/#doc.indexing
|
|
21
|
+
let line = '';
|
|
22
|
+
// if (node.type) {
|
|
23
|
+
line += ` - [${node.type.name}] `;
|
|
24
|
+
// } else {
|
|
25
|
+
// line += ` - `;
|
|
26
|
+
// }
|
|
27
|
+
line += `pos: ${currentPos}, `;
|
|
28
|
+
line += `nodeSize: ${node.nodeSize}, `; // isLeaf ? 1 : 2 + this.content.size
|
|
29
|
+
line += `epos: ${currentPos + node.nodeSize}, `; // isLeaf ? 1 : 2 + this.content.size
|
|
30
|
+
if (node.content) {
|
|
31
|
+
line += `fragment.size: ${node.content.size}, `;
|
|
32
|
+
}
|
|
33
|
+
output += (delim + line) + '\n';
|
|
34
|
+
let marksLine = '';
|
|
35
|
+
if (node.marks) {
|
|
36
|
+
for (const mark of node.marks) {
|
|
37
|
+
marksLine += `(${mark.type.name}), `;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (marksLine) {
|
|
41
|
+
output += (delim + ' ' + marksLine) + '\n';
|
|
42
|
+
}
|
|
43
|
+
if (node.text) {
|
|
44
|
+
output += (delim + ' "' + trimText(node.text) + '"') + '\n';
|
|
45
|
+
}
|
|
46
|
+
node.forEach((child, offset) => {
|
|
47
|
+
output += nodeToTreeString(child, level + 1, currentPos + offset + 1).replace(/\s+$/gm, '') + '\n'; // + (node.isLeaf ? 1 : 2)
|
|
48
|
+
});
|
|
49
|
+
return output;
|
|
50
|
+
}
|
|
51
|
+
export function debugNode(node) {
|
|
52
|
+
console.debug(nodeToTreeString(node));
|
|
53
|
+
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { Fragment, Node as ProseMirrorNode,
|
|
1
|
+
import { Fragment, Node as ProseMirrorNode, Schema } from 'prosemirror-model';
|
|
2
2
|
import type { Content } from '../types.js';
|
|
3
3
|
export type CreateNodeFromContentOptions = {
|
|
4
|
-
slice?: boolean;
|
|
5
|
-
parseOptions?: ParseOptions;
|
|
6
4
|
errorOnInvalidContent?: boolean;
|
|
7
5
|
};
|
|
8
|
-
export declare function elementFromString(value: string): HTMLElement;
|
|
9
|
-
export declare function createNodeFromHTML(content: string, schema: Schema, options?: CreateNodeFromContentOptions): ProseMirrorNode | Fragment;
|
|
10
6
|
export declare function createNodeFromObject(content: Content | ProseMirrorNode | Fragment, schema: Schema, options?: CreateNodeFromContentOptions): ProseMirrorNode | Fragment;
|
|
11
|
-
export declare function createNodeFromContent(content:
|
|
7
|
+
export declare function createNodeFromContent(content: Content | ProseMirrorNode | Fragment, schema: Schema, options?: CreateNodeFromContentOptions): ProseMirrorNode | Fragment;
|
|
12
8
|
//# sourceMappingURL=createNodeFromContent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createNodeFromContent.d.ts","sourceRoot":"","sources":["../../../../src/editor/src/utilities/createNodeFromContent.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"createNodeFromContent.d.ts","sourceRoot":"","sources":["../../../../src/editor/src/utilities/createNodeFromContent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,IAAI,IAAI,eAAe,EACvB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,4BAA4B,GAAG;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,QAAQ,EAC7C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,4BAA4B,GACrC,eAAe,GAAG,QAAQ,CAiC5B;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,QAAQ,EAC7C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,4BAA4B,GACrC,eAAe,GAAG,QAAQ,CAY5B"}
|
|
@@ -1,105 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const removeWhitespaces = (node) => {
|
|
3
|
-
const children = node.childNodes;
|
|
4
|
-
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
5
|
-
const child = children[i];
|
|
6
|
-
if (child.nodeType === 3 && child.nodeValue &&
|
|
7
|
-
/^(\n\s\s|\n)$/.test(child.nodeValue)) {
|
|
8
|
-
node.removeChild(child);
|
|
9
|
-
}
|
|
10
|
-
else if (child.nodeType === 1) {
|
|
11
|
-
removeWhitespaces(child);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return node;
|
|
15
|
-
};
|
|
16
|
-
export function elementFromString(value) {
|
|
17
|
-
// add a wrapper to preserve leading and trailing whitespace
|
|
18
|
-
const wrappedValue = `<body>${value}</body>`;
|
|
19
|
-
const html = new globalThis.DOMParser().parseFromString(wrappedValue, 'text/html').body;
|
|
20
|
-
return removeWhitespaces(html);
|
|
21
|
-
}
|
|
22
|
-
// TODO: refactor to converters?
|
|
23
|
-
export function createNodeFromHTML(content, schema, options) {
|
|
24
|
-
options = {
|
|
25
|
-
slice: true,
|
|
26
|
-
parseOptions: {},
|
|
27
|
-
...options,
|
|
28
|
-
};
|
|
29
|
-
// Check for invalid content
|
|
30
|
-
if (options.errorOnInvalidContent) {
|
|
31
|
-
let hasInvalidContent = false;
|
|
32
|
-
let invalidContent = '';
|
|
33
|
-
// A copy of the current schema with a catch-all node at the end
|
|
34
|
-
const contentCheckSchema = new Schema({
|
|
35
|
-
topNode: schema.spec.topNode,
|
|
36
|
-
marks: schema.spec.marks,
|
|
37
|
-
// Prosemirror's schemas are executed such that: the last to execute, matches last
|
|
38
|
-
// This means that we can add a catch-all node at the end of the schema to catch any content that we don't know how to handle
|
|
39
|
-
nodes: schema.spec.nodes.append({
|
|
40
|
-
__unknown__catch__all__node: {
|
|
41
|
-
content: 'inline*',
|
|
42
|
-
group: 'block',
|
|
43
|
-
parseDOM: [
|
|
44
|
-
{
|
|
45
|
-
tag: '*',
|
|
46
|
-
getAttrs: (e) => {
|
|
47
|
-
// If this is ever called, we know that the content has something that we don't know how to handle in the schema
|
|
48
|
-
hasInvalidContent = true;
|
|
49
|
-
// Try to stringify the element for a more helpful error message
|
|
50
|
-
invalidContent = typeof e === 'string' ? e : e.outerHTML;
|
|
51
|
-
return null;
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
if (options.slice) {
|
|
59
|
-
DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
|
|
63
|
-
}
|
|
64
|
-
if (options.errorOnInvalidContent && hasInvalidContent) {
|
|
65
|
-
throw new Error('Invalid HTML content', {
|
|
66
|
-
cause: new Error(`Invalid element found: ${invalidContent}`),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const parser = DOMParser.fromSchema(schema);
|
|
71
|
-
if (options.slice) {
|
|
72
|
-
return parser.parseSlice(elementFromString(content), options.parseOptions)
|
|
73
|
-
.content;
|
|
74
|
-
}
|
|
75
|
-
return parser.parse(elementFromString(content), options.parseOptions);
|
|
76
|
-
}
|
|
1
|
+
import { Fragment, Node as ProseMirrorNode, } from 'prosemirror-model';
|
|
77
2
|
export function createNodeFromObject(content, schema, options) {
|
|
78
|
-
options = {
|
|
79
|
-
slice: true,
|
|
80
|
-
parseOptions: {},
|
|
81
|
-
...options,
|
|
82
|
-
};
|
|
83
3
|
try {
|
|
84
4
|
// if the JSON Content is an array of nodes, create a fragment for each node
|
|
85
5
|
if (Array.isArray(content) && content.length > 0) {
|
|
86
6
|
return Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
|
|
87
7
|
}
|
|
88
8
|
const node = schema.nodeFromJSON(content);
|
|
89
|
-
if (options
|
|
9
|
+
if (options?.errorOnInvalidContent) {
|
|
90
10
|
node.check();
|
|
91
11
|
}
|
|
92
12
|
return node;
|
|
93
13
|
}
|
|
94
14
|
catch (error) {
|
|
95
|
-
if (options
|
|
15
|
+
if (options?.errorOnInvalidContent) {
|
|
96
16
|
throw new Error('Invalid JSON content', {
|
|
97
17
|
cause: error,
|
|
98
18
|
});
|
|
99
19
|
}
|
|
100
20
|
console.warn('Invalid content.', 'Passed value:', content, 'Error:', error);
|
|
101
|
-
|
|
102
|
-
return createNodeFromHTML('', schema, options);
|
|
21
|
+
return schema.topNodeType.createAndFill(null, []);
|
|
103
22
|
}
|
|
104
23
|
}
|
|
105
24
|
export function createNodeFromContent(content, schema, options) {
|
|
@@ -107,12 +26,8 @@ export function createNodeFromContent(content, schema, options) {
|
|
|
107
26
|
return content;
|
|
108
27
|
}
|
|
109
28
|
const isJSONContent = typeof content === 'object' && content !== null;
|
|
110
|
-
const isTextContent = typeof content === 'string';
|
|
111
29
|
if (isJSONContent) {
|
|
112
30
|
createNodeFromObject(content, schema, options);
|
|
113
31
|
}
|
|
114
|
-
|
|
115
|
-
return createNodeFromHTML(content, schema, options);
|
|
116
|
-
}
|
|
117
|
-
return createNodeFromHTML('', schema, options);
|
|
32
|
+
return schema.topNodeType.createAndFill(null, []);
|
|
118
33
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Schema } from 'prosemirror-model';
|
|
2
|
-
import { type Converter, Extension } from '../../editor/src/mod.js';
|
|
2
|
+
import { type Converter, type CoreEditor, Extension } from '../../editor/src/mod.js';
|
|
3
|
+
export interface OdtConfig {
|
|
4
|
+
linkFromRewriter?(href: string): string;
|
|
5
|
+
}
|
|
3
6
|
export declare class ExtensionOdt extends Extension {
|
|
7
|
+
protected config: OdtConfig;
|
|
4
8
|
name: string;
|
|
5
|
-
|
|
9
|
+
constructor(config?: OdtConfig);
|
|
10
|
+
getConverters(editor: CoreEditor, schema: Schema): Record<string, Converter>;
|
|
6
11
|
}
|
|
7
12
|
//# sourceMappingURL=ExtensionOdt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionOdt.d.ts","sourceRoot":"","sources":["../../../src/extension-odt/src/ExtensionOdt.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ExtensionOdt.d.ts","sourceRoot":"","sources":["../../../src/extension-odt/src/ExtensionOdt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMrF,MAAM,WAAW,SAAS;IACxB,gBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACzC;AAED,qBAAa,YAAa,SAAQ,SAAS;IAG7B,SAAS,CAAC,MAAM,EAAE,SAAS;IAFvC,IAAI,SAAS;gBAES,MAAM,GAAE,SAAc;IAI5C,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;CAuC7E"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { Extension } from '../../editor/src/mod.js';
|
|
2
2
|
import { parse_content, parse_styles, unzip } from '@kerebron/odt-wasm';
|
|
3
3
|
import { OdtParser } from './OdtParser.js';
|
|
4
|
+
import { getDefaultsPostProcessFilters } from './postprocess/postProcess.js';
|
|
4
5
|
export class ExtensionOdt extends Extension {
|
|
5
|
-
constructor() {
|
|
6
|
-
super(
|
|
6
|
+
constructor(config = {}) {
|
|
7
|
+
super(config);
|
|
8
|
+
Object.defineProperty(this, "config", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true,
|
|
12
|
+
value: config
|
|
13
|
+
});
|
|
7
14
|
Object.defineProperty(this, "name", {
|
|
8
15
|
enumerable: true,
|
|
9
16
|
configurable: true,
|
|
@@ -11,7 +18,8 @@ export class ExtensionOdt extends Extension {
|
|
|
11
18
|
value: 'odt'
|
|
12
19
|
});
|
|
13
20
|
}
|
|
14
|
-
getConverters(schema) {
|
|
21
|
+
getConverters(editor, schema) {
|
|
22
|
+
const config = this.config;
|
|
15
23
|
return {
|
|
16
24
|
'application/vnd.oasis.opendocument.text': {
|
|
17
25
|
fromDoc(document) {
|
|
@@ -23,8 +31,18 @@ export class ExtensionOdt extends Extension {
|
|
|
23
31
|
const contentTree = parse_content(files.get('content.xml'));
|
|
24
32
|
// console.log(JSON.stringify(stylesTree, null, 2).split('\n').slice(0, 20).join('\n'));
|
|
25
33
|
// console.log(JSON.stringify(contentTree, null, 2).split('\n').slice(0, 20).join('\n'));
|
|
26
|
-
const
|
|
27
|
-
|
|
34
|
+
const subEditor = editor.clone();
|
|
35
|
+
const parser = new OdtParser(subEditor.schema, config);
|
|
36
|
+
const doc = parser.parse({ ...files, contentTree, stylesTree });
|
|
37
|
+
const filterCommands = getDefaultsPostProcessFilters();
|
|
38
|
+
if (filterCommands.length > 0) {
|
|
39
|
+
subEditor.setDocument(doc);
|
|
40
|
+
for (const filter of filterCommands) {
|
|
41
|
+
filter(subEditor.state, tr => subEditor.dispatchTransaction(tr));
|
|
42
|
+
}
|
|
43
|
+
return subEditor.getDocument();
|
|
44
|
+
}
|
|
45
|
+
return doc;
|
|
28
46
|
},
|
|
29
47
|
},
|
|
30
48
|
};
|
|
@@ -1,22 +1,91 @@
|
|
|
1
|
-
import { Attrs, Node, Schema } from 'prosemirror-model';
|
|
1
|
+
import { Attrs, Mark, MarkType, Node, NodeType, Schema } from 'prosemirror-model';
|
|
2
2
|
interface OdtElement {
|
|
3
3
|
}
|
|
4
4
|
export interface ParseSpec {
|
|
5
5
|
node?: string;
|
|
6
6
|
children?: (node: OdtElement) => OdtElement[];
|
|
7
|
+
custom?: (state: OdtParseState, element?: OdtElement) => void;
|
|
7
8
|
text?: (node: OdtElement) => string;
|
|
8
|
-
block?: string | ((node: OdtElement) => string);
|
|
9
|
+
block?: string | ((node: OdtElement, style: any) => [string]);
|
|
9
10
|
mark?: string;
|
|
10
11
|
attrs?: Attrs | null;
|
|
11
12
|
getAttrs?: (token: OdtElement, style: Style) => Attrs | null;
|
|
12
13
|
ignore?: boolean;
|
|
13
14
|
}
|
|
15
|
+
interface ListStyle {
|
|
16
|
+
'@name': string;
|
|
17
|
+
}
|
|
14
18
|
interface Style {
|
|
15
19
|
'@name': string;
|
|
16
20
|
}
|
|
21
|
+
interface StylesTree {
|
|
22
|
+
styles: {
|
|
23
|
+
'list-style': Array<ListStyle>;
|
|
24
|
+
'style': Array<Style>;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
interface AutomaticStyles {
|
|
28
|
+
'style': Array<Style>;
|
|
29
|
+
}
|
|
30
|
+
interface TextMark {
|
|
31
|
+
markName: string;
|
|
32
|
+
markAttributes: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
declare class OdtParseState {
|
|
35
|
+
readonly schema: Schema;
|
|
36
|
+
readonly tokens: {
|
|
37
|
+
[name: string]: ParseSpec;
|
|
38
|
+
};
|
|
39
|
+
private readonly stylesTree;
|
|
40
|
+
private readonly automaticStyles;
|
|
41
|
+
stack: {
|
|
42
|
+
type: NodeType;
|
|
43
|
+
attrs: Attrs | null;
|
|
44
|
+
content: Node[];
|
|
45
|
+
marks: readonly Mark[];
|
|
46
|
+
}[];
|
|
47
|
+
textMarks: Set<TextMark>;
|
|
48
|
+
nextTextMarks: Set<TextMark>;
|
|
49
|
+
constructor(schema: Schema, tokens: {
|
|
50
|
+
[name: string]: ParseSpec;
|
|
51
|
+
}, stylesTree: StylesTree, automaticStyles: AutomaticStyles);
|
|
52
|
+
top(): {
|
|
53
|
+
type: NodeType;
|
|
54
|
+
attrs: Attrs | null;
|
|
55
|
+
content: Node[];
|
|
56
|
+
marks: readonly Mark[];
|
|
57
|
+
};
|
|
58
|
+
push(elt: Node): void;
|
|
59
|
+
addText(text: string): void;
|
|
60
|
+
openMark(mark: Mark): MarkType;
|
|
61
|
+
closeMark(mark: MarkType): void;
|
|
62
|
+
addNode(type: NodeType, attrs: Attrs | null, content?: readonly Node[], marks?: readonly Mark[]): Node | null;
|
|
63
|
+
openNode(type: NodeType, attrs: Attrs | null): void;
|
|
64
|
+
closeNode(marks?: readonly Mark[]): Node | null;
|
|
65
|
+
handleElement(nodeType: string, element: OdtElement): void;
|
|
66
|
+
}
|
|
67
|
+
interface Config {
|
|
68
|
+
linkFromRewriter?(href: string): string;
|
|
69
|
+
}
|
|
70
|
+
declare class ListNumbering {
|
|
71
|
+
levels: {
|
|
72
|
+
[level: number]: number;
|
|
73
|
+
};
|
|
74
|
+
levelNodes: {
|
|
75
|
+
[level: number]: Node;
|
|
76
|
+
};
|
|
77
|
+
constructor();
|
|
78
|
+
clearAbove(level: number): void;
|
|
79
|
+
setLevelNode(level: number, node: Node): void;
|
|
80
|
+
}
|
|
17
81
|
export declare class OdtParser {
|
|
18
82
|
private readonly schema;
|
|
19
|
-
|
|
83
|
+
private readonly config;
|
|
84
|
+
listStack: never[];
|
|
85
|
+
listNumberings: Map<string, ListNumbering>;
|
|
86
|
+
private lastNumbering?;
|
|
87
|
+
preserveMinLevel: number;
|
|
88
|
+
constructor(schema: Schema, config?: Config);
|
|
20
89
|
parse(files: any): Node;
|
|
21
90
|
}
|
|
22
91
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OdtParser.d.ts","sourceRoot":"","sources":["../../../src/extension-odt/src/OdtParser.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,
|
|
1
|
+
{"version":3,"file":"OdtParser.d.ts","sourceRoot":"","sources":["../../../src/extension-odt/src/OdtParser.ts"],"names":[],"mappings":"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"}
|