Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gutenberg: start editor shell in Calypso #26438

Merged
merged 13 commits into from
Aug 10, 2018
35 changes: 35 additions & 0 deletions assets/stylesheets/sections/gutenberg-editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,39 @@
@import '../shared/mixins/placeholder';
@import '../shared/typography';

// Editor package styles
@import '../../../node_modules/@wordpress/editor/build-style/style';

// Calypso specific Gutenberg editor styles
@import 'gutenberg/editor/style';

// Core blocks styles
@import 'gutenberg/editor/core-blocks/paragraph/style';
@import 'gutenberg/editor/core-blocks/heading/editor';

// Edit-post components styles
@import 'gutenberg/editor/edit-post/assets/stylesheets/colors';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SCSS variables and helpers from the assets folder could probably be published to npm as its own package. What do you think?

Copy link
Member Author

@vindl vindl Aug 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably help us in the short term, but given that we are supposed to re-implement Calypso specific versions of edit post components, I'm not sure if we'll be reusing them in the long run.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not worth the effort then

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on if core wants to eventually publish edit-post we'll untangle this in a bit otherwise in follow up PRs.

@import 'gutenberg/editor/edit-post/assets/stylesheets/variables';
@import 'gutenberg/editor/edit-post/assets/stylesheets/mixins';
@import 'gutenberg/editor/edit-post/assets/stylesheets/breakpoints';
@import 'gutenberg/editor/edit-post/assets/stylesheets/animations';
@import 'gutenberg/editor/edit-post/assets/stylesheets/z-index';
@import 'gutenberg/editor/edit-post/assets/stylesheets/main';
@import 'gutenberg/editor/edit-post/components/meta-boxes/meta-boxes-area/style';
@import 'gutenberg/editor/edit-post/components/text-editor/style';
@import 'gutenberg/editor/edit-post/components/layout/style';
@import 'gutenberg/editor/edit-post/components/sidebar/last-revision/style';
@import 'gutenberg/editor/edit-post/components/sidebar/post-visibility/style';
@import 'gutenberg/editor/edit-post/components/sidebar/style';
@import 'gutenberg/editor/edit-post/components/sidebar/post-author/style';
@import 'gutenberg/editor/edit-post/components/sidebar/post-status/style';
@import 'gutenberg/editor/edit-post/components/sidebar/settings-header/style';
@import 'gutenberg/editor/edit-post/components/sidebar/post-schedule/style';
@import 'gutenberg/editor/edit-post/components/sidebar/sidebar-header/style';
@import 'gutenberg/editor/edit-post/components/sidebar/post-trash/style';
@import 'gutenberg/editor/edit-post/components/sidebar/block-sidebar/style';
@import 'gutenberg/editor/edit-post/components/visual-editor/style';
@import 'gutenberg/editor/edit-post/components/header/style';
@import 'gutenberg/editor/edit-post/components/header/header-toolbar/style';
@import 'gutenberg/editor/edit-post/components/header/more-menu/style';
@import 'gutenberg/editor/edit-post/components/header/pinned-plugins/style';
80 changes: 80 additions & 0 deletions client/gutenberg/editor/core-blocks/heading/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* External dependencies
*/
import React from 'react';
import { range } from 'lodash';

/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { Fragment } from '@wordpress/element';
import { PanelBody, Toolbar } from '@wordpress/components';
import { createBlock } from '@wordpress/blocks';
import { RichText, BlockControls, InspectorControls, AlignmentToolbar } from '@wordpress/editor';

export default function HeadingEdit( {
attributes,
setAttributes,
mergeBlocks,
insertBlocksAfter,
onReplace,
className,
} ) {
const { align, content, level, placeholder } = attributes;
const tagName = 'h' + level;

function createLevelControl( targetLevel ) {
return {
icon: 'heading',
// translators: %s: heading level e.g: "1", "2", "3"
title: sprintf( __( 'Heading %d' ), targetLevel ),
isActive: targetLevel === level,
onClick: () => setAttributes( { level: targetLevel } ),
subscript: String( targetLevel ),
};
}

return (
<Fragment>
<BlockControls>
<Toolbar controls={ range( 2, 5 ).map( createLevelControl ) } />
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Heading Settings' ) }>
<p>{ __( 'Level' ) }</p>
<Toolbar controls={ range( 1, 7 ).map( createLevelControl ) } />
<p>{ __( 'Text Alignment' ) }</p>
<AlignmentToolbar
value={ align }
onChange={ ( nextAlign ) => {
setAttributes( { align: nextAlign } );
} }
/>
</PanelBody>
</InspectorControls>
<RichText
wrapperClassName="wp-block-heading"
tagName={ tagName }
value={ content }
onChange={ ( value ) => setAttributes( { content: value } ) }
onMerge={ mergeBlocks }
onSplit={
insertBlocksAfter ?
( before, after, ...blocks ) => {
setAttributes( { content: before } );
insertBlocksAfter( [
...blocks,
createBlock( 'core/paragraph', { content: after } ),
] );
} :
undefined
}
onRemove={ () => onReplace( [] ) }
style={ { textAlign: align } }
className={ className }
placeholder={ placeholder || __( 'Write heading…' ) }
/>
</Fragment>
);
}
46 changes: 46 additions & 0 deletions client/gutenberg/editor/core-blocks/heading/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.wp-block-heading {
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}

// These follow a Major Third type scale
h1 {
font-size: 2.44em;
}

h2 {
font-size: 1.95em;
}

h3 {
font-size: 1.56em;
}

h4 {
font-size: 1.25em;
}

h5 {
font-size: 1em;
}

h6 {
font-size: 0.8em;
}

// Adjust line spacing for larger headings.
h1.editor-rich-text__tinymce,
h2.editor-rich-text__tinymce,
h3.editor-rich-text__tinymce {
line-height: 1.4;
}

h4.editor-rich-text__tinymce {
line-height: 1.5;
}
}
192 changes: 192 additions & 0 deletions client/gutenberg/editor/core-blocks/heading/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/**
* External dependencies
*/
import React from 'react';
import { omit } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
createBlock,
getPhrasingContentSchema,
getBlockAttributes,
getBlockType,
children,
} from '@wordpress/blocks';
import { RichText } from '@wordpress/editor';

/**
* Internal dependencies
*/
import edit from './edit';

/**
* Given a node name string for a heading node, returns its numeric level.
*
* @param {string} nodeName Heading node name.
*
* @return {number} Heading level.
*/
export function getLevelFromHeadingNodeName( nodeName ) {
return Number( nodeName.substr( 1 ) );
}

const supports = {
className: false,
anchor: true,
};

const schema = {
content: {
type: 'array',
source: 'children',
selector: 'h1,h2,h3,h4,h5,h6',
},
level: {
type: 'number',
default: 2,
},
align: {
type: 'string',
},
placeholder: {
type: 'string',
},
};

export const name = 'core/heading';

export const settings = {
title: __( 'Heading' ),

description: __( 'Insert a headline above your post or page content.' ),

icon: 'heading',

category: 'common',

keywords: [ __( 'title' ), __( 'subtitle' ) ],

supports,

attributes: schema,

transforms: {
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( { content } ) => {
return createBlock( 'core/heading', {
content,
} );
},
},
{
type: 'raw',
selector: 'h1,h2,h3,h4,h5,h6',
schema: {
h1: { children: getPhrasingContentSchema() },
h2: { children: getPhrasingContentSchema() },
h3: { children: getPhrasingContentSchema() },
h4: { children: getPhrasingContentSchema() },
h5: { children: getPhrasingContentSchema() },
h6: { children: getPhrasingContentSchema() },
},
transform( node ) {
return createBlock( 'core/heading', {
...getBlockAttributes(
getBlockType( 'core/heading' ),
node.outerHTML
),
level: getLevelFromHeadingNodeName( node.nodeName ),
} );
},
},
{
type: 'pattern',
regExp: /^(#{2,6})\s/,
transform: ( { content, match } ) => {
const level = match[ 1 ].length;

return createBlock( 'core/heading', {
level,
content,
} );
},
},
],
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( { content } ) => {
return createBlock( 'core/paragraph', {
content,
} );
},
},
],
},

deprecated: [
{
supports,
attributes: {
...omit( schema, [ 'level' ] ),
nodeName: {
type: 'string',
source: 'property',
selector: 'h1,h2,h3,h4,h5,h6',
property: 'nodeName',
default: 'H2',
},
},
migrate( attributes ) {
const { nodeName, ...migratedAttributes } = attributes;

return {
...migratedAttributes,
level: getLevelFromHeadingNodeName( nodeName ),
};
},
save( { attributes } ) {
const { align, nodeName, content } = attributes;

return (
<RichText.Content
tagName={ nodeName.toLowerCase() }
style={ { textAlign: align } }
value={ content }
/>
);
},
},
],

merge( attributes, attributesToMerge ) {
return {
content: children.concat(
attributes.content,
attributesToMerge.content
),
};
},

edit,

save( { attributes } ) {
const { align, level, content } = attributes;
const tagName = 'h' + level;

return (
<RichText.Content
tagName={ tagName }
style={ { textAlign: align } }
value={ content }
/>
);
},
};
Loading