UNPKG

@wordpress/block-library

Version:
239 lines (222 loc) 5.53 kB
/** * External dependencies */ import { every } from 'lodash'; /** * WordPress dependencies */ import { createBlobURL } from '@wordpress/blob'; import { createBlock, getBlockAttributes } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; import { __ } from '@wordpress/i18n'; export function stripFirstImage( attributes, { shortcode } ) { const { body } = document.implementation.createHTMLDocument( '' ); body.innerHTML = shortcode.content; let nodeToRemove = body.querySelector( 'img' ); // If an image has parents, find the topmost node to remove. while ( nodeToRemove && nodeToRemove.parentNode && nodeToRemove.parentNode !== body ) { nodeToRemove = nodeToRemove.parentNode; } if ( nodeToRemove ) { nodeToRemove.parentNode.removeChild( nodeToRemove ); } return body.innerHTML.trim(); } function getFirstAnchorAttributeFormHTML( html, attributeName ) { const { body } = document.implementation.createHTMLDocument( '' ); body.innerHTML = html; const { firstElementChild } = body; if ( firstElementChild && firstElementChild.nodeName === 'A' ) { return firstElementChild.getAttribute( attributeName ) || undefined; } } const imageSchema = { img: { attributes: [ 'src', 'alt', 'title' ], classes: [ 'alignleft', 'aligncenter', 'alignright', 'alignnone', /^wp-image-\d+$/, ], }, }; const schema = ( { phrasingContentSchema } ) => ( { figure: { require: [ 'img' ], children: { ...imageSchema, a: { attributes: [ 'href', 'rel', 'target' ], children: imageSchema, }, figcaption: { children: phrasingContentSchema, }, }, }, } ); const transforms = { from: [ { type: 'raw', isMatch: ( node ) => node.nodeName === 'FIGURE' && !! node.querySelector( 'img' ), schema, transform: ( node ) => { // Search both figure and image classes. Alignment could be // set on either. ID is set on the image. const className = node.className + ' ' + node.querySelector( 'img' ).className; const alignMatches = /(?:^|\s)align(left|center|right)(?:$|\s)/.exec( className ); const anchor = node.id === '' ? undefined : node.id; const align = alignMatches ? alignMatches[ 1 ] : undefined; const idMatches = /(?:^|\s)wp-image-(\d+)(?:$|\s)/.exec( className ); const id = idMatches ? Number( idMatches[ 1 ] ) : undefined; const anchorElement = node.querySelector( 'a' ); const linkDestination = anchorElement && anchorElement.href ? 'custom' : undefined; const href = anchorElement && anchorElement.href ? anchorElement.href : undefined; const rel = anchorElement && anchorElement.rel ? anchorElement.rel : undefined; const linkClass = anchorElement && anchorElement.className ? anchorElement.className : undefined; const attributes = getBlockAttributes( 'core/image', node.outerHTML, { align, id, linkDestination, href, rel, linkClass, anchor, } ); return createBlock( 'core/image', attributes ); }, }, { // Note: when dragging and dropping multiple files onto a gallery this overrides the // gallery transform in order to add new images to the gallery instead of // creating a new gallery. type: 'files', isMatch( files ) { // The following check is intended to catch non-image files when dropped together with images. if ( files.some( ( file ) => file.type.indexOf( 'image/' ) === 0 ) && files.some( ( file ) => file.type.indexOf( 'image/' ) !== 0 ) ) { const { createErrorNotice } = dispatch( noticesStore ); createErrorNotice( __( 'If uploading to a gallery all files need to be image formats' ), { id: 'gallery-transform-invalid-file', type: 'snackbar', } ); } return every( files, ( file ) => file.type.indexOf( 'image/' ) === 0 ); }, transform( files ) { const blocks = files.map( ( file ) => { return createBlock( 'core/image', { url: createBlobURL( file ), } ); } ); return blocks; }, }, { type: 'shortcode', tag: 'caption', attributes: { url: { type: 'string', source: 'attribute', attribute: 'src', selector: 'img', }, alt: { type: 'string', source: 'attribute', attribute: 'alt', selector: 'img', }, caption: { shortcode: stripFirstImage, }, href: { shortcode: ( attributes, { shortcode } ) => { return getFirstAnchorAttributeFormHTML( shortcode.content, 'href' ); }, }, rel: { shortcode: ( attributes, { shortcode } ) => { return getFirstAnchorAttributeFormHTML( shortcode.content, 'rel' ); }, }, linkClass: { shortcode: ( attributes, { shortcode } ) => { return getFirstAnchorAttributeFormHTML( shortcode.content, 'class' ); }, }, id: { type: 'number', shortcode: ( { named: { id } } ) => { if ( ! id ) { return; } return parseInt( id.replace( 'attachment_', '' ), 10 ); }, }, align: { type: 'string', shortcode: ( { named: { align = 'alignnone' } } ) => { return align.replace( 'align', '' ); }, }, }, }, ], }; export default transforms;