diff --git a/README.md b/README.md index e8c31b87ddc8d..2e4b74058cd59 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Prototyping since 1440. This is the development and prototyping hub for the editor focus in core. +Gutenberg is the project name. Conversations and discussions take place in #core-editor in Slack. > 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 @@ -10,7 +11,6 @@ This is the development and prototyping hub for the editor focus in core. - What are little blocks made of? - Editor Technical Overview -- Mockups: https://cloudup.com/c9pKpaoDpQ4 ## Prototypes @@ -22,6 +22,36 @@ This is the development and prototyping hub for the editor focus in core. - WP Post grammar parser. ----- +## Mockups -Conversations and discussions take place in #core-editor in Slack. +These mockups are all subject to change and feedback. + +See also, clickable prototype. + +**Formatting** + +![Hover](mockups/Formatting, Hover.png) + +![Click](mockups/Formatting, Click.png) + +**New Blocks** + +![New Blocks](mockups/New Blocks.png) +![Insert Between](mockups/Insert Between.png) +![Insert Between, Keyboard Only](mockups/Insert Between, Keyboard.png) +![Insert](mockups/Insert.png) + +**Type Switcher** + +![Switcher](mockups/Type Switcher.png) + +**Other Blocks** + +![Image](mockups/Image.png) +![Quote](mockups/Quote.png) +![Quote 2](mockups/Quote 2.png) +![Headings](mockups/Headings.png) + +**Mobile** + +![Mobile](mockups/Mobile.png) diff --git a/blocks.js b/blocks.js index 8873400246e0d..e7fe7a19f7788 100644 --- a/blocks.js +++ b/blocks.js @@ -40,50 +40,181 @@ var config = { 'default': [] }, blockCategories: [ - { id: 'frequent', label: 'Frequently Used' }, - { id: 'media', label: 'Media' } + { id: 'common', label: 'Common' }, + { id: 'media', label: 'Media' }, + { id: 'embeds', label: 'Embeds' }, + { id: 'other', label: 'Other' }, + { id: 'layout', label: 'Layout' } ], blocks: [ - { - label: 'Paragraph', - icon: '', - categories: [ 'frequent' ] - }, - { - label: 'Heading', - icon: 'Heading', - categories: [ 'frequent' ] - }, - { - label: 'Image', - icon: 'Image', - categories: [ 'frequent' ] - }, - { - label: 'Quote', - icon: '', - categories: [ 'frequent' ] - }, - { - label: 'Gallery', - icon: '', - categories: [ 'media' ] - }, - { - label: 'Unordered List', - icon: '', - categories: [ 'frequent' ] - }, - { - label: 'Ordered List', - icon: '', - categories: [ 'frequent' ] - }, - { - label: 'Embed', - icon: '', - categories: [ 'media' ] - } + { + id: 'paragraph', + label: 'Paragraph', + icon: '', + category: 'common' + }, + { + id: 'heading', + label: 'Heading', + icon: 'Heading', + category: 'common' + }, + { + id: 'image', + label: 'Image', + icon: 'Image', + category: 'common' + }, + { + id: 'quote', + label: 'Quote', + icon: '', + category: 'common' + }, + { + id: 'gallery', + label: 'Gallery', + icon: '', + category: 'media' + }, + { + id: 'unordered-list', + label: 'Unordered List', + icon: '', + category: 'common' + }, + { + id: 'ordered-list', + label: 'Ordered List', + icon: '', + category: 'common' + }, + { + id: 'embed', + label: 'Embed', + icon: '', + category: 'embeds' + }, + { + id: 'separator', + label: 'Separator', + icon: 'Minus Small', + category: 'common' + }, + { + id: 'map', + label: 'Map', + icon: 'Custom Post Type', + category: 'embeds' + }, + { + id: 'google-map', + label: 'Google Map', + icon: 'Custom Post Type', + category: 'other' + }, + { + id: 'openstreet-map', + label: 'OpenStreet Map', + icon: 'Custom Post Type', + category: 'other' + }, + { + id: 'tweet', + label: 'Tweet', + icon: '', + category: 'other' + }, + { + id: 'video', + label: 'Video', + icon: 'Video', + category: 'media' + }, + { + id: 'youtube', + label: 'YouTube', + icon: '', + category: 'media' + }, + { + id: 'vimeo', + label: 'Vimeo', + icon: '', + category: 'media' + }, + { + id: 'audio', + label: 'Audio', + icon: 'Audio', + category: 'media' + }, + { + id: 'form', + label: 'Form', + icon: 'Custom Post Type', + category: 'other' + }, + { + id: 'survey', + label: 'Survey', + icon: 'Custom Post Type', + category: 'other' + }, + { + id: 'toc', + label: 'Table of Contents', + icon: 'Pages', + category: 'layout' + }, + { + id: 'wordpress-post', + label: 'WordPress Post', + icon: 'My Sites', + category: 'other' + }, + { + id: 'facebook-post', + label: 'Facebook Post', + icon: '', + category: 'other' + }, + { + id: 'opengraph-link', + label: 'OpenGraph Link', + icon: 'Link', + category: 'other' + }, + { + id: 'playlist', + label: 'Playlist', + icon: 'Audio', + category: 'media' + }, + { + id: 'spotify-playlist', + label: 'Spotify Playlist', + icon: '', + category: 'media' + }, + { + id: 'poet', + label: 'Poet', + icon: 'Pencil', + category: 'layout' + }, + { + id: 'custom-field', + label: 'Custom Field', + icon: 'Layout Blocks', + category: 'layout' + }, + { + id: 'gist', + label: 'Gist', + icon: 'Code', + category: 'other' + } ] }; @@ -91,8 +222,7 @@ var editor = queryFirst( '.editor' ); var switcher = queryFirst( '.block-switcher' ); var switcherButtons = query( '.block-switcher .type svg' ); var switcherMenu = queryFirst( '.switch-block__menu' ); -var blockControls = queryFirst( '.block-controls' ); -var inlineControls = queryFirst( '.inline-controls' ); +var dockedControls = queryFirst( '.docked-controls' ); var insertBlockButton = queryFirst( '.insert-block__button' ); var insertBlockMenu = queryFirst( '.insert-block__menu' ); var insertBlockMenuSearchInput = queryFirst( '.insert-block__search' ); @@ -105,8 +235,30 @@ var imageAlignNone = queryFirst( '.block-image__no-align' ); var imageAlignLeft = queryFirst( '.block-image__align-left' ); var imageAlignRight = queryFirst( '.block-image__align-right' ); +// Contants +var KEY_ENTER = 13; +var KEY_ARROW_LEFT = 37; +var KEY_ARROW_UP = 38; +var KEY_ARROW_RIGHT = 39; +var KEY_ARROW_DOWN = 40; + +// Editor Variables var selectedBlock = null; + +// Block Menu Variables +var previouslyFocusedBlock = null; var searchBlockFilter = ''; +var blockMenuOpened = false; +var menuSelectedBlock = null; + +// Helper variables +var orderedBlocks = config.blockCategories.reduce( function( memo, category ) { + var categoryBlocks = config.blocks.filter( function( block ) { + return block.category === category.id; + } ); + + return memo.concat( categoryBlocks ); +}, [] ); var supportedBlockTags = Object.keys( config.tagTypes ) .slice( 0, -1 ) // remove 'default' option @@ -122,12 +274,12 @@ insertBlockButton.addEventListener( 'click', openBlockMenu, false ); insertBlockMenu.addEventListener( 'click', function( event ) { event.stopPropagation(); }, false ); -window.addEventListener( 'mouseup', onSelectText, false ); attachBlockHandlers(); attachControlActions(); attachTypeSwitcherActions(); attachBlockMenuSearch(); +attachKeyboardShortcuts(); /** * Core logic @@ -144,6 +296,14 @@ function getBlocks() { supportedBlockTags.map( query ) ); } +function getFocusedBlock() { + var focusedBlocks = getBlocks().filter( function( block ) { + return block.contains( window.getSelection().anchorNode ); + } ); + + return focusedBlocks.length ? focusedBlocks[ 0 ] : null; +} + function selectBlock( event ) { clearBlocks(); event.stopPropagation(); @@ -168,6 +328,7 @@ function showControls( node ) { switcherButtons.forEach( function( element ) { element.style.display = 'none'; } ); + var blockType = getTagType( node.nodeName ); var switcherQuery = '.type-icon-' + blockType; queryFirst( switcherQuery ).style.display = 'block'; @@ -178,52 +339,48 @@ function showControls( node ) { switcher.style.top = ( position.top + 18 + window.scrollY ) + 'px'; // show/hide block-specific block controls - blockControls.className = 'block-controls'; + dockedControls.className = 'docked-controls'; getTypeKinds( blockType ).forEach( function( kind ) { - blockControls.classList.add( 'is-' + kind ); + dockedControls.classList.add( 'is-' + kind ); } ); - blockControls.style.display = 'block'; + dockedControls.style.display = 'block'; // reposition block-specific block controls - blockControls.style.top = ( position.top - 36 + window.scrollY ) + 'px'; - blockControls.style.maxHeight = 'none'; + updateDockedControlsPosition(); } -function hideControls() { - switcher.style.opacity = 0; - switcherMenu.style.display = 'none'; - blockControls.style.display = 'none'; -} +function updateDockedControlsPosition( newClassName ) { + var isImage = selectedBlock.tagName === 'IMG'; + var className = selectedBlock.className; + var position = selectedBlock.getBoundingClientRect(); + var alignedRight = className.match( /align-right/ ); + var alignedLeft = className.match( /align-left/ ); + var fullBleed = className.match( /full-bleed/ ); + + var topPosition = position.top - 36 + window.scrollY; + var leftPosition = null; + + if ( isImage && alignedRight ) { + leftPosition = position.left; + topPosition = newClassName ? topPosition - 15 : topPosition; + } else if ( isImage && alignedLeft && newClassName ) { + topPosition = topPosition - 15; + } else if ( isImage && className === 'is-selected' && dockedControls.style.left ) { + leftPosition = null; + topPosition = topPosition + 15; + } else if ( fullBleed ) { + leftPosition = ( window.innerWidth / 2 ) - ( dockedControls.clientWidth / 2 ); + } -function hideInlineControls() { - inlineControls.style.display = 'none'; + dockedControls.style.maxHeight = 'none'; + dockedControls.style.top = topPosition + 'px'; + dockedControls.style.left = leftPosition ? leftPosition + 'px' : null; } -// Show popup on text selection -function onSelectText( event ) { - event.stopPropagation(); - var txt = ""; - - if ( window.getSelection ) { - txt = window.getSelection(); - } else if ( document.getSelection ) { - txt = document.getSelection(); - } else if ( document.selection ) { - txt = document.selection.createRange().text; - } - - // Show formatting bar - if ( txt != '' ) { - inlineControls.style.display = 'block'; - var range = txt.getRangeAt(0); - var pos = range.getBoundingClientRect(); - var selectCenter = pos.width / 2; - var controlsCenter = inlineControls.offsetWidth / 2; - inlineControls.style.left = ( pos.left + selectCenter - controlsCenter ) + 'px'; - inlineControls.style.top = ( pos.top - 48 + window.scrollY ) + 'px'; - } else { - inlineControls.style.display = 'none'; - } +function hideControls() { + switcher.style.opacity = 0; + switcherMenu.style.display = 'none'; + dockedControls.style.display = 'none'; } function attachControlActions() { @@ -241,9 +398,11 @@ function attachControlActions() { if ( getter ) { node.addEventListener( 'click', function( event ) { event.stopPropagation(); + var previousOffset = selectedBlock.offsetTop; swapNodes( selectedBlock, getter( selectedBlock ) ); attachBlockHandlers(); reselect(); + window.scrollTo( window.scrollX, window.scrollY + selectedBlock.offsetTop - previousOffset ); }, false ); } } ); @@ -276,12 +435,9 @@ function attachTypeSwitcherActions() { } ); Object.keys( typeToTag ).forEach( function( type ) { - var selector = '.switch-block__block .type-icon-' + type; - var button = queryFirst( selector ); - var label = queryFirst( selector + ' + label' ); - + var iconSelector = '.switch-block__block .type-icon-' + type; + var button = queryFirst( iconSelector ).parentNode; button.addEventListener( 'click', switchBlockType, false ); - label.addEventListener( 'click', switchBlockType, false ); function switchBlockType( event ) { if ( ! selectedBlock ) { @@ -300,7 +456,7 @@ function attachTypeSwitcherActions() { } ); } -function fillBlockMenu() { +function renderBlockMenu() { insertBlockMenuContent.innerHTML = ''; config.blockCategories.forEach( function ( category ) { var node = document.createElement( 'div' ); @@ -314,13 +470,13 @@ function fillBlockMenu() { node.appendChild( nodeBlocks ); var categoryBlocks = config.blocks .filter( function( block ) { - return block.categories.indexOf( category.id ) !== -1 + return block.category === category.id && block.label.toLowerCase().indexOf( searchBlockFilter.toLowerCase() ) !== -1; } ); categoryBlocks .forEach( function( block ) { var node = document.createElement( 'div' ); - node.className = 'insert-block__block'; + node.className = 'insert-block__block block-' + block.id + ( menuSelectedBlock === block ? ' is-active' : '' ); node.innerHTML = block.icon + ' ' + block.label; nodeBlocks.appendChild(node); } ); @@ -329,21 +485,128 @@ function fillBlockMenu() { insertBlockMenuContent.appendChild( node ); } } ); - - var placeholder = document.createElement('div'); - placeholder.className = 'insert-block__separator'; - placeholder.textContent = 'These don\'t work yet.'; - insertBlockMenuContent.appendChild( placeholder ); } function attachBlockMenuSearch() { insertBlockMenuSearchInput.addEventListener( 'keyup', filterBlockMenu, false ); insertBlockMenuSearchInput.addEventListener( 'input', filterBlockMenu, false ); - fillBlockMenu(); + insertBlockMenuContent.addEventListener( 'scroll', handleBlockMenuScroll, false ); + selectBlockInMenu(); + renderBlockMenu(); function filterBlockMenu( event ) { searchBlockFilter = event.target.value; - fillBlockMenu(); + selectBlockInMenu(); + renderBlockMenu(); + } + + function handleBlockMenuScroll( event ) { + if ( insertBlockMenuContent.scrollHeight - insertBlockMenuContent.scrollTop <= insertBlockMenuContent.clientHeight ) { + insertBlockMenuContent.className = 'insert-block__content is-bottom'; + } else { + insertBlockMenuContent.className = 'insert-block__content'; + } + } +} + +/** + * Select a block in the block menu + * @param direction direction from the current position (up/down/left/right) + */ +function selectBlockInMenu( direction ) { + var filteredBlocks = orderedBlocks.filter( function( block ) { + return block.label.toLowerCase().indexOf( searchBlockFilter.toLowerCase() ) !== -1; + } ); + var countBlocksByCategories = filteredBlocks.reduce( function( memo, block ) { + if ( ! memo[ block.category ] ) { + memo[ block.category ] = 0; + } + memo[ block.category ]++; + return memo; + }, {} ); + + var selectedBlockIndex = filteredBlocks.indexOf( menuSelectedBlock ); + selectedBlockIndex = selectedBlockIndex === -1 ? 0 : selectedBlockIndex; + var currentBlock = filteredBlocks[ selectedBlockIndex ]; + var previousBlock = filteredBlocks[ selectedBlockIndex - 1 ]; + var nextBlock = filteredBlocks[ selectedBlockIndex + 1 ]; + var offset = 0; + switch ( direction ) { + case KEY_ARROW_UP: + offset = ( + currentBlock + && filteredBlocks[ selectedBlockIndex - 2 ] + && ( + filteredBlocks[ selectedBlockIndex - 2 ].category === currentBlock.category + || countBlocksByCategories[ previousBlock.category ] % 2 === 0 + ) + ) ? -2 : -1; + break; + case KEY_ARROW_DOWN: + offset = ( + currentBlock + && filteredBlocks[ selectedBlockIndex + 2 ] + && ( + currentBlock.category === filteredBlocks[ selectedBlockIndex + 2 ].category + || filteredBlocks[ selectedBlockIndex + 2 ].category === nextBlock.category + || nextBlock.category === currentBlock.category + ) + ) ? 2 : 1; + break; + case KEY_ARROW_RIGHT: + offset = 1; + break; + case KEY_ARROW_LEFT: + offset = -1; + break; + } + + menuSelectedBlock = filteredBlocks[ selectedBlockIndex + offset ] || menuSelectedBlock; + + // Hack to wait for the rerender before scrolling + setTimeout( function() { + var blockElement = queryFirst( '.insert-block__block.block-' + menuSelectedBlock.id ); + if ( + blockElement && ( + blockElement.offsetTop + blockElement.offsetHeight > insertBlockMenuContent.clientHeight + insertBlockMenuContent.scrollTop + || blockElement.offsetTop < insertBlockMenuContent.scrollTop + ) + ) { + insertBlockMenuContent.scrollTop = blockElement.offsetTop - 23; + } + } ); +} + +function attachKeyboardShortcuts() { + document.addEventListener( 'keypress', handleKeyPress, false ); + document.addEventListener( 'keydown', handleKeyDown, false ); + + function handleKeyPress( event ) { + if ( '/' === String.fromCharCode( event.keyCode ) && ! blockMenuOpened ) { + var focusedBlock = getFocusedBlock(); + if ( document.activeElement !== editor || ( focusedBlock && ! focusedBlock.textContent ) ) { + event.preventDefault(); + openBlockMenu(); + } + } + } + + function handleKeyDown( event ) { + if ( ! blockMenuOpened ) return; + switch ( event.keyCode ) { + case KEY_ENTER: + event.preventDefault(); + hideMenu(); + break; + case KEY_ARROW_DOWN: + case KEY_ARROW_UP: + case KEY_ARROW_LEFT: + case KEY_ARROW_RIGHT: + event.preventDefault(); + selectBlockInMenu( event.keyCode ); + renderBlockMenu(); + break; + } } } @@ -392,15 +655,26 @@ function siblingGetter( direction ) { } function openBlockMenu( event ) { - hideInlineControls(); clearBlocks(); - event.stopPropagation(); + event && event.stopPropagation(); insertBlockMenu.style.display = 'block'; + blockMenuOpened = true; + searchBlockFilter = ''; + insertBlockMenuSearchInput.value = ''; + menuSelectedBlock = false; + previouslyFocusedBlock = getFocusedBlock(); insertBlockMenuSearchInput.focus(); + selectBlockInMenu(); + renderBlockMenu(); } function hideMenu() { + if ( ! blockMenuOpened ) return; insertBlockMenu.style.display = 'none'; + blockMenuOpened = false; + if ( previouslyFocusedBlock ) { + setCaret( previouslyFocusedBlock ); + } } function showSwitcherMenu( event ) { @@ -436,6 +710,16 @@ function setElementState( className, event ) { if ( className ) { selectedBlock.classList.add( className ); } + updateBlockControlsPosition( className ); +} + +function setCaret( element ) { + var range = document.createRange(); + range.setStart( element.childNodes[0] ,0 ); + range.collapse( true ); + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange( range ); } function l( data ) { diff --git a/dom-parser/blocks.js b/dom-parser/blocks.js new file mode 100644 index 0000000000000..007ad88f04613 --- /dev/null +++ b/dom-parser/blocks.js @@ -0,0 +1,94 @@ +var RE_BLOCK_OPEN, RE_BLOCK_CLOSE, textarea, editor; + +RE_BLOCK_OPEN = /^\s*wp:(\S+)/; +RE_BLOCK_CLOSE = /^\s*\/wp\s*/; + +function findNodeBlocks( rootNode ) { + var stack = [ rootNode ], + comments = [], + blocks = [], + parent, i, node, match, block, child; + + while ( stack.length ) { + parent = stack.pop(); + + for ( i = 0; i < parent.childNodes.length; i++ ) { + node = parent.childNodes[ i ]; + + if ( Node.COMMENT_NODE !== node.nodeType ) { + stack.push( node ); + } else if ( RE_BLOCK_OPEN.test( node.nodeValue ) ) { + comments.push( node ); + } + } + } + + for ( i = comments.length; --i >= 0; ) { + node = comments[ i ]; + match = node.nodeValue.match( RE_BLOCK_OPEN ); + block = { + type: match[ 1 ], + startNode: node, + children: [] + }; + + child = node; + while ( ( child = child.nextSibling ) ) { + if ( Node.COMMENT_NODE !== child.nodeType ) { + block.children.push( child ); + } else if ( RE_BLOCK_CLOSE.test( child.nodeValue ) ) { + block.endNode = child; + break; + } + } + + blocks.unshift( block ); + } + + return blocks; +} + +function renderBlocks( rootNode ) { + var blocks = findNodeBlocks( rootNode ), + i, block, wrapper, hasInlineChild, child; + + for ( i = 0; i < blocks.length; i++ ) { + block = blocks[ i ]; + + if ( ! block.endNode ) { + continue; + } + + wrapper = document.createElement( 'div' ); + wrapper.className = 'block'; + wrapper.setAttribute( 'data-type', block.type ); + + hasInlineChild = block.children.some( function( node ) { + return ( + Node.ELEMENT_NODE === node.nodeType && + 'inline' === window.getComputedStyle( node ).display + ); + } ); + + if ( hasInlineChild ) { + wrapper.style.display = 'inline-block'; + } + + block.endNode.parentNode.insertBefore( wrapper, block.endNode ); + + while ( ( child = block.children.pop() ) ) { + wrapper.insertBefore( child, wrapper.lastChild ); + } + } +} + +textarea = document.getElementById( 'textarea' ); +editor = document.getElementById( 'editor' ); + +function renderEditor() { + editor.innerHTML = textarea.value; + renderBlocks( editor ); +} + +textarea.addEventListener( 'input', renderEditor ); +renderEditor(); diff --git a/dom-parser/index.html b/dom-parser/index.html new file mode 100644 index 0000000000000..7e86e8f3e4e29 --- /dev/null +++ b/dom-parser/index.html @@ -0,0 +1,29 @@ + +Editor Comment DOM Parser + + +
+
+ +
+
+
+ + diff --git a/dom-parser/style.css b/dom-parser/style.css new file mode 100644 index 0000000000000..e704276596f22 --- /dev/null +++ b/dom-parser/style.css @@ -0,0 +1,130 @@ +/** + * Basic + */ + +html, +body { + margin: 0; + padding: 0; + height: 100%; +} + +* { + box-sizing: border-box; +} + +body { + font: 13px / 1.8 "Merriweather", serif; + width: 90%; + max-width: 1280px; + margin: 2rem auto; + color: #12181e; +} + +img { + max-width: 100%; + height: auto; +} + +h2 { + font-weight: 900; + font-size: 28px; +} + +p { + margin: 28px 0; + font-size: 16px; +} + +blockquote { + font-size: 20px; + border-left: 4px solid #12181e; + margin: 8px 12px; + padding-left: 12px; + font-style: italic; +} + +blockquote p { + margin: 0; +} + +blockquote p + p { + margin-top: 28px; +} + +.displays { + position: relative; + display: flex; + min-height: 100%; +} + +.displays::after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + margin-left: -2px; + width: 4px; + background-color: #f0f2f4; +} + +.displays > #html, +.displays > #editor { + flex-basis: 50%; + margin: 0 3rem; + padding: 2rem 0; +} + +.displays > #html { + margin-left: 0; +} + +.displays > #editor { + margin-right: 0; +} + +#textarea { + display: block; + width: 100%; + height: 100%; + resize: none; + border: none; + border: 2px solid transparent; + outline: none; + padding: .8rem 1.2rem; + transition: border-color .2s; + font-family: Courier\ 10 Pitch, Courier, monospace; + font-size: 14px; + line-height: 1.3; +} + +#textarea:hover { + border-color: #d6d9dd; +} + +.block { + position: relative; + margin: 28px 0; + padding: 4px 8px; + border: 2px dashed #e0e5e9; +} + +.block::before { + content: attr( data-type ); + position: absolute; + bottom: 100%; + left: -2px; + margin-bottom: 2px; + padding: 2px 6px; + background-color: #e0e5e9; + text-transform: uppercase; + font-family: monospace; + font-style: normal; + font-size: 11px; +} + +.block > p, +.block > h2 { + margin: 0; +} diff --git a/index.html b/index.html index 59c07a4891173..ea509359dec09 100644 --- a/index.html +++ b/index.html @@ -18,36 +18,38 @@ Quote -
- - - - - - - -
-
- - - - - - +
+
+ + + + + + + +
+
+ + + + + + +
@@ -85,5 +87,6 @@

1.0 Is The Loneliest Number

+ diff --git a/mockups/Formatting, Click.png b/mockups/Formatting, Click.png new file mode 100644 index 0000000000000..e568d84bb287c Binary files /dev/null and b/mockups/Formatting, Click.png differ diff --git a/mockups/Formatting, Hover.png b/mockups/Formatting, Hover.png new file mode 100644 index 0000000000000..32954d15d2d3e Binary files /dev/null and b/mockups/Formatting, Hover.png differ diff --git a/mockups/Headings.png b/mockups/Headings.png new file mode 100644 index 0000000000000..01d30226d3fd6 Binary files /dev/null and b/mockups/Headings.png differ diff --git a/mockups/Image.png b/mockups/Image.png new file mode 100644 index 0000000000000..cf07ffd9563d3 Binary files /dev/null and b/mockups/Image.png differ diff --git a/mockups/Insert Between, Keyboard.png b/mockups/Insert Between, Keyboard.png new file mode 100644 index 0000000000000..199d655397d62 Binary files /dev/null and b/mockups/Insert Between, Keyboard.png differ diff --git a/mockups/Insert Between.png b/mockups/Insert Between.png new file mode 100644 index 0000000000000..3f1cdc125f0e1 Binary files /dev/null and b/mockups/Insert Between.png differ diff --git a/mockups/Insert.png b/mockups/Insert.png new file mode 100644 index 0000000000000..82b713ab0c8dc Binary files /dev/null and b/mockups/Insert.png differ diff --git a/mockups/Mobile.png b/mockups/Mobile.png new file mode 100644 index 0000000000000..952b415523db5 Binary files /dev/null and b/mockups/Mobile.png differ diff --git a/mockups/New Blocks.png b/mockups/New Blocks.png new file mode 100644 index 0000000000000..e6c7b2ce17500 Binary files /dev/null and b/mockups/New Blocks.png differ diff --git a/mockups/Quote 2.png b/mockups/Quote 2.png new file mode 100644 index 0000000000000..bb74cd2045f79 Binary files /dev/null and b/mockups/Quote 2.png differ diff --git a/mockups/Quote.png b/mockups/Quote.png new file mode 100644 index 0000000000000..4eee1d027a029 Binary files /dev/null and b/mockups/Quote.png differ diff --git a/mockups/Type Switcher.png b/mockups/Type Switcher.png new file mode 100644 index 0000000000000..12aa4aa075d9c Binary files /dev/null and b/mockups/Type Switcher.png differ diff --git a/navigation.js b/navigation.js new file mode 100644 index 0000000000000..328d04b1d5b54 --- /dev/null +++ b/navigation.js @@ -0,0 +1,73 @@ +( function( window, document ) { + var PROTOTYPES, paths, p, pl, path, navigation, path, label, link, style; + + /** + * Set of all prototypes, keyed by path with label value. + * + * @type {Object} + */ + PROTOTYPES = { + '/': 'UI Prototype', + '/tinymce-per-block/': 'TinyMCE per block prototype', + '/dom-parser/': 'DOM Parsing Prototype' + }; + + // Generate Navigation DOM + + navigation = document.createElement( 'div' ); + navigation.className = 'prototype-navigation'; + + paths = Object.keys( PROTOTYPES ); + + for ( p = 0, pl = paths.length; p < pl; p++ ) { + path = paths[ p ]; + label = PROTOTYPES[ path ]; + + link = document.createElement( 'a' ); + link.href = '/gutenberg' + path; + link.setAttribute( 'title', label ); + link.textContent = ( p + 1 ); + + if ( '/gutenberg' + path === window.location.pathname ) { + link.className = 'is-current'; + } + + navigation.appendChild( link ); + } + + // Generate Stylesheet DOM + + style = document.createElement( 'style' ); + style.innerHTML = [ + '.prototype-navigation {', + 'font: 13px/1.8 -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;', + 'display: flex;', + 'position: absolute;', + 'top: 24px;', + 'left: 24px;', + '}', + '.prototype-navigation a {', + 'display: inline-block;', + 'width: 28px;', + 'height: 28px;', + 'font-size: 12px;', + 'border: 1px solid #b4b9be;', + 'line-height: 28px;', + 'border-radius: 50%;', + 'text-decoration: none;', + 'text-align: center;', + 'margin-right: 8px;', + '}', + '.prototype-navigation a.is-current {', + 'background: #008ec2;', + 'border-color: #008ec2;', + 'color: #fff;', + '}' + ].join( '\n' ); + + // Append to body + + document.body.appendChild( navigation ); + document.body.appendChild( style ); + +} )( this, this.document ); diff --git a/package.json b/package.json index 157ef3e5da322..0835096466e79 100644 --- a/package.json +++ b/package.json @@ -9,19 +9,19 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Automattic/gutenberg.git" + "url": "git+https://github.com/WordPress/gutenberg.git" }, "keywords": [ "WordPress", "editor", "prototype" ], - "author": "Automattic, Inc.", + "author": "The WordPress Contributors", "license": "GPL-2.0+", "bugs": { - "url": "https://github.com/Automattic/gutenberg/issues" + "url": "https://github.com/WordPress/gutenberg/issues" }, - "homepage": "https://github.com/Automattic/gutenberg#readme", + "homepage": "https://github.com/WordPress/gutenberg#readme", "devDependencies": { "http-server": "0.9.0" } diff --git a/style.css b/style.css index 772d289b0436f..268a0671aa3ef 100644 --- a/style.css +++ b/style.css @@ -105,7 +105,7 @@ h6.is-selected, p.is-selected, blockquote.is-selected, img.is-selected { - box-shadow: inset 0px 0px 0px 2px #6d7882; + box-shadow: inset 0px 0px 0px 2px #e0e5e9; position: relative; z-index: 1; } @@ -163,12 +163,23 @@ img.is-selected { display: none; } - /** - * Inline controls + * Controls */ +.docked-controls { + position: absolute; + display: none; + z-index: 10; + transform: translateZ( 0 ); +} -.inline-controls { +.docked-controls.is-image .block-image, +.docked-controls.is-text .block-text { + display: block; +} + +.inline-controls, +.block-controls { background: #fff; border: 1px solid #e1e6ea; box-shadow: 0px 3px 20px rgba( 18, 24, 30, .1 ), 0px 1px 3px rgba( 18, 24, 30, .1 ); @@ -176,12 +187,15 @@ img.is-selected { display: inline-block; height: 38px; overflow: hidden; - position: absolute; - z-index: 10; + margin-left: 20px; +} + +.docked-controls.is-image .inline-controls { display: none; } -.inline-controls button { +.inline-controls button, +.block-controls button { background: #fff; border: none; width: 36px; @@ -192,29 +206,38 @@ img.is-selected { float: left; } -.inline-controls button.do-not-work { +.inline-controls button.do-not-work, +.block-controls button.do-not-work { margin: 0 8px; width: auto; } -.inline-controls button:hover { +.inline-controls button:hover, +.block-controls button:hover { background: #f0f2f4; } -.inline-controls button:focus { +.inline-controls button:focus, +.block-controls button:focus { outline: none; } -.control-group { +.control-group, { display: inline-block; margin-left: 20px; } -.inline-controls button.heading-dropdown { +.inline-controls button.heading-dropdown, +.block-controls button.heading-dropdown { width: 54px; position: relative; } +.inline-controls button.is-active, +.block-controls button.is-active { + background: #e0e5e9; +} + .heading-dropdown .heading { position: absolute; left: 0; @@ -239,47 +262,10 @@ img.is-selected { bottom: 8px; } - -/** - * Block Controls - */ - -.block-controls { - background: #191e23; - display: inline-block; - max-height: 36px; - overflow: hidden; - position: absolute; - z-index: 10; - display: none; - transform: translateZ( 0 ); - } - -.block-controls button { - background: #191e23; - color: #fff; - border: none; - width: 36px; - height: 36px; - padding: 6px; - cursor: pointer; - display: block; - float: left; - } - -.block-controls button.is-active { - background: #6d7882; -} - .block-controls button { display: none; } -.block-controls.is-image .block-image, -.block-controls.is-text .block-text { - display: block; -} - /** * Block inserter and switcher */ @@ -426,6 +412,15 @@ img.is-selected { .insert-block__content { max-height: 180px; overflow: auto; + box-shadow: inset 0px -4px 6px -2px rgba(224,229,233,1); +} + +.insert-block__content.is-bottom { + box-shadow: none; +} + +.insert-block__content:focus { + outline: none; } .insert_block__category-blocks { @@ -442,6 +437,7 @@ img.is-selected { align-items: center; cursor: pointer; } +.insert-block__block.is-active, .insert-block__block:hover, .switch-block__block:hover { background: #f0f2f4; @@ -456,6 +452,11 @@ img.is-selected { fill: #191e23; } +.insert-block__block svg { + widows: 24px; + height: 24px; +} + /* * Text actions */ diff --git a/tinymce-per-block/.babelrc b/tinymce-per-block/.babelrc new file mode 100644 index 0000000000000..2293ad41d1a26 --- /dev/null +++ b/tinymce-per-block/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ "es2015", { + "modules": false + } ], + "stage-2" + ], + "plugins": [ + [ "transform-react-jsx", { + "pragma": "createElement" + } ], + "lodash" + ] +} diff --git a/tinymce-per-block/.editorconfig b/tinymce-per-block/.editorconfig new file mode 100644 index 0000000000000..667a507d56e97 --- /dev/null +++ b/tinymce-per-block/.editorconfig @@ -0,0 +1,16 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[package.json] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/tinymce-per-block/.eslintignore b/tinymce-per-block/.eslintignore new file mode 100644 index 0000000000000..0b6bacfd9731b --- /dev/null +++ b/tinymce-per-block/.eslintignore @@ -0,0 +1 @@ +src/parsers/block/grammar.js diff --git a/tinymce-per-block/.eslintrc.json b/tinymce-per-block/.eslintrc.json new file mode 100644 index 0000000000000..4a800f0d5d04e --- /dev/null +++ b/tinymce-per-block/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "root": true, + "extends": "wpcalypso/react", + "parser": "babel-eslint", + "env": { + "browser": true, + "node": true + }, + "settings": { + "react": { + "pragma": "createElement" + } + }, + "rules": { + "camelcase": 0, + "max-len": [ 2, { "code": 120 } ], + "react/jsx-no-bind": 0 + } +} diff --git a/tinymce-per-block/README.md b/tinymce-per-block/README.md new file mode 100644 index 0000000000000..5e394708c698d --- /dev/null +++ b/tinymce-per-block/README.md @@ -0,0 +1,57 @@ +"TinyMCE Per Block" Prototype +============================= + +This is a WordPress editor technical prototype to explore the feasability of decorating blocks as editable, initializing TinyMCE on only those blocks for which it is required. + +## Demo + +https://wordpress.github.io/gutenberg/tinymce-per-block/ + +## Background + +This prototype implements ideas explored in the Make WordPress Core's [Editor Technical Overview](https://make.wordpress.org/core/2017/01/17/editor-technical-overview/) blog post. Instead of expecting TinyMCE to manage the entire markup of a post, this prototype instead uses a [formal post grammar](https://github.com/Automattic/wp-post-grammar) to parse a post's content in the browser client. The JavaScript data structure of the post content is then used to render a set of controls which form the visual representation of the editor. The look and feel of these controls can be extended through an included block registration API, with backwards compatibility for posts preserved by either a generic block type or automated migration (a solution is yet to be decided). + +Examples: + +- [Text Block](./src/blocks/text-block) +- [Image Block](./src/blocks/image-block) + +## Status + +This prototype currently implements: + +- Content parsing +- Block registration +- Editor block list rendering +- Binding TinyMCE to blocks ([see `wp-blocks/bind-editable`](./src/external/wp-blocks/bind-editable)) +- Block-level control changes (e.g. text centering) +- Serializing block content + +The prototype lacks: + +- Block reordering +- Inserting new blocks (including creating or splitting paragraphs) +- Selecting across paragraphs of text +- Backwards compatibility for non-block content + +## Development + +You must first [download and install Node.js](https://nodejs.org/en/download/) before you can build or develop this prototype. Next, in your terminal, navigate to the project directory and install dependencies: + +``` +npm install +``` + +**To develop with automatic recompilation:** + +``` +npm run dev +``` + +You can now visit [http://localhost:8081](http://localhost:8081) in your browser. + +**To compile changes for commit:** + +``` +npm run build +``` diff --git a/tinymce-per-block/build/app.js b/tinymce-per-block/build/app.js new file mode 100644 index 0000000000000..890088541f7af --- /dev/null +++ b/tinymce-per-block/build/app.js @@ -0,0 +1,19 @@ +!function(t){function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var e={};return n.m=t,n.c=e,n.i=function(t){return t},n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=201)}([function(t,n,e){"use strict";function r(t,n){var r=n&&n._wpElementsRendered;r&&r.parentNode!==n&&(r=null),r||(r=n.children[0]);var i=!0,u=!1,c=void 0;try{for(var a,f=n.childNodes[Symbol.iterator]();!(i=(a=f.next()).done);i=!0){var s=a.value;s!==r&&n.removeChild(s)}}catch(t){u=!0,c=t}finally{try{!i&&f.return&&f.return()}finally{if(u)throw c}}var l=e.i(o.render)(t,n,r);n&&(n._wpElementsRendered=l)}var o=e(54);e.n(o);e.o(o,"h")&&e.d(n,"b",function(){return o.h}),e.o(o,"Component")&&e.d(n,"c",function(){return o.Component}),n.a=r},function(t,n){var e=Array.isArray;t.exports=e},function(t,n,e){var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o=e(43),i="object"==("undefined"==typeof self?"undefined":r(self))&&self&&self.Object===Object&&self,u=o||i||Function("return this")();t.exports=u},function(t,n,e){function r(t,n){var e=i(t,n);return o(e)?e:void 0}var o=e(90),i=e(118);t.exports=r},function(t,n,e){function r(t){return null!=t&&i(t.length)&&!o(t)}var o=e(51),i=e(26);t.exports=r},function(t,n,e){"use strict";function r(t){return t=e.i(o.b)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 20 20",className:"dashicon"},t),function(){return t}}var o=e(0);n.a=r},function(t,n,e){function r(t){return null==t?void 0===t?a:c:f&&f in Object(t)?i(t):u(t)}var o=e(11),i=e(116),u=e(144),c="[object Null]",a="[object Undefined]",f=o?o.toStringTag:void 0;t.exports=r},function(t,n){function e(t){var n="undefined"==typeof t?"undefined":r(t);return null!=t&&("object"==n||"function"==n)}var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};t.exports=e},function(t,n){function e(t){return null!=t&&"object"==("undefined"==typeof t?"undefined":r(t))}var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};t.exports=e},function(t,n){function e(t,n){return t===n||t!==t&&n!==n}t.exports=e},function(t,n,e){function r(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n-1&&t%1==0&&t-1&&t%1==0&&t<=r}var r=9007199254740991;t.exports=e},function(t,n,e){"use strict";var r=e(186);e.d(n,"e",function(){return r.a});var o=e(185);e.d(n,"f",function(){return o.a});var i=e(187);e.d(n,"g",function(){return i.a});var u=e(183);e.d(n,"b",function(){return u.a});var c=e(184);e.d(n,"a",function(){return c.a});var a=e(188);e.d(n,"d",function(){return a.a});var f=e(189);e.d(n,"c",function(){return f.a})},function(t,n,e){"use strict";function r(t,n){return n=u()(n,{title:t}),a[t]=n,n}function o(t){return a[t]}var i=e(163),u=e.n(i),c=e(190);e.d(n,"c",function(){return c.a}),n.b=r,n.a=o;var a={}},function(t,n,e){"use strict";/*! + * is-equal-shallow + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ +var r=e(67);t.exports=function(t,n){if(!t&&!n)return!0;if(!t&&n||t&&!n)return!1;var e,o=0,i=0;for(e in n)if(i++,!r(n[e])||!t.hasOwnProperty(e)||t[e]!==n[e])return!1;for(e in t)o++;return o===i}},function(t,n,e){function r(t){var n=this.__data__=new o(t);this.size=n.size}var o=e(10),i=e(152),u=e(153),c=e(154),a=e(155),f=e(156);r.prototype.clear=i,r.prototype.delete=u,r.prototype.get=c,r.prototype.has=a,r.prototype.set=f,t.exports=r},function(t,n){function e(t,n,e){switch(e.length){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)}t.exports=e},function(t,n,e){function r(t,n){var e=u(t),r=!e&&i(t),s=!e&&!r&&c(t),p=!e&&!r&&!s&&f(t),d=e||r||s||p,v=d?o(t.length,String):[],h=v.length;for(var b in t)!n&&!l.call(t,b)||d&&("length"==b||s&&("offset"==b||"parent"==b)||p&&("buffer"==b||"byteLength"==b||"byteOffset"==b)||a(b,h))||v.push(b);return v}var o=e(100),i=e(49),u=e(1),c=e(50),a=e(24),f=e(52),s=Object.prototype,l=s.hasOwnProperty;t.exports=r},function(t,n){function e(t,n){for(var e=-1,r=null==t?0:t.length,o=Array(r);++ep))return!1;var v=s.get(t);if(v&&s.get(n))return v==n;var h=-1,b=!0,y=e&a?new o:void 0;for(s.set(t,n),s.set(n,t);++h2;)I.push(arguments[c]);for(e&&e.children&&(I.length||I.push(e.children),delete e.children);I.length;)if((i=I.pop())instanceof Array)for(c=i.length;c--;)I.push(i[c]);else null!=i&&i!==!0&&i!==!1&&("number"==typeof i&&(i=String(i)),u="string"==typeof i,u&&o?r[r.length-1]+=i:((r||(r=[])).push(i),o=u));var a=new n(t,e||void 0,r||D);return F.vnode&&F.vnode(a),a}function r(t,n){if(n)for(var e in n)t[e]=n[e];return t}function o(t){return r({},t)}function i(t,n){for(var e=n.split("."),r=0;r2?[].slice.call(arguments,2):t.children)}function l(t,n,e){var r=n.split(".");return function(n){for(var o=n&&n.target||this,u={},c=u,f=a(e)?i(n,e):o.nodeName?o.type.match(/^che|rad/)?o.checked:o.value:n,s=0;s=v?t.appendChild(a):a!==f[m]&&(a===f[m+1]&&g(f[m]),t.insertBefore(a,f[m]||null)))}if(p)for(var m in l)l[m]&&N(l[m]);for(;d<=h;)a=s[h--],a&&N(a)}function N(t,n){var e=t._component;if(e)R(e,!n);else{t[Z]&&t[Z].ref&&t[Z].ref(null),n||j(t);for(var r;r=t.lastChild;)N(r,n)}}function z(t,n,e){var r;for(r in e)n&&r in n||null==e[r]||x(t,r,e[r],e[r]=void 0,tt);if(n)for(r in n)"children"===r||"innerHTML"===r||r in e&&n[r]===("value"===r||"checked"===r?t[r]:e[r])||x(t,r,e[r],e[r]=n[r],tt)}function M(t){var n=t.constructor.name,e=et[n];e?e.push(t):et[n]=[t]}function P(t,n,e){var r=new t(n,e),o=et[t.name];if(L.call(r,n,e),o)for(var i=o.length;i--;)if(o[i].constructor===t){r.nextBase=o[i].nextBase,o.splice(i,1);break}return r}function T(t,n,e,r,o){t._disable||(t._disable=!0,(t.__ref=n.ref)&&delete n.ref,(t.__key=n.key)&&delete n.key,!t.base||o?t.componentWillMount&&t.componentWillMount():t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),r&&r!==t.context&&(t.prevContext||(t.prevContext=t.context),t.context=r),t.prevProps||(t.prevProps=t.props),t.props=n,t._disable=!1,0!==e&&(1!==e&&F.syncComponentUpdates===!1&&t.base?p(t):E(t,1,o)),t.__ref&&t.__ref(t))}function E(t,n,e,i){if(!t._disable){var u,a,f,s,l=t.props,p=t.state,d=t.context,b=t.prevProps||l,y=t.prevState||p,g=t.prevContext||d,x=t.base,_=t.nextBase,w=x||_,j=t._component;if(x&&(t.props=b,t.state=y,t.context=g,2!==n&&t.shouldComponentUpdate&&t.shouldComponentUpdate(l,p,d)===!1?u=!0:t.componentWillUpdate&&t.componentWillUpdate(l,p,d),t.props=l,t.state=p,t.context=d),t.prevProps=t.prevState=t.prevContext=t.nextBase=null,t._dirty=!1,!u){for(t.render&&(a=t.render(l,p,d)),t.getChildContext&&(d=r(o(d),t.getChildContext()));v(a);)a=h(a,d);var k,C,A=a&&a.nodeName;if(c(A)){var z=m(a);f=j,f&&f.constructor===A&&z.key==f.__key?T(f,z,1,d):(k=f,f=P(A,z,d),f.nextBase=f.nextBase||_,f._parentComponent=t,t._component=f,T(f,z,0,d),E(f,1,e,!0)),C=f.base}else s=w,k=j,k&&(s=t._component=null),(w||1===n)&&(s&&(s._component=null),C=O(s,a,d,e||!x,w&&w.parentNode,!0));if(w&&C!==w&&f!==j){var M=w.parentNode;M&&C!==M&&(M.replaceChild(C,w),k||(w._component=null,N(w)))}if(k&&R(k,C!==w),t.base=C,C&&!i){for(var U=t,L=t;L=L._parentComponent;)(U=L).base=C;C._component=U,C._componentConstructor=U.constructor}}!x||e?X.unshift(t):u||(t.componentDidUpdate&&t.componentDidUpdate(b,y,g),F.afterUpdate&&F.afterUpdate(t));var B,I=t._renderCallbacks;if(I)for(;B=I.pop();)B.call(t);Y||i||S()}}function U(t,n,e,r){for(var o=t&&t._component,i=o,u=t,c=o&&t._componentConstructor===n.nodeName,a=c,f=m(n);o&&!a&&(o=o._parentComponent);)a=o.constructor===n.nodeName;return o&&a&&(!r||o._component)?(T(o,f,3,e,r),t=o.base):(i&&!c&&(R(i,!0),t=u=null),o=P(n.nodeName,f,e),t&&!o.nextBase&&(o.nextBase=t,u=null),T(o,f,1,e,r),t=o.base,u&&t!==u&&(u._component=null,N(u))),t}function R(t,n){F.beforeUnmount&&F.beforeUnmount(t);var e=t.base;t._disable=!0,t.componentWillUnmount&&t.componentWillUnmount(),t.base=null;var r=t._component;if(r)R(r,n);else if(e){e[Z]&&e[Z].ref&&e[Z].ref(null),t.nextBase=e,n&&(g(e),M(t));for(var o;o=e.lastChild;)N(o,!n)}t.__ref&&t.__ref(null),t.componentDidUnmount&&t.componentDidUnmount()}function L(t,n){this._dirty=!0,this.context=n,this.props=t,this.state||(this.state={})}function B(t,n,e){return O(e,t,{},!1,n)}var F={},I=[],D=[],W={},$=function(t){return W[t]||(W[t]=t.toLowerCase())},H="undefined"!=typeof Promise&&Promise.resolve(),V=H?function(t){H.then(t)}:setTimeout,G={},Z="undefined"!=typeof Symbol?Symbol.for("preactattr"):"__preactattr_",q={boxFlex:1,boxFlexGroup:1,columnCount:1,fillOpacity:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,fontWeight:1,lineClamp:1,lineHeight:1,opacity:1,order:1,orphans:1,strokeOpacity:1,widows:1,zIndex:1,zoom:1},J={blur:1,error:1,focus:1,load:1,resize:1,scroll:1},K=[],Q={},X=[],Y=0,tt=!1,nt=!1,et={};r(L.prototype,{linkState:function(t,n){var e=this._linkedStates||(this._linkedStates={});return e[t+n]||(e[t+n]=l(this,t,n))},setState:function(t,n){var e=this.state;this.prevState||(this.prevState=o(e)),r(e,c(t)?t(e,this.props):t),n&&(this._renderCallbacks=this._renderCallbacks||[]).push(n),p(this)},forceUpdate:function(){E(this,2)},render:function(){}}),t.h=e,t.cloneElement=s,t.Component=L,t.render=B,t.rerender=d,t.options=F})},function(t,n){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=e(191);e.n(r);e.o(r,"parse")&&e.d(n,"parse",function(){return r.parse})},function(t,n){(function(n){t.exports=n}).call(n,{})},function(t,n,e){function r(t,n){var e=c(t)?o:i;return e(t,u(n))}var o=e(75),i=e(23),u=e(104),c=e(1);t.exports=r},function(t,n,e){"use strict";var r=e(28),o=e(27),i=e(181);e.i(r.b)("image",{title:"Image",icon:o.c,form:i.a})},function(t,n,e){"use strict";var r=e(28),o=e(27),i=e(182);e.i(r.b)("text",{title:"Text",form:e.i(r.c)(i.a),icon:o.d,controls:[{label:"Align Left",icon:o.e,isSelected:function(t){var n=t.attrs;return!n.align||"left"===n.align},onClick:function(t){t.setAttributes({align:"left"})}},{label:"Align Center",icon:o.f,isSelected:function(t){var n=t.attrs;return"center"===n.align},onClick:function(t){t.setAttributes({align:"center"})}},{label:"Align Right",icon:o.g,isSelected:function(t){var n=t.attrs;return"right"===n.align},onClick:function(t){t.setAttributes({align:"right"})}}]})},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=e(56);e.d(n,"block",function(){return r})},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=e(194);e.d(n,"block",function(){return r.a});var o=e(196);e.d(n,"html",function(){return o.a})},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=e(197);e.d(n,"block",function(){return r})},function(t,n,e){var r=e(198);"string"==typeof r&&(r=[[t.i,r,""]]);e(199)(r,{});r.locals&&(t.exports=r.locals)},function(t,n,e){var r,o,i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +!function(){"use strict";function u(){for(var t=[],n=0;n + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ +var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};t.exports=function(t){return null==t||"function"!=typeof t&&"object"!==("undefined"==typeof t?"undefined":r(t))}},function(t,n,e){var r=e(3),o=e(2),i=r(o,"DataView");t.exports=i},function(t,n,e){function r(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n1?e[o-1]:void 0,c=o>2?e[2]:void 0;for(u=t.length>3&&"function"==typeof u?(o--,u):void 0,c&&i(e[0],e[1],c)&&(u=o<3?void 0:u,o=1),n=Object(n);++r-1?c[a?n[f]:f]:void 0}}var o=e(13),i=e(4),u=e(19);t.exports=r},function(t,n,e){function r(t,n,e,r){return void 0===t||o(t,i[e])&&!u.call(r,e)?n:t}var o=e(9),i=Object.prototype,u=i.hasOwnProperty;t.exports=r},function(t,n,e){function r(t,n,e,r,o,j,S){switch(e){case w:if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)return!1;t=t.buffer,n=n.buffer;case _:return!(t.byteLength!=n.byteLength||!j(new i(t),new i(n)));case p:case d:case b:return u(+t,+n);case v:return t.name==n.name&&t.message==n.message;case y:case g:return t==n+"";case h:var O=a;case m:var C=r&s;if(O||(O=f),t.size!=n.size&&!C)return!1;var A=S.get(t);if(A)return A==n;r|=l,S.set(t,n);var N=c(O(t),O(n),r,o,j,S);return S.delete(t),N;case x:if(k)return k.call(t)==k.call(n)}return!1}var o=e(11),i=e(73),u=e(9),c=e(42),a=e(139),f=e(149),s=1,l=2,p="[object Boolean]",d="[object Date]",v="[object Error]",h="[object Map]",b="[object Number]",y="[object RegExp]",m="[object Set]",g="[object String]",x="[object Symbol]",_="[object ArrayBuffer]",w="[object DataView]",j=o?o.prototype:void 0,k=j?j.valueOf:void 0;t.exports=r},function(t,n,e){function r(t,n,e,r,u,a){var f=e&i,s=o(t),l=s.length,p=o(n),d=p.length;if(l!=d&&!f)return!1;for(var v=l;v--;){var h=s[v];if(!(f?h in n:c.call(n,h)))return!1}var b=a.get(t);if(b&&a.get(n))return b==n;var y=!0;a.set(t,n),a.set(n,t);for(var m=f;++v-1}var o=e(12);t.exports=r},function(t,n,e){function r(t,n){var e=this.__data__,r=o(e,t);return r<0?(++this.size,e.push([t,n])):e[r][1]=n,this}var o=e(12);t.exports=r},function(t,n,e){function r(){this.size=0,this.__data__={hash:new o,map:new(u||i),string:new o}}var o=e(69),i=e(10),u=e(21);t.exports=r},function(t,n,e){function r(t){var n=o(this,t).delete(t);return this.size-=n?1:0,n}var o=e(14);t.exports=r},function(t,n,e){function r(t){return o(this,t).get(t)}var o=e(14);t.exports=r},function(t,n,e){function r(t){return o(this,t).has(t)}var o=e(14);t.exports=r},function(t,n,e){function r(t,n){var e=o(this,t),r=e.size;return e.set(t,n),this.size+=e.size==r?0:1,this}var o=e(14);t.exports=r},function(t,n){function e(t){var n=-1,e=Array(t.size);return t.forEach(function(t,r){e[++n]=[r,t]}),e}t.exports=e},function(t,n,e){function r(t){var n=o(t,function(t){return e.size===i&&e.clear(),t}),e=n.cache;return n}var o=e(170),i=500;t.exports=r},function(t,n,e){var r=e(145),o=r(Object.keys,Object);t.exports=o},function(t,n){function e(t){var n=[];if(null!=t)for(var e in Object(t))n.push(e);return n}t.exports=e},function(t,n,e){(function(t){var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o=e(43),i="object"==r(n)&&n&&!n.nodeType&&n,u=i&&"object"==r(t)&&t&&!t.nodeType&&t,c=u&&u.exports===i,a=c&&o.process,f=function(){try{return a&&a.binding&&a.binding("util")}catch(t){}}();t.exports=f}).call(n,e(55)(t))},function(t,n){function e(t){return o.call(t)}var r=Object.prototype,o=r.toString;t.exports=e},function(t,n){function e(t,n){return function(e){return t(n(e))}}t.exports=e},function(t,n,e){function r(t,n,e){return n=i(void 0===n?t.length-1:n,0),function(){for(var r=arguments,u=-1,c=i(r.length-n,0),a=Array(c);++u0){if(++n>=r)return arguments[0]}else n=0;return t.apply(void 0,arguments)}}var r=800,o=16,i=Date.now;t.exports=e},function(t,n,e){function r(){this.__data__=new o,this.size=0}var o=e(10);t.exports=r},function(t,n){function e(t){var n=this.__data__,e=n.delete(t);return this.size=n.size,e}t.exports=e},function(t,n){function e(t){return this.__data__.get(t)}t.exports=e},function(t,n){function e(t){return this.__data__.has(t)}t.exports=e},function(t,n,e){function r(t,n){var e=this.__data__;if(e instanceof o){var r=e.__data__;if(!i||r.length",""":'"',"'":"'"},i=r(o);t.exports=i},function(t,n){function e(t){for(var n=w.lastIndex=0;w.test(t);)++n;return n}var r="\\ud800-\\udfff",o="\\u0300-\\u036f",i="\\ufe20-\\ufe2f",u="\\u20d0-\\u20ff",c=o+i+u,a="\\ufe0e\\ufe0f",f="["+r+"]",s="["+c+"]",l="\\ud83c[\\udffb-\\udfff]",p="(?:"+s+"|"+l+")",d="[^"+r+"]",v="(?:\\ud83c[\\udde6-\\uddff]){2}",h="[\\ud800-\\udbff][\\udc00-\\udfff]",b="\\u200d",y=p+"?",m="["+a+"]?",g="(?:"+b+"(?:"+[d,v,h].join("|")+")"+m+y+")*",x=m+y+g,_="(?:"+[d+s+"?",s,v,h,f].join("|")+")",w=RegExp(l+"(?="+l+")|"+_+x,"g");t.exports=e},function(t,n,e){var r=e(105),o=e(107),i=e(169),u=o(function(t,n,e,o){r(n,i(n),t,o)});t.exports=u},function(t,n){function e(t){return function(){return t}}t.exports=e},function(t,n,e){var r=e(31),o=e(161),i=e(39),u=e(111),c=i(function(t){return t.push(void 0,u),r(o,void 0,t)});t.exports=c},function(t,n,e){var r=e(110),o=e(165),i=r(o);t.exports=i},function(t,n,e){function r(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var a=null==e?0:u(e);return a<0&&(a=c(r+a,0)),o(t,i(n,3),a)}var o=e(82),i=e(13),u=e(177),c=Math.max;t.exports=r},function(t,n,e){function r(t,n,e){var r=null==t?void 0:o(t,n);return void 0===r?e:r}var o=e(35);t.exports=r},function(t,n,e){function r(t,n){return null!=t&&i(t,n,o)}var o=e(86),i=e(119);t.exports=r},function(t,n,e){function r(t){return"string"==typeof t||!i(t)&&u(t)&&o(t)==c}var o=e(6),i=e(1),u=e(8),c="[object String]";t.exports=r},function(t,n,e){function r(t){return u(t)?o(t,!0):i(t)}var o=e(32),i=e(92),u=e(4);t.exports=r},function(t,n,e){function r(t,n){if("function"!=typeof t||null!=n&&"function"!=typeof n)throw new TypeError(i);var e=function e(){var r=arguments,o=n?n.apply(this,r):r[0],i=e.cache;if(i.has(o))return i.get(o);var u=t.apply(this,r);return e.cache=i.set(o,u)||i,u};return e.cache=new(r.Cache||o),e}var o=e(22),i="Expected a function";r.Cache=o,t.exports=r},function(t,n,e){function r(t){return u(t)?o(c(t)):i(t)}var o=e(38),i=e(96),u=e(25),c=e(16);t.exports=r},function(t,n,e){function r(t,n,e){var r=a(t)?o:c,f=arguments.length<3;return r(t,u(n,4),e,f,i)}var o=e(78),i=e(23),u=e(13),c=e(98),a=e(1);t.exports=r},function(t,n,e){function r(t){if(null==t)return 0;if(u(t))return c(t)?a(t):t.length;var n=i(t);return n==f||n==s?t.size:o(t).length}var o=e(37),i=e(44),u=e(4),c=e(168),a=e(157),f="[object Map]",s="[object Set]";t.exports=r},function(t,n){function e(){return[]}t.exports=e},function(t,n){function e(){return!1}t.exports=e},function(t,n,e){function r(t){if(!t)return 0===t?t:0;if(t=o(t),t===i||t===-i){var n=t<0?-1:1;return n*u}return t===t?t:0}var o=e(178),i=1/0,u=1.7976931348623157e308;t.exports=r},function(t,n,e){function r(t){var n=o(t),e=n%1;return n===n?e?n-e:n:0}var o=e(176);t.exports=r},function(t,n,e){function r(t){if("number"==typeof t)return t;if(i(t))return u;if(o(t)){var n="function"==typeof t.valueOf?t.valueOf():t;t=o(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(c,"");var e=f.test(t);return e||s.test(t)?l(t.slice(2),e?2:8):a.test(t)?u:+t}var o=e(7),i=e(18),u=NaN,c=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,f=/^0b[01]+$/i,s=/^0o[0-7]+$/i,l=parseInt;t.exports=r},function(t,n,e){function r(t){return t=o(t),t&&c.test(t)?t.replace(u,i):t}var o=e(53),i=e(159),u=/&(?:amp|lt|gt|quot|#39);/g,c=RegExp(u.source);t.exports=r},function(t,n){var e,r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};e=function(){return this}();try{e=e||Function("return this")()||(0,eval)("this")}catch(t){"object"===("undefined"==typeof window?"undefined":r(window))&&(e=window)}t.exports=e},function(t,n,e){"use strict";function r(t){var n=t.children,r=i()(n,function(t){var n=t.name;return"img"===n});return r?e.i(u.b)("img",{src:r.attrs.src,className:"image-block__display"}):null}var o=e(164),i=e.n(o),u=e(0);n.a=r},function(t,n,e){"use strict";function r(t){if(t.value)return s()(t.value);var n=void 0;return t.children&&(n=u()(t.children,r)),"HTML_Tag"===t.type?e.i(l.b)(t.name,t.attrs,n):n}function o(t){var n=t.node,o=a()(n.attrs,function(t,n,e){switch(e){case"align":t["text-align"]=n}return t},{});return e.i(l.b)("p",{contentEditable:!0,style:o,className:"text-block__form"},u()(n.children,r))}var i=e(20),u=e.n(i),c=e(172),a=e.n(c),f=e(179),s=e.n(f),l=e(0);n.a=o},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M5 6l5 5 5-5 2 1-7 7-7-7z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M15 14l-5-5-5 5-2-1 7-7 7 7z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M14 5v-2h-8v2h8zM17 9v-2h-14v2h14zM14 13v-2h-8v2h8zM17 17v-2h-14v2h14z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M12 5v-2h-9v2h9zM17 9v-2h-14v2h14zM12 13v-2h-9v2h9zM17 17v-2h-14v2h14z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M17 5v-2h-9v2h9zM17 9v-2h-14v2h14zM17 13v-2h-9v2h9zM17 17v-2h-14v2h14z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M15 2h-7.46c-0.83 0-1.59 0.2-2.28 0.6-0.7 0.41-1.25 0.96-1.65 1.65-0.41 0.69-0.61 1.45-0.61 2.27s0.2 1.58 0.61 2.27c0.4 0.69 0.95 1.24 1.65 1.64 0.69 0.41 1.45 0.61 2.28 0.61h0.43v5.96c0 0.27 0.1 0.51 0.29 0.71 0.2 0.19 0.44 0.29 0.71 0.29 0.28 0 0.51-0.1 0.71-0.29 0.2-0.2 0.3-0.44 0.3-0.71v-12c0-0.27 0.090-0.51 0.29-0.71 0.2-0.19 0.44-0.29 0.71-0.29s0.51 0.1 0.71 0.29c0.19 0.2 0.29 0.44 0.29 0.71v12c0 0.27 0.1 0.51 0.3 0.71 0.2 0.19 0.43 0.29 0.71 0.29 0.27 0 0.51-0.1 0.71-0.29 0.19-0.2 0.29-0.44 0.29-0.71v-13h1.010c0.27 0 0.5-0.1 0.7-0.3 0.2-0.19 0.3-0.43 0.3-0.7s-0.1-0.51-0.3-0.71c-0.2-0.19-0.43-0.29-0.7-0.29z"}))},function(t,n,e){"use strict";var r=e(0),o=e(5);n.a=e.i(o.a)(e.i(r.b)("path",{d:"M2.25 1h15.5c0.69 0 1.25 0.56 1.25 1.25v15.5c0 0.69-0.56 1.25-1.25 1.25h-15.5c-0.69 0-1.25-0.56-1.25-1.25v-15.5c0-0.69 0.56-1.25 1.25-1.25zM17 17v-14h-14v14h14zM10 6c0-1.1-0.9-2-2-2s-2 0.9-2 2 0.9 2 2 2 2-0.9 2-2zM13 11c0 0 0-6 3-6v10c0 0.55-0.45 1-1 1h-10c-0.55 0-1-0.45-1-1v-7c2 0 3 4 3 4s1-3 3-3 3 2 3 2z"}))},function(t,n,e){"use strict";function r(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}function o(t,n){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?t:n}function i(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);t.prototype=Object.create(n&&n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(t,n):t.__proto__=n)}function u(t,n){t&&p.a.init({target:t.querySelector("[contenteditable=true]"),theme:"inlite",inline:!0,skin_url:"//s1.wp.com/wp-includes/js/tinymce/skins/lightgray",entity_encoding:"raw",setup:n})}function c(t){var n=function(n){function c(){var t,n,i,u;r(this,c);for(var a=arguments.length,f=Array(a),s=0;sQt&&(Qt=qt,Xt=[]),Xt.push(t))}function v(t,n,e){return new i(i.buildMessage(t,n),t,n,e)}function h(){var t,n;for(t=[],n=b();n!==H;)t.push(n),n=b();return t}function b(){var t,n,e;if(t=m(),t===H&&(t=g(),t===H&&(t=x(),t===H&&(t=O(),t===H&&(t=C(),t===H&&(t=A(),t===H&&(t=N(),t===H))))))){if(t=qt,n=[],e=y(),e!==H)for(;e!==H;)n.push(e),e=y();else n=H;n!==H&&(Jt=t,n=Z(n)),t=n}return t}function y(){var n;return q.test(t.charAt(qt))?(n=t.charAt(qt),qt++):(n=H,0===Yt&&d(J)),n}function m(){var t,n,e,r,o,i;if(t=qt,n=g(),n!==H){if(e=[],r=qt,o=qt,Yt++,i=x(),Yt--,i===H?o=void 0:(qt=o,o=H),o!==H?(i=b(),i!==H?(Jt=r,o=K(n,i),r=o):(qt=r,r=H)):(qt=r,r=H),r!==H)for(;r!==H;)e.push(r),r=qt,o=qt,Yt++,i=x(),Yt--,i===H?o=void 0:(qt=o,o=H),o!==H?(i=b(),i!==H?(Jt=r,o=K(n,i),r=o):(qt=r,r=H)):(qt=r,r=H);else e=H;e!==H?(r=x(),r!==H?(Jt=t,n=Q(n,e,r),t=n):(qt=t,t=H)):(qt=t,t=H)}else qt=t,t=H;return t}function g(){var n,e,r,o,i,u,c,a;return n=qt,t.substr(qt,4)===X?(e=X,qt+=4):(e=H,0===Yt&&d(Y)),e!==H?(r=W(),r!==H?(t.substr(qt,3)===tt?(o=tt,qt+=3):(o=H,0===Yt&&d(nt)),o!==H?(i=_(),i!==H?(u=w(),u!==H?(c=D(),c===H&&(c=null),c!==H?(t.substr(qt,3)===et?(a=et,qt+=3):(a=H,0===Yt&&d(rt)),a!==H?(Jt=n,e=ot(i,u),n=e):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H),n}function x(){var n,e,r,o,i,u;return n=qt,t.substr(qt,4)===X?(e=X,qt+=4):(e=H,0===Yt&&d(Y)),e!==H?(r=W(),r!==H?(t.substr(qt,3)===it?(o=it,qt+=3):(o=H,0===Yt&&d(ut)),o!==H?(i=W(),i!==H?(t.substr(qt,3)===et?(u=et,qt+=3):(u=H,0===Yt&&d(rt)),u!==H?(Jt=n,e=ct(),n=e):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H),n}function _(){var t,n,e,r;if(t=qt,n=F(),n!==H){for(e=[],r=B();r!==H;)e.push(r),r=B();e!==H?(Jt=t,n=at(n,e),t=n):(qt=t,t=H)}else qt=t,t=H;return t}function w(){var t,n,e,r,o;if(t=qt,n=[],e=qt,r=[],o=D(),o!==H)for(;o!==H;)r.push(o),o=D();else r=H;for(r!==H?(o=j(),o!==H?(Jt=e,r=ft(o),e=r):(qt=e,e=H)):(qt=e,e=H);e!==H;){if(n.push(e),e=qt,r=[],o=D(),o!==H)for(;o!==H;)r.push(o),o=D();else r=H;r!==H?(o=j(),o!==H?(Jt=e,r=ft(o),e=r):(qt=e,e=H)):(qt=e,e=H)}return n!==H&&(Jt=t,n=st(n)),t=n}function j(){var n,e,r,o;return n=qt,e=k(),e!==H?(58===t.charCodeAt(qt)?(r=lt,qt++):(r=H,0===Yt&&d(pt)),r!==H?(o=S(),o!==H?(Jt=n,e=dt(e,o),n=e):(qt=n,n=H)):(qt=n,n=H)):(qt=n,n=H),n}function k(){var t,n,e,r;if(t=qt,n=F(),n!==H){for(e=[],r=B();r!==H;)e.push(r),r=B();e!==H?(Jt=t,n=at(n,e),t=n):(qt=t,t=H)}else qt=t,t=H;return t}function S(){var t,n,e,r;if(t=qt,n=F(),n!==H){for(e=[],r=B();r!==H;)e.push(r),r=B();e!==H?(Jt=t,n=vt(n,e),t=n):(qt=t,t=H)}else qt=t,t=H;return t}function O(){var n,e,r,o,i,u;if(n=qt,t.substr(qt,4)===X?(e=X,qt+=4):(e=H,0===Yt&&d(Y)),e!==H){for(r=[],o=qt,i=qt,Yt++,t.substr(qt,3)===et?(u=et,qt+=3):(u=H,0===Yt&&d(rt)),Yt--,u===H?i=void 0:(qt=i,i=H),i!==H?(t.length>qt?(u=t.charAt(qt),qt++):(u=H,0===Yt&&d(ht)),u!==H?(Jt=o,i=bt(u),o=i):(qt=o,o=H)):(qt=o,o=H);o!==H;)r.push(o),o=qt,i=qt,Yt++,t.substr(qt,3)===et?(u=et,qt+=3):(u=H,0===Yt&&d(rt)),Yt--,u===H?i=void 0:(qt=i,i=H),i!==H?(t.length>qt?(u=t.charAt(qt),qt++):(u=H,0===Yt&&d(ht)),u!==H?(Jt=o,i=bt(u),o=i):(qt=o,o=H)):(qt=o,o=H);r!==H?(t.substr(qt,3)===et?(o=et,qt+=3):(o=H,0===Yt&&d(rt)),o!==H?(Jt=n,e=yt(r),n=e):(qt=n,n=H)):(qt=n,n=H)}else qt=n,n=H;return n}function C(){var t,n,e,r,o,i;if(t=qt,n=A(),n!==H){if(e=[],r=qt,o=qt,Yt++,i=N(),Yt--,i===H?o=void 0:(qt=o,o=H),o!==H?(i=b(),i!==H?(Jt=r,o=K(n,i),r=o):(qt=r,r=H)):(qt=r,r=H),r!==H)for(;r!==H;)e.push(r),r=qt,o=qt,Yt++,i=N(),Yt--,i===H?o=void 0:(qt=o,o=H),o!==H?(i=b(),i!==H?(Jt=r,o=K(n,i),r=o):(qt=r,r=H)):(qt=r,r=H);else e=H;e!==H?(r=N(),r!==H?(Jt=t,n=mt(n,e,r),t=n):(qt=t,t=H)):(qt=t,t=H)}else qt=t,t=H;return t}function A(){var n,e,r,o,i,u;if(n=qt,60===t.charCodeAt(qt)?(e=gt,qt++):(e=H,0===Yt&&d(xt)),e!==H)if(r=z(),r!==H)if(o=P(),o!==H){for(i=[],u=D();u!==H;)i.push(u),u=D();i!==H?(62===t.charCodeAt(qt)?(u=_t,qt++):(u=H,0===Yt&&d(wt)),u!==H?(Jt=n,e=jt(r,o),n=e):(qt=n,n=H)):(qt=n,n=H)}else qt=n,n=H;else qt=n,n=H;else qt=n,n=H;return n}function N(){var n,e,r,o,i;if(n=qt,t.substr(qt,2)===kt?(e=kt,qt+=2):(e=H,0===Yt&&d(St)),e!==H)if(r=z(),r!==H){for(o=[],i=D();i!==H;)o.push(i),i=D();o!==H?(62===t.charCodeAt(qt)?(i=_t,qt++):(i=H,0===Yt&&d(wt)),i!==H?(Jt=n,e=Ot(r),n=e):(qt=n,n=H)):(qt=n,n=H)}else qt=n,n=H;else qt=n,n=H;return n}function z(){var t,n,e;if(t=qt,n=[],e=M(),e!==H)for(;e!==H;)n.push(e),e=M();else n=H;return n!==H&&(Jt=t,n=Ct(n)),t=n}function M(){var t;return t=F(),t===H&&(t=I()),t}function P(){var t,n,e,r,o;if(t=qt,n=[],e=qt,r=[],o=D(),o!==H)for(;o!==H;)r.push(o),o=D();else r=H;for(r!==H?(o=T(),o!==H?(Jt=e,r=At(o),e=r):(qt=e,e=H)):(qt=e,e=H);e!==H;){if(n.push(e),e=qt,r=[],o=D(),o!==H)for(;o!==H;)r.push(o),o=D();else r=H;r!==H?(o=T(),o!==H?(Jt=e,r=At(o),e=r):(qt=e,e=H)):(qt=e,e=H)}return n!==H&&(Jt=t,n=st(n)),t=n}function T(){var t;return t=R(),t===H&&(t=U(),t===H&&(t=E())),t}function E(){var t,n;return t=qt,n=L(),n!==H&&(Jt=t,n=Nt(n)),t=n}function U(){var n,e,r,o,i,u,c;if(n=qt,e=L(),e!==H){for(r=[],o=D();o!==H;)r.push(o),o=D();if(r!==H)if(61===t.charCodeAt(qt)?(o=zt,qt++):(o=H,0===Yt&&d(Mt)),o!==H){for(i=[],u=D();u!==H;)i.push(u),u=D();if(i!==H){if(u=[],Pt.test(t.charAt(qt))?(c=t.charAt(qt),qt++):(c=H,0===Yt&&d(Tt)),c!==H)for(;c!==H;)u.push(c),Pt.test(t.charAt(qt))?(c=t.charAt(qt),qt++):(c=H,0===Yt&&d(Tt));else u=H;u!==H?(Jt=n,e=Et(e,u),n=e):(qt=n,n=H)}else qt=n,n=H}else qt=n,n=H;else qt=n,n=H}else qt=n,n=H;return n}function R(){var n,e,r,o,i,u,c,a,f,s;if(n=qt,e=L(),e!==H){for(r=[],o=D();o!==H;)r.push(o),o=D();if(r!==H)if(61===t.charCodeAt(qt)?(o=zt,qt++):(o=H,0===Yt&&d(Mt)),o!==H){for(i=[],u=D();u!==H;)i.push(u),u=D();if(i!==H)if(34===t.charCodeAt(qt)?(u=Ut,qt++):(u=H,0===Yt&&d(Rt)),u!==H){for(c=[],a=qt,f=qt,Yt++,34===t.charCodeAt(qt)?(s=Ut,qt++):(s=H,0===Yt&&d(Rt)),Yt--,s===H?f=void 0:(qt=f,f=H),f!==H?(t.length>qt?(s=t.charAt(qt),qt++):(s=H,0===Yt&&d(ht)),s!==H?(Jt=a,f=Lt(e,s),a=f):(qt=a,a=H)):(qt=a,a=H);a!==H;)c.push(a),a=qt,f=qt,Yt++,34===t.charCodeAt(qt)?(s=Ut,qt++):(s=H,0===Yt&&d(Rt)),Yt--,s===H?f=void 0:(qt=f,f=H),f!==H?(t.length>qt?(s=t.charAt(qt),qt++):(s=H,0===Yt&&d(ht)),s!==H?(Jt=a,f=Lt(e,s),a=f):(qt=a,a=H)):(qt=a,a=H);c!==H?(34===t.charCodeAt(qt)?(a=Ut,qt++):(a=H,0===Yt&&d(Rt)),a!==H?(Jt=n,e=Et(e,c),n=e):(qt=n,n=H)):(qt=n,n=H)}else qt=n,n=H;else qt=n,n=H}else qt=n,n=H;else qt=n,n=H}else qt=n, +n=H;if(n===H)if(n=qt,e=L(),e!==H){for(r=[],o=D();o!==H;)r.push(o),o=D();if(r!==H)if(61===t.charCodeAt(qt)?(o=zt,qt++):(o=H,0===Yt&&d(Mt)),o!==H){for(i=[],u=D();u!==H;)i.push(u),u=D();if(i!==H)if(39===t.charCodeAt(qt)?(u=Bt,qt++):(u=H,0===Yt&&d(Ft)),u!==H){for(c=[],a=qt,f=qt,Yt++,39===t.charCodeAt(qt)?(s=Bt,qt++):(s=H,0===Yt&&d(Ft)),Yt--,s===H?f=void 0:(qt=f,f=H),f!==H?(t.length>qt?(s=t.charAt(qt),qt++):(s=H,0===Yt&&d(ht)),s!==H?(Jt=a,f=Lt(e,s),a=f):(qt=a,a=H)):(qt=a,a=H);a!==H;)c.push(a),a=qt,f=qt,Yt++,39===t.charCodeAt(qt)?(s=Bt,qt++):(s=H,0===Yt&&d(Ft)),Yt--,s===H?f=void 0:(qt=f,f=H),f!==H?(t.length>qt?(s=t.charAt(qt),qt++):(s=H,0===Yt&&d(ht)),s!==H?(Jt=a,f=Lt(e,s),a=f):(qt=a,a=H)):(qt=a,a=H);c!==H?(39===t.charCodeAt(qt)?(a=Bt,qt++):(a=H,0===Yt&&d(Ft)),a!==H?(Jt=n,e=Et(e,c),n=e):(qt=n,n=H)):(qt=n,n=H)}else qt=n,n=H;else qt=n,n=H}else qt=n,n=H;else qt=n,n=H}else qt=n,n=H;return n}function L(){var n,e,r;if(n=qt,e=[],It.test(t.charAt(qt))?(r=t.charAt(qt),qt++):(r=H,0===Yt&&d(Dt)),r!==H)for(;r!==H;)e.push(r),It.test(t.charAt(qt))?(r=t.charAt(qt),qt++):(r=H,0===Yt&&d(Dt));else e=H;return e!==H&&(Jt=n,e=Ct(e)),n=e}function B(){var t;return t=F(),t===H&&(t=I()),t}function F(){var n;return Wt.test(t.charAt(qt))?(n=t.charAt(qt),qt++):(n=H,0===Yt&&d($t)),n}function I(){var n;return Ht.test(t.charAt(qt))?(n=t.charAt(qt),qt++):(n=H,0===Yt&&d(Vt)),n}function D(){var n;return Gt.test(t.charAt(qt))?(n=t.charAt(qt),qt++):(n=H,0===Yt&&d(Zt)),n}function W(){var t,n;if(t=[],n=D(),n!==H)for(;n!==H;)t.push(n),n=D();else t=H;return t}n=void 0!==n?n:{};var $,H={},V={Document:h},G=h,Z=function(t){return{type:"Text",value:t.join("")}},q=/^[^<]/,J=u(["<"],!0,!1),K=function(t,n){return n},Q=function(t,n,r){return{type:"WP_Block",blockType:t.blockType,attrs:t.attrs,startText:t.text,endText:r.text,rawContent:e(),children:n}},X="",rt=o("-->",!1),ot=function(t,n){return{type:"WP_Block_Start",blockType:t,attrs:n,text:e()}},it="/wp",ut=o("/wp",!1),ct=function(){return{type:"WP_Block_End",text:e()}},at=function(t,n){return[t].concat(n).join("")},ft=function(t){return t},st=function(t){return t.reduce(function(t,n){var e=c(n,2),o=e[0],i=e[1];return Object.assign(t,r({},o,i))},{})},lt=":",pt=o(":",!1),dt=function(t,n){return[t,n]},vt=function(t,n){return[t].concat(n).join("")},ht=a(),bt=function(t){return t},yt=function(t){return{type:"HTML_Comment",innerText:t.join(""),text:e()}},mt=function(t,n,e){return{type:"HTML_Tag",name:t.name,attrs:t.attrs,startText:t.text,endText:e.text,children:n}},gt="<",xt=o("<",!1),_t=">",wt=o(">",!1),jt=function(t,n){return{type:"HTML_Tag_Open",name:t,attrs:n,text:e()}},kt="0){for(n=1,e=1;n0&&e.i(s.b)("div",{className:"block-list__block-controls"},c()(n.controls,function(n){var r=v()("block-list__block-control",{"is-selected":n.isSelected(t)});return e.i(s.b)("button",{onClick:function(){return n.onClick(m)},className:r},e.i(s.b)(n.icon,null))})),o&&e.i(s.b)("div",{className:"block-list__block-arrangement"},e.i(s.b)("div",{className:"block-list__movement-controls"},e.i(s.b)("button",{className:"block-list__block-arrange-control"},e.i(s.b)(p.a,null)),e.i(s.b)("button",{className:"block-list__block-arrange-control"},e.i(s.b)(p.b,null))),n.icon&&e.i(s.b)("div",{className:"block-list__type-controls"},e.i(s.b)("button",{className:"block-list__block-arrange-control"},e.i(s.b)(n.icon,null)))))}}]),n}(s.c);n.a=g},function(t,n,e){"use strict";function r(t){if(Array.isArray(t)){for(var n=0,e=Array(t.length);n"+r(t.children)+"";case"HTML_Tag":return[t.startText,r(t.children),t.endText].join("");case"HTML_Tag_Open":return t.text}return t.value}).join("")}Object.defineProperty(n,"__esModule",{value:!0});var o=e(20),i=e.n(o);n.serialize=r},function(t,n,e){n=t.exports=e(66)(),n.push([t.i,'@-webkit-keyframes animate_fade{0%{opacity:0;-webkit-transform:scale(.92);transform:scale(.92)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes animate_fade{0%{opacity:0;-webkit-transform:scale(.92);transform:scale(.92)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.text-block__form{margin:0;outline:none}.image-block__display{display:block;max-width:100%}.dashicon{display:inline-block;width:2rem;height:2rem;fill:currentColor}.block-list{list-style:none;padding:0;margin:0;font-size:16px;font-weight:300;line-height:1.7;font-family:Merriweather,Georgia,Times New Roman,Times,serif}.block-list__block{position:relative;border:2px solid transparent;outline:none;margin-bottom:1rem;padding:.8rem 1.2rem;-webkit-transition:border-color .2s;transition:border-color .2s}.block-list__block:hover{border-color:#d6d9dd}.block-list__block.is-focused{border-color:#6c7781}.block-list__block-controls{-webkit-animation:animate_fade .2s ease-out;animation:animate_fade .2s ease-out;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;position:absolute;left:-2px;top:-30px}.block-list__block-control{padding:4px;background:none;background-color:#191e23;border:none;color:#fff;cursor:pointer}.block-list__block-control.is-selected{background-color:#6c7781}.block-list__block-control .dashicon{display:block}.block-list__block-arrangement{-webkit-animation:animate_fade .2s ease-out;animation:animate_fade .2s ease-out;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;position:absolute;top:0;left:-6rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.block-list__type-controls{margin-left:.6rem}.block-list__block-arrange-control{display:block;padding:0;border:none;outline:none;background:none;color:#6c7781;cursor:pointer}.block-list__block-arrange-control .dashicon{display:block;height:20px;width:20px}.html-editor{box-sizing:border-box;display:block;width:100%;height:100%;resize:none;border:none;border:2px solid transparent;outline:none;padding:.8rem 1.2rem;-webkit-transition:border-color .2s;transition:border-color .2s;font-family:Courier\\ 10 Pitch,Courier,monospace;font-size:14px;line-height:1.3}.html-editor:hover{border-color:#d6d9dd}.html-editor:focus{border-color:#6c7781}html{height:100%;font-size:10px}body{margin:4vh auto;min-height:92vh;width:90%;max-width:1280px;-webkit-font-smoothing:antialiased!important}.renderers{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;min-height:100%}.renderers:after{content:"";position:absolute;top:0;bottom:0;left:50%;margin-left:-2px;width:4px;background-color:#f0f2f4}.renderers>#block,.renderers>#html{-ms-flex-preferred-size:50%;flex-basis:50%;margin:0 8rem;padding:4vh 0}.renderers>#block:first-child,.renderers>#html:first-child{margin-left:0}.renderers>#block:last-child,.renderers>#html:last-child{margin-right:0}',""])},function(t,n){function e(t,n){for(var e=0;e=0&&m.splice(n,1)}function u(t){var n=document.createElement("style");return n.type="text/css",o(t,n),n}function c(t){var n=document.createElement("link");return n.rel="stylesheet",o(t,n),n}function a(t,n){var e,r,o;if(n.singleton){var a=y++;e=b||(b=u(n)),r=f.bind(null,e,a,!1),o=f.bind(null,e,a,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(e=c(n),r=l.bind(null,e),o=function(){i(e),e.href&&URL.revokeObjectURL(e.href)}):(e=u(n),r=s.bind(null,e),o=function(){i(e)});return r(t),function(n){if(n){if(n.css===t.css&&n.media===t.media&&n.sourceMap===t.sourceMap)return;r(t=n)}else o()}}function f(t,n,e,r){var o=e?"":r.css;if(t.styleSheet)t.styleSheet.cssText=g(n,o);else{var i=document.createTextNode(o),u=t.childNodes;u[n]&&t.removeChild(u[n]),u.length?t.insertBefore(i,u[n]):t.appendChild(i)}}function s(t,n){var e=n.css,r=n.media;if(r&&t.setAttribute("media",r),t.styleSheet)t.styleSheet.cssText=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}}function l(t,n){var e=n.css,r=n.sourceMap;r&&(e+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var o=new Blob([e],{type:"text/css"}),i=t.href;t.href=URL.createObjectURL(o),i&&URL.revokeObjectURL(i)}var p={},d=function(t){var n;return function(){return"undefined"==typeof n&&(n=t.apply(this,arguments)),n}},v=d(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),h=d(function(){return document.head||document.getElementsByTagName("head")[0]}),b=null,y=0,m=[];t.exports=function(t,n){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");n=n||{},"undefined"==typeof n.singleton&&(n.singleton=v()),"undefined"==typeof n.insertAt&&(n.insertAt="bottom");var o=r(t);return e(o,n),function(t){for(var i=[],u=0;u1&&void 0!==arguments[1]?arguments[1]:{};u()(a,function(e,i){function u(t){var n=f[i],e=t;n&&(e=n.serialize(e)),o(e,r({},i,t))}var a=c[i],s=document.getElementById(i),l=void 0;l=n[i]?n[i]:a?a.parse(t):t,e(l,s,u)})}Object.defineProperty(n,"__esModule",{value:!0});var i=e(58),u=e.n(i),c=e(61),a=e(62),f=e(63),s=e(64);e.n(s),e(60),e(59);o(window.content)}]); \ No newline at end of file diff --git a/tinymce-per-block/index.html b/tinymce-per-block/index.html new file mode 100644 index 0000000000000..c9ac580f72984 --- /dev/null +++ b/tinymce-per-block/index.html @@ -0,0 +1,20 @@ + + + + + Blocks + + +
+
+
+
+ + + + + + + diff --git a/tinymce-per-block/package.json b/tinymce-per-block/package.json new file mode 100644 index 0000000000000..b38c22d341222 --- /dev/null +++ b/tinymce-per-block/package.json @@ -0,0 +1,57 @@ +{ + "name": "gutenberg", + "version": "1.0.0", + "description": "Prototyping a new WordPress editor experience", + "main": "index.html", + "scripts": { + "prebuild": "npm run clean", + "build": "cross-env NODE_ENV=production webpack", + "clean": "rimraf build", + "predev": "npm run clean", + "dev": "webpack-dev-server --content-base ./" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Automattic/gutenberg.git" + }, + "keywords": [ + "WordPress", + "editor", + "prototype" + ], + "author": "WordPress Contributors", + "license": "GPL-2.0+", + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "homepage": "https://github.com/WordPress/gutenberg#readme", + "devDependencies": { + "autoprefixer": "^6.7.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-loader": "^6.2.10", + "babel-plugin-lodash": "^3.2.11", + "babel-plugin-transform-react-jsx": "^6.22.0", + "babel-preset-es2015": "^6.22.0", + "babel-preset-stage-2": "^6.22.0", + "cross-env": "^3.1.4", + "css-loader": "^0.26.1", + "eslint": "^3.15.0", + "eslint-config-wpcalypso": "^0.6.0", + "eslint-plugin-react": "^6.9.0", + "eslint-plugin-wpcalypso": "^3.0.2", + "node-sass": "^4.5.0", + "postcss-loader": "^1.2.2", + "rimraf": "^2.5.4", + "sass-loader": "^4.1.1", + "style-loader": "^0.13.1", + "webpack": "^2.2.1", + "webpack-dev-server": "^2.3.0" + }, + "dependencies": { + "classnames": "^2.2.5", + "is-equal-shallow": "^0.1.3", + "lodash": "^4.17.4", + "preact": "^7.1.0" + } +} diff --git a/tinymce-per-block/src/assets/stylesheets/_animations.scss b/tinymce-per-block/src/assets/stylesheets/_animations.scss new file mode 100644 index 0000000000000..33c8ec202d9a4 --- /dev/null +++ b/tinymce-per-block/src/assets/stylesheets/_animations.scss @@ -0,0 +1,15 @@ +@mixin animate_fade { + animation: animate_fade 0.2s ease-out; + animation-fill-mode: forwards; +} + +@keyframes animate_fade { + from { + opacity: 0; + transform: scale( 0.92 ) + } + to { + opacity: 1; + transform: scale( 1 ) + } +} diff --git a/tinymce-per-block/src/assets/stylesheets/_variables.scss b/tinymce-per-block/src/assets/stylesheets/_variables.scss new file mode 100644 index 0000000000000..de76ff87cc371 --- /dev/null +++ b/tinymce-per-block/src/assets/stylesheets/_variables.scss @@ -0,0 +1,4 @@ +// Colors +$gray-light: #f0f2f4; +$gray-dark-300: #6c7781; +$gray-dark-900: #191e23; diff --git a/tinymce-per-block/src/assets/stylesheets/main.scss b/tinymce-per-block/src/assets/stylesheets/main.scss new file mode 100644 index 0000000000000..ebf2ed97c69aa --- /dev/null +++ b/tinymce-per-block/src/assets/stylesheets/main.scss @@ -0,0 +1,52 @@ +@import 'variables'; +@import 'animations'; +@import '~blocks/text-block/style'; +@import '~blocks/image-block/style'; +@import '~external/dashicons/style'; +@import '~renderers/block/block-list/style'; +@import '~renderers/html/html-editor/style'; + +html { + height: 100%; + font-size: 10px; +} + +body { + margin: 4vh auto; + min-height: 92vh; + width: 90%; + max-width: 1280px; + -webkit-font-smoothing: antialiased !important; +} + +.renderers { + position: relative; + display: flex; + min-height: 100%; + + &::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + margin-left: -2px; + width: 4px; + background-color: $gray-light; + } + + > #html, + > #block { + flex-basis: 50%; + margin: 0 8rem; + padding: 4vh 0; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + } +} diff --git a/tinymce-per-block/src/blocks/image-block/_style.scss b/tinymce-per-block/src/blocks/image-block/_style.scss new file mode 100644 index 0000000000000..fcdc71aa23ff4 --- /dev/null +++ b/tinymce-per-block/src/blocks/image-block/_style.scss @@ -0,0 +1,4 @@ +.image-block__display { + display: block; + max-width: 100%; +} diff --git a/tinymce-per-block/src/blocks/image-block/form.js b/tinymce-per-block/src/blocks/image-block/form.js new file mode 100644 index 0000000000000..03f61c5446279 --- /dev/null +++ b/tinymce-per-block/src/blocks/image-block/form.js @@ -0,0 +1,18 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; +import { find } from 'lodash'; + +export default function ImageBlockForm( { children } ) { + const image = find( children, ( { name } ) => 'img' === name ); + if ( ! image ) { + return null; + } + + return ( + + ); +} diff --git a/tinymce-per-block/src/blocks/image-block/index.js b/tinymce-per-block/src/blocks/image-block/index.js new file mode 100644 index 0000000000000..56cd6ece65318 --- /dev/null +++ b/tinymce-per-block/src/blocks/image-block/index.js @@ -0,0 +1,16 @@ +/** + * External dependencies + */ +import { registerBlock } from 'wp-blocks'; +import { FormatImageIcon } from 'dashicons'; + +/** + * Internal dependencies + */ +import form from './form'; + +registerBlock( 'image', { + title: 'Image', + icon: FormatImageIcon, + form +} ); diff --git a/tinymce-per-block/src/blocks/text-block/_style.scss b/tinymce-per-block/src/blocks/text-block/_style.scss new file mode 100644 index 0000000000000..eab30f9132d75 --- /dev/null +++ b/tinymce-per-block/src/blocks/text-block/_style.scss @@ -0,0 +1,4 @@ +.text-block__form { + margin: 0; + outline: none; +} diff --git a/tinymce-per-block/src/blocks/text-block/form.js b/tinymce-per-block/src/blocks/text-block/form.js new file mode 100644 index 0000000000000..eb9a18e7336e6 --- /dev/null +++ b/tinymce-per-block/src/blocks/text-block/form.js @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; +import { unescape as unescapeString, reduce, map } from 'lodash'; + +function getChildElements( child ) { + if ( child.value ) { + return unescapeString( child.value ); + } + + let children; + if ( child.children ) { + children = map( child.children, getChildElements ); + } + + if ( 'HTML_Tag' === child.type ) { + return createElement( child.name, child.attrs, children ); + } + + return children; +} + +export default function TextBlockForm( { node } ) { + const style = reduce( node.attrs, ( memo, value, key ) => { + switch ( key ) { + case 'align': + memo[ 'text-align' ] = value; + break; + } + + return memo; + }, {} ); + + return ( +

+ { map( node.children, getChildElements ) } +

+ ); +} diff --git a/tinymce-per-block/src/blocks/text-block/index.js b/tinymce-per-block/src/blocks/text-block/index.js new file mode 100644 index 0000000000000..c500c786dd22d --- /dev/null +++ b/tinymce-per-block/src/blocks/text-block/index.js @@ -0,0 +1,53 @@ +/** + * External dependencies + */ +import { registerBlock, bindEditable } from 'wp-blocks'; +import { + EditorParagraphIcon, + EditorAlignLeftIcon, + EditorAlignCenterIcon, + EditorAlignRightIcon +} from 'dashicons'; + +/** + * Internal dependencies + */ +import form from './form'; + +registerBlock( 'text', { + title: 'Text', + form: bindEditable( form ), + icon: EditorParagraphIcon, + controls: [ + { + label: 'Align Left', + icon: EditorAlignLeftIcon, + isSelected: ( { attrs } ) => ! attrs.align || 'left' === attrs.align, + onClick( state ) { + state.setAttributes( { + align: 'left' + } ); + } + }, + { + label: 'Align Center', + icon: EditorAlignCenterIcon, + isSelected: ( { attrs } ) => 'center' === attrs.align, + onClick( state ) { + state.setAttributes( { + align: 'center' + } ); + } + }, + { + label: 'Align Right', + icon: EditorAlignRightIcon, + isSelected: ( { attrs } ) => 'right' === attrs.align, + onClick( state ) { + state.setAttributes( { + align: 'right' + } ); + } + } + ] +} ); diff --git a/tinymce-per-block/src/external/dashicons/_style.scss b/tinymce-per-block/src/external/dashicons/_style.scss new file mode 100644 index 0000000000000..281e8400e572b --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/_style.scss @@ -0,0 +1,6 @@ +.dashicon { + display: inline-block; + width: 2rem; + height: 2rem; + fill: currentColor; +} diff --git a/tinymce-per-block/src/external/dashicons/create-dashicon.js b/tinymce-per-block/src/external/dashicons/create-dashicon.js new file mode 100644 index 0000000000000..79527918c11ed --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/create-dashicon.js @@ -0,0 +1,21 @@ +/* eslint-disable wpcalypso/jsx-classname-namespace */ + +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +export default function createDashicon( icon ) { + icon = ( + + { icon } + + ); + + return () => icon; +} diff --git a/tinymce-per-block/src/external/dashicons/icons/.eslintrc.json b/tinymce-per-block/src/external/dashicons/icons/.eslintrc.json new file mode 100644 index 0000000000000..35b2f0fa7bf20 --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "max-len": 0 + } +} diff --git a/tinymce-per-block/src/external/dashicons/icons/arrow-down-alt2.js b/tinymce-per-block/src/external/dashicons/icons/arrow-down-alt2.js new file mode 100644 index 0000000000000..f769535078dad --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/arrow-down-alt2.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/arrow-up-alt2.js b/tinymce-per-block/src/external/dashicons/icons/arrow-up-alt2.js new file mode 100644 index 0000000000000..11790a53f875a --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/arrow-up-alt2.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/editor-aligncenter.js b/tinymce-per-block/src/external/dashicons/icons/editor-aligncenter.js new file mode 100644 index 0000000000000..498abaf5dc54e --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/editor-aligncenter.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/editor-alignleft.js b/tinymce-per-block/src/external/dashicons/icons/editor-alignleft.js new file mode 100644 index 0000000000000..9c3a90886c5e8 --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/editor-alignleft.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/editor-alignright.js b/tinymce-per-block/src/external/dashicons/icons/editor-alignright.js new file mode 100644 index 0000000000000..4c8dc838d4504 --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/editor-alignright.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/editor-paragraph.js b/tinymce-per-block/src/external/dashicons/icons/editor-paragraph.js new file mode 100644 index 0000000000000..f90b17155d05f --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/editor-paragraph.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/icons/format-image.js b/tinymce-per-block/src/external/dashicons/icons/format-image.js new file mode 100644 index 0000000000000..255b4308eb2f9 --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/icons/format-image.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import createDashicon from '../create-dashicon'; + +export default createDashicon( + +); diff --git a/tinymce-per-block/src/external/dashicons/index.js b/tinymce-per-block/src/external/dashicons/index.js new file mode 100644 index 0000000000000..1c05e25d58237 --- /dev/null +++ b/tinymce-per-block/src/external/dashicons/index.js @@ -0,0 +1,7 @@ +export { default as EditorAlignLeftIcon } from './icons/editor-alignleft'; +export { default as EditorAlignCenterIcon } from './icons/editor-aligncenter'; +export { default as EditorAlignRightIcon } from './icons/editor-alignright'; +export { default as ArrowDownAlt2Icon } from './icons/arrow-down-alt2'; +export { default as ArrowUpAlt2Icon } from './icons/arrow-up-alt2'; +export { default as EditorParagraphIcon } from './icons/editor-paragraph'; +export { default as FormatImageIcon } from './icons/format-image'; diff --git a/tinymce-per-block/src/external/wp-blocks/bind-editable/index.js b/tinymce-per-block/src/external/wp-blocks/bind-editable/index.js new file mode 100644 index 0000000000000..0686b38660e4d --- /dev/null +++ b/tinymce-per-block/src/external/wp-blocks/bind-editable/index.js @@ -0,0 +1,87 @@ +/** + * External dependencies + */ +import { createElement, Component } from 'wp-elements'; +import isEqualShallow from 'is-equal-shallow'; +import tinymce from 'tinymce'; + +// TODO: Shouldn't be able to access this from external +import { parse } from 'parsers/block'; + +function initialize( node, onSetup ) { + if ( ! node ) { + return; + } + + tinymce.init( { + target: node.querySelector( '[contenteditable=true]' ), + theme: 'inlite', + inline: true, + skin_url: '//s1.wp.com/wp-includes/js/tinymce/skins/lightgray', + entity_encoding: 'raw', + setup: onSetup + } ); +} + +export default function bindEditable( BaseComponent ) { + class EditableComponent extends Component { + static defaultProps = { + setContent() {} + }; + + componentDidMount() { + initialize( this.node, this.onSetup ); + } + + componentDidUpdate( prevProps ) { + if ( ! isEqualShallow( this.props, prevProps ) ) { + initialize( this.node, this.onChange ); + } + } + + componentWillUnmount() { + if ( this.editor ) { + this.editor.destroy(); + } + } + + onSetup = ( editor ) => { + this.editor = editor; + + editor.on( 'init', this.setInitialContent ); + editor.on( 'change focusout undo redo', this.onChange ); + }; + + setInitialContent = () => { + this.content = this.editor.getContent(); + }; + + onChange = () => { + // TODO: `getContent` is slow, but formats better than 'raw'. We + // should check implication of performance and see if we can rely + // on raw formatting instead. + + const content = this.editor.getContent(); + if ( content === this.content ) { + return; + } + + this.props.setChildren( parse( content ) ); + this.content = content; + }; + + setRef = ( node ) => { + this.node = node; + }; + + render() { + return ( +
+ +
+ ); + } + } + + return ( node, state ) => ; +} diff --git a/tinymce-per-block/src/external/wp-blocks/index.js b/tinymce-per-block/src/external/wp-blocks/index.js new file mode 100644 index 0000000000000..3181b4d7db9be --- /dev/null +++ b/tinymce-per-block/src/external/wp-blocks/index.js @@ -0,0 +1,22 @@ +/** + * External dependencies + */ +import { defaults } from 'lodash'; + +export { default as bindEditable } from './bind-editable'; + +const _registered = {}; + +export function registerBlock( name, options ) { + options = defaults( options, { + title: name + } ); + + _registered[ name ] = options; + + return options; +} + +export function getBlock( name ) { + return _registered[ name ]; +} diff --git a/tinymce-per-block/src/external/wp-elements/index.js b/tinymce-per-block/src/external/wp-elements/index.js new file mode 100644 index 0000000000000..915a705898d13 --- /dev/null +++ b/tinymce-per-block/src/external/wp-elements/index.js @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import { render as baseRender } from 'preact'; + +export { h as createElement, Component } from 'preact'; + +/** + * Render element to target DOM node. + * + * This implementation is copied essentially verbatim from `preact-compat`: + * - Source: https://github.com/developit/preact-compat + * - License: MIT (https://choosealicense.com/licenses/mit/) + * + * @param {VNode} element wp-elements Element + * @param {Node} target Target DOM node + */ +export function render( element, target ) { + let previous = target && target._wpElementsRendered; + + // Ignore impossible previous renders + if ( previous && previous.parentNode !== target ) { + previous = null; + } + + // Default to first Element child + if ( ! previous ) { + previous = target.children[ 0 ]; + } + + // Remove unaffected siblings + for ( const sibling of target.childNodes ) { + if ( sibling === previous ) { + continue; + } + + target.removeChild( sibling ); + } + + const out = baseRender( element, target, previous ); + if ( target ) { + target._wpElementsRendered = out; + } +} diff --git a/tinymce-per-block/src/index.js b/tinymce-per-block/src/index.js new file mode 100644 index 0000000000000..bdb0c5846da80 --- /dev/null +++ b/tinymce-per-block/src/index.js @@ -0,0 +1,50 @@ +/** + * External dependencies + */ +import { forEach } from 'lodash'; + +/** + * Internal dependencies + */ +import * as parsers from 'parsers'; +import * as renderers from 'renderers'; +import * as serializers from 'serializers'; +import 'assets/stylesheets/main.scss'; +import 'blocks/text-block'; +import 'blocks/image-block'; + +function render( content, initialParsed = {} ) { + forEach( renderers, ( renderer, type ) => { + const parser = parsers[ type ]; + const targetNode = document.getElementById( type ); + + let parsedContent; + if ( initialParsed[ type ] ) { + parsedContent = initialParsed[ type ]; + } else if ( parser ) { + parsedContent = parser.parse( content ); + } else { + parsedContent = content; + } + + // TODO: Consider whether there's a better way to (a) account for re- + // render during focusOut of block and (b) batch accumulated changes + + function onChange( nextParsedContent ) { + const serializer = serializers[ type ]; + + let nextContent = nextParsedContent; + if ( serializer ) { + nextContent = serializer.serialize( nextContent ); + } + + render( nextContent, { + [ type ]: nextParsedContent + } ); + } + + renderer( parsedContent, targetNode, onChange ); + } ); +} + +render( window.content ); diff --git a/tinymce-per-block/src/parsers/block/grammar.js b/tinymce-per-block/src/parsers/block/grammar.js new file mode 100644 index 0000000000000..bfe3ed2c8766f --- /dev/null +++ b/tinymce-per-block/src/parsers/block/grammar.js @@ -0,0 +1,1828 @@ +/* + * Generated by PEG.js 0.10.0. + * + * http://pegjs.org/ + */ +"use strict"; + +function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); +} + +function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } +} + +peg$subclass(peg$SyntaxError, Error); + +peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + "class": function(expectation) { + var escapedParts = "", + i; + + for (i = 0; i < expectation.parts.length; i++) { + escapedParts += expectation.parts[i] instanceof Array + ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) + : classEscape(expectation.parts[i]); + } + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + }, + + any: function(expectation) { + return "any character"; + }, + + end: function(expectation) { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/\]/g, '\\]') + .replace(/\^/g, '\\^') + .replace(/-/g, '\\-') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = new Array(expected.length), + i, j; + + for (i = 0; i < expected.length; i++) { + descriptions[i] = describeExpectation(expected[i]); + } + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; +}; + +function peg$parse(input, options) { + options = options !== void 0 ? options : {}; + + var peg$FAILED = {}, + + peg$startRuleFunctions = { Document: peg$parseDocument }, + peg$startRuleFunction = peg$parseDocument, + + peg$c0 = function(ts) { return { + type: 'Text', + value: ts.join('') + } }, + peg$c1 = /^[^<]/, + peg$c2 = peg$classExpectation(["<"], true, false), + peg$c3 = function(s, t) { return t }, + peg$c4 = function(s, ts, e) { return { + type: 'WP_Block', + blockType: s.blockType, + attrs: s.attrs, + startText: s.text, + endText: e.text, + rawContent: text(), + children: ts + } }, + peg$c5 = "", + peg$c10 = peg$literalExpectation("-->", false), + peg$c11 = function(blockType, attrs) { return { + type: 'WP_Block_Start', + blockType, + attrs, + text: text() + } }, + peg$c12 = "/wp", + peg$c13 = peg$literalExpectation("/wp", false), + peg$c14 = function() { return { + type: 'WP_Block_End', + text: text() + } }, + peg$c15 = function(head, tail) { return [ head ].concat( tail ).join('') }, + peg$c16 = function(attr) { return attr }, + peg$c17 = function(as) { return as.reduce( ( attrs, [ name, value ] ) => Object.assign( + attrs, + { [ name ]: value } + ), {} ) }, + peg$c18 = ":", + peg$c19 = peg$literalExpectation(":", false), + peg$c20 = function(name, value) { return [ name, value ] }, + peg$c21 = function(head, tail) { return [ head ].concat( tail ).join('') }, + peg$c22 = peg$anyExpectation(), + peg$c23 = function(c) { return c }, + peg$c24 = function(cs) { return { + type: "HTML_Comment", + innerText: cs.join(''), + text: text() + } }, + peg$c25 = function(s, ts, e) { return { + type: 'HTML_Tag', + name: s.name, + attrs: s.attrs, + startText: s.text, + endText: e.text, + children: ts + } }, + peg$c26 = "<", + peg$c27 = peg$literalExpectation("<", false), + peg$c28 = ">", + peg$c29 = peg$literalExpectation(">", false), + peg$c30 = function(name, attrs) { return { + type: 'HTML_Tag_Open', + name, + attrs, + text: text() + } }, + peg$c31 = " peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildSimpleError(message, location) { + return new peg$SyntaxError(message, null, null, location); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError( + peg$SyntaxError.buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parseDocument() { + var s0, s1; + + s0 = []; + s1 = peg$parseToken(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parseToken(); + } + + return s0; + } + + function peg$parseToken() { + var s0, s1, s2; + + s0 = peg$parseWP_Block_Balanced(); + if (s0 === peg$FAILED) { + s0 = peg$parseWP_Block_Start(); + if (s0 === peg$FAILED) { + s0 = peg$parseWP_Block_End(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Comment(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Tag_Balanced(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Tag_Open(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Tag_Close(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = []; + s2 = peg$parseHTML_Text(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parseHTML_Text(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c0(s1); + } + s0 = s1; + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseHTML_Text() { + var s0; + + if (peg$c1.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + + return s0; + } + + function peg$parseWP_Block_Balanced() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseWP_Block_Start(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseWP_Block_End(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parseToken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseWP_Block_End(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parseToken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseWP_Block_End(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c4(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_Start() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c5) { + s1 = peg$c5; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c7) { + s3 = peg$c7; + peg$currPos += 3; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parseWP_Block_Type(); + if (s4 !== peg$FAILED) { + s5 = peg$parseWP_Block_Attribute_List(); + if (s5 !== peg$FAILED) { + s6 = peg$parse_(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c9) { + s7 = peg$c9; + peg$currPos += 3; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c11(s4, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_End() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c5) { + s1 = peg$c5; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c12) { + s3 = peg$c12; + peg$currPos += 3; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c13); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c9) { + s5 = peg$c9; + peg$currPos += 3; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c14(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_Type() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseASCII_Letter(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseASCII_AlphaNumeric(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseASCII_AlphaNumeric(); + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_Attribute_List() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = []; + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parse_(); + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseWP_Block_Attribute(); + if (s4 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c16(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = []; + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parse_(); + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseWP_Block_Attribute(); + if (s4 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c16(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c17(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseWP_Block_Attribute() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseWP_Block_Attribute_Name(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s2 = peg$c18; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parseWP_Block_Attribute_Value(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c20(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_Attribute_Name() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseASCII_Letter(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseASCII_AlphaNumeric(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseASCII_AlphaNumeric(); + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseWP_Block_Attribute_Value() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseASCII_Letter(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseASCII_AlphaNumeric(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseASCII_AlphaNumeric(); + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c21(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Comment() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c5) { + s1 = peg$c5; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 3) === peg$c9) { + s5 = peg$c9; + peg$currPos += 3; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c23(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 3) === peg$c9) { + s5 = peg$c9; + peg$currPos += 3; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c23(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c9) { + s3 = peg$c9; + peg$currPos += 3; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c24(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Tag_Balanced() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseHTML_Tag_Open(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseHTML_Tag_Close(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parseToken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseHTML_Tag_Close(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = void 0; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parseToken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseHTML_Tag_Close(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c25(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Tag_Open() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 60) { + s1 = peg$c26; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c27); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseHTML_Tag_Name(); + if (s2 !== peg$FAILED) { + s3 = peg$parseHTML_Attribute_List(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parse_(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parse_(); + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s5 = peg$c28; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c30(s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Tag_Close() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c31) { + s1 = peg$c31; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseHTML_Tag_Name(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parse_(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parse_(); + } + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s4 = peg$c28; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c33(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Tag_Name() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parseHTML_Tag_Name_Character(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parseHTML_Tag_Name_Character(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseHTML_Tag_Name_Character() { + var s0; + + s0 = peg$parseASCII_Letter(); + if (s0 === peg$FAILED) { + s0 = peg$parseASCII_Digit(); + } + + return s0; + } + + function peg$parseHTML_Attribute_List() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = []; + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parse_(); + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseHTML_Attribute_Item(); + if (s4 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c35(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = []; + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parse_(); + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseHTML_Attribute_Item(); + if (s4 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c35(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c17(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseHTML_Attribute_Item() { + var s0; + + s0 = peg$parseHTML_Attribute_Quoted(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Attribute_Unquoted(); + if (s0 === peg$FAILED) { + s0 = peg$parseHTML_Attribute_Empty(); + } + } + + return s0; + } + + function peg$parseHTML_Attribute_Empty() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseHTML_Attribute_Name(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c36(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseHTML_Attribute_Unquoted() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$parseHTML_Attribute_Name(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parse_(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parse_(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s3 = peg$c37; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parse_(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parse_(); + } + if (s4 !== peg$FAILED) { + s5 = []; + if (peg$c39.test(input.charAt(peg$currPos))) { + s6 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c40); } + } + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + if (peg$c39.test(input.charAt(peg$currPos))) { + s6 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c40); } + } + } + } else { + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c41(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseHTML_Attribute_Quoted() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$parseHTML_Attribute_Name(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parse_(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parse_(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s3 = peg$c37; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parse_(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parse_(); + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s5 = peg$c42; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s5 !== peg$FAILED) { + s6 = []; + s7 = peg$currPos; + s8 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 34) { + s9 = peg$c42; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = void 0; + } else { + peg$currPos = s8; + s8 = peg$FAILED; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s7; + s8 = peg$c44(s1, s9); + s7 = s8; + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + while (s7 !== peg$FAILED) { + s6.push(s7); + s7 = peg$currPos; + s8 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 34) { + s9 = peg$c42; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = void 0; + } else { + peg$currPos = s8; + s8 = peg$FAILED; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s7; + s8 = peg$c44(s1, s9); + s7 = s8; + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } + if (s6 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s7 = peg$c42; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c41(s1, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseHTML_Attribute_Name(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parse_(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parse_(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s3 = peg$c37; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parse_(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parse_(); + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s5 = peg$c45; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + if (s5 !== peg$FAILED) { + s6 = []; + s7 = peg$currPos; + s8 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 39) { + s9 = peg$c45; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = void 0; + } else { + peg$currPos = s8; + s8 = peg$FAILED; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s7; + s8 = peg$c44(s1, s9); + s7 = s8; + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + while (s7 !== peg$FAILED) { + s6.push(s7); + s7 = peg$currPos; + s8 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 39) { + s9 = peg$c45; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = void 0; + } else { + peg$currPos = s8; + s8 = peg$FAILED; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s7; + s8 = peg$c44(s1, s9); + s7 = s8; + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } else { + peg$currPos = s7; + s7 = peg$FAILED; + } + } + if (s6 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s7 = peg$c45; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c41(s1, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseHTML_Attribute_Name() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + if (peg$c47.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c48); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c47.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c48); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseASCII_AlphaNumeric() { + var s0; + + s0 = peg$parseASCII_Letter(); + if (s0 === peg$FAILED) { + s0 = peg$parseASCII_Digit(); + } + + return s0; + } + + function peg$parseASCII_Letter() { + var s0; + + if (peg$c49.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + + return s0; + } + + function peg$parseASCII_Digit() { + var s0; + + if (peg$c51.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c52); } + } + + return s0; + } + + function peg$parseNewline() { + var s0; + + if (peg$c53.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c54); } + } + + return s0; + } + + function peg$parse_() { + var s0; + + if (peg$c55.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c56); } + } + + return s0; + } + + function peg$parse__() { + var s0, s1; + + s0 = []; + s1 = peg$parse_(); + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parse_(); + } + } else { + s0 = peg$FAILED; + } + + return s0; + } + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } +} + +module.exports = { + SyntaxError: peg$SyntaxError, + parse: peg$parse +}; diff --git a/tinymce-per-block/src/parsers/block/index.js b/tinymce-per-block/src/parsers/block/index.js new file mode 100644 index 0000000000000..29050d4332a0b --- /dev/null +++ b/tinymce-per-block/src/parsers/block/index.js @@ -0,0 +1,4 @@ +/** + * Internal dependencies + */ +export { parse } from './grammar'; diff --git a/tinymce-per-block/src/parsers/html/index.js b/tinymce-per-block/src/parsers/html/index.js new file mode 100644 index 0000000000000..d7a988e80eeba --- /dev/null +++ b/tinymce-per-block/src/parsers/html/index.js @@ -0,0 +1 @@ +export { identity as parse } from 'lodash'; diff --git a/tinymce-per-block/src/parsers/index.js b/tinymce-per-block/src/parsers/index.js new file mode 100644 index 0000000000000..43107279ab602 --- /dev/null +++ b/tinymce-per-block/src/parsers/index.js @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import * as block from './block'; + +export { block }; diff --git a/tinymce-per-block/src/renderers/block/block-list/_style.scss b/tinymce-per-block/src/renderers/block/block-list/_style.scss new file mode 100644 index 0000000000000..d146ca5600497 --- /dev/null +++ b/tinymce-per-block/src/renderers/block/block-list/_style.scss @@ -0,0 +1,79 @@ +.block-list { + list-style: none; + padding: 0; + margin: 0; + font-size: 16px; + font-weight: 300; + line-height: 1.7; + font-family: Merriweather, Georgia, "Times New Roman", Times, serif; +} + +.block-list__block { + position: relative; + border: 2px solid transparent; + outline: none; + margin-bottom: 1rem; + padding: 0.8rem 1.2rem; + transition: 0.2s border-color; + + &:hover { + border-color: mix( $gray-light, $gray-dark-300, 80% ); + } + + &.is-focused { + border-color: $gray-dark-300; + } +} + +.block-list__block-controls { + @include animate_fade; + position: absolute; + left: -2px; + top: -30px; +} + +.block-list__block-control { + padding: 4px; + background: none; + background-color: $gray-dark-900; + border: none; + color: #fff; + cursor: pointer; + + &.is-selected { + background-color: $gray-dark-300; + } + + .dashicon { + display: block; + } +} + +.block-list__block-arrangement { + @include animate_fade; + position: absolute; + top: 0; + left: -6rem; + display: flex; + align-items: center; +} + +.block-list__type-controls { + margin-left: 0.6rem; +} + +.block-list__block-arrange-control { + display: block; + padding: 0; + border: none; + outline: none; + background: none; + color: $gray-dark-300; + cursor: pointer; + + .dashicon { + display: block; + height: 20px; + width: 20px; + } +} diff --git a/tinymce-per-block/src/renderers/block/block-list/block.js b/tinymce-per-block/src/renderers/block/block-list/block.js new file mode 100644 index 0000000000000..709714ad5b1c2 --- /dev/null +++ b/tinymce-per-block/src/renderers/block/block-list/block.js @@ -0,0 +1,113 @@ +/** + * External dependencies + */ +import { createElement, Component } from 'wp-elements'; +import { getBlock } from 'wp-blocks'; +import { size, map } from 'lodash'; +import { ArrowDownAlt2Icon, ArrowUpAlt2Icon } from 'dashicons'; +import classNames from 'classnames'; +import isEqualShallow from 'is-equal-shallow'; + +export default class BlockListBlock extends Component { + maybeFocusOut = ( event ) => { + if ( ! this.node ) { + return; + } + + if ( ! this.node.contains( event.relatedTarget ) ) { + this.props.onFocusOut( event ); + } + }; + + setRef = ( node ) => { + this.node = node; + }; + + render() { + const { node } = this.props; + const block = getBlock( node.blockType ); + if ( ! block ) { + return null; + } + + const form = block.form || block.display; + if ( ! form ) { + return null; + } + + const { isFocused } = this.props; + const classes = classNames( 'block-list__block', { + 'is-focused': isFocused + } ); + + const { onChange, tabIndex, onFocus } = this.props; + const state = { + setChildren( children ) { + onChange( { + ...node, + children + } ); + }, + setAttributes( attributes ) { + if ( isEqualShallow( attributes, node.attrs ) ) { + return; + } + + onChange( { + ...node, + attrs: { + ...node.attrs, + ...attributes + } + } ); + } + }; + + return ( +
+ { form( node, state ) } + { isFocused && size( block.controls ) > 0 && ( +
+ { map( block.controls, ( control ) => { + const controlClasses = classNames( 'block-list__block-control', { + 'is-selected': control.isSelected( node ) + } ); + + return ( + + ); + } ) } +
+ ) } + { isFocused && ( +
+
+ + +
+ { block.icon && ( +
+ +
+ ) } +
+ ) } +
+ ); + } +} diff --git a/tinymce-per-block/src/renderers/block/block-list/index.js b/tinymce-per-block/src/renderers/block/block-list/index.js new file mode 100644 index 0000000000000..911dd95df10b7 --- /dev/null +++ b/tinymce-per-block/src/renderers/block/block-list/index.js @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; +import { map } from 'lodash'; + +/** + * Internal dependencies + */ +import BlockListBlock from './block'; + +function BlockList( { nodes, focusIndex, onFocusIndexChange, onChange } ) { + function onNodeChange( index, nextNode ) { + const nextNodes = [ ...nodes ]; + nextNodes[ index ] = { + ...nextNodes[ index ], + ...nextNode + }; + + onChange( nextNodes ); + } + + return ( +
+ { map( nodes, ( node, index ) => { + const isFocused = index === focusIndex; + + return ( + onFocusIndexChange( index ) } + onFocusOut={ () => onFocusIndexChange( null ) } + onChange={ ( nextNode ) => onNodeChange( index, nextNode ) } + node={ node } /> + ); + } ) } +
+ ); +} + +export default BlockList; diff --git a/tinymce-per-block/src/renderers/block/index.js b/tinymce-per-block/src/renderers/block/index.js new file mode 100644 index 0000000000000..0a861cceb0720 --- /dev/null +++ b/tinymce-per-block/src/renderers/block/index.js @@ -0,0 +1,36 @@ +/** + * External dependencies + */ +import { render, createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import BlockList from './block-list'; + +// TODO: Consider managing block state in more organized fashion (Redux?). Goal +// is to allow focus index to be preserved between rerender by parent (change). + +let focusIndex = null; + +function renderToTarget( props, target ) { + render( + , + target + ); +} + +export default function( nodes, target, onChange ) { + const props = { + nodes, + onChange, + onFocusIndexChange( index ) { + focusIndex = index; + renderToTarget( props, target ); + } + }; + + renderToTarget( props, target ); +} diff --git a/tinymce-per-block/src/renderers/html/html-editor/_style.scss b/tinymce-per-block/src/renderers/html/html-editor/_style.scss new file mode 100644 index 0000000000000..be33077bc4230 --- /dev/null +++ b/tinymce-per-block/src/renderers/html/html-editor/_style.scss @@ -0,0 +1,23 @@ +.html-editor { + box-sizing: border-box; + display: block; + width: 100%; + height: 100%; + resize: none; + border: none; + border: 2px solid transparent; + outline: none; + padding: 0.8rem 1.2rem; + transition: 0.2s border-color; + font-family: "Courier 10 Pitch", Courier, monospace; + font-size: 14px; + line-height: 1.3; + + &:hover { + border-color: mix( $gray-light, $gray-dark-300, 80% ); + } + + &:focus { + border-color: $gray-dark-300; + } +} diff --git a/tinymce-per-block/src/renderers/html/html-editor/index.js b/tinymce-per-block/src/renderers/html/html-editor/index.js new file mode 100644 index 0000000000000..c808ca141e517 --- /dev/null +++ b/tinymce-per-block/src/renderers/html/html-editor/index.js @@ -0,0 +1,14 @@ +/** + * External dependencies + */ +import { createElement } from 'wp-elements'; + +export default function HtmlEditor( { value, onChange } ) { + return ( + + ); +} diff --git a/tinymce-per-block/src/renderers/html/index.js b/tinymce-per-block/src/renderers/html/index.js new file mode 100644 index 0000000000000..ff5916cc18e97 --- /dev/null +++ b/tinymce-per-block/src/renderers/html/index.js @@ -0,0 +1,18 @@ +/** + * External dependencies + */ +import { render, createElement } from 'wp-elements'; + +/** + * Internal dependencies + */ +import HtmlEditor from './html-editor'; + +export default function( markup, target, onChange ) { + render( + , + target + ); +} diff --git a/tinymce-per-block/src/renderers/index.js b/tinymce-per-block/src/renderers/index.js new file mode 100644 index 0000000000000..320d43e0e62bd --- /dev/null +++ b/tinymce-per-block/src/renderers/index.js @@ -0,0 +1,2 @@ +export { default as block } from './block'; +export { default as html } from './html'; diff --git a/tinymce-per-block/src/serializers/block/index.js b/tinymce-per-block/src/serializers/block/index.js new file mode 100644 index 0000000000000..aa9037f8b1b35 --- /dev/null +++ b/tinymce-per-block/src/serializers/block/index.js @@ -0,0 +1,33 @@ +/** + * External dependencies + */ +import { map } from 'lodash'; + +export function serialize( nodes ) { + return map( nodes, ( node ) => { + switch ( node.type ) { + case 'WP_Block': + return ( + '' + + serialize( node.children ) + + '' + ); + + case 'HTML_Tag': + return [ + node.startText, + serialize( node.children ), + node.endText + ].join( '' ); + + case 'HTML_Tag_Open': + return node.text; + } + + return node.value; + } ).join( '' ); +} diff --git a/tinymce-per-block/src/serializers/index.js b/tinymce-per-block/src/serializers/index.js new file mode 100644 index 0000000000000..43107279ab602 --- /dev/null +++ b/tinymce-per-block/src/serializers/index.js @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import * as block from './block'; + +export { block }; diff --git a/tinymce-per-block/webpack.config.js b/tinymce-per-block/webpack.config.js new file mode 100644 index 0000000000000..2400f4701d5c0 --- /dev/null +++ b/tinymce-per-block/webpack.config.js @@ -0,0 +1,59 @@ +/** + * External dependencies + */ + +const webpack = require( 'webpack' ); + +const config = module.exports = { + entry: { + app: './src/index.js' + }, + output: { + filename: 'build/[name].js', + path: __dirname + }, + resolve: { + modules: [ + 'src', + 'src/external', + 'node_modules' + ] + }, + externals: [ + 'tinymce' + ], + module: { + rules: [ + { + test: /\.js$/, + use: 'babel-loader' + }, + { + test: /\.s?css$/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader' }, + { loader: 'postcss-loader' }, + { loader: 'sass-loader' } + ] + } + ] + }, + plugins: [ + new webpack.LoaderOptionsPlugin( { + minimize: process.env.NODE_ENV === 'production', + debug: process.env.NODE_ENV !== 'production', + options: { + postcss: [ + require( 'autoprefixer' ) + ] + } + } ) + ] +}; + +if ( 'production' === process.env.NODE_ENV ) { + config.plugins.push( new webpack.optimize.UglifyJsPlugin() ); +} else { + config.devtool = 'source-map'; +} diff --git a/tinymce/index.html b/tinymce/index.html new file mode 100644 index 0000000000000..0412e538e4f69 --- /dev/null +++ b/tinymce/index.html @@ -0,0 +1,16 @@ + + + + TinyMCE Formatting Demo + + + + + + + +
+

Many entrepreneurs idolize Steve Jobs. He’s such a perfectionist, they say. Nothing leaves the doors of 1 Infinite Loop in Cupertino without a polish and finish that makes geeks everywhere drool. No compromise!

+
+ + diff --git a/tinymce/style.css b/tinymce/style.css new file mode 100644 index 0000000000000..a4f49af8fe675 --- /dev/null +++ b/tinymce/style.css @@ -0,0 +1,21 @@ +/** + * Basic + */ + +html, +body { + margin: 0; + padding: 0; + height: 100%; +} + +* { + box-sizing: border-box; +} + +body { + font: 13px/1.8 -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif; + max-width: 720px; + margin: 60px auto; + color: #12181e; +}