diff --git a/.gitignore b/.gitignore index 283066ff44c040..9d58efe7906a66 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ gutenberg.pot yarn.lock gutenberg.zip storybook-static +.DS_Store diff --git a/.storybook/config.js b/.storybook/config.js index b8cdf2a2bee922..35d9b93b2b2988 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -17,6 +17,7 @@ function loadStories() { require( './stories/intro' ); require( './stories/contributing' ); require( './stories/coding-guidelines' ); + require( './stories/design' ); require( '../i18n/story' ); require( '../element/story' ); require( '../blocks/story' ); diff --git a/.storybook/stories/design.js b/.storybook/stories/design.js new file mode 100644 index 00000000000000..c2224d84af8c36 --- /dev/null +++ b/.storybook/stories/design.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import ReactMarkdown from 'react-markdown'; +import { storiesOf } from '@storybook/react'; +import { withKnobs } from '@storybook/addon-knobs'; + +/** + * Internal dependencies + */ +import readme from '../../docs/design.md'; + +storiesOf( 'Gutenberg', module ) + .addDecorator( withKnobs ) + .add( 'Design', () => ); diff --git a/.travis.yml b/.travis.yml index 9861d4b2e3d6d6..4e162f598ffcda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,8 +50,22 @@ before_script: script: - | if [[ ! -z "$WP_VERSION" ]] ; then + # Run the build because otherwise there will be a bunch of warnings about + # failed `stat` calls from `filemtime()`. npm install || exit 1 npm run build || exit 1 + # Make sure phpegjs parser is up to date + node bin/create-php-parser.js || exit 1 + if ! git diff --quiet --exit-code lib/parser.php; then + echo 'ERROR: The PEG parser has been updated, but the generated PHP version' + echo ' (lib/parser.php) has not. Run `bin/create-php-parser.js` and' + echo ' commit the resulting changes to resolve this.' + sleep .2 # Otherwise Travis doesn't want to print the whole message + exit 1 + fi + # Check parser syntax + php lib/parser.php || exit 1 + # Run PHPUnit tests phpunit || exit 1 WP_MULTISITE=1 phpunit || exit 1 fi diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 00000000000000..2130a5835b329e --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,70 @@ +# Contributors + +Gutenberg is built by many contributors and volunteers. Thanks to all of them for their work! + +This list is manually curated to include valuable contributions by volunteers that do not include code, such as user testing, providing feedback, or mockups. Please edit this list to include new contributors as they come in. There is no particular order to this list. If you or someone else were omitted from this list, we assure you that was not intentional. Please let us know and we'll add you. + +- @youknowriad +- @aduth +- @jasmussen +- @iseulde +- @mtias +- @nylen +- @EphoxJames +- @mkaz +- @notnownikki +- @BE-Webdesign +- @njpanderson +- @mimo84 +- @intronic +- @westonruter +- @mcsf +- @dmsnell +- @afercia +- @paulwilde +- @mitogh +- @codebykat +- @ahmadawais +- @kopepasah +- @circlecube +- @adamsilverstein +- @timmyc +- @ephox-mogran +- @nb +- @JDGrimes +- @Soean +- @mapk +- @sirjonathan +- @j-falk +- @ryelle +- @ntwb +- @lamosty +- @willybahuaud +- @maurobringolf +- @aaronjorbin +- @spocke +- @androb +- @annaephox +- @Afraithe +- @georgeh +- @m +- @melchoyce +- @pento +- @karmatosed +- @nitrajka +- @sirreal +- @inhil +- @georgeolaru +- @martinlugton +- @joyously +- @rileybrook +- @azaozz +- @folletto +- @ianstewart +- @johnpixle +- @mrwweb +- @diegoliv +- @lukecav +- @shaunandrews +- @hugobaeta +- @mizejewski diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000000000..34301d8f2ced40 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,400 @@ +### WordPress - Web publishing software + + Copyright 2011-2017 by the contributors + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +This program incorporates work covered by the following copyright and +permission notices: + + b2 is (c) 2001, 2002 Michel Valdrighi - m@tidakada.com - + http://tidakada.com + + Wherever third party code has been used, credit has been given in the code's + comments. + + b2 is released under the GPL + +and + + WordPress - Web publishing software + + Copyright 2003-2010 by the contributors + + WordPress is released under the GPL + +--- + +### GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +### Preamble + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, +we want its recipients to know that what they have is not the +original, so that any problems introduced by others will not reflect +on the original authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at +all. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work +based on the Program" means either the Program or any derivative work +under copyright law: that is to say, a work containing the Program or +a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is +included without limitation in the term "modification".) Each licensee +is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the Program +(independent of having been made by running the Program). Whether that +is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a +fee. + +**2.** You may modify your copy or copies of the Program or any +portion of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + +**a)** You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + + +**b)** You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any part +thereof, to be licensed as a whole at no charge to all third parties +under the terms of this License. + + +**c)** If the modified program normally reads commands interactively +when run, you must cause it, when started running for such interactive +use in the most ordinary way, to print or display an announcement +including an appropriate copyright notice and a notice that there is +no warranty (or else, saying that you provide a warranty) and that +users may redistribute the program under these conditions, and telling +the user how to view a copy of this License. (Exception: if the +Program itself is interactive but does not normally print such an +announcement, your work based on the Program is not required to print +an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + +**a)** Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections 1 +and 2 above on a medium customarily used for software interchange; or, + + +**b)** Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your cost of +physically performing source distribution, a complete machine-readable +copy of the corresponding source code, to be distributed under the +terms of Sections 1 and 2 above on a medium customarily used for +software interchange; or, + + +**c)** Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is allowed +only for noncommercial distribution and only if you received the +program in object code or executable form with such an offer, in +accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt otherwise +to copy, modify, sublicense or distribute the Program is void, and +will automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on +the Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +**7.** If, as a consequence of a court judgment or allegation of +patent infringement or for any other reason (not limited to patent +issues), conditions are imposed on you (whether by court order, +agreement or otherwise) that contradict the conditions of this +License, they do not excuse you from the conditions of this License. +If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, +then as a consequence you may not distribute the Program at all. For +example, if a patent license would not permit royalty-free +redistribution of the Program by all those who receive copies directly +or indirectly through you, then the only way you could satisfy both it +and this License would be to refrain entirely from distribution of the +Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**9.** The Free Software Foundation may publish revised and/or new +versions of the General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Program does not specify a +version number of this License, you may choose any version ever +published by the Free Software Foundation. + +**10.** If you wish to incorporate parts of the Program into other +free programs whose distribution conditions are different, write to +the author to ask for permission. For software which is copyrighted by +the Free Software Foundation, write to the Free Software Foundation; +we sometimes make exceptions for this. Our decision will be guided by +the two goals of preserving the free status of all derivatives of our +free software and of promoting the sharing and reuse of software +generally. + +**NO WARRANTY** + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +### END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. + Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper +mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w'. This is free software, and you are welcome + to redistribute it under certain conditions; type `show c' + for details. + +The hypothetical commands \`show w' and \`show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than \`show w' and +\`show c'; they could even be mouse-clicks or menu items--whatever +suits your program. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the program, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright + interest in the program `Gnomovision' + (which makes passes at compilers) written + by James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, +you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +[GNU Lesser General Public +License](http://www.gnu.org/licenses/lgpl.html) instead of this +License. diff --git a/README.md b/README.md index 685e9808771a0e..a7b025352d8fab 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,24 @@ # Gutenberg +[![Build Status](https://travis-ci.org/WordPress/gutenberg.svg?branch=master)](https://travis-ci.org/WordPress/gutenberg) Printing since 1440. ![Text block](https://wpcoredesign.mystagingwebsite.com/gutenberg/gutenberg.png) -This is the development hub for the editor focus in core. Gutenberg is the project name. If you want the latest release for your WordPress, download Gutenberg from the WordPress.org plugins repository. Conversations and discussions take place in #core-editor on the core WordPress Slack. This is our kickoff goal: +This is the development hub for the editor focus in a core. Gutenberg is the project name. If you want the latest release for your WordPress, download Gutenberg from the WordPress.org plugins repository. Conversations and discussions take place in #core-editor on the core WordPress Slack. This is our kickoff goal: > The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery. — Matt Mullenweg WordPress already supports a large amount of "blocks", but doesn't surface them very well, nor does it give them much in the way of layout options. By embracing the blocky nature of rich post content, we will surface the blocks that already exist, as well as provide more advanced layout options for each of them. This will allow you to easily compose beautiful posts like this example. +## Contributors + +Gutenberg is built by many contributors and volunteers. Please see the full list in CONTRIBUTORS.md. + ## Further Reading - Editor Technical Overview - How Blocks Work -- Editor Mockups - WP Post Grammar Parser - Development updates on make.wordpress.org @@ -24,7 +28,7 @@ Please see [CONTRIBUTING.md](CONTRIBUTING.md). ## Why -One thing that sets WordPress apart from other systems is that it allows you to create as rich a post layout as you can imagine -- but only if you know HTML & CSS and build your own custom theme. By thinking of the editor as a tool to let you write rich posts, and in a few clicks create beautiful layouts, hopefully we can make people start to _love_ WordPress, as opposed to pick it because it's what everyone else uses to blog. +One thing that sets WordPress apart from other systems is that it allows you to create as rich a post layout as you can imagine -- but only if you know HTML & CSS and build your own custom theme. By thinking of the editor as a tool to let you write rich posts, and in a few clicks create beautiful layouts, hopefully, we can make people start to _love_ WordPress, as opposed to pick it because it's what everyone else uses to blog. ## Ingredients @@ -36,6 +40,6 @@ By showing critical UI in the body of the content, many can get their basic blog **Advanced Formatting** -When the Post Settings sidebar is open — which it is by default — you are essentially in advanced layout mode. By default you'll see all your metaboxes right there. +When the Post Settings sidebar is open — which it is by default — you are essentially in advanced layout mode. By default, you'll see all your metaboxes right there. Every block can be _inspected_ by clicking it. And every block has advanced layout options available in the inspector; text might have drop-cap, image might have fixed position scrolling. As such, block attributes fall in two camps — the most important ones available right on the block, advanced ones living in the sidebar inspector. diff --git a/bin/build-plugin-zip.sh b/bin/build-plugin-zip.sh index 7117760ae3dbc3..b8497d635aaf9d 100755 --- a/bin/build-plugin-zip.sh +++ b/bin/build-plugin-zip.sh @@ -67,7 +67,6 @@ mv gutenberg.tmp.php gutenberg.php # Generate the plugin zip file zip -r gutenberg.zip \ gutenberg.php \ - index.php \ lib/*.php \ lib/blocks/*.php \ post-content.js \ diff --git a/bin/create-php-parser.js b/bin/create-php-parser.js new file mode 100755 index 00000000000000..fda773d0dd3f0c --- /dev/null +++ b/bin/create-php-parser.js @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const pegjs = require( 'pegjs' ); +const phpegjs = require( 'phpegjs' ); +const fs = require( 'fs' ); +const path = require( 'path' ); + +const peg = fs.readFileSync( 'blocks/api/post.pegjs', 'utf8' ); + +const parser = pegjs.generate( + peg, + { + plugins: [ phpegjs ], + phpegjs: { + parserNamespace: null, + parserGlobalNamePrefix: 'Gutenberg_PEG_', + }, + } +); + +fs.writeFileSync( + path.join( __dirname, '..', 'lib', 'parser.php' ), + parser +); diff --git a/blocks/README.md b/blocks/README.md index 20ce547a07c0e2..b775b9776d4ebb 100644 --- a/blocks/README.md +++ b/blocks/README.md @@ -28,7 +28,7 @@ The following sections will describe what you'll need to include in `block.js` t Let's imagine you wanted to define a block to show a randomly generated image in a post's content using [lorempixel.com](http://lorempixel.com/). The service provides a choice of category and you'd like to offer this as an option when editing the post. -Take a step back and consider the ideal workflow for adding a new random image. After inserting the block, as a user I'd expect it to be shown in some empty state, with an option to choose a category in a select dropdown. Upon confirming my selection, a preview of the image should be shown next to the dropdown. At this point, you might realize that while you'd want some controls to be shown when editing content, the markup included in the published post might not appear the same (your visitors should not see a dropdown field when reading your content). This leads to the first requirement of describing a block: __you will need to provide implementations both for what's to be shown in an editor and what's to be saved with the published content__. You needn't worry about redundant effort here, as concepts of [Elements](../elements/README.md) and componentization provide an avenue for sharing common behaviors. +Take a step back and consider the ideal workflow for adding a new random image. After inserting the block, as a user I'd expect it to be shown in some empty state, with an option to choose a category in a select dropdown. Upon confirming my selection, a preview of the image should be shown next to the dropdown. At this point, you might realize that while you'd want some controls to be shown when editing content, the markup included in the published post might not appear the same (your visitors should not see a dropdown field when reading your content). This leads to the first requirement of describing a block: __you will need to provide implementations both for what's to be shown in an editor and what's to be saved with the published content__. You needn't worry about redundant effort here, as concepts of [Elements](../element/README.md) and componentization provide an avenue for sharing common behaviors. Now that we've considered user interaction, you should think about the underlying values that determine the markup generated by your block. In our example, the output is affected only when the category changes. Put another way: __the output of a block is a function of its attributes__. The category, a simple string, is the only thing we require to be able to generate the image we want to include in the published content. We call these underlying values of a block instance its _attributes_. diff --git a/blocks/api/index.js b/blocks/api/index.js index f53c14a05d50c6..291c909f23ff36 100644 --- a/blocks/api/index.js +++ b/blocks/api/index.js @@ -6,7 +6,7 @@ import * as query from './query'; export { query }; export { createBlock, switchToBlockType } from './factory'; export { default as parse } from './parser'; -export { default as serialize } from './serializer'; +export { default as serialize, getBlockDefaultClassname } from './serializer'; export { getCategories } from './categories'; export { registerBlockType, diff --git a/blocks/api/post.pegjs b/blocks/api/post.pegjs index c53f9fe5f9c942..97d6372e514cae 100644 --- a/blocks/api/post.pegjs +++ b/blocks/api/post.pegjs @@ -1,15 +1,16 @@ { -function untransformValue( value ) { - return 'string' === typeof value - ? value.replace( /\\-/g, '-' ) - : value; -} - -function keyValue( key, value ) { - const o = {}; - o[ key ] = untransformValue( value ); - return o; +/** **/ + +function maybeJSON( s ) { + try { + return JSON.parse( s ); + } catch (e) { + return null; + } } } @@ -26,24 +27,63 @@ WP_Block / WP_Block_Html WP_Block_Void - = "" - { return { - blockName: blockName, - attrs: attrs, - rawContent: '' - } } + = "" + { + /** $blockName, + 'attrs' => $attrs, + 'rawContent' => '', + ); + ?> **/ + + return { + blockName: blockName, + attrs: attrs, + rawContent: '' + }; + } WP_Block_Balanced - = s:WP_Block_Start ts:(!WP_Block_End c:Any { return c })* e:WP_Block_End & { return s.blockName === e.blockName } - { return { - blockName: s.blockName, - attrs: s.attrs, - rawContent: ts.join( '' ), - } } + = s:WP_Block_Start ts:(!WP_Block_End c:Any { + /** **/ + return c; + })* e:WP_Block_End & { + /** **/ + return s.blockName === e.blockName; + } + { + /** $s['blockName'], + 'attrs' => $s['attrs'], + 'rawContent' => implode( '', $ts ), + ); + ?> **/ + + return { + blockName: s.blockName, + attrs: s.attrs, + rawContent: ts.join( '' ) + }; + } WP_Block_Html - = ts:(!WP_Block_Balanced !WP_Block_Void c:Any { return c })+ + = ts:(!WP_Block_Balanced !WP_Block_Void c:Any { + /** **/ + return c; + })+ { + /** array(), + 'rawContent' => implode( '', $ts ), + ); + ?> **/ + return { attrs: {}, rawContent: ts.join( '' ) @@ -51,46 +91,47 @@ WP_Block_Html } WP_Block_Start - = "" - { return { - blockName: blockName, - attrs: attrs - } } + = "" + { + /** $blockName, + 'attrs' => $attrs, + ); + ?> **/ + + return { + blockName: blockName, + attrs: attrs + }; + } WP_Block_End - = "" - { return { - blockName: blockName - } } + = "" + { + /** $blockName, + ); + ?> **/ + + return { + blockName: blockName + }; + } WP_Block_Name = $(ASCII_Letter (ASCII_AlphaNumeric / "/" ASCII_AlphaNumeric)*) -HTML_Attribute_List - = as:(_+ a:HTML_Attribute_Item { return a })* - { return as.reduce( function( attrs, attr ) { return Object.assign( attrs, attr ) }, {} ) } - -HTML_Attribute_Item - = HTML_Attribute_Quoted - / HTML_Attribute_Unquoted - / HTML_Attribute_Empty - -HTML_Attribute_Empty - = name:HTML_Attribute_Name - { return keyValue( name, true ) } - -HTML_Attribute_Unquoted - = name:HTML_Attribute_Name _* "=" _* value:$([a-zA-Z0-9]+) - { return keyValue( name, value ) } - -HTML_Attribute_Quoted - = name:HTML_Attribute_Name _* "=" _* '"' value:$(('\\"' . / !'"' .)*) '"' - { return keyValue( name, value ) } - / name:HTML_Attribute_Name _* "=" _* "'" value:$(("\\'" . / !"'" .)*) "'" - { return keyValue( name, value ) } - -HTML_Attribute_Name - = $([a-zA-Z0-9:.]+) +WP_Block_Attributes + = attrs:$("{" (!("}" WS+ """/"? "-->") .)* "}") + { + /** **/ + return maybeJSON( attrs ); + } ASCII_AlphaNumeric = ASCII_Letter @@ -106,6 +147,9 @@ ASCII_Digit Special_Chars = [\-\_] +WS + = [ \t\r\n] + Newline = [\r\n] diff --git a/blocks/api/query.js b/blocks/api/query.js index 5a91e6503694ef..c369164b335db3 100644 --- a/blocks/api/query.js +++ b/blocks/api/query.js @@ -1,7 +1,12 @@ +/** + * WordPress dependencies + */ +import { createElement } from 'element'; + /** * External dependencies */ -import { nodeListToReact } from 'dom-react'; +import { nodeListToReact, nodeToReact } from 'dom-react'; import { flow } from 'lodash'; import { attr as originalAttr, @@ -31,17 +36,28 @@ export const html = withKnownMatcherFlag( originalHtml ); export const text = withKnownMatcherFlag( originalText ); export const query = withKnownMatcherFlag( originalQuery ); export const children = withKnownMatcherFlag( ( selector ) => { - return ( node ) => { - let match = node; + return ( domNode ) => { + let match = domNode; if ( selector ) { - match = node.querySelector( selector ); + match = domNode.querySelector( selector ); } if ( match ) { - return nodeListToReact( match.childNodes || [], wp.element.createElement ); + return nodeListToReact( match.childNodes || [], createElement ); } return []; }; } ); +export const node = withKnownMatcherFlag( ( selector ) => { + return ( domNode ) => { + let match = domNode; + + if ( selector ) { + match = domNode.querySelector( selector ); + } + + return nodeToReact( match, createElement ); + }; +} ); diff --git a/blocks/api/serializer.js b/blocks/api/serializer.js index 54e64d9ee162b3..66b74219790647 100644 --- a/blocks/api/serializer.js +++ b/blocks/api/serializer.js @@ -1,8 +1,14 @@ /** * External dependencies */ -import { isEmpty, map, reduce } from 'lodash'; +import { isEmpty, reduce, kebabCase, isObject } from 'lodash'; import { html as beautifyHtml } from 'js-beautify'; +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Component, createElement, renderToString, cloneElement, Children } from 'element'; /** * Internal dependencies @@ -11,18 +17,33 @@ import { getBlockType } from './registration'; import { parseBlockAttributes } from './parser'; /** - * Given a block's save render implementation and attributes, returns the + * Returns the block's default classname from its name + * + * @param {String} blockName The block name + * @return {string} The block's default class + */ +export function getBlockDefaultClassname( blockName ) { + // Drop the namespace "core/"" for core blocks only + const match = /^([a-z0-9-]+)\/([a-z0-9-]+)$/.exec( blockName ); + const sanitizedBlockName = match[ 1 ] === 'core' ? match[ 2 ] : blockName; + + return `wp-block-${ kebabCase( sanitizedBlockName ) }`; +} + +/** + * Given a block type containg a save render implementation and attributes, returns the * static markup to be saved. * - * @param {Function|WPComponent} save Save render implementation + * @param {Object} blockType Block type * @param {Object} attributes Block attributes * @return {string} Save content */ -export function getSaveContent( save, attributes ) { +export function getSaveContent( blockType, attributes ) { + const { save, className = getBlockDefaultClassname( blockType.name ) } = blockType; let rawContent; - if ( save.prototype instanceof wp.element.Component ) { - rawContent = wp.element.createElement( save, { attributes } ); + if ( save.prototype instanceof Component ) { + rawContent = createElement( save, { attributes } ); } else { rawContent = save( { attributes } ); @@ -32,27 +53,20 @@ export function getSaveContent( save, attributes ) { } } - // Otherwise, infer as element - return wp.element.renderToString( rawContent ); -} + // Adding a generic classname + const addClassnameToElement = ( element ) => { + if ( ! element || ! isObject( element ) || ! className ) { + return element; + } -const escapeDoubleQuotes = value => value.replace( /"/g, '\"' ); -const escapeHyphens = value => value.replace( /-/g, '\\-' ); + const updatedClassName = classnames( element.props.className, className ); + return cloneElement( element, { className: updatedClassName } ); + }; + const contentWithClassname = Children.map( rawContent, addClassnameToElement ); -/** - * Transform value for storage in block comment - * - * Some special characters and sequences should not - * appear in a block comment header. This transformer - * will guarantee that we store the data safely. - * - * @param {*} value attribute value to serialize - * @returns {*} transformed value - */ -export const serializeValue = value => - 'string' === typeof value - ? escapeHyphens( escapeDoubleQuotes( value ) ) - : value; + // Otherwise, infer as element + return renderToString( contentWithClassname ); +} /** * Returns attributes which ought to be saved @@ -87,26 +101,22 @@ export function getCommentAttributes( allAttributes, attributesFromContent ) { ); } -/** - * Lodash iterator which transforms a key: value - * pair into a string of `key="value"` - * - * @param {*} value value to be stringified - * @param {String} key name of value - * @returns {string} stringified equality pair - */ -function asNameValuePair( value, key ) { - return `${ key }="${ serializeValue( value ) }"`; +export function serializeAttributes( attrs ) { + return JSON.stringify( attrs ) + .replace( /--/g, '\\u002d\\u002d' ) // don't break HTML comments + .replace( //g, '\\u003e' ) // ibid + .replace( /&/g, '\\u0026' ); // ibid } export function serializeBlock( block ) { const blockName = block.name; const blockType = getBlockType( blockName ); - const saveContent = getSaveContent( blockType.save, block.attributes ); + const saveContent = getSaveContent( blockType, block.attributes ); const saveAttributes = getCommentAttributes( block.attributes, parseBlockAttributes( saveContent, blockType ) ); const serializedAttributes = ! isEmpty( saveAttributes ) - ? map( saveAttributes, asNameValuePair ).join( ' ' ) + ' ' + ? serializeAttributes( saveAttributes ) + ' ' : ''; if ( ! saveContent ) { diff --git a/blocks/api/test/parser.js b/blocks/api/test/parser.js index 2d55b0764e0d22..9b48911a5ab8c1 100644 --- a/blocks/api/test/parser.js +++ b/blocks/api/test/parser.js @@ -152,7 +152,7 @@ describe( 'block parser', () => { } ); const parsed = parse( - '' + + '' + 'Brisket' + '' ); diff --git a/blocks/api/test/query.js b/blocks/api/test/query.js index e372cf1df66305..2a223d52f65a61 100644 --- a/blocks/api/test/query.js +++ b/blocks/api/test/query.js @@ -4,6 +4,11 @@ import { expect } from 'chai'; import { parse } from 'hpq'; +/** + * WordPress dependencies + */ +import { renderToString } from 'element'; + /** * Internal dependencies */ @@ -29,7 +34,24 @@ describe( 'query', () => { const html = '

A delicious sundae dessert

'; const match = parse( html, query.children() ); - expect( wp.element.renderToString( match ) ).to.equal( html ); + expect( renderToString( match ) ).to.equal( html ); + } ); + } ); + + describe( 'node()', () => { + it( 'should return a matcher function', () => { + const matcher = query.node(); + + expect( matcher ).to.be.a( 'function' ); + } ); + + it( 'should return HTML equivalent WPElement of matched element', () => { + // Assumption here is that we can cleanly convert back and forth + // between a string and WPElement representation + const html = '

A delicious sundae dessert

'; + const match = parse( html, query.node() ); + + expect( wp.element.renderToString( match ) ).to.equal( `${ html }` ); } ); } ); } ); diff --git a/blocks/api/test/serializer.js b/blocks/api/test/serializer.js index ace404fbffdc97..85c3598f9a3117 100644 --- a/blocks/api/test/serializer.js +++ b/blocks/api/test/serializer.js @@ -3,10 +3,15 @@ */ import { expect } from 'chai'; +/** + * WordPress dependencies + */ +import { createElement, Component } from 'element'; + /** * Internal dependencies */ -import serialize, { getCommentAttributes, getSaveContent, serializeValue } from '../serializer'; +import serialize, { getCommentAttributes, getSaveContent, serializeAttributes } from '../serializer'; import { getBlockTypes, registerBlockType, unregisterBlockType } from '../registration'; describe( 'block serializer', () => { @@ -20,7 +25,10 @@ describe( 'block serializer', () => { context( 'function save', () => { it( 'should return string verbatim', () => { const saved = getSaveContent( - ( { attributes } ) => attributes.fruit, + { + save: ( { attributes } ) => attributes.fruit, + name: 'core/fruit', + }, { fruit: 'Bananas' } ); @@ -28,9 +36,49 @@ describe( 'block serializer', () => { } ); it( 'should return element as string if save returns element', () => { - const { createElement } = wp.element; const saved = getSaveContent( - ( { attributes } ) => createElement( 'div', null, attributes.fruit ), + { + save: ( { attributes } ) => createElement( 'div', null, attributes.fruit ), + name: 'core/fruit', + }, + { fruit: 'Bananas' } + ); + + expect( saved ).to.equal( '
Bananas
' ); + } ); + + it( 'should return use the namespace in the classname if it\' not a core block', () => { + const saved = getSaveContent( + { + save: ( { attributes } ) => createElement( 'div', null, attributes.fruit ), + name: 'myplugin/fruit', + }, + { fruit: 'Bananas' } + ); + + expect( saved ).to.equal( '
Bananas
' ); + } ); + + it( 'should overrides the className', () => { + const saved = getSaveContent( + { + save: ( { attributes } ) => createElement( 'div', null, attributes.fruit ), + name: 'myplugin/fruit', + className: 'apples', + }, + { fruit: 'Bananas' } + ); + + expect( saved ).to.equal( '
Bananas
' ); + } ); + + it( 'should not add a className if falsy', () => { + const saved = getSaveContent( + { + save: ( { attributes } ) => createElement( 'div', null, attributes.fruit ), + name: 'myplugin/fruit', + className: false, + }, { fruit: 'Bananas' } ); @@ -40,12 +88,14 @@ describe( 'block serializer', () => { context( 'component save', () => { it( 'should return element as string', () => { - const { Component, createElement } = wp.element; const saved = getSaveContent( - class extends Component { - render() { - return createElement( 'div', null, this.props.attributes.fruit ); - } + { + save: class extends Component { + render() { + return createElement( 'div', null, this.props.attributes.fruit ); + } + }, + name: 'core/fruit', }, { fruit: 'Bananas' } ); @@ -87,15 +137,18 @@ describe( 'block serializer', () => { } ); } ); - describe( 'serializeValue()', () => { - it( 'should escape double-quotes', () => { - expect( serializeValue( 'a"b' ) ).to.equal( 'a\"b' ); + describe( 'serializeAttributes()', () => { + it( 'should not break HTML comments', () => { + expect( serializeAttributes( { a: '-- and --' } ) ).to.equal( '{"a":"\\u002d\\u002d and \\u002d\\u002d"}' ); } ); - - it( 'should escape hyphens', () => { - expect( serializeValue( '-' ) ).to.equal( '\u{5c}-' ); - expect( serializeValue( '--' ) ).to.equal( '\u{5c}-\u{5c}-' ); - expect( serializeValue( '\\-' ) ).to.equal( '\u{5c}\u{5c}-' ); + it( 'should not break standard-non-compliant tools for "<"', () => { + expect( serializeAttributes( { a: '< and <' } ) ).to.equal( '{"a":"\\u003c and \\u003c"}' ); + } ); + it( 'should not break standard-non-compliant tools for ">"', () => { + expect( serializeAttributes( { a: '> and >' } ) ).to.equal( '{"a":"\\u003e and \\u003e"}' ); + } ); + it( 'should not break standard-non-compliant tools for "&"', () => { + expect( serializeAttributes( { a: '& and &' } ) ).to.equal( '{"a":"\\u0026 and \\u0026"}' ); } ); } ); @@ -117,11 +170,11 @@ describe( 'block serializer', () => { name: 'core/test-block', attributes: { content: 'Ribs & Chicken', - align: 'left', + stuff: 'left & right -- but ', }, }, ]; - const expectedPostContent = '\n

Ribs & Chicken

\n'; + const expectedPostContent = '\n

Ribs & Chicken

\n'; expect( serialize( blockList ) ).to.eql( expectedPostContent ); } ); diff --git a/blocks/block-description/index.js b/blocks/block-description/index.js new file mode 100644 index 00000000000000..cdf5749bff607d --- /dev/null +++ b/blocks/block-description/index.js @@ -0,0 +1,12 @@ +/** + * Internal dependencies + */ +import './style.scss'; + +export default function BlockDescription( { children } ) { + return ( +
+ { children } +
+ ); +} diff --git a/blocks/block-description/style.scss b/blocks/block-description/style.scss new file mode 100644 index 00000000000000..376586d33f24ed --- /dev/null +++ b/blocks/block-description/style.scss @@ -0,0 +1,13 @@ +.components-block-description { + &:not(:last-child):after { + content: ''; + display: block; + border-bottom: 1px solid $light-gray-500; + margin: 1.5em 0; + } + + p { + font-style: italic; + margin-top: 0; + } +} diff --git a/blocks/block-description/test/index.js b/blocks/block-description/test/index.js new file mode 100644 index 00000000000000..d2d177255df38e --- /dev/null +++ b/blocks/block-description/test/index.js @@ -0,0 +1,21 @@ +/** + * External dependencies + */ +import { expect } from 'chai'; +import { shallow } from 'enzyme'; + +/** + * Internal dependencies + */ +import BlockDescription from '../'; + +describe( 'BlockDescription', () => { + describe( 'basic rendering', () => { + it( 'should render a

element with some content', () => { + const blockDescription = shallow(

Hello World

); + expect( blockDescription.hasClass( 'components-block-description' ) ).to.be.true(); + expect( blockDescription.type() ).to.equal( 'div' ); + expect( blockDescription.text() ).to.equal( 'Hello World' ); + } ); + } ); +} ); diff --git a/blocks/editable/format-toolbar.js b/blocks/editable/format-toolbar.js index ccc1379be2b5e0..431a28b8406ee1 100644 --- a/blocks/editable/format-toolbar.js +++ b/blocks/editable/format-toolbar.js @@ -1,23 +1,25 @@ /** * WordPress dependencies */ +import { __ } from 'i18n'; +import { Component } from 'element'; import { IconButton, Toolbar } from 'components'; import { ESCAPE } from 'utils/keycodes'; const FORMATTING_CONTROLS = [ { icon: 'editor-bold', - title: wp.i18n.__( 'Bold' ), + title: __( 'Bold' ), format: 'bold', }, { icon: 'editor-italic', - title: wp.i18n.__( 'Italic' ), + title: __( 'Italic' ), format: 'italic', }, { icon: 'editor-strikethrough', - title: wp.i18n.__( 'Strikethrough' ), + title: __( 'Strikethrough' ), format: 'strikethrough', }, ]; @@ -25,7 +27,7 @@ const FORMATTING_CONTROLS = [ // Default controls shown if no `enabledControls` prop provided const DEFAULT_CONTROLS = [ 'bold', 'italic', 'strikethrough', 'link' ]; -class FormatToolbar extends wp.element.Component { +class FormatToolbar extends Component { constructor( props ) { super( ...arguments ); this.state = { @@ -133,7 +135,7 @@ class FormatToolbar extends wp.element.Component { if ( enabledControls.indexOf( 'link' ) !== -1 ) { toolbarControls.push( { icon: 'admin-links', - title: wp.i18n.__( 'Link' ), + title: __( 'Link' ), onClick: this.addLink, isActive: !! formats.link, } ); @@ -156,7 +158,7 @@ class FormatToolbar extends wp.element.Component { required value={ this.state.linkValue } onChange={ this.updateLinkValue } - placeholder={ wp.i18n.__( 'Paste URL or type' ) } + placeholder={ __( 'Paste URL or type' ) } /> @@ -165,7 +167,11 @@ class FormatToolbar extends wp.element.Component { { !! formats.link && ! this.state.isEditingLink &&
- + { this.state.linkValue && decodeURI( this.state.linkValue ) } diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 547bbc58c40863..4b66cfe7db52c4 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -1,6 +1,7 @@ /** * External dependencies */ +import tinymce from 'tinymce'; import classnames from 'classnames'; import { last, isEqual, omitBy, forEach, merge, identity, find } from 'lodash'; import { nodeListToReact } from 'dom-react'; @@ -10,6 +11,7 @@ import 'element-closest'; /** * WordPress dependencies */ +import { createElement, Component, renderToString } from 'element'; import { BACKSPACE, DELETE, ENTER } from 'utils/keycodes'; /** @@ -19,7 +21,7 @@ import './style.scss'; import FormatToolbar from './format-toolbar'; import TinyMCE from './tinymce'; -function createElement( type, props, ...children ) { +function createTinyMCEElement( type, props, ...children ) { if ( props[ 'data-mce-bogus' ] === 'all' ) { return null; } @@ -28,14 +30,14 @@ function createElement( type, props, ...children ) { return children; } - return wp.element.createElement( + return createElement( type, omitBy( props, ( value, key ) => key.indexOf( 'data-mce-' ) === 0 ), ...children ); } -export default class Editable extends wp.element.Component { +export default class Editable extends Component { constructor( props ) { super( ...arguments ); @@ -104,11 +106,10 @@ export default class Editable extends wp.element.Component { return; } - const content = this.getContent(); const collapsed = this.editor.selection.isCollapsed(); this.setState( { - empty: ! content || ! content.length, + empty: tinymce.DOM.isEmpty( this.editor.getBody() ), } ); if ( @@ -261,8 +262,8 @@ export default class Editable extends wp.element.Component { const beforeFragment = beforeRange.extractContents(); const afterFragment = afterRange.extractContents(); - const beforeElement = nodeListToReact( beforeFragment.childNodes, createElement ); - const afterElement = nodeListToReact( afterFragment.childNodes, createElement ); + const beforeElement = nodeListToReact( beforeFragment.childNodes, createTinyMCEElement ); + const afterElement = nodeListToReact( afterFragment.childNodes, createTinyMCEElement ); this.setContent( beforeElement ); this.props.onSplit( beforeElement, afterElement ); @@ -311,8 +312,8 @@ export default class Editable extends wp.element.Component { this.setContent( this.props.value ); this.props.onSplit( - nodeListToReact( before, createElement ), - nodeListToReact( after, createElement ) + nodeListToReact( before, createTinyMCEElement ), + nodeListToReact( after, createTinyMCEElement ) ); } @@ -320,7 +321,7 @@ export default class Editable extends wp.element.Component { const formats = {}; const link = find( parents, ( node ) => node.nodeName.toLowerCase() === 'a' ); if ( link ) { - formats.link = { value: link.getAttribute( 'href' ), link }; + formats.link = { value: link.getAttribute( 'href' ) || '', link }; } const activeFormats = this.editor.formatter.matchAll( [ 'bold', 'italic', 'strikethrough' ] ); activeFormats.forEach( ( activeFormat ) => formats[ activeFormat ] = true ); @@ -346,12 +347,12 @@ export default class Editable extends wp.element.Component { content = ''; } - content = wp.element.renderToString( content ); + content = renderToString( content ); this.editor.setContent( content, { format: 'raw' } ); } getContent() { - return nodeListToReact( this.editor.getBody().childNodes || [], createElement ); + return nodeListToReact( this.editor.getBody().childNodes || [], createTinyMCEElement ); } updateFocus() { @@ -433,7 +434,7 @@ export default class Editable extends wp.element.Component { render() { const { - tagName, + tagName: Tagname = 'div', style, value, focus, @@ -441,12 +442,14 @@ export default class Editable extends wp.element.Component { inlineToolbar = false, formattingControls, placeholder, + inline, } = this.props; // Generating a key that includes `tagName` ensures that if the tag // changes, we unmount and destroy the previous TinyMCE element, then // mount and initialize a new child element in its place. - const key = [ 'editor', tagName ].join(); + const key = [ 'editor', Tagname ].join(); + const isPlaceholderVisible = placeholder && this.state.empty; const classes = classnames( className, 'blocks-editable' ); const formatToolbar = ( @@ -471,15 +474,23 @@ export default class Editable extends wp.element.Component {
} + { isPlaceholderVisible && + + { inline ? placeholder :

{ placeholder }

} +
+ } ); } diff --git a/blocks/editable/style.scss b/blocks/editable/style.scss index 9c143868dcdbe3..78fdb1c6f74062 100644 --- a/blocks/editable/style.scss +++ b/blocks/editable/style.scss @@ -4,6 +4,7 @@ .blocks-editable__tinymce { margin: 0; + position: relative; > p:empty { min-height: $editor-font-size * $editor-line-height; @@ -38,19 +39,24 @@ background: $light-gray-400; } - &[data-is-empty="true"] { - position: relative; + &[data-is-placeholder-visible="true"] { + position: absolute; + top: 0; + width: 100%; + margin-top: 0; + + & > p { + margin-top: 0; + } } - &[data-is-empty="true"]:before { - content: attr( data-placeholder ); + & + .blocks-editable__tinymce { opacity: 0.5; pointer-events: none; - position: absolute; } } -.drop-cap-true .blocks-editable__tinymce:not( :focus ) { +.has-drop-cap .blocks-editable__tinymce:not( :focus ) { &:first-letter { float: left; font-size: 4.1em; @@ -63,7 +69,7 @@ } } -.drop-cap-true:not( :focus ) { +.has-drop-cap:not( :focus ) { overflow: hidden; } diff --git a/blocks/editable/tinymce.js b/blocks/editable/tinymce.js index 8a4ec1dc9f8072..286388f3ae8c06 100644 --- a/blocks/editable/tinymce.js +++ b/blocks/editable/tinymce.js @@ -3,8 +3,14 @@ */ import tinymce from 'tinymce'; import { isEqual } from 'lodash'; +import classnames from 'classnames'; -export default class TinyMCE extends wp.element.Component { +/** + * WordPress dependencies + */ +import { Component, Children, createElement } from 'element'; + +export default class TinyMCE extends Component { componentDidMount() { this.initialize(); } @@ -18,10 +24,11 @@ export default class TinyMCE extends wp.element.Component { } componentWillReceiveProps( nextProps ) { - const isEmpty = String( nextProps.isEmpty ); + const name = 'data-is-placeholder-visible'; + const isPlaceholderVisible = String( !! nextProps.isPlaceholderVisible ); - if ( this.editorNode.getAttribute( 'data-is-empty' ) !== isEmpty ) { - this.editorNode.setAttribute( 'data-is-empty', isEmpty ); + if ( this.editorNode.getAttribute( name ) !== isPlaceholderVisible ) { + this.editorNode.setAttribute( name, isPlaceholderVisible ); } if ( ! isEqual( this.props.style, nextProps.style ) ) { @@ -71,23 +78,23 @@ export default class TinyMCE extends wp.element.Component { } render() { - const { tagName = 'div', style, defaultValue, placeholder } = this.props; + const { tagName = 'div', style, defaultValue, label, className } = this.props; // If a default value is provided, render it into the DOM even before // TinyMCE finishes initializing. This avoids a short delay by allowing // us to show and focus the content before it's truly ready to edit. let children; if ( defaultValue ) { - children = wp.element.Children.toArray( defaultValue ); + children = Children.toArray( defaultValue ); } - return wp.element.createElement( tagName, { + return createElement( tagName, { ref: ( node ) => this.editorNode = node, contentEditable: true, suppressContentEditableWarning: true, - className: 'blocks-editable__tinymce', + className: classnames( className, 'blocks-editable__tinymce' ), style, - 'data-placeholder': placeholder, + 'aria-label': label, }, children ); } } diff --git a/blocks/index.js b/blocks/index.js index c73c2217117d5d..2ddfd52779bc0b 100644 --- a/blocks/index.js +++ b/blocks/index.js @@ -15,5 +15,6 @@ import './library'; export * from './api'; export { default as AlignmentToolbar } from './alignment-toolbar'; export { default as BlockControls } from './block-controls'; +export { default as BlockDescription } from './block-description'; export { default as Editable } from './editable'; export { default as MediaUploadButton } from './media-upload-button'; diff --git a/blocks/inspector-controls/base-control/index.js b/blocks/inspector-controls/base-control/index.js new file mode 100644 index 00000000000000..6d671320fb915b --- /dev/null +++ b/blocks/inspector-controls/base-control/index.js @@ -0,0 +1,20 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import './style.scss'; + +function BaseControl( { id, label, className, children } ) { + return ( +
+ { label && } + { children } +
+ ); +} + +export default BaseControl; diff --git a/blocks/inspector-controls/base-control/style.scss b/blocks/inspector-controls/base-control/style.scss new file mode 100644 index 00000000000000..50fe2a2d599726 --- /dev/null +++ b/blocks/inspector-controls/base-control/style.scss @@ -0,0 +1,8 @@ +.blocks-base-control { + margin: 1em 0 1.5em 0; +} + +.blocks-base-control__label { + display: block; + margin-bottom: 5px; +} diff --git a/blocks/inspector-controls/checkbox-control/index.js b/blocks/inspector-controls/checkbox-control/index.js new file mode 100644 index 00000000000000..10eebd4072bc2a --- /dev/null +++ b/blocks/inspector-controls/checkbox-control/index.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { withInstanceId } from 'components'; + +/** + * Internal dependencies + */ +import BaseControl from './../base-control'; +import './style.scss'; + +function CheckboxControl( { label, heading, checked, instanceId, onChange, ...props } ) { + const id = 'inspector-checkbox-control-' + instanceId; + const onChangeValue = ( event ) => onChange( event.target.value ); + + return ( + + + + + ); +} + +export default withInstanceId( CheckboxControl ); diff --git a/blocks/inspector-controls/checkbox-control/style.scss b/blocks/inspector-controls/checkbox-control/style.scss new file mode 100644 index 00000000000000..90f1f24fe4ca7e --- /dev/null +++ b/blocks/inspector-controls/checkbox-control/style.scss @@ -0,0 +1,4 @@ +.blocks-checkbox-control__input[type=checkbox] { + margin-top: 0; + margin-right: 6px; +} \ No newline at end of file diff --git a/blocks/inspector-controls/radio-control/index.js b/blocks/inspector-controls/radio-control/index.js new file mode 100644 index 00000000000000..3ee2b938c54690 --- /dev/null +++ b/blocks/inspector-controls/radio-control/index.js @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +import { isEmpty } from 'lodash'; + +/** + * WordPress dependencies + */ +import { withInstanceId } from 'components'; + +/** + * Internal dependencies + */ +import BaseControl from './../base-control'; +import './style.scss'; + +function RadioControl( { label, selected, instanceId, onChange, options = [] } ) { + const id = 'inspector-radio-control-' + instanceId; + const onChangeValue = ( event ) => onChange( event.target.value ); + + return ! isEmpty( options ) && ( + + { options.map( ( option, index ) => +
+ + +
+ ) } +
+ ); +} + +export default withInstanceId( RadioControl ); diff --git a/blocks/inspector-controls/radio-control/style.scss b/blocks/inspector-controls/radio-control/style.scss new file mode 100644 index 00000000000000..9f11fd1c76f015 --- /dev/null +++ b/blocks/inspector-controls/radio-control/style.scss @@ -0,0 +1,13 @@ +.blocks-radio-control { + display: flex; + flex-direction: column; +} + +.blocks-radio-control__option:not(:last-child) { + margin-bottom: 4px; +} + +.blocks-radio-control__input[type=radio] { + margin-top: 0; + margin-right: 6px; +} \ No newline at end of file diff --git a/blocks/inspector-controls/range-control/index.js b/blocks/inspector-controls/range-control/index.js index a596513fdd9ca0..ce6ced8f6f7b0c 100644 --- a/blocks/inspector-controls/range-control/index.js +++ b/blocks/inspector-controls/range-control/index.js @@ -6,17 +6,17 @@ import { withInstanceId } from 'components'; /** * Internal dependencies */ +import BaseControl from './../base-control'; import './style.scss'; function RangeControl( { label, value, instanceId, onChange, ...props } ) { const id = 'inspector-range-control-' + instanceId; return ( -
- + - { value } -
+ { value } + ); } diff --git a/blocks/inspector-controls/range-control/style.scss b/blocks/inspector-controls/range-control/style.scss index 81b946ecd9393c..af4fcd62796f35 100644 --- a/blocks/inspector-controls/range-control/style.scss +++ b/blocks/inspector-controls/range-control/style.scss @@ -1,9 +1,14 @@ .blocks-range-control { - margin-bottom: 10px; + display: flex; + justify-content: center; } -.blocks-range-control__label { - display: block; - font-weight: 500; - margin-bottom: 5px; +.blocks-range-control__input { + width: 100%; } + +.blocks-range-control__hint { + display: inline-block; + margin-left: 10px; + font-weight: 500; +} \ No newline at end of file diff --git a/blocks/inspector-controls/select-control/index.js b/blocks/inspector-controls/select-control/index.js new file mode 100644 index 00000000000000..b7e97b768a8d44 --- /dev/null +++ b/blocks/inspector-controls/select-control/index.js @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import { isEmpty } from 'lodash'; + +/** + * WordPress dependencies + */ +import { withInstanceId } from 'components'; + +/** + * Internal dependencies + */ +import BaseControl from './../base-control'; +import './style.scss'; + +function SelectControl( { label, selected, instanceId, onBlur, options = [], ...props } ) { + const id = 'inspector-select-control-' + instanceId; + const onBlurValue = ( event ) => onBlur( event.target.value ); + + return ! isEmpty( options ) && ( + + + + ); +} + +export default withInstanceId( SelectControl ); diff --git a/blocks/inspector-controls/select-control/style.scss b/blocks/inspector-controls/select-control/style.scss new file mode 100644 index 00000000000000..fbfa090c76f202 --- /dev/null +++ b/blocks/inspector-controls/select-control/style.scss @@ -0,0 +1,3 @@ +.blocks-select-control__input { + width: 100%; +} \ No newline at end of file diff --git a/blocks/inspector-controls/text-control/index.js b/blocks/inspector-controls/text-control/index.js index 4294e20c321f8f..2b9874dd03a307 100644 --- a/blocks/inspector-controls/text-control/index.js +++ b/blocks/inspector-controls/text-control/index.js @@ -6,6 +6,7 @@ import { withInstanceId } from 'components'; /** * Internal dependencies */ +import BaseControl from './../base-control'; import './style.scss'; function TextControl( { label, value, instanceId, onChange, type = 'text', ...props } ) { @@ -13,10 +14,9 @@ function TextControl( { label, value, instanceId, onChange, type = 'text', ...pr const onChangeValue = ( event ) => onChange( event.target.value ); return ( -
- + -
+ ); } diff --git a/blocks/inspector-controls/text-control/style.scss b/blocks/inspector-controls/text-control/style.scss index be49efd08ff5cd..f363338fada1b6 100644 --- a/blocks/inspector-controls/text-control/style.scss +++ b/blocks/inspector-controls/text-control/style.scss @@ -1,15 +1,4 @@ -.blocks-text-control { - margin-bottom: 10px; -} - -.blocks-text-control__label { - display: block; - font-weight: 500; - margin-bottom: 5px; -} - .blocks-text-control__input { width: 100%; - padding: 6px 10px; + padding: 6px 8px; } - diff --git a/blocks/inspector-controls/textarea-control/index.js b/blocks/inspector-controls/textarea-control/index.js new file mode 100644 index 00000000000000..3c01c2b0ba860b --- /dev/null +++ b/blocks/inspector-controls/textarea-control/index.js @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import { withInstanceId } from 'components'; + +/** + * Internal dependencies + */ +import BaseControl from './../base-control'; +import './style.scss'; + +function TextareaControl( { label, value, instanceId, onChange, rows = 4, ...props } ) { + const id = 'inspector-textarea-control-' + instanceId; + const onChangeValue = ( event ) => onChange( event.target.value ); + + return ( + + + + ); +} + +export default withInstanceId( TextareaControl ); diff --git a/blocks/inspector-controls/textarea-control/style.scss b/blocks/inspector-controls/textarea-control/style.scss new file mode 100644 index 00000000000000..8a646f39b6dc05 --- /dev/null +++ b/blocks/inspector-controls/textarea-control/style.scss @@ -0,0 +1,4 @@ +.blocks-textarea-control__input { + width: 100%; + padding: 6px 8px; +} diff --git a/blocks/inspector-controls/toggle-control/index.js b/blocks/inspector-controls/toggle-control/index.js new file mode 100644 index 00000000000000..45df64248dd474 --- /dev/null +++ b/blocks/inspector-controls/toggle-control/index.js @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import { withInstanceId, FormToggle } from 'components'; + +/** + * Internal dependencies + */ +import BaseControl from './../base-control'; +import './style.scss'; + +function ToggleControl( { label, checked, instanceId, onChange } ) { + const id = 'inspector-toggle-control-' + instanceId; + + return ( + + + + ); +} + +export default withInstanceId( ToggleControl ); diff --git a/blocks/inspector-controls/toggle-control/style.scss b/blocks/inspector-controls/toggle-control/style.scss new file mode 100644 index 00000000000000..56823361911d8f --- /dev/null +++ b/blocks/inspector-controls/toggle-control/style.scss @@ -0,0 +1,4 @@ +.blocks-toggle-control { + display: flex; + justify-content: space-between; +} \ No newline at end of file diff --git a/blocks/library/button/block.scss b/blocks/library/button/block.scss new file mode 100644 index 00000000000000..e504ca92e2c03f --- /dev/null +++ b/blocks/library/button/block.scss @@ -0,0 +1,30 @@ +$blocks-button__height: 46px; + +.wp-block-button { + font-family: $default-font; + display: inline-block; + text-decoration: none; + font-size: $big-font-size; + margin: 0; + padding: 0 24px; + height: $blocks-button__height; + line-height: $blocks-button__height; + cursor: default; + border-radius: $blocks-button__height / 2; + white-space: nowrap; + background: $blue-medium-400; + color: $white; + vertical-align: top; + position: relative; + + &:hover { + color: $white; + } + + .editable-format-toolbar__link-modal { + z-index: 2; + top: $blocks-button__height + 2px; + left: 50%; + transform: translateX( -50% ); + } +} diff --git a/blocks/library/button/index.js b/blocks/library/button/index.js index c4c0d0e43a9e73..2c110c31838e75 100644 --- a/blocks/library/button/index.js +++ b/blocks/library/button/index.js @@ -1,12 +1,14 @@ /** * WordPress dependencies */ +import { __ } from 'i18n'; import { IconButton } from 'components'; /** * Internal dependencies */ import './style.scss'; +import './block.scss'; import { registerBlockType, query } from '../../api'; import Editable from '../../editable'; import BlockControls from '../../block-controls'; @@ -15,7 +17,7 @@ import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { attr, children } = query; registerBlockType( 'core/button', { - title: wp.i18n.__( 'Button' ), + title: __( 'Button' ), icon: 'button', @@ -34,7 +36,7 @@ registerBlockType( 'core/button', { } }, - edit( { attributes, setAttributes, focus, setFocus } ) { + edit( { attributes, setAttributes, focus, setFocus, className } ) { const { text, url, title, align } = attributes; const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); @@ -44,16 +46,15 @@ registerBlockType( 'core/button', { ), - + setAttributes( { text: value } ) } inline - inlineToolbar formattingControls={ [ 'bold', 'italic', 'strikethrough' ] } /> { focus && @@ -66,7 +67,7 @@ registerBlockType( 'core/button', { required value={ url } onChange={ ( event ) => setAttributes( { url: event.target.value } ) } - placeholder={ wp.i18n.__( 'Paste URL or type' ) } + placeholder={ __( 'Paste URL or type' ) } /> diff --git a/blocks/library/button/style.scss b/blocks/library/button/style.scss index f5499a0103dd48..d2efc56066873c 100644 --- a/blocks/library/button/style.scss +++ b/blocks/library/button/style.scss @@ -1,34 +1,3 @@ -$blocks-button__height: 46px; - -.blocks-button { - font-family: $default-font; - display: inline-block; - text-decoration: none; - font-size: $big-font-size; - margin: 0; - padding: 0 24px; - height: $blocks-button__height; - line-height: $blocks-button__height; - cursor: default; - border-radius: $blocks-button__height / 2; - white-space: nowrap; - background: $blue-medium-400; - color: $white; - vertical-align: top; - position: relative; - - &:hover { - color: $white; - } - - .editable-format-toolbar__link-modal { - z-index: 2; - top: $blocks-button__height + 2px; - left: 50%; - transform: translateX( -50% ); - } -} - .editor-visual-editor__block[data-type="core/button"] { &[data-align="center"] { text-align: center; diff --git a/blocks/library/code/index.js b/blocks/library/code/index.js index 2085ae7e7e3a65..4d34e6e1b6619a 100644 --- a/blocks/library/code/index.js +++ b/blocks/library/code/index.js @@ -3,6 +3,11 @@ */ import TextareaAutosize from 'react-autosize-textarea'; +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; + /** * Internal dependencies */ @@ -12,7 +17,7 @@ import { registerBlockType, query } from '../../api'; const { prop } = query; registerBlockType( 'core/code', { - title: wp.i18n.__( 'Code' ), + title: __( 'Code' ), icon: 'editor-code', @@ -22,11 +27,13 @@ registerBlockType( 'core/code', { content: prop( 'code', 'textContent' ), }, - edit( { attributes, setAttributes } ) { + edit( { attributes, setAttributes, className } ) { return ( setAttributes( { content: event.target.value } ) } + placeholder={ __( 'Write code…' ) } /> ); }, diff --git a/blocks/library/code/style.scss b/blocks/library/code/style.scss index 632554fa93a687..980481fb175d71 100644 --- a/blocks/library/code/style.scss +++ b/blocks/library/code/style.scss @@ -12,3 +12,57 @@ div[data-type="core/code"] { width: 100%; } } + +// We should extract this to a separate components-toolbar +.components-tab-button { + display: inline-flex; + align-items: flex-end; + margin: 0; + padding: 3px; + background: none; + outline: none; + color: $dark-gray-500; + cursor: pointer; + position: relative; + height: $icon-button-size; + font-family: $default-font; + font-size: $default-font-size; + font-weight: 500; + border: 0; + + &.is-active, + &.is-active:hover { + color: $white; + } + + &:disabled { + cursor: default; + } + + &> span { + border: 1px solid transparent; + padding: 0 6px; + box-sizing: content-box; + height: 28px; + line-height: 28px; + } + + &:hover > span, + &:focus > span { + color: $dark-gray-500; + } + + &:not(:disabled) { + &.is-active > span, + &:hover > span, + &:focus > span { + border: 1px solid $dark-gray-500; + } + } + + &.is-active > span, + &.is-active:hover > span { + background-color: $dark-gray-500; + color: $white; + } +} diff --git a/blocks/library/cover-image/block.scss b/blocks/library/cover-image/block.scss new file mode 100644 index 00000000000000..e761ddea3c3af4 --- /dev/null +++ b/blocks/library/cover-image/block.scss @@ -0,0 +1,37 @@ +.wp-block-cover-image { + margin: 0; + position: relative; + + h2 { + color: white; + font-size: 24pt; + line-height: 1em; + z-index: 1; + max-width: $visual-editor-max-width; + padding: $block-padding; + text-align: center; + } + + .cover-image { + background-size: cover; + height: 430px; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + .has-parallax { + background-attachment: fixed; + } + + .has-background-dim.cover-image:before { + content: ''; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: rgba( 0,0,0,.5 ); + } +} diff --git a/blocks/library/cover-image/index.js b/blocks/library/cover-image/index.js new file mode 100644 index 00000000000000..fccc30736cd3f6 --- /dev/null +++ b/blocks/library/cover-image/index.js @@ -0,0 +1,163 @@ +/** + * WordPress dependencies + */ +import { Placeholder, Toolbar, Dashicon } from 'components'; +import { __ } from 'i18n'; +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import './style.scss'; +import './block.scss'; +import { registerBlockType, query } from '../../api'; +import Editable from '../../editable'; +import MediaUploadButton from '../../media-upload-button'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; +import InspectorControls from '../../inspector-controls'; +import ToggleControl from '../../inspector-controls/toggle-control'; +import BlockDescription from '../../block-description'; + +const { text } = query; + +const validAlignments = [ 'left', 'center', 'right', 'wide', 'full' ]; + +registerBlockType( 'core/cover-image', { + title: __( 'Cover Image' ), + + icon: 'format-image', + + category: 'common', + + attributes: { + title: text( 'h2' ), + }, + + getEditWrapperProps( attributes ) { + const { align } = attributes; + if ( -1 !== validAlignments.indexOf( align ) ) { + return { 'data-align': align }; + } + }, + + edit( { attributes, setAttributes, focus, setFocus, className } ) { + const { url, title, align, id, hasParallax, hasBackgroundDim = true } = attributes; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + const onSelectImage = ( media ) => setAttributes( { url: media.url, id: media.id } ); + + const controls = ( + focus && ( + + + + +
  • + + + +
  • +
    +
    + ) + ); + + if ( ! url ) { + const uploadButtonProps = { isLarge: true }; + return [ + controls, + + + { __( 'Insert from Media Library' ) } + + , + ]; + } + + const style = { backgroundImage: `url(${ url })` }; + const sectionClasses = classnames( { + 'cover-image': true, + 'has-parallax': hasParallax, + 'has-background-dim': hasBackgroundDim, + } ); + const toggleParallax = () => setAttributes( { hasParallax: ! hasParallax } ); + const toggleBackgroundDim = () => setAttributes( { hasBackgroundDim: ! hasBackgroundDim } ); + + return [ + controls, + focus && ( + + +

    { __( 'Cover Image is a bold image block with an optional title.' ) }

    +
    +

    { __( 'Cover Image Settings' ) }

    + + +
    + ), +
    +
    + { title || !! focus ? ( + setAttributes( { title: value } ) } + inline + inlineToolbar + /> + ) : null } +
    +
    , + ]; + }, + + save( { attributes } ) { + const { url, title, hasParallax, hasBackgroundDim } = attributes; + const style = { + backgroundImage: `url(${ url })`, + }; + const sectionClasses = classnames( { + 'cover-image': true, + 'has-parallax': hasParallax, + 'has-background-dim': hasBackgroundDim, + } ); + + return ( +
    +
    +

    { title }

    +
    +
    + ); + }, +} ); diff --git a/blocks/library/cover-image/style.scss b/blocks/library/cover-image/style.scss new file mode 100644 index 00000000000000..6823a5090a74c0 --- /dev/null +++ b/blocks/library/cover-image/style.scss @@ -0,0 +1,64 @@ +.editor-visual-editor__block[data-type="core/cover-image"] { + .blocks-editable__tinymce[data-is-empty="true"]:before { + position: inherit; + } + + .wp-block-cover-image { + margin: 0; + + h2 { + color: white; + font-size: 24pt; + line-height: 1em; + max-width: $visual-editor-max-width; + padding: $block-padding; + text-align: center; + } + } + + .cover-image { + background-size: cover; + height: 430px; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + .has-parallax { + background-attachment: fixed; + } + + .cover-image.has-background-dim::before { + content: ''; + position: absolute; + top: 0; + right: $block-padding * 2 + $block-mover-margin; + bottom: 0; + left: $block-padding * 2 + $block-mover-margin; + background: rgba( 0,0,0,.5 ); + } + + &[data-align="full"] .cover-image::before { + right: 0; + left: 0; + } +} + +.cover-image { + .blocks-editable__tinymce a { + color: white; + } + + .blocks-editable__tinymce:focus a[data-mce-selected] { + padding: 0 2px; + margin: 0 -2px; + border-radius: 2px; + box-shadow: none; + background: rgba( 255, 255, 255, 0.3 ); + } + + .blocks-editable strong { + font-weight: 300; + } +} diff --git a/blocks/library/embed/index.js b/blocks/library/embed/index.js index 22a4fb98bd6ebc..3c276048b68df4 100644 --- a/blocks/library/embed/index.js +++ b/blocks/library/embed/index.js @@ -7,7 +7,9 @@ import { includes } from 'lodash'; /** * WordPress dependencies */ -import { Button, Placeholder, HtmlEmbed, Spinner } from 'components'; +import { __, sprintf } from 'i18n'; +import { Component } from 'element'; +import { Button, Placeholder, Spinner, SandBox } from 'components'; /** * Internal dependencies @@ -20,11 +22,12 @@ import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { attr, children } = query; +// These embeds do not work in sandboxes const HOSTS_NO_PREVIEWS = [ 'facebook.com' ]; function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { return { - title: wp.i18n.__( title ), + title: __( title ), icon, @@ -42,7 +45,7 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { } }, - edit: class extends wp.element.Component { + edit: class extends Component { constructor() { super( ...arguments ); this.doServerSideRender = this.doServerSideRender.bind( this ); @@ -69,6 +72,13 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { this.unmounting = true; } + getPhotoHtml( photo ) { + // 100% width for the preview so it fits nicely into the document, some "thumbnails" are + // acually the full size photo. + const photoPreview =

    {

    ; + return wp.element.renderToString( photoPreview ); + } + doServerSideRender( event ) { if ( event ) { event.preventDefault(); @@ -88,6 +98,8 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { const { html, type } = obj; if ( html ) { this.setState( { html, type } ); + } else if ( 'photo' === type ) { + this.setState( { html: this.getPhotoHtml( obj ), type } ); } else { this.setState( { error: true } ); } @@ -118,30 +130,33 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { if ( fetching ) { return [ controls, -
    +
    -

    { wp.i18n.__( 'Embedding…' ) }

    +

    { __( 'Embedding…' ) }

    , ]; } if ( ! html ) { + const label = sprintf( __( '%s URL' ), title ); + return [ controls, - +
    setAttributes( { url: event.target.value } ) } /> - { error &&

    { wp.i18n.__( 'Sorry, we could not embed that content.' ) }

    } + { error &&

    { __( 'Sorry, we could not embed that content.' ) }

    }
    , ]; @@ -149,27 +164,27 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { const parsedUrl = parse( url ); const cannotPreview = includes( HOSTS_NO_PREVIEWS, parsedUrl.host.replace( /^www\./, '' ) ); - let typeClassName = 'blocks-embed'; - + const iframeTitle = 'Embedded content from ' + parsedUrl.host; + let typeClassName = 'wp-block-embed'; if ( 'video' === type ) { - typeClassName = 'blocks-embed-video'; + typeClassName += ' is-video'; } return [ controls,
    { ( cannotPreview ) ? ( - +

    { url }

    -

    { wp.i18n.__( 'Previews for this are unavailable in the editor, sorry!' ) }

    +

    { __( 'Previews for this are unavailable in the editor, sorry!' ) }

    ) : ( - + ) } { ( caption && caption.length > 0 ) || !! focus ? ( { '\n' } +
    { '\n' } { url }
    { caption }
    @@ -199,38 +214,247 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { }; } -registerBlockType( 'core/embed', getEmbedBlockSettings( { title: 'Embed', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedanimoto', getEmbedBlockSettings( { title: 'Animoto', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedcloudup', getEmbedBlockSettings( { title: 'Cloudup', icon: 'cloud' } ) ); -registerBlockType( 'core/embedcollegehumor', getEmbedBlockSettings( { title: 'CollegeHumor', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embeddailymotion', getEmbedBlockSettings( { title: 'Dailymotion', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedfacebook', getEmbedBlockSettings( { title: 'Facebook', icon: 'facebook' } ) ); -registerBlockType( 'core/embedflickr', getEmbedBlockSettings( { title: 'Flickr', icon: 'format-image' } ) ); -registerBlockType( 'core/embedfunnyordie', getEmbedBlockSettings( { title: 'Funny or Die', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedhulu', getEmbedBlockSettings( { title: 'Hulu', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedimgur', getEmbedBlockSettings( { title: 'Imgur', icon: 'format-image' } ) ); -registerBlockType( 'core/embedinstagram', getEmbedBlockSettings( { title: 'Instagram', icon: 'camera' } ) ); -registerBlockType( 'core/embedissuu', getEmbedBlockSettings( { title: 'Issuu', icon: 'media-default' } ) ); -registerBlockType( 'core/embedkickstarter', getEmbedBlockSettings( { title: 'Kickstarter', icon: 'lightbulb' } ) ); -registerBlockType( 'core/embedmeetupcom', getEmbedBlockSettings( { title: 'Meetup.com', icon: 'location-alt' } ) ); -registerBlockType( 'core/embedmixcloud', getEmbedBlockSettings( { title: 'Mixcloud', icon: 'format-audio' } ) ); -registerBlockType( 'core/embedphotobucket', getEmbedBlockSettings( { title: 'Photobucket', icon: 'camera' } ) ); -registerBlockType( 'core/embedpolldaddy', getEmbedBlockSettings( { title: 'Polldaddy', icon: 'yes' } ) ); -registerBlockType( 'core/embedreddit', getEmbedBlockSettings( { title: 'Reddit', icon: 'share' } ) ); -registerBlockType( 'core/embedreverbnation', getEmbedBlockSettings( { title: 'ReverbNation', icon: 'format-audio' } ) ); -registerBlockType( 'core/embedscreencast', getEmbedBlockSettings( { title: 'Screencast', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedscribd', getEmbedBlockSettings( { title: 'Scribd', icon: 'book-alt' } ) ); -registerBlockType( 'core/embedslideshare', getEmbedBlockSettings( { title: 'Slideshare', icon: 'slides' } ) ); -registerBlockType( 'core/embedsmugmug', getEmbedBlockSettings( { title: 'SmugMug', icon: 'camera' } ) ); -registerBlockType( 'core/embedsoundcloud', getEmbedBlockSettings( { title: 'SoundCloud', icon: 'format-audio' } ) ); -registerBlockType( 'core/embedspeaker', getEmbedBlockSettings( { title: 'Speaker', icon: 'format-audio' } ) ); -registerBlockType( 'core/embedspotify', getEmbedBlockSettings( { title: 'Spotify', icon: 'format-audio' } ) ); -registerBlockType( 'core/embedted', getEmbedBlockSettings( { title: 'TED', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedtumblr', getEmbedBlockSettings( { title: 'Tumblr', icon: 'share' } ) ); -registerBlockType( 'core/embedtwitter', getEmbedBlockSettings( { title: 'Twitter', icon: 'twitter' } ) ); -registerBlockType( 'core/embedvideopress', getEmbedBlockSettings( { title: 'VideoPress', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedvimeo', getEmbedBlockSettings( { title: 'Vimeo', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedvine', getEmbedBlockSettings( { title: 'Vine', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedwordpress', getEmbedBlockSettings( { title: 'WordPress', icon: 'wordpress' } ) ); -registerBlockType( 'core/embedwordpresstv', getEmbedBlockSettings( { title: 'WordPress.tv', icon: 'video-alt3' } ) ); -registerBlockType( 'core/embedyoutube', getEmbedBlockSettings( { title: 'YouTube', icon: 'video-alt3' } ) ); +registerBlockType( + 'core/embed', + getEmbedBlockSettings( { + title: 'Embed', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/animoto', + getEmbedBlockSettings( { + title: 'Animoto', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/cloudup', + getEmbedBlockSettings( { + title: 'Cloudup', + icon: 'cloud', + } ) +); +registerBlockType( + 'core-embed/collegehumor', + getEmbedBlockSettings( { + title: 'CollegeHumor', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/dailymotion', + getEmbedBlockSettings( { + title: 'Dailymotion', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/facebook', + getEmbedBlockSettings( { + title: 'Facebook', + icon: 'facebook', + } ) +); +registerBlockType( + 'core-embed/flickr', + getEmbedBlockSettings( { + title: 'Flickr', + icon: 'format-image', + } ) +); +registerBlockType( + 'core-embed/funnyordie', + getEmbedBlockSettings( { + title: 'Funny or Die', + icon: 'video-alt3', + } ) ); +registerBlockType( + 'core-embed/hulu', + getEmbedBlockSettings( { + title: 'Hulu', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/imgur', + getEmbedBlockSettings( { + title: 'Imgur', + icon: 'format-image', + } ) +); +registerBlockType( + 'core-embed/instagram', + getEmbedBlockSettings( { + title: 'Instagram', + icon: 'camera', + } ) +); +registerBlockType( + 'core-embed/issuu', + getEmbedBlockSettings( { + title: 'Issuu', + icon: 'media-default', + } ) +); +registerBlockType( + 'core-embed/kickstarter', + getEmbedBlockSettings( { + title: 'Kickstarter', + icon: 'lightbulb', + } ) +); +registerBlockType( + 'core-embed/meetup-com', + getEmbedBlockSettings( { + title: 'Meetup.com', + icon: 'location-alt', + } ) +); +registerBlockType( + 'core-embed/mixcloud', + getEmbedBlockSettings( { + title: 'Mixcloud', + icon: 'format-audio', + } ) +); +registerBlockType( + 'core-embed/photobucket', + getEmbedBlockSettings( { + title: 'Photobucket', + icon: 'camera', + } ) +); +registerBlockType( + 'core-embed/polldaddy', + getEmbedBlockSettings( { + title: 'Polldaddy', + icon: 'yes', + } ) +); +registerBlockType( + 'core-embed/reddit', + getEmbedBlockSettings( { + title: 'Reddit', + icon: 'share', + } ) +); +registerBlockType( + 'core-embed/reverbnation', + getEmbedBlockSettings( { + title: 'ReverbNation', + icon: 'format-audio', + } ) +); +registerBlockType( + 'core-embed/screencast', + getEmbedBlockSettings( { + title: 'Screencast', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/scribd', + getEmbedBlockSettings( { + title: 'Scribd', + icon: 'book-alt', + } ) +); +registerBlockType( + 'core-embed/slideshare', + getEmbedBlockSettings( { + title: 'Slideshare', + icon: 'slides', + } ) +); +registerBlockType( + 'core-embed/smugmug', + getEmbedBlockSettings( { + title: 'SmugMug', + icon: 'camera', + } ) +); +registerBlockType( + 'core-embed/soundcloud', + getEmbedBlockSettings( { + title: 'SoundCloud', + icon: 'format-audio', + } ) +); +registerBlockType( + 'core-embed/speaker', + getEmbedBlockSettings( { + title: 'Speaker', + icon: 'format-audio', + } ) +); +registerBlockType( + 'core-embed/spotify', + getEmbedBlockSettings( { + title: 'Spotify', + icon: 'format-audio', + } ) +); +registerBlockType( + 'core-embed/ted', + getEmbedBlockSettings( { + title: 'TED', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/tumblr', + getEmbedBlockSettings( { + title: 'Tumblr', + icon: 'share', + } ) +); +registerBlockType( + 'core-embed/twitter', + getEmbedBlockSettings( { + title: 'Twitter', + icon: 'twitter', + } ) +); +registerBlockType( + 'core-embed/videopress', + getEmbedBlockSettings( { + title: 'VideoPress', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/vimeo', + getEmbedBlockSettings( { + title: 'Vimeo', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/vine', + getEmbedBlockSettings( { + title: 'Vine', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/wordpress', + getEmbedBlockSettings( { + title: 'WordPress', + icon: 'wordpress', + } ) +); +registerBlockType( + 'core-embed/wordpress-tv', + getEmbedBlockSettings( { + title: 'WordPress.tv', + icon: 'video-alt3', + } ) +); +registerBlockType( + 'core-embed/youtube', + getEmbedBlockSettings( { + title: 'YouTube', + icon: 'video-alt3', + } ) +); diff --git a/blocks/library/embed/style.scss b/blocks/library/embed/style.scss index f35c8f90fae3fb..f238164fcded7e 100644 --- a/blocks/library/embed/style.scss +++ b/blocks/library/embed/style.scss @@ -1,5 +1,4 @@ -.blocks-embed, -.blocks-embed-video { +.wp-block-embed { margin: 0; clear: both; // necessary because we use responsive trickery to set width/height, and therefore the video doesn't intrinsically clear floats like an img does @@ -17,19 +16,19 @@ font-size: $default-font-size; } } -} -.blocks-embed-video > div:first-child { - position: relative; - width: 100%; - height: 0; - padding-bottom: 56.25%; /* 16:9 */ -} + &.is-video > div:first-child { + position: relative; + width: 100%; + height: 0; + padding-bottom: 56.25%; /* 16:9 */ + } -.blocks-embed-video > div > iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; + &.is-video > div > iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } } diff --git a/blocks/library/freeform/format-list.js b/blocks/library/freeform/format-list.js index e372392436d72c..f71b12aedf5ea9 100644 --- a/blocks/library/freeform/format-list.js +++ b/blocks/library/freeform/format-list.js @@ -8,6 +8,7 @@ import { camelCase, fromPairs, omit } from 'lodash'; /** * WordPress dependencies */ +import { Component } from 'element'; import { Button, Dashicon } from 'components'; /** @@ -27,7 +28,7 @@ export function naiveCss2Jsx( styleText ) { ); } -class FormatList extends wp.element.Component { +class FormatList extends Component { constructor() { super( ...arguments ); this.switchFormat = this.switchFormat.bind( this ); diff --git a/blocks/library/freeform/freeform-block.js b/blocks/library/freeform/freeform-block.js index 9d4ea919471213..fe1f5ef6f9ad08 100644 --- a/blocks/library/freeform/freeform-block.js +++ b/blocks/library/freeform/freeform-block.js @@ -3,19 +3,23 @@ */ import classnames from 'classnames'; import { nodeListToReact } from 'dom-react'; -import { findDOMNode } from 'element'; import 'element-closest'; import { concat, find, flatten, isEqual, omitBy, throttle } from 'lodash'; +/** + * WordPress dependencies + */ +import { Component, createElement, renderToString, findDOMNode } from 'element'; +import { __ } from 'i18n'; +import { Toolbar } from 'components'; + /** * Internal dependencies */ import './freeform-block.scss'; -import { __ } from 'i18n'; import TinyMCE from '../../editable/tinymce'; import BlockControls from '../../block-controls'; import FormatList from './format-list'; -import { Toolbar } from 'components'; const BLOCK_CONTROLS_SELECTOR = '.editor-visual-editor__block-controls'; @@ -88,7 +92,7 @@ const MORE_CONTROLS = [ const MORE_DRAWER_HEIGHT = 40; -function createElement( type, props, ...children ) { +function createTinyMCEElement( type, props, ...children ) { if ( props[ 'data-mce-bogus' ] === 'all' ) { return null; } @@ -97,14 +101,14 @@ function createElement( type, props, ...children ) { return children; } - return wp.element.createElement( + return createElement( type, omitBy( props, ( value, key ) => key.indexOf( 'data-mce-' ) === 0 ), ...children ); } -export default class FreeformBlock extends wp.element.Component { +export default class FreeformBlock extends Component { constructor( props ) { super( ...arguments ); this.getSettings = this.getSettings.bind( this ); @@ -323,12 +327,12 @@ export default class FreeformBlock extends wp.element.Component { content = ''; } - content = wp.element.renderToString( content ); + content = renderToString( content ); this.editor.setContent( content, { format: 'raw' } ); } getContent() { - return nodeListToReact( this.editor.getBody().childNodes || [], createElement ); + return nodeListToReact( this.editor.getBody().childNodes || [], createTinyMCEElement ); } mapControls( controls ) { @@ -372,7 +376,7 @@ export default class FreeformBlock extends wp.element.Component { } render() { - const { content, focus } = this.props; + const { content, focus, className } = this.props; const { expandDown, showMore } = this.state; const moreDrawerClasses = classnames( 'more-drawer', expandDown ? 'down' : 'up' ); return [ @@ -401,6 +405,7 @@ export default class FreeformBlock extends wp.element.Component { , , }, - edit( { attributes, setAttributes, focus, setFocus } ) { + edit( { attributes, setAttributes, focus, setFocus, className } ) { const { content } = attributes; return ( { setAttributes( { diff --git a/blocks/library/gallery/block.scss b/blocks/library/gallery/block.scss new file mode 100644 index 00000000000000..beffdefd70155b --- /dev/null +++ b/blocks/library/gallery/block.scss @@ -0,0 +1,58 @@ +.wp-block-gallery { + display: flex; + flex-wrap: wrap; + + &:not( .components-placeholder ) { + margin-right: -16px; + margin-bottom: -16px; + } + + .blocks-gallery-image { + flex-grow: 1; + margin: 0 16px 16px 0; + + img { + max-width: 100%; + } + } + + // Cropped + &.is-cropped .blocks-gallery-image { + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + // Alas, IE11+ doesn't support object-fit + _:-ms-lang(x), img { + height: auto; + width: auto; + } + } + + &.columns-1 figure { + width: calc(100% / 1 - 2 * 8px); + } + &.columns-2 figure { + width: calc(100% / 2 - 3 * 8px); + } + &.columns-3 figure { + width: calc(100% / 3 - 4 * 8px); + } + &.columns-4 figure { + width: calc(100% / 4 - 5 * 8px); + } + &.columns-5 figure { + width: calc(100% / 5 - 6 * 8px); + } + &.columns-6 figure { + width: calc(100% / 6 - 7 * 8px); + } + &.columns-7 figure { + width: calc(100% / 7 - 8 * 8px); + } + &.columns-8 figure { + width: calc(100% / 8 - 9 * 8px); + } +} diff --git a/blocks/library/gallery/index.js b/blocks/library/gallery/index.js index 3de6361aafd436..8089448df38bbb 100644 --- a/blocks/library/gallery/index.js +++ b/blocks/library/gallery/index.js @@ -1,32 +1,33 @@ /** - * Internal dependencies + * WordPress dependencies */ import { __ } from 'i18n'; -import './style.scss'; -import { registerBlockType, query as hpq } from '../../api'; -import { Fill } from 'react-slot-fill'; +import { Toolbar, Placeholder } from 'components'; +import { pick } from 'lodash'; /** - * WordPress dependencies + * Internal dependencies */ -import { Toolbar, Placeholder } from 'components'; - +import './style.scss'; +import './block.scss'; +import { registerBlockType } from '../../api'; import MediaUploadButton from '../../media-upload-button'; import InspectorControls from '../../inspector-controls'; import RangeControl from '../../inspector-controls/range-control'; - +import ToggleControl from '../../inspector-controls/toggle-control'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; import GalleryImage from './gallery-image'; - -const { query, attr } = hpq; +import BlockDescription from '../../block-description'; const MAX_COLUMNS = 8; const editMediaLibrary = ( attributes, setAttributes ) => { const frameConfig = { frame: 'post', - title: wp.i18n.__( 'Update Gallery media' ), + title: __( 'Update Gallery media' ), button: { - text: wp.i18n.__( 'Select' ), + text: __( 'Select' ), }, multiple: true, state: 'gallery-edit', @@ -47,19 +48,12 @@ const editMediaLibrary = ( attributes, setAttributes ) => { editFrame.open( 'gutenberg-gallery' ); }; -/** - * Returns an attribute setter with behavior that if the target value is - * already the assigned attribute value, it will be set to undefined. - * - * @param {string} align Alignment value - * @return {Function} Attribute setter - */ -function toggleAlignment( align ) { - return ( attributes, setAttributes ) => { - const nextAlign = attributes.align === align ? undefined : align; - setAttributes( { align: nextAlign } ); - }; -} +// the media library image object contains numerous attributes +// we only need this set to display the image in the library +const slimImageObjects = ( imgs ) => { + const attrSet = [ 'sizes', 'mime', 'type', 'subtype', 'id', 'url', 'alt' ]; + return imgs.map( ( img ) => pick( img, attrSet ) ); +}; function defaultColumnsNumber( attributes ) { attributes.images = attributes.images || []; @@ -67,51 +61,10 @@ function defaultColumnsNumber( attributes ) { } registerBlockType( 'core/gallery', { - title: wp.i18n.__( 'Gallery' ), + title: __( 'Gallery' ), icon: 'format-gallery', category: 'common', - attributes: { - images: - query( 'div.blocks-gallery figure.blocks-gallery-image img', { - url: attr( 'src' ), - alt: attr( 'alt' ), - } ) || [], - }, - - controls: [ - { - icon: 'align-left', - title: wp.i18n.__( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: toggleAlignment( 'left' ), - }, - { - icon: 'align-center', - title: wp.i18n.__( 'Align center' ), - isActive: ( { align } ) => ! align || 'center' === align, - onClick: toggleAlignment( 'center' ), - }, - { - icon: 'align-right', - title: wp.i18n.__( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: toggleAlignment( 'right' ), - }, - { - icon: 'align-wide', - title: __( 'Wide width' ), - isActive: ( { align } ) => 'wide' === align, - onClick: toggleAlignment( 'wide' ), - }, - { - icon: 'align-full-width', - title: __( 'Full width' ), - isActive: ( { align } ) => 'full' === align, - onClick: toggleAlignment( 'full' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'wide' === align || 'full' === align ) { @@ -119,53 +72,91 @@ registerBlockType( 'core/gallery', { } }, - edit( { attributes, setAttributes, focus } ) { + edit( { attributes, setAttributes, focus, className } ) { const { images = [], columns = defaultColumnsNumber( attributes ), align = 'none' } = attributes; const setColumnsNumber = ( event ) => setAttributes( { columns: event.target.value } ); + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + const { imageCrop = true } = attributes; + const toggleImageCrop = () => setAttributes( { imageCrop: ! imageCrop } ); + + const controls = ( + focus && ( + + + { !! images.length && ( + editMediaLibrary( attributes, setAttributes ), + } ] } /> + ) } + + ) + ); + if ( images.length === 0 ) { - const setMediaUrl = ( imgs ) => setAttributes( { images: imgs } ); - return ( + const setMediaUrl = ( imgs ) => setAttributes( { images: slimImageObjects( imgs ) } ); + const uploadButtonProps = { isLarge: true }; + + return [ + controls, + label={ __( 'Gallery' ) } + className={ className }> - { wp.i18n.__( 'Insert from Media Library' ) } + { __( 'Insert from Media Library' ) } - - ); +
    , + ]; } - return ( -
    - - editMediaLibrary( attributes, setAttributes ), - } ] } /> - + return [ + controls, + focus && images.length > 1 && ( + + +

    { __( 'Image galleries are a great way to share groups of pictures on your site.' ) }

    +
    +

    { __( 'Gallery Settings' ) }

    + + +
    + ), +
    { images.map( ( img ) => ( ) ) } - { focus && images.length > 1 && - - - } -
    - ); +
    , + ]; }, save( { attributes } ) { - const { images, columns = defaultColumnsNumber( attributes ), align = 'none' } = attributes; + const { images, columns = defaultColumnsNumber( attributes ), align = 'none', imageCrop = true } = attributes; return ( -
    +
    { images.map( ( img ) => ( ) ) } diff --git a/blocks/library/gallery/style.scss b/blocks/library/gallery/style.scss index 709eeee2fa604c..79ba13dfe958fe 100644 --- a/blocks/library/gallery/style.scss +++ b/blocks/library/gallery/style.scss @@ -1,44 +1,4 @@ - -.blocks-gallery { - display: flex; - flex-wrap: wrap; - - .blocks-gallery-image { - flex-grow: 1; - margin: 8px; - - img { - max-width: 100%; - } - } - - &.columns-1 figure { - width: calc(100% / 1 - 2 * 8px); - } - &.columns-2 figure { - width: calc(100% / 2 - 3 * 8px); - } - &.columns-3 figure { - width: calc(100% / 3 - 4 * 8px); - } - &.columns-4 figure { - width: calc(100% / 4 - 5 * 8px); - } - &.columns-5 figure { - width: calc(100% / 5 - 6 * 8px); - } - &.columns-6 figure { - width: calc(100% / 6 - 7 * 8px); - } - &.columns-7 figure { - width: calc(100% / 7 - 8 * 8px); - } - &.columns-8 figure { - width: calc(100% / 8 - 9 * 8px); - } -} - -.blocks-gallery.is-placeholder { +.wp-block-gallery.is-placeholder { margin: -15px; padding: 6em 0; border: 2px solid $light-gray-500; diff --git a/blocks/library/heading/index.js b/blocks/library/heading/index.js index f586810c4df9f5..ad64a8abeb6f98 100644 --- a/blocks/library/heading/index.js +++ b/blocks/library/heading/index.js @@ -1,7 +1,14 @@ /** * External dependencies */ -import { isString } from 'lodash'; +import { isObject } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __, sprintf } from 'i18n'; +import { concatChildren } from 'element'; +import { Toolbar } from 'components'; /** * Internal dependencies @@ -10,16 +17,21 @@ import './style.scss'; import { registerBlockType, createBlock, query } from '../../api'; import Editable from '../../editable'; import BlockControls from '../../block-controls'; +import InspectorControls from '../../inspector-controls'; +import AlignmentToolbar from '../../alignment-toolbar'; +import BlockDescription from '../../block-description'; const { children, prop } = query; registerBlockType( 'core/heading', { - title: wp.i18n.__( 'Heading' ), + title: __( 'Heading' ), icon: 'heading', category: 'common', + className: false, + attributes: { content: children( 'h1,h2,h3,h4,h5,h6' ), nodeName: prop( 'h1,h2,h3,h4,h5,h6', 'nodeName' ), @@ -31,10 +43,11 @@ registerBlockType( 'core/heading', { type: 'block', blocks: [ 'core/text' ], transform: ( { content, ...attrs } ) => { - if ( Array.isArray( content ) ) { - const headingContent = isString( content[ 0 ] ) - ? content[ 0 ] - : content[ 0 ].props.children; + const isMultiParagraph = Array.isArray( content ) && isObject( content[ 0 ] ) && content[ 0 ].type === 'p'; + if ( isMultiParagraph ) { + const headingContent = isObject( content[ 0 ] ) && content[ 0 ].type === 'p' + ? content[ 0 ].props.children + : content[ 0 ]; const heading = createBlock( 'core/heading', { content: headingContent, } ); @@ -72,21 +85,21 @@ registerBlockType( 'core/heading', { merge( attributes, attributesToMerge ) { return { - content: wp.element.concatChildren( attributes.content, attributesToMerge.content ), + content: concatChildren( attributes.content, attributesToMerge.content ), }; }, edit( { attributes, setAttributes, focus, setFocus, mergeBlocks, insertBlockAfter } ) { - const { content, nodeName = 'H2' } = attributes; + const { align, content, nodeName = 'H2' } = attributes; return [ focus && ( ( { + '234'.split( '' ).map( ( level ) => ( { icon: 'heading', - title: wp.i18n.sprintf( wp.i18n.__( 'Heading %s' ), level ), + title: sprintf( __( 'Heading %s' ), level ), isActive: 'H' + level === nodeName, onClick: () => setAttributes( { nodeName: 'H' + level } ), subscript: level, @@ -94,6 +107,33 @@ registerBlockType( 'core/heading', { } /> ), + focus && ( + + +

    { __( 'Search engines use the headings to index the structure and content of your web pages.' ) }

    +
    +

    { __( 'Heading Settings' ) }

    +

    { __( 'Size' ) }

    + ( { + icon: 'heading', + title: sprintf( __( 'Heading %s' ), level ), + isActive: 'H' + level === nodeName, + onClick: () => setAttributes( { nodeName: 'H' + level } ), + subscript: level, + } ) ) + } + /> +

    { __( 'Text Alignment' ) }

    + { + setAttributes( { align: nextAlign } ); + } } + /> +
    + ), , ]; }, save( { attributes } ) { - const { nodeName = 'H2', content } = attributes; + const { align, nodeName = 'H2', content } = attributes; const Tag = nodeName.toLowerCase(); return ( - + { content } ); diff --git a/blocks/library/html/index.js b/blocks/library/html/index.js new file mode 100644 index 00000000000000..7d869fd30e258e --- /dev/null +++ b/blocks/library/html/index.js @@ -0,0 +1,89 @@ +/** + * External dependencies + */ +import TextareaAutosize from 'react-autosize-textarea'; + +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; +import { Component } from 'element'; + +/** + * Internal dependencies + */ +import './style.scss'; +import { registerBlockType, query } from '../../api'; +import BlockControls from '../../block-controls'; + +const { html } = query; + +registerBlockType( 'core/html', { + title: __( 'Custom HTML' ), + + icon: 'html', + + category: 'formatting', + + className: false, + + attributes: { + content: html(), + }, + + edit: class extends Component { + constructor() { + super( ...arguments ); + this.preview = this.preview.bind( this ); + this.edit = this.edit.bind( this ); + this.state = { + preview: false, + }; + } + + preview() { + this.setState( { preview: true } ); + } + + edit() { + this.setState( { preview: false } ); + } + + render() { + const { preview } = this.state; + const { attributes, setAttributes, focus } = this.props; + + return ( +
    + { focus && + +
      +
    • + +
    • +
    • + +
    • +
    +
    + } + { preview + ?
    + : setAttributes( { content: event.target.value } ) } + /> + } +
    + ); + } + }, + + save( { attributes } ) { + return attributes.content; + }, +} ); diff --git a/blocks/library/html/style.scss b/blocks/library/html/style.scss new file mode 100644 index 00000000000000..49fb5f71253ed0 --- /dev/null +++ b/blocks/library/html/style.scss @@ -0,0 +1,14 @@ +div[data-type="core/html"] { + textarea { + box-shadow: none; + font-family: $editor-html-font; + font-size: $text-editor-font-size; + color: $dark-gray-800; + border: 1px solid $light-gray-500; + border-radius: 4px; + padding: .8em 1.6em; + margin: 0; + overflow-x: auto; + width: 100%; + } +} diff --git a/blocks/library/image/index.js b/blocks/library/image/index.js index 10cc2bf6a33fcc..89a418d0119e3d 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from 'i18n'; -import { Placeholder } from 'components'; +import { Placeholder, Dashicon, Toolbar } from 'components'; /** * Internal dependencies @@ -15,6 +15,7 @@ import InspectorControls from '../../inspector-controls'; import TextControl from '../../inspector-controls/text-control'; import BlockControls from '../../block-controls'; import BlockAlignmentToolbar from '../../block-alignment-toolbar'; +import BlockDescription from '../../block-description'; const { attr, children } = query; @@ -38,10 +39,14 @@ registerBlockType( 'core/image', { } }, - edit( { attributes, setAttributes, focus, setFocus } ) { - const { url, alt, caption, align } = attributes; + edit( { attributes, setAttributes, focus, setFocus, className } ) { + const { url, alt, caption, align, id } = attributes; const updateAlt = ( newAlt ) => setAttributes( { alt: newAlt } ); const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + const onSelectImage = ( media ) => { + setAttributes( { url: media.url, alt: media.alt, caption: media.caption, id: media.id } ); + }; + const uploadButtonProps = { isLarge: true }; const controls = ( focus && ( @@ -51,13 +56,24 @@ registerBlockType( 'core/image', { onChange={ updateAlignment } controls={ [ 'left', 'center', 'right', 'wide', 'full' ] } /> + + +
  • + + + +
  • +
    ) ); if ( ! url ) { - const uploadButtonProps = { isLarge: true }; - const setMediaURL = ( media ) => setAttributes( { url: media.url } ); return [ controls, + className={ className }> { __( 'Insert from Media Library' ) } @@ -87,10 +103,14 @@ registerBlockType( 'core/image', { controls, focus && ( + +

    { __( 'Worth a thousand words.' ) }

    +
    +

    { __( 'Image Settings' ) }

    ), -
    +
    { { ( caption && caption.length > 0 ) || !! focus ? ( ; + // If there's no caption set only save the image element. if ( ! caption || ! caption.length ) { - return img; + return {; } return ( -
    - { img } +
    + {
    { caption }
    ); diff --git a/blocks/library/image/style.scss b/blocks/library/image/style.scss index b45d7085c0885c..7e582a4eddd04d 100644 --- a/blocks/library/image/style.scss +++ b/blocks/library/image/style.scss @@ -1,4 +1,4 @@ -.blocks-image { +.wp-block-image { margin: 0; img { diff --git a/blocks/library/index.js b/blocks/library/index.js index ef5b343afc2cfe..93a71f0cc3accb 100644 --- a/blocks/library/index.js +++ b/blocks/library/index.js @@ -4,7 +4,6 @@ import './gallery'; import './heading'; import './quote'; import './embed'; -import './freeform'; import './list'; import './separator'; import './button'; @@ -12,4 +11,7 @@ import './pullquote'; import './table'; import './preformatted'; import './code'; +import './html'; +import './freeform'; import './latest-posts'; +import './cover-image'; diff --git a/blocks/library/latest-posts/index.js b/blocks/library/latest-posts/index.js index a4d0a742074b55..81cfa3cb936894 100644 --- a/blocks/library/latest-posts/index.js +++ b/blocks/library/latest-posts/index.js @@ -1,16 +1,25 @@ /** * WordPress dependencies */ +import { Component } from 'element'; import { Placeholder } from 'components'; import { __ } from 'i18n'; +import moment from 'moment'; /** * Internal dependencies */ +import './style.scss'; import { registerBlockType } from '../../api'; import { getLatestPosts } from './data.js'; +import InspectorControls from '../../inspector-controls'; +import TextControl from '../../inspector-controls/text-control'; +import ToggleControl from '../../inspector-controls/toggle-control'; -registerBlockType( 'core/latestposts', { +const MIN_POSTS = 1; +const MAX_POSTS = 100; + +registerBlockType( 'core/latest-posts', { title: __( 'Latest Posts' ), icon: 'list-view', @@ -18,23 +27,59 @@ registerBlockType( 'core/latestposts', { category: 'widgets', defaultAttributes: { - poststoshow: 5, + postsToShow: 5, + displayPostDate: false, }, - edit: class extends wp.element.Component { + edit: class extends Component { constructor() { super( ...arguments ); + this.changePostsToShow = this.changePostsToShow.bind( this ); - const { poststoshow } = this.props.attributes; + const { postsToShow } = this.props.attributes; this.state = { latestPosts: [], }; - this.latestPostsRequest = getLatestPosts( poststoshow ); + this.latestPostsRequest = getLatestPosts( postsToShow ); this.latestPostsRequest .then( latestPosts => this.setState( { latestPosts } ) ); + + this.toggleDisplayPostDate = this.toggleDisplayPostDate.bind( this ); + } + + toggleDisplayPostDate() { + const { displayPostDate } = this.props.attributes; + const { setAttributes } = this.props; + + setAttributes( { displayPostDate: ! displayPostDate } ); + } + + componentWillReceiveProps( nextProps ) { + const { postsToShow: postToShowCurrent } = this.props.attributes; + const { postsToShow: postToShowNext } = nextProps.attributes; + const { setAttributes } = this.props; + + if ( postToShowCurrent === postToShowNext ) { + return; + } + + if ( postToShowNext >= MIN_POSTS && postToShowNext <= MAX_POSTS ) { + this.latestPostsRequest = getLatestPosts( postToShowNext ); + + this.latestPostsRequest + .then( latestPosts => this.setState( { latestPosts } ) ); + + setAttributes( { postsToShow: postToShowNext } ); + } + } + + changePostsToShow( postsToShow ) { + const { setAttributes } = this.props; + + setAttributes( { postsToShow: parseInt( postsToShow, 10 ) || 0 } ); } render() { @@ -50,15 +95,40 @@ registerBlockType( 'core/latestposts', { ); } - return ( -
    - -
    - ); + const { focus } = this.props; + const { displayPostDate } = this.props.attributes; + + return [ + focus && ( + + + this.changePostsToShow( value ) } + /> + + ), +
      + { latestPosts.map( ( post, i ) => +
    • + { post.title.rendered } + { displayPostDate && post.date_gmt && + + { moment( post.date_gmt ).local().format( 'MMM DD h:mm A' ) } + + } +
    • + ) } +
    , + ]; } componentWillUnmount() { diff --git a/blocks/library/latest-posts/style.scss b/blocks/library/latest-posts/style.scss new file mode 100644 index 00000000000000..d6746c6f0d7087 --- /dev/null +++ b/blocks/library/latest-posts/style.scss @@ -0,0 +1,10 @@ + +.wp-block-latest-posts { + padding-left: 2.5em; +} + +.wp-block-latest-posts__post-date { + display: block; + color: $dark-gray-100; + font-size: $default-font-size; +} diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index b8376e153f12fa..a31d69daf4db2a 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Component, createElement, switchChildrenNodeName } from 'element'; +import { Component, createElement, Children, concatChildren } from 'element'; import { find } from 'lodash'; import { __ } from 'i18n'; @@ -15,6 +15,55 @@ import BlockControls from '../../block-controls'; const { children, prop } = hpq; +const fromBrDelimitedContent = ( content ) => { + if ( undefined === content ) { + // converting an empty block to a list block + return content; + } + const listItems = []; + listItems.push( createElement( 'li', [], [] ) ); + content.forEach( function( element, elementIndex, elements ) { + // "split" the incoming content on 'br' elements + if ( 'br' === element.type && elementIndex < elements.length - 1 ) { + // if is br and there are more elements to come, push a new list item + listItems.push( createElement( 'li', [], [] ) ); + } else { + listItems[ listItems.length - 1 ].props.children.push( element ); + } + } ); + return listItems; +}; + +const toBrDelimitedContent = ( values ) => { + if ( undefined === values ) { + // converting an empty list + return values; + } + const content = []; + values.forEach( function( li, liIndex, listItems ) { + Children.toArray( li.props.children ).forEach( function( element, elementIndex, liChildren ) { + if ( 'ul' === element.type || 'ol' === element.type ) { // lists within lists + // we know we've just finished processing a list item, so break the text + content.push( createElement( 'br' ) ); + // push each element from the child list's converted content + content.push.apply( content, toBrDelimitedContent( Children.toArray( element.props.children ) ) ); + // add a break if there are more list items to come, because the recursive call won't + // have added it when it finished processing the child list because it thinks the content ended + if ( liIndex !== listItems.length - 1 ) { + content.push( createElement( 'br' ) ); + } + } else { + content.push( element ); + if ( elementIndex === liChildren.length - 1 && liIndex !== listItems.length - 1 ) { + // last element in this list item, but not last element overall + content.push( createElement( 'br' ) ); + } + } + } ); + } ); + return content; +}; + registerBlockType( 'core/list', { title: __( 'List' ), icon: 'editor-ul', @@ -25,6 +74,8 @@ registerBlockType( 'core/list', { values: children( 'ol,ul' ), }, + className: false, + transforms: { from: [ { @@ -33,10 +84,25 @@ registerBlockType( 'core/list', { transform: ( { content } ) => { return createBlock( 'core/list', { nodeName: 'ul', - values: switchChildrenNodeName( content, 'li' ), + values: fromBrDelimitedContent( content ), + } ); + }, + }, + { + type: 'block', + blocks: [ 'core/quote' ], + transform: ( { value, citation } ) => { + const listItems = fromBrDelimitedContent( value ); + const values = citation + ? concatChildren( listItems,
  • { citation }
  • ) + : listItems; + return createBlock( 'core/list', { + nodeName: 'ul', + values, } ); }, }, + ], to: [ { @@ -44,7 +110,16 @@ registerBlockType( 'core/list', { blocks: [ 'core/text' ], transform: ( { values } ) => { return createBlock( 'core/text', { - content: switchChildrenNodeName( values, 'p' ), + content: toBrDelimitedContent( values ), + } ); + }, + }, + { + type: 'block', + blocks: [ 'core/quote' ], + transform: ( { values } ) => { + return createBlock( 'core/quote', { + value: toBrDelimitedContent( values ), } ); }, }, diff --git a/blocks/library/preformatted/index.js b/blocks/library/preformatted/index.js index 354ec63e683b61..d2457e1976dcb1 100644 --- a/blocks/library/preformatted/index.js +++ b/blocks/library/preformatted/index.js @@ -1,3 +1,8 @@ +/** + * WordPress + */ +import { __ } from 'i18n'; + /** * Internal dependencies */ @@ -8,7 +13,7 @@ import Editable from '../../editable'; const { children } = query; registerBlockType( 'core/preformatted', { - title: wp.i18n.__( 'Preformatted' ), + title: __( 'Preformatted' ), icon: 'text', @@ -37,7 +42,7 @@ registerBlockType( 'core/preformatted', { ], }, - edit( { attributes, setAttributes, focus, setFocus } ) { + edit( { attributes, setAttributes, focus, setFocus, className } ) { const { content } = attributes; return ( @@ -51,6 +56,9 @@ registerBlockType( 'core/preformatted', { } } focus={ focus } onFocus={ setFocus } + placeholder={ __( 'Write preformatted text…' ) } + inline + className={ className } /> ); }, diff --git a/blocks/library/pullquote/block.scss b/blocks/library/pullquote/block.scss new file mode 100644 index 00000000000000..98a1aaa6cb2193 --- /dev/null +++ b/blocks/library/pullquote/block.scss @@ -0,0 +1,21 @@ +.wp-block-pullquote { + color: $light-gray-900; + padding: 2em; + text-align: center; + + > p { + font-family: $default-font; + font-size: 48px; + font-weight: 900; + } + + footer { + color: $dark-gray-900; + position: relative; + } + + footer p { + font-size: 16px; + font-family: $default-font; + } +} diff --git a/blocks/library/pullquote/index.js b/blocks/library/pullquote/index.js index 91df1ec8050ba6..cc315e5e1cee72 100644 --- a/blocks/library/pullquote/index.js +++ b/blocks/library/pullquote/index.js @@ -1,15 +1,23 @@ +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; + /** * Internal dependencies */ import './style.scss'; +import './block.scss'; import { registerBlockType, query as hpq } from '../../api'; import Editable from '../../editable'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { children, query } = hpq; registerBlockType( 'core/pullquote', { - title: wp.i18n.__( 'Pullquote' ), + title: __( 'Pullquote' ), icon: 'format-quote', @@ -20,25 +28,45 @@ registerBlockType( 'core/pullquote', { citation: children( 'footer' ), }, - edit( { attributes, setAttributes, focus, setFocus } ) { - const { value, citation } = attributes; + getEditWrapperProps( attributes ) { + const { align } = attributes; + if ( 'left' === align || 'right' === align || 'wide' === align || 'full' === align ) { + return { 'data-align': align }; + } + }, - return ( -
    + edit( { attributes, setAttributes, focus, setFocus, className } ) { + const { value, citation, align } = attributes; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + + return [ + focus && ( + + + + ), +
    setAttributes( { value: nextValue, } ) } + placeholder={ __( 'Write quote…' ) } focus={ focus && focus.editable === 'value' ? focus : null } onFocus={ ( props ) => setFocus( { ...props, editable: 'value' } ) } + className="blocks-pullquote__content" /> { ( citation || !! focus ) && ( setAttributes( { citation: nextCitation, @@ -49,15 +77,15 @@ registerBlockType( 'core/pullquote', { inline /> ) } -
    - ); +
    , + ]; }, save( { attributes } ) { - const { value, citation } = attributes; + const { value, citation, align = 'none' } = attributes; return ( -
    +
    { value && value.map( ( paragraph, i ) => (

    { paragraph }

    ) ) } diff --git a/blocks/library/pullquote/style.scss b/blocks/library/pullquote/style.scss index 476b0d38fe7561..2ba88b1c90c4a5 100644 --- a/blocks/library/pullquote/style.scss +++ b/blocks/library/pullquote/style.scss @@ -1,23 +1,18 @@ -.blocks-pullquote { - color: $light-gray-900; - padding: 2em; - text-align: center; - - footer { - color: $dark-gray-900; - position: relative; - } - - footer p { +.wp-block-pullquote { + footer .blocks-editable__tinymce[data-is-empty="true"]:before { font-size: 16px; font-family: $default-font; } -} -.editor-visual-editor .blocks-pullquote { + .blocks-editable__tinymce[data-is-empty="true"]:before { + width: 100%; + left: 50%; + transform: translateX( -50% ); + } + + & > .blocks-pullquote__content .blocks-editable__tinymce[data-is-empty="true"]:before, & > .blocks-editable p { - font-family: $default-font; font-size: 48px; - font-weight: 900; + font-weight: bold; } } diff --git a/blocks/library/quote/block.scss b/blocks/library/quote/block.scss new file mode 100644 index 00000000000000..03ff30255511c3 --- /dev/null +++ b/blocks/library/quote/block.scss @@ -0,0 +1,34 @@ +.wp-block-quote { + margin: 0; + box-shadow: inset 0px 0px 0px 0px $light-gray-500; + + footer { + color: $dark-gray-100; + margin-left: 1.3em; + margin-top: 1em; + position: relative; + font-size: $default-font-size; + font-style: normal; + + &:before { + content: '— '; + position: absolute; + left: -1.3em; + top: 0; + } + } + + + &.blocks-quote-style-1 { + border-left: 4px solid $black; + padding-left: 1em; + } + + &.blocks-quote-style-2 { + padding: 0 1em; + & > p { + font-size: 24px; + font-style: italic; + } + } +} diff --git a/blocks/library/quote/index.js b/blocks/library/quote/index.js index dc2a9508b2e7b4..16b71a20fddec6 100644 --- a/blocks/library/quote/index.js +++ b/blocks/library/quote/index.js @@ -1,38 +1,38 @@ +/** + * External dependencies + */ +import { isString, isObject } from 'lodash'; + /** * WordPress dependencies */ -import { switchChildrenNodeName } from 'element'; +import { __, sprintf } from 'i18n'; +import { Toolbar } from 'components'; /** * Internal dependencies */ -import './style.scss'; +import './block.scss'; import { registerBlockType, createBlock, query as hpq } from '../../api'; import AlignmentToolbar from '../../alignment-toolbar'; import BlockControls from '../../block-controls'; import Editable from '../../editable'; -const { children, query } = hpq; +const { children, node, query } = hpq; registerBlockType( 'core/quote', { - title: wp.i18n.__( 'Quote' ), + title: __( 'Quote' ), icon: 'format-quote', category: 'common', attributes: { - value: query( 'blockquote > p', children() ), + value: query( 'blockquote > p', node() ), citation: children( 'footer' ), }, - controls: [ 1, 2 ].map( ( variation ) => ( { - icon: 'format-quote', - title: wp.i18n.sprintf( wp.i18n.__( 'Quote style %d' ), variation ), - isActive: ( { style = 1 } ) => Number( style ) === variation, - onClick( attributes, setAttributes ) { - setAttributes( { style: variation } ); - }, - subscript: variation, - } ) ), + defaultAttributes: { + value: [], + }, transforms: { from: [ @@ -45,15 +45,6 @@ registerBlockType( 'core/quote', { } ); }, }, - { - type: 'block', - blocks: [ 'core/list' ], - transform: ( { values } ) => { - return createBlock( 'core/quote', { - value: switchChildrenNodeName( values, 'p' ), - } ); - }, - }, { type: 'block', blocks: [ 'core/heading' ], @@ -68,23 +59,28 @@ registerBlockType( 'core/quote', { { type: 'block', blocks: [ 'core/text' ], - transform: ( { value, citation } ) => { + transform: ( { value, citation, ...attrs } ) => { + const textElement = value[ 0 ]; + if ( ! textElement ) { + return createBlock( 'core/text', { + content: citation, + } ); + } + const textContent = isString( textElement ) ? textElement : textElement.props.children; + if ( Array.isArray( value ) || citation ) { + const text = createBlock( 'core/text', { + content: textContent, + } ); + const quote = createBlock( 'core/quote', { + ...attrs, + citation, + value: Array.isArray( value ) ? value.slice( 1 ) : '', + } ); + + return [ text, quote ]; + } return createBlock( 'core/text', { - content: wp.element.concatChildren( value, citation ), - } ); - }, - }, - { - type: 'block', - blocks: [ 'core/list' ], - transform: ( { value, citation } ) => { - const valueElements = switchChildrenNodeName( value, 'li' ); - const values = citation - ? wp.element.concatChildren( valueElements,
  • { citation }
  • ) - : valueElements; - return createBlock( 'core/list', { - nodeName: 'ul', - values, + content: textContent, } ); }, }, @@ -92,9 +88,14 @@ registerBlockType( 'core/quote', { type: 'block', blocks: [ 'core/heading' ], transform: ( { value, citation, ...attrs } ) => { - if ( Array.isArray( value ) || citation ) { + const isMultiParagraph = Array.isArray( value ) && isObject( value[ 0 ] ) && value[ 0 ].type === 'p'; + const headingElement = isMultiParagraph ? value[ 0 ] : value; + const headingContent = isObject( headingElement ) && value[ 0 ].type === 'p' + ? headingElement.props.children + : headingElement; + if ( isMultiParagraph || citation ) { const heading = createBlock( 'core/heading', { - content: Array.isArray( value ) ? value[ 0 ] : value, + content: headingContent, } ); const quote = createBlock( 'core/quote', { ...attrs, @@ -105,20 +106,29 @@ registerBlockType( 'core/quote', { return [ heading, quote ]; } return createBlock( 'core/heading', { - content: value, + content: headingContent, } ); }, }, ], }, - edit( { attributes, setAttributes, focus, setFocus, mergeBlocks } ) { + edit( { attributes, setAttributes, focus, setFocus, mergeBlocks, className } ) { const { align, value, citation, style = 1 } = attributes; const focusedEditable = focus ? focus.editable || 'value' : null; return [ focus && ( + ( { + icon: 'format-quote', + title: sprintf( __( 'Quote style %d' ), variation ), + isActive: Number( style ) === variation, + onClick() { + setAttributes( { style: variation } ); + }, + subscript: variation, + } ) ) } /> { @@ -129,7 +139,7 @@ registerBlockType( 'core/quote', { ),
    setFocus( { ...props, editable: 'value' } ) } onMerge={ mergeBlocks } style={ { textAlign: align } } + placeholder={ __( 'Write quote…' ) } /> { ( ( citation && citation.length > 0 ) || !! focus ) && ( setAttributes( { citation: nextCitation, @@ -172,7 +183,7 @@ registerBlockType( 'core/quote', { key={ i } style={ { textAlign: align ? align : null } } > - { paragraph } + { isString( paragraph ) ? paragraph : paragraph.props.children }

    ) ) } { citation && citation.length > 0 && ( diff --git a/blocks/library/quote/style.scss b/blocks/library/quote/style.scss index 71f55c72e862ae..7023cebb1e63d3 100644 --- a/blocks/library/quote/style.scss +++ b/blocks/library/quote/style.scss @@ -1,33 +1,4 @@ -.blocks-quote { - margin: 0; - box-shadow: inset 0px 0px 0px 0px $light-gray-500; - - footer { - color: $dark-gray-100; - margin-left: 1.3em; - margin-top: 1em; - position: relative; - font-size: $default-font-size; - font-style: normal; - - &:before { - content: '— '; - position: absolute; - left: -1.3em; - top: 0; - } - } -} - -.editor-visual-editor .blocks-quote-style-1 { - border-left: 4px solid $black; - padding-left: 1em; -} - -.editor-visual-editor .blocks-quote-style-2 { - padding: 0 1em; - & > .blocks-editable p { - font-size: 24px; - font-style: italic; - } +.wp-block-quote.blocks-quote-style-2 > .blocks-editable p { + font-size: 24px; + font-style: italic; } diff --git a/blocks/library/separator/style.scss b/blocks/library/separator/block.scss similarity index 81% rename from blocks/library/separator/style.scss rename to blocks/library/separator/block.scss index 8612d369395b72..37561623928515 100644 --- a/blocks/library/separator/style.scss +++ b/blocks/library/separator/block.scss @@ -1,4 +1,4 @@ -.blocks-separator { +.wp-block-separator { border: none; border-bottom: 2px solid $dark-gray-100; max-width: 100px; diff --git a/blocks/library/separator/index.js b/blocks/library/separator/index.js index aa54c61eac3d3d..a4bc70249bfadb 100644 --- a/blocks/library/separator/index.js +++ b/blocks/library/separator/index.js @@ -1,18 +1,23 @@ +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; + /** * Internal dependencies */ -import './style.scss'; +import './block.scss'; import { registerBlockType } from '../../api'; registerBlockType( 'core/separator', { - title: wp.i18n.__( 'Separator' ), + title: __( 'Separator' ), icon: 'minus', category: 'layout', - edit() { - return
    ; + edit( { className } ) { + return
    ; }, save() { diff --git a/blocks/library/table/index.js b/blocks/library/table/index.js index 3acc0ad7eccb72..d90c03abae3d5d 100644 --- a/blocks/library/table/index.js +++ b/blocks/library/table/index.js @@ -1,3 +1,9 @@ +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; +import { createElement } from 'element'; + /** * Internal dependencies */ @@ -10,7 +16,7 @@ import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { children, query } = hpq; registerBlockType( 'core/table', { - title: wp.i18n.__( 'Table' ), + title: __( 'Table' ), icon: 'editor-table', category: 'formatting', @@ -31,7 +37,7 @@ registerBlockType( 'core/table', { } }, - edit( { attributes, setAttributes, focus, setFocus } ) { + edit( { attributes, setAttributes, focus, setFocus, className } ) { const focussedKey = focus ? focus.editable || 'body.0.0' : null; const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); @@ -45,10 +51,10 @@ registerBlockType( 'core/table', { /> ), - +
    { [ 'head', 'body', 'foot' ].map( ( part ) => attributes[ part ] && attributes[ part ].length - ? wp.element.createElement( 't' + part, { key: part }, + ? createElement( 't' + part, { key: part }, attributes[ part ].map( ( rows = [], i ) => { rows.map( ( value = '', ii ) => { @@ -87,7 +93,7 @@ registerBlockType( 'core/table', {
    { [ 'head', 'body', 'foot' ].map( ( part ) => attributes[ part ] && attributes[ part ].length - ? wp.element.createElement( 't' + part, { key: part }, + ? createElement( 't' + part, { key: part }, attributes[ part ].map( ( rows = [], i ) => { rows.map( ( value = '', ii ) => { diff --git a/blocks/library/text/block.scss b/blocks/library/text/block.scss new file mode 100644 index 00000000000000..1cc6bd7b2ff4da --- /dev/null +++ b/blocks/library/text/block.scss @@ -0,0 +1,16 @@ +p.has-drop-cap { + &:first-letter { + float: left; + font-size: 4.1em; + line-height: 0.7; + font-family: serif; + font-weight: bold; + margin: .07em .23em 0 0; + text-transform: uppercase; + font-style: normal; + } +} + +p.has-drop-cap:not( :focus ) { + overflow: hidden; +} diff --git a/blocks/library/text/index.js b/blocks/library/text/index.js index 4ccb3b8beea74d..644a9213812d52 100644 --- a/blocks/library/text/index.js +++ b/blocks/library/text/index.js @@ -2,16 +2,19 @@ * WordPress dependencies */ import { __ } from 'i18n'; -import Toggle from 'components/form-toggle'; +import { concatChildren } from 'element'; /** * Internal dependencies */ +import './block.scss'; import { registerBlockType, createBlock, query as hpq, setDefaultBlock } from '../../api'; import AlignmentToolbar from '../../alignment-toolbar'; import BlockControls from '../../block-controls'; import Editable from '../../editable'; import InspectorControls from '../../inspector-controls'; +import ToggleControl from '../../inspector-controls/toggle-control'; +import BlockDescription from '../../block-description'; const { children, query } = hpq; @@ -22,13 +25,15 @@ registerBlockType( 'core/text', { category: 'common', + className: false, + attributes: { content: query( 'p', children() ), }, merge( attributes, attributesToMerge ) { return { - content: wp.element.concatChildren( attributes.content, attributesToMerge.content ), + content: concatChildren( attributes.content, attributesToMerge.content ), }; }, @@ -48,14 +53,15 @@ registerBlockType( 'core/text', { ), focus && ( -
    - - -
    + +

    { __( 'Text. Great things start here.' ) }

    +
    +

    { __( 'Text Settings' ) }

    +
    ), , ]; }, save( { attributes } ) { - const { align, content } = attributes; + const { align, content, dropCap } = attributes; + const className = dropCap && 'has-drop-cap'; if ( ! align ) { - return

    { content }

    ; + return

    { content }

    ; } - return

    { content }

    ; + return

    { content }

    ; }, } ); diff --git a/blocks/media-upload-button/index.js b/blocks/media-upload-button/index.js index f743ef71290765..81cd6f5445265e 100644 --- a/blocks/media-upload-button/index.js +++ b/blocks/media-upload-button/index.js @@ -10,6 +10,7 @@ class MediaUploadButton extends Component { super( ...arguments ); this.openModal = this.openModal.bind( this ); this.onSelect = this.onSelect.bind( this ); + this.onOpen = this.onOpen.bind( this ); const frameConfig = { title: __( 'Select or Upload a media' ), button: { @@ -24,6 +25,7 @@ class MediaUploadButton extends Component { // When an image is selected in the media frame... this.frame.on( 'select', this.onSelect ); + this.frame.on( 'open', this.onOpen ); } componentDidMount() { @@ -43,6 +45,25 @@ class MediaUploadButton extends Component { onSelect( multiple ? attachment : attachment[ 0 ] ); } + onOpen() { + const selection = this.frame.state().get( 'selection' ); + const addMedia = ( id ) => { + const attachment = wp.media.attachment( id ); + attachment.fetch(); + selection.add( attachment ); + }; + + if ( ! this.props.value ) { + return; + } + + if ( this.props.multiple ) { + this.props.value.map( addMedia ); + } else { + addMedia( this.props.value ); + } + } + openModal() { this.frame.open(); } diff --git a/blocks/test/fixtures/README.md b/blocks/test/fixtures/README.md index b17018f85c88c2..9be327c967bcf0 100644 --- a/blocks/test/fixtures/README.md +++ b/blocks/test/fixtures/README.md @@ -3,28 +3,31 @@ This directory contains sets of fixture files that are used to test the parsing and serialization logic. -Each test is made up of three fixture files: +Each test is made up of four fixture files: 1. `fixture-name.html`: The initial post content. -2. `fixture-name.json`: The **expected** parsed representation of the block(s) - inside the post content, along with their attributes and any nested content. - The contents of this file are compared against the **actual** parsed block - object(s). -3. `fixture-name.serialized.html`: The **expected** result of calling +2. `fixture-name.parsed.json`: The **expected** output of the PEG parser for + this content (checked against the **actual** output of both the JS and PHP + versions of the parser). +3. `fixture-name.json`: The **expected** representation of the block(s) inside + the post content, along with their attributes and any nested content. The + contents of this file are compared against the **actual** block object(s). +4. `fixture-name.serialized.html`: The **expected** result of calling `serialize` on the parsed block object(s). The contents of this file are compared against the **actual** re-serialized post content. This final step simulates opening and re-saving a post. Every block is required to have at least one such set of fixture files to test the parsing and serialization of that block. These fixtures must be named like -`core-blockname{-*,}.{html,json,serialized.html}`. For example, for the -`core/image` block, the following three fixture files must exist: +`core__blockname{__*,}.{html,json,serialized.html}`. For example, for the +`core/image` block, the following four fixture files must exist: -1. `core-image.html` (or `core-image-specific-test-name.html`). Must contain a - `` block. -2. `core-image.json` (or `core-image-specific-test-name.html`). -3. `core-image.serialized.html` (or - `core-image-specific-test-name.serialized.html`). +1. `core__image.html` (or `core__image__specific-test-name.html`). Must + contain a `` block. +2. `core__image.parsed.json` (or `core__image__specific-test-name.parsed.json`). +3. `core__image.json` (or `core__image__specific-test-name.json`). +4. `core__image.serialized.html` (or + `core__image__specific-test-name.serialized.html`). Ideally all important attributes and features of the block should be tested this way. New contributions in the form of additional test cases are always @@ -32,7 +35,7 @@ welcome - this is a great way for us to identify bugs and prevent them from recurring in the future. When adding a new test, it's only necessary to create file (1) above, then -there is a command you can run to generate (2) and (3): +there is a command you can run to generate (2) through (4): ```sh GENERATE_MISSING_FIXTURES=y npm run test-unit -- --grep 'full post content fixture' diff --git a/blocks/test/fixtures/core-button-center.html b/blocks/test/fixtures/core-button-center.html deleted file mode 100644 index b80f97864c2935..00000000000000 --- a/blocks/test/fixtures/core-button-center.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/blocks/test/fixtures/core-button-center.serialized.html b/blocks/test/fixtures/core-button-center.serialized.html deleted file mode 100644 index c360f9e247a91c..00000000000000 --- a/blocks/test/fixtures/core-button-center.serialized.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/blocks/test/fixtures/core-embed__animoto.html b/blocks/test/fixtures/core-embed__animoto.html new file mode 100644 index 00000000000000..b805520078110d --- /dev/null +++ b/blocks/test/fixtures/core-embed__animoto.html @@ -0,0 +1,6 @@ + +
    + https://animoto.com/ +
    Embedded content from animoto
    +
    + diff --git a/blocks/test/fixtures/core-embedanimoto.json b/blocks/test/fixtures/core-embed__animoto.json similarity index 84% rename from blocks/test/fixtures/core-embedanimoto.json rename to blocks/test/fixtures/core-embed__animoto.json index 4f2cbc392247d7..28c7c26cd2cc2a 100644 --- a/blocks/test/fixtures/core-embedanimoto.json +++ b/blocks/test/fixtures/core-embed__animoto.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedanimoto", + "name": "core-embed/animoto", "attributes": { "url": "https://animoto.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__animoto.parsed.json b/blocks/test/fixtures/core-embed__animoto.parsed.json new file mode 100644 index 00000000000000..8650b4f32fbe14 --- /dev/null +++ b/blocks/test/fixtures/core-embed__animoto.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/animoto", + "attrs": { + "url": "https://animoto.com/" + }, + "rawContent": "\n
    \n https://animoto.com/\n
    Embedded content from animoto
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__animoto.serialized.html b/blocks/test/fixtures/core-embed__animoto.serialized.html new file mode 100644 index 00000000000000..579267fe3b30e1 --- /dev/null +++ b/blocks/test/fixtures/core-embed__animoto.serialized.html @@ -0,0 +1,7 @@ + +
    + https://animoto.com/ +
    Embedded content from animoto
    +
    + + diff --git a/blocks/test/fixtures/core-embed__cloudup.html b/blocks/test/fixtures/core-embed__cloudup.html new file mode 100644 index 00000000000000..4737f84d4cf72b --- /dev/null +++ b/blocks/test/fixtures/core-embed__cloudup.html @@ -0,0 +1,6 @@ + +
    + https://cloudup.com/ +
    Embedded content from cloudup
    +
    + diff --git a/blocks/test/fixtures/core-embedcloudup.json b/blocks/test/fixtures/core-embed__cloudup.json similarity index 84% rename from blocks/test/fixtures/core-embedcloudup.json rename to blocks/test/fixtures/core-embed__cloudup.json index 6bda5b3051eef3..22a55a4d296f99 100644 --- a/blocks/test/fixtures/core-embedcloudup.json +++ b/blocks/test/fixtures/core-embed__cloudup.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedcloudup", + "name": "core-embed/cloudup", "attributes": { "url": "https://cloudup.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__cloudup.parsed.json b/blocks/test/fixtures/core-embed__cloudup.parsed.json new file mode 100644 index 00000000000000..eee1502a9e8202 --- /dev/null +++ b/blocks/test/fixtures/core-embed__cloudup.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/cloudup", + "attrs": { + "url": "https://cloudup.com/" + }, + "rawContent": "\n
    \n https://cloudup.com/\n
    Embedded content from cloudup
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__cloudup.serialized.html b/blocks/test/fixtures/core-embed__cloudup.serialized.html new file mode 100644 index 00000000000000..5f953aa46c1f4b --- /dev/null +++ b/blocks/test/fixtures/core-embed__cloudup.serialized.html @@ -0,0 +1,7 @@ + +
    + https://cloudup.com/ +
    Embedded content from cloudup
    +
    + + diff --git a/blocks/test/fixtures/core-embed__collegehumor.html b/blocks/test/fixtures/core-embed__collegehumor.html new file mode 100644 index 00000000000000..770c0664896490 --- /dev/null +++ b/blocks/test/fixtures/core-embed__collegehumor.html @@ -0,0 +1,6 @@ + +
    + https://collegehumor.com/ +
    Embedded content from collegehumor
    +
    + diff --git a/blocks/test/fixtures/core-embedcollegehumor.json b/blocks/test/fixtures/core-embed__collegehumor.json similarity index 83% rename from blocks/test/fixtures/core-embedcollegehumor.json rename to blocks/test/fixtures/core-embed__collegehumor.json index aa9183ead77484..47cff93865c5fa 100644 --- a/blocks/test/fixtures/core-embedcollegehumor.json +++ b/blocks/test/fixtures/core-embed__collegehumor.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedcollegehumor", + "name": "core-embed/collegehumor", "attributes": { "url": "https://collegehumor.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__collegehumor.parsed.json b/blocks/test/fixtures/core-embed__collegehumor.parsed.json new file mode 100644 index 00000000000000..c0170701eae6b0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__collegehumor.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/collegehumor", + "attrs": { + "url": "https://collegehumor.com/" + }, + "rawContent": "\n
    \n https://collegehumor.com/\n
    Embedded content from collegehumor
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__collegehumor.serialized.html b/blocks/test/fixtures/core-embed__collegehumor.serialized.html new file mode 100644 index 00000000000000..8234fe93591a38 --- /dev/null +++ b/blocks/test/fixtures/core-embed__collegehumor.serialized.html @@ -0,0 +1,7 @@ + +
    + https://collegehumor.com/ +
    Embedded content from collegehumor
    +
    + + diff --git a/blocks/test/fixtures/core-embed__dailymotion.html b/blocks/test/fixtures/core-embed__dailymotion.html new file mode 100644 index 00000000000000..e1fde0199be096 --- /dev/null +++ b/blocks/test/fixtures/core-embed__dailymotion.html @@ -0,0 +1,6 @@ + +
    + https://dailymotion.com/ +
    Embedded content from dailymotion
    +
    + diff --git a/blocks/test/fixtures/core-embeddailymotion.json b/blocks/test/fixtures/core-embed__dailymotion.json similarity index 83% rename from blocks/test/fixtures/core-embeddailymotion.json rename to blocks/test/fixtures/core-embed__dailymotion.json index 44f0b737a76784..4ad16679bf20e9 100644 --- a/blocks/test/fixtures/core-embeddailymotion.json +++ b/blocks/test/fixtures/core-embed__dailymotion.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embeddailymotion", + "name": "core-embed/dailymotion", "attributes": { "url": "https://dailymotion.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__dailymotion.parsed.json b/blocks/test/fixtures/core-embed__dailymotion.parsed.json new file mode 100644 index 00000000000000..d144c58f2b5d16 --- /dev/null +++ b/blocks/test/fixtures/core-embed__dailymotion.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/dailymotion", + "attrs": { + "url": "https://dailymotion.com/" + }, + "rawContent": "\n
    \n https://dailymotion.com/\n
    Embedded content from dailymotion
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__dailymotion.serialized.html b/blocks/test/fixtures/core-embed__dailymotion.serialized.html new file mode 100644 index 00000000000000..442c7348cc1e34 --- /dev/null +++ b/blocks/test/fixtures/core-embed__dailymotion.serialized.html @@ -0,0 +1,7 @@ + +
    + https://dailymotion.com/ +
    Embedded content from dailymotion
    +
    + + diff --git a/blocks/test/fixtures/core-embed__facebook.html b/blocks/test/fixtures/core-embed__facebook.html new file mode 100644 index 00000000000000..237516d4065f06 --- /dev/null +++ b/blocks/test/fixtures/core-embed__facebook.html @@ -0,0 +1,6 @@ + +
    + https://facebook.com/ +
    Embedded content from facebook
    +
    + diff --git a/blocks/test/fixtures/core-embedfacebook.json b/blocks/test/fixtures/core-embed__facebook.json similarity index 84% rename from blocks/test/fixtures/core-embedfacebook.json rename to blocks/test/fixtures/core-embed__facebook.json index 365f7043c6c808..07e08896c62b42 100644 --- a/blocks/test/fixtures/core-embedfacebook.json +++ b/blocks/test/fixtures/core-embed__facebook.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedfacebook", + "name": "core-embed/facebook", "attributes": { "url": "https://facebook.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__facebook.parsed.json b/blocks/test/fixtures/core-embed__facebook.parsed.json new file mode 100644 index 00000000000000..75927b1856bb28 --- /dev/null +++ b/blocks/test/fixtures/core-embed__facebook.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/facebook", + "attrs": { + "url": "https://facebook.com/" + }, + "rawContent": "\n
    \n https://facebook.com/\n
    Embedded content from facebook
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__facebook.serialized.html b/blocks/test/fixtures/core-embed__facebook.serialized.html new file mode 100644 index 00000000000000..75b045a5d87e15 --- /dev/null +++ b/blocks/test/fixtures/core-embed__facebook.serialized.html @@ -0,0 +1,7 @@ + +
    + https://facebook.com/ +
    Embedded content from facebook
    +
    + + diff --git a/blocks/test/fixtures/core-embed__flickr.html b/blocks/test/fixtures/core-embed__flickr.html new file mode 100644 index 00000000000000..b39f132e964bf3 --- /dev/null +++ b/blocks/test/fixtures/core-embed__flickr.html @@ -0,0 +1,6 @@ + +
    + https://flickr.com/ +
    Embedded content from flickr
    +
    + diff --git a/blocks/test/fixtures/core-embedflickr.json b/blocks/test/fixtures/core-embed__flickr.json similarity index 84% rename from blocks/test/fixtures/core-embedflickr.json rename to blocks/test/fixtures/core-embed__flickr.json index c4294719f27c10..35c28ec6b70e2f 100644 --- a/blocks/test/fixtures/core-embedflickr.json +++ b/blocks/test/fixtures/core-embed__flickr.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedflickr", + "name": "core-embed/flickr", "attributes": { "url": "https://flickr.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__flickr.parsed.json b/blocks/test/fixtures/core-embed__flickr.parsed.json new file mode 100644 index 00000000000000..3a36dce37fdd2b --- /dev/null +++ b/blocks/test/fixtures/core-embed__flickr.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/flickr", + "attrs": { + "url": "https://flickr.com/" + }, + "rawContent": "\n
    \n https://flickr.com/\n
    Embedded content from flickr
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__flickr.serialized.html b/blocks/test/fixtures/core-embed__flickr.serialized.html new file mode 100644 index 00000000000000..ba77735d14d3e0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__flickr.serialized.html @@ -0,0 +1,7 @@ + +
    + https://flickr.com/ +
    Embedded content from flickr
    +
    + + diff --git a/blocks/test/fixtures/core-embed__funnyordie.html b/blocks/test/fixtures/core-embed__funnyordie.html new file mode 100644 index 00000000000000..5adf1408411359 --- /dev/null +++ b/blocks/test/fixtures/core-embed__funnyordie.html @@ -0,0 +1,6 @@ + +
    + https://funnyordie.com/ +
    Embedded content from funnyordie
    +
    + diff --git a/blocks/test/fixtures/core-embedfunnyordie.json b/blocks/test/fixtures/core-embed__funnyordie.json similarity index 83% rename from blocks/test/fixtures/core-embedfunnyordie.json rename to blocks/test/fixtures/core-embed__funnyordie.json index a4787f0a9350ab..575ed6342f43b6 100644 --- a/blocks/test/fixtures/core-embedfunnyordie.json +++ b/blocks/test/fixtures/core-embed__funnyordie.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedfunnyordie", + "name": "core-embed/funnyordie", "attributes": { "url": "https://funnyordie.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__funnyordie.parsed.json b/blocks/test/fixtures/core-embed__funnyordie.parsed.json new file mode 100644 index 00000000000000..8926a608389376 --- /dev/null +++ b/blocks/test/fixtures/core-embed__funnyordie.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/funnyordie", + "attrs": { + "url": "https://funnyordie.com/" + }, + "rawContent": "\n
    \n https://funnyordie.com/\n
    Embedded content from funnyordie
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__funnyordie.serialized.html b/blocks/test/fixtures/core-embed__funnyordie.serialized.html new file mode 100644 index 00000000000000..608b9901f0d351 --- /dev/null +++ b/blocks/test/fixtures/core-embed__funnyordie.serialized.html @@ -0,0 +1,7 @@ + +
    + https://funnyordie.com/ +
    Embedded content from funnyordie
    +
    + + diff --git a/blocks/test/fixtures/core-embed__hulu.html b/blocks/test/fixtures/core-embed__hulu.html new file mode 100644 index 00000000000000..44a96f4ec070f3 --- /dev/null +++ b/blocks/test/fixtures/core-embed__hulu.html @@ -0,0 +1,6 @@ + +
    + https://hulu.com/ +
    Embedded content from hulu
    +
    + diff --git a/blocks/test/fixtures/core-embedhulu.json b/blocks/test/fixtures/core-embed__hulu.json similarity index 85% rename from blocks/test/fixtures/core-embedhulu.json rename to blocks/test/fixtures/core-embed__hulu.json index 7cbe2cd792d5fc..35baceb73b1c0c 100644 --- a/blocks/test/fixtures/core-embedhulu.json +++ b/blocks/test/fixtures/core-embed__hulu.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedhulu", + "name": "core-embed/hulu", "attributes": { "url": "https://hulu.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__hulu.parsed.json b/blocks/test/fixtures/core-embed__hulu.parsed.json new file mode 100644 index 00000000000000..ed9ca2f221cda0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__hulu.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/hulu", + "attrs": { + "url": "https://hulu.com/" + }, + "rawContent": "\n
    \n https://hulu.com/\n
    Embedded content from hulu
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__hulu.serialized.html b/blocks/test/fixtures/core-embed__hulu.serialized.html new file mode 100644 index 00000000000000..dda59ed6003289 --- /dev/null +++ b/blocks/test/fixtures/core-embed__hulu.serialized.html @@ -0,0 +1,7 @@ + +
    + https://hulu.com/ +
    Embedded content from hulu
    +
    + + diff --git a/blocks/test/fixtures/core-embed__imgur.html b/blocks/test/fixtures/core-embed__imgur.html new file mode 100644 index 00000000000000..41cf134f957d20 --- /dev/null +++ b/blocks/test/fixtures/core-embed__imgur.html @@ -0,0 +1,6 @@ + +
    + https://imgur.com/ +
    Embedded content from imgur
    +
    + diff --git a/blocks/test/fixtures/core-embedimgur.json b/blocks/test/fixtures/core-embed__imgur.json similarity index 84% rename from blocks/test/fixtures/core-embedimgur.json rename to blocks/test/fixtures/core-embed__imgur.json index e0a7537ddcbc4c..ea3b38321bec05 100644 --- a/blocks/test/fixtures/core-embedimgur.json +++ b/blocks/test/fixtures/core-embed__imgur.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedimgur", + "name": "core-embed/imgur", "attributes": { "url": "https://imgur.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__imgur.parsed.json b/blocks/test/fixtures/core-embed__imgur.parsed.json new file mode 100644 index 00000000000000..347f7030ce9da7 --- /dev/null +++ b/blocks/test/fixtures/core-embed__imgur.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/imgur", + "attrs": { + "url": "https://imgur.com/" + }, + "rawContent": "\n
    \n https://imgur.com/\n
    Embedded content from imgur
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__imgur.serialized.html b/blocks/test/fixtures/core-embed__imgur.serialized.html new file mode 100644 index 00000000000000..ad14cbe6c84c4f --- /dev/null +++ b/blocks/test/fixtures/core-embed__imgur.serialized.html @@ -0,0 +1,7 @@ + +
    + https://imgur.com/ +
    Embedded content from imgur
    +
    + + diff --git a/blocks/test/fixtures/core-embed__instagram.html b/blocks/test/fixtures/core-embed__instagram.html new file mode 100644 index 00000000000000..3cf13efbc3e9c7 --- /dev/null +++ b/blocks/test/fixtures/core-embed__instagram.html @@ -0,0 +1,6 @@ + +
    + https://instagram.com/ +
    Embedded content from instagram
    +
    + diff --git a/blocks/test/fixtures/core-embedinstagram.json b/blocks/test/fixtures/core-embed__instagram.json similarity index 83% rename from blocks/test/fixtures/core-embedinstagram.json rename to blocks/test/fixtures/core-embed__instagram.json index a2d7ea8e095e50..b47836c1c0daa2 100644 --- a/blocks/test/fixtures/core-embedinstagram.json +++ b/blocks/test/fixtures/core-embed__instagram.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedinstagram", + "name": "core-embed/instagram", "attributes": { "url": "https://instagram.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__instagram.parsed.json b/blocks/test/fixtures/core-embed__instagram.parsed.json new file mode 100644 index 00000000000000..a2bce58ca6c554 --- /dev/null +++ b/blocks/test/fixtures/core-embed__instagram.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/instagram", + "attrs": { + "url": "https://instagram.com/" + }, + "rawContent": "\n
    \n https://instagram.com/\n
    Embedded content from instagram
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__instagram.serialized.html b/blocks/test/fixtures/core-embed__instagram.serialized.html new file mode 100644 index 00000000000000..358a54d0fbd2a0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__instagram.serialized.html @@ -0,0 +1,7 @@ + +
    + https://instagram.com/ +
    Embedded content from instagram
    +
    + + diff --git a/blocks/test/fixtures/core-embed__issuu.html b/blocks/test/fixtures/core-embed__issuu.html new file mode 100644 index 00000000000000..41f8a3e556edcf --- /dev/null +++ b/blocks/test/fixtures/core-embed__issuu.html @@ -0,0 +1,6 @@ + +
    + https://issuu.com/ +
    Embedded content from issuu
    +
    + diff --git a/blocks/test/fixtures/core-embedissuu.json b/blocks/test/fixtures/core-embed__issuu.json similarity index 84% rename from blocks/test/fixtures/core-embedissuu.json rename to blocks/test/fixtures/core-embed__issuu.json index f1513bd35f5b05..868cd489e5c387 100644 --- a/blocks/test/fixtures/core-embedissuu.json +++ b/blocks/test/fixtures/core-embed__issuu.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedissuu", + "name": "core-embed/issuu", "attributes": { "url": "https://issuu.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__issuu.parsed.json b/blocks/test/fixtures/core-embed__issuu.parsed.json new file mode 100644 index 00000000000000..8295d85605975f --- /dev/null +++ b/blocks/test/fixtures/core-embed__issuu.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/issuu", + "attrs": { + "url": "https://issuu.com/" + }, + "rawContent": "\n
    \n https://issuu.com/\n
    Embedded content from issuu
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__issuu.serialized.html b/blocks/test/fixtures/core-embed__issuu.serialized.html new file mode 100644 index 00000000000000..e97013bd9c8753 --- /dev/null +++ b/blocks/test/fixtures/core-embed__issuu.serialized.html @@ -0,0 +1,7 @@ + +
    + https://issuu.com/ +
    Embedded content from issuu
    +
    + + diff --git a/blocks/test/fixtures/core-embed__kickstarter.html b/blocks/test/fixtures/core-embed__kickstarter.html new file mode 100644 index 00000000000000..3032298f35bfd0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__kickstarter.html @@ -0,0 +1,6 @@ + +
    + https://kickstarter.com/ +
    Embedded content from kickstarter
    +
    + diff --git a/blocks/test/fixtures/core-embedkickstarter.json b/blocks/test/fixtures/core-embed__kickstarter.json similarity index 83% rename from blocks/test/fixtures/core-embedkickstarter.json rename to blocks/test/fixtures/core-embed__kickstarter.json index cc0a212d539e75..e917cfa1e3385e 100644 --- a/blocks/test/fixtures/core-embedkickstarter.json +++ b/blocks/test/fixtures/core-embed__kickstarter.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedkickstarter", + "name": "core-embed/kickstarter", "attributes": { "url": "https://kickstarter.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__kickstarter.parsed.json b/blocks/test/fixtures/core-embed__kickstarter.parsed.json new file mode 100644 index 00000000000000..ec5e4da18a7b4e --- /dev/null +++ b/blocks/test/fixtures/core-embed__kickstarter.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/kickstarter", + "attrs": { + "url": "https://kickstarter.com/" + }, + "rawContent": "\n
    \n https://kickstarter.com/\n
    Embedded content from kickstarter
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__kickstarter.serialized.html b/blocks/test/fixtures/core-embed__kickstarter.serialized.html new file mode 100644 index 00000000000000..b35e710436b46e --- /dev/null +++ b/blocks/test/fixtures/core-embed__kickstarter.serialized.html @@ -0,0 +1,7 @@ + +
    + https://kickstarter.com/ +
    Embedded content from kickstarter
    +
    + + diff --git a/blocks/test/fixtures/core-embed__meetup-com.html b/blocks/test/fixtures/core-embed__meetup-com.html new file mode 100644 index 00000000000000..221881f0bf8ae7 --- /dev/null +++ b/blocks/test/fixtures/core-embed__meetup-com.html @@ -0,0 +1,6 @@ + +
    + https://meetup.com/ +
    Embedded content from meetup-com
    +
    + diff --git a/blocks/test/fixtures/core-embed__meetup-com.json b/blocks/test/fixtures/core-embed__meetup-com.json new file mode 100644 index 00000000000000..f29968f9082869 --- /dev/null +++ b/blocks/test/fixtures/core-embed__meetup-com.json @@ -0,0 +1,12 @@ +[ + { + "uid": "_uid_0", + "name": "core-embed/meetup-com", + "attributes": { + "url": "https://meetup.com/", + "caption": [ + "Embedded content from meetup-com" + ] + } + } +] diff --git a/blocks/test/fixtures/core-embed__meetup-com.parsed.json b/blocks/test/fixtures/core-embed__meetup-com.parsed.json new file mode 100644 index 00000000000000..55e12e8a55f310 --- /dev/null +++ b/blocks/test/fixtures/core-embed__meetup-com.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/meetup-com", + "attrs": { + "url": "https://meetup.com/" + }, + "rawContent": "\n
    \n https://meetup.com/\n
    Embedded content from meetup-com
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__meetup-com.serialized.html b/blocks/test/fixtures/core-embed__meetup-com.serialized.html new file mode 100644 index 00000000000000..c2bb49382b4ffd --- /dev/null +++ b/blocks/test/fixtures/core-embed__meetup-com.serialized.html @@ -0,0 +1,7 @@ + +
    + https://meetup.com/ +
    Embedded content from meetup-com
    +
    + + diff --git a/blocks/test/fixtures/core-embed__mixcloud.html b/blocks/test/fixtures/core-embed__mixcloud.html new file mode 100644 index 00000000000000..f88ce4620ea62f --- /dev/null +++ b/blocks/test/fixtures/core-embed__mixcloud.html @@ -0,0 +1,6 @@ + +
    + https://mixcloud.com/ +
    Embedded content from mixcloud
    +
    + diff --git a/blocks/test/fixtures/core-embedmixcloud.json b/blocks/test/fixtures/core-embed__mixcloud.json similarity index 84% rename from blocks/test/fixtures/core-embedmixcloud.json rename to blocks/test/fixtures/core-embed__mixcloud.json index f59153c7e00ea2..1594c158acbe68 100644 --- a/blocks/test/fixtures/core-embedmixcloud.json +++ b/blocks/test/fixtures/core-embed__mixcloud.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedmixcloud", + "name": "core-embed/mixcloud", "attributes": { "url": "https://mixcloud.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__mixcloud.parsed.json b/blocks/test/fixtures/core-embed__mixcloud.parsed.json new file mode 100644 index 00000000000000..9ae1b7ce80d37a --- /dev/null +++ b/blocks/test/fixtures/core-embed__mixcloud.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/mixcloud", + "attrs": { + "url": "https://mixcloud.com/" + }, + "rawContent": "\n
    \n https://mixcloud.com/\n
    Embedded content from mixcloud
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__mixcloud.serialized.html b/blocks/test/fixtures/core-embed__mixcloud.serialized.html new file mode 100644 index 00000000000000..e6a58ae7662ff5 --- /dev/null +++ b/blocks/test/fixtures/core-embed__mixcloud.serialized.html @@ -0,0 +1,7 @@ + +
    + https://mixcloud.com/ +
    Embedded content from mixcloud
    +
    + + diff --git a/blocks/test/fixtures/core-embed__photobucket.html b/blocks/test/fixtures/core-embed__photobucket.html new file mode 100644 index 00000000000000..045edc2b90b098 --- /dev/null +++ b/blocks/test/fixtures/core-embed__photobucket.html @@ -0,0 +1,6 @@ + +
    + https://photobucket.com/ +
    Embedded content from photobucket
    +
    + diff --git a/blocks/test/fixtures/core-embedphotobucket.json b/blocks/test/fixtures/core-embed__photobucket.json similarity index 83% rename from blocks/test/fixtures/core-embedphotobucket.json rename to blocks/test/fixtures/core-embed__photobucket.json index 36514c153de13a..f8c2148cbcc77a 100644 --- a/blocks/test/fixtures/core-embedphotobucket.json +++ b/blocks/test/fixtures/core-embed__photobucket.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedphotobucket", + "name": "core-embed/photobucket", "attributes": { "url": "https://photobucket.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__photobucket.parsed.json b/blocks/test/fixtures/core-embed__photobucket.parsed.json new file mode 100644 index 00000000000000..d555f9091b5689 --- /dev/null +++ b/blocks/test/fixtures/core-embed__photobucket.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/photobucket", + "attrs": { + "url": "https://photobucket.com/" + }, + "rawContent": "\n
    \n https://photobucket.com/\n
    Embedded content from photobucket
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__photobucket.serialized.html b/blocks/test/fixtures/core-embed__photobucket.serialized.html new file mode 100644 index 00000000000000..dac6bfdfd0e045 --- /dev/null +++ b/blocks/test/fixtures/core-embed__photobucket.serialized.html @@ -0,0 +1,7 @@ + +
    + https://photobucket.com/ +
    Embedded content from photobucket
    +
    + + diff --git a/blocks/test/fixtures/core-embed__polldaddy.html b/blocks/test/fixtures/core-embed__polldaddy.html new file mode 100644 index 00000000000000..eaf97d43c9c0b8 --- /dev/null +++ b/blocks/test/fixtures/core-embed__polldaddy.html @@ -0,0 +1,6 @@ + +
    + https://polldaddy.com/ +
    Embedded content from polldaddy
    +
    + diff --git a/blocks/test/fixtures/core-embedpolldaddy.json b/blocks/test/fixtures/core-embed__polldaddy.json similarity index 83% rename from blocks/test/fixtures/core-embedpolldaddy.json rename to blocks/test/fixtures/core-embed__polldaddy.json index 018a0e1c5ea4ef..05e4cbeaf045c3 100644 --- a/blocks/test/fixtures/core-embedpolldaddy.json +++ b/blocks/test/fixtures/core-embed__polldaddy.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedpolldaddy", + "name": "core-embed/polldaddy", "attributes": { "url": "https://polldaddy.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__polldaddy.parsed.json b/blocks/test/fixtures/core-embed__polldaddy.parsed.json new file mode 100644 index 00000000000000..6629a355f0e9b9 --- /dev/null +++ b/blocks/test/fixtures/core-embed__polldaddy.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/polldaddy", + "attrs": { + "url": "https://polldaddy.com/" + }, + "rawContent": "\n
    \n https://polldaddy.com/\n
    Embedded content from polldaddy
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__polldaddy.serialized.html b/blocks/test/fixtures/core-embed__polldaddy.serialized.html new file mode 100644 index 00000000000000..d124765b91db0d --- /dev/null +++ b/blocks/test/fixtures/core-embed__polldaddy.serialized.html @@ -0,0 +1,7 @@ + +
    + https://polldaddy.com/ +
    Embedded content from polldaddy
    +
    + + diff --git a/blocks/test/fixtures/core-embed__reddit.html b/blocks/test/fixtures/core-embed__reddit.html new file mode 100644 index 00000000000000..dbdf756fe06c85 --- /dev/null +++ b/blocks/test/fixtures/core-embed__reddit.html @@ -0,0 +1,6 @@ + +
    + https://reddit.com/ +
    Embedded content from reddit
    +
    + diff --git a/blocks/test/fixtures/core-embedreddit.json b/blocks/test/fixtures/core-embed__reddit.json similarity index 84% rename from blocks/test/fixtures/core-embedreddit.json rename to blocks/test/fixtures/core-embed__reddit.json index 011034075516ea..a04125b76926be 100644 --- a/blocks/test/fixtures/core-embedreddit.json +++ b/blocks/test/fixtures/core-embed__reddit.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedreddit", + "name": "core-embed/reddit", "attributes": { "url": "https://reddit.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__reddit.parsed.json b/blocks/test/fixtures/core-embed__reddit.parsed.json new file mode 100644 index 00000000000000..71d7fd1d48cbb0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__reddit.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/reddit", + "attrs": { + "url": "https://reddit.com/" + }, + "rawContent": "\n
    \n https://reddit.com/\n
    Embedded content from reddit
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__reddit.serialized.html b/blocks/test/fixtures/core-embed__reddit.serialized.html new file mode 100644 index 00000000000000..545afe9419afeb --- /dev/null +++ b/blocks/test/fixtures/core-embed__reddit.serialized.html @@ -0,0 +1,7 @@ + +
    + https://reddit.com/ +
    Embedded content from reddit
    +
    + + diff --git a/blocks/test/fixtures/core-embed__reverbnation.html b/blocks/test/fixtures/core-embed__reverbnation.html new file mode 100644 index 00000000000000..5015f02812540c --- /dev/null +++ b/blocks/test/fixtures/core-embed__reverbnation.html @@ -0,0 +1,6 @@ + +
    + https://reverbnation.com/ +
    Embedded content from reverbnation
    +
    + diff --git a/blocks/test/fixtures/core-embedreverbnation.json b/blocks/test/fixtures/core-embed__reverbnation.json similarity index 83% rename from blocks/test/fixtures/core-embedreverbnation.json rename to blocks/test/fixtures/core-embed__reverbnation.json index 44d1f94f2c59c2..de0f5c62ef564d 100644 --- a/blocks/test/fixtures/core-embedreverbnation.json +++ b/blocks/test/fixtures/core-embed__reverbnation.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedreverbnation", + "name": "core-embed/reverbnation", "attributes": { "url": "https://reverbnation.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__reverbnation.parsed.json b/blocks/test/fixtures/core-embed__reverbnation.parsed.json new file mode 100644 index 00000000000000..b06041940dccff --- /dev/null +++ b/blocks/test/fixtures/core-embed__reverbnation.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/reverbnation", + "attrs": { + "url": "https://reverbnation.com/" + }, + "rawContent": "\n
    \n https://reverbnation.com/\n
    Embedded content from reverbnation
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__reverbnation.serialized.html b/blocks/test/fixtures/core-embed__reverbnation.serialized.html new file mode 100644 index 00000000000000..d61d5d5b270891 --- /dev/null +++ b/blocks/test/fixtures/core-embed__reverbnation.serialized.html @@ -0,0 +1,7 @@ + +
    + https://reverbnation.com/ +
    Embedded content from reverbnation
    +
    + + diff --git a/blocks/test/fixtures/core-embed__screencast.html b/blocks/test/fixtures/core-embed__screencast.html new file mode 100644 index 00000000000000..69a132e33f867b --- /dev/null +++ b/blocks/test/fixtures/core-embed__screencast.html @@ -0,0 +1,6 @@ + +
    + https://screencast.com/ +
    Embedded content from screencast
    +
    + diff --git a/blocks/test/fixtures/core-embedscreencast.json b/blocks/test/fixtures/core-embed__screencast.json similarity index 83% rename from blocks/test/fixtures/core-embedscreencast.json rename to blocks/test/fixtures/core-embed__screencast.json index 6dec7a9a1a5322..a34839a87c2435 100644 --- a/blocks/test/fixtures/core-embedscreencast.json +++ b/blocks/test/fixtures/core-embed__screencast.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedscreencast", + "name": "core-embed/screencast", "attributes": { "url": "https://screencast.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__screencast.parsed.json b/blocks/test/fixtures/core-embed__screencast.parsed.json new file mode 100644 index 00000000000000..b32db115366573 --- /dev/null +++ b/blocks/test/fixtures/core-embed__screencast.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/screencast", + "attrs": { + "url": "https://screencast.com/" + }, + "rawContent": "\n
    \n https://screencast.com/\n
    Embedded content from screencast
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__screencast.serialized.html b/blocks/test/fixtures/core-embed__screencast.serialized.html new file mode 100644 index 00000000000000..9be1814e0ffdc4 --- /dev/null +++ b/blocks/test/fixtures/core-embed__screencast.serialized.html @@ -0,0 +1,7 @@ + +
    + https://screencast.com/ +
    Embedded content from screencast
    +
    + + diff --git a/blocks/test/fixtures/core-embed__scribd.html b/blocks/test/fixtures/core-embed__scribd.html new file mode 100644 index 00000000000000..5d960344af60dd --- /dev/null +++ b/blocks/test/fixtures/core-embed__scribd.html @@ -0,0 +1,6 @@ + +
    + https://scribd.com/ +
    Embedded content from scribd
    +
    + diff --git a/blocks/test/fixtures/core-embedscribd.json b/blocks/test/fixtures/core-embed__scribd.json similarity index 84% rename from blocks/test/fixtures/core-embedscribd.json rename to blocks/test/fixtures/core-embed__scribd.json index 5efcbdf619f5b0..81789fe717be3a 100644 --- a/blocks/test/fixtures/core-embedscribd.json +++ b/blocks/test/fixtures/core-embed__scribd.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedscribd", + "name": "core-embed/scribd", "attributes": { "url": "https://scribd.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__scribd.parsed.json b/blocks/test/fixtures/core-embed__scribd.parsed.json new file mode 100644 index 00000000000000..50922c445263cd --- /dev/null +++ b/blocks/test/fixtures/core-embed__scribd.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/scribd", + "attrs": { + "url": "https://scribd.com/" + }, + "rawContent": "\n
    \n https://scribd.com/\n
    Embedded content from scribd
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__scribd.serialized.html b/blocks/test/fixtures/core-embed__scribd.serialized.html new file mode 100644 index 00000000000000..bdddf5f3c65429 --- /dev/null +++ b/blocks/test/fixtures/core-embed__scribd.serialized.html @@ -0,0 +1,7 @@ + +
    + https://scribd.com/ +
    Embedded content from scribd
    +
    + + diff --git a/blocks/test/fixtures/core-embed__slideshare.html b/blocks/test/fixtures/core-embed__slideshare.html new file mode 100644 index 00000000000000..53435e5bafef63 --- /dev/null +++ b/blocks/test/fixtures/core-embed__slideshare.html @@ -0,0 +1,6 @@ + +
    + https://slideshare.com/ +
    Embedded content from slideshare
    +
    + diff --git a/blocks/test/fixtures/core-embedslideshare.json b/blocks/test/fixtures/core-embed__slideshare.json similarity index 83% rename from blocks/test/fixtures/core-embedslideshare.json rename to blocks/test/fixtures/core-embed__slideshare.json index 9010eb8206755a..db0f30df975a9f 100644 --- a/blocks/test/fixtures/core-embedslideshare.json +++ b/blocks/test/fixtures/core-embed__slideshare.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedslideshare", + "name": "core-embed/slideshare", "attributes": { "url": "https://slideshare.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__slideshare.parsed.json b/blocks/test/fixtures/core-embed__slideshare.parsed.json new file mode 100644 index 00000000000000..523505936a96de --- /dev/null +++ b/blocks/test/fixtures/core-embed__slideshare.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/slideshare", + "attrs": { + "url": "https://slideshare.com/" + }, + "rawContent": "\n
    \n https://slideshare.com/\n
    Embedded content from slideshare
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__slideshare.serialized.html b/blocks/test/fixtures/core-embed__slideshare.serialized.html new file mode 100644 index 00000000000000..7e8bd7559e87a4 --- /dev/null +++ b/blocks/test/fixtures/core-embed__slideshare.serialized.html @@ -0,0 +1,7 @@ + +
    + https://slideshare.com/ +
    Embedded content from slideshare
    +
    + + diff --git a/blocks/test/fixtures/core-embed__smugmug.html b/blocks/test/fixtures/core-embed__smugmug.html new file mode 100644 index 00000000000000..2c340e414b6606 --- /dev/null +++ b/blocks/test/fixtures/core-embed__smugmug.html @@ -0,0 +1,6 @@ + +
    + https://smugmug.com/ +
    Embedded content from smugmug
    +
    + diff --git a/blocks/test/fixtures/core-embedsmugmug.json b/blocks/test/fixtures/core-embed__smugmug.json similarity index 84% rename from blocks/test/fixtures/core-embedsmugmug.json rename to blocks/test/fixtures/core-embed__smugmug.json index cecab2e26b8e50..5b705c05e5c7d5 100644 --- a/blocks/test/fixtures/core-embedsmugmug.json +++ b/blocks/test/fixtures/core-embed__smugmug.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedsmugmug", + "name": "core-embed/smugmug", "attributes": { "url": "https://smugmug.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__smugmug.parsed.json b/blocks/test/fixtures/core-embed__smugmug.parsed.json new file mode 100644 index 00000000000000..4dba20d68362a2 --- /dev/null +++ b/blocks/test/fixtures/core-embed__smugmug.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/smugmug", + "attrs": { + "url": "https://smugmug.com/" + }, + "rawContent": "\n
    \n https://smugmug.com/\n
    Embedded content from smugmug
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__smugmug.serialized.html b/blocks/test/fixtures/core-embed__smugmug.serialized.html new file mode 100644 index 00000000000000..dd32192fa56e61 --- /dev/null +++ b/blocks/test/fixtures/core-embed__smugmug.serialized.html @@ -0,0 +1,7 @@ + +
    + https://smugmug.com/ +
    Embedded content from smugmug
    +
    + + diff --git a/blocks/test/fixtures/core-embed__soundcloud.html b/blocks/test/fixtures/core-embed__soundcloud.html new file mode 100644 index 00000000000000..9bc65d3b98839d --- /dev/null +++ b/blocks/test/fixtures/core-embed__soundcloud.html @@ -0,0 +1,6 @@ + +
    + https://soundcloud.com/ +
    Embedded content from soundcloud
    +
    + diff --git a/blocks/test/fixtures/core-embedsoundcloud.json b/blocks/test/fixtures/core-embed__soundcloud.json similarity index 83% rename from blocks/test/fixtures/core-embedsoundcloud.json rename to blocks/test/fixtures/core-embed__soundcloud.json index 637ecec8577f85..210360add6681b 100644 --- a/blocks/test/fixtures/core-embedsoundcloud.json +++ b/blocks/test/fixtures/core-embed__soundcloud.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedsoundcloud", + "name": "core-embed/soundcloud", "attributes": { "url": "https://soundcloud.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__soundcloud.parsed.json b/blocks/test/fixtures/core-embed__soundcloud.parsed.json new file mode 100644 index 00000000000000..97553adfaba9f5 --- /dev/null +++ b/blocks/test/fixtures/core-embed__soundcloud.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/soundcloud", + "attrs": { + "url": "https://soundcloud.com/" + }, + "rawContent": "\n
    \n https://soundcloud.com/\n
    Embedded content from soundcloud
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__soundcloud.serialized.html b/blocks/test/fixtures/core-embed__soundcloud.serialized.html new file mode 100644 index 00000000000000..61cb25dc74c495 --- /dev/null +++ b/blocks/test/fixtures/core-embed__soundcloud.serialized.html @@ -0,0 +1,7 @@ + +
    + https://soundcloud.com/ +
    Embedded content from soundcloud
    +
    + + diff --git a/blocks/test/fixtures/core-embed__speaker.html b/blocks/test/fixtures/core-embed__speaker.html new file mode 100644 index 00000000000000..c458601cf0ec50 --- /dev/null +++ b/blocks/test/fixtures/core-embed__speaker.html @@ -0,0 +1,6 @@ + +
    + https://speaker.com/ +
    Embedded content from speaker
    +
    + diff --git a/blocks/test/fixtures/core-embedspeaker.json b/blocks/test/fixtures/core-embed__speaker.json similarity index 84% rename from blocks/test/fixtures/core-embedspeaker.json rename to blocks/test/fixtures/core-embed__speaker.json index 0f0c54b3f0f772..7fea3ba89edbde 100644 --- a/blocks/test/fixtures/core-embedspeaker.json +++ b/blocks/test/fixtures/core-embed__speaker.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedspeaker", + "name": "core-embed/speaker", "attributes": { "url": "https://speaker.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__speaker.parsed.json b/blocks/test/fixtures/core-embed__speaker.parsed.json new file mode 100644 index 00000000000000..127334955b576d --- /dev/null +++ b/blocks/test/fixtures/core-embed__speaker.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/speaker", + "attrs": { + "url": "https://speaker.com/" + }, + "rawContent": "\n
    \n https://speaker.com/\n
    Embedded content from speaker
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__speaker.serialized.html b/blocks/test/fixtures/core-embed__speaker.serialized.html new file mode 100644 index 00000000000000..c193768710e72e --- /dev/null +++ b/blocks/test/fixtures/core-embed__speaker.serialized.html @@ -0,0 +1,7 @@ + +
    + https://speaker.com/ +
    Embedded content from speaker
    +
    + + diff --git a/blocks/test/fixtures/core-embed__spotify.html b/blocks/test/fixtures/core-embed__spotify.html new file mode 100644 index 00000000000000..a4713c74edf9e0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__spotify.html @@ -0,0 +1,6 @@ + +
    + https://spotify.com/ +
    Embedded content from spotify
    +
    + diff --git a/blocks/test/fixtures/core-embedspotify.json b/blocks/test/fixtures/core-embed__spotify.json similarity index 84% rename from blocks/test/fixtures/core-embedspotify.json rename to blocks/test/fixtures/core-embed__spotify.json index 2e712f86c1ec4a..2e1076dbb0c5fd 100644 --- a/blocks/test/fixtures/core-embedspotify.json +++ b/blocks/test/fixtures/core-embed__spotify.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedspotify", + "name": "core-embed/spotify", "attributes": { "url": "https://spotify.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__spotify.parsed.json b/blocks/test/fixtures/core-embed__spotify.parsed.json new file mode 100644 index 00000000000000..0c3167f1dc130f --- /dev/null +++ b/blocks/test/fixtures/core-embed__spotify.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/spotify", + "attrs": { + "url": "https://spotify.com/" + }, + "rawContent": "\n
    \n https://spotify.com/\n
    Embedded content from spotify
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__spotify.serialized.html b/blocks/test/fixtures/core-embed__spotify.serialized.html new file mode 100644 index 00000000000000..96b1a511ad1f17 --- /dev/null +++ b/blocks/test/fixtures/core-embed__spotify.serialized.html @@ -0,0 +1,7 @@ + +
    + https://spotify.com/ +
    Embedded content from spotify
    +
    + + diff --git a/blocks/test/fixtures/core-embed__ted.html b/blocks/test/fixtures/core-embed__ted.html new file mode 100644 index 00000000000000..ed6b0ef0ca02ab --- /dev/null +++ b/blocks/test/fixtures/core-embed__ted.html @@ -0,0 +1,6 @@ + +
    + https://ted.com/ +
    Embedded content from ted
    +
    + diff --git a/blocks/test/fixtures/core-embedted.json b/blocks/test/fixtures/core-embed__ted.json similarity index 85% rename from blocks/test/fixtures/core-embedted.json rename to blocks/test/fixtures/core-embed__ted.json index 13c190858f8c76..5011154882c69f 100644 --- a/blocks/test/fixtures/core-embedted.json +++ b/blocks/test/fixtures/core-embed__ted.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedted", + "name": "core-embed/ted", "attributes": { "url": "https://ted.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__ted.parsed.json b/blocks/test/fixtures/core-embed__ted.parsed.json new file mode 100644 index 00000000000000..6ee770cf1a0831 --- /dev/null +++ b/blocks/test/fixtures/core-embed__ted.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/ted", + "attrs": { + "url": "https://ted.com/" + }, + "rawContent": "\n
    \n https://ted.com/\n
    Embedded content from ted
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__ted.serialized.html b/blocks/test/fixtures/core-embed__ted.serialized.html new file mode 100644 index 00000000000000..24e3939e19c336 --- /dev/null +++ b/blocks/test/fixtures/core-embed__ted.serialized.html @@ -0,0 +1,7 @@ + +
    + https://ted.com/ +
    Embedded content from ted
    +
    + + diff --git a/blocks/test/fixtures/core-embed__tumblr.html b/blocks/test/fixtures/core-embed__tumblr.html new file mode 100644 index 00000000000000..6d323c0287889e --- /dev/null +++ b/blocks/test/fixtures/core-embed__tumblr.html @@ -0,0 +1,6 @@ + +
    + https://tumblr.com/ +
    Embedded content from tumblr
    +
    + diff --git a/blocks/test/fixtures/core-embedtumblr.json b/blocks/test/fixtures/core-embed__tumblr.json similarity index 84% rename from blocks/test/fixtures/core-embedtumblr.json rename to blocks/test/fixtures/core-embed__tumblr.json index 17e23cd9a8d0c4..ba37f49055801d 100644 --- a/blocks/test/fixtures/core-embedtumblr.json +++ b/blocks/test/fixtures/core-embed__tumblr.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedtumblr", + "name": "core-embed/tumblr", "attributes": { "url": "https://tumblr.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__tumblr.parsed.json b/blocks/test/fixtures/core-embed__tumblr.parsed.json new file mode 100644 index 00000000000000..dfed848f337c56 --- /dev/null +++ b/blocks/test/fixtures/core-embed__tumblr.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/tumblr", + "attrs": { + "url": "https://tumblr.com/" + }, + "rawContent": "\n
    \n https://tumblr.com/\n
    Embedded content from tumblr
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__tumblr.serialized.html b/blocks/test/fixtures/core-embed__tumblr.serialized.html new file mode 100644 index 00000000000000..64d2e470c49d52 --- /dev/null +++ b/blocks/test/fixtures/core-embed__tumblr.serialized.html @@ -0,0 +1,7 @@ + +
    + https://tumblr.com/ +
    Embedded content from tumblr
    +
    + + diff --git a/blocks/test/fixtures/core-embed__twitter.html b/blocks/test/fixtures/core-embed__twitter.html new file mode 100644 index 00000000000000..0c4dea12a0e811 --- /dev/null +++ b/blocks/test/fixtures/core-embed__twitter.html @@ -0,0 +1,6 @@ + +
    + https://twitter.com/automattic +
    We are Automattic
    +
    + diff --git a/blocks/test/fixtures/core-embedtwitter.json b/blocks/test/fixtures/core-embed__twitter.json similarity index 84% rename from blocks/test/fixtures/core-embedtwitter.json rename to blocks/test/fixtures/core-embed__twitter.json index b9d463c77dcebd..ff35783fbeeaa9 100644 --- a/blocks/test/fixtures/core-embedtwitter.json +++ b/blocks/test/fixtures/core-embed__twitter.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedtwitter", + "name": "core-embed/twitter", "attributes": { "url": "https://twitter.com/automattic", "caption": [ diff --git a/blocks/test/fixtures/core-embed__twitter.parsed.json b/blocks/test/fixtures/core-embed__twitter.parsed.json new file mode 100644 index 00000000000000..d6d343f46de5e6 --- /dev/null +++ b/blocks/test/fixtures/core-embed__twitter.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/twitter", + "attrs": { + "url": "https://twitter.com/automattic" + }, + "rawContent": "\n
    \n https://twitter.com/automattic\n
    We are Automattic
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__twitter.serialized.html b/blocks/test/fixtures/core-embed__twitter.serialized.html new file mode 100644 index 00000000000000..817d3f66df3b6d --- /dev/null +++ b/blocks/test/fixtures/core-embed__twitter.serialized.html @@ -0,0 +1,7 @@ + +
    + https://twitter.com/automattic +
    We are Automattic
    +
    + + diff --git a/blocks/test/fixtures/core-embed__videopress.html b/blocks/test/fixtures/core-embed__videopress.html new file mode 100644 index 00000000000000..30caf20e702259 --- /dev/null +++ b/blocks/test/fixtures/core-embed__videopress.html @@ -0,0 +1,6 @@ + +
    + https://videopress.com/ +
    Embedded content from videopress
    +
    + diff --git a/blocks/test/fixtures/core-embedvideopress.json b/blocks/test/fixtures/core-embed__videopress.json similarity index 83% rename from blocks/test/fixtures/core-embedvideopress.json rename to blocks/test/fixtures/core-embed__videopress.json index 8b8f35ff484b57..65e9458e95d877 100644 --- a/blocks/test/fixtures/core-embedvideopress.json +++ b/blocks/test/fixtures/core-embed__videopress.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedvideopress", + "name": "core-embed/videopress", "attributes": { "url": "https://videopress.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__videopress.parsed.json b/blocks/test/fixtures/core-embed__videopress.parsed.json new file mode 100644 index 00000000000000..5076dc3437aa9b --- /dev/null +++ b/blocks/test/fixtures/core-embed__videopress.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/videopress", + "attrs": { + "url": "https://videopress.com/" + }, + "rawContent": "\n
    \n https://videopress.com/\n
    Embedded content from videopress
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__videopress.serialized.html b/blocks/test/fixtures/core-embed__videopress.serialized.html new file mode 100644 index 00000000000000..756ab1521df778 --- /dev/null +++ b/blocks/test/fixtures/core-embed__videopress.serialized.html @@ -0,0 +1,7 @@ + +
    + https://videopress.com/ +
    Embedded content from videopress
    +
    + + diff --git a/blocks/test/fixtures/core-embed__vimeo.html b/blocks/test/fixtures/core-embed__vimeo.html new file mode 100644 index 00000000000000..4f0bbfceb9eafc --- /dev/null +++ b/blocks/test/fixtures/core-embed__vimeo.html @@ -0,0 +1,6 @@ + +
    + https://vimeo.com/ +
    Embedded content from vimeo
    +
    + diff --git a/blocks/test/fixtures/core-embedvimeo.json b/blocks/test/fixtures/core-embed__vimeo.json similarity index 84% rename from blocks/test/fixtures/core-embedvimeo.json rename to blocks/test/fixtures/core-embed__vimeo.json index 828eea64c814d1..a1f215beed6a8b 100644 --- a/blocks/test/fixtures/core-embedvimeo.json +++ b/blocks/test/fixtures/core-embed__vimeo.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedvimeo", + "name": "core-embed/vimeo", "attributes": { "url": "https://vimeo.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__vimeo.parsed.json b/blocks/test/fixtures/core-embed__vimeo.parsed.json new file mode 100644 index 00000000000000..b25b1ce8b02a74 --- /dev/null +++ b/blocks/test/fixtures/core-embed__vimeo.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/vimeo", + "attrs": { + "url": "https://vimeo.com/" + }, + "rawContent": "\n
    \n https://vimeo.com/\n
    Embedded content from vimeo
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__vimeo.serialized.html b/blocks/test/fixtures/core-embed__vimeo.serialized.html new file mode 100644 index 00000000000000..b0914dba977211 --- /dev/null +++ b/blocks/test/fixtures/core-embed__vimeo.serialized.html @@ -0,0 +1,7 @@ + +
    + https://vimeo.com/ +
    Embedded content from vimeo
    +
    + + diff --git a/blocks/test/fixtures/core-embed__vine.html b/blocks/test/fixtures/core-embed__vine.html new file mode 100644 index 00000000000000..3d412392ea304d --- /dev/null +++ b/blocks/test/fixtures/core-embed__vine.html @@ -0,0 +1,6 @@ + +
    + https://vine.com/ +
    Embedded content from vine
    +
    + diff --git a/blocks/test/fixtures/core-embedvine.json b/blocks/test/fixtures/core-embed__vine.json similarity index 85% rename from blocks/test/fixtures/core-embedvine.json rename to blocks/test/fixtures/core-embed__vine.json index e62878c5dc38a7..af44e8956044ca 100644 --- a/blocks/test/fixtures/core-embedvine.json +++ b/blocks/test/fixtures/core-embed__vine.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedvine", + "name": "core-embed/vine", "attributes": { "url": "https://vine.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__vine.parsed.json b/blocks/test/fixtures/core-embed__vine.parsed.json new file mode 100644 index 00000000000000..a52b9b41090066 --- /dev/null +++ b/blocks/test/fixtures/core-embed__vine.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/vine", + "attrs": { + "url": "https://vine.com/" + }, + "rawContent": "\n
    \n https://vine.com/\n
    Embedded content from vine
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__vine.serialized.html b/blocks/test/fixtures/core-embed__vine.serialized.html new file mode 100644 index 00000000000000..52983e6eab6ff0 --- /dev/null +++ b/blocks/test/fixtures/core-embed__vine.serialized.html @@ -0,0 +1,7 @@ + +
    + https://vine.com/ +
    Embedded content from vine
    +
    + + diff --git a/blocks/test/fixtures/core-embed__wordpress-tv.html b/blocks/test/fixtures/core-embed__wordpress-tv.html new file mode 100644 index 00000000000000..c978ca92539bfc --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress-tv.html @@ -0,0 +1,6 @@ + +
    + https://wordpress.tv/ +
    Embedded content from wordpress-tv
    +
    + diff --git a/blocks/test/fixtures/core-embed__wordpress-tv.json b/blocks/test/fixtures/core-embed__wordpress-tv.json new file mode 100644 index 00000000000000..8bf8d711faad06 --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress-tv.json @@ -0,0 +1,12 @@ +[ + { + "uid": "_uid_0", + "name": "core-embed/wordpress-tv", + "attributes": { + "url": "https://wordpress.tv/", + "caption": [ + "Embedded content from wordpress-tv" + ] + } + } +] diff --git a/blocks/test/fixtures/core-embed__wordpress-tv.parsed.json b/blocks/test/fixtures/core-embed__wordpress-tv.parsed.json new file mode 100644 index 00000000000000..1f4427486cee99 --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress-tv.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/wordpress-tv", + "attrs": { + "url": "https://wordpress.tv/" + }, + "rawContent": "\n
    \n https://wordpress.tv/\n
    Embedded content from wordpress-tv
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__wordpress-tv.serialized.html b/blocks/test/fixtures/core-embed__wordpress-tv.serialized.html new file mode 100644 index 00000000000000..bad4644955123f --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress-tv.serialized.html @@ -0,0 +1,7 @@ + +
    + https://wordpress.tv/ +
    Embedded content from wordpress-tv
    +
    + + diff --git a/blocks/test/fixtures/core-embed__wordpress.html b/blocks/test/fixtures/core-embed__wordpress.html new file mode 100644 index 00000000000000..ebe2b6df83f724 --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress.html @@ -0,0 +1,6 @@ + +
    + https://wordpress.com/ +
    Embedded content from WordPress
    +
    + diff --git a/blocks/test/fixtures/core-embedwordpress.json b/blocks/test/fixtures/core-embed__wordpress.json similarity index 83% rename from blocks/test/fixtures/core-embedwordpress.json rename to blocks/test/fixtures/core-embed__wordpress.json index 49ce85cd129344..eb24c5f14258d0 100644 --- a/blocks/test/fixtures/core-embedwordpress.json +++ b/blocks/test/fixtures/core-embed__wordpress.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedwordpress", + "name": "core-embed/wordpress", "attributes": { "url": "https://wordpress.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__wordpress.parsed.json b/blocks/test/fixtures/core-embed__wordpress.parsed.json new file mode 100644 index 00000000000000..283eb9495ab54c --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/wordpress", + "attrs": { + "url": "https://wordpress.com/" + }, + "rawContent": "\n
    \n https://wordpress.com/\n
    Embedded content from WordPress
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__wordpress.serialized.html b/blocks/test/fixtures/core-embed__wordpress.serialized.html new file mode 100644 index 00000000000000..220298c9942796 --- /dev/null +++ b/blocks/test/fixtures/core-embed__wordpress.serialized.html @@ -0,0 +1,7 @@ + +
    + https://wordpress.com/ +
    Embedded content from WordPress
    +
    + + diff --git a/blocks/test/fixtures/core-embed__youtube.html b/blocks/test/fixtures/core-embed__youtube.html new file mode 100644 index 00000000000000..f69ae07a8f7200 --- /dev/null +++ b/blocks/test/fixtures/core-embed__youtube.html @@ -0,0 +1,6 @@ + +
    + https://youtube.com/ +
    Embedded content from youtube
    +
    + diff --git a/blocks/test/fixtures/core-embedyoutube.json b/blocks/test/fixtures/core-embed__youtube.json similarity index 84% rename from blocks/test/fixtures/core-embedyoutube.json rename to blocks/test/fixtures/core-embed__youtube.json index 7beb5a715dfef6..e03983346dcee9 100644 --- a/blocks/test/fixtures/core-embedyoutube.json +++ b/blocks/test/fixtures/core-embed__youtube.json @@ -1,7 +1,7 @@ [ { "uid": "_uid_0", - "name": "core/embedyoutube", + "name": "core-embed/youtube", "attributes": { "url": "https://youtube.com/", "caption": [ diff --git a/blocks/test/fixtures/core-embed__youtube.parsed.json b/blocks/test/fixtures/core-embed__youtube.parsed.json new file mode 100644 index 00000000000000..6438051183d908 --- /dev/null +++ b/blocks/test/fixtures/core-embed__youtube.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core-embed/youtube", + "attrs": { + "url": "https://youtube.com/" + }, + "rawContent": "\n
    \n https://youtube.com/\n
    Embedded content from youtube
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed__youtube.serialized.html b/blocks/test/fixtures/core-embed__youtube.serialized.html new file mode 100644 index 00000000000000..4fa028c1d6d27c --- /dev/null +++ b/blocks/test/fixtures/core-embed__youtube.serialized.html @@ -0,0 +1,7 @@ + +
    + https://youtube.com/ +
    Embedded content from youtube
    +
    + + diff --git a/blocks/test/fixtures/core-embedanimoto.html b/blocks/test/fixtures/core-embedanimoto.html deleted file mode 100644 index 0e464a377f248d..00000000000000 --- a/blocks/test/fixtures/core-embedanimoto.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://animoto.com/ -
    Embedded content from animoto
    -
    - diff --git a/blocks/test/fixtures/core-embedanimoto.serialized.html b/blocks/test/fixtures/core-embedanimoto.serialized.html deleted file mode 100644 index e33c67b8256d61..00000000000000 --- a/blocks/test/fixtures/core-embedanimoto.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://animoto.com/ -
    Embedded content from animoto
    -
    - - diff --git a/blocks/test/fixtures/core-embedcloudup.html b/blocks/test/fixtures/core-embedcloudup.html deleted file mode 100644 index 4650c84b4b703c..00000000000000 --- a/blocks/test/fixtures/core-embedcloudup.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://cloudup.com/ -
    Embedded content from cloudup
    -
    - diff --git a/blocks/test/fixtures/core-embedcloudup.serialized.html b/blocks/test/fixtures/core-embedcloudup.serialized.html deleted file mode 100644 index 02951c1171ec50..00000000000000 --- a/blocks/test/fixtures/core-embedcloudup.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://cloudup.com/ -
    Embedded content from cloudup
    -
    - - diff --git a/blocks/test/fixtures/core-embedcollegehumor.html b/blocks/test/fixtures/core-embedcollegehumor.html deleted file mode 100644 index 5ecdbc3e4dd880..00000000000000 --- a/blocks/test/fixtures/core-embedcollegehumor.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://collegehumor.com/ -
    Embedded content from collegehumor
    -
    - diff --git a/blocks/test/fixtures/core-embedcollegehumor.serialized.html b/blocks/test/fixtures/core-embedcollegehumor.serialized.html deleted file mode 100644 index 82ffd18b7c8296..00000000000000 --- a/blocks/test/fixtures/core-embedcollegehumor.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://collegehumor.com/ -
    Embedded content from collegehumor
    -
    - - diff --git a/blocks/test/fixtures/core-embeddailymotion.html b/blocks/test/fixtures/core-embeddailymotion.html deleted file mode 100644 index 08bed7270fe70d..00000000000000 --- a/blocks/test/fixtures/core-embeddailymotion.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://dailymotion.com/ -
    Embedded content from dailymotion
    -
    - diff --git a/blocks/test/fixtures/core-embeddailymotion.serialized.html b/blocks/test/fixtures/core-embeddailymotion.serialized.html deleted file mode 100644 index 62f55871d1e1fc..00000000000000 --- a/blocks/test/fixtures/core-embeddailymotion.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://dailymotion.com/ -
    Embedded content from dailymotion
    -
    - - diff --git a/blocks/test/fixtures/core-embedfacebook.html b/blocks/test/fixtures/core-embedfacebook.html deleted file mode 100644 index 4a5044c13d6cdc..00000000000000 --- a/blocks/test/fixtures/core-embedfacebook.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://facebook.com/ -
    Embedded content from facebook
    -
    - diff --git a/blocks/test/fixtures/core-embedfacebook.serialized.html b/blocks/test/fixtures/core-embedfacebook.serialized.html deleted file mode 100644 index efda5813641da2..00000000000000 --- a/blocks/test/fixtures/core-embedfacebook.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://facebook.com/ -
    Embedded content from facebook
    -
    - - diff --git a/blocks/test/fixtures/core-embedflickr.html b/blocks/test/fixtures/core-embedflickr.html deleted file mode 100644 index 2325790efcab2a..00000000000000 --- a/blocks/test/fixtures/core-embedflickr.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://flickr.com/ -
    Embedded content from flickr
    -
    - diff --git a/blocks/test/fixtures/core-embedflickr.serialized.html b/blocks/test/fixtures/core-embedflickr.serialized.html deleted file mode 100644 index 4d86c30f5b8811..00000000000000 --- a/blocks/test/fixtures/core-embedflickr.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://flickr.com/ -
    Embedded content from flickr
    -
    - - diff --git a/blocks/test/fixtures/core-embedfunnyordie.html b/blocks/test/fixtures/core-embedfunnyordie.html deleted file mode 100644 index 67e845a743e95d..00000000000000 --- a/blocks/test/fixtures/core-embedfunnyordie.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://funnyordie.com/ -
    Embedded content from funnyordie
    -
    - diff --git a/blocks/test/fixtures/core-embedfunnyordie.serialized.html b/blocks/test/fixtures/core-embedfunnyordie.serialized.html deleted file mode 100644 index bba227b1c1956e..00000000000000 --- a/blocks/test/fixtures/core-embedfunnyordie.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://funnyordie.com/ -
    Embedded content from funnyordie
    -
    - - diff --git a/blocks/test/fixtures/core-embedhulu.html b/blocks/test/fixtures/core-embedhulu.html deleted file mode 100644 index 749b3ecb99aeeb..00000000000000 --- a/blocks/test/fixtures/core-embedhulu.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://hulu.com/ -
    Embedded content from hulu
    -
    - diff --git a/blocks/test/fixtures/core-embedhulu.serialized.html b/blocks/test/fixtures/core-embedhulu.serialized.html deleted file mode 100644 index c9c5b31537a69a..00000000000000 --- a/blocks/test/fixtures/core-embedhulu.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://hulu.com/ -
    Embedded content from hulu
    -
    - - diff --git a/blocks/test/fixtures/core-embedimgur.html b/blocks/test/fixtures/core-embedimgur.html deleted file mode 100644 index 93f03e68d48d8e..00000000000000 --- a/blocks/test/fixtures/core-embedimgur.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://imgur.com/ -
    Embedded content from imgur
    -
    - diff --git a/blocks/test/fixtures/core-embedimgur.serialized.html b/blocks/test/fixtures/core-embedimgur.serialized.html deleted file mode 100644 index e1e3510c97eab8..00000000000000 --- a/blocks/test/fixtures/core-embedimgur.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://imgur.com/ -
    Embedded content from imgur
    -
    - - diff --git a/blocks/test/fixtures/core-embedinstagram.html b/blocks/test/fixtures/core-embedinstagram.html deleted file mode 100644 index 12dc0d1ec08537..00000000000000 --- a/blocks/test/fixtures/core-embedinstagram.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://instagram.com/ -
    Embedded content from instagram
    -
    - diff --git a/blocks/test/fixtures/core-embedinstagram.serialized.html b/blocks/test/fixtures/core-embedinstagram.serialized.html deleted file mode 100644 index 018a38ab8d52b0..00000000000000 --- a/blocks/test/fixtures/core-embedinstagram.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://instagram.com/ -
    Embedded content from instagram
    -
    - - diff --git a/blocks/test/fixtures/core-embedissuu.html b/blocks/test/fixtures/core-embedissuu.html deleted file mode 100644 index 6849278719bc4d..00000000000000 --- a/blocks/test/fixtures/core-embedissuu.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://issuu.com/ -
    Embedded content from issuu
    -
    - diff --git a/blocks/test/fixtures/core-embedissuu.serialized.html b/blocks/test/fixtures/core-embedissuu.serialized.html deleted file mode 100644 index 18903978bd6e18..00000000000000 --- a/blocks/test/fixtures/core-embedissuu.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://issuu.com/ -
    Embedded content from issuu
    -
    - - diff --git a/blocks/test/fixtures/core-embedkickstarter.html b/blocks/test/fixtures/core-embedkickstarter.html deleted file mode 100644 index dbd11a91fe39b4..00000000000000 --- a/blocks/test/fixtures/core-embedkickstarter.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://kickstarter.com/ -
    Embedded content from kickstarter
    -
    - diff --git a/blocks/test/fixtures/core-embedkickstarter.serialized.html b/blocks/test/fixtures/core-embedkickstarter.serialized.html deleted file mode 100644 index 600c019a803420..00000000000000 --- a/blocks/test/fixtures/core-embedkickstarter.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://kickstarter.com/ -
    Embedded content from kickstarter
    -
    - - diff --git a/blocks/test/fixtures/core-embedmeetupcom.html b/blocks/test/fixtures/core-embedmeetupcom.html deleted file mode 100644 index f72f0acfcea7e9..00000000000000 --- a/blocks/test/fixtures/core-embedmeetupcom.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://meetupcom.com/ -
    Embedded content from meetupcom
    -
    - diff --git a/blocks/test/fixtures/core-embedmeetupcom.json b/blocks/test/fixtures/core-embedmeetupcom.json deleted file mode 100644 index 5fb470dcd8b6df..00000000000000 --- a/blocks/test/fixtures/core-embedmeetupcom.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "uid": "_uid_0", - "name": "core/embedmeetupcom", - "attributes": { - "url": "https://meetupcom.com/", - "caption": [ - "Embedded content from meetupcom" - ] - } - } -] diff --git a/blocks/test/fixtures/core-embedmeetupcom.serialized.html b/blocks/test/fixtures/core-embedmeetupcom.serialized.html deleted file mode 100644 index c271a0550b38cc..00000000000000 --- a/blocks/test/fixtures/core-embedmeetupcom.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://meetupcom.com/ -
    Embedded content from meetupcom
    -
    - - diff --git a/blocks/test/fixtures/core-embedmixcloud.html b/blocks/test/fixtures/core-embedmixcloud.html deleted file mode 100644 index bf79ac8537924a..00000000000000 --- a/blocks/test/fixtures/core-embedmixcloud.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://mixcloud.com/ -
    Embedded content from mixcloud
    -
    - diff --git a/blocks/test/fixtures/core-embedmixcloud.serialized.html b/blocks/test/fixtures/core-embedmixcloud.serialized.html deleted file mode 100644 index dd53c339d93a03..00000000000000 --- a/blocks/test/fixtures/core-embedmixcloud.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://mixcloud.com/ -
    Embedded content from mixcloud
    -
    - - diff --git a/blocks/test/fixtures/core-embedphotobucket.html b/blocks/test/fixtures/core-embedphotobucket.html deleted file mode 100644 index ba8170950c3729..00000000000000 --- a/blocks/test/fixtures/core-embedphotobucket.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://photobucket.com/ -
    Embedded content from photobucket
    -
    - diff --git a/blocks/test/fixtures/core-embedphotobucket.serialized.html b/blocks/test/fixtures/core-embedphotobucket.serialized.html deleted file mode 100644 index e2631ab04ceee4..00000000000000 --- a/blocks/test/fixtures/core-embedphotobucket.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://photobucket.com/ -
    Embedded content from photobucket
    -
    - - diff --git a/blocks/test/fixtures/core-embedpolldaddy.html b/blocks/test/fixtures/core-embedpolldaddy.html deleted file mode 100644 index 4176efd62628de..00000000000000 --- a/blocks/test/fixtures/core-embedpolldaddy.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://polldaddy.com/ -
    Embedded content from polldaddy
    -
    - diff --git a/blocks/test/fixtures/core-embedpolldaddy.serialized.html b/blocks/test/fixtures/core-embedpolldaddy.serialized.html deleted file mode 100644 index 20f6eba0732f39..00000000000000 --- a/blocks/test/fixtures/core-embedpolldaddy.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://polldaddy.com/ -
    Embedded content from polldaddy
    -
    - - diff --git a/blocks/test/fixtures/core-embedreddit.html b/blocks/test/fixtures/core-embedreddit.html deleted file mode 100644 index 3537909ad8430a..00000000000000 --- a/blocks/test/fixtures/core-embedreddit.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://reddit.com/ -
    Embedded content from reddit
    -
    - diff --git a/blocks/test/fixtures/core-embedreddit.serialized.html b/blocks/test/fixtures/core-embedreddit.serialized.html deleted file mode 100644 index 8fda9380fb2093..00000000000000 --- a/blocks/test/fixtures/core-embedreddit.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://reddit.com/ -
    Embedded content from reddit
    -
    - - diff --git a/blocks/test/fixtures/core-embedreverbnation.html b/blocks/test/fixtures/core-embedreverbnation.html deleted file mode 100644 index 3e03c3404f7570..00000000000000 --- a/blocks/test/fixtures/core-embedreverbnation.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://reverbnation.com/ -
    Embedded content from reverbnation
    -
    - diff --git a/blocks/test/fixtures/core-embedreverbnation.serialized.html b/blocks/test/fixtures/core-embedreverbnation.serialized.html deleted file mode 100644 index 3f5686dad96cf5..00000000000000 --- a/blocks/test/fixtures/core-embedreverbnation.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://reverbnation.com/ -
    Embedded content from reverbnation
    -
    - - diff --git a/blocks/test/fixtures/core-embedscreencast.html b/blocks/test/fixtures/core-embedscreencast.html deleted file mode 100644 index 75e7990c480f78..00000000000000 --- a/blocks/test/fixtures/core-embedscreencast.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://screencast.com/ -
    Embedded content from screencast
    -
    - diff --git a/blocks/test/fixtures/core-embedscreencast.serialized.html b/blocks/test/fixtures/core-embedscreencast.serialized.html deleted file mode 100644 index 2d6b5468637692..00000000000000 --- a/blocks/test/fixtures/core-embedscreencast.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://screencast.com/ -
    Embedded content from screencast
    -
    - - diff --git a/blocks/test/fixtures/core-embedscribd.html b/blocks/test/fixtures/core-embedscribd.html deleted file mode 100644 index 4971e8c9438426..00000000000000 --- a/blocks/test/fixtures/core-embedscribd.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://scribd.com/ -
    Embedded content from scribd
    -
    - diff --git a/blocks/test/fixtures/core-embedscribd.serialized.html b/blocks/test/fixtures/core-embedscribd.serialized.html deleted file mode 100644 index 06069125228bdf..00000000000000 --- a/blocks/test/fixtures/core-embedscribd.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://scribd.com/ -
    Embedded content from scribd
    -
    - - diff --git a/blocks/test/fixtures/core-embedslideshare.html b/blocks/test/fixtures/core-embedslideshare.html deleted file mode 100644 index abd33acdf7c46e..00000000000000 --- a/blocks/test/fixtures/core-embedslideshare.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://slideshare.com/ -
    Embedded content from slideshare
    -
    - diff --git a/blocks/test/fixtures/core-embedslideshare.serialized.html b/blocks/test/fixtures/core-embedslideshare.serialized.html deleted file mode 100644 index 8184fc98e5a1a6..00000000000000 --- a/blocks/test/fixtures/core-embedslideshare.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://slideshare.com/ -
    Embedded content from slideshare
    -
    - - diff --git a/blocks/test/fixtures/core-embedsmugmug.html b/blocks/test/fixtures/core-embedsmugmug.html deleted file mode 100644 index 7dc99c1cb7dfb2..00000000000000 --- a/blocks/test/fixtures/core-embedsmugmug.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://smugmug.com/ -
    Embedded content from smugmug
    -
    - diff --git a/blocks/test/fixtures/core-embedsmugmug.serialized.html b/blocks/test/fixtures/core-embedsmugmug.serialized.html deleted file mode 100644 index 4755f4de1a2c54..00000000000000 --- a/blocks/test/fixtures/core-embedsmugmug.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://smugmug.com/ -
    Embedded content from smugmug
    -
    - - diff --git a/blocks/test/fixtures/core-embedsoundcloud.html b/blocks/test/fixtures/core-embedsoundcloud.html deleted file mode 100644 index c02c19b249a0b1..00000000000000 --- a/blocks/test/fixtures/core-embedsoundcloud.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://soundcloud.com/ -
    Embedded content from soundcloud
    -
    - diff --git a/blocks/test/fixtures/core-embedsoundcloud.serialized.html b/blocks/test/fixtures/core-embedsoundcloud.serialized.html deleted file mode 100644 index 70688f2cad848b..00000000000000 --- a/blocks/test/fixtures/core-embedsoundcloud.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://soundcloud.com/ -
    Embedded content from soundcloud
    -
    - - diff --git a/blocks/test/fixtures/core-embedspeaker.html b/blocks/test/fixtures/core-embedspeaker.html deleted file mode 100644 index a7a9332fff5d2a..00000000000000 --- a/blocks/test/fixtures/core-embedspeaker.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://speaker.com/ -
    Embedded content from speaker
    -
    - diff --git a/blocks/test/fixtures/core-embedspeaker.serialized.html b/blocks/test/fixtures/core-embedspeaker.serialized.html deleted file mode 100644 index 77b6efdd62940d..00000000000000 --- a/blocks/test/fixtures/core-embedspeaker.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://speaker.com/ -
    Embedded content from speaker
    -
    - - diff --git a/blocks/test/fixtures/core-embedspotify.html b/blocks/test/fixtures/core-embedspotify.html deleted file mode 100644 index bfe67cb9034fc6..00000000000000 --- a/blocks/test/fixtures/core-embedspotify.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://spotify.com/ -
    Embedded content from spotify
    -
    - diff --git a/blocks/test/fixtures/core-embedspotify.serialized.html b/blocks/test/fixtures/core-embedspotify.serialized.html deleted file mode 100644 index 8e88da9f4e3a27..00000000000000 --- a/blocks/test/fixtures/core-embedspotify.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://spotify.com/ -
    Embedded content from spotify
    -
    - - diff --git a/blocks/test/fixtures/core-embedted.html b/blocks/test/fixtures/core-embedted.html deleted file mode 100644 index eb58f0c2c39497..00000000000000 --- a/blocks/test/fixtures/core-embedted.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://ted.com/ -
    Embedded content from ted
    -
    - diff --git a/blocks/test/fixtures/core-embedted.serialized.html b/blocks/test/fixtures/core-embedted.serialized.html deleted file mode 100644 index 5a9d51536f5daf..00000000000000 --- a/blocks/test/fixtures/core-embedted.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://ted.com/ -
    Embedded content from ted
    -
    - - diff --git a/blocks/test/fixtures/core-embedtumblr.html b/blocks/test/fixtures/core-embedtumblr.html deleted file mode 100644 index ee07d48e887ba4..00000000000000 --- a/blocks/test/fixtures/core-embedtumblr.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://tumblr.com/ -
    Embedded content from tumblr
    -
    - diff --git a/blocks/test/fixtures/core-embedtumblr.serialized.html b/blocks/test/fixtures/core-embedtumblr.serialized.html deleted file mode 100644 index 8f1da3fb2e4d98..00000000000000 --- a/blocks/test/fixtures/core-embedtumblr.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://tumblr.com/ -
    Embedded content from tumblr
    -
    - - diff --git a/blocks/test/fixtures/core-embedtwitter.html b/blocks/test/fixtures/core-embedtwitter.html deleted file mode 100644 index 807a6bfd27604d..00000000000000 --- a/blocks/test/fixtures/core-embedtwitter.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://twitter.com/automattic -
    We are Automattic
    -
    - diff --git a/blocks/test/fixtures/core-embedtwitter.serialized.html b/blocks/test/fixtures/core-embedtwitter.serialized.html deleted file mode 100644 index bc214e661e01e7..00000000000000 --- a/blocks/test/fixtures/core-embedtwitter.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://twitter.com/automattic -
    We are Automattic
    -
    - - diff --git a/blocks/test/fixtures/core-embedvideopress.html b/blocks/test/fixtures/core-embedvideopress.html deleted file mode 100644 index ba2ff6bdc2e51d..00000000000000 --- a/blocks/test/fixtures/core-embedvideopress.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://videopress.com/ -
    Embedded content from videopress
    -
    - diff --git a/blocks/test/fixtures/core-embedvideopress.serialized.html b/blocks/test/fixtures/core-embedvideopress.serialized.html deleted file mode 100644 index 571972d53ff4dd..00000000000000 --- a/blocks/test/fixtures/core-embedvideopress.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://videopress.com/ -
    Embedded content from videopress
    -
    - - diff --git a/blocks/test/fixtures/core-embedvimeo.html b/blocks/test/fixtures/core-embedvimeo.html deleted file mode 100644 index 81b4698f749c24..00000000000000 --- a/blocks/test/fixtures/core-embedvimeo.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://vimeo.com/ -
    Embedded content from vimeo
    -
    - diff --git a/blocks/test/fixtures/core-embedvimeo.serialized.html b/blocks/test/fixtures/core-embedvimeo.serialized.html deleted file mode 100644 index eb1522a937aea1..00000000000000 --- a/blocks/test/fixtures/core-embedvimeo.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://vimeo.com/ -
    Embedded content from vimeo
    -
    - - diff --git a/blocks/test/fixtures/core-embedvine.html b/blocks/test/fixtures/core-embedvine.html deleted file mode 100644 index b70558a5fc77b2..00000000000000 --- a/blocks/test/fixtures/core-embedvine.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://vine.com/ -
    Embedded content from vine
    -
    - diff --git a/blocks/test/fixtures/core-embedvine.serialized.html b/blocks/test/fixtures/core-embedvine.serialized.html deleted file mode 100644 index df9496fb94081e..00000000000000 --- a/blocks/test/fixtures/core-embedvine.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://vine.com/ -
    Embedded content from vine
    -
    - - diff --git a/blocks/test/fixtures/core-embedwordpress.html b/blocks/test/fixtures/core-embedwordpress.html deleted file mode 100644 index accd979b51f836..00000000000000 --- a/blocks/test/fixtures/core-embedwordpress.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://wordpress.com/ -
    Embedded content from WordPress
    -
    - diff --git a/blocks/test/fixtures/core-embedwordpress.serialized.html b/blocks/test/fixtures/core-embedwordpress.serialized.html deleted file mode 100644 index 0905c1b166b45d..00000000000000 --- a/blocks/test/fixtures/core-embedwordpress.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://wordpress.com/ -
    Embedded content from WordPress
    -
    - - diff --git a/blocks/test/fixtures/core-embedwordpresstv.html b/blocks/test/fixtures/core-embedwordpresstv.html deleted file mode 100644 index eca3877f5ced80..00000000000000 --- a/blocks/test/fixtures/core-embedwordpresstv.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://wordpresstv.com/ -
    Embedded content from wordpresstv
    -
    - diff --git a/blocks/test/fixtures/core-embedwordpresstv.json b/blocks/test/fixtures/core-embedwordpresstv.json deleted file mode 100644 index 43e137a66bdeb8..00000000000000 --- a/blocks/test/fixtures/core-embedwordpresstv.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "uid": "_uid_0", - "name": "core/embedwordpresstv", - "attributes": { - "url": "https://wordpresstv.com/", - "caption": [ - "Embedded content from wordpresstv" - ] - } - } -] diff --git a/blocks/test/fixtures/core-embedwordpresstv.serialized.html b/blocks/test/fixtures/core-embedwordpresstv.serialized.html deleted file mode 100644 index bc6c773f16293d..00000000000000 --- a/blocks/test/fixtures/core-embedwordpresstv.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://wordpresstv.com/ -
    Embedded content from wordpresstv
    -
    - - diff --git a/blocks/test/fixtures/core-embedyoutube.html b/blocks/test/fixtures/core-embedyoutube.html deleted file mode 100644 index e0832c00589d29..00000000000000 --- a/blocks/test/fixtures/core-embedyoutube.html +++ /dev/null @@ -1,6 +0,0 @@ - -
    - https://youtube.com/ -
    Embedded content from youtube
    -
    - diff --git a/blocks/test/fixtures/core-embedyoutube.serialized.html b/blocks/test/fixtures/core-embedyoutube.serialized.html deleted file mode 100644 index 02fa086d489e79..00000000000000 --- a/blocks/test/fixtures/core-embedyoutube.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    - https://youtube.com/ -
    Embedded content from youtube
    -
    - - diff --git a/blocks/test/fixtures/core-gallery.html b/blocks/test/fixtures/core-gallery.html deleted file mode 100644 index 523a6732dd9597..00000000000000 --- a/blocks/test/fixtures/core-gallery.html +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/blocks/test/fixtures/core-gallery.json b/blocks/test/fixtures/core-gallery.json deleted file mode 100644 index 4b1abd909fe7fd..00000000000000 --- a/blocks/test/fixtures/core-gallery.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "uid": "_uid_0", - "name": "core/gallery", - "attributes": { - "images": [ - { "url": "https://cldup.com/uuUqE_dXzy.jpg", "alt": "title" }, - { "url": "http://google.com/hi.png", "alt": "title" } - ] - } - } -] diff --git a/blocks/test/fixtures/core-gallery.serialized.html b/blocks/test/fixtures/core-gallery.serialized.html deleted file mode 100644 index 09f55993d4fd97..00000000000000 --- a/blocks/test/fixtures/core-gallery.serialized.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/blocks/test/fixtures/core-image-center-caption.html b/blocks/test/fixtures/core-image-center-caption.html deleted file mode 100644 index a528bacf467455..00000000000000 --- a/blocks/test/fixtures/core-image-center-caption.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    Give it a try. Press the "really wide" button on the image toolbar.
    - diff --git a/blocks/test/fixtures/core-image.html b/blocks/test/fixtures/core-image.html deleted file mode 100644 index 7ca7dd87f9f01a..00000000000000 --- a/blocks/test/fixtures/core-image.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/blocks/test/fixtures/core-image.serialized.html b/blocks/test/fixtures/core-image.serialized.html deleted file mode 100644 index 2b27696131025b..00000000000000 --- a/blocks/test/fixtures/core-image.serialized.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/blocks/test/fixtures/core-latestposts.html b/blocks/test/fixtures/core-latestposts.html deleted file mode 100644 index ee48abd1b42766..00000000000000 --- a/blocks/test/fixtures/core-latestposts.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/blocks/test/fixtures/core-latestposts.json b/blocks/test/fixtures/core-latestposts.json deleted file mode 100644 index 515a6af9aee5ae..00000000000000 --- a/blocks/test/fixtures/core-latestposts.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "uid": "_uid_0", - "name": "core/latestposts", - "attributes": { - "poststoshow": "5" - } - } -] diff --git a/blocks/test/fixtures/core-latestposts.serialized.html b/blocks/test/fixtures/core-latestposts.serialized.html deleted file mode 100644 index ee48abd1b42766..00000000000000 --- a/blocks/test/fixtures/core-latestposts.serialized.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/blocks/test/fixtures/core-preformatted.html b/blocks/test/fixtures/core-preformatted.html deleted file mode 100644 index 1b3abc31853c09..00000000000000 --- a/blocks/test/fixtures/core-preformatted.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    Some preformatted text...
    And more!
    - diff --git a/blocks/test/fixtures/core-preformatted.serialized.html b/blocks/test/fixtures/core-preformatted.serialized.html deleted file mode 100644 index b119b914cf0e42..00000000000000 --- a/blocks/test/fixtures/core-preformatted.serialized.html +++ /dev/null @@ -1,4 +0,0 @@ - -
    Some preformatted text...
    And more!
    - - diff --git a/blocks/test/fixtures/core-quote-style-1.html b/blocks/test/fixtures/core-quote-style-1.html deleted file mode 100644 index e8c9add2748c63..00000000000000 --- a/blocks/test/fixtures/core-quote-style-1.html +++ /dev/null @@ -1,3 +0,0 @@ - -

    The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

    Matt Mullenweg, 2017
    - diff --git a/blocks/test/fixtures/core-quote-style-1.json b/blocks/test/fixtures/core-quote-style-1.json deleted file mode 100644 index 37815136063030..00000000000000 --- a/blocks/test/fixtures/core-quote-style-1.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "uid": "_uid_0", - "name": "core/quote", - "attributes": { - "style": "1", - "value": [ - [ - "The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery." - ] - ], - "citation": [ - "Matt Mullenweg, 2017" - ] - } - } -] diff --git a/blocks/test/fixtures/core-quote-style-2.html b/blocks/test/fixtures/core-quote-style-2.html deleted file mode 100644 index b8c255beee8fe7..00000000000000 --- a/blocks/test/fixtures/core-quote-style-2.html +++ /dev/null @@ -1,3 +0,0 @@ - -

    There is no greater agony than bearing an untold story inside you.

    Maya Angelou
    - diff --git a/blocks/test/fixtures/core__button__center.html b/blocks/test/fixtures/core__button__center.html new file mode 100644 index 00000000000000..53c3b8c897ad06 --- /dev/null +++ b/blocks/test/fixtures/core__button__center.html @@ -0,0 +1,3 @@ + + + diff --git a/blocks/test/fixtures/core-button-center.json b/blocks/test/fixtures/core__button__center.json similarity index 100% rename from blocks/test/fixtures/core-button-center.json rename to blocks/test/fixtures/core__button__center.json diff --git a/blocks/test/fixtures/core__button__center.parsed.json b/blocks/test/fixtures/core__button__center.parsed.json new file mode 100644 index 00000000000000..e19d7f4991ae7e --- /dev/null +++ b/blocks/test/fixtures/core__button__center.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/button", + "attrs": { + "align": "center" + }, + "rawContent": "\n\n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__button__center.serialized.html b/blocks/test/fixtures/core__button__center.serialized.html new file mode 100644 index 00000000000000..67ce1c8adfd300 --- /dev/null +++ b/blocks/test/fixtures/core__button__center.serialized.html @@ -0,0 +1,4 @@ + + + + diff --git a/blocks/test/fixtures/core-code.html b/blocks/test/fixtures/core__code.html similarity index 60% rename from blocks/test/fixtures/core-code.html rename to blocks/test/fixtures/core__code.html index 0c00ab494b2f98..5d3f951c17f71c 100644 --- a/blocks/test/fixtures/core-code.html +++ b/blocks/test/fixtures/core__code.html @@ -1,5 +1,5 @@ -
    export default function MyButton() {
    +
    export default function MyButton() {
     	return <Button>Click Me!</Button>;
     }
    diff --git a/blocks/test/fixtures/core-code.json b/blocks/test/fixtures/core__code.json similarity index 100% rename from blocks/test/fixtures/core-code.json rename to blocks/test/fixtures/core__code.json diff --git a/blocks/test/fixtures/core__code.parsed.json b/blocks/test/fixtures/core__code.parsed.json new file mode 100644 index 00000000000000..127ba413fcb3cd --- /dev/null +++ b/blocks/test/fixtures/core__code.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/code", + "attrs": null, + "rawContent": "\n
    export default function MyButton() {\n\treturn <Button>Click Me!</Button>;\n}
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-code.serialized.html b/blocks/test/fixtures/core__code.serialized.html similarity index 60% rename from blocks/test/fixtures/core-code.serialized.html rename to blocks/test/fixtures/core__code.serialized.html index fbf78a33703c00..695395457a7c9e 100644 --- a/blocks/test/fixtures/core-code.serialized.html +++ b/blocks/test/fixtures/core__code.serialized.html @@ -1,5 +1,5 @@ -
    export default function MyButton() {
    +
    export default function MyButton() {
     	return <Button>Click Me!</Button>;
     }
    diff --git a/blocks/test/fixtures/core__cover-image.html b/blocks/test/fixtures/core__cover-image.html new file mode 100644 index 00000000000000..ac78109a092e21 --- /dev/null +++ b/blocks/test/fixtures/core__cover-image.html @@ -0,0 +1,7 @@ + +
    +
    +

    Guten Berg!

    +
    +
    + diff --git a/blocks/test/fixtures/core__cover-image.json b/blocks/test/fixtures/core__cover-image.json new file mode 100644 index 00000000000000..e76615bc0388e9 --- /dev/null +++ b/blocks/test/fixtures/core__cover-image.json @@ -0,0 +1,10 @@ +[ + { + "uid": "_uid_0", + "name": "core/cover-image", + "attributes": { + "url": "https://cldup.com/uuUqE_dXzy.jpg", + "title": "Guten Berg!" + } + } +] diff --git a/blocks/test/fixtures/core__cover-image.parsed.json b/blocks/test/fixtures/core__cover-image.parsed.json new file mode 100644 index 00000000000000..21afba0f6d0039 --- /dev/null +++ b/blocks/test/fixtures/core__cover-image.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/cover-image", + "attrs": { + "url": "https://cldup.com/uuUqE_dXzy.jpg" + }, + "rawContent": "\n
    \n\t
    \n\t\t

    Guten Berg!

    \n\t
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__cover-image.serialized.html b/blocks/test/fixtures/core__cover-image.serialized.html new file mode 100644 index 00000000000000..22def81fcfd94c --- /dev/null +++ b/blocks/test/fixtures/core__cover-image.serialized.html @@ -0,0 +1,8 @@ + +
    +
    +

    Guten Berg!

    +
    +
    + + diff --git a/blocks/test/fixtures/core-embed.html b/blocks/test/fixtures/core__embed.html similarity index 59% rename from blocks/test/fixtures/core-embed.html rename to blocks/test/fixtures/core__embed.html index af8b876de71e0d..a75136b0413ef7 100644 --- a/blocks/test/fixtures/core-embed.html +++ b/blocks/test/fixtures/core__embed.html @@ -1,5 +1,5 @@ - -
    + +
    https://example.com/
    Embedded content from an example URL
    diff --git a/blocks/test/fixtures/core-embed.json b/blocks/test/fixtures/core__embed.json similarity index 100% rename from blocks/test/fixtures/core-embed.json rename to blocks/test/fixtures/core__embed.json diff --git a/blocks/test/fixtures/core__embed.parsed.json b/blocks/test/fixtures/core__embed.parsed.json new file mode 100644 index 00000000000000..d0b20272ef818f --- /dev/null +++ b/blocks/test/fixtures/core__embed.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/embed", + "attrs": { + "url": "https://example.com/" + }, + "rawContent": "\n
    \n https://example.com/\n
    Embedded content from an example URL
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-embed.serialized.html b/blocks/test/fixtures/core__embed.serialized.html similarity index 59% rename from blocks/test/fixtures/core-embed.serialized.html rename to blocks/test/fixtures/core__embed.serialized.html index b8b1e50e7afef6..2b0842846c40f1 100644 --- a/blocks/test/fixtures/core-embed.serialized.html +++ b/blocks/test/fixtures/core__embed.serialized.html @@ -1,5 +1,5 @@ - -
    + +
    https://example.com/
    Embedded content from an example URL
    diff --git a/blocks/test/fixtures/core-freeform.html b/blocks/test/fixtures/core__freeform.html similarity index 100% rename from blocks/test/fixtures/core-freeform.html rename to blocks/test/fixtures/core__freeform.html diff --git a/blocks/test/fixtures/core-freeform.json b/blocks/test/fixtures/core__freeform.json similarity index 100% rename from blocks/test/fixtures/core-freeform.json rename to blocks/test/fixtures/core__freeform.json diff --git a/blocks/test/fixtures/core__freeform.parsed.json b/blocks/test/fixtures/core__freeform.parsed.json new file mode 100644 index 00000000000000..276442f4c7864f --- /dev/null +++ b/blocks/test/fixtures/core__freeform.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/freeform", + "attrs": null, + "rawContent": "\nTesting freeform block with some\n
    \n\tHTML content\n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-freeform.serialized.html b/blocks/test/fixtures/core__freeform.serialized.html similarity index 75% rename from blocks/test/fixtures/core-freeform.serialized.html rename to blocks/test/fixtures/core__freeform.serialized.html index d30114895dd4c6..a31ee92b0385e5 100644 --- a/blocks/test/fixtures/core-freeform.serialized.html +++ b/blocks/test/fixtures/core__freeform.serialized.html @@ -1,6 +1,6 @@ Testing freeform block with some -
    +
    HTML content
    diff --git a/blocks/test/fixtures/core__gallery.html b/blocks/test/fixtures/core__gallery.html new file mode 100644 index 00000000000000..2846a09568013a --- /dev/null +++ b/blocks/test/fixtures/core__gallery.html @@ -0,0 +1,10 @@ + + + diff --git a/blocks/test/fixtures/core__gallery.json b/blocks/test/fixtures/core__gallery.json new file mode 100644 index 00000000000000..aa42f70c3990a2 --- /dev/null +++ b/blocks/test/fixtures/core__gallery.json @@ -0,0 +1,42 @@ +[ + { + "uid": "_uid_0", + "name": "core/gallery", + "attributes": { + "images": [ + { + "sizes": { + "full": { + "url": "https://cldup.com/uuUqE_dXzy.jpg", + "height": 1080, + "width": 810, + "orientation": "portrait" + } + }, + "mime": "image/jpeg", + "type": "image", + "subtype": "jpeg", + "id": 1, + "url": "https://cldup.com/uuUqE_dXzy.jpg", + "alt": "title" + }, + { + "sizes": { + "full": { + "url": "http://google.com/hi.png", + "height": 1080, + "width": 1440, + "orientation": "landscape" + } + }, + "mime": "image/jpeg", + "type": "image", + "subtype": "jpeg", + "id": 2, + "url": "http://google.com/hi.png", + "alt": "title" + } + ] + } + } +] diff --git a/blocks/test/fixtures/core__gallery.parsed.json b/blocks/test/fixtures/core__gallery.parsed.json new file mode 100644 index 00000000000000..914a3635b82bb2 --- /dev/null +++ b/blocks/test/fixtures/core__gallery.parsed.json @@ -0,0 +1,46 @@ +[ + { + "blockName": "core/gallery", + "attrs": { + "images": [ + { + "sizes": { + "full": { + "url": "https://cldup.com/uuUqE_dXzy.jpg", + "height": 1080, + "width": 810, + "orientation": "portrait" + } + }, + "mime": "image/jpeg", + "type": "image", + "subtype": "jpeg", + "id": 1, + "url": "https://cldup.com/uuUqE_dXzy.jpg", + "alt": "title" + }, + { + "sizes": { + "full": { + "url": "http://google.com/hi.png", + "height": 1080, + "width": 1440, + "orientation": "landscape" + } + }, + "mime": "image/jpeg", + "type": "image", + "subtype": "jpeg", + "id": 2, + "url": "http://google.com/hi.png", + "alt": "title" + } + ] + }, + "rawContent": "\n
    \n\t\n\t\n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__gallery.serialized.html b/blocks/test/fixtures/core__gallery.serialized.html new file mode 100644 index 00000000000000..49e8169c9bd47c --- /dev/null +++ b/blocks/test/fixtures/core__gallery.serialized.html @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/blocks/test/fixtures/core-heading-h2-em.html b/blocks/test/fixtures/core__heading__h2-em.html similarity index 100% rename from blocks/test/fixtures/core-heading-h2-em.html rename to blocks/test/fixtures/core__heading__h2-em.html diff --git a/blocks/test/fixtures/core-heading-h2-em.json b/blocks/test/fixtures/core__heading__h2-em.json similarity index 100% rename from blocks/test/fixtures/core-heading-h2-em.json rename to blocks/test/fixtures/core__heading__h2-em.json diff --git a/blocks/test/fixtures/core__heading__h2-em.parsed.json b/blocks/test/fixtures/core__heading__h2-em.parsed.json new file mode 100644 index 00000000000000..3920297cb1ac9c --- /dev/null +++ b/blocks/test/fixtures/core__heading__h2-em.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/heading", + "attrs": null, + "rawContent": "\n

    The Inserter Tool

    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-heading-h2-em.serialized.html b/blocks/test/fixtures/core__heading__h2-em.serialized.html similarity index 100% rename from blocks/test/fixtures/core-heading-h2-em.serialized.html rename to blocks/test/fixtures/core__heading__h2-em.serialized.html diff --git a/blocks/test/fixtures/core-heading-h2.html b/blocks/test/fixtures/core__heading__h2.html similarity index 100% rename from blocks/test/fixtures/core-heading-h2.html rename to blocks/test/fixtures/core__heading__h2.html diff --git a/blocks/test/fixtures/core-heading-h2.json b/blocks/test/fixtures/core__heading__h2.json similarity index 100% rename from blocks/test/fixtures/core-heading-h2.json rename to blocks/test/fixtures/core__heading__h2.json diff --git a/blocks/test/fixtures/core__heading__h2.parsed.json b/blocks/test/fixtures/core__heading__h2.parsed.json new file mode 100644 index 00000000000000..a6d515e0ac0f13 --- /dev/null +++ b/blocks/test/fixtures/core__heading__h2.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/heading", + "attrs": null, + "rawContent": "\n

    A picture is worth a thousand words, or so the saying goes

    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-heading-h2.serialized.html b/blocks/test/fixtures/core__heading__h2.serialized.html similarity index 100% rename from blocks/test/fixtures/core-heading-h2.serialized.html rename to blocks/test/fixtures/core__heading__h2.serialized.html diff --git a/blocks/test/fixtures/core__html.html b/blocks/test/fixtures/core__html.html new file mode 100644 index 00000000000000..4824e6e373c06e --- /dev/null +++ b/blocks/test/fixtures/core__html.html @@ -0,0 +1,4 @@ + +

    Some HTML code

    +This text will scroll from right to left + diff --git a/blocks/test/fixtures/core__html.json b/blocks/test/fixtures/core__html.json new file mode 100644 index 00000000000000..c5f2daf6b551bc --- /dev/null +++ b/blocks/test/fixtures/core__html.json @@ -0,0 +1,9 @@ +[ + { + "uid": "_uid_0", + "name": "core/html", + "attributes": { + "content": "

    Some HTML code

    \nThis text will scroll from right to left" + } + } +] diff --git a/blocks/test/fixtures/core__html.parsed.json b/blocks/test/fixtures/core__html.parsed.json new file mode 100644 index 00000000000000..ae94db5e9027e1 --- /dev/null +++ b/blocks/test/fixtures/core__html.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/html", + "attrs": null, + "rawContent": "\n

    Some HTML code

    \nThis text will scroll from right to left\n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__html.serialized.html b/blocks/test/fixtures/core__html.serialized.html new file mode 100644 index 00000000000000..4824e6e373c06e --- /dev/null +++ b/blocks/test/fixtures/core__html.serialized.html @@ -0,0 +1,4 @@ + +

    Some HTML code

    +This text will scroll from right to left + diff --git a/blocks/test/fixtures/core__image.html b/blocks/test/fixtures/core__image.html new file mode 100644 index 00000000000000..2a414855b03441 --- /dev/null +++ b/blocks/test/fixtures/core__image.html @@ -0,0 +1,3 @@ + +
    + diff --git a/blocks/test/fixtures/core-image.json b/blocks/test/fixtures/core__image.json similarity index 100% rename from blocks/test/fixtures/core-image.json rename to blocks/test/fixtures/core__image.json diff --git a/blocks/test/fixtures/core__image.parsed.json b/blocks/test/fixtures/core__image.parsed.json new file mode 100644 index 00000000000000..e948d85add5d5c --- /dev/null +++ b/blocks/test/fixtures/core__image.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/image", + "attrs": null, + "rawContent": "\n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__image.serialized.html b/blocks/test/fixtures/core__image.serialized.html new file mode 100644 index 00000000000000..103b9582542792 --- /dev/null +++ b/blocks/test/fixtures/core__image.serialized.html @@ -0,0 +1,4 @@ + + + + diff --git a/blocks/test/fixtures/core__image__center-caption.html b/blocks/test/fixtures/core__image__center-caption.html new file mode 100644 index 00000000000000..293d010b4e5528 --- /dev/null +++ b/blocks/test/fixtures/core__image__center-caption.html @@ -0,0 +1,3 @@ + +
    Give it a try. Press the "really wide" button on the image toolbar.
    + diff --git a/blocks/test/fixtures/core-image-center-caption.json b/blocks/test/fixtures/core__image__center-caption.json similarity index 100% rename from blocks/test/fixtures/core-image-center-caption.json rename to blocks/test/fixtures/core__image__center-caption.json diff --git a/blocks/test/fixtures/core__image__center-caption.parsed.json b/blocks/test/fixtures/core__image__center-caption.parsed.json new file mode 100644 index 00000000000000..dbc7b92dd38660 --- /dev/null +++ b/blocks/test/fixtures/core__image__center-caption.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/image", + "attrs": { + "align": "center" + }, + "rawContent": "\n
    Give it a try. Press the "really wide" button on the image toolbar.
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-image-center-caption.serialized.html b/blocks/test/fixtures/core__image__center-caption.serialized.html similarity index 51% rename from blocks/test/fixtures/core-image-center-caption.serialized.html rename to blocks/test/fixtures/core__image__center-caption.serialized.html index 9b6743d36c62a8..7884d70b3986b5 100644 --- a/blocks/test/fixtures/core-image-center-caption.serialized.html +++ b/blocks/test/fixtures/core__image__center-caption.serialized.html @@ -1,5 +1,5 @@ - -
    + +
    Give it a try. Press the "really wide" button on the image toolbar.
    diff --git a/blocks/test/fixtures/core__latest-posts.html b/blocks/test/fixtures/core__latest-posts.html new file mode 100644 index 00000000000000..99d215f58affad --- /dev/null +++ b/blocks/test/fixtures/core__latest-posts.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__latest-posts.json b/blocks/test/fixtures/core__latest-posts.json new file mode 100644 index 00000000000000..3f27bca2cbd474 --- /dev/null +++ b/blocks/test/fixtures/core__latest-posts.json @@ -0,0 +1,10 @@ +[ + { + "uid": "_uid_0", + "name": "core/latest-posts", + "attributes": { + "postsToShow": 5, + "displayPostDate": false + } + } +] diff --git a/blocks/test/fixtures/core__latest-posts.parsed.json b/blocks/test/fixtures/core__latest-posts.parsed.json new file mode 100644 index 00000000000000..ac3a8dba1cc674 --- /dev/null +++ b/blocks/test/fixtures/core__latest-posts.parsed.json @@ -0,0 +1,14 @@ +[ + { + "blockName": "core/latest-posts", + "attrs": { + "postsToShow": 5, + "displayPostDate": false + }, + "rawContent": "" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__latest-posts.serialized.html b/blocks/test/fixtures/core__latest-posts.serialized.html new file mode 100644 index 00000000000000..99d215f58affad --- /dev/null +++ b/blocks/test/fixtures/core__latest-posts.serialized.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core-list-ul.html b/blocks/test/fixtures/core__list__ul.html similarity index 100% rename from blocks/test/fixtures/core-list-ul.html rename to blocks/test/fixtures/core__list__ul.html diff --git a/blocks/test/fixtures/core-list-ul.json b/blocks/test/fixtures/core__list__ul.json similarity index 100% rename from blocks/test/fixtures/core-list-ul.json rename to blocks/test/fixtures/core__list__ul.json diff --git a/blocks/test/fixtures/core__list__ul.parsed.json b/blocks/test/fixtures/core__list__ul.parsed.json new file mode 100644 index 00000000000000..c29157168e32c7 --- /dev/null +++ b/blocks/test/fixtures/core__list__ul.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/list", + "attrs": null, + "rawContent": "\n
    • Text & Headings
    • Images & Videos
    • Galleries
    • Embeds, like YouTube, Tweets, or other WordPress posts.
    • Layout blocks, like Buttons, Hero Images, Separators, etc.
    • And Lists like this one of course :)
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-list-ul.serialized.html b/blocks/test/fixtures/core__list__ul.serialized.html similarity index 100% rename from blocks/test/fixtures/core-list-ul.serialized.html rename to blocks/test/fixtures/core__list__ul.serialized.html diff --git a/blocks/test/fixtures/core__preformatted.html b/blocks/test/fixtures/core__preformatted.html new file mode 100644 index 00000000000000..1a890a7a5dc2d0 --- /dev/null +++ b/blocks/test/fixtures/core__preformatted.html @@ -0,0 +1,3 @@ + +
    Some preformatted text...
    And more!
    + diff --git a/blocks/test/fixtures/core-preformatted.json b/blocks/test/fixtures/core__preformatted.json similarity index 100% rename from blocks/test/fixtures/core-preformatted.json rename to blocks/test/fixtures/core__preformatted.json diff --git a/blocks/test/fixtures/core__preformatted.parsed.json b/blocks/test/fixtures/core__preformatted.parsed.json new file mode 100644 index 00000000000000..b0854646ed594e --- /dev/null +++ b/blocks/test/fixtures/core__preformatted.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/preformatted", + "attrs": null, + "rawContent": "\n
    Some preformatted text...
    And more!
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core__preformatted.serialized.html b/blocks/test/fixtures/core__preformatted.serialized.html new file mode 100644 index 00000000000000..ae726c700d0f14 --- /dev/null +++ b/blocks/test/fixtures/core__preformatted.serialized.html @@ -0,0 +1,4 @@ + +
    Some preformatted text...
    And more!
    + + diff --git a/blocks/test/fixtures/core-pullquote.html b/blocks/test/fixtures/core__pullquote.html similarity index 77% rename from blocks/test/fixtures/core-pullquote.html rename to blocks/test/fixtures/core__pullquote.html index 027188bce2960d..82b6234073ab9e 100644 --- a/blocks/test/fixtures/core-pullquote.html +++ b/blocks/test/fixtures/core__pullquote.html @@ -1,5 +1,5 @@ -
    +

    Testing pullquote block...

    ...with a caption
    diff --git a/blocks/test/fixtures/core-pullquote.json b/blocks/test/fixtures/core__pullquote.json similarity index 100% rename from blocks/test/fixtures/core-pullquote.json rename to blocks/test/fixtures/core__pullquote.json diff --git a/blocks/test/fixtures/core__pullquote.parsed.json b/blocks/test/fixtures/core__pullquote.parsed.json new file mode 100644 index 00000000000000..92a37a6ba57a70 --- /dev/null +++ b/blocks/test/fixtures/core__pullquote.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/pullquote", + "attrs": null, + "rawContent": "\n
    \n

    Testing pullquote block...

    ...with a caption
    \n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-pullquote.serialized.html b/blocks/test/fixtures/core__pullquote.serialized.html similarity index 74% rename from blocks/test/fixtures/core-pullquote.serialized.html rename to blocks/test/fixtures/core__pullquote.serialized.html index 5a75e75e7bc2cc..e367bc40919cba 100644 --- a/blocks/test/fixtures/core-pullquote.serialized.html +++ b/blocks/test/fixtures/core__pullquote.serialized.html @@ -1,5 +1,5 @@ -
    +

    Testing pullquote block...

    ...with a caption
    diff --git a/blocks/test/fixtures/core__quote__style-1.html b/blocks/test/fixtures/core__quote__style-1.html new file mode 100644 index 00000000000000..241b2927caead6 --- /dev/null +++ b/blocks/test/fixtures/core__quote__style-1.html @@ -0,0 +1,3 @@ + +

    The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

    Matt Mullenweg, 2017
    + diff --git a/blocks/test/fixtures/core__quote__style-1.json b/blocks/test/fixtures/core__quote__style-1.json new file mode 100644 index 00000000000000..dd76ad46a3da74 --- /dev/null +++ b/blocks/test/fixtures/core__quote__style-1.json @@ -0,0 +1,18 @@ +[ + { + "uid": "_uid_0", + "name": "core/quote", + "attributes": { + "style": "1", + "value": [ + { + "children": "The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.", + "type": "p" + } + ], + "citation": [ + "Matt Mullenweg, 2017" + ] + } + } +] diff --git a/blocks/test/fixtures/core__quote__style-1.parsed.json b/blocks/test/fixtures/core__quote__style-1.parsed.json new file mode 100644 index 00000000000000..9af35a7fe4be22 --- /dev/null +++ b/blocks/test/fixtures/core__quote__style-1.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/quote", + "attrs": { + "style": "1" + }, + "rawContent": "\n

    The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

    Matt Mullenweg, 2017
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-quote-style-1.serialized.html b/blocks/test/fixtures/core__quote__style-1.serialized.html similarity index 77% rename from blocks/test/fixtures/core-quote-style-1.serialized.html rename to blocks/test/fixtures/core__quote__style-1.serialized.html index e38001b88f29a9..0fd5a4efb7117c 100644 --- a/blocks/test/fixtures/core-quote-style-1.serialized.html +++ b/blocks/test/fixtures/core__quote__style-1.serialized.html @@ -1,5 +1,5 @@ - -
    + +

    The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

    Matt Mullenweg, 2017
    diff --git a/blocks/test/fixtures/core__quote__style-2.html b/blocks/test/fixtures/core__quote__style-2.html new file mode 100644 index 00000000000000..3c6a113e9bf5be --- /dev/null +++ b/blocks/test/fixtures/core__quote__style-2.html @@ -0,0 +1,3 @@ + +

    There is no greater agony than bearing an untold story inside you.

    Maya Angelou
    + diff --git a/blocks/test/fixtures/core-quote-style-2.json b/blocks/test/fixtures/core__quote__style-2.json similarity index 58% rename from blocks/test/fixtures/core-quote-style-2.json rename to blocks/test/fixtures/core__quote__style-2.json index ba3c1bd9241327..114a32462aea3a 100644 --- a/blocks/test/fixtures/core-quote-style-2.json +++ b/blocks/test/fixtures/core__quote__style-2.json @@ -5,9 +5,10 @@ "attributes": { "style": "2", "value": [ - [ - "There is no greater agony than bearing an untold story inside you." - ] + { + "children": "There is no greater agony than bearing an untold story inside you.", + "type": "p" + } ], "citation": [ "Maya Angelou" diff --git a/blocks/test/fixtures/core__quote__style-2.parsed.json b/blocks/test/fixtures/core__quote__style-2.parsed.json new file mode 100644 index 00000000000000..5988b9863e722b --- /dev/null +++ b/blocks/test/fixtures/core__quote__style-2.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/quote", + "attrs": { + "style": "2" + }, + "rawContent": "\n

    There is no greater agony than bearing an untold story inside you.

    Maya Angelou
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-quote-style-2.serialized.html b/blocks/test/fixtures/core__quote__style-2.serialized.html similarity index 61% rename from blocks/test/fixtures/core-quote-style-2.serialized.html rename to blocks/test/fixtures/core__quote__style-2.serialized.html index 6d5b9988eb347c..ae59dce584a223 100644 --- a/blocks/test/fixtures/core-quote-style-2.serialized.html +++ b/blocks/test/fixtures/core__quote__style-2.serialized.html @@ -1,5 +1,5 @@ - -
    + +

    There is no greater agony than bearing an untold story inside you.

    Maya Angelou
    diff --git a/blocks/test/fixtures/core-separator.html b/blocks/test/fixtures/core__separator.html similarity index 61% rename from blocks/test/fixtures/core-separator.html rename to blocks/test/fixtures/core__separator.html index a241e07204f9aa..d835a483147f13 100644 --- a/blocks/test/fixtures/core-separator.html +++ b/blocks/test/fixtures/core__separator.html @@ -1,3 +1,3 @@ -
    +
    diff --git a/blocks/test/fixtures/core-separator.json b/blocks/test/fixtures/core__separator.json similarity index 100% rename from blocks/test/fixtures/core-separator.json rename to blocks/test/fixtures/core__separator.json diff --git a/blocks/test/fixtures/core__separator.parsed.json b/blocks/test/fixtures/core__separator.parsed.json new file mode 100644 index 00000000000000..9dbc62b9dbd849 --- /dev/null +++ b/blocks/test/fixtures/core__separator.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/separator", + "attrs": null, + "rawContent": "\n
    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-separator.serialized.html b/blocks/test/fixtures/core__separator.serialized.html similarity index 62% rename from blocks/test/fixtures/core-separator.serialized.html rename to blocks/test/fixtures/core__separator.serialized.html index a4115292004428..0cc337d26dc88c 100644 --- a/blocks/test/fixtures/core-separator.serialized.html +++ b/blocks/test/fixtures/core__separator.serialized.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/blocks/test/fixtures/core-table.html b/blocks/test/fixtures/core__table.html similarity index 98% rename from blocks/test/fixtures/core-table.html rename to blocks/test/fixtures/core__table.html index 60008a1566ef04..de0498f605be4d 100644 --- a/blocks/test/fixtures/core-table.html +++ b/blocks/test/fixtures/core__table.html @@ -1,5 +1,5 @@ -
    +
    diff --git a/blocks/test/fixtures/core-table.json b/blocks/test/fixtures/core__table.json similarity index 100% rename from blocks/test/fixtures/core-table.json rename to blocks/test/fixtures/core__table.json diff --git a/blocks/test/fixtures/core__table.parsed.json b/blocks/test/fixtures/core__table.parsed.json new file mode 100644 index 00000000000000..714f17be0caa70 --- /dev/null +++ b/blocks/test/fixtures/core__table.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/table", + "attrs": null, + "rawContent": "\n
    Version
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    VersionMusicianDate
    .70No musician chosen.May 27, 2003
    1.0Miles DavisJanuary 3, 2004
    Lots of versions skipped, see the full list
    4.4Clifford BrownDecember 8, 2015
    4.5Coleman HawkinsApril 12, 2016
    4.6Pepper AdamsAugust 16, 2016
    4.7Sarah VaughanDecember 6, 2016
    \n" + }, + { + "attrs": {}, + "rawContent": "\n\n" + } +] diff --git a/blocks/test/fixtures/core-table.serialized.html b/blocks/test/fixtures/core__table.serialized.html similarity index 98% rename from blocks/test/fixtures/core-table.serialized.html rename to blocks/test/fixtures/core__table.serialized.html index 174adfec5ae84d..40d9109b062719 100644 --- a/blocks/test/fixtures/core-table.serialized.html +++ b/blocks/test/fixtures/core__table.serialized.html @@ -1,5 +1,5 @@ - +
    diff --git a/blocks/test/fixtures/core-text-align-right.html b/blocks/test/fixtures/core__text__align-right.html similarity index 76% rename from blocks/test/fixtures/core-text-align-right.html rename to blocks/test/fixtures/core__text__align-right.html index d3d0c922ce2bff..65a819fd91c6f2 100644 --- a/blocks/test/fixtures/core-text-align-right.html +++ b/blocks/test/fixtures/core__text__align-right.html @@ -1,3 +1,3 @@ - +

    ... like this one, which is separate from the above and right aligned.

    diff --git a/blocks/test/fixtures/core-text-align-right.json b/blocks/test/fixtures/core__text__align-right.json similarity index 100% rename from blocks/test/fixtures/core-text-align-right.json rename to blocks/test/fixtures/core__text__align-right.json diff --git a/blocks/test/fixtures/core__text__align-right.parsed.json b/blocks/test/fixtures/core__text__align-right.parsed.json new file mode 100644 index 00000000000000..b4c6287f3514c0 --- /dev/null +++ b/blocks/test/fixtures/core__text__align-right.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/text", + "attrs": { + "align": "right" + }, + "rawContent": "\n

    ... like this one, which is separate from the above and right aligned.

    \n" + }, + { + "attrs": {}, + "rawContent": "\n" + } +] diff --git a/blocks/test/fixtures/core-text-align-right.serialized.html b/blocks/test/fixtures/core__text__align-right.serialized.html similarity index 76% rename from blocks/test/fixtures/core-text-align-right.serialized.html rename to blocks/test/fixtures/core__text__align-right.serialized.html index 5bbeb051d31867..3a56f80bd3c546 100644 --- a/blocks/test/fixtures/core-text-align-right.serialized.html +++ b/blocks/test/fixtures/core__text__align-right.serialized.html @@ -1,4 +1,4 @@ - +

    ... like this one, which is separate from the above and right aligned.

    diff --git a/blocks/test/full-content.js b/blocks/test/full-content.js index 7a16290ddb872e..b98e1644d23b84 100644 --- a/blocks/test/full-content.js +++ b/blocks/test/full-content.js @@ -11,15 +11,17 @@ import { format } from 'util'; * Internal dependencies */ import parse from '../api/parser'; +import { parse as grammarParse } from '../api/post.pegjs'; import serialize from '../api/serializer'; import { getBlockTypes } from '../api/registration'; const fixturesDir = path.join( __dirname, 'fixtures' ); -// We expect 3 different types of files for each fixture: -// - fixture.html - original content -// - fixture.json - blocks structure -// - fixture.serialized.html - re-serialized content +// We expect 4 different types of files for each fixture: +// - fixture.html : original content +// - fixture.parsed.json : parser output +// - fixture.json : blocks structure +// - fixture.serialized.html : re-serialized content // Get the "base" name for each fixture first. const fileBasenames = uniq( fs.readdirSync( fixturesDir ) @@ -53,7 +55,7 @@ function normalizeReactTree( element ) { // Check if we got an object first, then if it actually has a `type` like a // React component. Sometimes we get other stuff here, which probably // indicates a bug. - if ( isObject( element ) && element.type ) { + if ( isObject( element ) && element.type && element.props ) { const toReturn = { type: element.type, }; @@ -91,6 +93,27 @@ describe( 'full post content fixture', () => { it( f, () => { const content = readFixtureFile( f + '.html' ); + const parserOutputActual = grammarParse( content ); + let parserOutputExpectedString = readFixtureFile( f + '.parsed.json' ); + + if ( ! parserOutputExpectedString ) { + if ( process.env.GENERATE_MISSING_FIXTURES ) { + parserOutputExpectedString = JSON.stringify( + parserOutputActual, + null, + 4 + ) + '\n'; + writeFixtureFile( f + '.parsed.json', parserOutputExpectedString ); + } else { + throw new Error( + 'Missing fixture file: ' + f + '.parsed.json' + ); + } + } + + const parserOutputExpected = JSON.parse( parserOutputExpectedString ); + expect( parserOutputActual ).to.eql( parserOutputExpected ); + const blocksActual = parse( content ); const blocksActualNormalized = normalizeParsedBlocks( blocksActual ); let blocksExpectedString = readFixtureFile( f + '.json' ); @@ -135,11 +158,11 @@ describe( 'full post content fixture', () => { const errors = []; getBlockTypes().map( block => block.name ).forEach( name => { - const nameToFilename = name.replace( /\//g, '-' ); + const nameToFilename = name.replace( /\//g, '__' ); const foundFixtures = fileBasenames .filter( basename => ( basename === nameToFilename || - startsWith( basename, nameToFilename + '-' ) + startsWith( basename, nameToFilename + '__' ) ) ) .map( basename => { const filename = basename + '.html'; @@ -152,7 +175,7 @@ describe( 'full post content fixture', () => { if ( ! foundFixtures.length ) { errors.push( format( - 'Expected a fixture file called \'%s.html\' or \'%s-*.html\'.', + 'Expected a fixture file called \'%s.html\' or \'%s__*.html\'.', nameToFilename, nameToFilename ) ); diff --git a/bootstrap-test.js b/bootstrap-test.js index e50256f2b0b82c..a29de5fc8b947f 100644 --- a/bootstrap-test.js +++ b/bootstrap-test.js @@ -60,3 +60,7 @@ global.window._wpDateSettings = { string: 'America/New_York', }, }; +global.wp = global.wp || {}; +global.wp.a11y = { + speak: () => {}, +}; diff --git a/components/button/index.js b/components/button/index.js index 87a8964150d947..e13ec43759c5a9 100644 --- a/components/button/index.js +++ b/components/button/index.js @@ -7,7 +7,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { Component } from 'element'; +import { Component, createElement } from 'element'; class Button extends Component { constructor( props ) { @@ -39,7 +39,7 @@ class Button extends Component { delete additionalProps.focus; - return wp.element.createElement( tag, { + return createElement( tag, { ...tagProps, ...additionalProps, className: classes, diff --git a/components/dashicon/index.js b/components/dashicon/index.js index 4d57249d0950b3..0e7328fbbfbfa5 100644 --- a/components/dashicon/index.js +++ b/components/dashicon/index.js @@ -63,8 +63,17 @@ export default class Dashicon extends wp.element.Component { case 'admin-settings': path = 'M18 16V4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h13c.55 0 1-.45 1-1zM8 11h1c.55 0 1 .45 1 1s-.45 1-1 1H8v1.5c0 .28-.22.5-.5.5s-.5-.22-.5-.5V13H6c-.55 0-1-.45-1-1s.45-1 1-1h1V5.5c0-.28.22-.5.5-.5s.5.22.5.5V11zm5-2h-1c-.55 0-1-.45-1-1s.45-1 1-1h1V5.5c0-.28.22-.5.5-.5s.5.22.5.5V7h1c.55 0 1 .45 1 1s-.45 1-1 1h-1v5.5c0 .28-.22.5-.5.5s-.5-.22-.5-.5V9z'; break; + case 'admin-site-alt': + path = 'M10 1a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm7.5 6.48a3.38 3.38 0 0 1-1.75 2.05 5.64 5.64 0 0 0-3.27-3.75 2 2 0 0 1 .79-1.09c-.43-.28-1-.42-1.34.07-.53.69 0 1.61.21 2v.14a3.07 3.07 0 0 1-1.24-1.44 5.2 5.2 0 0 0-2.76.69 3.44 3.44 0 0 1 .16-1.68 2.21 2.21 0 0 0 1.92-.8c.46-.52-.13-1.18-.59-1.58h.36a7.86 7.86 0 0 1 3.89 1 5.61 5.61 0 0 1 2.27 4.26c.24 0 .7-.55.91-.92a7.86 7.86 0 0 1 .44 1.05zM10 17.84c-2.05-2.08.25-3.75-1-5.24-.92-.85-2.29-.26-3.11-1.23a4.08 4.08 0 0 1 1.43-3.93c.52-.44 4-1 5.42.22a5.22 5.22 0 0 1 1.67 2.74 2.35 2.35 0 0 0 1.32-.29c.41 2.98-3.15 6.74-5.73 7.73zM6.15 3.09a1.84 1.84 0 0 1 2.16.66 2.92 2.92 0 0 1-1.5.72A3 3 0 0 1 7 3.61z'; + break; + case 'admin-site-alt2': + path = 'M10 1a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm2.92 12.34c0 .35.14.63.36.66s.47-.22.58-.6l.2.08a1.72 1.72 0 0 1 .84 2 1.58 1.58 0 0 1-1.45 1.24c-.49-1.21-2.11.06-3.56-.22a1.92 1.92 0 0 1-1.33-1.19c1.19-.11 2.85-1.73 4.36-1.97zM9 12.27a1.84 1.84 0 0 0 1.82-1.59 1.39 1.39 0 0 1-.07 1.83A1.17 1.17 0 0 1 9 12.27zm3-.76c.41.39 3-.06 3.52 1.09-.95-.2-2.95.61-3.47-1.08zm-1.27-5.06v.27c-.65-.77-1.33-1.07-1.61-.57s1 1.11.76 1.88S8.61 8.59 8 9.64s-.49 2.42 1.24 3.67A3 3 0 0 1 6.7 11.2c-.4-1.2-.09-2.26-.78-2.46C5 8.46 4 9.71 4 10.8c-1.26-1.26.05-2.86-1.2-4.18a7.89 7.89 0 0 1 9.64-4.13 5.34 5.34 0 0 0-1.71 3.96z'; + break; + case 'admin-site-alt3': + path = 'M10 1a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm-7.89 9.68h2.51a14.13 14.13 0 0 0 .38 2.7H2.84a7.86 7.86 0 0 1-.73-2.7zm8.57-5.4V2.19a4.13 4.13 0 0 1 2.22 2 8.53 8.53 0 0 1 .54 1.08zm3.22 1.35a12.88 12.88 0 0 1 .41 2.7h-3.63v-2.7zM9.32 2.19v3.09H6.56A8.53 8.53 0 0 1 7.1 4.2a4.13 4.13 0 0 1 2.22-2.01zm0 4.44v2.7H5.7a12.88 12.88 0 0 1 .41-2.7zm-4.7 2.69H2.11a7.86 7.86 0 0 1 .73-2.7H5a14.13 14.13 0 0 0-.38 2.7zm1.08 1.36h3.62v2.7H6.11a12.88 12.88 0 0 1-.41-2.7zm3.63 4v3.09a4.13 4.13 0 0 1-2.22-2 8.53 8.53 0 0 1-.54-1.08zm1.35 3.09v-3.04h2.76a8.53 8.53 0 0 1-.54 1.08 4.13 4.13 0 0 1-2.22 2zm0-4.44v-2.7h3.62a12.88 12.88 0 0 1-.41 2.7zm4.71-2.7h2.51a7.86 7.86 0 0 1-.73 2.7H15a14.13 14.13 0 0 0 .38-2.65zm0-1.35A14.13 14.13 0 0 0 15 6.63h2.16a7.86 7.86 0 0 1 .73 2.7zm1-4H14.6a8.92 8.92 0 0 0-1.39-2.52 8 8 0 0 1 3.14 2.52zm-9.6-2.52A8.92 8.92 0 0 0 5.4 5.28H3.65a8 8 0 0 1 3.14-2.52zm-3.15 12H5.4a8.92 8.92 0 0 0 1.39 2.52 8 8 0 0 1-3.14-2.55zm9.56 2.52a8.92 8.92 0 0 0 1.39-2.52h1.76a8 8 0 0 1-3.14 2.48z'; + break; case 'admin-site': - path = 'M19 10c0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9 9-4.03 9-9zm-11 .1c-2.84-.29-4.48-1.17-5.48-2.29.97-3.16 3.8-5.48 7.25-5.63-.84 1.38-1.5 4.13-.03 5.57-1.51.21-2.21-1.86-3.11-1.15-1.43 1.12-.08 2.67 3.2 3.27 3.29.59 3.66 1.58 3.63 3.08-.03 1.47-.8 3.3-4.06 4.7.09-4.18-2.64-3.84-3.2-5.04.2-.87.44-1.78 1.8-2.51zm8.49-4.32c2.15 3.3 1.02 6.08.84 6.68-.77-1.86-2.17-2.29-2.53-3.54-.32-1.11.62-2.23 1.69-3.14z'; + path = 'M10 1a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm3.46 11.95c0 1.47-.8 3.3-4.06 4.7.3-4.17-2.52-3.69-3.2-5A3.25 3.25 0 0 1 8 10.1a8.49 8.49 0 0 1-4.18-2 1.84 1.84 0 0 0 .64 1.21 4.18 4.18 0 0 1-1.94-1.5 7.94 7.94 0 0 1 7.25-5.63c-.84 1.38-1.5 4.13 0 5.57C8.23 8 7.26 6 6.41 6.79c-1.13 1.06.33 2.51 3.42 3.08 3.29.59 3.66 1.58 3.63 3.08zm1.34-4c-.32-1.11.62-2.23 1.69-3.14a7.27 7.27 0 0 1 .84 6.68c-.77-1.89-2.17-2.32-2.53-3.57z'; break; case 'admin-tools': path = 'M16.68 9.77c-1.34 1.34-3.3 1.67-4.95.99l-5.41 6.52c-.99.99-2.59.99-3.58 0s-.99-2.59 0-3.57l6.52-5.42c-.68-1.65-.35-3.61.99-4.95 1.28-1.28 3.12-1.62 4.72-1.06l-2.89 2.89 2.82 2.82 2.86-2.87c.53 1.58.18 3.39-1.08 4.65zM3.81 16.21c.4.39 1.04.39 1.43 0 .4-.4.4-1.04 0-1.43-.39-.4-1.03-.4-1.43 0-.39.39-.39 1.03 0 1.43z'; @@ -150,6 +159,39 @@ export default class Dashicon extends wp.element.Component { case 'book': path = 'M16 3h2v16H5c-1.66 0-3-1.34-3-3V4c0-1.66 1.34-3 3-3h9v14H5c-.55 0-1 .45-1 1s.45 1 1 1h11V3z'; break; + case 'buddicons-activity': + path = 'M8 1v7h2V6c0-1.52 1.45-3 3-3v.86c.55-.52 1.26-.86 2-.86v3h1c1.1 0 2 .9 2 2s-.9 2-2 2h-1v6c0 .55-.45 1-1 1s-1-.45-1-1v-2.18c-.31.11-.65.18-1 .18v2c0 .55-.45 1-1 1s-1-.45-1-1v-2H8v2c0 .55-.45 1-1 1s-1-.45-1-1v-2c-.35 0-.69-.07-1-.18V16c0 .55-.45 1-1 1s-1-.45-1-1v-4H2v-1c0-1.66 1.34-3 3-3h2V1h1zm5 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1z'; + break; + case 'buddicons-buddypress-logo': + path = 'M10 0c5.52 0 10 4.48 10 10s-4.48 10-10 10S0 15.52 0 10 4.48 0 10 0zm0 .5C4.75.5.5 4.75.5 10s4.25 9.5 9.5 9.5 9.5-4.25 9.5-9.5S15.25.5 10 .5zm0 1c4.7 0 8.5 3.8 8.5 8.5s-3.8 8.5-8.5 8.5-8.5-3.8-8.5-8.5S5.3 1.5 10 1.5zm1.8 1.71c-.57 0-1.1.17-1.55.45 1.56.37 2.73 1.77 2.73 3.45 0 .69-.21 1.33-.55 1.87 1.31-.29 2.29-1.45 2.29-2.85 0-1.61-1.31-2.92-2.92-2.92zm-2.38 1c-1.61 0-2.92 1.31-2.92 2.93 0 1.61 1.31 2.92 2.92 2.92 1.62 0 2.93-1.31 2.93-2.92 0-1.62-1.31-2.93-2.93-2.93zm4.25 5.01l-.51.59c2.34.69 2.45 3.61 2.45 3.61h1.28c0-4.71-3.22-4.2-3.22-4.2zm-2.1.8l-2.12 2.09-2.12-2.09C3.12 10.24 3.89 15 3.89 15h11.08c.47-4.98-3.4-4.98-3.4-4.98z'; + break; + case 'buddicons-community': + path = 'M9 3c0-.67-.47-1.43-1-2-.5.5-1 1.38-1 2 0 .48.45 1 1 1s1-.47 1-1zm4 0c0-.67-.47-1.43-1-2-.5.5-1 1.38-1 2 0 .48.45 1 1 1s1-.47 1-1zM9 9V5.5c0-.55-.45-1-1-1-.57 0-1 .49-1 1V9c0 .55.45 1 1 1 .57 0 1-.49 1-1zm4 0V5.5c0-.55-.45-1-1-1-.57 0-1 .49-1 1V9c0 .55.45 1 1 1 .57 0 1-.49 1-1zm4 1c0-1.48-1.41-2.77-3.5-3.46V9c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5V6.01c-.17 0-.33-.01-.5-.01s-.33.01-.5.01V9c0 .83-.67 1.5-1.5 1.5S6.5 9.83 6.5 9V6.54C4.41 7.23 3 8.52 3 10c0 1.41.95 2.65 3.21 3.37 1.11.35 2.39 1.12 3.79 1.12s2.69-.78 3.79-1.13C16.04 12.65 17 11.41 17 10zm-7 5.43c1.43 0 2.74-.79 3.88-1.11 1.9-.53 2.49-1.34 3.12-2.32v3c0 2.21-3.13 4-7 4s-7-1.79-7-4v-3c.64.99 1.32 1.8 3.15 2.33 1.13.33 2.44 1.1 3.85 1.1z'; + break; + case 'buddicons-forums': + path = 'M13.5 7h-7C5.67 7 5 6.33 5 5.5S5.67 4 6.5 4h1.59C8.04 3.84 8 3.68 8 3.5 8 2.67 8.67 2 9.5 2h1c.83 0 1.5.67 1.5 1.5 0 .18-.04.34-.09.5h1.59c.83 0 1.5.67 1.5 1.5S14.33 7 13.5 7zM4 8h12c.55 0 1 .45 1 1s-.45 1-1 1H4c-.55 0-1-.45-1-1s.45-1 1-1zm1 3h10c.55 0 1 .45 1 1s-.45 1-1 1H5c-.55 0-1-.45-1-1s.45-1 1-1zm2 3h6c.55 0 1 .45 1 1s-.45 1-1 1h-1.09c.05.16.09.32.09.5 0 .83-.67 1.5-1.5 1.5h-1c-.83 0-1.5-.67-1.5-1.5 0-.18.04-.34.09-.5H7c-.55 0-1-.45-1-1s.45-1 1-1z'; + break; + case 'buddicons-friends': + path = 'M8.75 5.77C8.75 4.39 7 2 7 2S5.25 4.39 5.25 5.77 5.9 7.5 7 7.5s1.75-.35 1.75-1.73zm6 0C14.75 4.39 13 2 13 2s-1.75 2.39-1.75 3.77S11.9 7.5 13 7.5s1.75-.35 1.75-1.73zM9 17V9c0-.55-.45-1-1-1H6c-.55 0-1 .45-1 1v8c0 .55.45 1 1 1h2c.55 0 1-.45 1-1zm6 0V9c0-.55-.45-1-1-1h-2c-.55 0-1 .45-1 1v8c0 .55.45 1 1 1h2c.55 0 1-.45 1-1zm-9-6l2-1v2l-2 1v-2zm6 0l2-1v2l-2 1v-2zm-6 3l2-1v2l-2 1v-2zm6 0l2-1v2l-2 1v-2z'; + break; + case 'buddicons-groups': + path = 'M15.45 6.25c1.83.94 1.98 3.18.7 4.98-.8 1.12-2.33 1.88-3.46 1.78L10.05 18H9l-2.65-4.99c-1.13.16-2.73-.63-3.55-1.79-1.28-1.8-1.13-4.04.71-4.97.48-.24.96-.33 1.43-.31-.01.4.01.8.07 1.21.26 1.69 1.41 3.53 2.86 4.37-.19.55-.49.99-.88 1.25L9 16.58v-5.66C7.64 10.55 6.26 8.76 6 7c-.4-2.65 1-5 3.5-5s3.9 2.35 3.5 5c-.26 1.76-1.64 3.55-3 3.92v5.77l2.07-3.84c-.44-.23-.77-.71-.99-1.3 1.48-.83 2.65-2.69 2.91-4.4.06-.41.08-.82.07-1.22.46-.01.92.08 1.39.32z'; + break; + case 'buddicons-pm': + path = 'M10 2c3 0 8 5 8 5v11H2V7s5-5 8-5zm7 14.72l-3.73-2.92L17 11l-.43-.37-2.26 1.3.24-4.31-8.77-.52-.46 4.54-1.99-.95L3 11l3.73 2.8-3.44 2.85.4.43L10 13l6.53 4.15z'; + break; + case 'buddicons-replies': + path = 'M17.54 10.29c1.17 1.17 1.17 3.08 0 4.25-1.18 1.17-3.08 1.17-4.25 0l-.34-.52c0 3.66-2 4.38-2.95 4.98-.82-.6-2.95-1.28-2.95-4.98l-.34.52c-1.17 1.17-3.07 1.17-4.25 0-1.17-1.17-1.17-3.08 0-4.25 0 0 1.02-.67 2.1-1.3C3.71 7.84 3.2 6.42 3.2 4.88c0-.34.03-.67.08-1C3.53 5.66 4.47 7.22 5.8 8.3c.67-.35 1.85-.83 2.37-.92H8c-1.1 0-2-.9-2-2s.9-2 2-2v-.5c0-.28.22-.5.5-.5s.5.22.5.5v.5h2v-.5c0-.28.22-.5.5-.5s.5.22.5.5v.5c1.1 0 2 .9 2 2s-.9 2-2 2h-.17c.51.09 1.78.61 2.38.92 1.33-1.08 2.27-2.64 2.52-4.42.05.33.08.66.08 1 0 1.54-.51 2.96-1.36 4.11 1.08.63 2.09 1.3 2.09 1.3zM8.5 6.38c.5 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm3-2c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-2.3 5.73c-.12.11-.19.26-.19.43.02.25.23.46.49.46h1c.26 0 .47-.21.49-.46 0-.15-.07-.29-.19-.43-.08-.06-.18-.11-.3-.11h-1c-.12 0-.22.05-.3.11zM12 12.5c0-.12-.06-.28-.19-.38-.09-.07-.19-.12-.31-.12h-3c-.12 0-.22.05-.31.12-.11.1-.19.25-.19.38 0 .28.22.5.5.5h3c.28 0 .5-.22.5-.5zM8.5 15h3c.28 0 .5-.22.5-.5s-.22-.5-.5-.5h-3c-.28 0-.5.22-.5.5s.22.5.5.5zm1 2h1c.28 0 .5-.22.5-.5s-.22-.5-.5-.5h-1c-.28 0-.5.22-.5.5s.22.5.5.5z'; + break; + case 'buddicons-topics': + path = 'M10.44 1.66c-.59-.58-1.54-.58-2.12 0L2.66 7.32c-.58.58-.58 1.53 0 2.12.6.6 1.56.56 2.12 0l5.66-5.66c.58-.58.59-1.53 0-2.12zm2.83 2.83c-.59-.59-1.54-.59-2.12 0l-5.66 5.66c-.59.58-.59 1.53 0 2.12.6.6 1.56.55 2.12 0l5.66-5.66c.58-.58.58-1.53 0-2.12zm1.06 6.72l4.18 4.18c.59.58.59 1.53 0 2.12s-1.54.59-2.12 0l-4.18-4.18-1.77 1.77c-.59.58-1.54.58-2.12 0-.59-.59-.59-1.54 0-2.13l5.66-5.65c.58-.59 1.53-.59 2.12 0 .58.58.58 1.53 0 2.12zM5 15c0-1.59-1.66-4-1.66-4S2 13.78 2 15s.6 2 1.34 2h.32C4.4 17 5 16.59 5 15z'; + break; + case 'buddicons-tracking': + path = 'M10.98 6.78L15.5 15c-1 2-3.5 3-5.5 3s-4.5-1-5.5-3L9 6.82c-.75-1.23-2.28-1.98-4.29-2.03l2.46-2.92c1.68 1.19 2.46 2.32 2.97 3.31.56-.87 1.2-1.68 2.7-2.12l1.83 2.86c-1.42-.34-2.64.08-3.69.86zM8.17 10.4l-.93 1.69c.49.11 1 .16 1.54.16 1.35 0 2.58-.36 3.55-.95l-1.01-1.82c-.87.53-1.96.86-3.15.92zm.86 5.38c1.99 0 3.73-.74 4.74-1.86l-.98-1.76c-1 1.12-2.74 1.87-4.74 1.87-.62 0-1.21-.08-1.76-.21l-.63 1.15c.94.5 2.1.81 3.37.81z'; + break; + case 'buddipress-bbpress-logo': + path = 'M8.5 12.6c.3-1.3 0-2.3-1.1-2.3-.8 0-1.6.6-1.8 1.5l-.3 1.7c-.3 1 .3 1.5 1 1.5 1.2 0 1.9-1.1 2.2-2.4zm-4-6.4C3.7 7.3 3.3 8.6 3.3 10c0 1 .2 1.9.6 2.8l1-4.6c.3-1.7.4-2-.4-2zm9.3 6.4c.3-1.3 0-2.3-1.1-2.3-.8 0-1.6.6-1.8 1.5l-.4 1.7c-.2 1.1.4 1.6 1.1 1.6 1.1-.1 1.9-1.2 2.2-2.5zM10 3.3c-2 0-3.9.9-5.1 2.3.6-.1 1.4-.2 1.8-.3.2 0 .2.1.2.2 0 .2-1 4.8-1 4.8.5-.3 1.2-.7 1.8-.7.9 0 1.5.4 1.9.9l.5-2.4c.4-1.6.4-1.9-.4-1.9-.4 0-.4-.5 0-.6.6-.1 1.8-.2 2.3-.3.2 0 .2.1.2.2l-1 4.8c.5-.4 1.2-.7 1.9-.7 1.7 0 2.5 1.3 2.1 3-.3 1.7-2 3-3.8 3-1.3 0-2.1-.7-2.3-1.4-.7.8-1.7 1.3-2.8 1.4 1.1.7 2.4 1.1 3.7 1.1 3.7 0 6.7-3 6.7-6.7s-3-6.7-6.7-6.7zM10 2c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 15.5c-2.1 0-4-.8-5.3-2.2-.3-.4-.7-.8-1-1.2-.7-1.2-1.2-2.6-1.2-4.1 0-4.1 3.4-7.5 7.5-7.5s7.5 3.4 7.5 7.5-3.4 7.5-7.5 7.5z'; + break; case 'building': path = 'M3 20h14V0H3v20zM7 3H5V1h2v2zm4 0H9V1h2v2zm4 0h-2V1h2v2zM7 6H5V4h2v2zm4 0H9V4h2v2zm4 0h-2V4h2v2zM7 9H5V7h2v2zm4 0H9V7h2v2zm4 0h-2V7h2v2zm-8 3H5v-2h2v2zm4 0H9v-2h2v2zm4 0h-2v-2h2v2zm-4 7H5v-6h6v6zm4-4h-2v-2h2v2zm0 3h-2v-2h2v2z'; break; @@ -345,7 +387,7 @@ export default class Dashicon extends wp.element.Component { case 'email': path = 'M3.87 4h13.25C18.37 4 19 4.59 19 5.79v8.42c0 1.19-.63 1.79-1.88 1.79H3.87c-1.25 0-1.88-.6-1.88-1.79V5.79c0-1.2.63-1.79 1.88-1.79zm6.62 8.6l6.74-5.53c.24-.2.43-.66.13-1.07-.29-.41-.82-.42-1.17-.17l-5.7 3.86L4.8 5.83c-.35-.25-.88-.24-1.17.17-.3.41-.11.87.13 1.07z'; break; - case 'exerpt-view': + case 'excerpt-view': path = 'M19 18V2c0-.55-.45-1-1-1H2c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1zM4 3c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm13 0v6H6V3h11zM4 11c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm13 0v6H6v-6h11z'; break; case 'external': @@ -414,6 +456,9 @@ export default class Dashicon extends wp.element.Component { case 'hidden': path = 'M17.2 3.3l.16.17c.39.39.39 1.02 0 1.41L4.55 17.7c-.39.39-1.03.39-1.41 0l-.17-.17c-.39-.39-.39-1.02 0-1.41l1.59-1.6c-1.57-1-2.76-2.3-3.56-3.93.81-1.65 2.03-2.98 3.64-3.99S8.04 5.09 10 5.09c1.2 0 2.33.21 3.4.6l2.38-2.39c.39-.39 1.03-.39 1.42 0zm-7.09 4.01c-.23.25-.34.54-.34.88 0 .31.12.58.31.81l1.8-1.79c-.13-.12-.28-.21-.45-.26-.11-.01-.28-.03-.49-.04-.33.03-.6.16-.83.4zM2.4 10.59c.69 1.23 1.71 2.25 3.05 3.05l1.28-1.28c-.51-.69-.77-1.47-.77-2.36 0-1.06.36-1.98 1.09-2.76-1.04.27-1.96.7-2.76 1.26-.8.58-1.43 1.27-1.89 2.09zm13.22-2.13l.96-.96c1.02.86 1.83 1.89 2.42 3.09-.81 1.65-2.03 2.98-3.64 3.99s-3.4 1.51-5.36 1.51c-.63 0-1.24-.07-1.83-.18l1.07-1.07c.25.02.5.05.76.05 1.63 0 3.13-.4 4.5-1.21s2.4-1.84 3.1-3.09c-.46-.82-1.09-1.51-1.89-2.09-.03-.01-.06-.03-.09-.04zm-5.58 5.58l4-4c-.01 1.1-.41 2.04-1.18 2.81-.78.78-1.72 1.18-2.82 1.19z'; break; + case 'html': + path = 'M4 16v-2H2v2H1v-5h1v2h2v-2h1v5H4zM7 16v-4H5.6v-1h3.7v1H8v4H7zM10 16v-5h1l1.4 3.4h.1L14 11h1v5h-1v-3.1h-.1l-1.1 2.5h-.6l-1.1-2.5H11V16h-1zM19 16h-3v-5h1v4h2v1zM9.4 4.2L7.1 6.5l2.3 2.3-.6 1.2-3.5-3.5L8.8 3l.6 1.2zm1.2 4.6l2.3-2.3-2.3-2.3.6-1.2 3.5 3.5-3.5 3.5-.6-1.2z'; + break; case 'id-alt': path = 'M18 18H2V2h16v16zM8.05 7.53c.13-.07.24-.15.33-.24.09-.1.17-.21.24-.34.07-.14.13-.26.17-.37s.07-.22.1-.34L8.95 6c0-.04.01-.07.01-.09.05-.32.03-.61-.04-.9-.08-.28-.23-.52-.46-.72C8.23 4.1 7.95 4 7.6 4c-.2 0-.39.04-.56.11-.17.08-.31.18-.41.3-.11.13-.2.27-.27.44-.07.16-.11.33-.12.51s0 .36.01.55l.02.09c.01.06.03.15.06.25s.06.21.1.33.1.25.17.37c.08.12.16.23.25.33s.2.19.34.25c.13.06.28.09.43.09s.3-.03.43-.09zM16 5V4h-5v1h5zm0 2V6h-5v1h5zM7.62 8.83l-1.38-.88c-.41 0-.79.11-1.14.32-.35.22-.62.5-.81.85-.19.34-.29.7-.29 1.07v1.25l.2.05c.13.04.31.09.55.14.24.06.51.12.8.17.29.06.62.1 1 .14.37.04.73.06 1.07.06s.69-.02 1.07-.06.7-.09.98-.14c.27-.05.54-.1.82-.17.27-.06.45-.11.54-.13.09-.03.16-.05.21-.06v-1.25c0-.36-.1-.72-.31-1.07s-.49-.64-.84-.86-.72-.33-1.11-.33zM16 9V8h-3v1h3zm0 2v-1h-3v1h3zm0 3v-1H4v1h12zm0 2v-1H4v1h12z'; break; @@ -682,7 +727,7 @@ export default class Dashicon extends wp.element.Component { path = 'M11 7H9.49c-.63 0-1.25.3-1.59.7L7 5H4.13l-2.39 7h1.69l.74-2H7v4H2c-1.1 0-2-.9-2-2V5c0-1.1.9-2 2-2h7c1.1 0 2 .9 2 2v2zM6.51 9H4.49l1-2.93zM10 8h7c1.1 0 2 .9 2 2v7c0 1.1-.9 2-2 2h-7c-1.1 0-2-.9-2-2v-7c0-1.1.9-2 2-2zm7.25 5v-1.08h-3.17V9.75h-1.16v2.17H9.75V13h1.28c.11.85.56 1.85 1.28 2.62-.87.36-1.89.62-2.31.62-.01.02.22.97.2 1.46.84 0 2.21-.5 3.28-1.15 1.09.65 2.48 1.15 3.34 1.15-.02-.49.2-1.44.2-1.46-.43 0-1.49-.27-2.38-.63.7-.77 1.14-1.77 1.25-2.61h1.36zm-3.81 1.93c-.5-.46-.85-1.13-1.01-1.93h2.09c-.17.8-.51 1.47-1 1.93l-.04.03s-.03-.02-.04-.03z'; break; case 'trash': - path = 'M12 4h3c.55 0 1 .45 1 1v1H3V5c0-.55.45-1 1-1h3c.23-1.14 1.29-2 2.5-2s2.27.86 2.5 2zM8 4h3c-.21-.58-.85-1-1.5-1S8.21 3.42 8 4zM4 7h11v10c0 .55-.45 1-1 1H5c-.55 0-1-.45-1-1V7zm3 9V9H6v7h1zm3 0V9H9v7h1zm3 0V9h-1v7h1z'; + path = 'M12 4h3c.6 0 1 .4 1 1v1H3V5c0-.6.5-1 1-1h3c.2-1.1 1.3-2 2.5-2s2.3.9 2.5 2zM8 4h3c-.2-.6-.9-1-1.5-1S8.2 3.4 8 4zM4 7h11l-.9 10.1c0 .5-.5.9-1 .9H5.9c-.5 0-.9-.4-1-.9L4 7z'; break; case 'twitter': path = 'M18.94 4.46c-.49.73-1.11 1.38-1.83 1.9.01.15.01.31.01.47 0 4.85-3.69 10.44-10.43 10.44-2.07 0-4-.61-5.63-1.65.29.03.58.05.88.05 1.72 0 3.3-.59 4.55-1.57-1.6-.03-2.95-1.09-3.42-2.55.22.04.45.07.69.07.33 0 .66-.05.96-.13-1.67-.34-2.94-1.82-2.94-3.6v-.04c.5.27 1.06.44 1.66.46-.98-.66-1.63-1.78-1.63-3.06 0-.67.18-1.3.5-1.84 1.81 2.22 4.51 3.68 7.56 3.83-.06-.27-.1-.55-.1-.84 0-2.02 1.65-3.66 3.67-3.66 1.06 0 2.01.44 2.68 1.16.83-.17 1.62-.47 2.33-.89-.28.85-.86 1.57-1.62 2.02.75-.08 1.45-.28 2.11-.57z'; diff --git a/components/form-toggle/index.js b/components/form-toggle/index.js index 20571ad5ef8753..4bb1c279be986a 100644 --- a/components/form-toggle/index.js +++ b/components/form-toggle/index.js @@ -27,7 +27,7 @@ function FormToggle( { className, checked, id, onChange = noop, showHint = true className="components-form-toggle__input" id={ id } type="checkbox" - value={ checked } + checked={ checked } onChange={ onChange } /> { showHint && diff --git a/components/form-toggle/style.scss b/components/form-toggle/style.scss index bb91893cd893fb..3b5eddd0cbe216 100644 --- a/components/form-toggle/style.scss +++ b/components/form-toggle/style.scss @@ -72,6 +72,7 @@ $toggle-border-width: 2px; .components-form-toggle__hint { display: inline-block; + min-width: 24px; // This prevents a position jog when the control is right aligned, and the width of the label changes margin-left: 10px; font-weight: 500; } diff --git a/components/form-toggle/test/index.js b/components/form-toggle/test/index.js index 72a8d15d3d0fbb..34500ccd1c6fe3 100644 --- a/components/form-toggle/test/index.js +++ b/components/form-toggle/test/index.js @@ -17,15 +17,15 @@ describe( 'FormToggle', () => { expect( formToggle.hasClass( 'components-form-toggle' ) ).to.be.true(); expect( formToggle.hasClass( 'is-checked' ) ).to.be.false(); expect( formToggle.type() ).to.equal( 'span' ); - expect( formToggle.find( '.components-form-toggle__input' ).prop( 'value' ) ).to.be.undefined(); + expect( formToggle.find( '.components-form-toggle__input' ).prop( 'checked' ) ).to.be.undefined(); expect( formToggle.find( '.components-form-toggle__hint' ).text() ).to.equal( 'Off' ); expect( formToggle.find( '.components-form-toggle__hint' ).prop( 'aria-hidden' ) ).to.be.true(); } ); - it( 'should render a checked checkbox and change the accessability text to On when providing checked prop', () => { + it( 'should render a checked checkbox and change the accessibility text to On when providing checked prop', () => { const formToggle = shallow( ); expect( formToggle.hasClass( 'is-checked' ) ).to.be.true(); - expect( formToggle.find( '.components-form-toggle__input' ).prop( 'value' ) ).to.be.true(); + expect( formToggle.find( '.components-form-toggle__input' ).prop( 'checked' ) ).to.be.true(); expect( formToggle.find( '.components-form-toggle__hint' ).text() ).to.equal( 'On' ); } ); diff --git a/components/form-token-field/README.md b/components/form-token-field/README.md index d979c49b9ed1bf..24935da716bb6a 100644 --- a/components/form-token-field/README.md +++ b/components/form-token-field/README.md @@ -41,6 +41,7 @@ The `value` property is handled in a manner similar to controlled form component Otherwise the REST API won't save them.) - `onChange` - Function to call when the tokens have changed. An array of new tokens is passed to the callback. +- `onInputChange` - Function to call when the users types in the input field. It can be used to trigger autocomplete requests. - `onFocus` - Function to call when the TokenField has been focused on. The event is passed to the callback. Useful for analytics. - `suggestions` - An array of strings to present to the user as suggested tokens. diff --git a/components/form-token-field/index.js b/components/form-token-field/index.js index 059c3ab5ac8d4a..bc74ab311df5de 100644 --- a/components/form-token-field/index.js +++ b/components/form-token-field/index.js @@ -1,12 +1,13 @@ /** * External dependencies */ -import { last, take, clone, uniq, map, difference, each, identity, some } from 'lodash'; +import { last, take, clone, uniq, map, difference, each, identity, some, throttle } from 'lodash'; import classnames from 'classnames'; /** * WordPress dependencies */ +import { __, _n, sprintf } from 'i18n'; import { Component } from 'element'; /** @@ -16,6 +17,7 @@ import './style.scss'; import Token from './token'; import TokenInput from './token-input'; import SuggestionsList from './suggestions-list'; +import withInstanceId from '../higher-order/with-instance-id'; const initialState = { incompleteTokenValue: '', @@ -44,6 +46,7 @@ class FormTokenField extends Component { this.onInputChange = this.onInputChange.bind( this ); this.bindInput = this.bindInput.bind( this ); this.bindTokensAndInput = this.bindTokensAndInput.bind( this ); + this.throlltedSpeak = throttle( this.speak.bind( this ), 1000 ); } componentDidUpdate() { @@ -172,16 +175,33 @@ class FormTokenField extends Component { const text = event.value; const separator = this.props.tokenizeOnSpace ? /[ ,\t]+/ : /[,\t]+/; const items = text.split( separator ); + const tokenValue = last( items ) || ''; if ( items.length > 1 ) { this.addNewTokens( items.slice( 0, -1 ) ); } this.setState( { - incompleteTokenValue: last( items ) || '', + incompleteTokenValue: tokenValue, selectedSuggestionIndex: -1, selectedSuggestionScroll: false, } ); + + this.props.onInputChange( tokenValue ); + + const showMessage = tokenValue.trim().length > 1; + if ( showMessage ) { + const matchingSuggestions = this.getMatchingSuggestions( tokenValue ); + if ( !! matchingSuggestions.length ) { + this.throlltedSpeak( sprintf( _n( + '%d result found, use up and down arrow keys to navigate.', + '%d results found, use up and down arrow keys to navigate.', + matchingSuggestions.length + ), matchingSuggestions.length ) ); + } else { + this.throlltedSpeak( __( 'No results.' ) ); + } + } } handleDeleteKey( deleteToken ) { @@ -227,7 +247,13 @@ class FormTokenField extends Component { this.setState( ( state, props ) => ( { selectedSuggestionIndex: Math.min( ( state.selectedSuggestionIndex + 1 ) || 0, - this.getMatchingSuggestions( state, props ).length - 1 + this.getMatchingSuggestions( + state.incompleteTokenValue, + props.suggestions, + props.value, + props.maxSuggestions, + props.saveTransform + ).length - 1 ), selectedSuggestionScroll: true, } ) ); @@ -314,6 +340,7 @@ class FormTokenField extends Component { addNewToken( token ) { this.addNewTokens( [ token ] ); + this.speak( this.props.messages.added ); this.setState( { incompleteTokenValue: '', @@ -331,6 +358,7 @@ class FormTokenField extends Component { return this.getTokenValue( item ) !== this.getTokenValue( token ); } ); this.props.onChange( newTokens ); + this.speak( this.props.messages.removed ); } getTokenValue( token ) { @@ -341,20 +369,25 @@ class FormTokenField extends Component { return token; } - getMatchingSuggestions( state = this.state, props = this.props ) { - let suggestions = props.suggestions; - let match = props.saveTransform( state.incompleteTokenValue ); + getMatchingSuggestions( + searchValue = this.state.incompleteTokenValue, + suggestions = this.props.suggestions, + value = this.props.value, + maxSuggestions = this.props.maxSuggestions, + saveTransform = this.props.saveTransform, + ) { + let match = saveTransform( searchValue ); const startsWithMatch = []; const containsMatch = []; if ( match.length === 0 ) { - suggestions = difference( suggestions, props.value ); + suggestions = difference( suggestions, value ); } else { match = match.toLocaleLowerCase(); each( suggestions, ( suggestion ) => { const index = suggestion.toLocaleLowerCase().indexOf( match ); - if ( props.value.indexOf( suggestion ) === -1 ) { + if ( value.indexOf( suggestion ) === -1 ) { if ( index === 0 ) { startsWithMatch.push( suggestion ); } else if ( index > 0 ) { @@ -366,7 +399,11 @@ class FormTokenField extends Component { suggestions = startsWithMatch.concat( containsMatch ); } - return take( suggestions, props.maxSuggestions ); + return take( suggestions, maxSuggestions ); + } + + speak( message ) { + wp.a11y.speak( message, 'assertive' ); } getSelectedSuggestion() { @@ -416,14 +453,16 @@ class FormTokenField extends Component { onMouseEnter={ token.onMouseEnter } onMouseLeave={ token.onMouseLeave } disabled={ 'error' !== status && this.props.disabled } + messages={ this.props.messages } /> ); } renderInput() { - const { autoCapitalize, autoComplete, maxLength, value, placeholder } = this.props; + const { autoCapitalize, autoComplete, maxLength, value, placeholder, instanceId } = this.props; let props = { + instanceId, autoCapitalize, autoComplete, ref: this.bindInput, @@ -431,6 +470,8 @@ class FormTokenField extends Component { disabled: this.props.disabled, value: this.state.incompleteTokenValue, onBlur: this.onBlur, + isExpanded: this.state.isActive, + selectedSuggestionIndex: this.state.selectedSuggestionIndex, }; if ( value.length === 0 && placeholder ) { @@ -447,7 +488,11 @@ class FormTokenField extends Component { } render() { - const { disabled } = this.props; + const { + disabled, + placeholder = _( 'Add item.' ), + instanceId, + } = this.props; const classes = classnames( 'components-form-token-field', { 'is-active': this.state.isActive, 'is-disabled': disabled, @@ -458,6 +503,8 @@ class FormTokenField extends Component { className: classes, tabIndex: '-1', }; + const matchingSuggestions = this.getMatchingSuggestions(); + const showSuggestions = this.state.incompleteTokenValue.trim().length > 1; if ( ! disabled ) { tokenFieldProps = Object.assign( {}, tokenFieldProps, { @@ -469,6 +516,9 @@ class FormTokenField extends Component { return (
    +
    { this.renderTokensAndInput() }
    - + + { showSuggestions && ( + + ) } +
    + { __( 'Separate with commas' ) } +
    ); } @@ -500,9 +557,15 @@ FormTokenField.defaultProps = { displayTransform: identity, saveTransform: ( token ) => token.trim(), onChange: () => {}, + onInputChange: () => {}, isBorderless: false, disabled: false, tokenizeOnSpace: false, + messages: { + added: __( 'Item added.' ), + removed: __( 'Item removed.' ), + remove: __( 'Remove item: %s.' ), + }, }; -export default FormTokenField; +export default withInstanceId( FormTokenField ); diff --git a/components/form-token-field/suggestions-list.js b/components/form-token-field/suggestions-list.js index a455e9932074f4..40f06232d55bde 100644 --- a/components/form-token-field/suggestions-list.js +++ b/components/form-token-field/suggestions-list.js @@ -81,7 +81,13 @@ class SuggestionsList extends Component { // why, since usually a div isn't focusable by default // TODO does this still apply now that it's a
      and not a
      ? return ( -
        +
          { map( this.props.suggestions, ( suggestion, index ) => { const match = this.computeSuggestionMatch( suggestion ); @@ -89,17 +95,22 @@ class SuggestionsList extends Component { 'is-selected': index === this.props.selectedIndex, } ); - /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ return (
        • + onMouseEnter={ this.handleHover( suggestion ) } + aria-selected={ index === this.props.selectedIndex } + > { match ? ( - + { match.suggestionBeforeMatch } { match.suggestionMatch } @@ -111,7 +122,7 @@ class SuggestionsList extends Component { }
        • ); - /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ } ) }
        diff --git a/components/form-token-field/test/index.js b/components/form-token-field/test/index.js index 0d0dceaf1d0772..88517e684392f7 100644 --- a/components/form-token-field/test/index.js +++ b/components/form-token-field/test/index.js @@ -133,9 +133,10 @@ describe( 'FormTokenField', function() { } ); describe( 'suggestions', function() { - it( 'should render default suggestions', function() { - // limited by maxSuggestions (default 100 so doesn't matter here) - expect( getSuggestionsText() ).to.deep.equal( wrapper.state( 'tokenSuggestions' ) ); + it( 'should not render suggestions unless we type at least two characters', function() { + expect( getSuggestionsText() ).to.eql( [] ); + setText( 'th' ); + expect( getSuggestionsText() ).to.eql( fixtures.matchingSuggestions.th ); } ); it( 'should remove already added tags from suggestions', function() { @@ -145,32 +146,13 @@ describe( 'FormTokenField', function() { expect( getSuggestionsText() ).to.not.include.members( getTokensHTML() ); } ); - it( 'should suggest partial matches', function() { - setText( 't' ); - expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.t ); - } ); - it( 'suggestions that begin with match are boosted', function() { - setText( 's' ); - expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.s ); - } ); - - it( 'should display suggestions with escaped special characters properly', function() { - wrapper.setState( { - tokenSuggestions: fixtures.specialSuggestions.textEscaped, - } ); - expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.htmlEscaped ); - } ); - - it( 'should display suggestions with special characters properly', function() { - wrapper.setState( { - tokenSuggestions: fixtures.specialSuggestions.textUnescaped, - } ); - expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.htmlUnescaped ); + setText( 'so' ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.so ); } ); it( 'should match against the unescaped values of suggestions with special characters', function() { - setText( '&' ); + setText( '& S' ); wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textUnescaped, } ); @@ -202,30 +184,30 @@ describe( 'FormTokenField', function() { // We need a high timeout here to accomodate Travis CI this.timeout( 10000 ); - setText( 't' ); - expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.t ); + setText( 'th' ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.th ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); - sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'e' ] ); + sendKeyDown( keyCodes.downArrow ); // 'that' + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'at' ] ); - const hoverSuggestion = tokenFieldNode.find( '.components-form-token-field__suggestion' ).at( 5 ); // 'it' - expect( getSuggestionNodeText( hoverSuggestion ) ).to.deep.equal( [ 'i', 't' ] ); + const hoverSuggestion = tokenFieldNode.find( '.components-form-token-field__suggestion' ).at( 3 ); // 'with' + expect( getSuggestionNodeText( hoverSuggestion ) ).to.deep.equal( [ 'wi', 'th' ] ); // before sending a hover event, we need to wait for // SuggestionList#_scrollingIntoView to become false this.clock.tick( 100 ); hoverSuggestion.simulate( 'mouseEnter' ); - expect( getSelectedSuggestion() ).to.deep.equal( [ 'i', 't' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'wi', 'th' ] ); sendKeyDown( keyCodes.upArrow ); - expect( getSelectedSuggestion() ).to.deep.equal( [ 'wi', 't', 'h' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'is' ] ); sendKeyDown( keyCodes.upArrow ); - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'his' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'at' ] ); hoverSuggestion.simulate( 'click' ); expect( getSelectedSuggestion() ).to.equal( null ); - expect( getTokensHTML() ).to.deep.equal( [ 'foo', 'bar', 'it' ] ); + expect( getTokensHTML() ).to.deep.equal( [ 'foo', 'bar', 'with' ] ); } ) ); } ); @@ -319,32 +301,31 @@ describe( 'FormTokenField', function() { 't', // initialText false, // selectSuggestion null, // expectedSuggestion - [ 'foo', 'bar', 't' ] // expectedTokens + [ 'foo', 'bar', 't' ] // expectedTokens ); } ) ); - it( 'should add the suggested token when the (non-blank) input field loses focus', test( function() { + it( 'shouldn\'t show any suggestion when the initial text is smaller than two characters', test( function() { testOnBlur( 't', // initialText true, // selectSuggestion - [ 't', 'o' ], // expectedSuggestion - [ 'foo', 'bar', 'to' ] // expectedTokens + null, // expectedSuggestion + [ 'foo', 'bar', 'to' ] // expectedTokens ); } ) ); - it( 'should not add the suggested token when the (blank) input field loses focus', test( function() { + it( 'should add the suggested token when the (non-blank) input field loses focus', test( function() { testOnBlur( - '', // initialText - true, // selectSuggestion - 'of', // expectedSuggestion - [ 'foo', 'bar' ], // expectedTokens - this.clock + 'to', // initialText + true, // selectSuggestion + [ 'to' ], // expectedSuggestion + [ 'foo', 'bar', 'to' ] // expectedTokens ); } ) ); it( 'should not lose focus when a suggestion is clicked', test( function() { // prevents regression of https://github.com/Automattic/wp-calypso/issues/1884 - + setText( 'th' ); const firstSuggestion = tokenFieldNode.find( '.components-form-token-field__suggestion' ).at( 0 ); firstSuggestion.simulate( 'click' ); @@ -364,48 +345,26 @@ describe( 'FormTokenField', function() { } ); it( 'should add tokens from the selected matching suggestion using Tab', function() { - setText( 't' ); + setText( 'th' ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); - sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'e' ] ); + sendKeyDown( keyCodes.downArrow ); // 'that' + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'at' ] ); sendKeyDown( keyCodes.tab ); - expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'to' ] ); + expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'that' ] ); expect( getSelectedSuggestion() ).to.equal( null ); } ); it( 'should add tokens from the selected matching suggestion using Enter', function() { - setText( 't' ); - expect( getSelectedSuggestion() ).to.equal( null ); - sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); - sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); - sendKeyDown( keyCodes.enter ); - expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'to' ] ); - expect( getSelectedSuggestion() ).to.equal( null ); - } ); - - it( 'should add tokens from the selected suggestion using Tab', function() { - expect( getSelectedSuggestion() ).to.equal( null ); - sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.equal( 'the' ); - sendKeyDown( keyCodes.downArrow ); // 'of' - expect( getSelectedSuggestion() ).to.equal( 'of' ); - sendKeyDown( keyCodes.tab ); - expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'of' ] ); - expect( getSelectedSuggestion() ).to.equal( null ); - } ); - - it( 'should add tokens from the selected suggestion using Enter', function() { + setText( 'th' ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.equal( 'the' ); - sendKeyDown( keyCodes.downArrow ); // 'of' - expect( getSelectedSuggestion() ).to.equal( 'of' ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'e' ] ); + sendKeyDown( keyCodes.downArrow ); // 'that' + expect( getSelectedSuggestion() ).to.deep.equal( [ 'th', 'at' ] ); sendKeyDown( keyCodes.enter ); - expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'of' ] ); + expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'that' ] ); expect( getSelectedSuggestion() ).to.equal( null ); } ); } ); diff --git a/components/form-token-field/test/lib/fixtures.js b/components/form-token-field/test/lib/fixtures.js index 89c64916fe502c..b5d27598fd7802 100644 --- a/components/form-token-field/test/lib/fixtures.js +++ b/components/form-token-field/test/lib/fixtures.js @@ -7,13 +7,10 @@ export default { }, specialSuggestions: { textEscaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], - htmlEscaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], textUnescaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], - htmlUnescaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], matchAmpersandUnescaped: [ - [ 'Stuff ', '&', ' Things' ], - [ 'Tags ', '&', ' Stuff' ], - [ 'Tags ', '&', ' Stuff 2' ], + [ 'Tags ', '& S', 'tuff' ], + [ 'Tags ', '& S', 'tuff 2' ], ], matchAmpersandSequence: [ [ 'Tag', 's &', ' Stuff' ], @@ -22,28 +19,20 @@ export default { matchAmpersandEscaped: [], }, matchingSuggestions: { - t: [ - [ 't', 'he' ], - [ 't', 'o' ], - [ 't', 'hat' ], - [ 't', 'his' ], - [ 'wi', 't', 'h' ], - [ 'i', 't' ], - [ 'no', 't' ], - [ 'a', 't' ], + th: [ + [ 'th', 'e' ], + [ 'th', 'at' ], + [ 'th', 'is' ], + [ 'wi', 'th' ], ], - s: [ - [ 's', 'nake' ], - [ 's', 'ound' ], - [ 'i', 's' ], - [ 'thi', 's' ], - [ 'a', 's' ], - [ 'wa', 's' ], - [ 'pipe', 's' ], + so: [ + [ 'so', 'und' ], + [ 'as', 'so', 'ciate' ], ], at: [ [ 'at' ], [ 'th', 'at' ], + [ 'associ', 'at', 'e' ], ], }, }; diff --git a/components/form-token-field/test/lib/token-field-wrapper.js b/components/form-token-field/test/lib/token-field-wrapper.js index 166c1e8a6eb781..e73e1243388c4a 100644 --- a/components/form-token-field/test/lib/token-field-wrapper.js +++ b/components/form-token-field/test/lib/token-field-wrapper.js @@ -12,7 +12,7 @@ import TokenField from '../../'; const suggestions = [ 'the', 'of', 'and', 'to', 'a', 'in', 'for', 'is', 'on', 'that', 'by', 'this', 'with', 'i', 'you', 'it', 'not', 'or', 'be', 'are', 'from', 'at', 'as', 'your', 'all', 'have', 'new', 'more', 'an', 'was', 'we', - 'snake', 'pipes', 'sound', + 'associate', 'snake', 'pipes', 'sound', ]; function unescapeAndFormatSpaces( str ) { diff --git a/components/form-token-field/token-input.js b/components/form-token-field/token-input.js index c8b9314ff43583..0e904c16801fa8 100644 --- a/components/form-token-field/token-input.js +++ b/components/form-token-field/token-input.js @@ -29,17 +29,26 @@ class TokenInput extends Component { } render() { - const props = { ...this.props, onChange: this.onChange }; - const { value, placeholder } = props; + const { value, placeholder, isExpanded, instanceId, selectedSuggestionIndex, ...props } = this.props; const size = ( ( value.length === 0 && placeholder && placeholder.length ) || value.length ) + 1; return ( ); } diff --git a/components/form-token-field/token.js b/components/form-token-field/token.js index e16734d413435d..2e03e3cf980e7e 100644 --- a/components/form-token-field/token.js +++ b/components/form-token-field/token.js @@ -7,6 +7,7 @@ import { noop } from 'lodash'; /** * WordPress dependencies */ +import { sprintf } from 'i18n'; import IconButton from 'components/icon-button'; function Token( { @@ -19,6 +20,7 @@ function Token( { onClickRemove = noop, onMouseEnter, onMouseLeave, + messages, } ) { const tokenClasses = classnames( 'components-form-token-field__token', { 'is-error': 'error' === status, @@ -41,10 +43,12 @@ function Token( { { displayTransform( value ) } + ); diff --git a/components/html-embed/index.js b/components/html-embed/index.js deleted file mode 100644 index c4e113f13e54d4..00000000000000 --- a/components/html-embed/index.js +++ /dev/null @@ -1,33 +0,0 @@ -// When embedding HTML from the WP oEmbed proxy, we need to insert it -// into a div and make sure any scripts get run. This component takes -// HTML and puts it into a div element, and creates and adds new script -// elements so all scripts get run as expected. - -export default class HtmlEmbed extends wp.element.Component { - - componentDidMount() { - const body = this.node; - const { html = '' } = this.props; - - body.innerHTML = html; - - const scripts = body.getElementsByTagName( 'script' ); - const newScripts = Array.from( scripts ).map( ( script ) => { - const newScript = document.createElement( 'script' ); - if ( script.src ) { - newScript.src = script.src; - } else { - newScript.innerHTML = script.innerHTML; - } - return newScript; - } ); - - newScripts.forEach( ( script ) => body.appendChild( script ) ); - } - - render() { - return ( -
        this.node = node } /> - ); - } -} diff --git a/components/icon-button/style.scss b/components/icon-button/style.scss index 67794e0fa18274..fcc5caee91dc92 100644 --- a/components/icon-button/style.scss +++ b/components/icon-button/style.scss @@ -27,7 +27,7 @@ } &:focus { - box-shadow: 0 0 0 1px $blue-medium-400, 0 0 2px 1px $blue-medium-400; + box-shadow: $button-focus-style; outline: none; } diff --git a/components/index.js b/components/index.js index d0b4689b205334..8d5a608fa52d42 100644 --- a/components/index.js +++ b/components/index.js @@ -4,13 +4,15 @@ export { default as ClipboardButton } from './clipboard-button'; export { default as Dashicon } from './dashicon'; export { default as FormToggle } from './form-toggle'; export { default as FormTokenField } from './form-token-field'; -export { default as HtmlEmbed } from './html-embed'; export { default as IconButton } from './icon-button'; +export { default as Notice } from './notice'; +export { default as NoticeList } from './notice/list'; export { default as Panel } from './panel'; export { default as PanelHeader } from './panel/header'; export { default as PanelBody } from './panel/body'; export { default as Placeholder } from './placeholder'; export { default as ResponsiveWrapper } from './responsive-wrapper'; +export { default as SandBox } from './sandbox'; export { default as Spinner } from './spinner'; export { default as Toolbar } from './toolbar'; export { default as Popover } from './popover'; diff --git a/components/notice/index.js b/components/notice/index.js new file mode 100644 index 00000000000000..8c1b063cfde8da --- /dev/null +++ b/components/notice/index.js @@ -0,0 +1,28 @@ +/** + * External dependencies + */ +import { isString, noop } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; + +/** + * Internal Dependencies + */ +import './style.scss'; + +function Notice( { status, content, onRemove = noop } ) { + const className = `notice notice-alt is-dismissible notice-${ status }`; + return ( +
        + { isString( content ) ?

        { content }

        : content } + +
        + ); +} + +export default Notice; diff --git a/components/notice/list.js b/components/notice/list.js new file mode 100644 index 00000000000000..888c755537e1c2 --- /dev/null +++ b/components/notice/list.js @@ -0,0 +1,23 @@ +/** + * External depednencies + */ +import { noop } from 'lodash'; + +/** + * Internal dependencies + */ +import Notice from './'; + +function NoticeList( { notices, onRemove = noop } ) { + const removeNotice = ( id ) => () => onRemove( id ); + + return ( +
        + { notices.reverse().map( ( notice ) => ( + + ) ) } +
        + ); +} + +export default NoticeList; diff --git a/components/notice/style.scss b/components/notice/style.scss new file mode 100644 index 00000000000000..a57109491d4683 --- /dev/null +++ b/components/notice/style.scss @@ -0,0 +1,8 @@ +.components-notice-list { + position: fixed; + top: 40px; + right: 0; + min-width: 300px; + max-width: 400px; + z-index: z-index( ".components-notice-list" ); +} diff --git a/components/panel/style.scss b/components/panel/style.scss index 50a74919376fc7..0d0dbcfb6562e0 100644 --- a/components/panel/style.scss +++ b/components/panel/style.scss @@ -18,10 +18,13 @@ } .components-panel__body { - padding: 15px; - border: 1px solid $light-gray-500; - margin-left: -1px; - margin-right: -1px; + padding: $panel-padding; + border-top: 1px solid $light-gray-500; + border-bottom: 1px solid $light-gray-500; + + h3 { + margin: 0 0 .5em 0; + } } .components-panel__header { @@ -29,11 +32,10 @@ justify-content: space-between; align-items: center; background: $light-gray-300; - padding: 0 15px; + padding: 0 $panel-padding; height: 50px; - border: 1px solid $light-gray-500; - margin-left: -1px; - margin-right: -1px; + border-top: 1px solid $light-gray-500; + border-bottom: 1px solid $light-gray-500; h2 { margin: 0; @@ -49,7 +51,7 @@ margin-top: -1px; } -.components-panel__body-title { +.components-panel .components-panel__body-title { display: block; padding: 0; margin: 0; diff --git a/components/placeholder/index.js b/components/placeholder/index.js index fdaf803246d275..be362bdf7866ac 100644 --- a/components/placeholder/index.js +++ b/components/placeholder/index.js @@ -13,7 +13,7 @@ function Placeholder( { icon, children, label, instructions, className, ...addit const classes = classnames( 'components-placeholder', className ); return ( -
        +
        { !! icon && } { label } diff --git a/components/placeholder/test/index.js b/components/placeholder/test/index.js index dc8c01ad076f39..4b84f0a56489a1 100644 --- a/components/placeholder/test/index.js +++ b/components/placeholder/test/index.js @@ -35,13 +35,12 @@ describe( 'Placeholder', () => { expect( placeholderLabel.find( 'Dashicon' ).exists() ).to.be.true(); } ); - it( 'should render a label section and add aria label', () => { + it( 'should render a label section', () => { const label = 'WordPress'; const placeholder = shallow( ); const placeholderLabel = placeholder.find( '.components-placeholder__label' ); const child = placeholderLabel.childAt( 0 ); - expect( placeholder.prop( 'aria-label' ) ).to.equal( label ); expect( child.text() ).to.equal( label ); } ); diff --git a/components/popover/style.scss b/components/popover/style.scss index 3c01adcbf26379..51537e03dcae60 100644 --- a/components/popover/style.scss +++ b/components/popover/style.scss @@ -8,7 +8,7 @@ right: 0; @include break-medium { - width: 280px; + width: 300px; left: -122px; right: auto; height: auto; diff --git a/components/sandbox/index.js b/components/sandbox/index.js new file mode 100644 index 00000000000000..630939c92b6e4e --- /dev/null +++ b/components/sandbox/index.js @@ -0,0 +1,163 @@ +import { renderToString } from 'element'; + +export default class Sandbox extends wp.element.Component { + + constructor() { + super( ...arguments ); + this.state = { + width: 0, + height: 0, + }; + this.trySandbox = this.trySandbox.bind( this ); + this.checkMessageForResize = this.checkMessageForResize.bind( this ); + } + + isFrameAccessible() { + try { + return !! this.iframe.contentDocument.body; + } catch ( e ) { + return false; + } + } + + checkMessageForResize( event ) { + const iframe = this.iframe; + + // Attempt to parse the message data as JSON if passed as string + let data = event.data || {}; + if ( 'string' === typeof data ) { + try { + data = JSON.parse( data ); + } catch ( e ) {} // eslint-disable-line no-empty + } + + // Verify that the mounted element is the source of the message + if ( ! iframe || iframe.contentWindow !== event.source ) { + return; + } + + // Update the state only if the message is formatted as we expect, i.e. + // as an object with a 'resize' action, width, and height + const { action, width, height } = data; + const { width: oldWidth, height: oldHeight } = this.state; + + if ( 'resize' === action && ( oldWidth !== width || oldHeight !== height ) ) { + this.setState( { width, height } ); + } + } + + componentDidMount() { + window.addEventListener( 'message', this.checkMessageForResize, false ); + this.trySandbox(); + } + + componentDidUpdate() { + this.trySandbox(); + } + + componentWillUnmount() { + window.removeEventListener( 'message', this.checkMessageForResize ); + } + + trySandbox() { + if ( ! this.isFrameAccessible() ) { + return; + } + + const body = this.iframe.contentDocument.body; + if ( null !== body.getAttribute( 'data-resizable-iframe-connected' ) ) { + return; + } + + const observeAndResizeJS = ` + ( function() { + var observer; + + if ( ! window.MutationObserver || ! document.body || ! window.top ) { + return; + } + + function sendResize() { + window.top.postMessage( { + action: 'resize', + width: document.body.offsetWidth, + height: document.body.offsetHeight + }, '*' ); + } + + observer = new MutationObserver( sendResize ); + observer.observe( document.body, { + attributes: true, + attributeOldValue: false, + characterData: true, + characterDataOldValue: false, + childList: true, + subtree: true + } ); + + window.addEventListener( 'load', sendResize, true ); + + // Hack: Remove viewport unit styles, as these are relative + // the iframe root and interfere with our mechanism for + // determining the unconstrained page bounds. + function removeViewportStyles( ruleOrNode ) { + [ 'width', 'height', 'minHeight', 'maxHeight' ].forEach( function( style ) { + if ( /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] ) ) { + ruleOrNode.style[ style ] = ''; + } + } ); + } + + Array.prototype.forEach.call( document.querySelectorAll( '[style]' ), removeViewportStyles ); + Array.prototype.forEach.call( document.styleSheets, function( stylesheet ) { + Array.prototype.forEach.call( stylesheet.cssRules || stylesheet.rules, removeViewportStyles ); + } ); + + document.body.style.position = 'absolute'; + document.body.setAttribute( 'data-resizable-iframe-connected', '' ); + + sendResize(); + } )();`; + + // put the html snippet into a html document, and then write it to the iframe's document + // we can use this in the future to inject custom styles or scripts + const htmlDoc = ( + + + { this.props.title } + + +
        +
    Version