@livingdocs/editable.js 3.0.12 → 3.0.15

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,11 +1,10 @@
1
1
  {
2
2
  "name": "@livingdocs/editable.js",
3
3
  "description": "Friendly contenteditable API",
4
- "version": "3.0.12",
4
+ "version": "3.0.15",
5
5
  "dependencies": {
6
6
  "@babel/runtime": "^7.16.7",
7
7
  "bowser": "2.11.0",
8
- "chai": "^4.3.6",
9
8
  "lodash-es": "^4.17.21",
10
9
  "rangy": "^1.3.0"
11
10
  },
@@ -18,6 +17,7 @@
18
17
  "babel-loader": "^8.2.3",
19
18
  "babel-plugin-add-module-exports": "^1.0.4",
20
19
  "babel-plugin-istanbul": "^6.1.1",
20
+ "chai": "^4.3.6",
21
21
  "css-loader": "^6.5.1",
22
22
  "eslint": "^8.8.0",
23
23
  "eslint-plugin-react": "^7.28.0",
@@ -83,11 +83,11 @@
83
83
  "isCi": true,
84
84
  "name": "Drone",
85
85
  "service": "drone",
86
- "commit": "c6a519554f759a223875739b9f20d991388a6185",
87
- "build": "423",
86
+ "commit": "cfb72eb34899004520ea0b1d0bd7bb9434681502",
87
+ "build": "454",
88
88
  "branch": "master",
89
89
  "isPr": false,
90
90
  "slug": "livingdocsIO/editable.js",
91
- "date": "2022-02-01T11:35:53.353Z"
91
+ "date": "2022-02-23T12:28:23.761Z"
92
92
  }
93
93
  }
package/src/config.js CHANGED
@@ -13,22 +13,26 @@ export default {
13
13
  boldMarkup: {
14
14
  type: 'tag',
15
15
  name: 'strong',
16
- attribs: {}
16
+ attribs: {},
17
+ trim: true
17
18
  },
18
19
  italicMarkup: {
19
20
  type: 'tag',
20
21
  name: 'em',
21
- attribs: {}
22
+ attribs: {},
23
+ trim: true
22
24
  },
23
25
  underlineMarkup: {
24
26
  type: 'tag',
25
27
  name: 'u',
26
- attribs: {}
28
+ attribs: {},
29
+ trim: false
27
30
  },
28
31
  linkMarkup: {
29
32
  type: 'tag',
30
33
  name: 'a',
31
- attribs: {}
34
+ attribs: {},
35
+ trim: true
32
36
  },
33
37
 
34
38
  // Rules that are applied when filtering pasted content
@@ -134,7 +134,7 @@ export default {
134
134
  // This has two notable behaviours:
135
135
  // - It uses a NodeIterator which will skip elements
136
136
  // with data-editable="remove"
137
- // - It returns a space for <br> elements
137
+ // - It returns a \n for <br> elements
138
138
  // (The only block level element allowed inside of editables)
139
139
  function getText (element, callback) {
140
140
  const iterator = new NodeIterator(element)
@@ -143,7 +143,7 @@ function getText (element, callback) {
143
143
  if (next.nodeType === nodeType.textNode && next.data !== '') {
144
144
  callback(next.data)
145
145
  } else if (next.nodeType === nodeType.elementNode && next.nodeName === 'BR') {
146
- callback(' ')
146
+ callback('\n')
147
147
  }
148
148
  }
149
149
  }
package/src/selection.js CHANGED
@@ -87,9 +87,21 @@ export default class Selection extends Cursor {
87
87
  link.setAttribute(key, value)
88
88
  }
89
89
  }
90
+ if (config.linkMarkup.trim) this.trimRange()
91
+
90
92
  this.forceWrap(link)
91
93
  }
92
94
 
95
+ // trims whitespaces on the left and right of a selection, i.e. what you want in case of links
96
+ trimRange () {
97
+ const textToTrim = this.range.toString()
98
+ const whitespacesOnTheLeft = textToTrim.search(/\S|$/)
99
+ const lastNonWhitespace = textToTrim.search(/\S[\s]+$/)
100
+ const whitespacesOnTheRight = lastNonWhitespace === -1 ? 0 : textToTrim.length - (lastNonWhitespace + 1)
101
+ this.range.setStart(this.range.startContainer, this.range.startOffset + whitespacesOnTheLeft)
102
+ this.range.setEnd(this.range.endContainer, this.range.endOffset - whitespacesOnTheRight)
103
+ }
104
+
93
105
  unlink () {
94
106
  this.removeFormatting(config.linkMarkup.name)
95
107
  }
@@ -137,43 +149,51 @@ export default class Selection extends Cursor {
137
149
  this.setSelection()
138
150
  }
139
151
 
140
- toggleCustom ({tagName, attributes}) {
152
+ toggleCustom ({tagName, attributes, trim = false}) {
141
153
  const customElem = this.createElement(tagName, attributes)
154
+ if (trim) this.trimRange()
142
155
  this.toggle(customElem)
143
156
  }
144
157
 
145
- makeCustom ({tagName, attributes}) {
158
+ makeCustom ({tagName, attributes, trim = false}) {
146
159
  const customElem = this.createElement(tagName, attributes)
160
+ if (trim) this.trimRange()
147
161
  this.forceWrap(customElem)
148
162
  }
149
163
 
150
164
  makeBold () {
151
165
  const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs)
166
+ if (config.boldMarkup.trim) this.trimRange()
152
167
  this.forceWrap(bold)
153
168
  }
154
169
 
155
170
  toggleBold () {
156
171
  const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs)
172
+ if (config.boldMarkup.trim) this.trimRange()
157
173
  this.toggle(bold)
158
174
  }
159
175
 
160
176
  giveEmphasis () {
161
177
  const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs)
178
+ if (config.italicMarkup.trim) this.trimRange()
162
179
  this.forceWrap(em)
163
180
  }
164
181
 
165
182
  toggleEmphasis () {
166
183
  const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs)
184
+ if (config.italicMarkup.trim) this.trimRange()
167
185
  this.toggle(em)
168
186
  }
169
187
 
170
188
  makeUnderline () {
171
189
  const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs)
190
+ if (config.underlineMarkup.trim) this.trimRange()
172
191
  this.forceWrap(u)
173
192
  }
174
193
 
175
194
  toggleUnderline () {
176
195
  const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs)
196
+ if (config.underlineMarkup.trim) this.trimRange()
177
197
  this.toggle(u)
178
198
  }
179
199