smeditor 0.2.1 → 0.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/app/assets/javascripts/smeditor.js +32 -10
- data/lib/smeditor/rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: deea7d855b9ea5c7d61a51d82adeb656e3583db0dc9ed8d677345fe2d1bac550
|
|
4
|
+
data.tar.gz: 99a68a8823548919c2acb1aaea114822b677e33d464cd37a66f42fe4cc802e73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6cf34629807ab5b326dff8ddaa85e80bc2f4b5c7de86a233e4d2a9c1196a3151df18af818f658f6826e0f21c7d90317c8f190df1697f5ecc8501c4f24511c9b7
|
|
7
|
+
data.tar.gz: 3f72f9d9fc819294563dd2519eb07e84dd159432fd2bc8ad6111b0ed125c46790163ef7caae49ae1b76ea7ced5406baf65b1dc9a2350e6115edc15b34c3d57bc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog — smeditor
|
|
2
2
|
|
|
3
|
+
## 0.2.2 — 2026-09-09
|
|
4
|
+
|
|
5
|
+
- Fixed caret jumps and reordered typing inside the Rails Shadow DOM editor. The core now resolves the live DOM Selection from the editor's own root instead of always using `document.getSelection()`.
|
|
6
|
+
- Selection restore and caret coordinate ranges now use the editor element's owner document, keeping the DOM integration correct in isolated roots and embedded documents.
|
|
7
|
+
|
|
3
8
|
## 0.2.1 — 2026-09-09
|
|
4
9
|
|
|
5
10
|
- Rails editor now renders inside Shadow DOM so host application CSS cannot alter the SMEditor toolbar or editing surface.
|
|
@@ -763,14 +763,14 @@ class Editor {
|
|
|
763
763
|
*/
|
|
764
764
|
coordsAtPoint(point) {
|
|
765
765
|
var _a;
|
|
766
|
-
if (!this.element
|
|
766
|
+
if (!this.element)
|
|
767
767
|
return null;
|
|
768
768
|
const deep = (_a = this.options.deepSelection) !== null && _a !== void 0 ? _a : false;
|
|
769
769
|
const loc = domNodeFromPoint(point, this.element, deep);
|
|
770
770
|
if (!loc)
|
|
771
771
|
return null;
|
|
772
772
|
try {
|
|
773
|
-
const range =
|
|
773
|
+
const range = this.element.ownerDocument.createRange();
|
|
774
774
|
const offset = Math.min(loc.offset, lengthOf(loc.node));
|
|
775
775
|
range.setStart(loc.node, offset);
|
|
776
776
|
range.collapse(true);
|
|
@@ -1243,9 +1243,7 @@ class Editor {
|
|
|
1243
1243
|
var _a, _b;
|
|
1244
1244
|
if (this.updatingDOM || !this.element)
|
|
1245
1245
|
return;
|
|
1246
|
-
|
|
1247
|
-
return;
|
|
1248
|
-
const domSel = document.getSelection();
|
|
1246
|
+
const domSel = selectionForElement(this.element);
|
|
1249
1247
|
if (!domSel)
|
|
1250
1248
|
return;
|
|
1251
1249
|
if (!this.element.contains(domSel.anchorNode))
|
|
@@ -1267,9 +1265,9 @@ class Editor {
|
|
|
1267
1265
|
}
|
|
1268
1266
|
readSelectionFromDOM() {
|
|
1269
1267
|
var _a;
|
|
1270
|
-
if (!this.element
|
|
1268
|
+
if (!this.element)
|
|
1271
1269
|
return null;
|
|
1272
|
-
const sel =
|
|
1270
|
+
const sel = selectionForElement(this.element);
|
|
1273
1271
|
if (!sel || sel.rangeCount === 0)
|
|
1274
1272
|
return null;
|
|
1275
1273
|
const deep = (_a = this.options.deepSelection) !== null && _a !== void 0 ? _a : false;
|
|
@@ -1290,10 +1288,10 @@ class Editor {
|
|
|
1290
1288
|
}
|
|
1291
1289
|
applySelectionToDOM() {
|
|
1292
1290
|
var _a;
|
|
1293
|
-
if (!this.selection || !this.element
|
|
1291
|
+
if (!this.selection || !this.element) {
|
|
1294
1292
|
return;
|
|
1295
1293
|
}
|
|
1296
|
-
const sel =
|
|
1294
|
+
const sel = selectionForElement(this.element);
|
|
1297
1295
|
if (!sel)
|
|
1298
1296
|
return;
|
|
1299
1297
|
const deep = (_a = this.options.deepSelection) !== null && _a !== void 0 ? _a : false;
|
|
@@ -1302,7 +1300,7 @@ class Editor {
|
|
|
1302
1300
|
if (!anchorNode || !headNode)
|
|
1303
1301
|
return;
|
|
1304
1302
|
try {
|
|
1305
|
-
const range =
|
|
1303
|
+
const range = this.element.ownerDocument.createRange();
|
|
1306
1304
|
range.setStart(anchorNode.node, Math.min(anchorNode.offset, lengthOf(anchorNode.node)));
|
|
1307
1305
|
range.setEnd(headNode.node, Math.min(headNode.offset, lengthOf(headNode.node)));
|
|
1308
1306
|
sel.removeAllRanges();
|
|
@@ -1353,6 +1351,30 @@ class Editor {
|
|
|
1353
1351
|
// ============================================================================
|
|
1354
1352
|
// Helpers (module-private)
|
|
1355
1353
|
// ============================================================================
|
|
1354
|
+
/**
|
|
1355
|
+
* Return the Selection object that actually owns the editor caret.
|
|
1356
|
+
*
|
|
1357
|
+
* `document.getSelection()` is not sufficient for editors mounted inside an
|
|
1358
|
+
* open ShadowRoot: Chromium exposes a composed selection on the document whose
|
|
1359
|
+
* anchor can be the shadow host instead of the text node inside the editor.
|
|
1360
|
+
* Reading that selection produces a null/wrong editor position; the next DOM
|
|
1361
|
+
* render then loses the caret (most visibly when typing spaces).
|
|
1362
|
+
*
|
|
1363
|
+
* Both Document and Chromium's ShadowRoot expose getSelection(). Prefer the
|
|
1364
|
+
* editor's root and fall back to its owner document for browsers that do not
|
|
1365
|
+
* expose ShadowRoot#getSelection.
|
|
1366
|
+
*/
|
|
1367
|
+
function selectionForElement(element) {
|
|
1368
|
+
var _a, _b, _c, _d;
|
|
1369
|
+
const root = (_a = element.getRootNode) === null || _a === void 0 ? void 0 : _a.call(element);
|
|
1370
|
+
const rootedGetSelection = root === null || root === void 0 ? void 0 : root.getSelection;
|
|
1371
|
+
if (root && typeof rootedGetSelection === "function") {
|
|
1372
|
+
const selection = rootedGetSelection.call(root);
|
|
1373
|
+
if (selection)
|
|
1374
|
+
return selection;
|
|
1375
|
+
}
|
|
1376
|
+
return (_d = (_c = (_b = element.ownerDocument) === null || _b === void 0 ? void 0 : _b.getSelection) === null || _c === void 0 ? void 0 : _c.call(_b)) !== null && _d !== void 0 ? _d : null;
|
|
1377
|
+
}
|
|
1356
1378
|
/**
|
|
1357
1379
|
* Strip noise and unsafe elements from pasted HTML.
|
|
1358
1380
|
*
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: smeditor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SMEditor contributors
|
|
@@ -96,7 +96,7 @@ metadata:
|
|
|
96
96
|
source_code_uri: https://github.com/sCruze/smeditor/tree/main/gems/smeditor
|
|
97
97
|
changelog_uri: https://github.com/sCruze/smeditor/blob/main/gems/smeditor/CHANGELOG.md
|
|
98
98
|
bug_tracker_uri: https://github.com/sCruze/smeditor/issues
|
|
99
|
-
documentation_uri: https://rubydoc.info/gems/smeditor/0.2.
|
|
99
|
+
documentation_uri: https://rubydoc.info/gems/smeditor/0.2.2
|
|
100
100
|
rubygems_mfa_required: 'true'
|
|
101
101
|
rdoc_options: []
|
|
102
102
|
require_paths:
|