New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

draftail

Package Overview
Dependencies
Maintainers
2
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

draftail - npm Package Compare versions

Comparing version 0.4.1 to 0.5.0

38

CHANGELOG.md

@@ -7,9 +7,25 @@ Changelog

## [[v0.4.1]](https://github.com/springload/draftail/releases/tag/v0.4.1) - 2017-01-18
## [[v0.5.0]](https://github.com/springload/draftail/releases/tag/v0.5.0)
### Added
- Implement list depth normalisation on copy/paste.
- Add title attributes on buttons to display keyboard shortcuts. Fix #37.
- Override default code-block element. Fix #41.
### Changed
- Update project to use draft-js@0.10 API
- Move draftjs-utils `peerDependency` to be a dependency.
- Move immutable `peerDependency` to be a dependency.
- Copy/paste of rich text is now configurable via the `stripPastedStyles` option.
- Copy/paste of rich text is now disabled by default. This will be enabled by default once it is better supported.
## [[v0.4.1]](https://github.com/springload/draftail/releases/tag/v0.4.1)
### Fixed
- Fix image block not unlocking editor on cancel
- Fix image block not unlocking editor on cancel.
## [[v0.4.0]](https://github.com/springload/draftail/releases/tag/v0.4.0) - 2017-01-18
## [[v0.4.0]](https://github.com/springload/draftail/releases/tag/v0.4.0)

@@ -50,3 +66,3 @@ ### Added

## [[v0.3.3]](https://github.com/springload/draftail/releases/tag/v0.3.3) - 2016-12-13
## [[v0.3.3]](https://github.com/springload/draftail/releases/tag/v0.3.3)

@@ -57,3 +73,3 @@ ### Added

## [[v0.3.2]](https://github.com/springload/draftail/releases/tag/v0.3.2) - 2016-11-29
## [[v0.3.2]](https://github.com/springload/draftail/releases/tag/v0.3.2)

@@ -65,3 +81,3 @@ ### Added

## [[v0.3.1]](https://github.com/springload/draftail/releases/tag/v0.3.1) - 2016-11-28
## [[v0.3.1]](https://github.com/springload/draftail/releases/tag/v0.3.1)

@@ -72,3 +88,3 @@ ### Fixed

## [[v0.3.0]](https://github.com/springload/draftail/releases/tag/v0.3.0) - 2016-11-28
## [[v0.3.0]](https://github.com/springload/draftail/releases/tag/v0.3.0)

@@ -91,3 +107,3 @@ > This release contains __breaking changes__.

## [[v0.2.0]](https://github.com/springload/draftail/releases/tag/v0.2.0) - 2016-11-14
## [[v0.2.0]](https://github.com/springload/draftail/releases/tag/v0.2.0)

@@ -99,3 +115,3 @@ ### Changed

## [[v0.1.0]](https://github.com/springload/draftail/releases/tag/v0.1.0) - 2016-11-11
## [[v0.1.0]](https://github.com/springload/draftail/releases/tag/v0.1.0)

@@ -106,4 +122,6 @@ First usable release!

## [[x.y.z]](https://github.com/springload/draftail/releases/tag/x.y.z) - YYYY-MM-DD (Template: http://keepachangelog.com/)
Template from http://keepachangelog.com/
## [[vx.y.z]](https://github.com/springload/draftail/releases/tag/x.y.z)
### Added

@@ -110,0 +128,0 @@

@@ -13,8 +13,14 @@ 'use strict';

var hasCommandModifier = _draftJs.KeyBindingUtil.hasCommandModifier;
var hasCommandModifier = _draftJs.KeyBindingUtil.hasCommandModifier,
isOptionKeyCommand = _draftJs.KeyBindingUtil.isOptionKeyCommand;
// TODO Get rid of this as soon as possible.
// Hack relying on the internals of Draft.js.
// See https://github.com/facebook/draft-js/pull/869
var isMacOS = isOptionKeyCommand({ altKey: 'test' }) === 'test';
/**
* Behavioral methods for the editor, generated from its configuration.
*/
exports.default = {

@@ -29,2 +35,13 @@ /**

// Override default element for code block.
// Fix https://github.com/facebook/draft-js/issues/406.
if (blockTypes.some(function (block) {
return block.type === _constants.BLOCK_TYPE.CODE;
})) {
renderMap[_constants.BLOCK_TYPE.CODE] = {
element: 'code',
wrapper: _draftJs.DefaultDraftBlockRenderMap.get(_constants.BLOCK_TYPE.CODE).wrapper
};
}
blockTypes.filter(function (block) {

@@ -148,2 +165,8 @@ return block.element;

},
getKeyboardShortcut: function getKeyboardShortcut(type) {
var shortcut = _constants.KEYBOARD_SHORTCUTS[type];
var system = isMacOS ? 'macOS' : 'other';
return shortcut ? shortcut[system] : 'No keyboard shortcut';
},
getBeforeInputBlockType: function getBeforeInputBlockType(input) {

@@ -150,0 +173,0 @@ var blockTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

@@ -28,2 +28,12 @@ 'use strict';

});
describe('code block element', function () {
it('default is "code"', function () {
expect(_behavior2.default.getBlockRenderMap([{ type: _constants.BLOCK_TYPE.CODE }]).get(_constants.BLOCK_TYPE.CODE).element).toEqual('code');
});
it('can be overriden', function () {
expect(_behavior2.default.getBlockRenderMap([{ type: _constants.BLOCK_TYPE.CODE, element: 'span' }]).get(_constants.BLOCK_TYPE.CODE).element).toEqual('span');
});
});
});

@@ -173,2 +183,12 @@

describe('#getKeyboardShortcut', function () {
it('exists', function () {
expect(_behavior2.default.getKeyboardShortcut).toBeDefined();
});
it('header five shortcut', function () {
expect(_behavior2.default.getKeyboardShortcut(_constants.BLOCK_TYPE.HEADER_FIVE)).toBe('ctrl + alt + 5');
});
});
describe('#getBeforeInputBlockType', function () {

@@ -175,0 +195,0 @@ it('exists', function () {

@@ -43,2 +43,4 @@ 'use strict';

var BR_TYPE = exports.BR_TYPE = 'BR';
// Originally from https://github.com/facebook/draft-js/blob/master/src/component/utils/getDefaultKeyBinding.js.

@@ -62,2 +64,19 @@ var KEY_CODES = exports.KEY_CODES = {

var KEYBOARD_SHORTCUTS = exports.KEYBOARD_SHORTCUTS = {};
KEYBOARD_SHORTCUTS[BLOCK_TYPE.UNSTYLED] = { other: 'ctrl + alt + 0', macOS: '⌘ + option + 0' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_ONE] = { other: 'ctrl + alt + 1', macOS: '⌘ + option + 1' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_TWO] = { other: 'ctrl + alt + 2', macOS: '⌘ + option + 2' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_THREE] = { other: 'ctrl + alt + 3', macOS: '⌘ + option + 3' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_FOUR] = { other: 'ctrl + alt + 4', macOS: '⌘ + option + 4' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_FIVE] = { other: 'ctrl + alt + 5', macOS: '⌘ + option + 5' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.HEADER_SIX] = { other: 'ctrl + alt + 6', macOS: '⌘ + option + 6' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.UNORDERED_LIST_ITEM] = { other: 'ctrl + shift + 8', macOS: '⌘ + shift + 8' };
KEYBOARD_SHORTCUTS[BLOCK_TYPE.ORDERED_LIST_ITEM] = { other: 'ctrl + shift + 7', macOS: '⌘ + shift + 7' };
KEYBOARD_SHORTCUTS[ENTITY_TYPE.LINK] = { other: 'ctrl + K', macOS: '⌘ + K' };
KEYBOARD_SHORTCUTS[BR_TYPE] = { other: 'shift + enter', macOS: 'shift + enter' };
KEYBOARD_SHORTCUTS[INLINE_STYLE.BOLD] = { other: 'ctrl + B', macOS: '⌘ + B' };
KEYBOARD_SHORTCUTS[INLINE_STYLE.ITALIC] = { other: 'ctrl + I', macOS: '⌘ + I' };
KEYBOARD_SHORTCUTS[INLINE_STYLE.UNDERLINE] = { other: 'ctrl + U', macOS: '⌘ + U' };
KEYBOARD_SHORTCUTS[INLINE_STYLE.STRIKETHROUGH] = { other: 'alt + shift + 5', macOS: 'option + shift + 5' };
var NBSP = exports.NBSP = '\xA0';

@@ -64,0 +83,0 @@

@@ -24,2 +24,8 @@ 'use strict';

describe('#BR_TYPE', function () {
it('exists', function () {
expect(_constants.BR_TYPE).toBeDefined();
});
});
describe('#KEY_CODES', function () {

@@ -31,2 +37,8 @@ it('exists', function () {

describe('#KEYBOARD_SHORTCUTS', function () {
it('exists', function () {
expect(_constants.KEYBOARD_SHORTCUTS).toBeDefined();
});
});
describe('#NBSP', function () {

@@ -33,0 +45,0 @@ it('exists', function () {

@@ -11,24 +11,21 @@ 'use strict';

var stubs = {
emptyContent: {},
realContent: {
entityMap: {},
blocks: [{
key: '1dcqo',
text: 'Hello, World!',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {}
}, {
key: 'dmtba',
text: 'This is a title',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {}
}]
}
var stubContent = {
entityMap: {},
blocks: [{
key: '1dcqo',
text: 'Hello, World!',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {}
}, {
key: 'dmtba',
text: 'This is a title',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {}
}]
};

@@ -43,3 +40,3 @@

it('creates empty state from empty content', function () {
var state = _conversion2.default.createEditorState(stubs.emptyContent);
var state = _conversion2.default.createEditorState({});
var result = (0, _draftJs.convertToRaw)(state.getCurrentContent());

@@ -51,3 +48,3 @@ expect(result.blocks.length).toEqual(1);

it('creates state from real content', function () {
var state = _conversion2.default.createEditorState(stubs.realContent);
var state = _conversion2.default.createEditorState(stubContent);
var result = (0, _draftJs.convertToRaw)(state.getCurrentContent());

@@ -64,12 +61,19 @@ expect(result.blocks.length).toEqual(2);

it('keeps real content', function () {
var state = _conversion2.default.createEditorState(stubContent);
expect(_conversion2.default.serialiseEditorState(state)).toEqual(stubContent);
});
it('discards empty content', function () {
var state = _conversion2.default.createEditorState(stubs.emptyContent);
expect(_conversion2.default.serialiseEditorState(state)).toEqual(stubs.emptyContent);
var state = _conversion2.default.createEditorState({});
expect(_conversion2.default.serialiseEditorState(state)).toEqual({});
});
it('keeps real content', function () {
var state = _conversion2.default.createEditorState(stubs.realContent);
expect(_conversion2.default.serialiseEditorState(state)).toEqual(stubs.realContent);
it('discards content with only empty text', function () {
var contentBlocks = (0, _draftJs.convertFromHTML)('<h1> </h1>');
var contentState = _draftJs.ContentState.createFromBlockArray(contentBlocks);
var editorState = _draftJs.EditorState.createWithContent(contentState);
expect(_conversion2.default.serialiseEditorState(editorState)).toEqual({});
});
});
});

@@ -31,2 +31,4 @@ 'use strict';

getAllBlocks: _draftjsUtils2.default.getAllBlocks.bind(_draftjsUtils2.default),
/**

@@ -75,10 +77,10 @@ * Creates a selection for the entirety of an entity that can be partially selected.

// TODO Document.
// TODO Refactor to be a shortcut rather than use `Modifier`.
createEntity: function createEntity(editorState, entityType, entityData, entityText) {
var entityMutability = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'IMMUTABLE';
var entityKey = _draftJs.Entity.create(entityType, entityMutability, entityData);
var contentState = editorState.getCurrentContent();
var selection = editorState.getSelection();
var contentStateWithEntity = contentState.createEntity(entityType, entityMutability, entityData);
var entityKey = contentStateWithEntity.getLastCreatedEntityKey();

@@ -88,5 +90,5 @@ var nextContentState = void 0;

if (selection.isCollapsed()) {
nextContentState = _draftJs.Modifier.insertText(contentState, editorState.getSelection(), entityText, null, entityKey);
nextContentState = _draftJs.Modifier.insertText(contentState, selection, entityText, null, entityKey);
} else {
nextContentState = _draftJs.Modifier.replaceText(contentState, editorState.getSelection(), entityText, null, entityKey);
nextContentState = _draftJs.Modifier.replaceText(contentState, selection, entityText, null, entityKey);
}

@@ -98,4 +100,13 @@

},
/**
* Inserts a horizontal rule in the place of the current selection.
* Returns updated EditorState.
* Inspired by DraftUtils.addLineBreakRemovingSelection.
*/
addHorizontalRuleRemovingSelection: function addHorizontalRuleRemovingSelection(editorState) {
var entityKey = _draftJs.Entity.create(_constants.ENTITY_TYPE.HORIZONTAL_RULE, 'IMMUTABLE', {});
var contentState = editorState.getCurrentContent();
var contentStateWithEntity = contentState.createEntity(_constants.ENTITY_TYPE.HORIZONTAL_RULE, 'IMMUTABLE', {});
var entityKey = contentStateWithEntity.getLastCreatedEntityKey();
var nextState = _draftJs.AtomicBlockUtils.insertAtomicBlock(editorState, entityKey, ' ');

@@ -105,2 +116,8 @@

},
/**
* Changes a block type to be `newType`. Other attributes of the block
* can also be changed at the same time with `overrides`.
*/
resetBlockWithType: function resetBlockWithType(editorState, newType) {

@@ -126,3 +143,26 @@ var overrides = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

return _draftJs.EditorState.push(editorState, newContentState, 'change-block-type');
},
/**
* Reset the depth of all the content to be at most maxListNesting.
* Meant to be used after a paste of non-constrained list items.
*/
normaliseBlockDepth: function normaliseBlockDepth(editorState, maxListNesting) {
var contentState = editorState.getCurrentContent();
var blockMap = contentState.getBlockMap();
var blocks = blockMap.filter(function (block) {
return block.getDepth() > maxListNesting;
}).map(function (block) {
return block.set('depth', maxListNesting);
});
blockMap = blockMap.merge(blocks);
contentState = contentState.merge({ blockMap: blockMap });
// Use an immutable `set` instead of the `push` API to prevent undo.
return _draftJs.EditorState.set(editorState, {
currentContent: contentState
});
}
};

@@ -42,2 +42,8 @@ 'use strict';

describe('#getAllBlocks', function () {
it('exists', function () {
expect(_DraftUtils2.default.getAllBlocks).toBeDefined();
});
});
describe('#isSelectedBlockType', function () {

@@ -56,3 +62,4 @@ it('exists', function () {

});
var entityKey = _draftJs.Entity.create('LINK', 'MUTABLE', { url: 'www.testing.com' });
var contentStateWithEntity = contentState.createEntity('LINK', 'MUTABLE', { url: 'www.testing.com' });
var entityKey = contentStateWithEntity.getLastCreatedEntityKey();
editorState = _draftJs.RichUtils.toggleLink(editorState, updatedSelection, entityKey);

@@ -70,3 +77,4 @@ expect(_DraftUtils2.default.isSelectedBlockType(editorState, 'header-one')).toBeTruthy();

});
var entityKey = _draftJs.Entity.create('LINK', 'MUTABLE', { url: 'www.testing.com' });
var contentStateWithEntity = contentState.createEntity('LINK', 'MUTABLE', { url: 'www.testing.com' });
var entityKey = contentStateWithEntity.getLastCreatedEntityKey();
editorState = _draftJs.RichUtils.toggleLink(editorState, updatedSelection, entityKey);

@@ -90,3 +98,4 @@ expect(_DraftUtils2.default.isSelectedBlockType(editorState, 'header-two')).toBeFalsy();

});
var entityKey = _draftJs.Entity.create('LINK', 'MUTABLE', { url: 'www.testing.com' });
var contentStateWithEntity = contentState.createEntity('LINK', 'MUTABLE', { url: 'www.testing.com' });
var entityKey = contentStateWithEntity.getLastCreatedEntityKey();
editorState = _draftJs.RichUtils.toggleLink(editorState, updatedSelection, entityKey);

@@ -96,2 +105,18 @@ expect(_DraftUtils2.default.getSelectedEntitySelection(editorState)).toBeInstanceOf(_draftJs.SelectionState);

});
describe('#normaliseBlockDepth', function () {
it('exists', function () {
expect(_DraftUtils2.default.normaliseBlockDepth).toBeDefined();
});
it('normalises depth to a given number', function () {
var contentBlocks = (0, _draftJs.convertFromHTML)('<ul>\n <li>Depth 0</li>\n <li><ul>\n <li>Depth 1</li>\n <li><ul><li>Depth 2</li></ul></li>\n </ul></li>\n </ul>');
var contentState = _draftJs.ContentState.createFromBlockArray(contentBlocks);
var editorState = _DraftUtils2.default.normaliseBlockDepth(_draftJs.EditorState.createWithContent(contentState), 1);
var blocks = _DraftUtils2.default.getAllBlocks(editorState);
expect(blocks.map(function (block) {
return block.getDepth();
}).toJS()).toEqual([0, 0, 0, 1, 1]);
});
});
});

@@ -17,3 +17,3 @@ 'use strict';

var stubProps = {
var mockProps = {
entity: {

@@ -40,7 +40,7 @@ getData: function getData() {

it('basic', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_EmbedBlock2.default, stubProps))).toMatchSnapshot();
expect((0, _enzyme.shallow)(_react2.default.createElement(_EmbedBlock2.default, mockProps))).toMatchSnapshot();
});
it('#isActive', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_EmbedBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_EmbedBlock2.default, _extends({}, mockProps, {
isActive: true

@@ -47,0 +47,0 @@ })))).toMatchSnapshot();

@@ -17,3 +17,3 @@ 'use strict';

var stubProps = {
var mockProps = {
entity: {

@@ -42,7 +42,7 @@ getData: function getData() {

it('basic', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, stubProps))).toMatchSnapshot();
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, mockProps))).toMatchSnapshot();
});
it('#isActive', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, mockProps, {
isActive: true

@@ -53,3 +53,3 @@ })))).toMatchSnapshot();

it('#entityConfig.imageFormats', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, mockProps, {
entityConfig: {

@@ -63,3 +63,3 @@ imageFormats: [{ label: 'Left', value: 'left' }, { label: 'Right', value: 'right' }]

it('#alignment', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, mockProps, {
entityConfig: {

@@ -73,7 +73,7 @@ imageFormats: [{ label: 'Left', value: 'left' }, { label: 'Right', value: 'right' }]

it('#onCancel', function () {
(0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, stubProps, {
(0, _enzyme.shallow)(_react2.default.createElement(_ImageBlock2.default, _extends({}, mockProps, {
isActive: true
}))).find('.button.no').simulate('click');
expect(stubProps.onCancel.mock.calls.length).toBe(1);
expect(mockProps.onCancel).toHaveBeenCalledTimes(1);
});
});

@@ -13,4 +13,2 @@ 'use strict';

var _draftJs = require('draft-js');
var _constants = require('../api/constants');

@@ -91,7 +89,9 @@

value: function onSave(nextData) {
var block = this.props.block;
var _props = this.props,
block = _props.block,
contentState = _props.contentState;
// This will update in place
_draftJs.Entity.mergeData(block.getEntityAt(0), nextData);
contentState.mergeEntityData(block.getEntityAt(0), nextData);
this.closeBlock();

@@ -127,2 +127,3 @@ }

block: _react2.default.PropTypes.object.isRequired,
contentState: _react2.default.PropTypes.object.isRequired,
blockProps: _react2.default.PropTypes.object.isRequired

@@ -129,0 +130,0 @@ };

@@ -19,3 +19,3 @@ 'use strict';

var stubProps = {
var mockProps = {
block: {},

@@ -27,3 +27,4 @@ blockProps: {

entityConfig: {}
}
},
contentState: {}
};

@@ -37,7 +38,7 @@

it('basic', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, stubProps))).toMatchSnapshot();
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, mockProps))).toMatchSnapshot();
});
it('image', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, mockProps, {
blockProps: { entity: { type: _constants.ENTITY_TYPE.IMAGE }, entityConfig: {} }

@@ -48,3 +49,3 @@ })))).toMatchSnapshot();

it('embed', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, mockProps, {
blockProps: { entity: { type: _constants.ENTITY_TYPE.EMBED }, entityConfig: {} }

@@ -55,3 +56,3 @@ })))).toMatchSnapshot();

it('#isActive', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, stubProps)).setState({
expect((0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, mockProps)).setState({
isActive: true

@@ -63,7 +64,15 @@ })).toMatchSnapshot();

var unlockEditor = jest.fn();
(0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, stubProps, {
blockProps: Object.assign({ unlockEditor: unlockEditor }, stubProps.blockProps)
(0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, mockProps, {
blockProps: Object.assign({ unlockEditor: unlockEditor }, mockProps.blockProps)
}))).instance().closeBlock();
expect(unlockEditor.mock.calls.length).toBe(1);
expect(unlockEditor).toHaveBeenCalledTimes(1);
});
it('#blockProps.lockEditor', function () {
var lockEditor = jest.fn();
(0, _enzyme.shallow)(_react2.default.createElement(_MediaBlock2.default, _extends({}, mockProps, {
blockProps: Object.assign({ lockEditor: lockEditor }, mockProps.blockProps)
}))).instance().onClick();
expect(lockEditor).toHaveBeenCalledTimes(1);
});
});

@@ -24,5 +24,6 @@ 'use strict';

var Button = function Button(_ref) {
var icon = _ref.icon,
var active = _ref.active,
label = _ref.label,
active = _ref.active,
title = _ref.title,
icon = _ref.icon,
onClick = _ref.onClick;

@@ -34,2 +35,3 @@ return _react2.default.createElement(

type: 'button',
title: title,
onMouseDown: onMouseDown.bind(null, onClick)

@@ -43,15 +45,17 @@ },

Button.propTypes = {
active: _react2.default.PropTypes.bool,
label: _react2.default.PropTypes.string,
onClick: _react2.default.PropTypes.func,
title: _react2.default.PropTypes.string,
icon: _react2.default.PropTypes.string,
active: _react2.default.PropTypes.bool
onClick: _react2.default.PropTypes.func
};
Button.defaultProps = {
active: false,
label: null,
onClick: function onClick() {},
title: null,
icon: null,
active: false
onClick: function onClick() {}
};
exports.default = Button;

@@ -40,5 +40,5 @@ 'use strict';

(0, _enzyme.shallow)(_react2.default.createElement(_Button2.default, { onClick: onClick })).simulate('mousedown', event);
expect(onClick.mock.calls.length).toBe(1);
expect(event.preventDefault.mock.calls.length).toBe(1);
expect(onClick).toHaveBeenCalledTimes(1);
expect(event.preventDefault).toHaveBeenCalledTimes(1);
});
});

@@ -71,2 +71,5 @@ 'use strict';

enableLineBreak: false,
// Disable copy/paste of rich text in the editor.
// TODO Make this false by default once copy/paste is better supported.
stripPastedStyles: true,
// List of the available entity types.

@@ -78,3 +81,3 @@ entityTypes: [],

inlineStyles: [],
// Max level of nesting for unordered and ordered lists.
// Max level of nesting for unordered and ordered lists. 0 = no nesting.
maxListNesting: 1,

@@ -90,2 +93,3 @@ // Frequency at which the save callback is triggered (ms).

enableLineBreak: _react2.default.PropTypes.bool,
stripPastedStyles: _react2.default.PropTypes.bool,
entityTypes: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.shape({

@@ -182,9 +186,21 @@ label: _react2.default.PropTypes.string.isRequired,

key: 'onChange',
value: function onChange(editorState) {
value: function onChange(nextEditorState) {
var _this2 = this;
var stateSaveInterval = this.props.stateSaveInterval;
var _props = this.props,
stateSaveInterval = _props.stateSaveInterval,
maxListNesting = _props.maxListNesting;
var editorState = this.state.editorState;
var contentState = editorState.getCurrentContent();
var nextContentState = nextEditorState.getCurrentContent();
this.setState({ editorState: editorState }, function () {
if (nextContentState !== contentState && nextEditorState.getLastChangeType() === 'insert-fragment') {
// eslint-disable-next-line no-param-reassign
nextEditorState = _DraftUtils2.default.normaliseBlockDepth(nextEditorState, maxListNesting);
}
this.setState({
editorState: nextEditorState
}, function () {
global.clearTimeout(_this2.updateTimeout);

@@ -239,2 +255,3 @@ _this2.updateTimeout = global.setTimeout(_this2.saveState, stateSaveInterval);

var contentState = editorState.getCurrentContent();
var ret = false;

@@ -251,3 +268,3 @@

if (entityKey) {
var entityData = _draftJs.Entity.get(entityKey).getData();
var entityData = contentState.getEntity(entityKey).getData();

@@ -375,3 +392,4 @@ if (entityData.url) {

var entity = _draftJs.Entity.get(entityKey);
var contentState = editorState.getCurrentContent();
var entity = contentState.getEntity(entityKey);

@@ -419,2 +437,3 @@ // TODO It seems strange to update the selection state when requesting an edit.

var contentState = editorState.getCurrentContent();
var entity = void 0;

@@ -426,3 +445,3 @@ var isHorizontalRule = void 0;

case _constants.BLOCK_TYPE.ATOMIC:
entity = _draftJs.Entity.get(block.getEntityAt(0));
entity = contentState.getEntity(block.getEntityAt(0));
isHorizontalRule = entity.type === _constants.ENTITY_TYPE.HORIZONTAL_RULE;

@@ -465,5 +484,6 @@

var contentState = editorState.getCurrentContent();
var entityKey = _DraftUtils2.default.getSelectionEntity(editorState);
this.toggleDialog(entityType, entityKey ? _draftJs.Entity.get(entityKey) : null);
this.toggleDialog(entityType, entityKey ? contentState.getEntity(entityKey) : null);
}

@@ -520,4 +540,7 @@ }, {

value: function renderTooltip() {
var shouldShowTooltip = this.state.shouldShowTooltip;
var _state2 = this.state,
editorState = _state2.editorState,
shouldShowTooltip = _state2.shouldShowTooltip;
var contentState = editorState.getCurrentContent();
var entityKey = this.tooltip && this.tooltip.getAttribute('data-tooltip');

@@ -531,3 +554,3 @@

onEdit: this.onEditEntity.bind(this, entityKey),
entityData: _draftJs.Entity.get(entityKey).getData(),
entityData: contentState.getEntity(entityKey).getData(),
position: {

@@ -545,11 +568,12 @@ top: this.tooltip.getBoundingClientRect().top + document.body.scrollTop + this.tooltip.offsetHeight,

var _props = this.props,
enableHorizontalRule = _props.enableHorizontalRule,
enableLineBreak = _props.enableLineBreak,
blockTypes = _props.blockTypes,
inlineStyles = _props.inlineStyles,
entityTypes = _props.entityTypes;
var _state2 = this.state,
editorState = _state2.editorState,
readOnly = _state2.readOnly;
var _props2 = this.props,
enableHorizontalRule = _props2.enableHorizontalRule,
enableLineBreak = _props2.enableLineBreak,
stripPastedStyles = _props2.stripPastedStyles,
blockTypes = _props2.blockTypes,
inlineStyles = _props2.inlineStyles,
entityTypes = _props2.entityTypes;
var _state3 = this.state,
editorState = _state3.editorState,
readOnly = _state3.readOnly;

@@ -587,2 +611,3 @@ /* eslint-disable jsx-a11y/no-static-element-interactions */

readOnly: readOnly,
stripPastedStyles: stripPastedStyles,
handleReturn: this.handleReturn,

@@ -589,0 +614,0 @@ keyBindingFn: _behavior2.default.getKeyBindingFn(blockTypes, inlineStyles, entityTypes),

@@ -19,2 +19,8 @@ 'use strict';

var _constants = require('../api/constants');
var _behavior = require('../api/behavior');
var _behavior2 = _interopRequireDefault(_behavior);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -42,2 +48,3 @@

label: block.label,
title: _behavior2.default.getKeyboardShortcut(block.type),
icon: block.icon,

@@ -52,2 +59,3 @@ onClick: toggleBlockType.bind(null, block.type)

label: style.label,
title: _behavior2.default.getKeyboardShortcut(style.type),
icon: style.icon,

@@ -63,3 +71,4 @@ onClick: toggleInlineStyle.bind(null, style.type)

onClick: addBR,
label: 'BR'
label: 'BR',
title: _behavior2.default.getKeyboardShortcut(_constants.BR_TYPE)
}) : null,

@@ -71,2 +80,3 @@ entityTypes.map(function (entity) {

label: entity.label,
title: _behavior2.default.getKeyboardShortcut(entity.type),
icon: entity.icon

@@ -73,0 +83,0 @@ });

@@ -17,3 +17,3 @@ 'use strict';

var stubProps = {
var mockProps = {
position: {

@@ -34,7 +34,7 @@ top: 0,

it('basic', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, stubProps))).toMatchSnapshot();
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, mockProps))).toMatchSnapshot();
});
it('#entityData.url', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, _extends({}, mockProps, {
entityData: {

@@ -47,3 +47,3 @@ url: 'http://www.example.com/'

it('#entityData.label', function () {
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, _extends({}, stubProps, {
expect((0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, _extends({}, mockProps, {
entityData: {

@@ -56,10 +56,10 @@ label: 'Test label'

it('#onEdit', function () {
(0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, stubProps)).find('button').first().simulate('click');
expect(stubProps.onEdit.mock.calls.length).toBe(1);
(0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, mockProps)).find('button').first().simulate('click');
expect(mockProps.onEdit).toHaveBeenCalledTimes(1);
});
it('#onRemove', function () {
(0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, stubProps)).find('button').last().simulate('click');
expect(stubProps.onRemove.mock.calls.length).toBe(1);
(0, _enzyme.shallow)(_react2.default.createElement(_Tooltip2.default, mockProps)).find('button').last().simulate('click');
expect(mockProps.onRemove).toHaveBeenCalledTimes(1);
});
});
{
"name": "draftail",
"version": "0.4.1",
"version": "0.5.0",
"description": "A batteries-excluded rich text editor based on Draft.js",

@@ -38,23 +38,25 @@ "author": "Springload",

},
"dependencies": {},
"dependencies": {
"draftjs-utils": "0.6.0",
"immutable": "^3.0.0"
},
"devDependencies": {
"babel-core": "^6.18.2",
"babel-cli": "^6.22.2",
"babel-jest": "^18.0.0",
"babel-loader": "^6.2.7",
"babel-loader": "^6.2.10",
"babel-preset-latest": "^6.16.0",
"babel-preset-react": "^6.16.0",
"coveralls": "^2.11.15",
"draft-js": "^0.9.1",
"draftjs-utils": "^0.3.2",
"dotenv": "^4.0.0",
"draft-js": "^0.10.0",
"enzyme": "^2.7.0",
"enzyme-to-json": "^1.4.5",
"eslint": "^3.9.1",
"eslint-config-airbnb": "^13.0.0",
"eslint": "^3.13.1",
"eslint-config-airbnb": "^14.0.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.6.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.9.0",
"express": "^4.14.0",
"immutable": "^3.8.1",
"jest": "^18.1.0",
"node-sass": "^3.11.2",
"node-sass": "^4.3.0",
"progress-bar-webpack-plugin": "^1.9.0",

@@ -69,7 +71,5 @@ "react": "^15.4.1",

"peerDependencies": {
"draft-js": "0.9.1",
"draftjs-utils": "0.3.2",
"immutable": "^3.x.x",
"react": "^15.x.x",
"react-dom": "^15.x.x"
"draft-js": "^0.10.0",
"react": "^15.0.0",
"react-dom": "^15.0.0"
},

@@ -76,0 +76,0 @@ "scripts": {

@@ -8,10 +8,46 @@ [draftail](https://springload.github.io/draftail/) [![npm](https://img.shields.io/npm/v/draftail.svg?style=flat-square)](https://www.npmjs.com/package/draftail) [![Build Status](https://travis-ci.org/springload/draftail.svg?branch=master)](https://travis-ci.org/springload/draftail) [![Coverage Status](https://coveralls.io/repos/github/springload/draftail/badge.svg)](https://coveralls.io/github/springload/draftail) [![Dependency Status](https://david-dm.org/springload/draftail.svg?style=flat-square)](https://david-dm.org/springload/draftail) [![devDependency Status](https://david-dm.org/springload/draftail/dev-status.svg?style=flat-square)](https://david-dm.org/springload/draftail#info=devDependencies) [![Code Climate](https://codeclimate.com/github/springload/draftail/badges/gpa.svg)](https://codeclimate.com/github/springload/draftail)

## Usage
First, grab the package from npm:
```sh
npm install --save draftail
# Draftail's peerDependencies:
npm install --save draft-js@^0.9.x draftjs-utils@^0.3.2 immutable@^3.x.x react@^15.x.x react-dom@^15.x.x
npm install --save draft-js@^0.10.0 react@^15.0.0 react-dom@^15.0.0
# Note: Draft.js builds upon ES6 language features. If targeting browsers that do not support them,
# see https://facebook.github.io/draft-js/docs/advanced-topics-issues-and-pitfalls.html#polyfills.
```
[ES6 polyfills for Draft.js](https://facebook.github.io/draft-js/docs/advanced-topics-issues-and-pitfalls.html#polyfills) are also required.
Then, import the editor and use it in your code. Here is a [basic example](https://springload.github.io/draftail/example.html):
```js
import React from 'react';
import ReactDOM from 'react-dom';
import DraftailEditor, { BLOCK_TYPE, INLINE_STYLE } from 'draftail';
const initialContentState = JSON.parse(sessionStorage.getItem('basic:contentState')) || {};
const onSave = (contentState) => {
sessionStorage.setItem('basic:contentState', JSON.stringify(contentState));
};
const editor = (
<DraftailEditor
rawContentState={initialContentState}
onSave={onSave}
blockTypes={[
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'UL', type: BLOCK_TYPE.UNORDERED_LIST_ITEM, icon: 'icon-list-ul' },
]}
inlineStyles={[
{ label: 'Bold', type: INLINE_STYLE.BOLD, icon: 'icon-bold' },
{ label: 'Italic', type: INLINE_STYLE.ITALIC, icon: 'icon-italic' },
]}
/>
);
ReactDOM.render(editor, document.querySelector('[data-mount-basic]'));
```
## Development

@@ -27,4 +63,6 @@

npm install
# Optionally, install the git hooks.
# Install the git hooks.
./.githooks/deploy
# Set up a `.env` file with the appropriate secrets.
touch .env
```

@@ -31,0 +69,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc