@lesjoursfr/edith 1.0.1 → 1.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/package.json +12 -12
- package/src/core/dom.js +44 -0
- package/src/core/edit.js +7 -0
- package/src/core/event.js +1 -0
- package/src/index.js +4 -0
- package/src/ui/editor.js +9 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lesjoursfr/edith",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Simple WYSIWYG editor.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "lesjoursfr/edith",
|
|
@@ -45,29 +45,29 @@
|
|
|
45
45
|
"editor"
|
|
46
46
|
],
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@babel/core": "^7.20.
|
|
48
|
+
"@babel/core": "^7.20.12",
|
|
49
49
|
"@babel/preset-env": "^7.20.2",
|
|
50
50
|
"@codemirror/lang-html": "^6.4.0",
|
|
51
51
|
"@fortawesome/fontawesome-free": "^6.2.1",
|
|
52
52
|
"@popperjs/core": "^2.11.6",
|
|
53
53
|
"ava": "^5.1.0",
|
|
54
|
-
"babel-loader": "^9.1.
|
|
54
|
+
"babel-loader": "^9.1.2",
|
|
55
55
|
"codemirror": "^6.0.1",
|
|
56
56
|
"css-loader": "^6.7.3",
|
|
57
|
-
"eslint": "^8.
|
|
58
|
-
"eslint-config-prettier": "^8.
|
|
57
|
+
"eslint": "^8.31.0",
|
|
58
|
+
"eslint-config-prettier": "^8.6.0",
|
|
59
59
|
"eslint-config-standard": "^17.0.0",
|
|
60
60
|
"eslint-plugin-import": "^2.26.0",
|
|
61
|
-
"eslint-plugin-n": "^15.6.
|
|
61
|
+
"eslint-plugin-n": "^15.6.1",
|
|
62
62
|
"eslint-plugin-promise": "^6.1.1",
|
|
63
|
-
"jsdom": "^
|
|
63
|
+
"jsdom": "^21.0.0",
|
|
64
64
|
"mini-css-extract-plugin": "^2.7.2",
|
|
65
|
-
"postcss": "^8.4.
|
|
66
|
-
"prettier": "^2.8.
|
|
67
|
-
"sass": "^1.57.
|
|
65
|
+
"postcss": "^8.4.21",
|
|
66
|
+
"prettier": "^2.8.2",
|
|
67
|
+
"sass": "^1.57.1",
|
|
68
68
|
"sass-loader": "^13.2.0",
|
|
69
69
|
"style-loader": "^3.3.1",
|
|
70
|
-
"stylelint": "^14.16.
|
|
70
|
+
"stylelint": "^14.16.1",
|
|
71
71
|
"stylelint-config-prettier": "^9.0.4",
|
|
72
72
|
"stylelint-config-sass-guidelines": "^9.0.1",
|
|
73
73
|
"webpack": "^5.75.0",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"@popperjs/core": "^2.11.6",
|
|
81
81
|
"codemirror": "^6.0.1"
|
|
82
82
|
},
|
|
83
|
-
"packageManager": "yarn@3.3.
|
|
83
|
+
"packageManager": "yarn@3.3.1"
|
|
84
84
|
}
|
package/src/core/dom.js
CHANGED
|
@@ -92,6 +92,31 @@ export function textifyNode(node) {
|
|
|
92
92
|
return newNode;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Know if a tag si a self-closing tag
|
|
97
|
+
* @param {String} tagName
|
|
98
|
+
* @returns {Boolean}
|
|
99
|
+
*/
|
|
100
|
+
export function isSelfClosing(tagName) {
|
|
101
|
+
return [
|
|
102
|
+
"AREA",
|
|
103
|
+
"BASE",
|
|
104
|
+
"BR",
|
|
105
|
+
"COL",
|
|
106
|
+
"EMBED",
|
|
107
|
+
"HR",
|
|
108
|
+
"IMG",
|
|
109
|
+
"INPUT",
|
|
110
|
+
"KEYGEN",
|
|
111
|
+
"LINK",
|
|
112
|
+
"META",
|
|
113
|
+
"PARAM",
|
|
114
|
+
"SOURCE",
|
|
115
|
+
"TRACK",
|
|
116
|
+
"WBR",
|
|
117
|
+
].includes(tagName);
|
|
118
|
+
}
|
|
119
|
+
|
|
95
120
|
/**
|
|
96
121
|
* Remove all node's child nodes that pass the test implemented by the provided function.
|
|
97
122
|
* @param {Node} node the node to process
|
|
@@ -105,6 +130,25 @@ export function removeNodes(node, callbackFn) {
|
|
|
105
130
|
}
|
|
106
131
|
}
|
|
107
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Remove recursively all node's child nodes that pass the test implemented by the provided function.
|
|
135
|
+
* @param {Node} node the node to process
|
|
136
|
+
* @param {Function} callbackFn the predicate
|
|
137
|
+
*/
|
|
138
|
+
export function removeNodesRecursively(node, callbackFn) {
|
|
139
|
+
// Remove the node if it meets the condition
|
|
140
|
+
if (callbackFn(node)) {
|
|
141
|
+
node.remove();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Loop through the node’s children
|
|
146
|
+
for (const el of [...node.childNodes]) {
|
|
147
|
+
// Execute the same function if it’s an element node
|
|
148
|
+
removeNodesRecursively(el, callbackFn);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
108
152
|
/**
|
|
109
153
|
* Remove all node's child nodes that are empty text nodes.
|
|
110
154
|
* @param {Node} node the node to process
|
package/src/core/edit.js
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
createNodeWith,
|
|
7
7
|
unwrapNode,
|
|
8
8
|
textifyNode,
|
|
9
|
+
isSelfClosing,
|
|
10
|
+
removeNodes,
|
|
9
11
|
removeEmptyTextNodes,
|
|
10
12
|
removeCommentNodes,
|
|
11
13
|
} from "./dom.js";
|
|
@@ -167,6 +169,11 @@ export function wrapInsideTag(tag, options = {}) {
|
|
|
167
169
|
const node = document.createElement(tag);
|
|
168
170
|
node.appendChild(range.extractContents());
|
|
169
171
|
range.insertNode(node);
|
|
172
|
+
|
|
173
|
+
// Remove empty tags
|
|
174
|
+
removeNodes(parent, (el) => !isSelfClosing(el.tagName) && el.textContent.length === 0);
|
|
175
|
+
|
|
176
|
+
// Return the node
|
|
170
177
|
selectNodeContents(node);
|
|
171
178
|
return node;
|
|
172
179
|
}
|
package/src/core/event.js
CHANGED
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EdithEditor } from "./ui/editor.js";
|
|
2
2
|
import { EdithButton, EdithButtons } from "./ui/button.js";
|
|
3
|
+
import { Events } from "./core/event.js";
|
|
3
4
|
|
|
4
5
|
/*
|
|
5
6
|
* Represents an editor
|
|
@@ -43,6 +44,9 @@ function Edith(element, options) {
|
|
|
43
44
|
this.modals = document.createElement("div");
|
|
44
45
|
this.modals.setAttribute("class", "edith-modals");
|
|
45
46
|
this.element.append(this.modals);
|
|
47
|
+
|
|
48
|
+
// Trigger the initialized event once its initialized
|
|
49
|
+
this.trigger(Events.initialized);
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
Edith.prototype.on = function (type, listener, options) {
|
package/src/ui/editor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EditorView, basicSetup } from "codemirror";
|
|
2
2
|
import { html } from "@codemirror/lang-html";
|
|
3
|
-
import { hasClass, hasTagName } from "../core/dom.js";
|
|
3
|
+
import { hasClass, hasTagName, createNodeWith, isSelfClosing, removeNodesRecursively } from "../core/dom.js";
|
|
4
4
|
import {
|
|
5
5
|
wrapInsideTag,
|
|
6
6
|
replaceSelectionByHtml,
|
|
@@ -101,8 +101,15 @@ EdithEditor.prototype.getContent = function () {
|
|
|
101
101
|
return "";
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// Remove empty tags
|
|
105
|
+
const placeholder = createNodeWith("div", { innerHTML: code });
|
|
106
|
+
removeNodesRecursively(
|
|
107
|
+
placeholder,
|
|
108
|
+
(el) => el.nodeType === Node.ELEMENT_NODE && !isSelfClosing(el.tagName) && el.textContent.length === 0
|
|
109
|
+
);
|
|
110
|
+
|
|
104
111
|
// Return clean code
|
|
105
|
-
return
|
|
112
|
+
return placeholder.innerHTML
|
|
106
113
|
.replace(/\u200B/gi, "")
|
|
107
114
|
.replace(/<\/p>\s*<p>/gi, "<br>")
|
|
108
115
|
.replace(/(<p>|<\/p>)/gi, "")
|