Skip to content

Commit

Permalink
File Block: Add support for embedding PDFs (#30857)
Browse files Browse the repository at this point in the history
Co-authored-by: Nik Tsekouras <ntsekouras@outlook.com>
  • Loading branch information
pento and ntsekouras authored Apr 21, 2021
1 parent c7306de commit 79707b4
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 10 deletions.
2 changes: 1 addition & 1 deletion lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ function gutenberg_reregister_core_block_types() {
'code',
'column',
'columns',
'file',
'gallery',
'group',
'heading',
Expand Down Expand Up @@ -53,6 +52,7 @@ function gutenberg_reregister_core_block_types() {
'calendar.php' => 'core/calendar',
'categories.php' => 'core/categories',
'cover.php' => 'core/cover',
'file.php' => 'core/file',
'latest-comments.php' => 'core/latest-comments',
'latest-posts.php' => 'core/latest-posts',
'legacy-widget.php' => 'core/legacy-widget',
Expand Down
7 changes: 7 additions & 0 deletions packages/block-library/src/file/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
"type": "string",
"source": "html",
"selector": "a[download]"
},
"displayPreview": {
"type": "boolean"
},
"previewHeight": {
"type": "number",
"default": 600
}
},
"supports": {
Expand Down
79 changes: 78 additions & 1 deletion packages/block-library/src/file/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';
import {
__unstableGetAnimateClassName as getAnimateClassName,
withNotices,
ResizableBox,
ToolbarButton,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
Expand All @@ -33,6 +34,10 @@ import { store as noticesStore } from '@wordpress/notices';
* Internal dependencies
*/
import FileBlockInspector from './inspector';
import { browserSupportsPdfs } from './utils';

export const MIN_PREVIEW_HEIGHT = 200;
export const MAX_PREVIEW_HEIGHT = 2000;

function ClipboardToolbarButton( { text, disabled } ) {
const { createNotice } = useDispatch( noticesStore );
Expand All @@ -54,7 +59,13 @@ function ClipboardToolbarButton( { text, disabled } ) {
);
}

function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
function FileEdit( {
attributes,
isSelected,
setAttributes,
noticeUI,
noticeOperations,
} ) {
const {
id,
fileName,
Expand All @@ -63,6 +74,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
textLinkTarget,
showDownloadButton,
downloadButtonText,
displayPreview,
previewHeight,
} = attributes;
const [ hasError, setHasError ] = useState( false );
const { media, mediaUpload } = useSelect(
Expand All @@ -76,6 +89,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
[ id ]
);

const { toggleSelection } = useDispatch( blockEditorStore );

useEffect( () => {
// Upload a file drag-and-dropped into the editor
if ( isBlobURL( href ) ) {
Expand All @@ -101,11 +116,14 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
function onSelectFile( newMedia ) {
if ( newMedia && newMedia.url ) {
setHasError( false );
const isPdf = newMedia.url.endsWith( '.pdf' );
setAttributes( {
href: newMedia.url,
fileName: newMedia.title,
textLinkHref: newMedia.url,
id: newMedia.id,
displayPreview: isPdf ? true : undefined,
previewHeight: isPdf ? 600 : undefined,
} );
}
}
Expand Down Expand Up @@ -138,6 +156,25 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
} );
}

function changeDisplayPreview( newValue ) {
setAttributes( { displayPreview: newValue } );
}

function handleOnResizeStop( event, direction, elt, delta ) {
toggleSelection( true );

const newHeight = parseInt( previewHeight + delta.height, 10 );
setAttributes( { previewHeight: newHeight } );
}

function changePreviewHeight( newValue ) {
const newHeight = Math.max(
parseInt( newValue, 10 ),
MIN_PREVIEW_HEIGHT
);
setAttributes( { previewHeight: newHeight } );
}

const attachmentPage = media && media.link;

const blockProps = useBlockProps( {
Expand All @@ -149,6 +186,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
),
} );

const displayPreviewInEditor = browserSupportsPdfs() && displayPreview;

if ( ! href || hasError ) {
return (
<div { ...blockProps }>
Expand Down Expand Up @@ -179,6 +218,10 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
changeLinkDestinationOption,
changeOpenInNewWindow,
changeShowDownloadButton,
displayPreview,
changeDisplayPreview,
previewHeight,
changePreviewHeight,
} }
/>
<BlockControls group="other">
Expand All @@ -195,6 +238,40 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
/>
</BlockControls>
<div { ...blockProps }>
{ displayPreviewInEditor && (
<ResizableBox
size={ { height: previewHeight } }
minHeight={ MIN_PREVIEW_HEIGHT }
maxHeight={ MAX_PREVIEW_HEIGHT }
minWidth="100%"
grid={ [ 10, 10 ] }
enable={ {
top: false,
right: false,
bottom: true,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
} }
onResizeStart={ () => toggleSelection( false ) }
onResizeStop={ handleOnResizeStop }
showHandle={ isSelected }
>
<object
className="wp-block-file__preview"
data={ href }
type="application/pdf"
aria-label={ __(
'Embed of the selected PDF file.'
) }
/>
{ ! isSelected && (
<div className="wp-block-file__preview-overlay" />
) }
</ResizableBox>
) }
<div className={ 'wp-block-file__content-wrapper' }>
<RichText
style={ { display: 'inline-block' } }
Expand Down
25 changes: 25 additions & 0 deletions packages/block-library/src/file/editor.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
.wp-block-file {
.wp-block[data-align="left"] > &,
.wp-block[data-align="right"] > & {
// Stop file block from collapsing when floated.
height: auto;
}

display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
margin-bottom: 0;

.components-resizable-box__container {
margin-bottom: 1em;
}

.wp-block-file__preview {
margin-bottom: 1em;
width: 100%;
height: 100%;
}

.wp-block-file__preview-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

.wp-block-file__content-wrapper {
flex-grow: 1;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/block-library/src/file/frontend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Internal dependencies
*/
import { hidePdfEmbedsOnUnsupportedBrowsers } from './utils';

hidePdfEmbedsOnUnsupportedBrowsers();
38 changes: 38 additions & 0 deletions packages/block-library/src/file/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* Server-side rendering of the `core/file` block.
*
* @package WordPress
*/

/**
* When the `core/file` block is rendering, check if we need to enqueue the `'wp-block-library-file` script.
*
* @param array $attributes The block attributes.
* @param array $content The block content.
*
* @return string Returns the block content.
*/
function render_block_core_file( $attributes, $content ) {
if ( ! empty( $attributes['displayPreview'] ) ) {
// Check if it's already enqueued, so we don't add the inline script multiple times.
if ( ! wp_script_is( 'wp-block-library-file' ) ) {
wp_enqueue_script( 'wp-block-library-file', plugins_url( 'file/frontend.js', __FILE__ ) );
}
}

return $content;
}

/**
* Registers the `core/file` block on server.
*/
function register_block_core_file() {
register_block_type_from_metadata(
__DIR__ . '/file',
array(
'render_callback' => 'render_block_core_file',
)
);
}
add_action( 'init', 'register_block_core_file' );
42 changes: 41 additions & 1 deletion packages/block-library/src/file/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,30 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, SelectControl, ToggleControl } from '@wordpress/components';
import {
PanelBody,
RangeControl,
SelectControl,
ToggleControl,
} from '@wordpress/components';
import { InspectorControls } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { MIN_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT } from './edit';

export default function FileBlockInspector( {
hrefs,
openInNewWindow,
showDownloadButton,
changeLinkDestinationOption,
changeOpenInNewWindow,
changeShowDownloadButton,
displayPreview,
changeDisplayPreview,
previewHeight,
changePreviewHeight,
} ) {
const { href, textLinkHref, attachmentPage } = hrefs;

Expand All @@ -26,6 +40,32 @@ export default function FileBlockInspector( {
return (
<>
<InspectorControls>
{ href.endsWith( '.pdf' ) && (
<PanelBody title={ __( 'PDF settings' ) }>
<ToggleControl
label={ __( 'Show inline embed' ) }
help={
displayPreview
? __(
"Note: Most phone and tablet browsers won't display embedded PDFs."
)
: null
}
checked={ !! displayPreview }
onChange={ changeDisplayPreview }
/>
<RangeControl
label={ __( 'Height in pixels' ) }
min={ MIN_PREVIEW_HEIGHT }
max={ Math.max(
MAX_PREVIEW_HEIGHT,
previewHeight
) }
value={ previewHeight }
onChange={ changePreviewHeight }
/>
</PanelBody>
) }
<PanelBody title={ __( 'Text link settings' ) }>
<SelectControl
label={ __( 'Link to' ) }
Expand Down
29 changes: 28 additions & 1 deletion packages/block-library/src/file/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { RichText, useBlockProps } from '@wordpress/block-editor';
import { __, sprintf } from '@wordpress/i18n';

export default function save( { attributes } ) {
const {
Expand All @@ -11,16 +12,42 @@ export default function save( { attributes } ) {
textLinkTarget,
showDownloadButton,
downloadButtonText,
displayPreview,
previewHeight,
} = attributes;

const pdfEmbedLabel = RichText.isEmpty( fileName )
? __( 'PDF embed' )
: sprintf(
/* translators: %s: filename. */
__( 'Embed of %s.' ),
fileName
);

return (
href && (
<div { ...useBlockProps.save() }>
{ displayPreview && (
<>
<object
className="wp-block-file__embed"
data={ href }
type="application/pdf"
style={ {
width: '100%',
height: `${ previewHeight }px`,
} }
aria-label={ pdfEmbedLabel }
/>
</>
) }
{ ! RichText.isEmpty( fileName ) && (
<a
href={ textLinkHref }
target={ textLinkTarget }
rel={ textLinkTarget ? 'noreferrer noopener' : false }
rel={
textLinkTarget ? 'noreferrer noopener' : undefined
}
>
<RichText.Content value={ fileName } />
</a>
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/file/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
text-align: right;
}

.wp-block-file__embed {
margin-bottom: 1em;
}

.wp-block-file__button {
background: #32373c;
border-radius: 2em;
Expand Down
Loading

0 comments on commit 79707b4

Please sign in to comment.