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

Commit a2408b6

Browse files
Zyntondmo-odoo
authored andcommitted
[REF] Modifiers: introduce Modifiers.get
This also changes the signature of `renderAttributes` so it can get the given attributes class on the given node's modifiers.
1 parent eeacd21 commit a2408b6

File tree

23 files changed

+84
-131
lines changed

23 files changed

+84
-131
lines changed

packages/core/src/Modifiers.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,13 @@ export class Modifiers {
4949
}
5050
/**
5151
* Return the first modifier in the array that is an instance of the given
52-
* modifier class, if any. If the modifier passed is a modifier instance,
53-
* return it if it was present in the array.
52+
* Modifier class, if any.
53+
* If the modifier passed is a Modifier instance, return it if it was
54+
* present in the array.
55+
* This also functions as a proxy to the native `find` method of `Array`,
56+
* for `this._contents`.
5457
*
58+
* @see Array.find
5559
* @param modifier
5660
*/
5761
find<T extends Modifier>(callback: (modifier: T) => boolean): T;
@@ -71,10 +75,29 @@ export class Modifiers {
7175
return this._contents.find(modifier) as T;
7276
}
7377
}
78+
/**
79+
* Return the first modifier in the array that is an instance of the given
80+
* modifier class or create one, append it and return it.
81+
* If the modifier passed is a modifier instance, return it if it was
82+
* present in the array.
83+
*
84+
* @param modifier
85+
*/
86+
get<T extends Modifier>(modifier: T | Constructor<T>): T {
87+
let found = this.find(modifier);
88+
if (!found && isConstructor<typeof Modifier>(modifier, Modifier)) {
89+
found = new modifier();
90+
this.append(found);
91+
}
92+
return found;
93+
}
7494
/**
7595
* Return all modifiers in the array that are an instance of the given
7696
* modifier class, if any.
97+
* This also functions as a proxy to the native `filter` method of `Array`,
98+
* for `this._contents`.
7799
*
100+
* @see Array.filter
78101
* @param modifier
79102
*/
80103
filter<T extends Modifier>(

packages/plugin-align/src/Align.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ export class Align<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T
6262
* @param [type]
6363
*/
6464
static isAligned(node: VNode, type?: AlignType): boolean {
65-
if (typeof node.modifiers.find(Attributes)?.get('style') !== 'string') {
66-
return false;
67-
} else {
68-
const styles = node.modifiers
69-
.find(Attributes)
70-
?.get('style')
71-
.split(';');
65+
const styles = node.modifiers
66+
.find(Attributes)
67+
?.get('style')
68+
?.split(';');
69+
if (styles) {
7270
const align = styles.find(style => style.includes('text-align'));
7371
return type ? align?.includes(type) : !!align;
72+
} else {
73+
return false;
7474
}
7575
}
7676
/**
@@ -86,11 +86,11 @@ export class Align<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T
8686

8787
// Compute current alignment.
8888
let currentAlignment: string;
89-
if (typeof alignedAncestor?.modifiers.find(Attributes)?.get('style') === 'string') {
90-
const styles = alignedAncestor.modifiers
91-
.find(Attributes)
92-
.get('style')
93-
.split(';');
89+
const styles = alignedAncestor?.modifiers
90+
?.find(Attributes)
91+
?.get('style')
92+
?.split(';');
93+
if (styles) {
9494
const alignment = styles.find(style => style.includes('text-align'));
9595
currentAlignment = alignment?.replace(/text-align\s*:|;/, '').trim();
9696
}

packages/plugin-char/src/CharFormatHtmlDomRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ export class CharFormatHtmlDomRenderer extends FormatDomRenderer {
2121
// attributes.
2222
let rendering: Node[];
2323
const attributes = node.modifiers.find(Attributes);
24-
if (attributes && attributes.length) {
24+
if (attributes?.length) {
2525
const span = document.createElement('span');
26-
this.engine.renderAttributes(attributes, span);
26+
this.engine.renderAttributes(Attributes, node, span);
2727
textNode.forEach(child => span.appendChild(child));
2828
rendering = [span];
2929
} else {

packages/plugin-dom-editable/src/DomEditable.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,11 @@ export class DomEditable<T extends DomEditableConfig = DomEditableConfig> extend
3838
// Semantic elements are inline by default.
3939
// We need to guarantee it's a block so it can contain
4040
// other blocks.
41-
let attributes = root.modifiers.find(Attributes);
42-
if (!attributes) {
43-
attributes = new Attributes();
44-
root.modifiers.append(attributes);
45-
}
46-
attributes.set('style', 'display: block;');
41+
root.modifiers.get(Attributes).set('style', 'display: block;');
4742
}
4843
root.editable = false;
4944
root.breakable = false;
50-
let attributes = root.modifiers.find(Attributes);
51-
if (!attributes) {
52-
attributes = new Attributes();
53-
root.modifiers.append(attributes);
54-
}
55-
root.modifiers.find(Attributes).set('contentEditable', 'true');
45+
root.modifiers.get(Attributes).set('contentEditable', 'true');
5646

5747
if (!this.editor.selection.anchor.parent && this.configuration.autoFocus) {
5848
this.editor.selection.setAt(root, RelativePosition.INSIDE);

packages/plugin-fontawesome/src/FontAwesomeHtmlDomRenderer.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ export class FontAwesomeHtmlDomRenderer extends AbstractRenderer<Node[]> {
1212

1313
async render(node: FontAwesomeNode): Promise<Node[]> {
1414
const fontawesome = document.createElement(node.htmlTag);
15-
const attributes = node.modifiers.find(Attributes);
16-
if (attributes) {
17-
this.engine.renderAttributes(attributes, fontawesome);
18-
}
15+
this.engine.renderAttributes(Attributes, node, fontawesome);
1916
// Surround the fontawesome with two invisible characters so the
2017
// selection can navigate around it.
2118
return [

packages/plugin-html/src/DefaultHtmlDomRenderer.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ export class DefaultHtmlDomRenderer extends AbstractRenderer<Node[]> {
2222
nodeName = node.constructor.name.toUpperCase() + '-' + node.id;
2323
}
2424
const element = document.createElement(nodeName);
25-
const attributes = node.modifiers.find(Attributes);
26-
if (attributes) {
27-
this.engine.renderAttributes(attributes, element);
28-
}
25+
this.engine.renderAttributes(Attributes, node, element);
2926
domNode = element;
3027
}
3128

packages/plugin-html/src/HtmlDomRenderingEngine.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ export class HtmlDomRenderingEngine extends RenderingEngine<Node[]> {
88
static readonly id = 'dom/html';
99
static readonly defaultRenderer = DefaultHtmlDomRenderer;
1010
/**
11-
* Render the attributes of the given VNode onto the given DOM Element.
11+
* Render the attributes (of the given Class extending Attributes) of the
12+
* given VNode onto the given DOM Element.
1213
*
14+
* @param Class
1315
* @param node
16+
* @param element
1417
*/
15-
renderAttributes(attributes: Attributes, element: Element): void {
16-
for (const name of attributes.keys().sort()) {
17-
const value = attributes.get(name);
18-
element.setAttribute(name, value);
18+
renderAttributes<T extends typeof Attributes>(Class: T, node: VNode, element: Element): void {
19+
const attributes = node.modifiers.find(Class);
20+
if (attributes) {
21+
for (const name of attributes.keys().sort()) {
22+
const value = attributes.get(name);
23+
element.setAttribute(name, value);
24+
}
1925
}
2026
}
2127
/**

packages/plugin-image/src/ImageHtmlDomRenderer.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ export class ImageHtmlDomRenderer extends AbstractRenderer<Node[]> {
1010

1111
async render(node: ImageNode): Promise<Node[]> {
1212
const image = document.createElement('img');
13-
const attributes = node.modifiers.find(Attributes);
14-
if (attributes) {
15-
this.engine.renderAttributes(attributes, image);
16-
}
13+
this.engine.renderAttributes(Attributes, node, image);
1714
return [image];
1815
}
1916
}

packages/plugin-inline/src/Format.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class Format extends Modifier {
3636
const attributes = this.modifiers.find(Attributes);
3737
if (attributes) {
3838
for (const name of attributes.keys()) {
39-
node.setAttribute(name, this.modifiers.find(Attributes).get(name));
39+
node.setAttribute(name, attributes.get(name));
4040
}
4141
}
4242
return node;

packages/plugin-inline/src/Inline.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,12 @@ export class Inline<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<
7272
const format = inline.modifiers.find(FormatClass);
7373
// Apply the attributes of the format we're about to remove to
7474
// the inline itself.
75-
const attributes = inline.modifiers.find(Attributes);
75+
const attributes = inline.modifiers.get(Attributes);
7676
const matchingFormatAttributes = format.modifiers.find(Attributes);
77-
if (attributes && matchingFormatAttributes) {
77+
if (matchingFormatAttributes) {
7878
for (const key of matchingFormatAttributes.keys()) {
7979
attributes.set(key, matchingFormatAttributes.get(key));
8080
}
81-
} else if (matchingFormatAttributes) {
82-
inline.modifiers.append(matchingFormatAttributes.clone());
8381
}
8482
// Remove the format.
8583
inline.modifiers.remove(format);
@@ -88,7 +86,7 @@ export class Inline<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<
8886
// If there is at least one char in the range without the format
8987
// `FormatClass`, set the format for all nodes.
9088
for (const inline of selectedInlines) {
91-
if (!inline.modifiers.find(f => f instanceof FormatClass)) {
89+
if (!inline.modifiers.find(FormatClass)) {
9290
new FormatClass().applyTo(inline);
9391
}
9492
}
@@ -100,14 +98,12 @@ export class Inline<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<
10098
if (!this.cache.modifiers) {
10199
this.cache.modifiers = this.getCurrentModifiers(range);
102100
}
103-
return !!this.cache.modifiers.find(format => format instanceof FormatClass);
101+
return !!this.cache.modifiers.find(FormatClass);
104102
} else {
105103
const selectedInlines = range.selectedNodes(InlineNode);
106104
return (
107105
selectedInlines.length &&
108-
selectedInlines.every(
109-
char => !!char.modifiers.find(format => format instanceof FormatClass),
110-
)
106+
selectedInlines.every(char => !!char.modifiers.find(FormatClass))
111107
);
112108
}
113109
}

0 commit comments

Comments
 (0)