Skip to content

Commit

Permalink
Merge branch 'master' into fix/arrow-key-into-textarea
Browse files Browse the repository at this point in the history
  • Loading branch information
tiny-james committed Oct 30, 2017
2 parents fd5a4ab + 1b2c770 commit ed9f49e
Show file tree
Hide file tree
Showing 87 changed files with 1,997 additions and 1,064 deletions.
21 changes: 18 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,22 @@
"constructor-super": "error",
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": "error",
"func-call-spacing": "error",
"indent": [ "error", "tab", { "SwitchCase": 1 } ],
"jsx-a11y/label-has-for": [ "error", {
"required": "id"
} ],
"jsx-a11y/media-has-caption": "off",
"jsx-a11y/no-noninteractive-tabindex": "off",
"jsx-a11y/role-has-required-aria-props": "off",
"jsx-quotes": "error",
"key-spacing": "error",
"keyword-spacing": "error",
"lines-around-comment": "off",
"no-alert": "error",
"no-bitwise": "error",
"no-caller": "error",
"no-console": "error",
"no-const-assign": "error",
"no-debugger": "error",
Expand All @@ -71,6 +80,7 @@
"no-mixed-spaces-and-tabs": "error",
"no-multiple-empty-lines": [ "error", { "max": 1 } ],
"no-multi-spaces": "error",
"no-multi-str": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "error",
"no-redeclare": "error",
Expand All @@ -94,16 +104,18 @@
}
],
"no-shadow": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-unreachable": "error",
"no-unsafe-negation": "error",
"no-unused-expressions": "error",
"no-unused-vars": "error",
"no-useless-computed-key": "error",
"no-useless-constructor": "error",
"no-useless-return": "error",
"no-var": "error",
"no-whitespace-before-property": "error",
"object-curly-spacing": [ "error", "always" ],
"one-var": "off",
"padded-blocks": [ "error", "never" ],
"prefer-const": "error",
"quote-props": [ "error", "as-needed" ],
Expand All @@ -113,7 +125,9 @@
"react/jsx-indent": [ "error", "tab" ],
"react/jsx-indent-props": [ "error", "tab" ],
"react/jsx-key": "error",
"react/jsx-space-before-closing": "error",
"react/jsx-tag-spacing": "error",
"react/no-children-prop": "off",
"react/no-find-dom-node": "warn",
"react/prop-types": "off",
"semi": "error",
"semi-spacing": "error",
Expand All @@ -128,6 +142,7 @@
} ],
"template-curly-spacing": [ "error", "always" ],
"valid-jsdoc": [ "error", { "requireReturn": false } ],
"valid-typeof": "error"
"valid-typeof": "error",
"yoda": "off"
}
}
24 changes: 12 additions & 12 deletions blocks/api/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ export function getBlockContent( block ) {
* @return {String} Comment-delimited block content
*/
export function getCommentDelimitedContent( rawBlockName, attributes, content ) {
const serializedAttributes = ! isEmpty( attributes )
? serializeAttributes( attributes ) + ' '
: '';
const serializedAttributes = ! isEmpty( attributes ) ?
serializeAttributes( attributes ) + ' ' :
'';

// strip core blocks of their namespace prefix
const blockName = rawBlockName.startsWith( 'core/' )
? rawBlockName.slice( 5 )
: rawBlockName;
const blockName = rawBlockName.startsWith( 'core/' ) ?
rawBlockName.slice( 5 ) :
rawBlockName;

if ( ! content ) {
return `<!-- wp:${ blockName } ${ serializedAttributes }/-->`;
Expand Down Expand Up @@ -211,13 +211,13 @@ export function serializeBlock( block ) {
case 'core/more':
const { customText, noTeaser } = saveAttributes;

const moreTag = customText
? `<!--more ${ customText }-->`
: '<!--more-->';
const moreTag = customText ?
`<!--more ${ customText }-->` :
'<!--more-->';

const noTeaserTag = noTeaser
? '<!--noteaser-->'
: '';
const noTeaserTag = noTeaser ?
'<!--noteaser-->' :
'';

return compact( [ moreTag, noTeaserTag ] ).join( '\n' );

Expand Down
6 changes: 3 additions & 3 deletions blocks/block-alignment-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ function BlockAlignmentToolbar( { value, onChange, controls = DEFAULT_CONTROLS,
return () => onChange( value === align ? undefined : align );
}

const enabledControls = wideControlsEnabled
? controls
: controls.filter( ( control ) => WIDE_CONTROLS.indexOf( control ) === -1 );
const enabledControls = wideControlsEnabled ?
controls :
controls.filter( ( control ) => WIDE_CONTROLS.indexOf( control ) === -1 );

return (
<Toolbar
Expand Down
28 changes: 28 additions & 0 deletions blocks/editable/aria.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* External dependencies
*/

import {
difference,
isEqual,
pickBy,
startsWith,
} from 'lodash';

const isAriaPropName = ( name ) =>
startsWith( name, 'aria-' );

const getAriaKeys = ( props ) =>
Object.keys( props ).filter( isAriaPropName );

export const pickAriaProps = ( props ) =>
pickBy( props, ( value, key ) => isAriaPropName( key ) );

export const diffAriaProps = ( props, nextProps ) => {
const prevAriaKeys = getAriaKeys( props );
const nextAriaKeys = getAriaKeys( nextProps );
const removedKeys = difference( prevAriaKeys, nextAriaKeys );
const updatedKeys = nextAriaKeys.filter( ( key ) =>
! isEqual( props[ key ], nextProps[ key ] ) );
return { removedKeys, updatedKeys };
};
6 changes: 3 additions & 3 deletions blocks/editable/format-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ class FormatToolbar extends Component {
render() {
const { formats, focusPosition, enabledControls = DEFAULT_CONTROLS, customControls = [] } = this.props;
const { isAddingLink, isEditingLink, newLinkValue, settingsVisible, opensInNewWindow } = this.state;
const linkStyle = focusPosition
? { position: 'absolute', ...focusPosition }
: null;
const linkStyle = focusPosition ?
{ position: 'absolute', ...focusPosition } :
null;

const toolbarControls = FORMATTING_CONTROLS.concat( customControls )
.filter( control => enabledControls.indexOf( control.format ) !== -1 )
Expand Down
18 changes: 11 additions & 7 deletions blocks/editable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import './style.scss';
import { pasteHandler } from '../api';
import FormatToolbar from './format-toolbar';
import TinyMCE from './tinymce';
import { pickAriaProps } from './aria';
import patterns from './patterns';
import { EVENTS } from './constants';

Expand Down Expand Up @@ -313,19 +314,19 @@ export default class Editable extends Component {
const position = this.getEditorSelectionRect();

// Find the parent "relative" positioned container
const container = this.props.inlineToolbar
? this.editor.getBody().closest( '.blocks-editable' )
: this.editor.getBody().closest( '.editor-visual-editor__block' );
const container = this.props.inlineToolbar ?
this.editor.getBody().closest( '.blocks-editable' ) :
this.editor.getBody().closest( '.editor-visual-editor__block' );
const containerPosition = container.getBoundingClientRect();
const blockPadding = 14;
const blockMoverMargin = 18;

// These offsets are necessary because the toolbar where the link modal lives
// is absolute positioned and it's not shown when we compute the position here
// so we compute the position about its parent relative position and adds the offset
const toolbarOffset = this.props.inlineToolbar
? { top: 50, left: 0 }
: { top: 40, left: -( ( blockPadding * 2 ) + blockMoverMargin ) };
const toolbarOffset = this.props.inlineToolbar ?
{ top: 50, left: 0 } :
{ top: 40, left: -( ( blockPadding * 2 ) + blockMoverMargin ) };
const linkModalWidth = 250;

return {
Expand Down Expand Up @@ -656,6 +657,8 @@ export default class Editable extends Component {
formatters,
} = this.props;

const ariaProps = pickAriaProps( this.props );

// Generating a key that includes `tagName` ensures that if the tag
// changes, we unmount and destroy the previous TinyMCE element, then
// mount and initialize a new child element in its place.
Expand Down Expand Up @@ -693,7 +696,8 @@ export default class Editable extends Component {
style={ style }
defaultValue={ value }
isPlaceholderVisible={ isPlaceholderVisible }
label={ placeholder }
aria-label={ placeholder }
{ ...ariaProps }
className={ className }
key={ key }
/>
Expand Down
110 changes: 110 additions & 0 deletions blocks/editable/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { shallow } from 'enzyme';
* Internal dependencies
*/
import Editable from '../';
import { diffAriaProps, pickAriaProps } from '../aria';

describe( 'Editable', () => {
describe( '.propTypes', () => {
Expand Down Expand Up @@ -40,4 +41,113 @@ describe( 'Editable', () => {
} );
/* eslint-enable no-console */
} );
describe( 'pickAriaProps()', () => {
it( 'should should filter all properties to only those begining with "aria-"', () => {
expect( pickAriaProps( {
tagName: 'p',
className: 'class1 class2',
'aria-label': 'my label',
style: {
backgroundColor: 'white',
color: 'black',
fontSize: '12px',
textAlign: 'left',
},
'aria-owns': 'some-id',
'not-aria-prop': 'value',
ariaWithoutDash: 'value',
} ) ).toEqual( {
'aria-label': 'my label',
'aria-owns': 'some-id',
} );
} );
} );
describe( 'diffAriaProps()', () => {
it( 'should report empty arrays for no props', () => {
expect( diffAriaProps( {}, {} ) ).toEqual( {
removedKeys: [],
updatedKeys: [],
} );
} );
it( 'should report empty arrays for non-aria props', () => {
expect( diffAriaProps( {
'non-aria-prop': 'old value',
'removed-prop': 'value',
}, {
'non-aria-prop': 'new value',
'added-prop': 'value',
} ) ).toEqual( {
removedKeys: [],
updatedKeys: [],
} );
} );
it( 'should report added aria props', () => {
expect( diffAriaProps( {
}, {
'aria-prop': 'value',
} ) ).toEqual( {
removedKeys: [],
updatedKeys: [ 'aria-prop' ],
} );
} );
it( 'should report removed aria props', () => {
expect( diffAriaProps( {
'aria-prop': 'value',
}, {
} ) ).toEqual( {
removedKeys: [ 'aria-prop' ],
updatedKeys: [],
} );
} );
it( 'should report changed aria props', () => {
expect( diffAriaProps( {
'aria-prop': 'old value',
}, {
'aria-prop': 'new value',
} ) ).toEqual( {
removedKeys: [],
updatedKeys: [ 'aria-prop' ],
} );
} );
it( 'should not report unchanged aria props', () => {
expect( diffAriaProps( {
'aria-prop': 'value',
}, {
'aria-prop': 'value',
} ) ).toEqual( {
removedKeys: [],
updatedKeys: [],
} );
} );
it( 'should work with a mixture of aria and non-aria props', () => {
expect( diffAriaProps( {
tagName: 'p',
className: 'class1 class2',
'aria-label': 'my label',
style: {
backgroundColor: 'white',
color: 'black',
fontSize: '12px',
textAlign: 'left',
},
'aria-owns': 'some-id',
'aria-active': 'some-active-id',
'not-aria-prop': 'old value',
}, {
tagName: 'div',
className: 'class1 class2',
style: {
backgroundColor: 'red',
color: 'black',
fontSize: '12px',
},
'aria-active': 'some-other-active-id',
'not-aria-prop': 'new value',
'aria-label': 'my label',
} ) ).toEqual( {
removedKeys: [ 'aria-owns' ],
updatedKeys: [ 'aria-active' ],
} );
} );
} );
} );
16 changes: 14 additions & 2 deletions blocks/editable/tinymce.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import classnames from 'classnames';
*/
import { Component, Children, createElement } from '@wordpress/element';

/**
* Internal dependencies
*/
import { diffAriaProps, pickAriaProps } from './aria';

export default class TinyMCE extends Component {
componentDidMount() {
this.initialize();
Expand Down Expand Up @@ -39,6 +44,12 @@ export default class TinyMCE extends Component {
if ( ! isEqual( this.props.className, nextProps.className ) ) {
this.editorNode.className = classnames( nextProps.className, 'blocks-editable__tinymce' );
}

const { removedKeys, updatedKeys } = diffAriaProps( this.props, nextProps );
removedKeys.forEach( ( key ) =>
this.editorNode.removeAttribute( key ) );
updatedKeys.forEach( ( key ) =>
this.editorNode.setAttribute( key, nextProps[ key ] ) );
}

componentWillUnmount() {
Expand Down Expand Up @@ -88,7 +99,8 @@ export default class TinyMCE extends Component {
}

render() {
const { tagName = 'div', style, defaultValue, label, className } = this.props;
const { tagName = 'div', style, defaultValue, className } = this.props;
const ariaProps = pickAriaProps( this.props );

// If a default value is provided, render it into the DOM even before
// TinyMCE finishes initializing. This avoids a short delay by allowing
Expand All @@ -104,7 +116,7 @@ export default class TinyMCE extends Component {
suppressContentEditableWarning: true,
className: classnames( className, 'blocks-editable__tinymce' ),
style,
'aria-label': label,
...ariaProps,
}, children );
}
}
Loading

0 comments on commit ed9f49e

Please sign in to comment.