diff --git a/blocks/library/freeform/format-list.js b/blocks/library/freeform/format-list.js deleted file mode 100644 index f71b12aedf5ea..0000000000000 --- a/blocks/library/freeform/format-list.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * External dependencies - */ -import clickOutside from 'react-click-outside'; -import classnames from 'classnames'; -import { camelCase, fromPairs, omit } from 'lodash'; - -/** - * WordPress dependencies - */ -import { Component } from 'element'; -import { Button, Dashicon } from 'components'; - -/** - * Internal dependencies - */ -import { __ } from 'i18n'; -import './format-list.scss'; - -export function naiveCss2Jsx( styleText ) { - return fromPairs( - styleText.split( ';' ).filter( ( text ) => /\S/.test( text ) ).map( - ( stylePart ) => { - const [ cssKey, cssValue ] = stylePart.split( ':', 2 ); - return [ camelCase( cssKey ), cssValue ]; - } - ) - ); -} - -class FormatList extends Component { - constructor() { - super( ...arguments ); - this.switchFormat = this.switchFormat.bind( this ); - this.toggleMenu = this.toggleMenu.bind( this ); - this.state = { - open: false, - }; - } - - handleClickOutside() { - if ( ! this.state.open ) { - return; - } - this.setState( { open: false } ); - } - - toggleMenu() { - this.setState( ( state ) => ( { - open: ! state.open, - } ) ); - } - - switchFormat( newValue ) { - if ( this.props.onFormatChange ) { - this.props.onFormatChange( newValue ); - } - this.setState( { open: false } ); - } - - render() { - const { formats } = this.props; - const selectedValue = this.props.value; - const noFormat = { text: __( 'No format' ), value: null }; - const styleExclude = [ 'color', 'backgroundColor' ]; - return ( - formats &&
- - { this.state.open && -
- { formats.map( ( { text, value, textStyle } ) => ( - - ) ) } -
- } -
- ); - } -} - -export default clickOutside( FormatList ); diff --git a/blocks/library/freeform/format-list.scss b/blocks/library/freeform/format-list.scss deleted file mode 100644 index 15dd3b2ddde6f..0000000000000 --- a/blocks/library/freeform/format-list.scss +++ /dev/null @@ -1,86 +0,0 @@ -.editor-format-list { - border: 1px solid $light-gray-500; - box-shadow: $shadow-popover; - background-color: $white; - margin-right: 10px; - font-family: $default-font; - font-size: $default-font-size; - line-height: $default-line-height; - display: flex; - flex-direction: row; - padding: 0; - position: relative; -} - -.editor-format-list__toggle { - display: inline-flex; - flex-direction: row; - align-items: center; - padding: 0 8px; - - &:focus:before { - top: -3px; - right: -3px; - bottom: -3px; - left: -3px; - } - - .formats { - display: inline; - text-align: start; - line-height: 0; - visibility: hidden; - - .active { - visibility: visible; - } - } -} - -.editor-format-list .editor-format-list__menu { - position: absolute; - top: $block-controls-height - 2px; - left: -1px; - box-shadow: $shadow-popover; - border: 1px solid $light-gray-500; - background: $white; - padding: 3px 3px 0 3px; - display: flex; - flex-direction: column; - align-content: flex-start; - z-index: z-index( '.editor-format-list__menu' ); - - input { - font-size: 13px; - } -} - -.editor-format-list .editor-format-list__menu-item { - width: 100%; - margin-bottom: 3px; - padding: 6px; - padding-left: 4px; - padding-right: 24px; - line-height: 1; - background: none; - border: 1px solid transparent; - outline: none; - border-radius: 0; - color: $dark-gray-500; - cursor: pointer; - text-align: start; - - &:hover, - &:focus, - &:not(:disabled):hover { - box-shadow: none; - color: $dark-gray-500; - border-color: $dark-gray-500; - } - - &.is-active, - &.is-active:hover { - color: $white; - background-color: $dark-gray-500; - } -} \ No newline at end of file diff --git a/blocks/library/freeform/freeform-block.js b/blocks/library/freeform/freeform-block.js deleted file mode 100644 index 902d8a88364a4..0000000000000 --- a/blocks/library/freeform/freeform-block.js +++ /dev/null @@ -1,415 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import { nodeListToReact } from 'dom-react'; -import 'element-closest'; -import { concat, find, flatten, isEqual, omitBy, throttle } from 'lodash'; - -/** - * WordPress dependencies - */ -import { Component, createElement, renderToString, findDOMNode } from 'element'; -import { __ } from 'i18n'; -import { Toolbar } from 'components'; - -/** - * Internal dependencies - */ -import './freeform-block.scss'; -import TinyMCE from '../../editable/tinymce'; -import BlockControls from '../../block-controls'; -import FormatList from './format-list'; - -const BLOCK_CONTROLS_SELECTOR = '.editor-visual-editor__block-controls'; - -const ALIGNMENT_CONTROLS = [ - { - id: 'alignleft', - icon: 'editor-alignleft', - title: __( 'Align left' ), - }, - { - id: 'aligncenter', - icon: 'editor-aligncenter', - title: __( 'Align center' ), - }, - { - id: 'alignright', - icon: 'editor-alignright', - title: __( 'Align right' ), - }, -]; - -const FREEFORM_CONTROLS = [ - [ - { - id: 'blockquote', - icon: 'editor-quote', - title: __( 'Quote' ), - }, - { - id: 'bullist', - icon: 'editor-ul', - title: __( 'Convert to unordered' ), - }, - { - id: 'numlist', - icon: 'editor-ol', - title: __( 'Convert to ordered' ), - }, - ], - [ - { - id: 'bold', - icon: 'editor-bold', - title: __( 'Bold' ), - }, - { - id: 'italic', - icon: 'editor-italic', - title: __( 'Italic' ), - }, - { - id: 'strikethrough', - icon: 'editor-strikethrough', - title: __( 'Strikethrough' ), - }, - ], -]; -const MORE_CONTROLS = [ - { - id: 'indent', - icon: 'editor-indent', - title: __( 'Indent' ), - }, - { - id: 'outdent', - icon: 'editor-outdent', - title: __( 'Outdent' ), - }, -]; - -const MORE_DRAWER_HEIGHT = 40; - -function createTinyMCEElement( type, props, ...children ) { - if ( props[ 'data-mce-bogus' ] === 'all' ) { - return null; - } - - if ( props.hasOwnProperty( 'data-mce-bogus' ) ) { - return children; - } - - return createElement( - type, - omitBy( props, ( value, key ) => key.indexOf( 'data-mce-' ) === 0 ), - ...children - ); -} - -export default class FreeformBlock extends Component { - constructor( props ) { - super( ...arguments ); - this.getSettings = this.getSettings.bind( this ); - this.setButtonActive = this.setButtonActive.bind( this ); - this.setButtonDisabled = this.setButtonDisabled.bind( this ); - this.setFormatActive = this.setFormatActive.bind( this ); - this.toggleMoreDrawer = this.toggleMoreDrawer.bind( this ); - this.setToolbarRef = this.setToolbarRef.bind( this ); - this.onSetup = this.onSetup.bind( this ); - this.onInit = this.onInit.bind( this ); - this.onSelectionChange = this.onSelectionChange.bind( this ); - this.onChange = this.onChange.bind( this ); - this.onFocus = this.onFocus.bind( this ); - this.onScroll = throttle( this.onScroll.bind( this ), 250 ); - this.isEndOfEditor = this.isEndOfEditor.bind( this ); - this.updateFocus = this.updateFocus.bind( this ); - this.updateContent = this.updateContent.bind( this ); - this.setContent = this.setContent.bind( this ); - this.getContent = this.getContent.bind( this ); - this.mapControls = this.mapControls.bind( this ); - this.editor = null; - this.toolbarElem = null; - this.savedContent = null; - this.formats = null; - this.handleFormatChange = null; - this.state = { - empty: ! props.value || ! props.value.length, - activeButtons: { }, - disabledButtons: { }, - activeFormat: null, - showMore: false, - expandDown: false, - }; - } - - getSettings( baseSettings ) { - return { - ...baseSettings, - plugins: ( baseSettings.plugins || [] ).concat( 'lists' ), - }; - } - - setButtonActive( id, active ) { - this.setState( ( prevState ) => ( { - activeButtons: { - ...prevState.activeButtons, - [ id ]: active, - }, - } ) ); - } - - setButtonDisabled( id, disabled ) { - this.setState( ( prevState ) => ( { - disabledButtons: { - ...prevState.disabledButtons, - [ id ]: disabled, - }, - } ) ); - } - - setFormatActive( newActiveFormat ) { - this.setState( { activeFormat: newActiveFormat } ); - } - - toggleMoreDrawer() { - this.setState( { showMore: ! this.state.showMore } ); - } - - setToolbarRef( elem ) { - this.toolbarElem = elem; - this.onScroll(); - } - - onSetup( editor ) { - this.editor = editor; - editor.on( 'init', this.onInit ); - editor.on( 'focusout', this.onChange ); - editor.on( 'focusin', this.onFocus ); - editor.on( 'selectionChange', this.onSelectionChange ); - } - - onInit() { - const formatselect = this.editor.buttons.formatselect(); - formatselect.onPostRender.call( { - value: this.setFormatActive, - } ); - this.formats = formatselect.values; - this.handleFormatChange = formatselect.onselect; - this.forceUpdate(); - - [ ...ALIGNMENT_CONTROLS, ...flatten( FREEFORM_CONTROLS ), ...MORE_CONTROLS ].forEach( ( control ) => { - if ( control.id ) { - const button = this.editor.buttons[ control.id ]; - // TinyMCE uses the first 2 cases, I am not sure about the third. - const fnNames = [ 'onPostRender', 'onpostrender', 'OnPostRender' ]; - const onPostRender = find( fnNames, ( fn ) => button.hasOwnProperty( fn ) ); - if ( onPostRender ) { - button[ onPostRender ].call( { - active: ( isActive ) => this.setButtonActive( control.id, isActive ), - }, { control: { - disabled: ( isDisabled ) => this.setButtonDisabled( control.id, isDisabled ), - } } ); - } - } - } ); - this.updateFocus(); - } - - isActive() { - return document.activeElement === this.editor.getBody(); - } - - onSelectionChange() { - // We must check this because selectionChange is a global event. - if ( ! this.isActive() ) { - return; - } - - const content = this.getContent(); - const collapsed = this.editor.selection.isCollapsed(); - - this.setState( { - empty: ! content || ! content.length, - } ); - - if ( - this.props.focus && this.props.onFocus && - this.props.focus.collapsed !== collapsed - ) { - this.props.onFocus( { - ...this.props.focus, - collapsed, - } ); - } - } - - onChange() { - if ( ! this.editor.isDirty() ) { - return; - } - - this.savedContent = this.getContent(); - this.editor.save(); - this.props.onChange( this.savedContent ); - } - - onFocus() { - if ( this.props.onFocus ) { - this.props.onFocus(); - } - } - - onScroll() { - if ( this.toolbarElem ) { - const n = findDOMNode( this.toolbarElem ); - const blockControls = n ? n.closest( BLOCK_CONTROLS_SELECTOR ) : null; - if ( blockControls ) { - const currentTop = blockControls.getBoundingClientRect().top; - const stickyTop = parseInt( window.getComputedStyle( blockControls ).top, 10 ); - const expandDown = currentTop - stickyTop <= MORE_DRAWER_HEIGHT; - this.setState( { expandDown } ); - } - } - } - - isEndOfEditor() { - const range = this.editor.selection.getRng(); - if ( range.endOffset !== range.endContainer.textContent.length || ! range.collapsed ) { - return false; - } - const start = range.endContainer; - const body = this.editor.getBody(); - let element = start; - while ( element !== body ) { - const child = element; - element = element.parentNode; - if ( element.lastChild !== child ) { - return false; - } - } - return true; - } - - updateFocus() { - const { focus } = this.props; - const isActive = this.isActive(); - - if ( focus ) { - if ( ! isActive ) { - this.editor.focus(); - } - - // Offset = -1 means we should focus the end of the editable - if ( focus.offset === -1 && ! this.isEndOfEditor() ) { - this.editor.selection.select( this.editor.getBody(), true ); - this.editor.selection.collapse( false ); - } - } else if ( isActive ) { - this.editor.getBody().blur(); - } - } - - updateContent() { - const bookmark = this.editor.selection.getBookmark( 2, true ); - this.savedContent = this.props.value; - this.setContent( this.savedContent ); - this.editor.selection.moveToBookmark( bookmark ); - - // Saving the editor on updates avoid unecessary onChanges calls - // These calls can make the focus jump - this.editor.save(); - } - - setContent( content ) { - if ( ! content ) { - content = ''; - } - - content = renderToString( content ); - this.editor.setContent( content, { format: 'raw' } ); - } - - getContent() { - return nodeListToReact( this.editor.getBody().childNodes || [], createTinyMCEElement ); - } - - mapControls( controls ) { - return controls.map( ( control ) => { - if ( Array.isArray( control ) ) { - return this.mapControls( control ); - } - - return { - ...control, - onClick: () => this.editor && this.editor.buttons[ control.id ].onclick(), - isActive: this.state.activeButtons[ control.id ], - isDisabled: this.state.disabledButtons[ control.id ], - }; - } ); - } - - componentDidMount() { - window.addEventListener( 'scroll', this.onScroll ); - } - - componentWillUnmount() { - this.onChange(); - window.removeEventListener( 'scroll', this.onScroll ); - } - - componentDidUpdate( prevProps ) { - if ( this.props.focus !== prevProps.focus ) { - this.updateFocus(); - } - - // The `savedContent` var allows us to avoid updating the content right after an `onChange` call - if ( - this.props.content !== prevProps.content && - this.props.content !== this.savedContent && - ! isEqual( this.props.content, prevProps.content ) && - ! isEqual( this.props.content, this.savedContent ) - ) { - this.updateContent(); - } - } - - render() { - const { content, focus } = this.props; - const { expandDown, showMore } = this.state; - const moreDrawerClasses = classnames( 'more-drawer', expandDown ? 'down' : 'up' ); - return [ - focus && - - - -
- -
- ), - } ] ] ) } - /> -
, - , - ]; - } -} diff --git a/blocks/library/freeform/freeform-block.scss b/blocks/library/freeform/freeform-block.scss deleted file mode 100644 index f311c78e4c6f3..0000000000000 --- a/blocks/library/freeform/freeform-block.scss +++ /dev/null @@ -1,64 +0,0 @@ - -.editor-visual-editor__block[data-type="core/freeform"] .editor-visual-editor__block-controls { - // Slot creates a div which has no class on it, I need it to be flex - &> div { - display: flex; - } - - .more-drawer { - position: absolute; - display: inline-flex; - top: -5px - $icon-button-size; - right: 0; - - &.down { - top: 5px + $icon-button-size; - } - - &> .components-toolbar:last-child { - margin-right: 0; - } - - .more-draw__arrow { - width: 0; - height: 0; - line-height: 0; - position: absolute; - right: $icon-button-size / 2; - margin-right: -10px; - border: 10px solid $light-gray-500; - border-left-color: transparent; - border-right-color: transparent; - - &:before { - content: " "; - position: absolute; - left: 50%; - margin-left: -10px; - border: 10px solid $light-gray-100; - border-left-color: transparent; - border-right-color: transparent; - } - } - - &.up .more-draw__arrow { - bottom: -10px; - border-bottom: none; - - &:before { - bottom: 2px; - border-bottom: none; - } - } - - &.down .more-draw__arrow { - top: -10px; - border-top: none; - - &:before { - top: 2px; - border-top: none; - } - } - } -} \ No newline at end of file diff --git a/blocks/library/freeform/index.js b/blocks/library/freeform/index.js index 447f3da7f4980..78beb9972cf33 100644 --- a/blocks/library/freeform/index.js +++ b/blocks/library/freeform/index.js @@ -8,9 +8,9 @@ import { __ } from 'i18n'; */ import './style.scss'; import { registerBlockType, query, setUnknownTypeHandler } from '../../api'; -import FreeformBlock from './freeform-block'; +import OldEditor from './old-editor'; -const { children } = query; +const { prop } = query; registerBlockType( 'core/freeform', { title: __( 'Classic Text' ), @@ -20,29 +20,10 @@ registerBlockType( 'core/freeform', { category: 'formatting', attributes: { - content: children(), + content: prop( 'innerHTML' ), }, - defaultAttributes: { - content:

, - }, - - edit( { attributes, setAttributes, focus, setFocus } ) { - const { content } = attributes; - - return ( - { - setAttributes( { - content: nextContent, - } ); - } } - focus={ focus } - onFocus={ setFocus } - /> - ); - }, + edit: OldEditor, save( { attributes } ) { const { content } = attributes; diff --git a/blocks/library/freeform/old-editor.js b/blocks/library/freeform/old-editor.js new file mode 100644 index 0000000000000..e258479de7572 --- /dev/null +++ b/blocks/library/freeform/old-editor.js @@ -0,0 +1,159 @@ +/** + * WordPress dependencies + */ +import { Component } from 'element'; + +export default class OldEditor extends Component { + constructor( props ) { + super( props ); + this.initialize = this.initialize.bind( this ); + this.onSetup = this.onSetup.bind( this ); + } + + componentDidMount() { + const { baseURL, suffix } = window.wpEditorL10n.tinymce; + + window.tinymce.EditorManager.overrideDefaults( { + base_url: baseURL, + suffix, + } ); + + if ( document.readyState === 'complete' ) { + this.initialize(); + } else { + window.addEventListener( 'DOMContentLoaded', this.initialize ); + } + } + + componentWillUnmount() { + window.addEventListener( 'DOMContentLoaded', this.initialize ); + wp.oldEditor.remove( this.props.id ); + } + + componentDidUpdate( prevProps ) { + const { id, attributes: { content } } = this.props; + + if ( prevProps.attributes.content !== content ) { + window.tinymce.get( id ).setContent( content || '' ); + } + } + + initialize() { + const { id } = this.props; + const { + plugins, + external_plugins, + toolbar1, + toolbar2, + toolbar3, + toolbar4, + } = window.wpEditorL10n.tinymce.settings; + + wp.oldEditor.initialize( id, { + tinymce: { + inline: true, + content_css: false, + fixed_toolbar_container: '#' + id + '-toolbar', + plugins, + external_plugins, + toolbar1: toolbar1.join( ',' ), + toolbar2: toolbar2.join( ',' ), + toolbar3: toolbar3.join( ',' ), + toolbar4: toolbar4.join( ',' ), + setup: this.onSetup, + }, + } ); + } + + onSetup( editor ) { + const { attributes: { content }, setAttributes } = this.props; + const { ref } = this; + const initialContent = window.switchEditors.wpautop( content || '' ); + + editor.on( 'loadContent', () => editor.setContent( initialContent ) ); + + editor.on( 'blur', () => { + setAttributes( { + content: editor.getContent(), + } ); + } ); + + editor.addButton( 'kitchensink', { + tooltip: 'Toolbar Toggle', + icon: 'dashicon dashicons-editor-kitchensink', + onClick: function() { + const button = this; + const active = ! button.active(); + + button.active( active ); + editor.dom.toggleClass( ref, 'has-advanced-toolbar', active ); + }, + } ); + + /* eslint-disable */ + + // Re-register WP_More as it doesn't work with inline mode. + // This should be fixed in core. + // See wp-includes/js/tinymce/plugins/wordpress/plugin.js + // Swaps node.nodeName === 'BODY' to node === editor.getBody() + window.setTimeout( () => editor.addCommand( 'WP_More', function( tag ) { + var parent, html, title, + classname = 'wp-more-tag', + dom = editor.dom, + node = editor.selection.getNode(), + rootNode = editor.getBody(); + + tag = tag || 'more'; + classname += ' mce-wp-' + tag; + title = tag === 'more' ? 'Read more...' : 'Next page'; + title = __( title ); + html = ''; + + // Most common case + if ( node === rootNode || ( node.nodeName === 'P' && node.parentNode == rootNode ) ) { + editor.insertContent( html ); + return; + } + + // Get the top level parent node + parent = dom.getParent( node, function( found ) { + if ( found.parentNode && found.parentNode === rootNode ) { + return true; + } + + return false; + }, editor.getBody() ); + + if ( parent ) { + if ( parent.nodeName === 'P' ) { + parent.appendChild( dom.create( 'p', null, html ).firstChild ); + } else { + dom.insertAfter( dom.create( 'p', null, html ), parent ); + } + + editor.nodeChanged(); + } + } ) ); + + /* eslint-enable */ + } + + render() { + const { id } = this.props; + + return [ +

this.ref = ref } + className="editor-visual-editor__block-controls freeform-toolbar" + />, +
, + ]; + } +} diff --git a/blocks/library/freeform/style.scss b/blocks/library/freeform/style.scss index 835c15bf1e87b..e51650d57748b 100644 --- a/blocks/library/freeform/style.scss +++ b/blocks/library/freeform/style.scss @@ -18,15 +18,6 @@ color: $dark-gray-800; } - h1, - h2, - h3, - h4, - h5, - h6 { - margin: 0; - } - h1 { font-size: 2em; } @@ -51,15 +42,15 @@ font-size: 1em; } - > p:first-child { + > *:first-child { margin-top: 0; } - > p:last-child { + > *:last-child { margin-bottom: 0; } - &:focus { + &.mce-edit-focus { outline: none; } @@ -87,4 +78,140 @@ &:focus code[data-mce-selected] { background: $light-gray-400; } -} \ No newline at end of file +} + +.editor-visual-editor__block-controls.freeform-toolbar { + width: auto; +} + +.freeform-toolbar .mce-tinymce-inline { + margin: 0; + background: transparent; +} + +// Overwrite inline styles. +.freeform-toolbar .mce-tinymce-inline, +.freeform-toolbar .mce-tinymce-inline > div, +.freeform-toolbar div.mce-toolbar-grp, +.freeform-toolbar div.mce-toolbar-grp > div { + height: auto !important; + width: 100% !important; + border: none !important; +} + +.freeform-toolbar div.mce-toolbar-grp { + background-color: transparent; + border: none; + position: static; +} + +div.mce-toolbar-grp > div { + padding: 0; +} + +.freeform-toolbar div.mce-btn-group { + border: 1px solid $light-gray-500; + box-shadow: $shadow-popover; + background-color: $white; + padding: 0; + + &:not(:first-child) { + margin-left: 6px; + } +} + +.freeform-toolbar .mce-container-body.mce-abs-layout { + overflow: visible; +} + +.freeform-toolbar .mce-toolbar:not(:first-child) { + display: none; + position: absolute; + top: -44px; +} + +.freeform-toolbar.has-advanced-toolbar .mce-toolbar { + display: block; +} + +.freeform-toolbar .mce-toolbar .mce-btn { + margin: 0; + padding: 3px; + background: none; + outline: none; + color: $dark-gray-500; + cursor: pointer; + position: relative; + width: $icon-button-size; + height: $icon-button-size; + + // Overwrite + border: none; + box-sizing: border-box; + + &:hover, + /* the ":not(:disabled)" is needed to make it specific enough */ + &:hover:not(:disabled), + &:focus, + &:focus:active { + color: $dark-gray-500; + outline: none; + box-shadow: none; + background: inherit; + } + + &.mce-active, + &.mce-active:hover { + background: none; + color: $white; + } + + &:disabled { + cursor: default; + } + + &> button { + border: 1px solid transparent; + padding: 4px; + box-sizing: content-box; + } + + &:hover button, + &:focus button { + color: $dark-gray-500; + } + + &:not(:disabled) { + &.mce-active button, + &:hover button, + &:focus button { + border: 1px solid $dark-gray-500; + } + } + + &.mce-active button, + &.mce-active:hover button { + background-color: $dark-gray-500; + color: $white; + } + + &.mce-active .mce-ico { + color: $white; + } + + &.mce-listbox, + &.mce-colorbutton { + width: auto; + border: none; + box-shadow: none; + } + + &.mce-colorbutton .mce-preview { + bottom: 8px; + left: 8px; + } +} + +.components-toolbar__control .dashicon { + display: block; +} diff --git a/blocks/library/freeform/test/naiveCss2Jsx.js b/blocks/library/freeform/test/naiveCss2Jsx.js deleted file mode 100644 index 4384ecc724ec7..0000000000000 --- a/blocks/library/freeform/test/naiveCss2Jsx.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * External dependencies - */ -import { expect } from 'chai'; -/** - * Internal dependencies - */ -import { naiveCss2Jsx } from '../format-list'; - -describe( 'naiveCss2Jsx', () => { - it( 'should convert the Paragraph format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:16px;font-weight:400;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(68, 68, 68);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '16px', - fontWeight: '400', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(68, 68, 68)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Heading 1 format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:32px;font-weight:600;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(35, 40, 45);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '32px', - fontWeight: '600', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(35, 40, 45)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Heading 2/3 format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:20.8px;font-weight:600;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(35, 40, 45);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '20.8px', - fontWeight: '600', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(35, 40, 45)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Heading 4 format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:16px;font-weight:600;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(68, 68, 68);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '16px', - fontWeight: '600', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(68, 68, 68)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Heading 5 format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:13.2833px;font-weight:600;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(68, 68, 68);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '13.2833px', - fontWeight: '600', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(68, 68, 68)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Heading 6 format', () => { - expect( naiveCss2Jsx( - 'font-family:"Noto Serif",serif;font-size:10.7167px;font-weight:600;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(68, 68, 68);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: '"Noto Serif",serif', - fontSize: '10.7167px', - fontWeight: '600', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(68, 68, 68)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); - it( 'should convert the Preformatted format', () => { - expect( naiveCss2Jsx( - 'font-family:monospace;font-size:16px;font-weight:400;' + - 'font-style:normal;text-decoration:none;text-transform:none;' + - 'color:rgb(68, 68, 68);background-color:transparent;border:;' + - 'border-radius:;outline:;text-shadow:none;' - ) ).to.deep.equal( { - fontFamily: 'monospace', - fontSize: '16px', - fontWeight: '400', - fontStyle: 'normal', - textDecoration: 'none', - textTransform: 'none', - color: 'rgb(68, 68, 68)', - backgroundColor: 'transparent', - border: '', - borderRadius: '', - outline: '', - textShadow: 'none', - } ); - } ); -} ); diff --git a/blocks/test/fixtures/core-freeform.json b/blocks/test/fixtures/core-freeform.json index c12160e958417..35efd7b04fd19 100644 --- a/blocks/test/fixtures/core-freeform.json +++ b/blocks/test/fixtures/core-freeform.json @@ -3,28 +3,7 @@ "uid": "_uid_0", "name": "core/freeform", "attributes": { - "content": [ - "Testing freeform block with some\n", - { - "attributes": { - "className": "wp-some-class" - }, - "children": [ - "\n\tHTML ", - { - "attributes": { - "style": { - "color": "red" - } - }, - "children": "content", - "type": "span" - }, - "\n" - ], - "type": "div" - } - ] + "content": "Testing freeform block with some\n
\n\tHTML content\n
" } } ] diff --git a/blocks/test/fixtures/core-freeform.serialized.html b/blocks/test/fixtures/core-freeform.serialized.html index a31ee92b0385e..05bbc06efe57b 100644 --- a/blocks/test/fixtures/core-freeform.serialized.html +++ b/blocks/test/fixtures/core-freeform.serialized.html @@ -1,7 +1,7 @@ Testing freeform block with some -
- HTML content +
+ HTML content
diff --git a/lib/client-assets.php b/lib/client-assets.php index 99f3036b83581..8eaaa258d2fdb 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -374,6 +374,11 @@ function gutenberg_scripts_and_styles( $hook ) { * Scripts */ wp_enqueue_media(); + wp_enqueue_editor(); + + wp_add_inline_script( + 'editor', 'window.wp.oldEditor = window.wp.editor;', 'after' + ); gutenberg_extend_wp_api_backbone_client(); @@ -381,11 +386,72 @@ function gutenberg_scripts_and_styles( $hook ) { wp_enqueue_script( 'wp-editor', gutenberg_url( 'editor/build/index.js' ), - array( 'wp-api', 'wp-date', 'wp-i18n', 'wp-blocks', 'wp-element', 'wp-components', 'wp-utils' ), + array( 'wp-api', 'wp-date', 'wp-i18n', 'wp-blocks', 'wp-element', 'wp-components', 'wp-utils', 'editor' ), filemtime( gutenberg_dir_path() . 'editor/build/index.js' ), true // enqueue in the footer. ); + wp_localize_script( 'wp-editor', 'wpEditorL10n', array( + 'tinymce' => array( + 'baseURL' => includes_url( 'js/tinymce' ), + 'suffix' => SCRIPT_DEBUG ? '' : '.min', + 'settings' => array( + 'external_plugins' => apply_filters( 'mce_external_plugins', array() ), + 'plugins' => array_unique( apply_filters( 'tiny_mce_plugins', array( + 'charmap', + 'colorpicker', + 'hr', + 'lists', + 'media', + 'paste', + 'tabfocus', + 'textcolor', + 'fullscreen', + 'wordpress', + 'wpautoresize', + 'wpeditimage', + 'wpemoji', + 'wpgallery', + 'wplink', + 'wpdialogs', + 'wptextpattern', + 'wpview', + ) ) ), + 'toolbar1' => array_merge( apply_filters( 'mce_buttons', array( + 'formatselect', + '|', + 'alignleft', + 'aligncenter', + 'alignright', + '|', + 'bullist', + 'numlist', + 'blockquote', + '|', + 'bold', + 'italic', + 'strikethrough', + 'link', + ), 'editor' ), array( '|', 'kitchensink' ) ), + 'toolbar2' => apply_filters( 'mce_buttons_2', array( + 'hr', + 'wp_more', + 'forecolor', + 'pastetext', + 'removeformat', + 'charmap', + 'outdent', + 'indent', + 'undo', + 'redo', + 'wp_help', + ), 'editor' ), + 'toolbar3' => apply_filters( 'mce_buttons_3', array(), 'editor' ), + 'toolbar4' => apply_filters( 'mce_buttons_4', array(), 'editor' ), + ), + ), + ) ); + $post_id = null; if ( isset( $_GET['post_id'] ) && (int) $_GET['post_id'] > 0 ) { $post_id = (int) $_GET['post_id'];