@livingdocs/editable.js 3.0.4 → 3.0.8

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@livingdocs/editable.js",
3
3
  "description": "Friendly contenteditable API",
4
- "version": "3.0.4",
4
+ "version": "3.0.8",
5
5
  "dependencies": {
6
6
  "@babel/runtime": "^7.13.17",
7
7
  "bowser": "2.11.0",
@@ -9,21 +9,21 @@
9
9
  "rangy": "^1.3.0"
10
10
  },
11
11
  "devDependencies": {
12
- "@babel/cli": "^7.13.16",
13
- "@babel/core": "^7.13.16",
14
- "@babel/plugin-transform-runtime": "^7.13.15",
15
- "@babel/preset-env": "^7.13.15",
12
+ "@babel/cli": "^7.15.7",
13
+ "@babel/core": "^7.15.8",
14
+ "@babel/plugin-transform-runtime": "^7.15.8",
15
+ "@babel/preset-env": "^7.15.8",
16
16
  "@babel/preset-react": "^7.13.13",
17
17
  "@esm-bundle/chai": "^4.3.4-fix.0",
18
- "babel-loader": "^8.2.2",
18
+ "babel-loader": "^8.2.3",
19
19
  "babel-plugin-add-module-exports": "^1.0.4",
20
- "babel-plugin-istanbul": "^6.0.0",
21
- "css-loader": "^5.2.4",
22
- "eslint": "^7.24.0",
20
+ "babel-plugin-istanbul": "^6.1.1",
21
+ "css-loader": "^6.4.0",
22
+ "eslint": "^7.32.0",
23
23
  "eslint-plugin-react": "^7.23.2",
24
24
  "font-awesome": "^4.7.0",
25
25
  "gh-pages": "^3.1.0",
26
- "karma": "^6.3.2",
26
+ "karma": "^6.3.6",
27
27
  "karma-chrome-launcher": "^3.1.0",
28
28
  "karma-coverage": "^2.0.3",
29
29
  "karma-firefox-launcher": "^2.1.0",
@@ -31,9 +31,9 @@
31
31
  "karma-safari-launcher": "^1.0.0",
32
32
  "karma-sourcemap-loader": "^0.3.8",
33
33
  "karma-webpack": "^5.0.0",
34
- "mocha": "^9.0.3",
34
+ "mocha": "^9.1.3",
35
35
  "normalize.css": "^8.0.1",
36
- "prismjs": "^1.23.0",
36
+ "prismjs": "^1.25.0",
37
37
  "react": "^17.0.2",
38
38
  "react-dom": "^17.0.2",
39
39
  "react-transition-group": "^4.4.1",
@@ -41,9 +41,9 @@
41
41
  "sinon": "^10.0.0",
42
42
  "style-loader": "^2.0.0",
43
43
  "url-loader": "^4.1.1",
44
- "webpack": "^5.35.0",
45
- "webpack-cli": "^4.6.0",
46
- "webpack-dev-server": "^4.0.0-beta.3"
44
+ "webpack": "^5.60.0",
45
+ "webpack-cli": "^4.9.1",
46
+ "webpack-dev-server": "^4.3.1"
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=12"
@@ -74,8 +74,7 @@
74
74
  "test:all": "npm run test:karma -s -- --browsers Chrome,Firefox,Safari",
75
75
  "test:karma": "karma start",
76
76
  "test:watch": "npm run test:karma -s -- --single-run false",
77
- "lint": "eslint --ignore-path .gitignore .",
78
- "postversion": "/release/node_modules/.bin/set-ci"
77
+ "lint": "eslint --ignore-path .gitignore ."
79
78
  },
80
79
  "release": {
81
80
  "extends": "@livingdocs/semantic-release-presets/npm-github-verify"
@@ -84,11 +83,11 @@
84
83
  "isCi": true,
85
84
  "name": "Drone",
86
85
  "service": "drone",
87
- "commit": "ad5e43330e0f2b32687c86346775766167593cb5",
88
- "build": "351",
86
+ "commit": "e4c7383e5620ccbb13b71e155a8f26d5f245b64d",
87
+ "build": "398",
89
88
  "branch": "master",
90
89
  "isPr": false,
91
90
  "slug": "livingdocsIO/editable.js",
92
- "date": "2021-09-09T12:40:33.657Z"
91
+ "date": "2021-12-15T14:59:21.802Z"
93
92
  }
94
93
  }
package/src/content.js CHANGED
@@ -29,6 +29,12 @@ export function tidyHtml (element) {
29
29
  export function normalizeTags (element) {
30
30
  const fragment = document.createDocumentFragment()
31
31
 
32
+ // Remove line breaks at the beginning of a content block
33
+ removeWhitespaces(element, 'firstChild')
34
+
35
+ // Remove line breaks at the end of a content block
36
+ removeWhitespaces(element, 'lastChild')
37
+
32
38
  for (const node of element.childNodes) {
33
39
  // skip empty tags, so they'll get removed
34
40
  if (node.nodeName !== 'BR' && !node.textContent) continue
@@ -136,7 +142,7 @@ export function cloneRangeContents (range) {
136
142
  return fragment
137
143
  }
138
144
 
139
- function removeWhitespaces (node, type) {
145
+ function removeWhitespaces (node, type, firstCall = true) {
140
146
  let elem
141
147
  while ((elem = node[type])) {
142
148
  if (elem.nodeType === nodeType.textNode) {
@@ -145,10 +151,17 @@ function removeWhitespaces (node, type) {
145
151
  } else if (elem.nodeName === 'BR') {
146
152
  elem.remove()
147
153
  } else {
148
- if (elem[type]) removeWhitespaces(elem, type)
154
+ if (elem[type]) removeWhitespaces(elem, type, false)
149
155
  break
150
156
  }
151
157
  }
158
+
159
+ if (!firstCall) return
160
+ elem = node[type]
161
+ if (elem?.nodeType !== nodeType.textNode) return
162
+ // Remove whitespaces at the end or start of a block with content
163
+ // e.g. ' Hello world' > 'Hello World'
164
+ elem.textContent = elem.textContent.replace(type.startsWith('last') ? /\s+$/ : /^\s+/, '')
152
165
  }
153
166
 
154
167
  // Remove elements that were inserted for internal or user interface purposes
package/src/cursor.js CHANGED
@@ -96,7 +96,7 @@ export default class Cursor {
96
96
  hostRange.collapse(false)
97
97
  const hostCoords = getRangeBoundingClientRect(hostRange, this.win)
98
98
  const cursorCoords = getRangeBoundingClientRect(this.range.nativeRange, this.win)
99
- return hostCoords.bottom === cursorCoords.bottom
99
+ return isCloseTo(hostCoords.bottom, cursorCoords.bottom)
100
100
  }
101
101
 
102
102
  isAtFirstLine () {
@@ -105,7 +105,7 @@ export default class Cursor {
105
105
  hostRange.collapse(true)
106
106
  const hostCoords = getRangeBoundingClientRect(hostRange, this.win)
107
107
  const cursorCoords = getRangeBoundingClientRect(this.range.nativeRange, this.win)
108
- return hostCoords.top === cursorCoords.top
108
+ return isCloseTo(hostCoords.top, cursorCoords.top)
109
109
  }
110
110
 
111
111
  isAtBeginning () {
@@ -368,3 +368,9 @@ function getRangeBoundingClientRect (range, win) {
368
368
  el.remove()
369
369
  return coords
370
370
  }
371
+
372
+ function isCloseTo (a, b) {
373
+ if (a === b) return true
374
+ if (Math.abs(a - b) <= 2) return true
375
+ return false
376
+ }
@@ -9,8 +9,8 @@ export default class WordHighlighting {
9
9
 
10
10
  isElement (obj) {
11
11
  try {
12
- // Using W3 DOM2 (works for FF, Opera and Chrome)
13
- return obj instanceof HTMLElement
12
+ if (!obj) return false
13
+ return obj instanceof obj.ownerDocument?.defaultView.HTMLElement
14
14
  } catch (e) {
15
15
  // Browsers not supporting W3 DOM2 don't have HTMLElement and
16
16
  // an exception is thrown and we end up here. Testing some
package/src/selection.js CHANGED
@@ -78,7 +78,15 @@ export default class Selection extends Cursor {
78
78
  link (href, attrs = {}) {
79
79
  if (href) attrs.href = href
80
80
  const link = this.createElement(config.linkMarkup.name, config.linkMarkup.attribs)
81
- for (const key in attrs) link.setAttribute(key, attrs[key])
81
+ for (const key in attrs) {
82
+ const value = attrs[key]
83
+ if (value === undefined) continue
84
+ if (value === null) {
85
+ link.removeAttribute(key)
86
+ } else {
87
+ link.setAttribute(key, value)
88
+ }
89
+ }
82
90
  this.forceWrap(link)
83
91
  }
84
92