Skip to content

Commit

Permalink
Rename key to duplicable and invert logic
Browse files Browse the repository at this point in the history
The use of `unique` implies strict uniqueness across blocks of the
same type, which is not actually enforced here. For clarity the key
is changed to `duplicable` and the logic inverted.
  • Loading branch information
stacimc committed Jul 8, 2021
1 parent 6ae7fae commit 9999bfc
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 36 deletions.
10 changes: 6 additions & 4 deletions docs/reference-guides/block-api/block-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,19 @@ _Example_: Extract `src` and `alt` from each image element in the block's markup
// }
```

## Unique Attributes
## Duplicable Attributes

The `unique` key is used to mark block attributes that should not be copied when a block is duplicated. By default all attribute values will be cloned to the duplicate block. If an attribute sets the `unique` key to `true`, its value will not be copied, and it will instead fall back to the default value if one is supplied.
The `duplicable` key is used to indicate whether a block attribute should be copied when a block is duplicated. If an attribute sets the `duplicable` key to `false`, its value will not be copied, and it will instead fall back to the default value if one is supplied. If the key is not explicitly set, the attribute will be considered duplicable by default.

_Example_: A `resourceId` attribute is marked as `unique` so that it will not be copied to duplicate blocks.
The `duplicable` key should not be used for attributes that are extracted from block content using an [attribute source](#common-sources).

_Example_: A `resourceId` attribute which should not be copied to duplicate blocks.

```js
{
resourceId: {
type: 'string',
unique: true
duplicable: false
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/api/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function __experimentalCloneSanitizedBlock(
...block.attributes,
...mergeAttributes,
},
true
{ shouldRemoveDuplicateAttributes: true }
);

return {
Expand Down
14 changes: 7 additions & 7 deletions packages/blocks/src/api/test/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,27 +453,27 @@ describe( 'block factory', () => {
registerBlockType( 'core/test-block', {
...defaultBlockSettings,
attributes: {
uniqueAttribute: {
nonDuplicableAttr: {
type: 'string',
unique: true,
duplicable: false,
},
uniqueAttributeWithDefault: {
nonDuplicableAttrWithDefault: {
type: 'string',
unique: true,
duplicable: false,
default: 'default-value',
},
},
} );

const block = createBlock( 'core/test-block', {
uniqueAttribute: 'unique-value',
uniqueAttributeWithDefault: 'unique-non-default-value',
nonDuplicableAttr: 'unique-value',
nonDuplicableAttrWithDefault: 'unique-non-default-value',
} );

const clonedBlock = __experimentalCloneSanitizedBlock( block, {} );

expect( clonedBlock.attributes ).toEqual( {
uniqueAttributeWithDefault: 'default-value',
nonDuplicableAttrWithDefault: 'default-value',
} );
} );
} );
Expand Down
28 changes: 14 additions & 14 deletions packages/blocks/src/api/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,12 @@ describe( 'sanitizeBlockAttributes', () => {
} );
} );

it( 'does not strip unique attributes by default', () => {
it( 'does not strip non-duplicable attributes by default', () => {
registerBlockType( 'core/test-block', {
attributes: {
uniqueAttr: {
nonDupicableAttr: {
type: 'string',
unique: true,
duplicable: false,
},
},
title: 'Test block',
Expand All @@ -294,25 +294,25 @@ describe( 'sanitizeBlockAttributes', () => {
const attributes = __experimentalSanitizeBlockAttributes(
'core/test-block',
{
uniqueAttr: 'unique-value',
nonDupicableAttr: 'unique-value',
}
);

expect( attributes ).toEqual( {
uniqueAttr: 'unique-value',
nonDupicableAttr: 'unique-value',
} );
} );

it( 'sanitizes unique attributes and falls back to defaults when sanitizeUniqueAttributes is true', () => {
it( 'removes non-duplicable attributes and falls back to defaults when shouleRemoveDuplicateAttributes is true', () => {
registerBlockType( 'core/test-block', {
attributes: {
uniqueAttr: {
nonDuplicableAttr: {
type: 'string',
unique: true,
duplicable: false,
},
uniqueAttrWithDefault: {
nonDuplicableAttrWithDefault: {
type: 'string',
unique: true,
duplicable: false,
default: 'default-value',
},
},
Expand All @@ -322,14 +322,14 @@ describe( 'sanitizeBlockAttributes', () => {
const attributes = __experimentalSanitizeBlockAttributes(
'core/test-block',
{
uniqueAttr: 'unique-value',
uniqueAttrWithDefault: 'unique-non-default-value',
nonDuplicableAttr: 'unique-value',
nonDuplicableAttrWithDefault: 'unique-non-default-value',
},
true
{ shouldRemoveDuplicateAttributes: true }
);

expect( attributes ).toEqual( {
uniqueAttrWithDefault: 'default-value',
nonDuplicableAttrWithDefault: 'default-value',
} );
} );

Expand Down
22 changes: 12 additions & 10 deletions packages/blocks/src/api/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,15 +237,15 @@ export function getAccessibleBlockLabel(
* Ensure attributes contains only values defined by block type, and merge
* default values for missing attributes.
*
* @param {string} name The block's name.
* @param {Object} attributes The block's attributes.
* @param {boolean} sanitizeUniqueAttributes Whether to sanitize unique attributes.
* @param {string} name The block's name.
* @param {Object} attributes The block's attributes.
* @param {boolean} shouldRemoveDuplicateAttributes Whether to remove non-duplicable attributes.
* @return {Object} The sanitized attributes.
*/
export function __experimentalSanitizeBlockAttributes(
name,
attributes,
sanitizeUniqueAttributes = false
{ shouldRemoveDuplicateAttributes = false } = {}
) {
// Get the type definition associated with a registered block.
const blockType = getBlockType( name );
Expand All @@ -260,12 +260,14 @@ export function __experimentalSanitizeBlockAttributes(
const value = attributes[ key ];

if ( undefined !== value ) {
if ( sanitizeUniqueAttributes ) {
// Remove unique attributes and merge default values.
const unique =
schema.hasOwnProperty( 'unique' ) && schema.unique;

if ( ! unique ) {
// Remove non-duplicable attributes and merge default values.
if ( shouldRemoveDuplicateAttributes ) {
// An attribute is duplicable by default if not specified in the schema.
const duplicable =
! schema.hasOwnProperty( 'duplicable' ) ||
schema.duplicable;

if ( duplicable ) {
accumulator[ key ] = value;
} else if ( schema.hasOwnProperty( 'default' ) ) {
accumulator[ key ] = schema.default;
Expand Down

0 comments on commit 9999bfc

Please sign in to comment.