Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
[WIP] Moving entities into content state #185 (#376)
Browse files Browse the repository at this point in the history
* Initial demo changeset for entities in content state

* lowercase string

* add entity methods to content state

* remove `DraftEntity` module

* remove some `DraftEntity` requires

* fix linting issues

* fix flow issues

* update `DraftPasteProcessor` and `convertFromHTMLtoContentBlocks` to work with passed-in `ContentState` instance

* remove last traces of `DraftEntity` module

* allow second argument for `createFromBlockArray`

* use `contentState.getEntity` instead of pulling out entity map first

* match exported function name

* re-sort requires/imports to: classes, functions, types

* respect 80 char limit

* switch from random entity key to number

* pass around `EntityMap` instance instead of `ContentState` when creating new html fragment

* set new `entityMap` when regenerating block tree during editor state update, as the "current" content does not yet contain it

* change entity key to be a numerical string to prevent enity-not-found error  when using stringified key

* fix flow errors
  • Loading branch information
johanneslumpe authored and Isaac Salier-Hellendag committed Sep 14, 2016
1 parent 4e4ad98 commit 5d5f1b4
Show file tree
Hide file tree
Showing 39 changed files with 541 additions and 401 deletions.
6 changes: 3 additions & 3 deletions examples/entity/entity.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,14 @@
}

function getEntityStrategy(mutability) {
return function(contentBlock, callback) {
return function(contentState, contentBlock, callback) {
contentBlock.findEntityRanges(
(character) => {
const entityKey = character.getEntity();
if (entityKey === null) {
return false;
}
return Entity.get(entityKey).getMutability() === mutability;
return contentState.getEntity(entityKey).getMutability() === mutability;
},
callback
);
Expand All @@ -174,7 +174,7 @@

const TokenSpan = (props) => {
const style = getDecoratedStyle(
Entity.get(props.entityKey).getMutability()
props.contentState.getEntity(props.entityKey).getMutability()
);
return (
<span {...props} style={style}>
Expand Down
15 changes: 9 additions & 6 deletions examples/link/link.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,14 @@
_confirmLink(e) {
e.preventDefault();
const {editorState, urlValue} = this.state;
const entityKey = Entity.create('LINK', 'MUTABLE', {url: urlValue});
const contentState = editorState.getCurrentContent();
const contentStateWithEntity = Entity.create(contentState, 'LINK', 'MUTABLE', {url: urlValue});
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
const newEditorState = EditorState.set(editorState, { currentContent: contentStateWithEntity });
this.setState({
editorState: RichUtils.toggleLink(
editorState,
editorState.getSelection(),
newEditorState,
newEditorState.getSelection(),
entityKey
),
showURLInput: false,
Expand Down Expand Up @@ -173,21 +176,21 @@
}
}

function findLinkEntities(contentBlock, callback) {
function findLinkEntities(contentState, contentBlock, callback) {
contentBlock.findEntityRanges(
(character) => {
const entityKey = character.getEntity();
return (
entityKey !== null &&
Entity.get(entityKey).getType() === 'LINK'
contentState.getEntity(entityKey).getType() === 'LINK'
);
},
callback
);
}

const Link = (props) => {
const {url} = Entity.get(props.entityKey).getData();
const {url} = props.contentState.getEntity(props.entityKey).getData();
return (
<a href={url} style={styles.link}>
{props.children}
Expand Down
2 changes: 0 additions & 2 deletions src/Draft.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const DefaultDraftInlineStyle = require('DefaultDraftInlineStyle');
const DraftEditor = require('DraftEditor.react');
const DraftEditorBlock = require('DraftEditorBlock.react');
const DraftModifier = require('DraftModifier');
const DraftEntity = require('DraftEntity');
const DraftEntityInstance = require('DraftEntityInstance');
const EditorState = require('EditorState');
const KeyBindingUtil = require('KeyBindingUtil');
Expand All @@ -43,7 +42,6 @@ const DraftPublic = {
EditorState,

CompositeDecorator: CompositeDraftDecorator,
Entity: DraftEntity,
EntityInstance: DraftEntityInstance,

BlockMapBuilder,
Expand Down
3 changes: 3 additions & 0 deletions src/component/contents/DraftEditorBlock.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
'use strict';

const ContentBlock = require('ContentBlock');
const ContentState = require('ContentState');
const DraftEditorLeaf = require('DraftEditorLeaf.react');
const DraftOffsetKey = require('DraftOffsetKey');
const React = require('React');
Expand All @@ -37,6 +38,7 @@ import type {List} from 'immutable';
const SCROLL_BUFFER = 10;

type Props = {
contentState: ContentState,
block: ContentBlock,
customStyleMap: Object,
customStyleFn: Function,
Expand Down Expand Up @@ -184,6 +186,7 @@ class DraftEditorBlock extends React.Component {
return (
<DecoratorComponent
{...decoratorProps}
contentState={this.props.contentState}
decoratedText={decoratedText}
dir={dir}
key={decoratorOffsetKey}
Expand Down
1 change: 1 addition & 0 deletions src/component/contents/DraftEditorContents.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class DraftEditorContents extends React.Component {
const direction = directionMap.get(key);
const offsetKey = DraftOffsetKey.encode(key, 0, 0);
const componentProps = {
contentState: content,
block,
blockProps: customProps,
customStyleMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jest.disableAutomock()
.mock('getScrollPosition')
.mock('getViewportDimensions');

var ContentState = require('ContentState');
var BlockTree = require('BlockTree');
var CharacterMetadata = require('CharacterMetadata');
var ContentBlock = require('ContentBlock');
Expand Down Expand Up @@ -100,7 +101,7 @@ function getSelection() {
function getProps(block, decorator) {
return {
block,
tree: BlockTree.generate(block, decorator),
tree: BlockTree.generate(ContentState.createFromText(''), block, decorator),
selection: getSelection(),
decorator: decorator || null,
forceSelection: false,
Expand Down Expand Up @@ -249,7 +250,11 @@ describe('DraftEditorBlock.react', () => {
);
var decorator = new Decorator();

var newTree = BlockTree.generate(helloBlock, decorator);
var newTree = BlockTree.generate(
ContentState.createFromText(helloBlock.getText()),
helloBlock,
decorator
);
var nextProps = {...props, tree: newTree, decorator};

expect(props.tree).not.toBe(nextProps.tree);
Expand Down
3 changes: 1 addition & 2 deletions src/component/handlers/edit/editOnInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
var DraftModifier = require('DraftModifier');
var DraftOffsetKey = require('DraftOffsetKey');
var EditorState = require('EditorState');
var Entity = require('DraftEntity');
var UserAgent = require('UserAgent');

var findAncestorOffsetKey = require('findAncestorOffsetKey');
Expand Down Expand Up @@ -81,7 +80,7 @@ function editOnInput(): void {
});

const entityKey = block.getEntityAt(start);
const entity = entityKey && Entity.get(entityKey);
const entity = entityKey && content.getEntity(entityKey);
const entityType = entity && entity.getMutability();
const preserveEntity = entityType === 'MUTABLE';

Expand Down
22 changes: 15 additions & 7 deletions src/component/handlers/edit/editOnPaste.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ var EditorState = require('EditorState');

var getEntityKeyForSelection = require('getEntityKeyForSelection');
var getTextContentFromFiles = require('getTextContentFromFiles');
const isEventHandled = require('isEventHandled');
var splitTextIntoTextBlocks = require('splitTextIntoTextBlocks');

import type {BlockMap} from 'BlockMap';
const isEventHandled = require('isEventHandled');

import type {EntityMap} from 'EntityMap';
/**
* Paste content.
*/
Expand Down Expand Up @@ -150,9 +150,14 @@ function editOnPaste(e: SyntheticClipboardEvent): void {
this.props.blockRenderMap
);
if (htmlFragment) {
var htmlMap = BlockMapBuilder.createFromArray(htmlFragment);
this.update(insertFragment(this.props.editorState, htmlMap));
return;
const { contentBlocks, entityMap } = htmlFragment;
if (contentBlocks) {
var htmlMap = BlockMapBuilder.createFromArray(contentBlocks);
this.update(
insertFragment(this.props.editorState, htmlMap, entityMap)
);
return;
}
}
}

Expand Down Expand Up @@ -183,16 +188,19 @@ function editOnPaste(e: SyntheticClipboardEvent): void {

function insertFragment(
editorState: EditorState,
fragment: BlockMap
fragment: BlockMap,
entityMap: ?EntityMap,
): EditorState {
var newContent = DraftModifier.replaceWithFragment(
editorState.getCurrentContent(),
editorState.getSelection(),
fragment
);
const mergedEntityMap = newContent.getEntityMap().merge(entityMap);

return EditorState.push(
editorState,
newContent,
newContent.set('entityMap', mergedEntityMap),
'insert-fragment'
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/model/decorators/CompositeDraftDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var Immutable = require('immutable');

import type ContentBlock from 'ContentBlock';
import type {DraftDecorator} from 'DraftDecorator';
import type ContentState from 'ContentState';

var {List} = Immutable;

Expand Down Expand Up @@ -51,14 +52,14 @@ class CompositeDraftDecorator {
this._decorators = decorators.slice();
}

getDecorations(block: ContentBlock): List<?string> {
getDecorations(contentState: ContentState, block: ContentBlock): List<?string> {
var decorations = Array(block.getText().length).fill(null);

this._decorators.forEach(
(/*object*/ decorator, /*number*/ ii) => {
var counter = 0;
var strategy = decorator.strategy;
strategy(block, (/*number*/ start, /*number*/ end) => {
strategy(contentState, block, (/*number*/ start, /*number*/ end) => {
// Find out if any of our matching range is already occupied
// by another decorator. If so, discard the match. Otherwise, store
// the component key for rendering.
Expand Down
2 changes: 2 additions & 0 deletions src/model/decorators/DraftDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
'use strict';

import type ContentBlock from 'ContentBlock';
import type ContentState from 'ContentState';

/**
* A DraftDecorator is a strategy-component pair intended for use when
Expand All @@ -31,6 +32,7 @@ import type ContentBlock from 'ContentBlock';
*/
export type DraftDecorator = {
strategy: (
contentState: ContentState,
block: ContentBlock,
callback: (start: number, end: number) => void
) => void,
Expand Down
3 changes: 2 additions & 1 deletion src/model/decorators/DraftDecoratorType.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
'use strict';

import type ContentBlock from 'ContentBlock';
import type ContentState from 'ContentState';
import type {List} from 'immutable';

/**
Expand All @@ -25,7 +26,7 @@ export type DraftDecoratorType = {
/**
* Given a `ContentBlock`, return an immutable List of decorator keys.
*/
getDecorations(block: ContentBlock): List<?string>,
getDecorations(contentState: ContentState, block: ContentBlock): List<?string>,

/**
* Given a decorator key, return the component to use when rendering
Expand Down
24 changes: 16 additions & 8 deletions src/model/decorators/__tests__/CompositeDraftDecorator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
jest.unmock('CompositeDraftDecorator');

var CompositeDraftDecorator = require('CompositeDraftDecorator');
const ContentState = require('ContentState');

describe('CompositeDraftDecorator', () => {
class ContentBlock {
Expand All @@ -25,7 +26,7 @@ describe('CompositeDraftDecorator', () => {
}

function searchWith(regex) {
return function(block, callback) {
return function(contentState, block, callback) {
var text = block.getText();
text.replace(
regex,
Expand Down Expand Up @@ -81,7 +82,8 @@ describe('CompositeDraftDecorator', () => {
var composite = getCompositeDecorator();
var text = 'take a sad song and make it better';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();
expect(decorations.length).toBe(text.length);
expect(decorations).toEqual(Array(text.length).fill(null));
});
Expand All @@ -90,7 +92,8 @@ describe('CompositeDraftDecorator', () => {
var composite = getCompositeDecorator();
var text = 'a footballing fool';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();
expect(decorations.length).toBe(text.length);

expect(isOccupied(decorations.slice(2, 5))).toBe(true);
Expand All @@ -108,7 +111,8 @@ describe('CompositeDraftDecorator', () => {
var composite = getCompositeDecorator();
var text = 'a foosball bar';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();

// Match the "Foo" decorator.
expect(isOccupied(decorations.slice(2, 5))).toBe(true);
Expand All @@ -129,7 +133,8 @@ describe('CompositeDraftDecorator', () => {
var composite = getCompositeDecorator();
var text = 'some bar food';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();

// Match the "Foo" decorator.
expect(isOccupied(decorations.slice(9, 12))).toBe(true);
Expand All @@ -148,7 +153,8 @@ describe('CompositeDraftDecorator', () => {

var text = 'bart has a bar';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();

// Even though "bart" matches our "bar" strategy, "bart" comes first
// in our decoration order and will claim those letters first.
Expand All @@ -172,7 +178,8 @@ describe('CompositeDraftDecorator', () => {

var text = 'bart has a bar';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();

// "bar" comes first and claims two strings.
expect(isOccupied(decorations.slice(0, 3))).toBe(true);
Expand All @@ -194,7 +201,8 @@ describe('CompositeDraftDecorator', () => {

var text = 'barbarbar';
var content = new ContentBlock(text);
var decorations = composite.getDecorations(content).toArray();
var contentState = ContentState.createFromText(text);
var decorations = composite.getDecorations(contentState, content).toArray();

expect(isOccupied(decorations.slice(0, 3))).toBe(true);
expect(decorations[0]).toEqual(decorations[2]);
Expand Down
3 changes: 1 addition & 2 deletions src/model/encoding/convertFromDraftStateToRaw.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

'use strict';

var DraftEntity = require('DraftEntity');
var DraftStringKey = require('DraftStringKey');

var encodeEntityRanges = require('encodeEntityRanges');
Expand Down Expand Up @@ -58,7 +57,7 @@ function convertFromDraftStateToRaw(
var entityKeys = Object.keys(entityStorageMap);
var flippedStorageMap = {};
entityKeys.forEach((key, jj) => {
var entity = DraftEntity.get(DraftStringKey.unstringify(key));
var entity = contentState.getEntity(DraftStringKey.unstringify(key));
flippedStorageMap[jj] = {
type: entity.getType(),
mutability: entity.getMutability(),
Expand Down
Loading

0 comments on commit 5d5f1b4

Please sign in to comment.