Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit 0b6ee6b

Browse files
committed
handle insertHtml
1 parent 63a4c1b commit 0b6ee6b

File tree

5 files changed

+74
-89
lines changed

5 files changed

+74
-89
lines changed

packages/bundle-odoo-website-editor/odoo-integration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { LinkFormat } from '../plugin-link/src/LinkFormat';
1111
import { Attributes } from '../plugin-xml/src/Attributes';
1212
import { OdooStructureNode } from '../plugin-odoo/src/OdooStructureNode';
1313
import { Inline } from '../plugin-inline/src/Inline';
14+
import { DomHelpers } from '../plugin-dom-helpers/src/DomHelpers';
1415
import { getOdooCommands } from '../plugin-odoo/src/OdooCommands';
1516

1617
export {
@@ -29,4 +30,5 @@ export {
2930
Attributes,
3031
OdooStructureNode,
3132
Inline,
33+
DomHelpers,
3234
};

packages/plugin-char/src/Char.ts

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,11 @@ import { Parser } from '../../plugin-parser/src/Parser';
1010
import { Renderer } from '../../plugin-renderer/src/Renderer';
1111
import { Attributes } from '../../plugin-xml/src/Attributes';
1212

13-
import { Point, RelativePosition, VNode } from '../../core/src/VNodes/VNode';
14-
1513
export interface InsertTextParams extends CommandParams {
1614
text: string;
1715
select?: boolean;
1816
formats?: Modifiers;
1917
}
20-
export interface InsertHtmlParams extends CommandParams {
21-
rangePoint?: Point;
22-
html: string;
23-
}
2418

2519
export class Char<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T> {
2620
static dependencies = [Inline];
@@ -32,9 +26,6 @@ export class Char<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
3226
insertText: {
3327
handler: this.insertText,
3428
},
35-
insertHtml: {
36-
handler: this.insertHtml,
37-
},
3829
};
3930

4031
//--------------------------------------------------------------------------
@@ -79,41 +70,4 @@ export class Char<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
7970
}
8071
inline.resetCache();
8172
}
82-
async insertHtml(params: InsertHtmlParams): Promise<VNode[]> {
83-
const parser = this.editor.plugins.get(Parser);
84-
const domParser = parser && parser.engines['dom/html'];
85-
if (!domParser) {
86-
// TODO: remove this when the editor can be instantiated on
87-
// something else than DOM.
88-
throw new Error(`No DOM parser installed.`);
89-
}
90-
const div = document.createElement('div');
91-
div.innerHTML = params.html;
92-
const parsedEditable = await domParser.parse(div);
93-
const newNodes = parsedEditable[0].children();
94-
95-
// Remove the contents of the range if needed.
96-
// todo: use Point or Range but not both.
97-
const range = params.context.range;
98-
if (!range.isCollapsed()) {
99-
range.empty();
100-
}
101-
if (params.rangePoint) {
102-
const [node, position] = params.rangePoint;
103-
switch (position) {
104-
case RelativePosition.BEFORE:
105-
newNodes.forEach(node.before.bind(node));
106-
break;
107-
case RelativePosition.AFTER:
108-
[...newNodes].reverse().forEach(node.after.bind(node));
109-
break;
110-
case RelativePosition.INSIDE:
111-
node.append(...newNodes);
112-
break;
113-
}
114-
} else {
115-
newNodes.forEach(range.start.before.bind(range.start));
116-
}
117-
return newNodes;
118-
}
11973
}

packages/plugin-devtools/test/devtools.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,6 @@ describe('Plugin: DevTools', () => {
848848
'deleteForward',
849849
'hide',
850850
'insert',
851-
'insertHtml',
852851
'insertParagraphBreak',
853852
'insertText',
854853
'selectAll',

packages/plugin-dom-helpers/src/DomHelpers.ts

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
6262
*/
6363
addClass(params: { domNode: Node | Node[]; class: string | string[] }): void {
6464
const classes = Array.isArray(params.class) ? params.class : [params.class];
65-
for (const node of this._getNodes(params.domNode)) {
65+
for (const node of this.getNodes(params.domNode)) {
6666
node.modifiers.get(Attributes).classList.add(...classes);
6767
}
6868
}
@@ -73,7 +73,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
7373
*/
7474
removeClass(params: { domNode: Node | Node[]; class: string | string[] }): void {
7575
const classes = Array.isArray(params.class) ? params.class : [params.class];
76-
for (const node of this._getNodes(params.domNode)) {
76+
for (const node of this.getNodes(params.domNode)) {
7777
node.modifiers.get(Attributes).classList.remove(...classes);
7878
}
7979
}
@@ -85,7 +85,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
8585
*/
8686
toggleClass(params: { domNode: Node | Node[]; class: string }): void {
8787
const classes = Array.isArray(params.class) ? params.class : [params.class];
88-
for (const node of this._getNodes(params.domNode)) {
88+
for (const node of this.getNodes(params.domNode)) {
8989
node.modifiers.get(Attributes).classList.toggle(...classes);
9090
}
9191
}
@@ -95,7 +95,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
9595
* @param params
9696
*/
9797
setAttribute(params: { domNode: Node | Node[]; name: string; value: string }): void {
98-
for (const node of this._getNodes(params.domNode)) {
98+
for (const node of this.getNodes(params.domNode)) {
9999
node.modifiers.get(Attributes).set(params.name, params.value);
100100
}
101101
}
@@ -110,7 +110,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
110110
value: string;
111111
important?: boolean;
112112
}): void {
113-
for (const node of this._getNodes(params.domNode)) {
113+
for (const node of this.getNodes(params.domNode)) {
114114
const value = params.important ? params.value + ' !important' : params.value;
115115
node.modifiers.get(Attributes).style.set(params.name, value);
116116
}
@@ -121,7 +121,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
121121
* @param params
122122
*/
123123
remove(params: { domNode: Node | Node[] }): void {
124-
for (const node of this._getNodes(params.domNode)) {
124+
for (const node of this.getNodes(params.domNode)) {
125125
node.remove();
126126
}
127127
}
@@ -131,7 +131,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
131131
* @param params
132132
*/
133133
empty(params: { domNode: Node | Node[] }): void {
134-
for (const node of this._getNodes(params.domNode)) {
134+
for (const node of this.getNodes(params.domNode)) {
135135
node.empty();
136136
}
137137
}
@@ -141,7 +141,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
141141
* @param params
142142
*/
143143
async replace(params: { domNodes: Node | Node[]; html: string }): Promise<void> {
144-
const nodes = this._getNodes(params.domNodes);
144+
const nodes = this.getNodes(params.domNodes);
145145
const parsedNodes = await this._parseHTMLString(params.html);
146146
const firstNode = nodes[0];
147147
for (const parsedNode of parsedNodes) {
@@ -157,7 +157,7 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
157157
* @param params
158158
*/
159159
async wrap(params: { domContainer: Node; html: string }): Promise<void> {
160-
const container = this._getNodes(params.domContainer)[0];
160+
const container = this.getNodes(params.domContainer)[0];
161161
if (!(container instanceof ContainerNode)) {
162162
throw new Error(
163163
'The provided container must be a ContainerNode in the Jabberwock structure.',
@@ -174,8 +174,8 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
174174
* @param params
175175
*/
176176
moveBefore(params: { fromDomNode: Node; toDomNode: Node }): void {
177-
const toNode = this._getNodes(params.toDomNode)[0];
178-
for (const fromNode of this._getNodes(params.fromDomNode)) {
177+
const toNode = this.getNodes(params.toDomNode)[0];
178+
for (const fromNode of this.getNodes(params.fromDomNode)) {
179179
fromNode.before(toNode);
180180
}
181181
}
@@ -185,12 +185,71 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
185185
* @param params
186186
*/
187187
moveAfter(params: { fromDomNode: Node; toDomNode: Node }): void {
188-
const toNodes = this._getNodes(params.toDomNode);
188+
const toNodes = this.getNodes(params.toDomNode);
189189
const toNode = toNodes[toNodes.length - 1];
190-
for (const fromNode of this._getNodes(params.fromDomNode).reverse()) {
190+
for (const fromNode of this.getNodes(params.fromDomNode).reverse()) {
191191
fromNode.after(toNode);
192192
}
193193
}
194+
/**
195+
* Insert html content before, after or inside a DOM Node. If no DOM Node
196+
* was provided, empty the range and insert the html content before the it.
197+
*
198+
* @param params
199+
*/
200+
async insertHtml(params: {
201+
html: string;
202+
domNode?: Node;
203+
position?: RelativePosition;
204+
}): Promise<VNode[]> {
205+
let nodes: VNode[];
206+
let position: RelativePosition;
207+
if (params.domNode) {
208+
nodes = this.getNodes(params.domNode);
209+
position = params.position || RelativePosition.BEFORE;
210+
} else {
211+
this.editor.selection.range.empty();
212+
nodes = [this.editor.selection.range.start];
213+
position = RelativePosition.BEFORE;
214+
}
215+
const parsedNodes = await this._parseHTMLString(params.html);
216+
switch (position.toUpperCase()) {
217+
case RelativePosition.BEFORE.toUpperCase():
218+
for (const parsedNode of parsedNodes) {
219+
nodes[0].before(parsedNode);
220+
}
221+
break;
222+
case RelativePosition.AFTER.toUpperCase():
223+
for (const parsedNode of parsedNodes.reverse()) {
224+
nodes[nodes.length - 1].after(parsedNode);
225+
}
226+
break;
227+
case RelativePosition.INSIDE.toUpperCase():
228+
for (const parsedNode of parsedNodes.reverse()) {
229+
nodes[nodes.length - 1].append(parsedNode);
230+
}
231+
break;
232+
}
233+
return parsedNodes;
234+
}
235+
/**
236+
* Return the `VNode`(s) matching a DOM Node or a list of DOM Nodes.
237+
*
238+
* @param domNode
239+
*/
240+
getNodes(domNode: Node | Node[]): VNode[] {
241+
const layout = this.editor.plugins.get(Layout);
242+
const domEngine = layout.engines.dom as DomLayoutEngine;
243+
let nodes: VNode[] = [];
244+
if (Array.isArray(domNode)) {
245+
for (const oneDomNode of domNode) {
246+
nodes.push(...domEngine.getNodes(oneDomNode));
247+
}
248+
} else {
249+
nodes = domEngine.getNodes(domNode);
250+
}
251+
return nodes;
252+
}
194253

195254
//--------------------------------------------------------------------------
196255
// Private
@@ -208,17 +267,4 @@ export class DomHelpers<T extends JWPluginConfig = JWPluginConfig> extends JWPlu
208267
div.innerHTML = content;
209268
return (await domParser.parse(div))[0].children();
210269
}
211-
_getNodes(domNode: Node | Node[]): VNode[] {
212-
const layout = this.editor.plugins.get(Layout);
213-
const domEngine = layout.engines.dom as DomLayoutEngine;
214-
let nodes: VNode[] = [];
215-
if (Array.isArray(domNode)) {
216-
for (const oneDomNode of domNode) {
217-
nodes.push(...domEngine.getNodes(oneDomNode));
218-
}
219-
} else {
220-
nodes = domEngine.getNodes(domNode);
221-
}
222-
return nodes;
223-
}
224270
}

packages/plugin-odoo/src/OdooCommands.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import JWEditor from '../../core/src/JWEditor';
2-
import { RelativePosition } from '../../core/src/VNodes/VNode';
3-
import { Char, InsertHtmlParams } from '../../plugin-char/src/Char';
42
import { DomLayoutEngine } from '../../plugin-dom-layout/src/ui/DomLayoutEngine';
53
import { Layout } from '../../plugin-layout/src/Layout';
64

@@ -9,25 +7,11 @@ interface ExecCommandHelpers {
97
[key: string]: (...args: any[]) => void;
108
}
119

12-
export type HtmlPoint = [Node, RelativePosition];
13-
1410
export function getOdooCommands(editor: JWEditor): ExecCommandHelpers {
1511
const layout = editor.plugins.get(Layout);
1612
const domEngine = layout.engines.dom as DomLayoutEngine;
1713

1814
const odooCommands = {
19-
// todo: sometimes i need to append. Because the implementation of the insertHTML append
20-
// it when the RelativePosition is 'inside', it work. But this is unclear that it will
21-
// append.
22-
// Change the API to have a clearer distinction and allowing to append/prepend;
23-
async insertHtml(rangePoint: HtmlPoint, html: string): Promise<void> {
24-
const node = domEngine.getNodes(rangePoint[0])[0];
25-
const params: InsertHtmlParams = {
26-
rangePoint: [node, rangePoint[1]],
27-
html,
28-
};
29-
return await editor.execCommand<Char>('insertHtml', params);
30-
},
3115
exists(domNode: Node): boolean {
3216
return !!domEngine.getNodes(domNode);
3317
},

0 commit comments

Comments
 (0)