Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
{
"dist/index.umd.js": {
"bundled": 15914,
"minified": 6880,
"gzipped": 2594
"bundled": 16295,
"minified": 7136,
"gzipped": 2643
},
"dist/index.umd.min.js": {
"bundled": 15914,
"minified": 6880,
"gzipped": 2594
"bundled": 16295,
"minified": 7136,
"gzipped": 2643
},
"dist/index.esm.js": {
"bundled": 14601,
"minified": 7845,
"gzipped": 2641,
"bundled": 14952,
"minified": 7975,
"gzipped": 2690,
"treeshaked": {
"rollup": {
"code": 6566,
"code": 6822,
"import_statements": 63
},
"webpack": {
"code": 7644
"code": 7914
}
}
}
Expand Down
28 changes: 16 additions & 12 deletions lib/cjs/react-sane-contenteditable.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

Expand All @@ -36,12 +38,12 @@ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) ===

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var propTypes = {
Expand Down Expand Up @@ -76,7 +78,7 @@ function (_Component) {

_this = _possibleConstructorReturn(this, _getPrototypeOf(ContentEditable).call(this));

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "insertAtCaret", function (prevValue, valueToInsert) {
_defineProperty(_assertThisInitialized(_this), "insertAtCaret", function (prevValue, valueToInsert) {
var _this$getRange = _this.getRange(),
startOffset = _this$getRange.startOffset,
endOffset = _this$getRange.endOffset;
Expand All @@ -86,7 +88,7 @@ function (_Component) {
return [prefix, valueToInsert, suffix].join('');
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onBlur", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onBlur", function (ev) {
var value = _this.state.value;
var onBlur = _this.props.onBlur;

Expand All @@ -95,7 +97,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onInput", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onInput", function (ev) {
var maxLength = _this.props.maxLength;
var innerText = ev.target.innerText;

Expand All @@ -116,7 +118,7 @@ function (_Component) {
});
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onKeyDown", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onKeyDown", function (ev) {
var innerText = ev.target.innerText;
var _this$props = _this.props,
maxLength = _this$props.maxLength,
Expand Down Expand Up @@ -153,7 +155,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onKeyUp", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onKeyUp", function (ev) {
var innerText = ev.target.innerText;
var onKeyUp = _this.props.onKeyUp;

Expand All @@ -162,7 +164,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onPaste", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onPaste", function (ev) {
ev.preventDefault();
var pastedValue = ev.clipboardData.getData('text');

Expand All @@ -183,7 +185,7 @@ function (_Component) {
});
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setRef", function (ref) {
_defineProperty(_assertThisInitialized(_this), "setRef", function (ref) {
var innerRef = _this.props.innerRef;
_this.ref = ref;

Expand Down Expand Up @@ -252,15 +254,17 @@ function (_Component) {
var _this$state = this.state,
caretPosition = _this$state.caretPosition,
value = _this$state.value;
var node = this.ref.childNodes[0] || this.ref;
var val = nextValue || value;
var pos = position || caretPosition;
return Math.min(pos, val.length);
return Math.min(pos, val.length, node.length);
}
}, {
key: "setCaretPosition",
value: function setCaretPosition() {
var range = this.getRange();
range.setStart(this.ref.childNodes[0] || this.ref, this.getSafeCaretPosition());
var node = this.ref.childNodes[0] || this.ref;
range.setStart(node, this.getSafeCaretPosition());
range.collapse();
this.selection.removeAllRanges();
this.selection.addRange(range);
Expand Down
4 changes: 3 additions & 1 deletion lib/cjs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
value: true
});

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

Expand Down
28 changes: 17 additions & 11 deletions lib/esm/react-sane-contenteditable.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import _extends from "@babel/runtime/helpers/extends";
import _objectSpread from "@babel/runtime/helpers/objectSpread";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/inherits";
import _defineProperty from "@babel/runtime/helpers/defineProperty";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isFunction, omit } from './utils';
Expand Down Expand Up @@ -43,7 +47,7 @@ function (_Component) {

_this = _possibleConstructorReturn(this, _getPrototypeOf(ContentEditable).call(this));

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "insertAtCaret", function (prevValue, valueToInsert) {
_defineProperty(_assertThisInitialized(_this), "insertAtCaret", function (prevValue, valueToInsert) {
var _this$getRange = _this.getRange(),
startOffset = _this$getRange.startOffset,
endOffset = _this$getRange.endOffset;
Expand All @@ -53,7 +57,7 @@ function (_Component) {
return [prefix, valueToInsert, suffix].join('');
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onBlur", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onBlur", function (ev) {
var value = _this.state.value;
var onBlur = _this.props.onBlur;

Expand All @@ -62,7 +66,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onInput", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onInput", function (ev) {
var maxLength = _this.props.maxLength;
var innerText = ev.target.innerText;

Expand All @@ -83,7 +87,7 @@ function (_Component) {
});
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onKeyDown", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onKeyDown", function (ev) {
var innerText = ev.target.innerText;
var _this$props = _this.props,
maxLength = _this$props.maxLength,
Expand Down Expand Up @@ -120,7 +124,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onKeyUp", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onKeyUp", function (ev) {
var innerText = ev.target.innerText;
var onKeyUp = _this.props.onKeyUp;

Expand All @@ -129,7 +133,7 @@ function (_Component) {
}
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "onPaste", function (ev) {
_defineProperty(_assertThisInitialized(_this), "onPaste", function (ev) {
ev.preventDefault();
var pastedValue = ev.clipboardData.getData('text');

Expand All @@ -150,7 +154,7 @@ function (_Component) {
});
});

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setRef", function (ref) {
_defineProperty(_assertThisInitialized(_this), "setRef", function (ref) {
var innerRef = _this.props.innerRef;
_this.ref = ref;

Expand Down Expand Up @@ -219,15 +223,17 @@ function (_Component) {
var _this$state = this.state,
caretPosition = _this$state.caretPosition,
value = _this$state.value;
var node = this.ref.childNodes[0] || this.ref;
var val = nextValue || value;
var pos = position || caretPosition;
return Math.min(pos, val.length);
return Math.min(pos, val.length, node.length);
}
}, {
key: "setCaretPosition",
value: function setCaretPosition() {
var range = this.getRange();
range.setStart(this.ref.childNodes[0] || this.ref, this.getSafeCaretPosition());
var node = this.ref.childNodes[0] || this.ref;
range.setStart(node, this.getSafeCaretPosition());
range.collapse();
this.selection.removeAllRanges();
this.selection.addRange(range);
Expand Down
5 changes: 4 additions & 1 deletion lib/esm/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectSpread from "@babel/runtime/helpers/objectSpread";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

var reduceTargetKeys = function reduceTargetKeys(target, keys, predicate) {
return Object.keys(target).reduce(predicate, {});
Expand Down
13 changes: 12 additions & 1 deletion src/__tests__/react-sane-contenteditable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import ContentEditable from '../react-sane-contenteditable';

// jsDOM
const doc = new JSDOM('<!doctype html><html><body></body></html>');
const addRange = jest.fn();

const mockedRange = {
cloneRange: jest.fn(() => mockedRange),
collapse: jest.fn(),
Expand All @@ -20,7 +22,7 @@ const mockedRange = {
global.document = doc;
global.window = doc.defaultView;
global.document.getSelection = jest.fn(() => ({
addRange: jest.fn(),
addRange: addRange,
getRangeAt: jest.fn(() => mockedRange),
rangeCount: 0,
removeAllRanges: jest.fn(),
Expand Down Expand Up @@ -214,6 +216,15 @@ describe('Handles selections', () => {
expect(wrapper.state('caretPosition')).toEqual(startOffset);
expect(wrapper.text()).toEqual(nextContent);
});

it('sets a new range without error when length of new value exceeds existing ref childNode', () => {
const content = 'Foo bar.';
const wrapper = mount(<ContentEditable content={content} />);
const ref = wrapper.instance().ref;
ref.innerText = content;
wrapper.setProps({ content: 'Foo <b>bar</b>' });
expect(addRange).toHaveBeenCalled();
});
});

describe('Sanitisation', () => {
Expand Down
6 changes: 4 additions & 2 deletions src/react-sane-contenteditable.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,18 @@ class ContentEditable extends Component {
getSafeCaretPosition(position, nextValue) {
const { caretPosition, value } = this.state;

const node = this.ref.childNodes[0] || this.ref;
const val = nextValue || value;
let pos = position || caretPosition;

return Math.min(pos, val.length);
return Math.min(pos, val.length, node.length);
}

setCaretPosition() {
let range = this.getRange();

range.setStart(this.ref.childNodes[0] || this.ref, this.getSafeCaretPosition());
const node = this.ref.childNodes[0] || this.ref;
range.setStart(node, this.getSafeCaretPosition());
range.collapse();
this.selection.removeAllRanges();
this.selection.addRange(range);
Expand Down