From 387bb77b0f21c73399f71445f85ad9db91750d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Thu, 6 Dec 2018 11:17:29 +0100 Subject: [PATCH 01/33] RichText: fix onSetup doc (#12607) --- packages/editor/src/components/rich-text/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/components/rich-text/index.js b/packages/editor/src/components/rich-text/index.js index 872049c948e6a..de0e7dd5aa363 100644 --- a/packages/editor/src/components/rich-text/index.js +++ b/packages/editor/src/components/rich-text/index.js @@ -134,12 +134,9 @@ export class RichText extends Component { } /** - * Handles the onSetup event for the TinyMCE component. + * Sets a reference to the TinyMCE editor instance. * - * Will setup event handlers for the TinyMCE instance. - * An `onSetup` function in the props will be called if it is present. - * - * @param {tinymce} editor The editor instance as passed by TinyMCE. + * @param {Editor} editor The editor instance as passed by TinyMCE. */ onSetup( editor ) { this.editor = editor; From d7eaeb916779bd31d9abe657ac14f7f20cbc4a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fda=C5=9F=20Da=C4=9F?= Date: Fri, 7 Dec 2018 18:09:50 +0300 Subject: [PATCH 02/33] Update broken links (#12660) * Update broken links There was 2 broken links. I changed same way with Data Module Reference page. * Update docs/designers-developers/developers/block-api/README.md Co-Authored-By: cagdasdag * Update docs/designers-developers/developers/block-api/README.md Co-Authored-By: cagdasdag --- docs/designers-developers/developers/block-api/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/designers-developers/developers/block-api/README.md b/docs/designers-developers/developers/block-api/README.md index 1301449ecdf2c..2c18a261d8fc5 100644 --- a/docs/designers-developers/developers/block-api/README.md +++ b/docs/designers-developers/developers/block-api/README.md @@ -4,8 +4,8 @@ Blocks are the fundamental element of the Gutenberg editor. They are the primary ## Registering a block -All blocks must be registered before they can be used in the editor. You can learn about block registration, and the available options, in the [block registration](block-api/block-registration.md) documentation. +All blocks must be registered before they can be used in the editor. You can learn about block registration, and the available options, in the [block registration](../../../../docs/designers-developers/developers/block-api/block-registration.md) documentation. ## Block `edit` and `save` -The `edit` and `save` functions define the editor interface with which a user would interact, and the markup to be serialized back when a post is saved. They are the heart of how a block operates, so they are [covered separately](block-api/block-edit-save.md). +The `edit` and `save` functions define the editor interface with which a user would interact, and the markup to be serialized back when a post is saved. They are the heart of how a block operates, so they are [covered separately](../../../../docs/designers-developers/developers/block-api/block-edit-save.md). From 50cafddcc593fbb37c99f54c878079bd9aa5bfe7 Mon Sep 17 00:00:00 2001 From: Marcus Kazmierczak Date: Fri, 7 Dec 2018 07:10:21 -0800 Subject: [PATCH 03/33] Docs: Update Glossary (#12479) * Update glossar with missing terms * Convert glossary to use dl/dt/dd dtags. Fixes #9976 * Fix TinyMCE link * remove spacing around tags * Add template definition, with link * Updates per review * Update docs/designers-developers/glossary.md Co-Authored-By: mkaz --- docs/designers-developers/glossary.md | 78 ++++++++++++++++++++------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/docs/designers-developers/glossary.md b/docs/designers-developers/glossary.md index afa574179db27..f51c0d16d5dba 100644 --- a/docs/designers-developers/glossary.md +++ b/docs/designers-developers/glossary.md @@ -1,21 +1,61 @@ # Glossary -- **Attribute sources**: An object describing the attributes shape of a block. The keys can be named as most appropriate to describe the state of a block type. The value for each key is a function which describes the strategy by which the attribute value should be extracted from the content of a saved post's content. When processed, a new object is created, taking the form of the keys defined in the attribute sources, where each value is the result of the attribute source function. -- **Attributes**: The object representation of the current state of a block in post content. When loading a saved post, this is determined by the attribute sources for the block type. These values can change over time during an editing session when the user modifies a block, and are used when determining how to serialize the block. -- **Block**: The abstract term used to describe units of markup that, composed together, form the content or layout of a webpage. The idea combines concepts of what in WordPress today we achieve with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. -- **Block Categories**: These are not a WordPress taxonomy, but instead used internally to sort blocks in the Block Inserter. -- **Block Inserter**: Primary interface for selecting from the available blocks, triggered by plus icon buttons on Blocks or in the top-left of the editor interface. -- **Block name**: A unique identifier for a block type, consisting of a plugin-specific namespace and a short label describing the block's intent. e.g. `core/image` -- **Block type**: In contrast with the blocks composing a particular post, a block type describes the blueprint by which any block of that type should behave. So while there may be many images within a post, each behaves consistent with a unified image block type definition. -- **Classic block**: -- **Dynamic block**: A type of block where the content of which may change and cannot be determined at the time of saving a post, instead calculated any time the post is shown on the front of a site. These blocks may save fallback content or no content at all in their JavaScript implementation, instead deferring to a PHP block implementation for runtime rendering. -- **RichText**: A common component enabling rich content editing including bold, italics, hyperlinks, etc. It is not too much unlike the single editor region of the legacy post editor, and is in fact powered by the same TinyMCE library. -- **Inspector**: A block settings region shown in place of the post settings when a block is selected. Fields may be shown here to allow the user to customize the selected block. -- **Post settings**: A sidebar region containing metadata fields for the post, including scheduling, visibility, terms, and featured image. -- **Reusable block**: -- **Sidebar**: -- **Serialization**: The process of converting a block's attributes object into HTML markup, typically occurring when saving the post. -- **Static block**: A type of block where the content of which is known at the time of saving a post. A static block will be saved with HTML markup directly in post content. -- **TinyMCE**: [TinyMCE](https://www.tinymce.com/) is a web-based JavaScript WYSIWYG (What You See Is What You Get) editor. -- **Toolbar**: A set of button controls. In the context of a block, usually referring to the toolbar of block controls shown above the selected block. -- **Template**: +
+
Attribute sources
+
An object describing the attributes shape of a block. The keys can be named as most appropriate to describe the state of a block type. The value for each key is a function which describes the strategy by which the attribute value should be extracted from the content of a saved post's content. When processed, a new object is created, taking the form of the keys defined in the attribute sources, where each value is the result of the attribute source function.
+ +
Attributes
+
The object representation of the current state of a block in post content. When loading a saved post, this is determined by the attribute sources for the block type. These values can change over time during an editing session when the user modifies a block, and are used when determining how to serialize the block.
+ +
Block
+
The abstract term used to describe units of markup that, composed together, form the content or layout of a webpage. The idea combines concepts of what in WordPress today we achieve with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.
+ +
Block Categories
+
These are not a WordPress taxonomy, but instead used internally to sort blocks in the Block Inserter.
+ +
Block Inserter
+
Primary interface for selecting from the available blocks, triggered by plus icon buttons on Blocks or in the top-left of the editor interface.
+ +
Block name
+
A unique identifier for a block type, consisting of a plugin-specific namespace and a short label describing the block's intent. e.g. core/image
+ +
Block type
+
In contrast with the blocks composing a particular post, a block type describes the blueprint by which any block of that type should behave. So while there may be many images within a post, each behaves consistent with a unified image block type definition.
+ +
Classic block
+
A block which embeds the TinyMCE editor as a block, TinyMCE was the base of the previous core editor. Older content created prior to the block editor will be loaded in to a single Classic block.
+ +
Dynamic block
+
A type of block where the content of which may change and cannot be determined at the time of saving a post, instead calculated any time the post is shown on the front of a site. These blocks may save fallback content or no content at all in their JavaScript implementation, instead deferring to a PHP block implementation for runtime rendering.
+ +
Inspector
+
A block settings region shown in place of the post settings when a block is selected. Fields may be shown here to allow the user to customize the selected block.
+ +
Post settings
+
A sidebar region containing metadata fields for the post, including scheduling, visibility, terms, and featured image.
+ +
RichText
+
A common component enabling rich content editing including bold, italics, hyperlinks, etc. It is not too much unlike the single editor region of the legacy post editor, and is in fact powered by the same TinyMCE library.
+ +
Reusable block
+
A block that is saved and then can be shared as a reusable, repeatable piece of content.
+ +
Sidebar
+
The panel on the right which contains the document and block settings. The sidebar is toggled using the Settings gear icon.
+ +
Serialization
+
The process of converting a block's attributes object into HTML markup, which occurs each time a block is edited.
+ +
Static block
+
A type of block where the content of which is known at the time of saving a post. A static block will be saved with HTML markup directly in post content.
+ +
TinyMCE
+
TinyMCE is a web-based JavaScript WYSIWYG (What You See Is What You Get) editor.
+ +
Toolbar
+
A set of button controls. In the context of a block, usually referring to the toolbar of block controls shown above the selected block.
+ +
Template
+
A template is a pre-defined arrangement of blocks, possibly with predefined attributes or placeholder content. You can provide a template for a post type, to give users a starting point when creating a new piece of content, or inside a custom block with the InnerBlocks component. See the templates documentation for more information. See templates documentation for more information.
+ +
From 6b8cd54fde910aee9928679a18bb8daf84daf03d Mon Sep 17 00:00:00 2001 From: George Hotelling Date: Fri, 7 Dec 2018 10:10:48 -0500 Subject: [PATCH 04/33] Add documentation for `safeDecodeURI()` and `filterURLForDisplay()` (#12570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add documentation for `safeDecodeURI()` and `filterURLForDisplay()` * Whitespace * Consistant Capit… i mean capitalization * Oxford comma Co-Authored-By: georgeh --- packages/url/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/url/README.md b/packages/url/README.md index 4c092d670fc9f..fb78d8808bb2b 100644 --- a/packages/url/README.md +++ b/packages/url/README.md @@ -167,4 +167,20 @@ const newUrl = removeQueryArgs( 'https://wordpress.org?foo=bar&bar=baz&baz=fooba Removes one or more query string arguments from the given URL. +### safeDecodeURI + +```js +const badUri = safeDecodeURI( '%z' ); // does not throw an Error, simply returns '%z' +``` + +Safely decodes a URI with `decodeURI`. Returns the URI unmodified if `decodeURI` throws an Error. + +### filterURLForDisplay + +```js +const displayUrl = filterURLForDisplay( 'https://www.wordpress.org/gutenberg/' ); // wordpress.org/gutenberg +``` + +Returns a URL for display, without protocol, www subdomain, or trailing slash. +

Code is Poetry.

From f5b18c2a1e8ea7a5be8183b78fbaa71bc3da262e Mon Sep 17 00:00:00 2001 From: Joseph Chesterton <37393284+josephchesterton@users.noreply.github.com> Date: Sat, 8 Dec 2018 01:13:08 +1000 Subject: [PATCH 05/33] Update theme-support.md (#12661) --- docs/designers-developers/developers/themes/theme-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/designers-developers/developers/themes/theme-support.md b/docs/designers-developers/developers/themes/theme-support.md index abc611dc5d000..a5da2c7199e97 100644 --- a/docs/designers-developers/developers/themes/theme-support.md +++ b/docs/designers-developers/developers/themes/theme-support.md @@ -4,7 +4,7 @@ The new Blocks include baseline support in all themes, enhancements to opt-in to There are a few new concepts to consider when building themes: -- **Editor Color Palette** - A default set of colors is provided, but themes and register their own and optionally lock users into picking from the defined palette. +- **Editor Color Palette** - A default set of colors is provided, but themes can register their own and optionally lock users into picking from the defined palette. - **Editor Text Size Palette** - A default set of sizes is provided, but themes and register their own and optionally lock users into picking from preselected sizes. - **Responsive Embeds** - Themes must opt-in to responsive embeds. - **Frontend & Editor Styles** - To get the most out of blocks, theme authors will want to make sure Core styles look good and opt-in, or write their own styles to best fit their theme. From 7f118ddbb66452ccbcf820ba36240330845df9d7 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Sat, 8 Dec 2018 06:50:33 +0000 Subject: [PATCH 06/33] Fix: Undoing Image Selection in Image Block results in Broken Image (#12567) --- packages/block-library/src/image/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index cb059b5bfcdc6..551e3dadda255 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -414,7 +414,7 @@ class ImageEdit extends Component { ); - if ( isEditing ) { + if ( isEditing || ! url ) { const src = isExternal ? url : undefined; return ( From 715af6b4980ae75c8dd505f06765f610894ef0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sat, 8 Dec 2018 11:38:14 +0100 Subject: [PATCH 07/33] Optimize isViewportMatch (#12542) --- packages/viewport/src/store/selectors.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/viewport/src/store/selectors.js b/packages/viewport/src/store/selectors.js index ea8308d6ee156..d379beeb5052f 100644 --- a/packages/viewport/src/store/selectors.js +++ b/packages/viewport/src/store/selectors.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import { takeRight } from 'lodash'; - /** * Returns true if the viewport matches the given query, or false otherwise. * @@ -20,9 +15,10 @@ import { takeRight } from 'lodash'; * @return {boolean} Whether viewport matches query. */ export function isViewportMatch( state, query ) { - // Pad to _at least_ two elements to take from the right, effectively - // defaulting the left-most value. - const key = takeRight( [ '>=', ...query.split( ' ' ) ], 2 ).join( ' ' ); + // Default to `>=` if no operator is present. + if ( query.indexOf( ' ' ) === -1 ) { + query = '>= ' + query; + } - return !! state[ key ]; + return !! state[ query ]; } From 8e772be25ad16891db000351a929c4957c54029f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sat, 8 Dec 2018 11:39:02 +0100 Subject: [PATCH 08/33] Cache createBlock call in isUnmodifiedDefaultBlock (#12521) * Cache createBlock call in isUnmodifiedDefaultBlock * Invalidate cache when default block name changes * Merge ifs --- packages/blocks/src/api/test/utils.js | 29 +++++++++++++++++++++++++++ packages/blocks/src/api/utils.js | 11 +++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/blocks/src/api/test/utils.js b/packages/blocks/src/api/test/utils.js index 0bfeb8b0fe258..ea3fe57908441 100644 --- a/packages/blocks/src/api/test/utils.js +++ b/packages/blocks/src/api/test/utils.js @@ -67,5 +67,34 @@ describe( 'block helpers', () => { expect( isUnmodifiedDefaultBlock( block ) ).toBe( false ); } ); + + it( 'should invalidate cache if the default block name changed', () => { + registerBlockType( 'core/test-block1', { + attributes: { + includesDefault1: { + type: 'boolean', + default: true, + }, + }, + save: noop, + category: 'common', + title: 'test block', + } ); + registerBlockType( 'core/test-block2', { + attributes: { + includesDefault2: { + type: 'boolean', + default: true, + }, + }, + save: noop, + category: 'common', + title: 'test block', + } ); + setDefaultBlockName( 'core/test-block1' ); + isUnmodifiedDefaultBlock( createBlock( 'core/test-block1' ) ); + setDefaultBlockName( 'core/test-block2' ); + expect( isUnmodifiedDefaultBlock( createBlock( 'core/test-block2' ) ) ).toBe( true ); + } ); } ); } ); diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 392593b440096..6dcabbcbcea01 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -38,7 +38,16 @@ export function isUnmodifiedDefaultBlock( block ) { return false; } - const newDefaultBlock = createBlock( defaultBlockName ); + // Cache a created default block if no cache exists or the default block + // name changed. + if ( + ! isUnmodifiedDefaultBlock.block || + isUnmodifiedDefaultBlock.block.name !== defaultBlockName + ) { + isUnmodifiedDefaultBlock.block = createBlock( defaultBlockName ); + } + + const newDefaultBlock = isUnmodifiedDefaultBlock.block; const blockType = getBlockType( defaultBlockName ); return every( blockType.attributes, ( value, key ) => From d385f3d76f7574a8284c41bfbe12ab1c909ff66c Mon Sep 17 00:00:00 2001 From: Andrea Fercia Date: Sat, 8 Dec 2018 11:40:06 +0100 Subject: [PATCH 09/33] Font Size Picker: Use a menuitemradio role and better labels. (#12372) * Use a menuitemradio role and better labels. * Restore Button and remove MenuItem import. * Use template literals. --- .../components/src/font-size-picker/index.js | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/components/src/font-size-picker/index.js b/packages/components/src/font-size-picker/index.js index 16329316d5ad1..2908b3879c1eb 100644 --- a/packages/components/src/font-size-picker/index.js +++ b/packages/components/src/font-size-picker/index.js @@ -6,8 +6,7 @@ import { map } from 'lodash'; /** * WordPress dependencies */ -import { __, _x } from '@wordpress/i18n'; -import { withInstanceId } from '@wordpress/compose'; +import { __, _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -37,6 +36,7 @@ function FontSizePicker( { }; const currentFont = fontSizes.find( ( font ) => font.size === value ); + const currentFontSizeName = ( currentFont && currentFont.name ) || ( ! value && _x( 'Normal', 'font size name' ) ) || _x( 'Custom', 'font size name' ); return ( @@ -51,26 +51,34 @@ function FontSizePicker( { isLarge onClick={ onToggle } aria-expanded={ isOpen } - aria-label={ __( 'Custom font size' ) } + aria-label={ sprintf( + /* translators: %s: font size name */ + __( 'Font size: %s' ), currentFontSizeName + ) } > - { ( currentFont && currentFont.name ) || ( ! value && _x( 'Normal', 'font size name' ) ) || _x( 'Custom', 'font size name' ) } + { currentFontSizeName } ) } renderContent={ () => ( - { map( fontSizes, ( { name, size, slug } ) => ( - - ) ) } + { map( fontSizes, ( { name, size, slug } ) => { + const isSelected = ( value === size || ( ! value && slug === 'normal' ) ); + + return ( + + ); + } ) } ) } /> @@ -90,7 +98,6 @@ function FontSizePicker( { onClick={ () => onChange( undefined ) } isSmall isDefault - aria-label={ __( 'Reset font size' ) } > { __( 'Reset' ) } @@ -112,4 +119,4 @@ function FontSizePicker( { ); } -export default withInstanceId( FontSizePicker ); +export default FontSizePicker; From 13459da2de90fba6279668b8ab6771020e8f4a2b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 8 Dec 2018 04:40:40 -0600 Subject: [PATCH 10/33] Set document title for preview interstitial (#12466) --- packages/editor/src/components/post-preview-button/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/post-preview-button/index.js b/packages/editor/src/components/post-preview-button/index.js index 5c31e9e271de8..b735ebcd5324e 100644 --- a/packages/editor/src/components/post-preview-button/index.js +++ b/packages/editor/src/components/post-preview-button/index.js @@ -80,6 +80,7 @@ function writeInterstitialMessage( targetDocument ) { `; targetDocument.write( markup ); + targetDocument.title = __( 'Generating preview…' ); targetDocument.close(); } From 1d5fa326dce3998c8fef809645121ba5a6b75384 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Sun, 9 Dec 2018 09:52:04 -0600 Subject: [PATCH 11/33] Fix e2e tests after the WordPress 5.0 upgrade (#12715) * Fix e2e tests after the WordPress 5.0 upgrade * Remove the php unit tests testing the WP5.0 core instead of the plugin --- phpunit/class-parsing-test.php | 105 ---- ...ss-rest-block-renderer-controller-test.php | 454 --------------- phpunit/class-rest-blocks-controller-test.php | 204 ------- phpunit/class-rest-search-controller-test.php | 521 ------------------ test/e2e/specs/classic-editor.test.js | 25 - test/e2e/specs/font-size-picker.test.js | 12 +- test/e2e/specs/new-post.test.js | 7 + test/e2e/specs/templates.test.js | 10 +- test/e2e/specs/writing-flow.test.js | 3 + test/e2e/support/plugins.js | 2 +- test/e2e/test-plugins/post-formats.php | 15 + 11 files changed, 42 insertions(+), 1316 deletions(-) delete mode 100644 phpunit/class-parsing-test.php delete mode 100644 phpunit/class-rest-block-renderer-controller-test.php delete mode 100644 phpunit/class-rest-blocks-controller-test.php delete mode 100644 phpunit/class-rest-search-controller-test.php delete mode 100644 test/e2e/specs/classic-editor.test.js create mode 100644 test/e2e/test-plugins/post-formats.php diff --git a/phpunit/class-parsing-test.php b/phpunit/class-parsing-test.php deleted file mode 100644 index b854f8e306a2b..0000000000000 --- a/phpunit/class-parsing-test.php +++ /dev/null @@ -1,105 +0,0 @@ -parse( _gutenberg_utf8_split( $html ) ); - - $this->assertEquals( - $expected_parsed, - $result, - "File '$parsed_json_filename' does not match expected value" - ); - } - - /** - * @dataProvider parsing_test_filenames - */ - function test_default_parser_output( $html_filename, $parsed_json_filename ) { - // include the parser if it was not yet loaded. - require_once dirname( __FILE__ ) . '/../packages/block-serialization-default-parser/parser.php'; - $html_path = self::$fixtures_dir . '/' . $html_filename; - $parsed_json_path = self::$fixtures_dir . '/' . $parsed_json_filename; - - foreach ( array( $html_path, $parsed_json_path ) as $filename ) { - if ( ! file_exists( $filename ) ) { - throw new Exception( "Missing fixture file: '$filename'" ); - } - } - - $html = self::strip_r( file_get_contents( $html_path ) ); - $expected_parsed = json_decode( self::strip_r( file_get_contents( $parsed_json_path ) ), true ); - - $parser = new WP_Block_Parser(); - $result = json_decode( json_encode( $parser->parse( $html ) ), true ); - - $this->assertEquals( - $expected_parsed, - $result, - "File '$parsed_json_filename' does not match expected value" - ); - } -} diff --git a/phpunit/class-rest-block-renderer-controller-test.php b/phpunit/class-rest-block-renderer-controller-test.php deleted file mode 100644 index 3691c4d162af4..0000000000000 --- a/phpunit/class-rest-block-renderer-controller-test.php +++ /dev/null @@ -1,454 +0,0 @@ -user->create( - array( - 'role' => 'editor', - ) - ); - - self::$author_id = $factory->user->create( - array( - 'role' => 'author', - ) - ); - - self::$post_id = $factory->post->create( - array( - 'post_title' => 'Test Post', - ) - ); - } - - /** - * Delete test data after our tests run. - */ - public static function wpTearDownAfterClass() { - self::delete_user( self::$user_id ); - } - - /** - * Set up. - * - * @see gutenberg_register_rest_routes() - */ - public function setUp() { - $this->register_test_block(); - $this->register_post_context_test_block(); - parent::setUp(); - } - - /** - * Tear down. - */ - public function tearDown() { - WP_Block_Type_Registry::get_instance()->unregister( self::$block_name ); - WP_Block_Type_Registry::get_instance()->unregister( self::$context_block_name ); - parent::tearDown(); - } - - /** - * Register test block. - */ - public function register_test_block() { - register_block_type( - self::$block_name, - array( - 'attributes' => array( - 'some_string' => array( - 'type' => 'string', - 'default' => 'some_default', - ), - 'some_int' => array( - 'type' => 'integer', - ), - 'some_array' => array( - 'type' => 'array', - 'items' => array( - 'type' => 'integer', - ), - ), - ), - 'render_callback' => array( $this, 'render_test_block' ), - ) - ); - } - - /** - * Register test block with post_id as attribute for post context test. - */ - public function register_post_context_test_block() { - register_block_type( - self::$context_block_name, - array( - 'attributes' => array(), - 'render_callback' => array( $this, 'render_post_context_test_block' ), - ) - ); - } - - /** - * Test render callback. - * - * @param array $attributes Props. - * @return string Rendered attributes, which is here just JSON. - */ - public function render_test_block( $attributes ) { - return wp_json_encode( $attributes ); - } - - /** - * Test render callback for testing post context. - * - * @return string - */ - public function render_post_context_test_block() { - return get_the_title(); - } - - /** - * Check that the route was registered properly. - * - * @covers WP_REST_Block_Renderer_Controller::register_routes() - */ - public function test_register_routes() { - $dynamic_block_names = get_dynamic_block_names(); - $this->assertContains( self::$block_name, $dynamic_block_names ); - - $routes = rest_get_server()->get_routes(); - foreach ( $dynamic_block_names as $dynamic_block_name ) { - $this->assertArrayHasKey( self::$rest_api_route . "(?P$dynamic_block_name)", $routes ); - } - } - - /** - * Test getting item without permissions. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item_without_permissions() { - wp_set_current_user( 0 ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'gutenberg_block_cannot_read', $response, rest_authorization_required_code() ); - } - - /** - * Test getting item without 'edit' context. - */ - public function test_get_item_with_invalid_context() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); - } - - /** - * Test getting item with invalid block name. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item_invalid_block_name() { - wp_set_current_user( self::$user_id ); - $request = new WP_REST_Request( 'GET', self::$rest_api_route . 'core/123' ); - - $request->set_param( 'context', 'edit' ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'rest_no_route', $response, 404 ); - } - - /** - * Check getting item with an invalid param provided. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item_invalid_attribute() { - wp_set_current_user( self::$user_id ); - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - $request->set_param( - 'attributes', - array( - 'some_string' => array( 'no!' ), - ) - ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 400, $response->get_status() ); - } - - /** - * Check getting item with an invalid param provided. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item_unrecognized_attribute() { - wp_set_current_user( self::$user_id ); - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - $request->set_param( - 'attributes', - array( - 'unrecognized' => 'yes', - ) - ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 400, $response->get_status() ); - } - - /** - * Check getting item with default attributes provided. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item_default_attributes() { - wp_set_current_user( self::$user_id ); - - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( self::$block_name ); - $defaults = array(); - foreach ( $block_type->attributes as $key => $attribute ) { - if ( isset( $attribute['default'] ) ) { - $defaults[ $key ] = $attribute['default']; - } - } - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - $request->set_param( 'attributes', array() ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->assertEquals( $defaults, json_decode( $data['rendered'], true ) ); - $this->assertEquals( - json_decode( $block_type->render( $defaults ) ), - json_decode( $data['rendered'] ) - ); - } - - /** - * Check getting item with attributes provided. - * - * @covers WP_REST_Block_Renderer_Controller::get_item() - */ - public function test_get_item() { - wp_set_current_user( self::$user_id ); - - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( self::$block_name ); - $attributes = array( - 'some_int' => '123', - 'some_string' => 'foo', - 'some_array' => array( 1, '2', 3 ), - ); - - $expected_attributes = $attributes; - $expected_attributes['some_int'] = (int) $expected_attributes['some_int']; - $expected_attributes['some_array'] = array_map( 'intval', $expected_attributes['some_array'] ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - $request->set_param( 'attributes', $attributes ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->assertEquals( $expected_attributes, json_decode( $data['rendered'], true ) ); - $this->assertEquals( - json_decode( $block_type->render( $attributes ), true ), - json_decode( $data['rendered'], true ) - ); - } - - - - /** - * Check success response for getting item with layout attribute provided. - */ - public function test_get_item_with_layout() { - wp_set_current_user( self::$user_id ); - - $attributes = array( - 'layout' => 'foo', - ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); - $request->set_param( 'context', 'edit' ); - $request->set_param( 'attributes', $attributes ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - } - - /** - * Test getting item with post context. - */ - public function test_get_item_with_post_context() { - wp_set_current_user( self::$user_id ); - - $expected_title = 'Test Post'; - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$context_block_name ); - $request->set_param( 'context', 'edit' ); - - // Test without post ID. - $response = rest_get_server()->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->assertTrue( empty( $data['rendered'] ) ); - - // Now test with post ID. - $request->set_param( 'post_id', self::$post_id ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->assertEquals( $expected_title, $data['rendered'] ); - } - - /** - * Test getting item with invalid post ID. - */ - public function test_get_item_without_permissions_invalid_post() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$context_block_name ); - $request->set_param( 'context', 'edit' ); - - // Test with invalid post ID. - $request->set_param( 'post_id', PHP_INT_MAX ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'gutenberg_block_cannot_read', $response, 403 ); - } - - /** - * Test getting item without permissions to edit context post. - */ - public function test_get_item_without_permissions_cannot_edit_post() { - wp_set_current_user( self::$author_id ); - - $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$context_block_name ); - $request->set_param( 'context', 'edit' ); - - // Test with private post ID. - $request->set_param( 'post_id', self::$post_id ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'gutenberg_block_cannot_read', $response, 403 ); - } - - /** - * Get item schema. - * - * @covers WP_REST_Block_Renderer_Controller::get_item_schema() - */ - public function test_get_item_schema() { - $request = new WP_REST_Request( 'OPTIONS', self::$rest_api_route . self::$block_name ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertEqualSets( array( 'GET' ), $data['endpoints'][0]['methods'] ); - $this->assertEqualSets( - array( 'name', 'context', 'attributes', 'post_id' ), - array_keys( $data['endpoints'][0]['args'] ) - ); - $this->assertEquals( 'object', $data['endpoints'][0]['args']['attributes']['type'] ); - - $this->assertArrayHasKey( 'schema', $data ); - $this->assertEquals( 'rendered-block', $data['schema']['title'] ); - $this->assertEquals( 'object', $data['schema']['type'] ); - $this->arrayHasKey( 'rendered', $data['schema']['properties'] ); - $this->arrayHasKey( 'string', $data['schema']['properties']['rendered']['type'] ); - $this->assertEquals( array( 'edit' ), $data['schema']['properties']['rendered']['context'] ); - } - - public function test_update_item() { - $this->markTestSkipped( 'Controller doesn\'t implement update_item().' ); - } - - public function test_create_item() { - $this->markTestSkipped( 'Controller doesn\'t implement create_item().' ); - } - - public function test_delete_item() { - $this->markTestSkipped( 'Controller doesn\'t implement delete_item().' ); - } - - public function test_get_items() { - $this->markTestSkipped( 'Controller doesn\'t implement get_items().' ); - } - - public function test_context_param() { - $this->markTestSkipped( 'Controller doesn\'t implement context_param().' ); - } - - public function test_prepare_item() { - $this->markTestSkipped( 'Controller doesn\'t implement prepare_item().' ); - } -} diff --git a/phpunit/class-rest-blocks-controller-test.php b/phpunit/class-rest-blocks-controller-test.php deleted file mode 100644 index 5a9e71af7e33e..0000000000000 --- a/phpunit/class-rest-blocks-controller-test.php +++ /dev/null @@ -1,204 +0,0 @@ - 'wp_block', - 'post_status' => 'publish', - 'post_title' => 'My cool block', - 'post_content' => '

Hello!

', - ) - ); - - self::$user_ids = array( - 'editor' => $factory->user->create( array( 'role' => 'editor' ) ), - 'author' => $factory->user->create( array( 'role' => 'author' ) ), - 'contributor' => $factory->user->create( array( 'role' => 'contributor' ) ), - ); - } - - /** - * Delete our fake data after our tests run. - */ - public static function wpTearDownAfterClass() { - wp_delete_post( self::$post_id ); - - foreach ( self::$user_ids as $user_id ) { - self::delete_user( $user_id ); - } - } - - /** - * Test cases for test_capabilities(). - */ - public function data_capabilities() { - return array( - array( 'create', 'editor', 201 ), - array( 'create', 'author', 201 ), - array( 'create', 'contributor', 403 ), - array( 'create', null, 401 ), - - array( 'read', 'editor', 200 ), - array( 'read', 'author', 200 ), - array( 'read', 'contributor', 200 ), - array( 'read', null, 401 ), - - array( 'update_delete_own', 'editor', 200 ), - array( 'update_delete_own', 'author', 200 ), - array( 'update_delete_own', 'contributor', 403 ), - - array( 'update_delete_others', 'editor', 200 ), - array( 'update_delete_others', 'author', 403 ), - array( 'update_delete_others', 'contributor', 403 ), - array( 'update_delete_others', null, 401 ), - ); - } - - /** - * Exhaustively check that each role either can or cannot create, edit, - * update, and delete reusable blocks. - * - * @dataProvider data_capabilities - */ - public function test_capabilities( $action, $role, $expected_status ) { - if ( $role ) { - $user_id = self::$user_ids[ $role ]; - wp_set_current_user( $user_id ); - } else { - wp_set_current_user( 0 ); - } - - switch ( $action ) { - case 'create': - $request = new WP_REST_Request( 'POST', '/wp/v2/blocks' ); - $request->set_body_params( - array( - 'title' => 'Test', - 'content' => '

Test

', - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - break; - - case 'read': - $request = new WP_REST_Request( 'GET', '/wp/v2/blocks/' . self::$post_id ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - break; - - case 'update_delete_own': - $post_id = wp_insert_post( - array( - 'post_type' => 'wp_block', - 'post_status' => 'publish', - 'post_title' => 'My cool block', - 'post_content' => '

Hello!

', - 'post_author' => $user_id, - ) - ); - - $request = new WP_REST_Request( 'PUT', '/wp/v2/blocks/' . $post_id ); - $request->set_body_params( - array( - 'title' => 'Test', - 'content' => '

Test

', - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - $request = new WP_REST_Request( 'DELETE', '/wp/v2/blocks/' . $post_id ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - wp_delete_post( $post_id ); - - break; - - case 'update_delete_others': - $request = new WP_REST_Request( 'PUT', '/wp/v2/blocks/' . self::$post_id ); - $request->set_body_params( - array( - 'title' => 'Test', - 'content' => '

Test

', - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - $request = new WP_REST_Request( 'DELETE', '/wp/v2/blocks/' . self::$post_id ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( $expected_status, $response->get_status() ); - - break; - - default: - $this->fail( "'$action' is not a valid action." ); - } - } - - /** - * Check that the raw title and content of a block can be accessed when there - * is no set schema, and that the rendered content of a block is not included - * in the response. - */ - public function test_content() { - wp_set_current_user( self::$user_ids['author'] ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/blocks/' . self::$post_id ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertEquals( - array( - 'raw' => 'My cool block', - ), - $data['title'] - ); - $this->assertEquals( - array( - 'raw' => '

Hello!

', - 'protected' => false, - ), - $data['content'] - ); - } -} diff --git a/phpunit/class-rest-search-controller-test.php b/phpunit/class-rest-search-controller-test.php deleted file mode 100644 index 26649037e8ff2..0000000000000 --- a/phpunit/class-rest-search-controller-test.php +++ /dev/null @@ -1,521 +0,0 @@ -post->create_many( - 4, - array( - 'post_title' => 'my-footitle', - 'post_type' => 'post', - ) - ); - - self::$my_title_page_ids = $factory->post->create_many( - 4, - array( - 'post_title' => 'my-footitle', - 'post_type' => 'page', - ) - ); - - self::$my_content_post_ids = $factory->post->create_many( - 6, - array( - 'post_content' => 'my-foocontent', - ) - ); - } - - /** - * Delete our fake data after our tests run. - */ - public static function wpTearDownAfterClass() { - $post_ids = array_merge( - self::$my_title_post_ids, - self::$my_title_page_ids, - self::$my_content_post_ids - ); - - foreach ( $post_ids as $post_id ) { - wp_delete_post( $post_id, true ); - } - } - - /** - * Check that our routes get set up properly. - */ - public function test_register_routes() { - $routes = rest_get_server()->get_routes(); - - $this->assertArrayHasKey( '/wp/v2/search', $routes ); - $this->assertCount( 1, $routes['/wp/v2/search'] ); - } - - /** - * Check the context parameter. - */ - public function test_context_param() { - $response = $this->do_request_with_params( array(), 'OPTIONS' ); - $data = $response->get_data(); - - $this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] ); - $this->assertEquals( array( 'view', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] ); - } - - /** - * Search through all content. - */ - public function test_get_items() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - array_merge( - self::$my_title_post_ids, - self::$my_title_page_ids, - self::$my_content_post_ids - ), - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through all content with a low limit. - */ - public function test_get_items_with_limit() { - $response = $this->do_request_with_params( - array( - 'per_page' => 3, - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( 3, count( $response->get_data() ) ); - } - - /** - * Search through posts of any post type. - */ - public function test_get_items_search_type_post() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'post', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - array_merge( - self::$my_title_post_ids, - self::$my_title_page_ids, - self::$my_content_post_ids - ), - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through posts of post type 'post'. - */ - public function test_get_items_search_type_post_subtype_post() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'post', - 'subtype' => 'post', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - array_merge( - self::$my_title_post_ids, - self::$my_content_post_ids - ), - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through posts of post type 'page'. - */ - public function test_get_items_search_type_post_subtype_page() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'post', - 'subtype' => 'page', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - self::$my_title_page_ids, - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through an invalid type - */ - public function test_get_items_search_type_invalid() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'invalid', - ) - ); - - $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); - } - - /** - * Search through posts of an invalid post type. - */ - public function test_get_items_search_type_post_subtype_invalid() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'post', - 'subtype' => 'invalid', - ) - ); - - $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); - } - - /** - * Search through posts and pages. - */ - public function test_get_items_search_posts_and_pages() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'type' => 'post', - 'subtype' => 'post,page', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - array_merge( - self::$my_title_post_ids, - self::$my_title_page_ids, - self::$my_content_post_ids - ), - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through all that matches a 'footitle' search. - */ - public function test_get_items_search_for_footitle() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'search' => 'footitle', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - array_merge( - self::$my_title_post_ids, - self::$my_title_page_ids - ), - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Search through all that matches a 'foocontent' search. - */ - public function test_get_items_search_for_foocontent() { - $response = $this->do_request_with_params( - array( - 'per_page' => 100, - 'search' => 'foocontent', - ) - ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEqualSets( - self::$my_content_post_ids, - wp_list_pluck( $response->get_data(), 'id' ) - ); - } - - /** - * Test retrieving a single item isn't possible. - */ - public function test_get_item() { - /** The search controller does not allow getting individual item content */ - $request = new WP_REST_Request( 'GET', '/wp/v2/search' . self::$my_title_post_ids[0] ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 404, $response->get_status() ); - } - - /** - * Test creating an item isn't possible. - */ - public function test_create_item() { - /** The search controller does not allow creating content */ - $request = new WP_REST_Request( 'POST', '/wp/v2/search' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 404, $response->get_status() ); - } - - /** - * Test updating an item isn't possible. - */ - public function test_update_item() { - /** The search controller does not allow upading content */ - $request = new WP_REST_Request( 'POST', '/wp/v2/search' . self::$my_title_post_ids[0] ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 404, $response->get_status() ); - } - - /** - * Test deleting an item isn't possible. - */ - public function test_delete_item() { - /** The search controller does not allow deleting content */ - $request = new WP_REST_Request( 'DELETE', '/wp/v2/search' . self::$my_title_post_ids[0] ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 404, $response->get_status() ); - } - - /** - * Test preparing the data contains the correct fields. - */ - public function test_prepare_item() { - $response = $this->do_request_with_params(); - $this->assertEquals( 200, $response->get_status() ); - - $data = $response->get_data(); - $this->assertEquals( - array( - 'id', - 'title', - 'url', - 'type', - 'subtype', - '_links', - ), - array_keys( $data[0] ) - ); - } - - /** - * Test preparing the data with limited fields contains the correct fields. - */ - public function test_prepare_item_limit_fields() { - if ( ! method_exists( 'WP_REST_Controller', 'get_fields_for_response' ) ) { - $this->markTestSkipped( 'Limiting fields requires the WP_REST_Controller::get_fields_for_response() method.' ); - } - - $response = $this->do_request_with_params( - array( - '_fields' => 'id,title', - ) - ); - $this->assertEquals( 200, $response->get_status() ); - - $data = $response->get_data(); - $this->assertEquals( - array( - 'id', - 'title', - '_links', - ), - array_keys( $data[0] ) - ); - } - - /** - * Tests the item schema is correct. - */ - public function test_get_item_schema() { - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/search' ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - $properties = $data['schema']['properties']; - - $this->assertArrayHasKey( 'id', $properties ); - $this->assertArrayHasKey( 'title', $properties ); - $this->assertArrayHasKey( 'url', $properties ); - $this->assertArrayHasKey( 'type', $properties ); - $this->assertArrayHasKey( 'subtype', $properties ); - } - - /** - * Tests that non-public post types are not allowed. - */ - public function test_non_public_post_type() { - $response = $this->do_request_with_params( - array( - 'type' => 'post', - 'subtype' => 'post,nav_menu_item', - ) - ); - $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); - } - - /** - * Test getting items directly with a custom search handler. - */ - public function test_custom_search_handler_get_items() { - $controller = new WP_REST_Search_Controller( array( new WP_REST_Dummy_Search_Handler( 10 ) ) ); - - $request = $this->get_request( - array( - 'page' => 1, - 'per_page' => 10, - 'type' => 'dummy', - 'subtype' => array( WP_REST_Search_Controller::TYPE_ANY ), - ) - ); - $response = $controller->get_items( $request ); - $this->assertEqualSets( range( 1, 10 ), wp_list_pluck( $response->get_data(), 'id' ) ); - - $request = $this->get_request( - array( - 'page' => 1, - 'per_page' => 10, - 'type' => 'dummy', - 'subtype' => array( 'dummy_first_type' ), - ) - ); - $response = $controller->get_items( $request ); - $this->assertEqualSets( range( 1, 5 ), wp_list_pluck( $response->get_data(), 'id' ) ); - } - - /** - * Test preparing an item directly with a custom search handler. - */ - public function test_custom_search_handler_prepare_item() { - $controller = new WP_REST_Search_Controller( array( new WP_REST_Dummy_Search_Handler( 10 ) ) ); - - $request = $this->get_request( - array( - 'type' => 'dummy', - 'subtype' => array( WP_REST_Search_Controller::TYPE_ANY ), - ) - ); - $response = $controller->prepare_item_for_response( 1, $request ); - $data = $response->get_data(); - $this->assertEquals( - array( - 'id', - 'title', - 'url', - 'type', - 'subtype', - ), - array_keys( $data ) - ); - } - - /** - * Test preparing an item directly with a custom search handler with limited fields. - */ - public function test_custom_search_handler_prepare_item_limit_fields() { - if ( ! method_exists( 'WP_REST_Controller', 'get_fields_for_response' ) ) { - $this->markTestSkipped( 'Limiting fields requires the WP_REST_Controller::get_fields_for_response() method.' ); - } - - $controller = new WP_REST_Search_Controller( array( new WP_REST_Dummy_Search_Handler( 10 ) ) ); - - $request = $this->get_request( - array( - 'type' => 'dummy', - 'subtype' => array( WP_REST_Search_Controller::TYPE_ANY ), - '_fields' => 'id,title', - ) - ); - $response = $controller->prepare_item_for_response( 1, $request ); - $data = $response->get_data(); - $this->assertEquals( - array( - 'id', - 'title', - ), - array_keys( $data ) - ); - } - - /** - * Test getting the collection params directly with a custom search handler. - */ - public function test_custom_search_handler_get_collection_params() { - $controller = new WP_REST_Search_Controller( array( new WP_REST_Dummy_Search_Handler( 10 ) ) ); - - $params = $controller->get_collection_params(); - $this->assertEquals( 'dummy', $params[ WP_REST_Search_Controller::PROP_TYPE ]['default'] ); - $this->assertEqualSets( array( 'dummy' ), $params[ WP_REST_Search_Controller::PROP_TYPE ]['enum'] ); - $this->assertEqualSets( array( 'dummy_first_type', 'dummy_second_type', WP_REST_Search_Controller::TYPE_ANY ), $params[ WP_REST_Search_Controller::PROP_SUBTYPE ]['items']['enum'] ); - } - - /** - * Perform a REST request to our search endpoint with given parameters. - */ - private function do_request_with_params( $params = array(), $method = 'GET' ) { - $request = $this->get_request( $params, $method ); - - return rest_get_server()->dispatch( $request ); - } - - /** - * Get a REST request object for given parameters. - */ - private function get_request( $params = array(), $method = 'GET' ) { - $request = new WP_REST_Request( $method, '/wp/v2/search' ); - - foreach ( $params as $param => $value ) { - $request->set_param( $param, $value ); - } - - return $request; - } -} diff --git a/test/e2e/specs/classic-editor.test.js b/test/e2e/specs/classic-editor.test.js deleted file mode 100644 index 0d51c93e5b342..0000000000000 --- a/test/e2e/specs/classic-editor.test.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Internal dependencies - */ -import { visitAdmin } from '../support/utils'; - -describe( 'classic editor', () => { - beforeAll( async () => { - await visitAdmin( 'post-new.php', 'classic-editor' ); - } ); - - it( 'Should work properly', async () => { - // Click visual editor - await expect( page ).toClick( '#content-tmce' ); - await expect( page ).toClick( '#content_ifr' ); - - // type some random text - await page.keyboard.type( 'Typing in classic editor' ); - - // Switch to HTML mode - await expect( page ).toClick( '#content-html' ); - - const textEditorContent = await page.$eval( '.wp-editor-area', ( element ) => element.value ); - expect( textEditorContent ).toEqual( 'Typing in classic editor' ); - } ); -} ); diff --git a/test/e2e/specs/font-size-picker.test.js b/test/e2e/specs/font-size-picker.test.js index 4a55dd3e0dbc8..42bfe7e17f5a4 100644 --- a/test/e2e/specs/font-size-picker.test.js +++ b/test/e2e/specs/font-size-picker.test.js @@ -5,6 +5,7 @@ import { clickBlockAppender, getEditedPostContent, newPost, + pressTimes, } from '../support/utils'; describe( 'Font Size Picker', () => { @@ -32,7 +33,8 @@ describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph to be made "small"' ); await page.click( '.blocks-font-size .components-range-control__number' ); - await page.keyboard.type( '13' ); + // This should be the "small" font-size of the current theme. + await page.keyboard.type( '19.5' ); // Ensure content matches snapshot. const content = await getEditedPostContent(); @@ -58,7 +60,8 @@ describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using button' ); await page.click( '.blocks-font-size .components-range-control__number' ); - await page.keyboard.type( '13' ); + // This should be the default font-size of the current theme. + await page.keyboard.type( '22' ); // Blur the range control await page.click( '.components-base-control__label' ); @@ -80,9 +83,10 @@ describe( 'Font Size Picker', () => { const changeSizeButton = await page.waitForSelector( '.components-button.is-font-large' ); await changeSizeButton.click(); + // Clear the custom font size input. await page.click( '.blocks-font-size .components-range-control__number' ); - await page.keyboard.press( 'Backspace' ); - await page.keyboard.press( 'Backspace' ); + await pressTimes( 'ArrowRight', 4 ); + await pressTimes( 'Backspace', 4 ); // Ensure content matches snapshot. const content = await getEditedPostContent(); diff --git a/test/e2e/specs/new-post.test.js b/test/e2e/specs/new-post.test.js index da171371330db..44e08f1902f2d 100644 --- a/test/e2e/specs/new-post.test.js +++ b/test/e2e/specs/new-post.test.js @@ -2,12 +2,19 @@ * Internal dependencies */ import { newPost } from '../support/utils'; +import { activatePlugin, deactivatePlugin } from '../support/plugins'; describe( 'new editor state', () => { beforeAll( async () => { + await activatePlugin( 'gutenberg-test-plugin-post-formats-support' ); await newPost(); } ); + afterAll( async () => { + await newPost(); + await deactivatePlugin( 'gutenberg-test-plugin-post-formats-support' ); + } ); + it( 'should show the New Post page in Gutenberg', async () => { expect( page.url() ).toEqual( expect.stringContaining( 'post-new.php' ) ); // Should display the blank title. diff --git a/test/e2e/specs/templates.test.js b/test/e2e/specs/templates.test.js index 9b5d22080e0d4..4d8d16e9ce951 100644 --- a/test/e2e/specs/templates.test.js +++ b/test/e2e/specs/templates.test.js @@ -72,8 +72,14 @@ describe( 'templates', () => { await switchToTestUser(); } - beforeAll( async () => await setPostFormat( 'image' ) ); - afterAll( async () => await setPostFormat( STANDARD_FORMAT_VALUE ) ); + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-plugin-post-formats-support' ); + await setPostFormat( 'image' ); + } ); + afterAll( async () => { + await setPostFormat( STANDARD_FORMAT_VALUE ); + await deactivatePlugin( 'gutenberg-test-plugin-post-formats-support' ); + } ); it( 'should populate new post with default block for format', async () => { await newPost(); diff --git a/test/e2e/specs/writing-flow.test.js b/test/e2e/specs/writing-flow.test.js index bcad1f3d55bb0..7c4197755bab8 100644 --- a/test/e2e/specs/writing-flow.test.js +++ b/test/e2e/specs/writing-flow.test.js @@ -44,6 +44,8 @@ describe( 'adding blocks', () => { // Arrow up in inner blocks should navigate through (1) column wrapper, // (2) text fields. + // We need to arrow up key presses in the paragraph block because it shows up in two lines. + await page.keyboard.press( 'ArrowUp' ); await page.keyboard.press( 'ArrowUp' ); await page.keyboard.press( 'ArrowUp' ); activeElementText = await page.evaluate( () => document.activeElement.textContent ); @@ -53,6 +55,7 @@ describe( 'adding blocks', () => { // columns wrappers before escaping out. let activeElementBlockType; await page.keyboard.press( 'ArrowUp' ); + await page.keyboard.press( 'ArrowUp' ); activeElementBlockType = await page.evaluate( () => ( document.activeElement.getAttribute( 'data-type' ) ) ); diff --git a/test/e2e/support/plugins.js b/test/e2e/support/plugins.js index da9edd3656860..f8d64a7a1ec17 100644 --- a/test/e2e/support/plugins.js +++ b/test/e2e/support/plugins.js @@ -11,7 +11,7 @@ import { visitAdmin, switchToAdminUser, switchToTestUser } from './utils'; */ export async function installPlugin( slug, searchTerm ) { await switchToAdminUser(); - await visitAdmin( 'plugin-install.php?s=' + encodeURIComponent( searchTerm || slug ) + '&tab=search&type=term' ); + await visitAdmin( 'plugin-install.php', 's=' + encodeURIComponent( searchTerm || slug ) + '&tab=search&type=term' ); await page.click( '.install-now[data-slug="' + slug + '"]' ); await page.waitForSelector( '.activate-now[data-slug="' + slug + '"]' ); await switchToTestUser(); diff --git a/test/e2e/test-plugins/post-formats.php b/test/e2e/test-plugins/post-formats.php new file mode 100644 index 0000000000000..b0fdec68947fc --- /dev/null +++ b/test/e2e/test-plugins/post-formats.php @@ -0,0 +1,15 @@ + Date: Mon, 10 Dec 2018 03:17:48 +1100 Subject: [PATCH 12/33] Meta Boxes: Don't hide disabled meta boxes by modifying DOM (#12628) Hiding disabled meta boxes by setting `element.style.display = 'none'` interferes with plugins like ACF which rely on being able to show and hide meta boxes using `$.hide()` and `$.show()`. Hiding the meta box using a new `.edit-post-meta-boxes-area .is-hidden` class ensures that we don't interfere with third party code. --- .../src/components/meta-boxes/meta-box-visibility.js | 11 +++++++++-- .../components/meta-boxes/meta-boxes-area/style.scss | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js b/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js index 31bc0becf225f..970cf26355e6c 100644 --- a/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js +++ b/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js @@ -17,9 +17,16 @@ class MetaBoxVisibility extends Component { updateDOM() { const { id, isVisible } = this.props; + const element = document.getElementById( id ); - if ( element ) { - element.style.display = isVisible ? '' : 'none'; + if ( ! element ) { + return; + } + + if ( isVisible ) { + element.classList.remove( 'is-hidden' ); + } else { + element.classList.add( 'is-hidden' ); } } diff --git a/packages/edit-post/src/components/meta-boxes/meta-boxes-area/style.scss b/packages/edit-post/src/components/meta-boxes/meta-boxes-area/style.scss index f336804fa38de..b86d15952683b 100644 --- a/packages/edit-post/src/components/meta-boxes/meta-boxes-area/style.scss +++ b/packages/edit-post/src/components/meta-boxes/meta-boxes-area/style.scss @@ -75,6 +75,12 @@ right: 20px; z-index: z-index(".edit-post-meta-boxes-area .spinner"); } + + // Hide disabled meta boxes using CSS so that we don't interfere with plugins + // that modify `element.style.display` on the meta box. + .is-hidden { + display: none; + } } .edit-post-meta-boxes-area__clear { From 29cfa83674a663c2ee8bd64372483aefd9ed4bbb Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Sun, 9 Dec 2018 11:21:07 -0500 Subject: [PATCH 13/33] Add a word-wrap style to the facebook embed preview screen (#11890) * Add a word-break style to the facebook embed preview screen to prevent the long embed url from breaking the block boundary * Fix typo and missing space in scss comment --- packages/block-library/src/embed/editor.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-library/src/embed/editor.scss b/packages/block-library/src/embed/editor.scss index 0b79d5b0414be..29cbd9fb932cf 100644 --- a/packages/block-library/src/embed/editor.scss +++ b/packages/block-library/src/embed/editor.scss @@ -25,4 +25,9 @@ font-size: $default-font-size; } } + + // Stops long URLs from breaking out of the no preview available screen + .components-placeholder__error { + word-break: break-word; + } } From 607c46f73804efbb19d47a8d4849dfbaae29b97d Mon Sep 17 00:00:00 2001 From: Alda Vigdis Skarphedinsdottir <191583+aldavigdis@users.noreply.github.com> Date: Sun, 9 Dec 2018 17:26:17 +0100 Subject: [PATCH 14/33] Adding @aldavigdis to the contributors list (#12686) --- CONTRIBUTORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 8f7b5d83932b6..2c58e53ed7685 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -122,3 +122,5 @@ This list is manually curated to include valuable contributions by volunteers th | @sharazghouri | @sharaz | | @jakeparis | @jakeparis | | @designsimply | @designsimply | +| @aldavigdis | @aldavigdis | + From 85d83ad4adae33501463cc31f9bb5c791cb75736 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sun, 9 Dec 2018 11:07:19 -0600 Subject: [PATCH 15/33] Make media & text block placeholder translatable (#12706) --- packages/block-library/src/media-text/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index c1cabf248e57c..9f9b626f837fd 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -7,7 +7,7 @@ import { get } from 'lodash'; /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; import { BlockControls, InnerBlocks, @@ -32,7 +32,7 @@ import MediaContainer from './media-container'; */ const ALLOWED_BLOCKS = [ 'core/button', 'core/paragraph', 'core/heading', 'core/list' ]; const TEMPLATE = [ - [ 'core/paragraph', { fontSize: 'large', placeholder: 'Content…' } ], + [ 'core/paragraph', { fontSize: 'large', placeholder: _x( 'Content…', 'content placeholder' ) } ], ]; class MediaTextEdit extends Component { From 9f6dc6dddde1c9c4f80bcaa79903849fcd266b69 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Sun, 9 Dec 2018 17:19:38 +0000 Subject: [PATCH 16/33] Fix: Problems on Media & Text block resizing; Load wp-block-library styles before wp-edit-blocks. (#12619) --- lib/client-assets.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/client-assets.php b/lib/client-assets.php index 6fa221bf4c5d8..13672f6516bcd 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -461,6 +461,7 @@ function gutenberg_register_scripts_and_styles() { array( 'wp-components', 'wp-editor', + 'wp-block-library', // Always include visual styles so the editor never appears broken. 'wp-block-library-theme', ), From 779a18eb2f08b2c113a54d0162bc88abccb59d7a Mon Sep 17 00:00:00 2001 From: Takayuki Miyauchi Date: Mon, 10 Dec 2018 02:27:41 +0900 Subject: [PATCH 17/33] Get wordcount type from translation (#12586) * get wordcount type from translation * Add description to explain the options for wordcount type * Added mylsef into contributors.md. :) --- CONTRIBUTORS.md | 2 +- packages/editor/src/components/word-count/index.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 2c58e53ed7685..8279df075b66b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -123,4 +123,4 @@ This list is manually curated to include valuable contributions by volunteers th | @jakeparis | @jakeparis | | @designsimply | @designsimply | | @aldavigdis | @aldavigdis | - +| @miya0001 | @miyauchi | diff --git a/packages/editor/src/components/word-count/index.js b/packages/editor/src/components/word-count/index.js index 176435cdc76eb..719351ba32382 100644 --- a/packages/editor/src/components/word-count/index.js +++ b/packages/editor/src/components/word-count/index.js @@ -2,11 +2,19 @@ * WordPress dependencies */ import { withSelect } from '@wordpress/data'; +import { _x } from '@wordpress/i18n'; import { count as wordCount } from '@wordpress/wordcount'; function WordCount( { content } ) { + /* + * translators: If your word count is based on single characters (e.g. East Asian characters), + * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. + * Do not translate into your own language. + */ + const wordCountType = _x( 'words', 'Word count type. Do not translate!' ); + return ( - { wordCount( content, 'words' ) } + { wordCount( content, wordCountType ) } ); } From a12fcec4e77b15b661402dd27d24d0efbe7b6d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sun, 9 Dec 2018 13:04:42 -0600 Subject: [PATCH 18/33] Only render InserterWithShortcuts on hover (#12510) --- .../src/components/default-block-appender/index.js | 14 +++++++++++--- .../test/__snapshots__/index.js.snap | 9 ++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/default-block-appender/index.js b/packages/editor/src/components/default-block-appender/index.js index ecfe98d351a90..d4b95c4d961ba 100644 --- a/packages/editor/src/components/default-block-appender/index.js +++ b/packages/editor/src/components/default-block-appender/index.js @@ -7,7 +7,7 @@ import TextareaAutosize from 'react-autosize-textarea'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { compose } from '@wordpress/compose'; +import { compose, withState } from '@wordpress/compose'; import { getDefaultBlockName } from '@wordpress/blocks'; import { decodeEntities } from '@wordpress/html-entities'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -26,6 +26,8 @@ export function DefaultBlockAppender( { showPrompt, placeholder, rootClientId, + hovered, + setState, } ) { if ( isLocked || ! isVisible ) { return null; @@ -49,7 +51,12 @@ export function DefaultBlockAppender( { // The wp-block className is important for editor styles. return ( -
+
setState( { hovered: true } ) } + onMouseLeave={ () => setState( { hovered: false } ) } + > - + { hovered && }
); } export default compose( + withState( { hovered: false } ), withSelect( ( select, ownProps ) => { const { getBlockCount, getBlockName, isBlockValid, getEditorSettings, getTemplateLock } = select( 'core/editor' ); diff --git a/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap b/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap index df9daeebd54f2..dc26d4405d863 100644 --- a/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap @@ -4,6 +4,8 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
- @@ -33,6 +34,8 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
- @@ -55,6 +57,8 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
- From 42bf37553bf18a23835f686c35d37b222b2ea639 Mon Sep 17 00:00:00 2001 From: Joen Asmussen Date: Sun, 9 Dec 2018 20:11:14 +0100 Subject: [PATCH 19/33] Fix issue where default appender has icons overlaying the text (#12536) * Fix issue where default appender has icons overlaying the text This fixes #11425. It adds padding to the right of the default block appender to fit 3 icons. * chore: Tweak spelling --- packages/block-library/src/paragraph/editor.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/paragraph/editor.scss b/packages/block-library/src/paragraph/editor.scss index 98ea5e4e2b85a..1110e5d5832d4 100644 --- a/packages/block-library/src/paragraph/editor.scss +++ b/packages/block-library/src/paragraph/editor.scss @@ -1,6 +1,11 @@ // Specific to the empty paragraph placeholder: -// when shown on mobile and in nested contexts, the plus to add blocks shows up on the right. +// when shown on mobile and in nested contexts, one or more icons show up on the right. // This padding makes sure it doesn't overlap text. .editor-rich-text__tinymce[data-is-placeholder-visible="true"] + .editor-rich-text__tinymce.wp-block-paragraph { - padding-right: $icon-button-size; + padding-right: $icon-button-size * 3; + + // In nested contexts only one icon shows up. + .wp-block .wp-block & { + padding-right: $icon-button-size; + } } From 2f4317cedafdbff5cf09d6d6726c528dcf6d14ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sun, 9 Dec 2018 13:54:43 -0600 Subject: [PATCH 20/33] Classic Block: set correct focus back after blur (#12415) * Classic Block: set correct focus back after blur * Add e2e test * reset bookmark on mousedown and touchstart * e2e: Look for aria-label="Add Media" rather than "Insert Media" --- packages/block-library/src/classic/edit.js | 14 ++++ .../blocks/__snapshots__/classic.test.js.snap | 3 + test/e2e/specs/blocks/classic.test.js | 73 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 test/e2e/specs/blocks/__snapshots__/classic.test.js.snap create mode 100644 test/e2e/specs/blocks/classic.test.js diff --git a/packages/block-library/src/classic/edit.js b/packages/block-library/src/classic/edit.js index 2502c0f7e0eb5..f0eb37ff30ca9 100644 --- a/packages/block-library/src/classic/edit.js +++ b/packages/block-library/src/classic/edit.js @@ -78,6 +78,7 @@ export default class ClassicEdit extends Component { onSetup( editor ) { const { attributes: { content }, setAttributes } = this.props; const { ref } = this; + let bookmark; this.editor = editor; @@ -86,12 +87,25 @@ export default class ClassicEdit extends Component { } editor.on( 'blur', () => { + bookmark = editor.selection.getBookmark( 2, true ); + setAttributes( { content: editor.getContent(), } ); + + editor.once( 'focus', () => { + if ( bookmark ) { + editor.selection.moveToBookmark( bookmark ); + } + } ); + return false; } ); + editor.on( 'mousedown touchstart', () => { + bookmark = null; + } ); + editor.on( 'keydown', ( event ) => { if ( ( event.keyCode === BACKSPACE || event.keyCode === DELETE ) && isTmceEmpty( editor ) ) { // delete the block diff --git a/test/e2e/specs/blocks/__snapshots__/classic.test.js.snap b/test/e2e/specs/blocks/__snapshots__/classic.test.js.snap new file mode 100644 index 0000000000000..a4461344bb438 --- /dev/null +++ b/test/e2e/specs/blocks/__snapshots__/classic.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Classic should be inserted 1`] = `"test"`; diff --git a/test/e2e/specs/blocks/classic.test.js b/test/e2e/specs/blocks/classic.test.js new file mode 100644 index 0000000000000..f0b733b4a9947 --- /dev/null +++ b/test/e2e/specs/blocks/classic.test.js @@ -0,0 +1,73 @@ +/** + * External dependencies + */ +import path from 'path'; +import fs from 'fs'; +import os from 'os'; +import uuid from 'uuid/v4'; + +/** + * Internal dependencies + */ +import { + getEditedPostContent, + newPost, + insertBlock, + pressWithModifier, +} from '../../support/utils'; + +describe( 'Classic', () => { + beforeEach( async () => { + await newPost(); + } ); + + it( 'should be inserted', async () => { + await insertBlock( 'Classic' ); + // Wait for TinyMCE to initialise. + await page.waitForSelector( '.mce-content-body' ); + // Ensure there is focus. + await page.focus( '.mce-content-body' ); + await page.keyboard.type( 'test' ); + // Move focus away. + await pressWithModifier( 'shift', 'Tab' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'should insert media', async () => { + await insertBlock( 'Classic' ); + // Wait for TinyMCE to initialise. + await page.waitForSelector( '.mce-content-body' ); + // Ensure there is focus. + await page.focus( '.mce-content-body' ); + await page.keyboard.type( 'test' ); + + // Click the image button. + await page.waitForSelector( 'div[aria-label="Add Media"]' ); + await page.click( 'div[aria-label="Add Media"]' ); + + // Wait for media modal to appear and upload image. + await page.waitForSelector( '.media-modal input[type=file]' ); + const inputElement = await page.$( '.media-modal input[type=file]' ); + const testImagePath = path.join( __dirname, '..', '..', 'assets', '10x10_e2e_test_image_z9T8jK.png' ); + const filename = uuid(); + const tmpFileName = path.join( os.tmpdir(), filename + '.png' ); + fs.copyFileSync( testImagePath, tmpFileName ); + await inputElement.uploadFile( tmpFileName ); + + // Wait for upload. + await page.waitForSelector( `.media-modal li[aria-label="${ filename }"]` ); + + // Insert the uploaded image. + await page.click( '.media-modal button.media-button-insert' ); + + // Wait for image to be inserted. + await page.waitForSelector( '.mce-content-body img' ); + + // Move focus away. + await pressWithModifier( 'shift', 'Tab' ); + + const regExp = new RegExp( `test` ); + expect( await getEditedPostContent() ).toMatch( regExp ); + } ); +} ); From f23282bfa292e457ea5cc6d704a76fee99de93d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sun, 9 Dec 2018 14:35:07 -0600 Subject: [PATCH 21/33] RichText: only replace range and nodes if different (#12547) * RichText: only set range if different * Check rangeCount * Also compare nodes * Add e2e test * Simplify * RichText: Document isRangeEqual * Testing: RichText: Assure subscriber removal * Unsubscribe in page.evaluate --- packages/rich-text/src/to-dom.js | 46 +++++++++--- .../__snapshots__/rich-text.test.js.snap | 6 ++ test/e2e/specs/rich-text.test.js | 71 +++++++++++++++++++ 3 files changed, 112 insertions(+), 11 deletions(-) diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 1c34d8680dd2b..c811bbc618059 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -226,21 +226,17 @@ export function apply( { export function applyValue( future, current ) { let i = 0; + let futureChild; - while ( future.firstChild ) { + while ( ( futureChild = future.firstChild ) ) { const currentChild = current.childNodes[ i ]; - const futureNodeType = future.firstChild.nodeType; if ( ! currentChild ) { - current.appendChild( future.firstChild ); - } else if ( - futureNodeType !== currentChild.nodeType || - futureNodeType !== TEXT_NODE || - future.firstChild.nodeValue !== currentChild.nodeValue - ) { - current.replaceChild( future.firstChild, currentChild ); + current.appendChild( futureChild ); + } else if ( ! currentChild.isEqualNode( futureChild ) ) { + current.replaceChild( futureChild, currentChild ); } else { - future.removeChild( future.firstChild ); + future.removeChild( futureChild ); } i++; @@ -251,6 +247,25 @@ export function applyValue( future, current ) { } } +/** + * Returns true if two ranges are equal, or false otherwise. Ranges are + * considered equal if their start and end occur in the same container and + * offset. + * + * @param {Range} a First range object to test. + * @param {Range} b First range object to test. + * + * @return {boolean} Whether the two ranges are equal. + */ +function isRangeEqual( a, b ) { + return ( + a.startContainer === b.startContainer && + a.startOffset === b.startOffset && + a.endContainer === b.endContainer && + a.endOffset === b.endOffset + ); +} + export function applySelection( selection, current ) { const { node: startContainer, offset: startOffset } = getNodeByPath( current, selection.startPath ); const { node: endContainer, offset: endOffset } = getNodeByPath( current, selection.endPath ); @@ -283,6 +298,15 @@ export function applySelection( selection, current ) { range.setEnd( endContainer, endOffset ); } - windowSelection.removeAllRanges(); + if ( windowSelection.rangeCount > 0 ) { + // If the to be added range and the live range are the same, there's no + // need to remove the live range and add the equivalent range. + if ( isRangeEqual( range, windowSelection.getRangeAt( 0 ) ) ) { + return; + } + + windowSelection.removeAllRanges(); + } + windowSelection.addRange( range ); } diff --git a/test/e2e/specs/__snapshots__/rich-text.test.js.snap b/test/e2e/specs/__snapshots__/rich-text.test.js.snap index e911f407edd68..275080b436f2d 100644 --- a/test/e2e/specs/__snapshots__/rich-text.test.js.snap +++ b/test/e2e/specs/__snapshots__/rich-text.test.js.snap @@ -24,6 +24,12 @@ exports[`RichText should handle change in tag name gracefully 1`] = ` " `; +exports[`RichText should only mutate text data on input 1`] = ` +" +

1234

+" +`; + exports[`RichText should transform backtick to code 1`] = ` "

A backtick

diff --git a/test/e2e/specs/rich-text.test.js b/test/e2e/specs/rich-text.test.js index dca248c828931..2f1012766444f 100644 --- a/test/e2e/specs/rich-text.test.js +++ b/test/e2e/specs/rich-text.test.js @@ -67,4 +67,75 @@ describe( 'RichText', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); + + it( 'should only mutate text data on input', async () => { + await clickBlockAppender(); + await page.keyboard.type( '1' ); + await pressWithModifier( 'primary', 'b' ); + await page.keyboard.type( '2' ); + await pressWithModifier( 'primary', 'b' ); + await page.keyboard.type( '3' ); + + await page.evaluate( () => { + let called; + const { body } = document; + const config = { + attributes: true, + childList: true, + characterData: true, + subtree: true, + }; + + const mutationObserver = new MutationObserver( ( records ) => { + if ( called || records.length > 1 ) { + throw new Error( 'Typing should only mutate once.' ); + } + + records.forEach( ( record ) => { + if ( record.type !== 'characterData' ) { + throw new Error( + `Typing mutated more than character data: ${ record.type }` + ); + } + } ); + + called = true; + } ); + + mutationObserver.observe( body, config ); + + window.unsubscribes = [ () => mutationObserver.disconnect() ]; + + document.addEventListener( 'selectionchange', () => { + function throwMultipleSelectionChange() { + throw new Error( 'Typing should only emit one selection change event.' ); + } + + document.addEventListener( + 'selectionchange', + throwMultipleSelectionChange, + { once: true } + ); + + window.unsubscribes.push( () => { + document.removeEventListener( 'selectionchange', throwMultipleSelectionChange ); + } ); + }, { once: true } ); + } ); + + await page.keyboard.type( '4' ); + + await page.evaluate( () => { + // The selection change event should be called once. If there's only + // one item in `window.unsubscribes`, it means that only one + // function is present to disconnect the `mutationObserver`. + if ( window.unsubscribes.length === 1 ) { + throw new Error( 'The selection change event listener was never called.' ); + } + + window.unsubscribes.forEach( ( unsubscribe ) => unsubscribe() ); + } ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); } ); From c63bb7d5836132a743a47302106e88d0b0a8ac51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20=28Greg=29=20Zi=C3=B3=C5=82kowski?= Date: Sun, 9 Dec 2018 14:59:48 -0600 Subject: [PATCH 22/33] Mark temporary eslint-config package as private (#12734) --- packages/eslint-config/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 07a609d7278fa..8d5c6c93c35ee 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,5 +1,6 @@ { "name": "@wordpress/eslint-config", + "private": true, "version": "1.0.0-alpha.0", "description": "ESLint config for WordPress development.", "author": "The WordPress Contributors", From 4ea5094b4b24c65bc2783fddd6c4e53409f6749c Mon Sep 17 00:00:00 2001 From: Jason Coleman <33220397+ideadude@users.noreply.github.com> Date: Sun, 9 Dec 2018 15:03:21 -0600 Subject: [PATCH 23/33] When a post is saved, check for tinymce and save any editors. (#12568) * When a post is saved, check for tinymce and save any editors. * Importing tinymce and using tinyMCE vs the object stored in window.tinymce. * Updated version number and changelog. * no longer importing tinymce since we use the tinyMCE global. tinyMCE.triggerSave works now. checking if tinyMCE exists before making the call just in case. * Using typeof to check for tinyMCE and fixed issues brought up in travis run. * using window.tinyMCE again to avoid warning RE undefined var * Restore the package.json version. * Add e2e tests for the custom wp_editor metaboxes --- packages/edit-post/CHANGELOG.md | 5 +++ packages/edit-post/src/store/effects.js | 5 +++ .../wp-editor-meta-box.test.js.snap | 3 ++ test/e2e/specs/wp-editor-meta-box.test.js | 38 +++++++++++++++++++ test/e2e/test-plugins/wp-editor-metabox.php | 27 +++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 test/e2e/specs/__snapshots__/wp-editor-meta-box.test.js.snap create mode 100644 test/e2e/specs/wp-editor-meta-box.test.js create mode 100644 test/e2e/test-plugins/wp-editor-metabox.php diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 3fdf099954c98..e4b0c1ad32c68 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.1.5 (Unreleased) + +### Bug Fixes + - Fix saving WYSIWYG Meta Boxes + ## 3.1.4 (2018-11-30) ## 3.1.3 (2018-11-30) diff --git a/packages/edit-post/src/store/effects.js b/packages/edit-post/src/store/effects.js index 699b08f0636ed..70ebd8cbb5305 100644 --- a/packages/edit-post/src/store/effects.js +++ b/packages/edit-post/src/store/effects.js @@ -72,6 +72,11 @@ const effects = { } ); }, REQUEST_META_BOX_UPDATES( action, store ) { + // Saves the wp_editor fields + if ( window.tinyMCE ) { + window.tinyMCE.triggerSave(); + } + const state = store.getState(); // Additional data needed for backwards compatibility. diff --git a/test/e2e/specs/__snapshots__/wp-editor-meta-box.test.js.snap b/test/e2e/specs/__snapshots__/wp-editor-meta-box.test.js.snap new file mode 100644 index 0000000000000..485862873b648 --- /dev/null +++ b/test/e2e/specs/__snapshots__/wp-editor-meta-box.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`WP Editor Meta Boxes Should save the changes 1`] = `"

Typing in a metabox

"`; diff --git a/test/e2e/specs/wp-editor-meta-box.test.js b/test/e2e/specs/wp-editor-meta-box.test.js new file mode 100644 index 0000000000000..496057bb55c1c --- /dev/null +++ b/test/e2e/specs/wp-editor-meta-box.test.js @@ -0,0 +1,38 @@ +/** + * Internal dependencies + */ +import { newPost, publishPost } from '../support/utils'; +import { activatePlugin, deactivatePlugin } from '../support/plugins'; + +describe( 'WP Editor Meta Boxes', () => { + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-plugin-wp-editor-meta-box' ); + await newPost(); + } ); + + afterAll( async () => { + await deactivatePlugin( 'gutenberg-test-plugin-wp-editor-meta-box' ); + } ); + + it( 'Should save the changes', async () => { + // Add title to enable valid non-empty post save. + await page.type( '.editor-post-title__input', 'Hello Meta' ); + + // Type something + await page.click( '#test_tinymce_id-html' ); + await page.type( '#test_tinymce_id', 'Typing in a metabox' ); + await page.click( '#test_tinymce_id-tmce' ); + + await publishPost(); + + await page.reload(); + + await page.click( '#test_tinymce_id-html' ); + const content = await page.$eval( + '#test_tinymce_id', + ( textarea ) => textarea.value + ); + + expect( content ).toMatchSnapshot(); + } ); +} ); diff --git a/test/e2e/test-plugins/wp-editor-metabox.php b/test/e2e/test-plugins/wp-editor-metabox.php new file mode 100644 index 0000000000000..088fd2ee6e87a --- /dev/null +++ b/test/e2e/test-plugins/wp-editor-metabox.php @@ -0,0 +1,27 @@ +ID, 'test_tinymce', true ); + wp_editor( $field_value, 'test_tinymce_id', array( + 'wpautop' => true, + 'media_buttons' => false, + 'textarea_name' => 'test_tinymce', + 'textarea_rows' => 10, + 'teeny' => true + ) ); + }, null, 'advanced', 'high' ); +}); +add_action( 'save_post', function( $post_id ){ + if ( ! isset( $_POST['test_tinymce'] ) ) { + return; + } + update_post_meta( $post_id, 'test_tinymce', $_POST['test_tinymce'] ); +}); From 4bb3b0cf79e7aca2bd1724ab2aa13142919d1e70 Mon Sep 17 00:00:00 2001 From: Marcus Kazmierczak Date: Sun, 9 Dec 2018 13:05:04 -0800 Subject: [PATCH 24/33] Rename functions, removing gutenberg_ prefix (#12326) * Rename functions, removing gutenberg_ and prefixing with wp_ * Remove wp_ prefix to match core * Remove function check per review --- lib/load.php | 5 +- .../src/latest-comments/index.php | 58 +++++++++---------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/lib/load.php b/lib/load.php index ee1c973f99568..0c55db3a37f6c 100644 --- a/lib/load.php +++ b/lib/load.php @@ -62,10 +62,7 @@ if ( ! function_exists( 'render_block_core_categories' ) ) { require dirname( __FILE__ ) . '/../packages/block-library/src/categories/index.php'; } -// Currently merged in core as `gutenberg_render_block_core_latest_comments`, -// expected to change soon. -if ( ! function_exists( 'render_block_core_latest_comments' ) - && ! function_exists( 'gutenberg_render_block_core_latest_comments' ) ) { +if ( ! function_exists( 'render_block_core_latest_comments' ) ) { require dirname( __FILE__ ) . '/../packages/block-library/src/latest-comments/index.php'; } if ( ! function_exists( 'render_block_core_latest_posts' ) ) { diff --git a/packages/block-library/src/latest-comments/index.php b/packages/block-library/src/latest-comments/index.php index 29e17e9de5008..fcc17c3cd6a00 100644 --- a/packages/block-library/src/latest-comments/index.php +++ b/packages/block-library/src/latest-comments/index.php @@ -5,34 +5,32 @@ * @package WordPress */ -if ( ! function_exists( 'gutenberg_draft_or_post_title' ) ) { - /** - * Get the post title. - * - * The post title is fetched and if it is blank then a default string is - * returned. - * - * Copied from `wp-admin/includes/template.php`, but we can't include that - * file because: - * - * 1. It causes bugs with test fixture generation and strange Docker 255 error - * codes. - * 2. It's in the admin; ideally we *shouldn't* be including files from the - * admin for a block's output. It's a very small/simple function as well, - * so duplicating it isn't too terrible. - * - * @since 3.3.0 - * - * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. - * @return string The post title if set; "(no title)" if no title is set. - */ - function gutenberg_draft_or_post_title( $post = 0 ) { - $title = get_the_title( $post ); - if ( empty( $title ) ) { - $title = __( '(no title)' ); - } - return esc_html( $title ); +/** + * Get the post title. + * + * The post title is fetched and if it is blank then a default string is + * returned. + * + * Copied from `wp-admin/includes/template.php`, but we can't include that + * file because: + * + * 1. It causes bugs with test fixture generation and strange Docker 255 error + * codes. + * 2. It's in the admin; ideally we *shouldn't* be including files from the + * admin for a block's output. It's a very small/simple function as well, + * so duplicating it isn't too terrible. + * + * @since 3.3.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string The post title if set; "(no title)" if no title is set. + */ +function wp_latest_comments_draft_or_post_title( $post = 0 ) { + $title = get_the_title( $post ); + if ( empty( $title ) ) { + $title = __( '(no title)' ); } + return esc_html( $title ); } /** @@ -42,7 +40,7 @@ function gutenberg_draft_or_post_title( $post = 0 ) { * * @return string Returns the post content with latest comments added. */ -function gutenberg_render_block_core_latest_comments( $attributes = array() ) { +function render_block_core_latest_comments( $attributes = array() ) { // This filter is documented in wp-includes/widgets/class-wp-widget-recent-comments.php. $comments = get_comments( apply_filters( @@ -94,7 +92,7 @@ function gutenberg_render_block_core_latest_comments( $attributes = array() ) { // `_draft_or_post_title` calls `esc_html()` so we don't need to wrap that call in // `esc_html`. - $post_title = '' . gutenberg_draft_or_post_title( $comment->comment_post_ID ) . ''; + $post_title = '' . wp_latest_comments_draft_or_post_title( $comment->comment_post_ID ) . ''; $list_items_markup .= sprintf( /* translators: 1: author name (inside or tag, based on if they have a URL), 2: post title related to this comment */ @@ -179,6 +177,6 @@ function gutenberg_render_block_core_latest_comments( $attributes = array() ) { 'enum' => array( 'center', 'left', 'right', 'wide', 'full', '' ), ), ), - 'render_callback' => 'gutenberg_render_block_core_latest_comments', + 'render_callback' => 'render_block_core_latest_comments', ) ); From e7fb179e41710df72a57e681c8dab4aea63c42a0 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Sun, 9 Dec 2018 16:22:03 -0600 Subject: [PATCH 25/33] Annotations: Apply annotation className as string (#12741) --- packages/annotations/src/block/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/annotations/src/block/index.js b/packages/annotations/src/block/index.js index 5095fc473d67e..e2677bbf6a9b3 100644 --- a/packages/annotations/src/block/index.js +++ b/packages/annotations/src/block/index.js @@ -17,7 +17,7 @@ const addAnnotationClassName = ( OriginalComponent ) => { return { className: annotations.map( ( annotation ) => { return 'is-annotated-by-' + annotation.source; - } ), + } ).join( ' ' ), }; } )( OriginalComponent ); }; From b44a2f114e99b6f6f774f9b1cb0be781d9a4d569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20Van=C2=A0Dorpe?= Date: Sun, 9 Dec 2018 17:47:53 -0600 Subject: [PATCH 26/33] RichText: Ensure instance is selected before setting back selection (#12737) --- packages/editor/src/components/rich-text/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/rich-text/index.js b/packages/editor/src/components/rich-text/index.js index de0e7dd5aa363..0731916d6a1a7 100644 --- a/packages/editor/src/components/rich-text/index.js +++ b/packages/editor/src/components/rich-text/index.js @@ -688,9 +688,12 @@ export class RichText extends Component { if ( shouldReapply ) { const record = this.formatToValue( value ); - // Maintain the previous selection: - record.start = this.state.start; - record.end = this.state.end; + // Maintain the previous selection if the instance is currently + // selected. + if ( isSelected ) { + record.start = this.state.start; + record.end = this.state.end; + } this.applyRecord( record ); } From 47736a4d25a7d69d83389ec1521458a57011907a Mon Sep 17 00:00:00 2001 From: Saleeh Date: Sun, 9 Dec 2018 21:13:29 -0600 Subject: [PATCH 27/33] Fix for #11663 (#12728) * Fixed Deleting an HTML Anchor attribute leaves an empty HTML id attribute * Fixed Deleting an HTML Anchor attribute leaves an empty --- packages/editor/src/hooks/anchor.js | 2 +- packages/editor/src/hooks/test/anchor.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/hooks/anchor.js b/packages/editor/src/hooks/anchor.js index 66b1c4f01eef4..3af32e39ef2ac 100644 --- a/packages/editor/src/hooks/anchor.js +++ b/packages/editor/src/hooks/anchor.js @@ -98,7 +98,7 @@ export const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => */ export function addSaveProps( extraProps, blockType, attributes ) { if ( hasBlockSupport( blockType, 'anchor' ) ) { - extraProps.id = attributes.anchor; + extraProps.id = attributes.anchor === '' ? null : attributes.anchor; } return extraProps; diff --git a/packages/editor/src/hooks/test/anchor.js b/packages/editor/src/hooks/test/anchor.js index 74bfa2e20dfc2..21a5c65be83cb 100644 --- a/packages/editor/src/hooks/test/anchor.js +++ b/packages/editor/src/hooks/test/anchor.js @@ -62,5 +62,17 @@ describe( 'anchor', () => { expect( extraProps.id ).toBe( 'foo' ); } ); + + it( 'should remove an anchor attribute ID when feild is cleared', () => { + const attributes = { anchor: '' }; + const extraProps = getSaveContentExtraProps( {}, { + ...blockSettings, + supports: { + anchor: true, + }, + }, attributes ); + + expect( extraProps.id ).toBe( null ); + } ); } ); } ); From 8a5486d748160772c10763fcd13ca4fa58ec200c Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Mon, 10 Dec 2018 17:06:21 +1100 Subject: [PATCH 28/33] Update plugin version to 4.7.0-rc.1 (#12752) --- gutenberg.php | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 2f75a595903e7..9f9d7b183aeb5 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the new block editor in core. - * Version: 4.6.1 + * Version: 4.7.0-rc.1 * Author: Gutenberg Team * * @package gutenberg diff --git a/package-lock.json b/package-lock.json index df6980879a342..8ced31ee5d85a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "4.6.1", + "version": "4.7.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 541ebbfa9df50..7351c13255f05 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "4.6.1", + "version": "4.7.0-rc.1", "private": true, "description": "A new WordPress editor experience", "repository": "git+https://github.com/WordPress/gutenberg.git", From b6949b9169f92ad71b32f320119c28a61894fb71 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Mon, 10 Dec 2018 02:15:40 -0500 Subject: [PATCH 29/33] Add an error state to the image block to allow upload errors to display (#10224) --- packages/block-library/src/image/edit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 551e3dadda255..f7fdd73a9aaa5 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -121,7 +121,7 @@ class ImageEdit extends Component { } componentDidMount() { - const { attributes, setAttributes } = this.props; + const { attributes, setAttributes, noticeOperations } = this.props; const { id, url = '' } = attributes; if ( isTemporaryImage( id, url ) ) { @@ -134,6 +134,10 @@ class ImageEdit extends Component { setAttributes( pickRelevantMediaFiles( image ) ); }, allowedTypes: ALLOWED_MEDIA_TYPES, + onError: ( message ) => { + noticeOperations.createErrorNotice( message ); + this.setState( { isEditing: true } ); + }, } ); } } From 40d1282a992702e1933118ef626f0666692baf2b Mon Sep 17 00:00:00 2001 From: Joen Asmussen Date: Mon, 10 Dec 2018 08:26:23 +0100 Subject: [PATCH 30/33] Try: JS Console warning for when in Quirks Mode (#12575) * Try: JS Console warning for when in Quirks Mode This PR detects whether the browser is in Quirks Mode. Quirks Mode is a rendering method used when the doctype definition is missing or incorrectly placed in the HTML source, causing the browser to have difficulty detecting the type of document it is to render. This is usually caused by a PHP error, or even just a style tag that is output incorrectly on the page. See discussion in https://github.com/WordPress/gutenberg/pull/12455 and https://github.com/WordPress/gutenberg/issues/11378. The usual result is Gutenberg rendering incorrectly, notably with metaboxes overlapping content. The purpose of this PR is to help developers debug the issue and fix it at the root. As such, it adds a console warning, props @nickcernis for the text: ``` [Warning] Your browser is using Quirks Mode. This can cause rendering issues such as blocks overlaying meta boxes in the editor. Quirks Mode can be triggered by PHP errors or HTML code appearing before the opening . Try checking the raw page source or your site's PHP error log and resolving errors there, removing any HTML before the doctype, or disabling plugins. ``` It also augments the documentation to add a note about this. * Move warning to index.js * Remove try/catch. * Tweak: Remove redundant [warning] in warn call --- .../developers/backwards-compatibility/meta-box.md | 2 ++ packages/edit-post/src/index.js | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/docs/designers-developers/developers/backwards-compatibility/meta-box.md b/docs/designers-developers/developers/backwards-compatibility/meta-box.md index eb96bfc38e0ff..2f28f48ed77cb 100644 --- a/docs/designers-developers/developers/backwards-compatibility/meta-box.md +++ b/docs/designers-developers/developers/backwards-compatibility/meta-box.md @@ -82,3 +82,5 @@ Most PHP meta boxes should continue to work in Gutenberg, but some meta boxes th - Plugins relying on selectors that target the post title, post content fields, and other metaboxes (of the old editor). - Plugins relying on TinyMCE's API because there's no longer a single TinyMCE instance to talk to in Gutenberg. - Plugins making updates to their DOM on "submit" or on "save". + +Please also note that if your plugin triggers a PHP warning or notice to be output on the page, this will cause the HTML document type (``) to be output incorrectly. This will cause the browser to render using "Quirks Mode", which is a compatibility layer that gets enabled when the browser doesn't know what type of document it is parsing. The block editor is not meant to work in this mode, but it can _appear_ to be working just fine. If you encounter issues such as *meta boxes overlaying the editor* or other layout issues, please check the raw page source of your document to see that the document type definition is the first thing output on the page. There will also be a warning in the JavaScript console, noting the issue. diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index bce8285f72b0b..59e870e7929da 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -68,6 +68,13 @@ export function initializeEditor( id, postType, postId, settings, initialEdits ) registerCoreBlocks(); + // Show a console log warning if the browser is not in Standards rendering mode. + const documentMode = document.compatMode === 'CSS1Compat' ? 'Standards' : 'Quirks'; + if ( documentMode !== 'Standards' ) { + // eslint-disable-next-line no-console + console.warn( "Your browser is using Quirks Mode. \nThis can cause rendering issues such as blocks overlaying meta boxes in the editor. Quirks Mode can be triggered by PHP errors or HTML code appearing before the opening . Try checking the raw page source or your site's PHP error log and resolving errors there, removing any HTML before the doctype, or disabling plugins." ); + } + dispatch( 'core/nux' ).triggerGuide( [ 'core/editor.inserter', 'core/editor.settings', From b7e343d892fbcbe471e0438de64c3b9b373a44b0 Mon Sep 17 00:00:00 2001 From: Terri Ann Date: Mon, 10 Dec 2018 09:48:41 -0600 Subject: [PATCH 31/33] Organizing screenshot assets for the block tutorial inside the designers-developers directory in the repo (#12745) --- .../block-tutorial => assets}/inspector.png | Bin .../assets/toolbar-text.png | Bin 0 -> 22683 bytes .../block-controls-toolbars-and-inspector.md | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename docs/designers-developers/{developers/tutorials/block-tutorial => assets}/inspector.png (100%) create mode 100644 docs/designers-developers/assets/toolbar-text.png diff --git a/docs/designers-developers/developers/tutorials/block-tutorial/inspector.png b/docs/designers-developers/assets/inspector.png similarity index 100% rename from docs/designers-developers/developers/tutorials/block-tutorial/inspector.png rename to docs/designers-developers/assets/inspector.png diff --git a/docs/designers-developers/assets/toolbar-text.png b/docs/designers-developers/assets/toolbar-text.png new file mode 100644 index 0000000000000000000000000000000000000000..76b18c6b8f368f3abd5d2559e5a6f71c75913ed4 GIT binary patch literal 22683 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 +![Screenshot of the rich text toolbar applied to a paragraph block inside the block editor](https://raw.githubusercontent.com/WordPress/gutenberg/master/docs/designers-developers/assets/toolbar-text.png) When the user selects a block, a number of control buttons may be shown in a toolbar above the selected block. Some of these block-level controls are included automatically if the editor is able to transform the block to another type, or if the focused element is an RichText component. @@ -171,7 +171,7 @@ Note that `BlockControls` is only visible when the block is currently selected a ## Inspector -inspector +![Screenshot of the inspector panel focused on the settings for a paragraph block](https://raw.githubusercontent.com/WordPress/gutenberg/master/docs/designers-developers/assets/inspector.png) The inspector is used to display less-often-used settings or settings that require more screen space. The inspector should be used for **block-level settings only**. From 8790bce7ae56191d00fe7384ea1832df10624961 Mon Sep 17 00:00:00 2001 From: Marcus Kazmierczak Date: Mon, 10 Dec 2018 12:55:19 -0800 Subject: [PATCH 32/33] Rename backwards compatiblity to backward compatibility (#12751) * Rename backwards compatiblity to backward compatibility * Remove package-lock from commit * Update CONTRIBUTING.md Co-Authored-By: mkaz * Update CONTRIBUTING.md Co-Authored-By: mkaz * Whitespace in manifest --- CONTRIBUTING.md | 6 +++--- README.md | 4 ++-- docs/designers-developers/developers/README.md | 2 +- .../developers/backward-compatibility/README.md | 1 + .../deprecations.md | 2 +- .../meta-box.md | 6 +++--- .../developers/backwards-compatibility/README.md | 1 - docs/manifest.json | 14 +++++++------- docs/toc.json | 6 +++--- lib/client-assets.php | 2 +- .../components/src/server-side-render/README.md | 4 ++-- packages/edit-post/src/store/effects.js | 2 +- 12 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 docs/designers-developers/developers/backward-compatibility/README.md rename docs/designers-developers/developers/{backwards-compatibility => backward-compatibility}/deprecations.md (97%) rename docs/designers-developers/developers/{backwards-compatibility => backward-compatibility}/meta-box.md (95%) delete mode 100644 docs/designers-developers/developers/backwards-compatibility/README.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ccb59aa2df44..e9a47c7322e47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -166,9 +166,9 @@ Maintaining dozens of npm packages is difficult—it can be tough to keep track The developer who proposes a change (pull request) is responsible to choose the correct version increment (`major`, `minor`, or `patch`) according to the following guidelines: -- Major version X (X.y.z | X > 0) should be changed with any backwards-incompatible/"breaking" change. This will usually occur at the final stage of deprecating and removing of a feature. -- Minor version Y (x.Y.z | x > 0) should be changed when you add functionality or change functionality in a backwards-compatible manner. It must be incremented if any public API functionality is marked as deprecated. -- Patch version Z (x.y.Z | x > 0) should be incremented when you make backwards-compatible bug fixes. +- Major version X (X.y.z | X > 0) should be changed with any backward incompatible/"breaking" change. This will usually occur at the final stage of deprecating and removing of a feature. +- Minor version Y (x.Y.z | x > 0) should be changed when you add functionality or change functionality in a backward compatible manner. It must be incremented if any public API functionality is marked as deprecated. +- Patch version Z (x.y.Z | x > 0) should be incremented when you make backward compatible bug fixes. When in doubt, refer to [Semantic Versioning specification](https://semver.org/). diff --git a/README.md b/README.md index 03251ceba2160..855958ef9635e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This repo is the development hub for the editor focus in WordPress Core. `Gutenberg` is the project name. ## Getting started -- **Download:** If you want to use the latest release with your WordPress site, download the latest release from the WordPress.org plugins repository. +- **Download:** If you want to use the latest release with your WordPress site, download the latest release from the WordPress.org plugins repository. - **Discuss:** Conversations and discussions take place in `#core-editor` channel on the Making WordPress Slack. - **Contribute:** Development of Gutenberg happens in this GitHub repo. Get started by reading the contributing guidelines. - **Learn:** Discover more about the project on WordPress.org. @@ -44,7 +44,7 @@ Check out the ( block="core/archives" attributes={ { showPostCounts: true, - displayAsDropdown: false, + displayAsDropdown: false, } } /> ); diff --git a/packages/edit-post/src/store/effects.js b/packages/edit-post/src/store/effects.js index 70ebd8cbb5305..a177c36c1b761 100644 --- a/packages/edit-post/src/store/effects.js +++ b/packages/edit-post/src/store/effects.js @@ -79,7 +79,7 @@ const effects = { const state = store.getState(); - // Additional data needed for backwards compatibility. + // Additional data needed for backward compatibility. // If we do not provide this data, the post will be overridden with the default values. const post = select( 'core/editor' ).getCurrentPost( state ); const additionalData = [ From 1a1dc7c15f556a5298c2549e219fdc79fb951304 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 11 Dec 2018 03:21:35 -0600 Subject: [PATCH 33/33] Update node-sass to 4.11.0 to support Node.js 11 (#12541) ## Description Fixes #12539 by updating node-sass to support Node.js 11. ## How has this been tested? Running `npm install` on macOS 10.14 with Node.js 11.2 without problems. ## Types of changes Minor dependency bump to support Node.js 11. ## Checklist: - [x] My code is tested. - [x] My code follows the WordPress code style. - [x] My code follows the accessibility standards. - [x] My code has proper inline documentation. --- package-lock.json | 158 +++++++++++++++++++++++++++++++++------------- package.json | 2 +- 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ced31ee5d85a..347cbcd533748 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15030,9 +15030,9 @@ } }, "node-sass": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz", - "integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", + "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -15048,14 +15048,26 @@ "meow": "^3.7.0", "mkdirp": "^0.5.1", "nan": "^2.10.0", - "node-gyp": "^3.3.1", + "node-gyp": "^3.8.0", "npmlog": "^4.0.0", - "request": "2.87.0", + "request": "^2.88.0", "sass-graph": "^2.2.4", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" }, "dependencies": { + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -15068,6 +15080,12 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -15076,7 +15094,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { @@ -15086,7 +15104,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -15107,6 +15125,28 @@ "which": "^1.2.9" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -15116,15 +15156,11 @@ "repeating": "^2.0.0" } }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "map-obj": { "version": "1.0.1", @@ -15134,7 +15170,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { @@ -15150,12 +15186,33 @@ "trim-newlines": "^1.0.0" } }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -15166,9 +15223,37 @@ "strip-indent": "^1.0.1" } }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -18883,7 +18968,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { @@ -18903,7 +18988,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -19038,7 +19123,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -19674,9 +19759,9 @@ "dev": true }, "stdout-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", - "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", "dev": true, "requires": { "readable-stream": "^2.0.1" @@ -20723,27 +20808,12 @@ "dev": true }, "true-case-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", - "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", "dev": true, "requires": { - "glob": "^6.0.4" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } + "glob": "^7.1.2" } }, "tryer": { diff --git a/package.json b/package.json index 7351c13255f05..432662628f9e2 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "lint-staged": "7.2.0", "lodash": "4.17.10", "mkdirp": "0.5.1", - "node-sass": "4.9.2", + "node-sass": "4.11.0", "path-type": "3.0.0", "pegjs": "0.10.0", "phpegjs": "1.0.0-beta7",