From 75330f55e6628938400a9f7d808d65678cf151bb Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Fri, 23 Jun 2017 22:33:30 -0400 Subject: [PATCH 1/5] Allow build process to split css files for front end and backend. Related to #963. This PR splits up some of our CSS build process to have seperate files generated for blocks and editor specific styles of blocks. Block specific styles are now loaded both on the front-end and back end. Styles that should appear on both are currently in a block.scss file. Styles added: wp-edit-blocks: blocks/build/edit-block.css wp-blocks: blocks/build/style.css Caveats: It was suggested that the reverse be done, by using an edit.scss to hold editor specific styles. This seemed pretty daunting a task to me and I did not fully grasp what benefit that would bring over this approach either. ** Testing Instructions ** build the files via `npm run build` or `npm run dev` Verify that the gallery columns work both on the front end as well as back end. Verify that the drop cap style still works on the back end. --- blocks/editable/block.scss | 16 ++++++++ blocks/editable/index.js | 1 + blocks/library/gallery/block.scss | 58 ++++++++++++++++++++++++++ blocks/library/gallery/index.js | 1 + blocks/library/gallery/style.scss | 60 --------------------------- lib/client-assets.php | 17 +++++++- webpack.config.js | 68 +++++++++++++++++++++++++++++-- 7 files changed, 156 insertions(+), 65 deletions(-) create mode 100644 blocks/editable/block.scss create mode 100644 blocks/library/gallery/block.scss diff --git a/blocks/editable/block.scss b/blocks/editable/block.scss new file mode 100644 index 00000000000000..e62b5016ddea79 --- /dev/null +++ b/blocks/editable/block.scss @@ -0,0 +1,16 @@ +.drop-cap-true .blocks-editable__tinymce:not( :focus ) { + &:first-letter { + float: left; + font-size: 4.1em; + line-height: 0.7; + font-family: serif; + font-weight: bold; + margin: .07em .23em 0 0; + text-transform: uppercase; + font-style: normal; + } +} + +.drop-cap-true:not( :focus ) { + overflow: hidden; +} diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 4b66cfe7db52c4..59996cadb4af28 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -18,6 +18,7 @@ import { BACKSPACE, DELETE, ENTER } from 'utils/keycodes'; * Internal dependencies */ import './style.scss'; +import './block.scss'; import FormatToolbar from './format-toolbar'; import TinyMCE from './tinymce'; diff --git a/blocks/library/gallery/block.scss b/blocks/library/gallery/block.scss new file mode 100644 index 00000000000000..beffdefd70155b --- /dev/null +++ b/blocks/library/gallery/block.scss @@ -0,0 +1,58 @@ +.wp-block-gallery { + display: flex; + flex-wrap: wrap; + + &:not( .components-placeholder ) { + margin-right: -16px; + margin-bottom: -16px; + } + + .blocks-gallery-image { + flex-grow: 1; + margin: 0 16px 16px 0; + + img { + max-width: 100%; + } + } + + // Cropped + &.is-cropped .blocks-gallery-image { + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + // Alas, IE11+ doesn't support object-fit + _:-ms-lang(x), img { + height: auto; + width: auto; + } + } + + &.columns-1 figure { + width: calc(100% / 1 - 2 * 8px); + } + &.columns-2 figure { + width: calc(100% / 2 - 3 * 8px); + } + &.columns-3 figure { + width: calc(100% / 3 - 4 * 8px); + } + &.columns-4 figure { + width: calc(100% / 4 - 5 * 8px); + } + &.columns-5 figure { + width: calc(100% / 5 - 6 * 8px); + } + &.columns-6 figure { + width: calc(100% / 6 - 7 * 8px); + } + &.columns-7 figure { + width: calc(100% / 7 - 8 * 8px); + } + &.columns-8 figure { + width: calc(100% / 8 - 9 * 8px); + } +} diff --git a/blocks/library/gallery/index.js b/blocks/library/gallery/index.js index a4b1d13a85d9b0..358429ad7e1ac0 100644 --- a/blocks/library/gallery/index.js +++ b/blocks/library/gallery/index.js @@ -8,6 +8,7 @@ import { Toolbar, Placeholder } from 'components'; * Internal dependencies */ import './style.scss'; +import './block.scss'; import { registerBlockType, query as hpq } from '../../api'; import MediaUploadButton from '../../media-upload-button'; import InspectorControls from '../../inspector-controls'; diff --git a/blocks/library/gallery/style.scss b/blocks/library/gallery/style.scss index e4b7d4d33bd012..79ba13dfe958fe 100644 --- a/blocks/library/gallery/style.scss +++ b/blocks/library/gallery/style.scss @@ -1,63 +1,3 @@ - -.wp-block-gallery { - display: flex; - flex-wrap: wrap; - - &:not( .components-placeholder ) { - margin-right: -16px; - margin-bottom: -16px; - } - - .blocks-gallery-image { - flex-grow: 1; - margin: 0 16px 16px 0; - - img { - max-width: 100%; - } - } - - // Cropped - &.is-cropped .blocks-gallery-image { - img { - width: 100%; - height: 100%; - object-fit: cover; - } - - // Alas, IE11+ doesn't support object-fit - _:-ms-lang(x), img { - height: auto; - width: auto; - } - } - - &.columns-1 figure { - width: calc(100% / 1 - 2 * 8px); - } - &.columns-2 figure { - width: calc(100% / 2 - 3 * 8px); - } - &.columns-3 figure { - width: calc(100% / 3 - 4 * 8px); - } - &.columns-4 figure { - width: calc(100% / 4 - 5 * 8px); - } - &.columns-5 figure { - width: calc(100% / 5 - 6 * 8px); - } - &.columns-6 figure { - width: calc(100% / 6 - 7 * 8px); - } - &.columns-7 figure { - width: calc(100% / 7 - 8 * 8px); - } - &.columns-8 figure { - width: calc(100% / 8 - 9 * 8px); - } -} - .wp-block-gallery.is-placeholder { margin: -15px; padding: 6em 0; diff --git a/lib/client-assets.php b/lib/client-assets.php index 2942d0283d61a2..d13492e66f0058 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -120,6 +120,12 @@ function gutenberg_register_scripts_and_styles() { array(), filemtime( gutenberg_dir_path() . 'blocks/build/style.css' ) ); + wp_register_style( + 'wp-edit-blocks', + gutenberg_url( 'blocks/build/edit-blocks.css' ), + array(), + filemtime( gutenberg_dir_path() . 'blocks/build/edit-blocks.css' ) + ); } add_action( 'init', 'gutenberg_register_scripts_and_styles' ); @@ -453,8 +459,17 @@ function gutenberg_scripts_and_styles( $hook ) { wp_enqueue_style( 'wp-editor', gutenberg_url( 'editor/build/style.css' ), - array( 'wp-components', 'wp-blocks' ), + array( 'wp-components', 'wp-blocks', 'wp-edit-blocks' ), filemtime( gutenberg_dir_path() . 'editor/build/style.css' ) ); } add_action( 'admin_enqueue_scripts', 'gutenberg_scripts_and_styles' ); + +/** + * Handles the enqueueing of front end scripts and styles from Gutenberg. + */ +function gutenberg_frontend_scripts_and_styles() { + // Enqueue basic styles built out of Gutenberg through npm build. + wp_enqueue_style( 'wp-blocks' ); +} +add_action( 'wp_enqueue_scripts', 'gutenberg_frontend_scripts_and_styles' ); diff --git a/webpack.config.js b/webpack.config.js index c20462f582084c..3000ca4ae6a139 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,6 +6,21 @@ const glob = require( 'glob' ); const webpack = require( 'webpack' ); const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); +// Main CSS loader for everything but blocks.. +const MainCSSExtractTextPlugin = new ExtractTextPlugin( { + filename: './[name]/build/style.css', +} ); + +// CSS loader for styles specific to block editing. +const EditBlocksCSSPlugin = new ExtractTextPlugin( { + filename: './blocks/build/edit-blocks.css', +} ); + +// CSS loader for styles specific to blocks in general. +const BlocksCSSPlugin = new ExtractTextPlugin( { + filename: './blocks/build/style.css', +} ); + const entryPointNames = [ 'element', 'i18n', @@ -64,9 +79,54 @@ const config = { exclude: /node_modules/, use: 'babel-loader', }, + { + test: /block\.s?css$/, + use: BlocksCSSPlugin.extract( { + use: [ + { loader: 'raw-loader' }, + { loader: 'postcss-loader' }, + { + loader: 'sass-loader', + query: { + includePaths: [ 'editor/assets/stylesheets' ], + data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', + outputStyle: 'production' === process.env.NODE_ENV ? + 'compressed' : 'nested', + }, + }, + ], + } ), + }, { test: /\.s?css$/, - use: ExtractTextPlugin.extract( { + include: [ + /blocks/, + ], + exclude: [ + /block\.s?css$/, + ], + use: EditBlocksCSSPlugin.extract( { + use: [ + { loader: 'raw-loader' }, + { loader: 'postcss-loader' }, + { + loader: 'sass-loader', + query: { + includePaths: [ 'editor/assets/stylesheets' ], + data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', + outputStyle: 'production' === process.env.NODE_ENV ? + 'compressed' : 'nested', + }, + }, + ], + } ), + }, + { + test: /\.s?css$/, + exclude: [ + /blocks/, + ], + use: MainCSSExtractTextPlugin.extract( { use: [ { loader: 'raw-loader' }, { loader: 'postcss-loader' }, @@ -88,9 +148,9 @@ const config = { new webpack.DefinePlugin( { 'process.env.NODE_ENV': JSON.stringify( process.env.NODE_ENV || 'development' ), } ), - new ExtractTextPlugin( { - filename: './[name]/build/style.css', - } ), + BlocksCSSPlugin, + EditBlocksCSSPlugin, + MainCSSExtractTextPlugin, new webpack.LoaderOptionsPlugin( { minimize: process.env.NODE_ENV === 'production', debug: process.env.NODE_ENV !== 'production', From 82e6d90b7a5f431e6381416572d7002cc3c989c5 Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Mon, 26 Jun 2017 14:04:13 -0400 Subject: [PATCH 2/5] Changes related to feedback. Adding documentation about the build process, updating variable names, reducing duplication. Making the drop cap style work on the front end as well as gallery styles. --- blocks/editable/index.js | 1 - blocks/{editable => library/text}/block.scss | 4 +- blocks/library/text/index.js | 15 +++- docs/coding-guidelines.md | 10 +++ webpack.config.js | 80 +++++++------------- 5 files changed, 53 insertions(+), 57 deletions(-) rename blocks/{editable => library/text}/block.scss (71%) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 59996cadb4af28..4b66cfe7db52c4 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -18,7 +18,6 @@ import { BACKSPACE, DELETE, ENTER } from 'utils/keycodes'; * Internal dependencies */ import './style.scss'; -import './block.scss'; import FormatToolbar from './format-toolbar'; import TinyMCE from './tinymce'; diff --git a/blocks/editable/block.scss b/blocks/library/text/block.scss similarity index 71% rename from blocks/editable/block.scss rename to blocks/library/text/block.scss index e62b5016ddea79..947c3351c6f5ba 100644 --- a/blocks/editable/block.scss +++ b/blocks/library/text/block.scss @@ -1,4 +1,4 @@ -.drop-cap-true .blocks-editable__tinymce:not( :focus ) { +.has-drop-cap { &:first-letter { float: left; font-size: 4.1em; @@ -11,6 +11,6 @@ } } -.drop-cap-true:not( :focus ) { +.has-drop-cap:not( :focus ) { overflow: hidden; } diff --git a/blocks/library/text/index.js b/blocks/library/text/index.js index acdd6740d1b77c..9eff0e285b655a 100644 --- a/blocks/library/text/index.js +++ b/blocks/library/text/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -7,6 +12,7 @@ import { concatChildren } from 'element'; /** * Internal dependencies */ +import './block.scss'; import { registerBlockType, createBlock, query as hpq, setDefaultBlock } from '../../api'; import AlignmentToolbar from '../../alignment-toolbar'; import BlockControls from '../../block-controls'; @@ -85,13 +91,16 @@ registerBlockType( 'core/text', { }, save( { attributes } ) { - const { align, content } = attributes; + const { align, content, dropCap } = attributes; + const cssClassNames = classnames( { + 'has-drop-cap': dropCap, + } ); if ( ! align ) { - return

{ content }

; + return

{ content }

; } - return

{ content }

; + return

{ content }

; }, } ); diff --git a/docs/coding-guidelines.md b/docs/coding-guidelines.md index 3bc74b444c4ce0..8032bef4130d63 100644 --- a/docs/coding-guidelines.md +++ b/docs/coding-guidelines.md @@ -32,6 +32,16 @@ In all of the above cases, except in separating the top-level element from its d You may observe that these conventions adhere closely to the [BEM (Blocks, Elements, Modifiers)](http://getbem.com/introduction/) CSS methodology, with minor adjustments to the application of modifiers. +#### SCSS File Naming Conventions for Blocks + +The build process will split SCSS from within the blocks library directory into two separate CSS files when Webpack runs. + +Styles placed in a block.scss file will be built into `blocks/build/style.css`, to load on the front end theme as well as in the editor. + +All other SCSS files will be built into `blocks/build/edit-blocks.css`, to load **only in the editor**. + +Examples of styles that appear in both the theme and the editor include gallery columns and drop caps. + ## JavaScript ### Imports diff --git a/webpack.config.js b/webpack.config.js index 3000ca4ae6a139..2648adc0bd2481 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,20 +7,37 @@ const webpack = require( 'webpack' ); const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); // Main CSS loader for everything but blocks.. -const MainCSSExtractTextPlugin = new ExtractTextPlugin( { +const mainCSSExtractTextPlugin = new ExtractTextPlugin( { filename: './[name]/build/style.css', } ); // CSS loader for styles specific to block editing. -const EditBlocksCSSPlugin = new ExtractTextPlugin( { +const editBlocksCSSPlugin = new ExtractTextPlugin( { filename: './blocks/build/edit-blocks.css', } ); // CSS loader for styles specific to blocks in general. -const BlocksCSSPlugin = new ExtractTextPlugin( { +const blocksCSSPlugin = new ExtractTextPlugin( { filename: './blocks/build/style.css', } ); +// Configuration for the ExtractTextPlugin. +const extractConfig = { + use: [ + { loader: 'raw-loader' }, + { loader: 'postcss-loader' }, + { + loader: 'sass-loader', + query: { + includePaths: [ 'editor/assets/stylesheets' ], + data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', + outputStyle: 'production' === process.env.NODE_ENV ? + 'compressed' : 'nested', + }, + }, + ], +}; + const entryPointNames = [ 'element', 'i18n', @@ -81,21 +98,10 @@ const config = { }, { test: /block\.s?css$/, - use: BlocksCSSPlugin.extract( { - use: [ - { loader: 'raw-loader' }, - { loader: 'postcss-loader' }, - { - loader: 'sass-loader', - query: { - includePaths: [ 'editor/assets/stylesheets' ], - data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', - outputStyle: 'production' === process.env.NODE_ENV ? - 'compressed' : 'nested', - }, - }, - ], - } ), + include: [ + /blocks/, + ], + use: blocksCSSPlugin.extract( extractConfig ), }, { test: /\.s?css$/, @@ -105,42 +111,14 @@ const config = { exclude: [ /block\.s?css$/, ], - use: EditBlocksCSSPlugin.extract( { - use: [ - { loader: 'raw-loader' }, - { loader: 'postcss-loader' }, - { - loader: 'sass-loader', - query: { - includePaths: [ 'editor/assets/stylesheets' ], - data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', - outputStyle: 'production' === process.env.NODE_ENV ? - 'compressed' : 'nested', - }, - }, - ], - } ), + use: editBlocksCSSPlugin.extract( extractConfig ), }, { test: /\.s?css$/, exclude: [ /blocks/, ], - use: MainCSSExtractTextPlugin.extract( { - use: [ - { loader: 'raw-loader' }, - { loader: 'postcss-loader' }, - { - loader: 'sass-loader', - query: { - includePaths: [ 'editor/assets/stylesheets' ], - data: '@import "variables"; @import "mixins"; @import "animations";@import "z-index";', - outputStyle: 'production' === process.env.NODE_ENV ? - 'compressed' : 'nested', - }, - }, - ], - } ), + use: mainCSSExtractTextPlugin.extract( extractConfig ), }, ], }, @@ -148,9 +126,9 @@ const config = { new webpack.DefinePlugin( { 'process.env.NODE_ENV': JSON.stringify( process.env.NODE_ENV || 'development' ), } ), - BlocksCSSPlugin, - EditBlocksCSSPlugin, - MainCSSExtractTextPlugin, + blocksCSSPlugin, + editBlocksCSSPlugin, + mainCSSExtractTextPlugin, new webpack.LoaderOptionsPlugin( { minimize: process.env.NODE_ENV === 'production', debug: process.env.NODE_ENV !== 'production', From 34079b2ebc9485205d9eaf5003d2aed3fd9c9e43 Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Mon, 26 Jun 2017 15:46:33 -0400 Subject: [PATCH 3/5] Fix Test Fixing test to not include empty class property. --- blocks/library/text/index.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/blocks/library/text/index.js b/blocks/library/text/index.js index 9eff0e285b655a..9131836aba53d1 100644 --- a/blocks/library/text/index.js +++ b/blocks/library/text/index.js @@ -96,6 +96,15 @@ registerBlockType( 'core/text', { 'has-drop-cap': dropCap, } ); + // If no classes are present don't add empty attribute. + if ( cssClassNames.length === 0 ) { + if ( ! align ) { + return

{ content }

; + } + + return

{ content }

; + } + if ( ! align ) { return

{ content }

; } From 68c9c57d012ef31bb53a6b9657f559a1698250cd Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Mon, 26 Jun 2017 22:45:27 -0400 Subject: [PATCH 4/5] Clean up text block save method. --- blocks/library/text/index.js | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/blocks/library/text/index.js b/blocks/library/text/index.js index 9131836aba53d1..89302a507a1d67 100644 --- a/blocks/library/text/index.js +++ b/blocks/library/text/index.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ @@ -92,24 +87,13 @@ registerBlockType( 'core/text', { save( { attributes } ) { const { align, content, dropCap } = attributes; - const cssClassNames = classnames( { - 'has-drop-cap': dropCap, - } ); - - // If no classes are present don't add empty attribute. - if ( cssClassNames.length === 0 ) { - if ( ! align ) { - return

{ content }

; - } - - return

{ content }

; - } + const className = dropCap ? 'has-drop-cap' : undefined; if ( ! align ) { - return

{ content }

; + return

{ content }

; } - return

{ content }

; + return

{ content }

; }, } ); From 4b5f5faacc7eea39a287d323782b2274848212f2 Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Wed, 28 Jun 2017 17:35:27 -0400 Subject: [PATCH 5/5] Updating with minor fixes Changing a ternary operator into an && statement. Adding a p.has-drop-cap as the selector instead of just .has-drop-cap. --- blocks/library/text/block.scss | 4 ++-- blocks/library/text/index.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blocks/library/text/block.scss b/blocks/library/text/block.scss index 947c3351c6f5ba..1cc6bd7b2ff4da 100644 --- a/blocks/library/text/block.scss +++ b/blocks/library/text/block.scss @@ -1,4 +1,4 @@ -.has-drop-cap { +p.has-drop-cap { &:first-letter { float: left; font-size: 4.1em; @@ -11,6 +11,6 @@ } } -.has-drop-cap:not( :focus ) { +p.has-drop-cap:not( :focus ) { overflow: hidden; } diff --git a/blocks/library/text/index.js b/blocks/library/text/index.js index 89302a507a1d67..3e1f27aaba9cd2 100644 --- a/blocks/library/text/index.js +++ b/blocks/library/text/index.js @@ -87,7 +87,7 @@ registerBlockType( 'core/text', { save( { attributes } ) { const { align, content, dropCap } = attributes; - const className = dropCap ? 'has-drop-cap' : undefined; + const className = dropCap && 'has-drop-cap'; if ( ! align ) { return

{ content }

;