EditorCore.prototype.componentWillMount = function componentWillMount() { var plugins = this.initPlugins().concat([toolbar]); var customStyleMap = {}; var customBlockStyleMap = {}; var customBlockRenderMap = (0, _immutable.Map)(_draftJs.DefaultDraftBlockRenderMap); var compositeDecorator = new _draftJs.CompositeDecorator(plugins.filter(function (plugin) { return plugin.decorators !== undefined; }).map(function (plugin) { return plugin.decorators; }).reduce(function (prev, curr) { return prev.concat(curr); }, [])); var toolbarPlugins = (0, _immutable.List)(plugins.filter(function (plugin) { return !!plugin.component && plugin.name !== 'toolbar'; })); plugins.forEach(function (plugin) { var styleMap = plugin.styleMap, blockStyleMap = plugin.blockStyleMap, blockRenderMap = plugin.blockRenderMap; if (styleMap) { for (var key in styleMap) { if (styleMap.hasOwnProperty(key)) { customStyleMap[key] = styleMap[key]; } } } if (blockStyleMap) { for (var _key in blockStyleMap) { if (blockStyleMap.hasOwnProperty(_key)) { customBlockStyleMap[_key] = blockStyleMap[_key]; customBlockRenderMap = customBlockRenderMap.set(_key, { element: null }); } } } if (blockRenderMap) { for (var _key2 in blockRenderMap) { if (blockRenderMap.hasOwnProperty(_key2)) { customBlockRenderMap = customBlockRenderMap.set(_key2, blockRenderMap[_key2]); } } } }); configStore.set('customStyleMap', customStyleMap); configStore.set('customBlockStyleMap', customBlockStyleMap); configStore.set('blockRenderMap', customBlockRenderMap); configStore.set('customStyleFn', this.customStyleFn.bind(this)); this.setState({ toolbarPlugins: toolbarPlugins, compositeDecorator: compositeDecorator }); this.setEditorState(_draftJs.EditorState.set(this.state.editorState, { decorator: compositeDecorator })); };
constructor(props) { super(props); const customBlockRenderMap = Immutable.Map({ 'ticketDetails': { element: 'div', }, 'center': { element: 'div', }, 'left': { element: 'div', }, 'right': { element: 'div' } }); this.decorator = new PrismDecorator({defaultSyntax: 'javascript'}); this.state = { blockRenderMap: DefaultDraftBlockRenderMap.merge(customBlockRenderMap), editorState: EditorState.createEmpty(this.decorator), }; this.focus = () => this.refs.editor.focus(); this.onChange = (editorState) => { this.setState({editorState}); if(this.props.changeBody) this.props.changeBody({rawbody:convertToRaw(editorState.getCurrentContent()),body:editorState.getCurrentContent().getPlainText()}); }; this.submitClick = () => { this.props.submitComment({rawbody:convertToRaw(this.state.editorState.getCurrentContent()),body:this.state.editorState.getCurrentContent().getPlainText()}); this.setState({editorState: EditorState.createEmpty(this.decorator)}); } this.updateClick = () => { this.props.updateComment({rawbody:convertToRaw(this.state.editorState.getCurrentContent()),body:this.state.editorState.getCurrentContent().getPlainText()}); } this.ticketDetails = (ticketid) => this._ticketDetails(ticketid); this.color = (e) => this._color(e); this.colorClick = (e) => this._color(e); this.handleKeyCommand = (command) => this._handleKeyCommand(command); this.toggleBlockType = (type) => this._toggleBlockType(type); this.toggleInlineStyle = (style) => this._toggleInlineStyle(style); this.handlePaste = (f) => { var image = document.createElement('img'); image.src = window.URL.createObjectURL(f[0]); document.body.appendChild(image); } }
addLink: Function = (linkTitle, linkTarget, linkTargetOption): void => { const { editorState, onChange } = this.props; const { currentEntity } = this.state; let selection = editorState.getSelection(); if (currentEntity) { const entityRange = getEntityRange(editorState, currentEntity); selection = selection.merge({ anchorOffset: entityRange.start, focusOffset: entityRange.end, }); } const entityKey = editorState .getCurrentContent() .createEntity('LINK', 'MUTABLE', { url: linkTarget, target: linkTargetOption }) .getLastCreatedEntityKey(); let contentState = Modifier.replaceText( editorState.getCurrentContent(), selection, `${linkTitle}`, editorState.getCurrentInlineStyle(), entityKey, ); let newEditorState = EditorState.push(editorState, contentState, 'insert-characters'); // insert a blank space after link selection = newEditorState.getSelection().merge({ anchorOffset: selection.get('anchorOffset') + linkTitle.length, focusOffset: selection.get('anchorOffset') + linkTitle.length, }); newEditorState = EditorState.acceptSelection(newEditorState, selection); contentState = Modifier.insertText( newEditorState.getCurrentContent(), selection, ' ', newEditorState.getCurrentInlineStyle(), undefined, ); onChange(EditorState.push(newEditorState, contentState, 'insert-characters')); this.doCollapse(); };
const addMention = (editorState, mention, mentionPrefix, mentionTrigger, entityMutability) => { const contentStateWithEntity = editorState.getCurrentContent().createEntity( getTypeByTrigger(mentionTrigger), entityMutability, { mention } ); const entityKey = contentStateWithEntity.getLastCreatedEntityKey(); const currentSelectionState = editorState.getSelection(); const { begin, end } = getSearchText(editorState, currentSelectionState, mentionTrigger); // get selection of the @mention search text const mentionTextSelection = currentSelectionState.merge({ anchorOffset: begin, focusOffset: end, }); let mentionReplacedContent = Modifier.replaceText( editorState.getCurrentContent(), mentionTextSelection, `${mentionPrefix}${mention.name}`, null, // no inline style needed entityKey ); // If the mention is inserted at the end, a space is appended right after for // a smooth writing experience. const blockKey = mentionTextSelection.getAnchorKey(); const blockSize = editorState.getCurrentContent().getBlockForKey(blockKey).getLength(); if (blockSize === end) { mentionReplacedContent = Modifier.insertText( mentionReplacedContent, mentionReplacedContent.getSelectionAfter(), ' ', ); } const newEditorState = EditorState.push( editorState, mentionReplacedContent, 'insert-mention', ); return EditorState.forceSelection(newEditorState, mentionReplacedContent.getSelectionAfter()); };
export default (editorState) => { const newEditorState = editorState; const contentState = newEditorState.getCurrentContent(); const selectionState = newEditorState.getSelection(); const currentBlock = contentState.getBlockForKey(selectionState.getFocusKey()); /** * Draft Convert converts html to blocks and sets the block's text to * it's innerHTML. This isn't configurable so to prevent this text * being inserted when creating a new line we remove the block and create a * new block with empty text. */ const contentStateAfterRemoval = removeBlock(contentState, currentBlock.getKey()); const fragmentArray = [ new ContentBlock({ key: genKey(), type: currentBlock.getType(), text: ' ', characterList: currentBlock.getCharacterList(), }), new ContentBlock({ key: genKey(), type: 'unstyled', text: '', characterList: List(), }), ]; const fragment = BlockMapBuilder.createFromArray(fragmentArray); const withUnstyledBlock = Modifier.replaceWithFragment( contentStateAfterRemoval, selectionState, fragment, ); return EditorState.forceSelection( EditorState.push(newEditorState, withUnstyledBlock, 'insert-fragment'), withUnstyledBlock.getSelectionAfter(), ); };
addEmoji: Function = (emoji: string): void => { const { editorState, onChange } = this.props; const contentState = Modifier.replaceText( editorState.getCurrentContent(), editorState.getSelection(), emoji, editorState.getCurrentInlineStyle(), ); onChange(EditorState.push(editorState, contentState, 'insert-characters')); this.doCollapse(); };
export default function insertMention(editorState, mention, data, mode) { var entityMode = mode === 'immutable' ? 'IMMUTABLE' : 'MUTABLE'; var selection = editorState.getSelection(); var contentState = editorState.getCurrentContent(); contentState.createEntity('mention', entityMode, data || mention); var searchWord = getSearchWord(editorState, selection); var begin = searchWord.begin, end = searchWord.end; var replacedContent = Modifier.replaceText(contentState, selection.merge({ anchorOffset: begin, focusOffset: end }), mention, null, contentState.getLastCreatedEntityKey()); var InsertSpaceContent = Modifier.insertText(replacedContent, replacedContent.getSelectionAfter(), ' '); var newEditorState = EditorState.push(editorState, InsertSpaceContent, 'insert-mention'); return EditorState.forceSelection(newEditorState, InsertSpaceContent.getSelectionAfter()); }
constructor(props) { super(props); this.state = {editorState: EditorState.createEmpty()}; this.focus = () => this.refs.editor.focus(); this.onChange = (editorState) => this.setState({editorState}); this.handleKeyCommand = (command) => this._handleKeyCommand(command); this.toggleBlockType = (type) => this._toggleBlockType(type); this.toggleInlineStyle = (style) => this._toggleInlineStyle(style); }
constructor (props) { super(props) this.state = { editorState: EditorState.createWithContent( ContentState.createFromText(this.props.nodeId), createHighlightDecorator() ), suggestions: mentions } }
constructor(props) { super(props); this.state = { editorState: EditorState.createEmpty(), title:'' }; this.onChangeText = (editorState) => this.setState({editorState}); this.onChangeTitle = (e) => this.setState({title: e.target.value}); this.focus = ()=> this.refs.editor.focus(); this.onSubmit = this.onSubmit.bind(this); }
// Function to change depth of block(s). function changeBlocksDepth( editorState: EditorState, adjustment: number, maxDepth: number, ): ContentState { const selectionState = editorState.getSelection(); const contentState = editorState.getCurrentContent(); let blockMap = contentState.getBlockMap(); const blocks = getSelectedBlocksMap(editorState).map(block => { let depth = block.getDepth() + adjustment; depth = Math.max(0, Math.min(depth, maxDepth)); return block.set('depth', depth); }); blockMap = blockMap.merge(blocks); return contentState.merge({ blockMap, selectionBefore: selectionState, selectionAfter: selectionState, }); }
const addEmoji = (editorState, emojiShortName) => { const currentSelectionState = editorState.getSelection(); const { begin, end } = getSearchText(editorState, currentSelectionState); // Get the selection of the :emoji: search text const emojiTextSelection = currentSelectionState.merge({ anchorOffset: begin, focusOffset: end, }); const unicode = emojiList.list[emojiShortName][0]; const emoji = convertShortNameToUnicode(unicode); const entityKey = Entity.create('emoji', 'IMMUTABLE', { emojiUnicode: emoji }); let emojiReplacedContent = Modifier.replaceText( editorState.getCurrentContent(), emojiTextSelection, emoji, null, entityKey ); // If the emoji is inserted at the end, a space is appended right after for // a smooth writing experience. const blockKey = emojiTextSelection.getAnchorKey(); const blockSize = editorState.getCurrentContent().getBlockForKey(blockKey).getLength(); if (blockSize === end) { emojiReplacedContent = Modifier.insertText( emojiReplacedContent, emojiReplacedContent.getSelectionAfter(), ' ', ); } const newEditorState = EditorState.push( editorState, emojiReplacedContent, 'insert-emoji', ); return EditorState.forceSelection(newEditorState, emojiReplacedContent.getSelectionAfter()); };
value: function setEntity(entityType, data) { var mutability = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "MUTABLE"; var editorState = this.props.editorState; var contentState = editorState.getCurrentContent(); var contentStateWithEntity = contentState.createEntity(entityType, mutability, data); var entityKey = contentStateWithEntity.getLastCreatedEntityKey(); var newState = _draftJs.RichUtils.toggleLink(editorState, editorState.getSelection(), entityKey); var selectionState = _draftJs.EditorState.forceSelection(newState, editorState.getSelection()); this.props.onChange(selectionState); }
function insertDataBlock(editorState, data) { const contentState = editorState.getCurrentContent(); const selectionState = editorState.getSelection(); const afterRemoval = Modifier.removeRange( contentState, selectionState, "backward" ); const targetSelection = afterRemoval.getSelectionAfter(); const afterSplit = Modifier.splitBlock(afterRemoval, targetSelection); const insertionTarget = afterSplit.getSelectionAfter(); const asAtomicBlock = Modifier.setBlockType( afterSplit, insertionTarget, "atomic" ); const block = new ContentBlock({ key: genKey(), type: "atomic", text: "", characterList: List(), data: new Map(data) }); const fragmentArray = [ block, new ContentBlock({ key: genKey(), type: "unstyled", text: "", characterList: List() }) ]; const fragment = BlockMapBuilder.createFromArray(fragmentArray); const withAtomicBlock = Modifier.replaceWithFragment( asAtomicBlock, insertionTarget, fragment ); const newContent = withAtomicBlock.merge({ selectionBefore: selectionState, selectionAfter: withAtomicBlock.getSelectionAfter().set("hasFocus", true) }); return EditorState.push(editorState, newContent, "insert-fragment"); }
value: function setLink() { var link = this.state.link; var editorState = this.props.editorState; if (!link.startsWith("http://") && !link.startsWith("https://")) { link = "http://" + link; } var entityKey = _draftJs.Entity.create("LINK", "MUTABLE", { url: link }); var newState = _draftJs.RichUtils.toggleLink(editorState, editorState.getSelection(), entityKey); newState = _draftJs.EditorState.forceSelection(newState, this.props.editorState.getSelection()); this.props.onChange(newState); }
constructor(props) { super(props); this.state = { editorState: EditorState.createWithContent(ContentState.createFromText(props.content)) }; this.focus = () => this.refs.editor.focus(); this.onChange = (editorState) => this.setState({ editorState }); this.handleKeyCommand = (command) => this.onHandleKeyCommand(command); this.toggleBlockType = (type) => this.onToggleBlockType(type); this.toggleInlineStyle = (style) => this.onToggleInlineStyle(style); this.saveContent = () => this.onSaveContent(); }
export function applyEntity(editorState, entityOptions) { let contentState = editorState.getCurrentContent() let entityKey = null let contentStateWithEntity = contentState if (entityOptions) { let {type, immutable, data}=entityOptions contentStateWithEntity = contentState.createEntity(type, immutable, data) entityKey = contentStateWithEntity.getLastCreatedEntityKey() } const newContentState = Modifier.applyEntity(contentStateWithEntity, editorState.getSelection(), entityKey) return EditorState.push(editorState, newContentState, 'apply-entity') }
EditorCore.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { if (this.forceUpdateImmediate) { this.cancelForceUpdateImmediate(); } if (this.controlledMode) { var decorators = nextProps.value.getDecorator(); var editorState = decorators ? nextProps.value : _draftJs.EditorState.set(nextProps.value, { decorator: this.state.compositeDecorator }); this.setState({ editorState: editorState }); } };
toggleBlockType: function toggleBlockType(blockType) { const state = this.getEditorState(); const newState = RichUtils.toggleBlockType( state, blockType ); this.setEditorState( EditorState.forceSelection( newState, newState.getCurrentContent().getSelectionAfter() ) ); }
setEntityAlignment: Function = (alignment): void => { const { block, contentState } = this.props; const entityKey = block.getEntityAt(0); contentState.mergeEntityData( entityKey, { alignment }, ); config.onChange(EditorState.push(config.getEditorState(), contentState, 'change-block-data')); this.setState({ dummy: true, }); };
export default function (editorState, blockKey, newType) { let content = editorState.getCurrentContent(); const targetRange = new SelectionState({ anchorKey: blockKey, anchorOffset: 0, focusKey: blockKey, focusOffset: 1, }); // change the blocktype and remove the characterList entry with the block content = Modifier.setBlockType( content, targetRange, newType ); // force to new selection const newState = EditorState.push(editorState, content, 'modify-block'); return EditorState.forceSelection(newState, editorState.getSelection()); }
constructor (props) { super(props) this.handleLeave = this.handleLeave.bind(this) this.handleChange = this.handleChange.bind(this) this.handleBeforeInput = this.handleBeforeInput.bind(this) this.handlePastedText = this.handlePastedText.bind(this) this.toggleBlockStyleType = (type) => this.handleToggleBlockType(type) const editorStateValue = !this.props.value ? EditorState.createEmpty() : EditorState.createWithContent(convertFromRaw(JSON.parse(this.props.value))) this.state = { ...this.state, editorState: editorStateValue, charCount: editorStateValue ? (editorStateValue.getCurrentContent().getPlainText('')).length : 0, isChangingDirty : false } this.id = shortid.generate() };
/** * Function will handle followind keyPress scenarios when Shift key is not pressed. */ function handleHardNewlineEvent(editorState: EditorState): EditorState { const selection = editorState.getSelection(); if (selection.isCollapsed()) { const contentState = editorState.getCurrentContent(); const blockKey = selection.getStartKey(); const block = contentState.getBlockForKey(blockKey); if (!isListBlock(block) && block.getType() !== 'unstyled' && block.getLength() === selection.getStartOffset()) { return insertNewUnstyledBlock(editorState); } else if (isListBlock(block) && block.getLength() === 0) { const depth = block.getDepth(); if (depth === 0) { return removeSelectedBlocksStyle(editorState); } if (depth > 0) { return changeDepth(editorState, -1, depth); } } } return undefined; }
constructor(props) { super(props); this.state = { editorState: EditorState.createEmpty(), inlineToolbar: { show: false }, }; console.log(props) this.onChange = (editorState) => { if (!editorState.getSelection().isCollapsed()) { const selectionRange = getSelectionRange(); const selectionCoords = getSelectionCoords(selectionRange); this.setState({ inlineToolbar: { show: true, position: { top: selectionCoords.offsetTop, left: selectionCoords.offsetLeft } } }); } else { this.setState({ inlineToolbar: { show: false } }); } this.setState({ editorState }); const contentState1 = editorState.getCurrentContent(); const contentState = convertToRaw(contentState1); this.run(JSON.stringify(contentState)); setTimeout(this.updateSelection, 0); setTimeout(this.props.onChangeContent, 0); }; this.focus = () => this.refs.editor.focus(); this.updateSelection = () => this._updateSelection(); this.handleKeyCommand = (command) => this._handleKeyCommand(command); this.handleFileInput = (e) => this._handleFileInput(e); this.handleUploadImage = () => this._handleUploadImage(); this.toggleBlockType = (type) => this._toggleBlockType(type); this.toggleInlineStyle = (style) => this._toggleInlineStyle(style); this.insertImage = (file) => this._insertImage(file); this.blockRenderer = (block) => { if (block.getType() === 'atomic') { return { component: ImageComponent }; } return null; } this.blockStyler = (block) => { if (block.getType() === 'unstyled') { return 'paragraph'; } return null; } }
export function removeTeXBlock(editorState, blockKey) { var content = editorState.getCurrentContent(); var block = content.getBlockForKey(blockKey); var targetRange = new SelectionState({ anchorKey: blockKey, anchorOffset: 0, focusKey: blockKey, focusOffset: block.getLength(), }); var withoutTeX = Modifier.removeRange(content, targetRange, 'backward'); var resetBlock = Modifier.setBlockType( withoutTeX, withoutTeX.getSelectionAfter(), 'unstyled' ); var newState = EditorState.push(editorState, resetBlock, 'remove-range'); return EditorState.forceSelection(newState, resetBlock.getSelectionAfter()); }
rehydrate: function (state) { this.activity = state.activity this.volunteers = state.volunteers this.invalidDatetime = state.invalidDatetime this.invalidEndtime = state.invalidEndtime _.forEach(state.activityDescription.entityMap, function(val, key) { val.data.mention = fromJS(val.data.mention) }) var contentState = Draft.convertFromRaw(state.activityDescription) this.activityDescription = Draft.EditorState.push(this.activityDescription, Draft.ContentState.createFromBlockArray(contentState.getBlocksAsArray())) // Formularz aktualizacji do zadania _.forEach(state.editorState.entityMap, function(val, key) { val.data.mention = fromJS(val.data.mention) }) var contentState2 = Draft.convertFromRaw(state.editorState) this.editorState = Draft.EditorState.createWithContent(contentState2) }
componentWillReceiveProps(props) { const newState = {}; if (this.props.toolbar !== props.toolbar) { const toolbar = mergeRecursive(defaultToolbar, props.toolbar); newState.toolbar = toolbar; } if ( hasProperty(props, "editorState") && this.props.editorState !== props.editorState ) { if (props.editorState) { newState.editorState = EditorState.set(props.editorState, { decorator: this.compositeDecorator }); } else { newState.editorState = EditorState.createEmpty(this.compositeDecorator); } } else if ( hasProperty(props, "contentState") && this.props.contentState !== props.contentState ) { if (props.contentState) { const newEditorState = this.changeEditorState(props.contentState); if (newEditorState) { newState.editorState = newEditorState; } } else { newState.editorState = EditorState.createEmpty(this.compositeDecorator); } } if ( props.editorState !== this.props.editorState || props.contentState !== this.props.contentState ) { extractInlineStyle(newState.editorState); } this.setState(newState); this.editorProps = this.filterEditorProps(props); this.customStyleMap = getCustomStyleMap(); }
function expandMacro(editorState: EditorState, macros: MacroList, patient: Patient): EditorState { const currentSelection: SelectionState = editorState.getSelection(); // Don't trigger macros if more than one character is selected. if (!currentSelection.isCollapsed()) { return editorState; } const focusKey = currentSelection .getFocusKey(); const focusOffset = currentSelection .getFocusOffset(); const candidateText: string = editorState .getCurrentContent() .getBlockForKey(focusKey) .getText() .slice(0, focusOffset); for (const key of Object.keys(macros)) { const macroRegex = new RegExp(`${key}$`); if (macroRegex.test(candidateText)) { const nextContentState = Modifier.replaceText( editorState.getCurrentContent(), currentSelection.merge({ anchorOffset: currentSelection.getAnchorOffset() - key.length, }), applyPatientContext(macros[key], patient) ); const nextState = EditorState.push( editorState, nextContentState, 'insert-characters' ); return nextState; } } return editorState; }
it('removes disabled attribute from button if the getRedoStack is not empty', () => { const contentState = editorState.getCurrentContent(); const SelectionState = editorState.getSelection(); const newContent = Modifier.insertText( contentState, SelectionState, 'hello' ); const newEditorState = EditorState.push(editorState, newContent, 'insert-text'); const undoEditorState = EditorState.undo(newEditorState); store = { getEditorState: () => undoEditorState, setEditorState: onChange, }; const result = shallow( <Redo store={ store } children="redo" /> ); expect(result.find('button')).prop('disabled').to.equal(false); });
beforeEach(() => { const onChange = sinon.spy(); const editorState = EditorState.createEmpty(); const result = mount( <PluginEditor editorState={ editorState } onChange={ onChange } plugins={ [] } /> ); draftEditor = result.node; pluginEditor = result.instance(); });