From 40472dac0b7b01563625aec52c109b25c0d1152c Mon Sep 17 00:00:00 2001 From: James Johnson Date: Tue, 9 May 2017 15:57:52 +1000 Subject: [PATCH 01/15] Add lists plugin to support list indenting correctly --- blocks/components/editable/tinymce.js | 1 + 1 file changed, 1 insertion(+) diff --git a/blocks/components/editable/tinymce.js b/blocks/components/editable/tinymce.js index e50e0b72f75e4d..f40c77dd249829 100644 --- a/blocks/components/editable/tinymce.js +++ b/blocks/components/editable/tinymce.js @@ -31,6 +31,7 @@ export default class TinyMCE extends wp.element.Component { browser_spellcheck: true, entity_encoding: 'raw', convert_urls: false, + plugins: [ 'lists' ], setup: ( editor ) => { this.editor = editor; this.props.onSetup( editor ); From b19ee7fb68081d8306ebbfe3d5b50f9c4ece3394 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Tue, 9 May 2017 15:59:26 +1000 Subject: [PATCH 02/15] Add onNodeChange as an optional entry in the Editable props --- blocks/components/editable/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blocks/components/editable/index.js b/blocks/components/editable/index.js index 83672b055e21ac..c717c49372050b 100644 --- a/blocks/components/editable/index.js +++ b/blocks/components/editable/index.js @@ -209,6 +209,10 @@ export default class Editable extends wp.element.Component { const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); this.setState( { alignment, bookmark, formats, focusPosition } ); + + if ( this.props.onNodeChange ) { + this.props.onNodeChange( { element, parents } ); + } } updateContent() { From 2418990653d76afd859ec7befd631b44f4801206 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Tue, 9 May 2017 16:04:40 +1000 Subject: [PATCH 03/15] Add indent/outdent buttons; list type buttons handle sublists --- blocks/library/list/index.js | 60 +++++++++++++++++++++++++++++----- blocks/library/list/style.scss | 5 +-- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index a292a558d6ae0d..c0fbde2ca0d3c5 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -7,6 +7,34 @@ import Editable from 'components/editable'; const { children, prop } = hpq; +function activeEditorExecCommand( command ) { + return () => { + const ed = tinymce.activeEditor; + if ( ed ) { + ed.execCommand( command ); + } + }; +} + +function listIsActive( listType ) { + return ( { nodeName = 'OL', internalListType } ) => { + return listType === ( internalListType ? internalListType : nodeName ); + }; +} + +function listSetType( listType, editorCommand ) { + return ( { internalListType }, setAttributes ) => { + if ( internalListType ) { + // only change list types, don't toggle off internal lists + if ( internalListType !== listType ) { + activeEditorExecCommand( editorCommand )(); + } + } else { + setAttributes( { nodeName: listType } ); + } + }; +} + registerBlock( 'core/list', { title: wp.i18n.__( 'List' ), icon: 'editor-ul', @@ -21,22 +49,35 @@ registerBlock( 'core/list', { { icon: 'editor-ul', title: wp.i18n.__( 'Convert to unordered' ), - isActive: ( { nodeName = 'OL' } ) => nodeName === 'UL', - onClick( attributes, setAttributes ) { - setAttributes( { nodeName: 'UL' } ); - } + isActive: listIsActive( 'UL' ), + onClick: listSetType( 'UL', 'InsertUnorderedList' ) }, { icon: 'editor-ol', title: wp.i18n.__( 'Convert to ordered' ), - isActive: ( { nodeName = 'OL' } ) => nodeName === 'OL', - onClick( attributes, setAttributes ) { - setAttributes( { nodeName: 'OL' } ); - } - } + isActive: listIsActive( 'OL' ), + onClick: listSetType( 'OL', 'InsertOrderedList' ) + }, + { + icon: 'editor-outdent', + title: wp.i18n.__( 'Outdent list item' ), + isActive: () => false, + onClick: activeEditorExecCommand( 'Outdent' ) + }, + { + icon: 'editor-indent', + title: wp.i18n.__( 'Indent list item' ), + isActive: () => false, + onClick: activeEditorExecCommand( 'Indent' ) + }, ], edit( { attributes, setAttributes, focus, setFocus } ) { + const onNodeChange = ( { parents } ) => { + const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); + const internalListType = list ? list.nodeName : null; + setAttributes( { internalListType } ); + }; const { nodeName = 'OL', values = [] } = attributes; return ( ); diff --git a/blocks/library/list/style.scss b/blocks/library/list/style.scss index ef4dea4a01274b..e3eab791690098 100644 --- a/blocks/library/list/style.scss +++ b/blocks/library/list/style.scss @@ -1,3 +1,4 @@ -.blocks-list { - list-style-position: inside; +.blocks-list, .blocks-list ul, .blocks-list ol { + padding-left: 20px; + margin-left: 0; } From 5f2c3d01962ad72ba39f95acf24f014d6064d424 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Wed, 10 May 2017 14:13:37 +1000 Subject: [PATCH 04/15] Avoid use of global tinymce.activeEditor --- blocks/editable/index.js | 4 ++++ blocks/library/list/index.js | 36 +++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index a49937580dc3eb..11cb6e1b2baef8 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -88,6 +88,10 @@ export default class Editable extends wp.element.Component { editor.on( 'focusin', this.onFocus ); editor.on( 'nodechange', this.onNodeChange ); editor.on( 'keydown', this.onKeyDown ); + + if ( this.props.onSetup ) { + this.props.onSetup( editor ); + } } onInit() { diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 9df2ee3b80dc77..0234e52d35f9ce 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -7,11 +7,10 @@ import Editable from '../../editable'; const { children, prop } = hpq; -function activeEditorExecCommand( command ) { - return () => { - const ed = tinymce.activeEditor; - if ( ed ) { - ed.execCommand( command ); +function execCommand( command ) { + return ( { editor } ) => { + if ( editor ) { + editor.execCommand( command ); } }; } @@ -23,11 +22,13 @@ function listIsActive( listType ) { } function listSetType( listType, editorCommand ) { - return ( { internalListType }, setAttributes ) => { + return ( { internalListType, editor }, setAttributes ) => { if ( internalListType ) { // only change list types, don't toggle off internal lists if ( internalListType !== listType ) { - activeEditorExecCommand( editorCommand )(); + if ( editor ) { + editor.execCommand( editorCommand ); + } } } else { setAttributes( { nodeName: listType } ); @@ -35,6 +36,11 @@ function listSetType( listType, editorCommand ) { }; } +function findInternalListType( { parents } ) { + const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); + return list ? list.nodeName : null; +} + registerBlock( 'core/list', { title: wp.i18n.__( 'List' ), icon: 'editor-ul', @@ -62,33 +68,33 @@ registerBlock( 'core/list', { icon: 'editor-outdent', title: wp.i18n.__( 'Outdent list item' ), isActive: () => false, - onClick: activeEditorExecCommand( 'Outdent' ) + onClick: execCommand( 'Outdent' ) }, { icon: 'editor-indent', title: wp.i18n.__( 'Indent list item' ), isActive: () => false, - onClick: activeEditorExecCommand( 'Indent' ) + onClick: execCommand( 'Indent' ) }, ], edit( { attributes, setAttributes, focus, setFocus } ) { - const onNodeChange = ( { parents } ) => { - const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); - const internalListType = list ? list.nodeName : null; - setAttributes( { internalListType } ); - }; const { nodeName = 'OL', values = [] } = attributes; return ( { + setAttributes( { editor: nextEditor } ); + } } onChange={ ( nextValues ) => { setAttributes( { values: nextValues } ); } } + onNodeChange={ ( nodeInfo ) => { + setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); + } } value={ values } focus={ focus } onFocus={ setFocus } - onNodeChange={ onNodeChange } showAlignments className="blocks-list" /> ); From ba33927d3b9fc6122f0cc8f85fa41ae741552418 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Thu, 11 May 2017 16:28:36 +1000 Subject: [PATCH 05/15] Allow the control.isActive function to be optional defaulting to false --- blocks/library/list/index.js | 2 -- editor/modes/visual-editor/block.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 0234e52d35f9ce..a377b1f0da3f37 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -67,13 +67,11 @@ registerBlock( 'core/list', { { icon: 'editor-outdent', title: wp.i18n.__( 'Outdent list item' ), - isActive: () => false, onClick: execCommand( 'Outdent' ) }, { icon: 'editor-indent', title: wp.i18n.__( 'Indent list item' ), - isActive: () => false, onClick: execCommand( 'Indent' ) }, ], diff --git a/editor/modes/visual-editor/block.js b/editor/modes/visual-editor/block.js index 063ab8d4ec96cc..49a847371ca5c2 100644 --- a/editor/modes/visual-editor/block.js +++ b/editor/modes/visual-editor/block.js @@ -221,7 +221,7 @@ class VisualEditorBlock extends wp.element.Component { controls={ settings.controls.map( ( control ) => ( { ...control, onClick: () => control.onClick( block.attributes, this.setAttributes ), - isActive: control.isActive( block.attributes ) + isActive: control.isActive ? control.isActive( block.attributes ) : false } ) ) } /> ) } From f60e11db060a7a52e7d59502d1e29b0dece83935 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Tue, 16 May 2017 11:59:28 +1000 Subject: [PATCH 06/15] Moved list logic into Editable --- blocks/editable/index.js | 58 +++++++++++++++++++++++++++++- blocks/library/list/index.js | 70 ++---------------------------------- 2 files changed, 59 insertions(+), 69 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 24e9ee0eb2a062..27820c68c9f58f 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -45,6 +45,31 @@ const ALIGNMENT_CONTROLS = [ }, ]; +const LIST_CONTROLS = [ + { + list: 'UL', + icon: 'editor-ul', + title: wp.i18n.__( 'Convert to unordered' ), + cmd: 'InsertUnorderedList', + }, + { + list: 'OL', + icon: 'editor-ol', + title: wp.i18n.__( 'Convert to ordered' ), + cmd: 'InsertOrderedList', + }, + { + icon: 'editor-outdent', + title: wp.i18n.__( 'Outdent list item' ), + cmd: 'Outdent', + }, + { + icon: 'editor-indent', + title: wp.i18n.__( 'Indent list item' ), + cmd: 'Indent', + }, +]; + function createElement( type, props, ...children ) { if ( props[ 'data-mce-bogus' ] === 'all' ) { return null; @@ -248,10 +273,12 @@ export default class Editable extends wp.element.Component { activeFormats.forEach( ( activeFormat ) => formats[ activeFormat ] = true ); const alignments = this.editor.formatter.matchAll( [ 'alignleft', 'aligncenter', 'alignright' ] ); const alignment = alignments.length > 0 ? alignmentMap[ alignments[ 0 ] ] : null; + const aList = this.editor.dom.getParent( element, 'OL,UL' ); + const list = aList ? { type: aList.nodeName, isInternal: aList !== this.editor.getBody() } : null; const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); - this.setState( { alignment, bookmark, formats, focusPosition } ); + this.setState( { alignment, bookmark, formats, focusPosition, list } ); if ( this.props.onNodeChange ) { this.props.onNodeChange( { element, parents } ); @@ -368,6 +395,24 @@ export default class Editable extends wp.element.Component { } } + isListActive( listType ) { + return this.state.list && this.state.list.type === listType; + } + + setListType( listType, listCommand ) { + this.editor.focus(); + + if ( this.state.list ) { + if ( this.state.list.isInternal ) { + if ( this.state.list.type !== listType ) { + this.editor.execCommand( listCommand ); + } + } else if ( this.props.onListChange ) { + this.props.onListChange( listType ); + } + } + } + render() { const { tagName, @@ -401,6 +446,17 @@ export default class Editable extends wp.element.Component {
{ focus && + { this.state.list && + ( { + ...control, + isActive: control.list && this.isListActive( control.list ), + onClick: () => ( control.list ? + this.setListType( control.list, control.cmd ) : + this.editor.execCommand( control.cmd ) ), + } ) ) } + /> + } { showAlignments && ( { diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 561fcdc22c41b3..f67f00e45ad580 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -12,40 +12,6 @@ import Editable from '../../editable'; const { children, prop } = hpq; -function execCommand( command ) { - return ( { editor } ) => { - if ( editor ) { - editor.execCommand( command ); - } - }; -} - -function listIsActive( listType ) { - return ( { nodeName = 'OL', internalListType } ) => { - return listType === ( internalListType ? internalListType : nodeName ); - }; -} - -function listSetType( listType, editorCommand ) { - return ( { internalListType, editor }, setAttributes ) => { - if ( internalListType ) { - // only change list types, don't toggle off internal lists - if ( internalListType !== listType ) { - if ( editor ) { - editor.execCommand( editorCommand ); - } - } - } else { - setAttributes( { nodeName: listType } ); - } - }; -} - -function findInternalListType( { parents } ) { - const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); - return list ? list.nodeName : null; -} - registerBlock( 'core/list', { title: wp.i18n.__( 'List' ), icon: 'editor-ul', @@ -56,31 +22,6 @@ registerBlock( 'core/list', { values: children( 'ol,ul' ), }, - controls: [ - { - icon: 'editor-ul', - title: wp.i18n.__( 'Convert to unordered' ), - isActive: listIsActive( 'UL' ), - onClick: listSetType( 'UL', 'InsertUnorderedList' ), - }, - { - icon: 'editor-ol', - title: wp.i18n.__( 'Convert to ordered' ), - isActive: listIsActive( 'OL' ), - onClick: listSetType( 'OL', 'InsertOrderedList' ), - }, - { - icon: 'editor-outdent', - title: wp.i18n.__( 'Outdent list item' ), - onClick: execCommand( 'Outdent' ), - }, - { - icon: 'editor-indent', - title: wp.i18n.__( 'Indent list item' ), - onClick: execCommand( 'Indent' ), - }, - ], - transforms: { from: [ { @@ -112,15 +53,8 @@ registerBlock( 'core/list', { return ( { - setAttributes( { editor: nextEditor } ); - } } - onChange={ ( nextValues ) => { - setAttributes( { values: nextValues } ); - } } - onNodeChange={ ( nodeInfo ) => { - setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); - } } + onChange={ ( nextValues ) => setAttributes( { values: nextValues } ) } + onListChange={ ( listType ) => setAttributes( { nodeName: listType } ) } value={ values } focus={ focus } onFocus={ setFocus } From abb531f86fa9b7ec6f3bfe34a7d88e3c372e4452 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Tue, 16 May 2017 12:13:46 +1000 Subject: [PATCH 07/15] Removed onSetup and onNodeChange callbacks --- blocks/editable/index.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 27820c68c9f58f..b1911725f07616 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -117,10 +117,6 @@ export default class Editable extends wp.element.Component { editor.on( 'nodechange', this.onNodeChange ); editor.on( 'keydown', this.onKeyDown ); editor.on( 'selectionChange', this.onSelectionChange ); - - if ( this.props.onSetup ) { - this.props.onSetup( editor ); - } } onInit() { @@ -279,10 +275,6 @@ export default class Editable extends wp.element.Component { const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); this.setState( { alignment, bookmark, formats, focusPosition, list } ); - - if ( this.props.onNodeChange ) { - this.props.onNodeChange( { element, parents } ); - } } updateContent() { From 27e1c0f77d684080a4fc95de31266c4a4a7648bd Mon Sep 17 00:00:00 2001 From: James Johnson Date: Thu, 18 May 2017 09:32:13 +1000 Subject: [PATCH 08/15] Put separate CSS selectors on different lines to improve readablity --- blocks/library/list/style.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/blocks/library/list/style.scss b/blocks/library/list/style.scss index f1e2aabf72787d..4448ee1c55d8f1 100644 --- a/blocks/library/list/style.scss +++ b/blocks/library/list/style.scss @@ -1,4 +1,6 @@ -.blocks-list .blocks-editable__tinymce, .blocks-list .blocks-editable__tinymce ul, .blocks-list .blocks-editable__tinymce ol { +.blocks-list .blocks-editable__tinymce, +.blocks-list .blocks-editable__tinymce ul, +.blocks-list .blocks-editable__tinymce ol { padding-left: 2.5em; margin-left: 0; } From f8cce5a2369d9082fd8daace1d18102d747ab886 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Fri, 19 May 2017 14:03:00 +1000 Subject: [PATCH 09/15] Revert "Removed onSetup and onNodeChange callbacks" This reverts commit abb531f86fa9b7ec6f3bfe34a7d88e3c372e4452. --- blocks/editable/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 7a18ac8994f52f..a961c11053fb91 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -118,6 +118,10 @@ export default class Editable extends wp.element.Component { editor.on( 'nodechange', this.onNodeChange ); editor.on( 'keydown', this.onKeyDown ); editor.on( 'selectionChange', this.onSelectionChange ); + + if ( this.props.onSetup ) { + this.props.onSetup( editor ); + } } onInit() { @@ -300,6 +304,10 @@ export default class Editable extends wp.element.Component { const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); this.setState( { alignment, bookmark, formats, focusPosition, list } ); + + if ( this.props.onNodeChange ) { + this.props.onNodeChange( { element, parents } ); + } } updateContent() { From befe07bda17334725f92318d7b7ab7c8ad16b585 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Fri, 19 May 2017 14:03:43 +1000 Subject: [PATCH 10/15] Revert "Moved list logic into Editable" This reverts commit f60e11db060a7a52e7d59502d1e29b0dece83935. --- blocks/editable/index.js | 58 +----------------------------- blocks/library/list/index.js | 70 ++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 59 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index a961c11053fb91..22a788e89d84b9 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -46,31 +46,6 @@ const ALIGNMENT_CONTROLS = [ }, ]; -const LIST_CONTROLS = [ - { - list: 'UL', - icon: 'editor-ul', - title: wp.i18n.__( 'Convert to unordered' ), - cmd: 'InsertUnorderedList', - }, - { - list: 'OL', - icon: 'editor-ol', - title: wp.i18n.__( 'Convert to ordered' ), - cmd: 'InsertOrderedList', - }, - { - icon: 'editor-outdent', - title: wp.i18n.__( 'Outdent list item' ), - cmd: 'Outdent', - }, - { - icon: 'editor-indent', - title: wp.i18n.__( 'Indent list item' ), - cmd: 'Indent', - }, -]; - function createElement( type, props, ...children ) { if ( props[ 'data-mce-bogus' ] === 'all' ) { return null; @@ -298,12 +273,10 @@ export default class Editable extends wp.element.Component { activeFormats.forEach( ( activeFormat ) => formats[ activeFormat ] = true ); const alignments = this.editor.formatter.matchAll( [ 'alignleft', 'aligncenter', 'alignright' ] ); const alignment = alignments.length > 0 ? alignmentMap[ alignments[ 0 ] ] : null; - const aList = this.editor.dom.getParent( element, 'OL,UL' ); - const list = aList ? { type: aList.nodeName, isInternal: aList !== this.editor.getBody() } : null; const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); - this.setState( { alignment, bookmark, formats, focusPosition, list } ); + this.setState( { alignment, bookmark, formats, focusPosition } ); if ( this.props.onNodeChange ) { this.props.onNodeChange( { element, parents } ); @@ -420,24 +393,6 @@ export default class Editable extends wp.element.Component { } } - isListActive( listType ) { - return this.state.list && this.state.list.type === listType; - } - - setListType( listType, listCommand ) { - this.editor.focus(); - - if ( this.state.list ) { - if ( this.state.list.isInternal ) { - if ( this.state.list.type !== listType ) { - this.editor.execCommand( listCommand ); - } - } else if ( this.props.onListChange ) { - this.props.onListChange( listType ); - } - } - } - render() { const { tagName, @@ -471,17 +426,6 @@ export default class Editable extends wp.element.Component {
{ focus && - { this.state.list && - ( { - ...control, - isActive: control.list && this.isListActive( control.list ), - onClick: () => ( control.list ? - this.setListType( control.list, control.cmd ) : - this.editor.execCommand( control.cmd ) ), - } ) ) } - /> - } { showAlignments && ( { diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index f67f00e45ad580..561fcdc22c41b3 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -12,6 +12,40 @@ import Editable from '../../editable'; const { children, prop } = hpq; +function execCommand( command ) { + return ( { editor } ) => { + if ( editor ) { + editor.execCommand( command ); + } + }; +} + +function listIsActive( listType ) { + return ( { nodeName = 'OL', internalListType } ) => { + return listType === ( internalListType ? internalListType : nodeName ); + }; +} + +function listSetType( listType, editorCommand ) { + return ( { internalListType, editor }, setAttributes ) => { + if ( internalListType ) { + // only change list types, don't toggle off internal lists + if ( internalListType !== listType ) { + if ( editor ) { + editor.execCommand( editorCommand ); + } + } + } else { + setAttributes( { nodeName: listType } ); + } + }; +} + +function findInternalListType( { parents } ) { + const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); + return list ? list.nodeName : null; +} + registerBlock( 'core/list', { title: wp.i18n.__( 'List' ), icon: 'editor-ul', @@ -22,6 +56,31 @@ registerBlock( 'core/list', { values: children( 'ol,ul' ), }, + controls: [ + { + icon: 'editor-ul', + title: wp.i18n.__( 'Convert to unordered' ), + isActive: listIsActive( 'UL' ), + onClick: listSetType( 'UL', 'InsertUnorderedList' ), + }, + { + icon: 'editor-ol', + title: wp.i18n.__( 'Convert to ordered' ), + isActive: listIsActive( 'OL' ), + onClick: listSetType( 'OL', 'InsertOrderedList' ), + }, + { + icon: 'editor-outdent', + title: wp.i18n.__( 'Outdent list item' ), + onClick: execCommand( 'Outdent' ), + }, + { + icon: 'editor-indent', + title: wp.i18n.__( 'Indent list item' ), + onClick: execCommand( 'Indent' ), + }, + ], + transforms: { from: [ { @@ -53,8 +112,15 @@ registerBlock( 'core/list', { return ( setAttributes( { values: nextValues } ) } - onListChange={ ( listType ) => setAttributes( { nodeName: listType } ) } + onSetup={ ( nextEditor ) => { + setAttributes( { editor: nextEditor } ); + } } + onChange={ ( nextValues ) => { + setAttributes( { values: nextValues } ); + } } + onNodeChange={ ( nodeInfo ) => { + setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); + } } value={ values } focus={ focus } onFocus={ setFocus } From 528f0884f332596fdc20a5309f1f9c2ce81ab003 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Fri, 19 May 2017 15:56:18 +1000 Subject: [PATCH 11/15] Removed onNodeChange; allow tinyMCE configuration outside Editable --- blocks/editable/index.js | 15 ++++++++++----- blocks/editable/tinymce.js | 18 ++++++++++-------- blocks/library/list/index.js | 15 ++++++++++----- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 22a788e89d84b9..fe915497adfed8 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { last, isEqual, capitalize, omitBy, forEach, merge } from 'lodash'; +import { last, isEqual, capitalize, omitBy, forEach, merge, identity } from 'lodash'; import { nodeListToReact } from 'dom-react'; import { Fill } from 'react-slot-fill'; import 'element-closest'; @@ -67,6 +67,7 @@ export default class Editable extends wp.element.Component { super( ...arguments ); this.onInit = this.onInit.bind( this ); + this.onConfig = this.onConfig.bind( this ); this.onSetup = this.onSetup.bind( this ); this.onChange = this.onChange.bind( this ); this.onNewBlock = this.onNewBlock.bind( this ); @@ -84,6 +85,13 @@ export default class Editable extends wp.element.Component { }; } + onConfig( settings ) { + return ( this.props.onConfig || identity )( { + ...settings, + forced_root_block: this.props.inline ? false : 'p', + } ); + } + onSetup( editor ) { this.editor = editor; editor.on( 'init', this.onInit ); @@ -402,7 +410,6 @@ export default class Editable extends wp.element.Component { className, showAlignments = false, inlineToolbar = false, - inline, formattingControls, placeholder, } = this.props; @@ -446,12 +453,10 @@ export default class Editable extends wp.element.Component { diff --git a/blocks/editable/tinymce.js b/blocks/editable/tinymce.js index 9fc5dfce0b0b01..dce9cfb8ce289c 100644 --- a/blocks/editable/tinymce.js +++ b/blocks/editable/tinymce.js @@ -34,25 +34,27 @@ export default class TinyMCE extends wp.element.Component { } initialize() { - const { settings, focus } = this.props; + const { focus } = this.props; - tinymce.init( { - target: this.editorNode, + const settings = this.props.onConfig( { theme: false, inline: true, toolbar: false, browser_spellcheck: true, entity_encoding: 'raw', convert_urls: false, - plugins: [ 'lists' ], - setup: ( editor ) => { - this.editor = editor; - this.props.onSetup( editor ); - }, formats: { strikethrough: { inline: 'del' }, }, + } ); + + tinymce.init( { ...settings, + target: this.editorNode, + setup: ( editor ) => { + this.editor = editor; + this.props.onSetup( editor ); + }, } ); if ( focus ) { diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 561fcdc22c41b3..2ed70f5a158d83 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -112,15 +112,20 @@ registerBlock( 'core/list', { return ( { - setAttributes( { editor: nextEditor } ); + onConfig={ ( settings ) => ( { + ...settings, + plugins: ( settings.plugins || [] ).concat( 'lists' ), + lists_indent_on_tab: false, + } ) } + onSetup={ ( editor ) => { + editor.on( 'nodeChange', ( nodeInfo ) => { + setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); + } ); + setAttributes( { editor } ); } } onChange={ ( nextValues ) => { setAttributes( { values: nextValues } ); } } - onNodeChange={ ( nodeInfo ) => { - setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); - } } value={ values } focus={ focus } onFocus={ setFocus } From 68ab9ee23099ec4e56624a1ec2239a2e69387a8f Mon Sep 17 00:00:00 2001 From: James Johnson Date: Mon, 22 May 2017 11:33:21 +1000 Subject: [PATCH 12/15] Remove onNodeChange property callback --- blocks/editable/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index fe915497adfed8..7284e0ebd4a1f8 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -285,10 +285,6 @@ export default class Editable extends wp.element.Component { const focusPosition = this.getRelativePosition( element ); const bookmark = this.editor.selection.getBookmark( 2, true ); this.setState( { alignment, bookmark, formats, focusPosition } ); - - if ( this.props.onNodeChange ) { - this.props.onNodeChange( { element, parents } ); - } } updateContent() { From 8e36e05104c09b5a22311d2a786012c6d7a01dcc Mon Sep 17 00:00:00 2001 From: James Johnson Date: Mon, 22 May 2017 11:35:06 +1000 Subject: [PATCH 13/15] Renamed onConfig to getSettings --- blocks/editable/index.js | 8 ++++---- blocks/editable/tinymce.js | 2 +- blocks/library/list/index.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 7284e0ebd4a1f8..a02964b7a7fc4e 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -67,7 +67,7 @@ export default class Editable extends wp.element.Component { super( ...arguments ); this.onInit = this.onInit.bind( this ); - this.onConfig = this.onConfig.bind( this ); + this.getSettings = this.getSettings.bind( this ); this.onSetup = this.onSetup.bind( this ); this.onChange = this.onChange.bind( this ); this.onNewBlock = this.onNewBlock.bind( this ); @@ -85,8 +85,8 @@ export default class Editable extends wp.element.Component { }; } - onConfig( settings ) { - return ( this.props.onConfig || identity )( { + getSettings( settings ) { + return ( this.props.getSettings || identity )( { ...settings, forced_root_block: this.props.inline ? false : 'p', } ); @@ -449,7 +449,7 @@ export default class Editable extends wp.element.Component { ( { + getSettings={ ( settings ) => ( { ...settings, plugins: ( settings.plugins || [] ).concat( 'lists' ), lists_indent_on_tab: false, From 9c5b029a7ac73c69a571031fd05c0e7696175ca6 Mon Sep 17 00:00:00 2001 From: James Johnson Date: Mon, 22 May 2017 11:37:03 +1000 Subject: [PATCH 14/15] Use find from lodash to avoid IE 11 support problems --- blocks/library/list/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 75df0536eb15ca..21d9cf72b25e64 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { switchChildrenNodeName } from 'element'; +import { find } from 'lodash'; /** * Internal dependencies @@ -42,7 +43,7 @@ function listSetType( listType, editorCommand ) { } function findInternalListType( { parents } ) { - const list = parents.find( ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); + const list = find( parents, ( node ) => node.nodeName === 'UL' || node.nodeName === 'OL' ); return list ? list.nodeName : null; } From 9ed5cf4a66f06712013e8d886500fe63c8893b4d Mon Sep 17 00:00:00 2001 From: James Johnson Date: Mon, 22 May 2017 11:37:38 +1000 Subject: [PATCH 15/15] Replaced some out of position tab chars with spaces --- blocks/library/list/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 21d9cf72b25e64..46b0acf18d812e 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -31,7 +31,7 @@ function listSetType( listType, editorCommand ) { return ( { internalListType, editor }, setAttributes ) => { if ( internalListType ) { // only change list types, don't toggle off internal lists - if ( internalListType !== listType ) { + if ( internalListType !== listType ) { if ( editor ) { editor.execCommand( editorCommand ); } @@ -123,7 +123,7 @@ registerBlock( 'core/list', { setAttributes( { internalListType: findInternalListType( nodeInfo ) } ); } ); setAttributes( { editor } ); - } } + } } onChange={ ( nextValues ) => { setAttributes( { values: nextValues } ); } }