Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions blocks/api/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ let unknownTypeHandler;
*/
let defaultBlockName;

/**
* Flags that control the internal behavior of the block registration API.
*/
export const registrationFlags = {
ALLOW_CORE_NAMESPACES: false,
};

/**
* Registers a new block provided a unique name and an object defining its
* behavior. Once registered, the block is made available as an option to any
Expand All @@ -49,6 +56,12 @@ export function registerBlockType( name, settings ) {
);
return;
}
if ( ! registrationFlags.ALLOW_CORE_NAMESPACES && /^core[\/-]/.test( name ) ) {
console.error(
'Plugins may not register blocks in the "core" or "core-*" namespaces.'
);
return;
}
if ( ! settings || ! isFunction( settings.save ) ) {
console.error(
'The "save" property must be specified and must be a valid function.'
Expand Down
128 changes: 64 additions & 64 deletions blocks/api/test/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ describe( 'block factory', () => {

describe( 'createBlock()', () => {
it( 'should create a block given its blockType and attributes', () => {
registerBlockType( 'core/test-block', {
registerBlockType( 'not-core/test-block', {
defaultAttributes: {
includesDefault: true,
},
save: noop,
} );
const block = createBlock( 'core/test-block', {
const block = createBlock( 'not-core/test-block', {
align: 'left',
} );

expect( block.name ).toEqual( 'core/test-block' );
expect( block.name ).toEqual( 'not-core/test-block' );
expect( block.attributes ).toEqual( {
includesDefault: true,
align: 'left',
Expand All @@ -43,44 +43,44 @@ describe( 'block factory', () => {

describe( 'switchToBlockType()', () => {
it( 'should switch the blockType of a block using the "transform form"', () => {
registerBlockType( 'core/updated-text-block', {
registerBlockType( 'not-core/updated-text-block', {
transforms: {
from: [ {
blocks: [ 'core/text-block' ],
blocks: [ 'not-core/text-block' ],
transform: ( { value } ) => {
return createBlock( 'core/updated-text-block', {
return createBlock( 'not-core/updated-text-block', {
value: 'chicken ' + value,
} );
},
} ],
},
save: noop,
} );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toHaveLength( 1 );
expect( transformedBlocks[ 0 ] ).toHaveProperty( 'uid' );
expect( transformedBlocks[ 0 ].name ).toBe( 'core/updated-text-block' );
expect( transformedBlocks[ 0 ].name ).toBe( 'not-core/updated-text-block' );
expect( transformedBlocks[ 0 ].isValid ).toBe( true );
expect( transformedBlocks[ 0 ].attributes ).toEqual( {
value: 'chicken ribs',
} );
} );

it( 'should switch the blockType of a block using the "transform to"', () => {
registerBlockType( 'core/updated-text-block', defaultBlockSettings );
registerBlockType( 'core/text-block', {
registerBlockType( 'not-core/updated-text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', {
transforms: {
to: [ {
blocks: [ 'core/updated-text-block' ],
blocks: [ 'not-core/updated-text-block' ],
transform: ( { value } ) => {
return createBlock( 'core/updated-text-block', {
return createBlock( 'not-core/updated-text-block', {
value: 'chicken ' + value,
} );
},
Expand All @@ -89,81 +89,81 @@ describe( 'block factory', () => {
save: noop,
} );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toHaveLength( 1 );
expect( transformedBlocks[ 0 ] ).toHaveProperty( 'uid' );
expect( transformedBlocks[ 0 ].name ).toBe( 'core/updated-text-block' );
expect( transformedBlocks[ 0 ].name ).toBe( 'not-core/updated-text-block' );
expect( transformedBlocks[ 0 ].isValid ).toBe( true );
expect( transformedBlocks[ 0 ].attributes ).toEqual( {
value: 'chicken ribs',
} );
} );

it( 'should return null if no transformation is found', () => {
registerBlockType( 'core/updated-text-block', defaultBlockSettings );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/updated-text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject transformations that return null', () => {
registerBlockType( 'core/updated-text-block', {
registerBlockType( 'not-core/updated-text-block', {
transforms: {
from: [ {
blocks: [ 'core/text-block' ],
blocks: [ 'not-core/text-block' ],
transform: () => null,
} ],
},
save: noop,
} );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject transformations that return an empty array', () => {
registerBlockType( 'core/updated-text-block', {
registerBlockType( 'not-core/updated-text-block', {
transforms: {
from: [ {
blocks: [ 'core/text-block' ],
blocks: [ 'not-core/text-block' ],
transform: () => [],
} ],
},
save: noop,
} );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject single transformations that do not include block types', () => {
registerBlockType( 'core/updated-text-block', {
registerBlockType( 'not-core/updated-text-block', {
transforms: {
from: [ {
blocks: [ 'core/text-block' ],
blocks: [ 'not-core/text-block' ],
transform: ( { value } ) => {
return {
attributes: {
Expand All @@ -175,25 +175,25 @@ describe( 'block factory', () => {
},
save: noop,
} );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject array transformations that do not include block types', () => {
registerBlockType( 'core/updated-text-block', {
registerBlockType( 'not-core/updated-text-block', {
transforms: {
from: [ {
blocks: [ 'core/text-block' ],
blocks: [ 'not-core/text-block' ],
transform: ( { value } ) => {
return [
createBlock( 'core/updated-text-block', {
createBlock( 'not-core/updated-text-block', {
value: 'chicken ' + value,
} ),
{
Expand All @@ -207,25 +207,25 @@ describe( 'block factory', () => {
},
save: noop,
} );
registerBlockType( 'core/text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', defaultBlockSettings );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject single transformations with unexpected block types', () => {
registerBlockType( 'core/updated-text-block', defaultBlockSettings );
registerBlockType( 'core/text-block', {
registerBlockType( 'not-core/updated-text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', {
transforms: {
to: [ {
blocks: [ 'core/updated-text-block' ],
blocks: [ 'not-core/updated-text-block' ],
transform: ( { value } ) => {
return createBlock( 'core/text-block', {
return createBlock( 'not-core/text-block', {
value: 'chicken ' + value,
} );
},
Expand All @@ -234,27 +234,27 @@ describe( 'block factory', () => {
save: noop,
} );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toBeNull();
} );

it( 'should reject array transformations with unexpected block types', () => {
registerBlockType( 'core/updated-text-block', defaultBlockSettings );
registerBlockType( 'core/text-block', {
registerBlockType( 'not-core/updated-text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', {
transforms: {
to: [ {
blocks: [ 'core/updated-text-block' ],
blocks: [ 'not-core/updated-text-block' ],
transform: ( { value } ) => {
return [
createBlock( 'core/text-block', {
createBlock( 'not-core/text-block', {
value: 'chicken ' + value,
} ),
createBlock( 'core/text-block', {
createBlock( 'not-core/text-block', {
value: 'smoked ' + value,
} ),
];
Expand All @@ -264,27 +264,27 @@ describe( 'block factory', () => {
save: noop,
} );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

expect( transformedBlocks ).toEqual( null );
} );

it( 'should accept valid array transformations', () => {
registerBlockType( 'core/updated-text-block', defaultBlockSettings );
registerBlockType( 'core/text-block', {
registerBlockType( 'not-core/updated-text-block', defaultBlockSettings );
registerBlockType( 'not-core/text-block', {
transforms: {
to: [ {
blocks: [ 'core/updated-text-block' ],
blocks: [ 'not-core/updated-text-block' ],
transform: ( { value } ) => {
return [
createBlock( 'core/text-block', {
createBlock( 'not-core/text-block', {
value: 'chicken ' + value,
} ),
createBlock( 'core/updated-text-block', {
createBlock( 'not-core/updated-text-block', {
value: 'smoked ' + value,
} ),
];
Expand All @@ -294,26 +294,26 @@ describe( 'block factory', () => {
save: noop,
} );

const block = createBlock( 'core/text-block', {
const block = createBlock( 'not-core/text-block', {
value: 'ribs',
} );

const transformedBlocks = switchToBlockType( block, 'core/updated-text-block' );
const transformedBlocks = switchToBlockType( block, 'not-core/updated-text-block' );

// Make sure the block UIDs are set as expected: the first
// transformed block whose type matches the "destination" type gets
// to keep the existing block's UID.
expect( transformedBlocks ).toHaveLength( 2 );
expect( transformedBlocks[ 0 ] ).toHaveProperty( 'uid' );
expect( transformedBlocks[ 0 ].uid ).not.toBe( block.uid );
expect( transformedBlocks[ 0 ].name ).toBe( 'core/text-block' );
expect( transformedBlocks[ 0 ].name ).toBe( 'not-core/text-block' );
expect( transformedBlocks[ 0 ].isValid ).toBe( true );
expect( transformedBlocks[ 0 ].attributes ).toEqual( {
value: 'chicken ribs',
} );
expect( transformedBlocks[ 1 ].uid ).toBe( block.uid );
expect( transformedBlocks[ 1 ] ).toHaveProperty( 'uid' );
expect( transformedBlocks[ 1 ].name ).toBe( 'core/updated-text-block' );
expect( transformedBlocks[ 1 ].name ).toBe( 'not-core/updated-text-block' );
expect( transformedBlocks[ 1 ].isValid ).toBe( true );
expect( transformedBlocks[ 1 ].attributes ).toEqual( {
value: 'smoked ribs',
Expand Down
Loading