@lesjoursfr/edith 2.1.3 → 2.2.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.
@@ -1,148 +1,4 @@
1
- const eventsNamespace = "edithEvents";
2
- let eventsGuid = 0;
3
-
4
- type EdithEvent = { type: string; ns: Array<string> | null; handler: EventListenerOrEventListenerObject };
5
-
6
- type EdithEvents = {
7
- [key: string]: EdithEvent;
8
- };
9
-
10
- declare global {
11
- interface Window {
12
- edithEvents: EdithEvents;
13
- }
14
- interface Document {
15
- edithEvents: EdithEvents;
16
- }
17
- interface HTMLElement {
18
- edithEvents: EdithEvents;
19
- }
20
- }
21
-
22
1
  export enum Events {
23
2
  modeChanged = "edith-mode-changed",
24
3
  initialized = "edith-initialized",
25
4
  }
26
-
27
- /**
28
- * Parse an event type to separate the type & the namespace
29
- * @param {string} string
30
- */
31
- function parseEventType(string: string): Omit<EdithEvent, "handler"> {
32
- const [type, ...nsArray] = string.split(".");
33
- return {
34
- type,
35
- ns: nsArray ?? null,
36
- };
37
- }
38
-
39
- /**
40
- * Set an event listener on the node.
41
- * @param {Window|Document|HTMLElement} node
42
- * @param {string} events
43
- * @param {Function} handler
44
- */
45
- function addEventListener(
46
- node: Window | Document | HTMLElement,
47
- events: string,
48
- handler: EventListenerOrEventListenerObject
49
- ): void {
50
- if (node[eventsNamespace] === undefined) {
51
- node[eventsNamespace] = {};
52
- }
53
-
54
- for (const event of events.split(" ")) {
55
- const { type, ns } = parseEventType(event);
56
- const handlerGuid = (++eventsGuid).toString(10);
57
- node.addEventListener(type, handler);
58
- node[eventsNamespace][handlerGuid] = { type, ns, handler };
59
- }
60
- }
61
-
62
- /**
63
- * Remove event listeners from the node.
64
- * @param {Window|Document|HTMLElement} node
65
- * @param {string} events
66
- * @param {Function|undefined} handler
67
- */
68
- function removeEventListener(
69
- node: Window | Document | HTMLElement,
70
- events: string,
71
- handler?: EventListenerOrEventListenerObject
72
- ): void {
73
- if (node[eventsNamespace] === undefined) {
74
- node[eventsNamespace] = {};
75
- }
76
-
77
- for (const event of events.split(" ")) {
78
- const { type, ns } = parseEventType(event);
79
-
80
- for (const [guid, handlerObj] of Object.entries(node[eventsNamespace])) {
81
- if (handlerObj.type !== type && type !== "*") {
82
- continue;
83
- }
84
-
85
- if (
86
- (ns === null || handlerObj.ns?.includes(ns[0])) &&
87
- (handler === undefined || (typeof handler === "function" && handler === handlerObj.handler))
88
- ) {
89
- delete node[eventsNamespace][guid];
90
- node.removeEventListener(handlerObj.type, handlerObj.handler);
91
- }
92
- }
93
- }
94
- }
95
-
96
- /**
97
- * Set an event listener on every node.
98
- * @param {Window|Document|HTMLElement|NodeList} nodes
99
- * @param {string} events
100
- * @param {Function} handler
101
- */
102
- export function on(
103
- nodes: Window | Document | HTMLElement | NodeListOf<HTMLElement>,
104
- events: string,
105
- handler: EventListenerOrEventListenerObject
106
- ): void {
107
- if (nodes instanceof NodeList) {
108
- for (const node of nodes) {
109
- addEventListener(node, events, handler);
110
- }
111
- } else {
112
- addEventListener(nodes, events, handler);
113
- }
114
- }
115
-
116
- /**
117
- * Remove event listeners from the node.
118
- * @param {Window|Document|HTMLElement|NodeList} node
119
- * @param {string} events
120
- * @param {Function|undefined} handler
121
- */
122
- export function off(
123
- nodes: Window | Document | HTMLElement | NodeListOf<HTMLElement>,
124
- events: string,
125
- handler?: EventListenerOrEventListenerObject
126
- ): void {
127
- if (nodes instanceof NodeList) {
128
- for (const node of nodes) {
129
- removeEventListener(node, events, handler);
130
- }
131
- } else {
132
- removeEventListener(nodes, events, handler);
133
- }
134
- }
135
-
136
- /**
137
- * Trigger the EdithEvent on the node.
138
- * @param {Window|Document|HTMLElement} node
139
- * @param {string} event
140
- * @param {Object|undefined} payload
141
- */
142
- export function trigger(
143
- node: Window | Document | HTMLElement,
144
- event: string,
145
- payload?: { [key: string]: unknown }
146
- ): void {
147
- node.dispatchEvent(new CustomEvent(event, { detail: payload }));
148
- }
package/src/core/index.ts CHANGED
@@ -1,7 +1,5 @@
1
- export * from "./dom.js";
2
1
  export * from "./edit.js";
3
2
  export * from "./events.js";
4
3
  export * from "./history.js";
5
4
  export * from "./mode.js";
6
5
  export * from "./range.js";
7
- export * from "./throttle.js";
package/src/core/range.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { isHTMLElement, isSelfClosing } from "./dom.js";
1
+ import { isHTMLElement, isSelfClosing } from "@lesjoursfr/browser-tools";
2
2
 
3
3
  /**
4
4
  * @typedef {Object} CurrentSelection
package/src/edith.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Events, addClass, createNodeWith, off, on, removeClass, trigger } from "./core/index.js";
1
+ import { addClass, createNodeWith, off, on, removeClass, trigger } from "@lesjoursfr/browser-tools";
2
+ import { Events } from "./core/index.js";
2
3
  import { DefaultOptions, EdithButtonsOption, EdithOptions, EdithToolbarOption } from "./edith-options.js";
3
4
  import { EdithButton, EdithButtons, EdithEditor } from "./ui/index.js";
4
5
 
package/src/ui/button.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import { createNodeWith } from "@lesjoursfr/browser-tools";
1
2
  import { createPopper } from "@popperjs/core";
2
- import { EditorModes, Events, createNodeWith } from "../core/index.js";
3
+ import { EditorModes, Events } from "../core/index.js";
3
4
  import { EdithButtonsOption } from "../edith-options.js";
4
5
  import { Edith } from "../edith.js";
5
6
 
package/src/ui/editor.ts CHANGED
@@ -1,4 +1,15 @@
1
1
  import { html } from "@codemirror/lang-html";
2
+ import {
3
+ createNodeWith,
4
+ hasClass,
5
+ hasTagName,
6
+ isHTMLElement,
7
+ isSelfClosing,
8
+ isTextNode,
9
+ removeNodesRecursively,
10
+ throttle,
11
+ unwrapNode,
12
+ } from "@lesjoursfr/browser-tools";
2
13
  import { EditorView, basicSetup } from "codemirror";
3
14
  import {
4
15
  EditorModes,
@@ -6,18 +17,10 @@ import {
6
17
  History,
7
18
  cleanPastedHtml,
8
19
  clearSelectionStyle,
9
- createNodeWith,
10
20
  getSelection,
11
- hasClass,
12
- hasTagName,
13
- isHTMLElement,
14
21
  isSelectionInsideNode,
15
- isSelfClosing,
16
- removeNodesRecursively,
17
22
  replaceSelectionByHtml,
18
23
  restoreSelection,
19
- throttle,
20
- unwrapNode,
21
24
  wrapInsideLink,
22
25
  wrapInsideTag,
23
26
  } from "../core/index.js";
@@ -362,7 +365,7 @@ export class EdithEditor {
362
365
  }
363
366
  } else {
364
367
  // Detect style blocs in parents
365
- let dest = sel.anchorNode as HTMLElement;
368
+ let dest = (isTextNode(sel.anchorNode!) ? sel.anchorNode!.parentNode : sel.anchorNode) as HTMLElement;
366
369
  const style = { B: false, I: false, U: false, S: false, Q: false };
367
370
  while (dest !== null && !hasClass(dest, "edith-visual")) {
368
371
  // Check if it's a style tag
package/src/ui/modal.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createNodeWith, getAttribute, hasAttribute } from "../core/index.js";
1
+ import { createNodeWith, getAttribute, hasAttribute } from "@lesjoursfr/browser-tools";
2
2
  import { Edith } from "../edith.js";
3
3
 
4
4
  export enum EdithModalFieldType {
@@ -1,224 +0,0 @@
1
- type EdithData = {
2
- [key: string]: string | null;
3
- };
4
- declare global {
5
- interface Document {
6
- edithData: EdithData;
7
- }
8
- interface HTMLElement {
9
- edithData: EdithData;
10
- }
11
- }
12
- /**
13
- * Check if a node is an HTML Element.
14
- * @param {Node} node the node to test
15
- * @returns {boolean} true if the node is an HTMLElement
16
- */
17
- export declare function isCommentNode(node: Node): node is Comment;
18
- /**
19
- * Check if a node is an HTML Element.
20
- * @param {Node} node the node to test
21
- * @returns {boolean} true if the node is an HTMLElement
22
- */
23
- export declare function isTextNode(node: Node): node is Text;
24
- /**
25
- * Check if a node is an HTML Element.
26
- * @param {Node} node the node to test
27
- * @returns {boolean} true if the node is an HTMLElement
28
- */
29
- export declare function isHTMLElement(node: Node): node is HTMLElement;
30
- /**
31
- * Create an HTMLElement from the HTML template.
32
- * @param {string} template the HTML template
33
- * @returns {HTMLElement} the created HTMLElement
34
- */
35
- export declare function createFromTemplate(template: string): HTMLElement;
36
- /**
37
- * Update the given CSS property.
38
- * If the value is `null` the property will be removed.
39
- * @param {HTMLElement} node the node to update
40
- * @param {string|{ [key: string]: string|null }} property multi-word property names are hyphenated (kebab-case) and not camel-cased.
41
- * @param {string|null} value (default to `null`)
42
- * @returns {HTMLElement} the element
43
- */
44
- export declare function updateCSS(node: HTMLElement, property: string | {
45
- [key: string]: string | null;
46
- }, value?: string | null): HTMLElement;
47
- /**
48
- * Check if the node has the given attribute.
49
- * @param {HTMLElement} node
50
- * @param {string} attribute
51
- * @returns {boolean} true or false
52
- */
53
- export declare function hasAttribute(node: HTMLElement, attribute: string): boolean;
54
- /**
55
- * Get the given attribute.
56
- * @param {HTMLElement} node
57
- * @param {string} attribute
58
- * @returns {string|null} the value
59
- */
60
- export declare function getAttribute(node: HTMLElement, attribute: string): string | null;
61
- /**
62
- * Set the given attribute.
63
- * If the value is `null` the attribute will be removed.
64
- * @param {HTMLElement} node
65
- * @param {string} attribute
66
- * @param {string|null} value
67
- * @returns {HTMLElement} the element
68
- */
69
- export declare function setAttribute(node: HTMLElement, attribute: string, value: string | null): HTMLElement;
70
- /**
71
- * Get the given data.
72
- * This function does not change the DOM.
73
- * If there is no key this function return all data
74
- * @param {HTMLElement} node
75
- * @param {string|undefined} key
76
- * @returns {EdithData|string|null} the value
77
- */
78
- export declare function getData(node: HTMLElement, key?: string): EdithData | string | null;
79
- /**
80
- * Set the given data.
81
- * If the value is `null` the data will be removed.
82
- * This function does not change the DOM.
83
- * @param {HTMLElement} node
84
- * @param {string} key
85
- * @param {string|null} value
86
- * @returns {HTMLElement} the element
87
- */
88
- export declare function setData(node: HTMLElement, key: string, value: string | null): HTMLElement;
89
- /**
90
- * Check if the node has the given tag name, or if its tag name is in the given list.
91
- * @param {HTMLElement} node the element to check
92
- * @param {string|Array<string>} tags a tag name or a list of tag name
93
- * @returns {boolean} true if the node has the given tag name
94
- */
95
- export declare function hasTagName(node: HTMLElement, tags: string | Array<string>): boolean;
96
- /**
97
- * Check if the node has the given class name.
98
- * @param {HTMLElement} node the element to check
99
- * @param {string} className a class name
100
- * @returns {boolean} true if the node has the given class name
101
- */
102
- export declare function hasClass(node: HTMLElement, className: string): boolean;
103
- /**
104
- * Add the class to the node's class attribute.
105
- * @param {HTMLElement} node
106
- * @param {string|Array<string>} className
107
- * @returns {HTMLElement} the element
108
- */
109
- export declare function addClass(node: HTMLElement, className: string | Array<string>): HTMLElement;
110
- /**
111
- * Remove the class from the node's class attribute.
112
- * @param {HTMLElement} node
113
- * @param {string|Array<string>} className
114
- * @returns {HTMLElement} the element
115
- */
116
- export declare function removeClass(node: HTMLElement, className: string | Array<string>): HTMLElement;
117
- /**
118
- * Test if the node match the given selector.
119
- * @param {HTMLElement} node
120
- * @param {string} selector
121
- * @returns {boolean} true or false
122
- */
123
- export declare function is(node: HTMLElement, selector: string): boolean;
124
- /**
125
- * Get the node's offset.
126
- * @param {HTMLElement} node
127
- * @returns {{ top: number, left: number }} The node's offset
128
- */
129
- export declare function offset(node: HTMLElement): {
130
- top: number;
131
- left: number;
132
- };
133
- /**
134
- * Create a new node.
135
- * @param {string} tag the tag name of the node
136
- * @param {object} options optional parameters
137
- * @param {string} options.innerHTML the HTML code of the node
138
- * @param {string} options.textContent the text content of the node
139
- * @param {object} options.attributes attributes of the node
140
- * @returns {HTMLElement} the created node
141
- */
142
- export declare function createNodeWith<K extends keyof HTMLElementTagNameMap>(tag: K, { innerHTML, textContent, attributes, }?: {
143
- innerHTML?: string;
144
- textContent?: string;
145
- attributes?: {
146
- [keyof: string]: string;
147
- };
148
- }): HTMLElementTagNameMap[K];
149
- /**
150
- * Replace a node.
151
- * @param {HTMLElement} node the node to replace
152
- * @param {HTMLElement} replacement the new node
153
- * @returns {HTMLElement} the new node
154
- */
155
- export declare function replaceNodeWith(node: HTMLElement, replacement: HTMLElement): HTMLElement;
156
- /**
157
- * Replace the node by its child nodes.
158
- * @param {HTMLElement} node the node to replace
159
- * @returns {Array<ChildNode>} its child nodes
160
- */
161
- export declare function unwrapNode(node: HTMLElement): ChildNode[];
162
- /**
163
- * Replace the node by its text content.
164
- * @param {HTMLElement} node the node to replace
165
- * @returns {Text} the created Text node
166
- */
167
- export declare function textifyNode(node: HTMLElement): Text;
168
- /**
169
- * Know if a tag si a self-closing tag
170
- * @param {string} tagName
171
- * @returns {boolean}
172
- */
173
- export declare function isSelfClosing(tagName: string): boolean;
174
- /**
175
- * Remove all node's child nodes that pass the test implemented by the provided function.
176
- * @param {ChildNode} node the node to process
177
- * @param {Function} callbackFn the predicate
178
- */
179
- export declare function removeNodes(node: ChildNode, callbackFn: (node: ChildNode) => boolean): void;
180
- /**
181
- * Remove recursively all node's child nodes that pass the test implemented by the provided function.
182
- * @param {ChildNode} node the node to process
183
- * @param {Function} callbackFn the predicate
184
- */
185
- export declare function removeNodesRecursively(node: ChildNode, callbackFn: (node: ChildNode) => boolean): void;
186
- /**
187
- * Remove all node's child nodes that are empty text nodes.
188
- * @param {ChildNode} node the node to process
189
- */
190
- export declare function removeEmptyTextNodes(node: ChildNode): void;
191
- /**
192
- * Remove all node's child nodes that are comment nodes.
193
- * @param {ChildNode} node the node to process
194
- */
195
- export declare function removeCommentNodes(node: ChildNode): void;
196
- /**
197
- * Reset all node's attributes to the given list.
198
- * @param {HTMLElement} node the node
199
- * @param {object} targetAttributes the requested node's attributes
200
- */
201
- export declare function resetAttributesTo(node: HTMLElement, targetAttributes: {
202
- [keyof: string]: string;
203
- }): void;
204
- /**
205
- * Replace the node's style attribute by some regular nodes (<b>, <i>, <u> or <s>).
206
- * @param {HTMLElement} node the node to process
207
- * @returns {HTMLElement} the new node
208
- */
209
- export declare function replaceNodeStyleByTag(node: HTMLElement): HTMLElement;
210
- /**
211
- * Remove all leading & trailing node's child nodes that match the given tag.
212
- * @param {HTMLElement} node the node to process
213
- * @param {string} tag the tag
214
- */
215
- export declare function trimTag(node: HTMLElement, tag: string): void;
216
- /**
217
- * Clean the DOM content of the node
218
- * @param {HTMLElement} root the node to process
219
- * @param {object} style active styles for the root
220
- */
221
- export declare function cleanDomContent(root: HTMLElement, style: {
222
- [keyof: string]: boolean;
223
- }): void;
224
- export {};