@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lesjoursfr/edith",
3
- "version": "1.0.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.5",
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.0",
54
+ "babel-loader": "^9.1.2",
55
55
  "codemirror": "^6.0.1",
56
56
  "css-loader": "^6.7.3",
57
- "eslint": "^8.30.0",
58
- "eslint-config-prettier": "^8.5.0",
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.0",
61
+ "eslint-plugin-n": "^15.6.1",
62
62
  "eslint-plugin-promise": "^6.1.1",
63
- "jsdom": "^20.0.3",
63
+ "jsdom": "^21.0.0",
64
64
  "mini-css-extract-plugin": "^2.7.2",
65
- "postcss": "^8.4.20",
66
- "prettier": "^2.8.1",
67
- "sass": "^1.57.0",
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.0",
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.0"
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
@@ -1,3 +1,4 @@
1
1
  export const Events = Object.freeze({
2
2
  modeChanged: "edith-mode-changed",
3
+ initialized: "edith-initialized",
3
4
  });
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 code
112
+ return placeholder.innerHTML
106
113
  .replace(/\u200B/gi, "")
107
114
  .replace(/<\/p>\s*<p>/gi, "<br>")
108
115
  .replace(/(<p>|<\/p>)/gi, "")