Skip to content

Commit

Permalink
Merge pull request #30 from springload/feature/overhaul. Fix #2 Fix #3
Browse files Browse the repository at this point in the history
…Fix #28

Editor overhaul
  • Loading branch information
thibaudcolas authored Nov 27, 2016
2 parents 93f6017 + 7450d9a commit 1bc482d
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 71 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ There are other, not so explicit dependencies at the moment:

- jQuery 2, separately loaded onto the page.
- Specific styles from Wagtail, including its icon font.
- ES6 polyfill (like for Draft.js)

## Development

Expand Down
55 changes: 55 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
draftail documentation
======================

## Editor behavior

### Keyboard shortcuts

We support most of the common keyboard shortcuts users would expect to find in text editors thanks to [Draft.js key bindings](https://facebook.github.io/draft-js/docs/advanced-topics-key-bindings.html).

Here are the most important shortcuts:

|Shortcut|Function|
|--------|--------|
|Cmd + B | Bolden text (if enabled) |
|Cmd + I | Italicise text (if enabled) |
|Cmd + U | Underline text (if enabled) |
|Cmd + J | Format as code (if enabled) |
|Cmd + Z | Undo |
|Cmd + Maj + Z | Redo |
|Cmd + Left | Move selection to start of block |
|Cmd + Right | Move selection to end of block |
|Cmd + Tab|Increase indentation of list items|
|Cmd + Maj + Tab|Decrease indentation of list items|

Other shortcuts we would like to support in the future:

|Shortcut|Function|
|--------|--------|
|Cmd + Option + 1/2/3/4/5/6 | Format as heading level |
|Cmd + Option + 0 | Format as paragraph |
|Cmd + K | Create a link (if enabled) |

### Expected behavior

### Unsupported scenarios

- Nesting `ol` inside `ul` or the other way around.

## R&D notes

### Other Draft.js editors

> Full list on https://github.com/nikgraf/awesome-draft-js
Other approaches:

- https://github.com/ianstormtaylor/slate
- http://quilljs.com/

### Other Wagtail-integrated editors to learn from.

Things to borrow: keyboard shortcuts, Wagtail integration mechanism,

- https://github.com/jaydensmith/wagtailfroala
- https://github.com/isotoma/wagtailtinymce
13 changes: 7 additions & 6 deletions examples/assets/draftail.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@
margin-right: 4px;
margin-right: 0.25rem;
color: inherit;
border: 0;
cursor: pointer; }
.RichEditor-styleButton:hover {
color: inherit; }

.RichEditor-activeButton {
background: #666;
color: #fff; }
color: #ffffff; }
.RichEditor-activeButton:hover {
color: #fff; }
color: #ffffff; }

.RichEditor-tooltip__button {
appearance: none;
background: #808080;
color: #fff;
color: #ffffff;
padding: 0.25rem 0.5rem;
border: 0;
border-radius: 1px; }
Expand Down Expand Up @@ -58,7 +59,7 @@
justify-content: center; }

.Modal-content {
background: #fff;
background: #ffffff;
max-width: 500px; }

.Modal-header {
Expand Down Expand Up @@ -311,7 +312,7 @@
padding: 0.375rem 0.5rem;
margin-top: 0.5rem;
background-color: #333;
color: #fff;
color: #ffffff;
z-index: 1; }
.RichEditor-tooltip:before {
content: '';
Expand All @@ -328,7 +329,7 @@
display: inline-block; }

.RichEditor-tooltip__link:hover {
color: #fff; }
color: #ffffff; }

.RichEditor-tooltip__link:last-child {
margin-right: 0; }
Expand Down
12 changes: 10 additions & 2 deletions examples/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const options = {
],
};

const value = {
const rawContentState = {
entityMap: {},
blocks: [
{
Expand Down Expand Up @@ -223,8 +223,16 @@ const value = {
],
};

const onSave = (contentState) => {
console.log('Save basic example:', contentState);
};

const editor = (
<DraftailEditor name="basic" value={JSON.stringify(value)} options={options} />
<DraftailEditor
rawContentState={rawContentState}
options={options}
onSave={onSave}
/>
);

ReactDOM.render(editor, mount);
14 changes: 12 additions & 2 deletions examples/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,21 @@ const options = {
],
};

const saveField = document.createElement('input');
saveField.type = 'hidden';
mount.parentNode.appendChild(saveField);

const onSave = (rawContentState) => {
const serialised = JSON.stringify(rawContentState);
saveField.value = serialised;
localStorage.setItem('entities:rawContentState', serialised);
};

const editor = (
<DraftailEditor
name="test"
value="{}"
rawContentState={JSON.parse(localStorage.getItem('entities:rawContentState')) || {}}
options={options}
onSave={onSave}
/>
);

Expand Down
6 changes: 6 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,11 @@ <h3>Usage</h3>
<script src="assets/vendor.bundle.js"></script>
<script src="assets/basic.bundle.js"></script>
<script src="assets/entities.bundle.js"></script>

<script>
window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create','UA-79835767-6','auto');ga('send','pageview')
</script>
<script src="https://www.google-analytics.com/analytics.js" async defer></script>
</body>
</html>
17 changes: 8 additions & 9 deletions lib/api/conversion.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { EditorState, convertFromRaw, convertToRaw } from 'draft-js';

export default {
// Serialised RawDraftContentState => EditorState.
createEditorState(serialisedState, decorators) {
const rawState = JSON.parse(serialisedState);
// RawDraftContentState + decorators => EditorState.
createEditorState(rawContentState, decorators) {
let editorState;

if (rawState && Object.keys(rawState).length !== 0) {
const contentState = convertFromRaw(rawState);
if (rawContentState && Object.keys(rawContentState).length !== 0) {
const contentState = convertFromRaw(rawContentState);
editorState = EditorState.createWithContent(contentState, decorators);
} else {
editorState = EditorState.createEmpty(decorators);
Expand All @@ -16,17 +15,17 @@ export default {
return editorState;
},

// EditorState => Serialised RawDraftContentState.
// EditorState => RawDraftContentState.
serialiseEditorState(editorState) {
const contentState = editorState.getCurrentContent();
const rawContent = convertToRaw(contentState);
const rawContentState = convertToRaw(contentState);

const isEmpty = rawContent.blocks.every((block) => {
const isEmpty = rawContentState.blocks.every((block) => {
return block.text.trim().length === 0
&& block.entityRanges.length === 0
&& block.inlineStyleRanges.length === 0;
});

return JSON.stringify(isEmpty ? {} : rawContent);
return isEmpty ? {} : rawContentState;
},
};
6 changes: 3 additions & 3 deletions lib/api/conversion.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import conversion from '../api/conversion';
const emptyDecorator = new CompositeDecorator([]);

const stubs = {
emptyContent: JSON.stringify({}),
realContent: JSON.stringify({
emptyContent: {},
realContent: {
entityMap: {},
blocks: [
{
Expand All @@ -27,7 +27,7 @@ const stubs = {
data: {},
},
],
}),
},
};

describe('conversion', () => {
Expand Down
18 changes: 14 additions & 4 deletions lib/components/Button.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import React from 'react';

const onMouseDown = (onClick, e) => {
e.preventDefault();

onClick();
};

const Button = ({ icon, label, active, onClick }) => (
<a
href="#"
<button
className={`RichEditor-styleButton${active ? ' RichEditor-activeButton' : ''}${icon ? ` icon icon-${icon}` : ''}`}
onClick={onClick}
onMouseDown={onMouseDown.bind(null, onClick)}
>
{label}
</a>
</button>
);

Button.propTypes = {
Expand All @@ -17,4 +22,9 @@ Button.propTypes = {
active: React.PropTypes.bool,
};

Button.defaultProps = {
icon: '',
active: false,
};

export default Button;
13 changes: 13 additions & 0 deletions lib/components/Button.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import Button from '../components/Button';

describe('Button', () => {
it('exists', () => {
expect(Button).toBeDefined();
});

it('basic', () => {
expect(shallow(<Button label="Test" onClick={() => {}} />)).toBeDefined();
});
});
Loading

0 comments on commit 1bc482d

Please sign in to comment.