diff --git a/README.md b/README.md
index 630d13f..6ecb6a5 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ We made [Gutenberg](https://github.com/Wordpress/gutenberg) editor a little more
Gutenberg editor can **be easly included in your apps** with this [package](https://github.com/front/gutenberg-js).
-This package is based on [Gutenberg v4.2.0](https://github.com/WordPress/gutenberg/releases/tag/v4.2.0) and respective @wordpress packages versions.
+This package is based on [Gutenberg v4.4.0](https://github.com/WordPress/gutenberg/releases/tag/v4.4.0) and respective @wordpress packages versions.
## Table of contents
@@ -285,8 +285,8 @@ We've tried to make it easy to import **gutenberg-js** modules to your apps.
// Importing global variables that Gutenberg requires
import './globals';
-// Importing editPost module
-import { editPost } from '@frontkom/gutenberg-js';
+// Importing domReady and editPost modules
+import { domReady, editPost } from '@frontkom/gutenberg-js';
// Don't forget to import the style
import '@frontkom/gutenberg-js/build/css/block-library/style.css';
@@ -327,7 +327,11 @@ const settings = {
const overridePost = {};
// Et voilá... Initializing the editor!
-editPost.initializeEditor(target, postType, postId, settings, overridePost);
+window._wpLoadGutenbergEditor = new Promise(function (resolve) {
+ domReady(function () {
+ resolve(editPost.initializeEditor(target, postType, postId, settings, overridePost));
+ });
+});
```
**Note**: Gutenberg requires utf-8 encoding, so don't forget to add ` ` tag to your html `
`.
diff --git a/package.json b/package.json
index 3e386b8..c728908 100644
--- a/package.json
+++ b/package.json
@@ -33,64 +33,64 @@
],
"dependencies": {
"@wordpress/a11y": "^2.0.2",
- "@wordpress/api-fetch": "2.2.2",
+ "@wordpress/api-fetch": "2.2.4",
"@wordpress/autop": "^2.0.2",
"@wordpress/blob": "^2.1.0",
- "@wordpress/block-library": "2.1.8",
- "@wordpress/block-serialization-default-parser": "^1.0.2",
- "@wordpress/blocks": "5.1.2",
- "@wordpress/components": "^5.0.2",
- "@wordpress/core-data": "^2.0.9",
- "@wordpress/data": "^3.1.0",
- "@wordpress/date": "^2.1.0",
+ "@wordpress/block-library": "2.2.4",
+ "@wordpress/block-serialization-default-parser": "^2.0.0",
+ "@wordpress/blocks": "6.0.0",
+ "@wordpress/components": "^6.0.2",
+ "@wordpress/compose": "^3.0.0",
+ "@wordpress/core-data": "^2.0.13",
+ "@wordpress/data": "^4.0.0",
+ "@wordpress/date": "^3.0.0",
"@wordpress/deprecated": "^2.0.3",
- "@wordpress/dom": "^2.0.4",
+ "@wordpress/dom": "^2.0.6",
"@wordpress/dom-ready": "^2.0.2",
- "@wordpress/edit-post": "2.0.3",
- "@wordpress/editor": "6.1.1",
- "@wordpress/element": "^2.1.5",
+ "@wordpress/edit-post": "3.0.2",
+ "@wordpress/editor": "8.0.0",
+ "@wordpress/element": "^2.1.8",
"@wordpress/escape-html": "^1.0.1",
- "@wordpress/format-library": "^1.0.3",
+ "@wordpress/format-library": "^1.2.2",
"@wordpress/hooks": "^2.0.3",
"@wordpress/html-entities": "^2.0.2",
- "@wordpress/i18n": "^3.0.1",
+ "@wordpress/i18n": "^3.1.0",
"@wordpress/is-shallow-equal": "^1.1.4",
"@wordpress/keycodes": "^2.0.3",
- "@wordpress/notices": "^1.0.2",
- "@wordpress/nux": "^2.0.9",
- "@wordpress/plugins": "^2.0.6",
+ "@wordpress/notices": "^1.0.5",
+ "@wordpress/nux": "^3.0.0",
+ "@wordpress/plugins": "^2.0.9",
"@wordpress/redux-routine": "^3.0.3",
- "@wordpress/rich-text": "^2.0.2",
+ "@wordpress/rich-text": "^3.0.0",
"@wordpress/shortcode": "^2.0.2",
"@wordpress/token-list": "^1.0.2",
- "@wordpress/url": "~2.2.0",
- "@wordpress/viewport": "^2.0.8",
+ "@wordpress/url": "2.3.0",
+ "@wordpress/viewport": "^2.0.11",
"@wordpress/wordcount": "^2.0.3",
"tinymce": "4.8.0"
},
"devDependencies": {
+ "@babel/core": "7.0.0",
"@wordpress/babel-plugin-makepot": "^2.1.2",
- "@wordpress/scripts": "^2.4.1",
+ "@wordpress/scripts": "^2.4.3",
"babel-core": "^6.26.3",
- "babel-eslint": "7.2.3",
- "babel-jest": "20.0.3",
- "babel-loader": "7.1.4",
+ "babel-eslint": "^7.2.3",
+ "babel-jest": "^20.0.3",
+ "babel-loader": "^7.1.5",
"babel-preset-react-app": "^3.1.1",
- "babel-runtime": "6.26.0",
+ "babel-runtime": "^6.26.0",
"clean-webpack-plugin": "^0.1.19",
- "copy-webpack-plugin": "4.5.2",
- "cssnano": "4.0.3",
- "eslint": "^5.0.1",
+ "eslint": "^5.9.0",
"eslint-plugin-jsx-a11y": "^6.1.0",
"eslint-plugin-react": "^7.10.0",
"extract-text-webpack-plugin": "4.0.0-beta.0",
"node-sass": "git://github.com/sass/node-sass.git#v4.7.0",
"path-replace-loader": "^2.0.0",
- "postcss-color-function": "4.0.1",
- "postcss-loader": "2.1.3",
- "postcss-wrapper-loader": "0.0.2",
- "raw-loader": "0.5.1",
- "sass-loader": "6.0.7",
+ "postcss-color-function": "^4.0.1",
+ "postcss-loader": "^2.1.6",
+ "postcss-wrapper-loader": "^0.0.2",
+ "raw-loader": "^0.5.1",
+ "sass-loader": "^6.0.7",
"string-replace-webpack-plugin": "^0.1.3",
"webpack": "4.8.3",
"webpack-cli": "2.1.3"
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/cover/index.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/cover/index.js
index 9757331..0c1fc01 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/cover/index.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/cover/index.js
@@ -398,7 +398,7 @@ export const settings = {
}
),
- save ({ attributes, className }) {
+ save ({ attributes }) {
const {
align,
backgroundType,
@@ -421,7 +421,6 @@ export const settings = {
}
const classes = classnames(
- className,
dimRatioToClass(dimRatio),
overlayColorClass,
{
@@ -495,11 +494,10 @@ export const settings = {
},
},
- save ({ attributes, className }) {
+ save ({ attributes }) {
const { url, title, hasParallax, dimRatio, align } = attributes;
const style = backgroundImageStyles(url);
const classes = classnames(
- className,
dimRatioToClass(dimRatio),
{
'has-background-dim': dimRatio !== 0,
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/gallery/edit.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/gallery/edit.js
index e2ff390..c315dd0 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/gallery/edit.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/gallery/edit.js
@@ -1,13 +1,13 @@
/**
* External Dependencies
*/
-import { filter, pick } from 'lodash';
+import { filter, pick, get } from 'lodash';
/**
* WordPress dependencies
*/
import { Component, Fragment } from '@wordpress/element';
-import { __ } from '@wordpress/i18n';
+import { __, sprintf } from '@wordpress/i18n';
import {
IconButton,
DropZone,
@@ -45,7 +45,9 @@ export function defaultColumnsNumber (attributes) {
}
export const pickRelevantMediaFiles = image => {
- return pick(image, [ 'alt', 'id', 'link', 'url', 'caption' ]);
+ const imageProps = pick(image, [ 'alt', 'id', 'link', 'caption' ]);
+ imageProps.url = get(image, [ 'sizes', 'large', 'url' ]) || get(image, [ 'media_details', 'sizes', 'large', 'source_url' ]) || image.url;
+ return imageProps;
};
class GalleryEdit extends Component {
@@ -243,21 +245,27 @@ class GalleryEdit extends Component {
{ noticeUI }
{ dropZone }
- { images.map((img, index) => (
-
- this.setImageAttributes(index, attrs) }
- caption={ img.caption }
- data={ img.data }
- />
-
- )) }
+ { images.map((img, index) => {
+ /* translators: %1$d is the order number of the image, %2$d is the total number of images. */
+ const ariaLabel = __(sprintf('image %1$d of %2$d in gallery', (index + 1), images.length));
+
+ return (
+
+ this.setImageAttributes(index, attrs) }
+ caption={ img.caption }
+ aria-label={ ariaLabel }
+ data={ img.data }
+ />
+
+ );
+ }) }
{ isSelected &&
: ;
+ const img = (
+ // Disable reason: Image itself is not meant to be interactive, but should
+ // direct image selection and unfocus caption fields.
+ /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+
+
+ { isBlobURL(url) && }
+
+ /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */
+ );
const className = classnames({
'is-selected': isSelected,
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/edit.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/edit.js
index 47799ef..daf5a3e 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/edit.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/edit.js
@@ -6,15 +6,16 @@ import {
get,
isEmpty,
map,
+ last,
pick,
- startCase,
- keyBy,
+ compact,
} from 'lodash';
/**
* WordPress dependencies
*/
-import { __ } from '@wordpress/i18n';
+import { getPath } from '@wordpress/url';
+import { __, sprintf } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { getBlobByURL, revokeBlobURL, isBlobURL } from '@wordpress/blob';
import {
@@ -24,6 +25,7 @@ import {
PanelBody,
ResizableBox,
SelectControl,
+ Spinner,
TextControl,
TextareaControl,
Toolbar,
@@ -59,7 +61,9 @@ const LINK_DESTINATION_CUSTOM = 'custom';
const ALLOWED_MEDIA_TYPES = [ 'image' ];
export const pickRelevantMediaFiles = image => {
- return pick(image, [ 'alt', 'id', 'link', 'url', 'caption' ]);
+ const imageProps = pick(image, [ 'alt', 'id', 'link', 'caption' ]);
+ imageProps.url = get(image, [ 'sizes', 'large', 'url' ]) || get(image, [ 'media_details', 'sizes', 'large', 'source_url' ]) || image.url;
+ return imageProps;
};
/**
@@ -87,9 +91,7 @@ const isExternalImage = (id, url) => url && ! id && ! isBlobURL(url);
class ImageEdit extends Component {
constructor (props) {
super(props);
-
const { attributes } = props;
-
this.updateAlt = this.updateAlt.bind(this);
this.updateAlignment = this.updateAlignment.bind(this);
this.onFocusCaption = this.onFocusCaption.bind(this);
@@ -102,7 +104,9 @@ class ImageEdit extends Component {
this.updateDimensions = this.updateDimensions.bind(this);
this.onSetCustomHref = this.onSetCustomHref.bind(this);
this.onSetLinkDestination = this.onSetLinkDestination.bind(this);
+ this.getFilename = this.getFilename.bind(this);
this.toggleIsEditing = this.toggleIsEditing.bind(this);
+ this.onUploadError = this.onUploadError.bind(this);
this.state = {
captionFocused: false,
@@ -144,6 +148,14 @@ class ImageEdit extends Component {
}
}
+ onUploadError (message) {
+ const { noticeOperations } = this.props;
+ noticeOperations.createErrorNotice(message);
+ this.setState({
+ isEditing: true,
+ });
+ }
+
onSelectImage (media) {
if (! media || ! media.url) {
this.props.setAttributes({
@@ -264,8 +276,11 @@ class ImageEdit extends Component {
};
}
- getImageSizes () {
- return get(this.props.image, [ 'media_details', 'sizes' ], {});
+ getFilename (url) {
+ const path = getPath(url);
+ if (path) {
+ return last(path.split('/'));
+ }
}
getLinkDestinationOptions () {
@@ -283,6 +298,20 @@ class ImageEdit extends Component {
});
}
+ getImageSizeOptions () {
+ const { imageSizes, image } = this.props;
+ return compact(map(imageSizes, ({ name, slug }) => {
+ const sizeUrl = get(image, [ 'media_details', 'sizes', slug, 'source_url' ]);
+ if (! sizeUrl) {
+ return null;
+ }
+ return {
+ value: sizeUrl,
+ label: name,
+ };
+ }));
+ }
+
render () {
const { isEditing } = this.state;
const {
@@ -292,15 +321,13 @@ class ImageEdit extends Component {
isSelected,
className,
maxWidth,
- noticeOperations,
noticeUI,
toggleSelection,
isRTL,
- availableImageSizes,
} = this.props;
const { url, alt, caption, align, id, href, linkDestination, width, height, linkTarget, data } = attributes;
const isExternal = isExternalImage(id, url);
- const availableImageSizesBySlug = keyBy(availableImageSizes, 'slug');
+ const imageSizeOptions = this.getImageSizeOptions();
let toolbarEditButton;
if (url) {
@@ -358,7 +385,7 @@ class ImageEdit extends Component {
onSelect={ this.onSelectImage }
onSelectURL={ this.onSelectURL }
notices={ noticeUI }
- onError={ noticeOperations.createErrorNotice }
+ onError={ this.onUploadError }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ { id, src } }
@@ -373,7 +400,6 @@ class ImageEdit extends Component {
'is-focused': isSelected,
});
- const imageSizes = this.getImageSizes();
const isResizable = [ 'wide', 'full' ].indexOf(align) === -1 && isLargeViewport;
const isLinkURLInputDisabled = linkDestination !== LINK_DESTINATION_CUSTOM;
@@ -386,14 +412,11 @@ class ImageEdit extends Component {
onChange={ this.updateAlt }
help={ __('Alternative text describes your image to people who can’t see it. Add a short description with its key details.') }
/>
- { ! isEmpty(imageSizes) && (
+ { ! isEmpty(imageSizeOptions) && (
({
- value: size.source_url,
- label: availableImageSizesBySlug[ slug ] ? availableImageSizesBySlug[ slug ].name : startCase(slug),
- })) }
+ options={ imageSizeOptions }
onChange={ this.updateImageURL }
/>
) }
@@ -494,10 +517,28 @@ class ImageEdit extends Component {
imageHeight,
} = sizes;
- // Disable reason: Image itself is not meant to be
- // interactive, but should direct focus to block
- // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
- const img = ;
+ const filename = this.getFilename(url);
+ let defaultedAlt;
+ if (alt) {
+ defaultedAlt = alt;
+ }
+ else if (filename) {
+ defaultedAlt = sprintf(__('This image has an empty alt attribute; its file name is %s'), filename);
+ }
+ else {
+ defaultedAlt = __('This image has an empty alt attribute');
+ }
+
+ const img = (
+ // Disable reason: Image itself is not meant to be interactive, but
+ // should direct focus to block.
+ /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+
+
+ { isBlobURL(url) && }
+
+ /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */
+ );
if (! isResizable || ! imageWidthWithinContainer) {
return (
@@ -517,6 +558,13 @@ class ImageEdit extends Component {
const minWidth = imageWidth < imageHeight ? MIN_SIZE : MIN_SIZE * ratio;
const minHeight = imageHeight < imageWidth ? MIN_SIZE : MIN_SIZE / ratio;
+ // With the current implementation of ResizableBox, an image needs an explicit pixel value for the max-width.
+ // In absence of being able to set the content-width, this max-width is currently dictated by the vanilla editor style.
+ // The following variable adds a buffer to this vanilla style, so 3rd party themes have some wiggleroom.
+ // This does, in most cases, allow you to scale the image beyond the width of the main column, though not infinitely.
+ // @todo It would be good to revisit this once a content-width variable becomes available.
+ const maxWidthBuffer = maxWidth * 2.5;
+
let showRightHandle = false;
let showLeftHandle = false;
@@ -561,9 +609,9 @@ class ImageEdit extends Component {
} : undefined
}
minWidth={ minWidth }
- maxWidth={ maxWidth }
+ maxWidth={ maxWidthBuffer }
minHeight={ minHeight }
- maxHeight={ maxWidth / ratio }
+ maxHeight={ maxWidthBuffer / ratio }
lockAspectRatio
enable={ {
top: false,
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/index.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/index.js
index 046fb6f..b8a8668 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/index.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/image/index.js
@@ -11,7 +11,6 @@ import { __ } from '@wordpress/i18n';
import {
createBlock,
getBlockAttributes,
- getBlockType,
getPhrasingContentSchema,
} from '@wordpress/blocks';
import { RichText } from '@wordpress/editor';
@@ -138,8 +137,7 @@ export const settings = {
const anchorElement = node.querySelector('a');
const linkDestination = anchorElement && anchorElement.href ? 'custom' : undefined;
const href = anchorElement && anchorElement.href ? anchorElement.href : undefined;
- const blockType = getBlockType('core/image');
- const attributes = getBlockAttributes(blockType, node.outerHTML, { align, id, linkDestination, href });
+ const attributes = getBlockAttributes('core/image', node.outerHTML, { align, id, linkDestination, href });
return createBlock('core/image', attributes);
},
},
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/edit.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/edit.js
index 14d8268..b987bfe 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/edit.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/edit.js
@@ -2,6 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
+import { get } from 'lodash';
/**
* WordPress dependencies
@@ -50,6 +51,7 @@ class MediaTextEdit extends Component {
const { setAttributes } = this.props;
let mediaType;
+ let src;
// for media selections originated from a file upload.
if (media.media_type) {
if (media.media_type === 'image') {
@@ -65,12 +67,17 @@ class MediaTextEdit extends Component {
mediaType = media.type;
}
+ if (mediaType === 'image') {
+ // Try the "large" size URL, falling back to the "full" size URL below.
+ src = get(media, [ 'sizes', 'large', 'url' ]) || get(media, [ 'media_details', 'sizes', 'large', 'source_url' ]);
+ }
+
// GUTENBERG JS
const toUpdate = {
mediaAlt: media.alt,
mediaId: media.id,
mediaType,
- mediaUrl: media.url,
+ mediaUrl: src || media.url,
};
if (media.data) {
@@ -201,6 +208,7 @@ class MediaTextEdit extends Component {
diff --git a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/index.js b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/index.js
index f80ae61..dfc906e 100644
--- a/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/index.js
+++ b/src/js/gutenberg-overrides/@wordpress/block-library/build-module/media-text/index.js
@@ -13,6 +13,7 @@ import {
InnerBlocks,
getColorClassName,
} from '@wordpress/editor';
+import { createBlock } from '@wordpress/blocks';
/**
* Internal dependencies
@@ -87,6 +88,63 @@ export const settings = {
align: [ 'wide', 'full' ],
},
+ transforms: {
+ from: [
+ {
+ type: 'block',
+ blocks: [ 'core/image' ],
+ transform: ({ alt, url, id }) => (
+ createBlock('core/media-text', {
+ mediaAlt: alt,
+ mediaId: id,
+ mediaUrl: url,
+ mediaType: 'image',
+ })
+ ),
+ },
+ {
+ type: 'block',
+ blocks: [ 'core/video' ],
+ transform: ({ src, id }) => (
+ createBlock('core/media-text', {
+ mediaId: id,
+ mediaUrl: src,
+ mediaType: 'video',
+ })
+ ),
+ },
+ ],
+ to: [
+ {
+ type: 'block',
+ blocks: [ 'core/image' ],
+ isMatch: ({ mediaType, mediaUrl }) => {
+ return ! mediaUrl || mediaType === 'image';
+ },
+ transform: ({ mediaAlt, mediaId, mediaUrl }) => {
+ return createBlock('core/image', {
+ alt: mediaAlt,
+ id: mediaId,
+ url: mediaUrl,
+ });
+ },
+ },
+ {
+ type: 'block',
+ blocks: [ 'core/video' ],
+ isMatch: ({ mediaType, mediaUrl }) => {
+ return ! mediaUrl || mediaType === 'video';
+ },
+ transform: ({ mediaId, mediaUrl }) => {
+ return createBlock('core/video', {
+ id: mediaId,
+ src: mediaUrl,
+ });
+ },
+ },
+ ],
+ },
+
edit,
save ({ attributes }) {
diff --git a/src/js/gutenberg-overrides/@wordpress/editor/CHANGELOG.md b/src/js/gutenberg-overrides/@wordpress/editor/CHANGELOG.md
index 4d69282..c243e89 100644
--- a/src/js/gutenberg-overrides/@wordpress/editor/CHANGELOG.md
+++ b/src/js/gutenberg-overrides/@wordpress/editor/CHANGELOG.md
@@ -14,6 +14,8 @@
### Added
+- 'post-publish-button' override
+
- 'post-preview-button' override
- `addQueryArgs` to 'Manage All Reusable Blocks' link (Inserter Menu) ([packages/editor/build-module/components/inserter/menu.js](https://github.com/front/gutenberg-js/blob/v2.7.0/src/js/gutenberg-overrides/packages/editor/build-module/components/inserter/menu.js))
diff --git a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/autosave-monitor/index.js b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/autosave-monitor/index.js
index f7a459a..815ed98 100644
--- a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/autosave-monitor/index.js
+++ b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/autosave-monitor/index.js
@@ -54,6 +54,7 @@ export default compose([
isAutosaveable: isEditedPostAutosaveable(),
editsReference: getReferenceByDistinctEdits(),
autosaveInterval,
+
// GUTENBERG JS
canSave,
canAutosave,
@@ -62,6 +63,7 @@ export default compose([
withDispatch(dispatch => ({
autosave: dispatch('core/editor').autosave,
})),
+
// GUTENBERG JS
// added the ifCondition to enable/disable
// the autoave feature according 'canSave' and 'canAutosave' settings
diff --git a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-preview-button/index.js b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-preview-button/index.js
index 40b033c..4a30bb7 100644
--- a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-preview-button/index.js
+++ b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-preview-button/index.js
@@ -13,6 +13,76 @@ import { withSelect, withDispatch } from '@wordpress/data';
import { DotTip } from '@wordpress/nux';
import { ifCondition, compose } from '@wordpress/compose';
+function writeInterstitialMessage (targetDocument) {
+ let markup = renderToString(
+
+ { /* GUTENBERG-JS
+
+
+ */}
+
{ __('Generating preview…') }
+
+ );
+
+ markup += `
+
+ `;
+
+ targetDocument.write(markup);
+ targetDocument.close();
+}
+
export class PostPreviewButton extends Component {
constructor (props) {
super(props);
@@ -54,119 +124,64 @@ export class PostPreviewButton extends Component {
return `wp-preview-${postId}`;
}
- /**
- * Opens a popup window, navigating user to a preview of the current post.
- * Triggers autosave if post is autosaveable.
- */
- openPreviewWindow () {
- const { isAutosaveable, previewLink, currentPostLink } = this.props;
+ openPreviewWindow (event) {
+ // Our Preview button has its 'href' and 'target' set correctly for a11y
+ // purposes. Unfortunately, though, we can't rely on the default 'click'
+ // handler since sometimes it incorrectly opens a new tab instead of reusing
+ // the existing one.
+ // https://github.com/WordPress/gutenberg/pull/8330
+ event.preventDefault();
- // Open a popup, BUT: Set it to a blank page until save completes. This
- // is necessary because popups can only be opened in response to user
- // interaction (click), but we must still wait for the post to save.
+ // Open up a Preview tab if needed. This is where we'll show the preview.
if (! this.previewWindow || this.previewWindow.closed) {
this.previewWindow = window.open('', this.getWindowTarget());
}
- // Ask the browser to bring the preview tab to the front
- // This can work or not depending on the browser's user preferences
+ // Focus the Preview tab. This might not do anything, depending on the browser's
+ // and user's preferences.
// https://html.spec.whatwg.org/multipage/interaction.html#dom-window-focus
this.previewWindow.focus();
- // If there are no changes to autosave, we cannot perform the save, but
- // if there is an existing preview link (e.g. previous published post
- // autosave), it should be reused as the popup destination.
- if (! isAutosaveable && ! previewLink && currentPostLink) {
- this.setPreviewWindowLink(currentPostLink);
- return;
- }
-
- if (! isAutosaveable) {
- this.setPreviewWindowLink(previewLink);
+ // If we don't need to autosave the post before previewing, then we simply
+ // load the Preview URL in the Preview tab.
+ if (! this.props.isAutosaveable) {
+ this.setPreviewWindowLink(event.target.href);
return;
}
+ // Request an autosave. This happens asynchronously and causes the component
+ // to update when finished.
this.props.autosave();
- let markup = renderToString(
-
- { /* GUTENBERG-JS
-
-
- */}
-
{ __('Generating preview…') }
-
- );
-
- markup += `
- `;
-
- this.previewWindow.document.write(markup);
- this.previewWindow.document.close();
+ // Display a 'Generating preview' message in the Preview tab while we wait for the
+ // autosave to finish.
+ writeInterstitialMessage(this.previewWindow.document);
}
render () {
- const { isSaveable } = this.props;
+ const { previewLink, currentPostLink, isSaveable } = this.props;
+
+ // Link to the `?preview=true` URL if we have it, since this lets us see
+ // changes that were autosaved since the post was last published. Otherwise,
+ // just link to the post's URL.
+ const href = previewLink || currentPostLink;
return (
{ _x('Preview', 'imperative verb') }
+
+ {
+ /* translators: accessibility text */
+ __('(opens in a new tab)')
+ }
+
{ __('Click “Preview” to load a preview of this page, so you can make sure you’re happy with your blocks.') }
@@ -182,8 +197,6 @@ export default compose([
getCurrentPostAttribute,
getAutosaveAttribute,
getEditedPostAttribute,
- isEditedPostDirty,
- isEditedPostNew,
isEditedPostSaveable,
isEditedPostAutosaveable,
} = select('core/editor');
@@ -195,8 +208,6 @@ export default compose([
postId: getCurrentPostId(),
currentPostLink: getCurrentPostAttribute('link'),
previewLink: getAutosaveAttribute('preview_link'),
- isDirty: isEditedPostDirty(),
- isNew: isEditedPostNew(),
isSaveable: isEditedPostSaveable(),
isAutosaveable: isEditedPostAutosaveable(),
isViewable: get(postType, [ 'viewable' ], false),
diff --git a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-button/index.js b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-button/index.js
new file mode 100644
index 0000000..9f5df5e
--- /dev/null
+++ b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-button/index.js
@@ -0,0 +1,168 @@
+/**
+ * External dependencies
+ */
+import { noop, get } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { Button } from '@wordpress/components';
+import { Component, createRef } from '@wordpress/element';
+import { withSelect, withDispatch } from '@wordpress/data';
+import { compose, ifCondition } from '@wordpress/compose';
+import { __ } from '@wordpress/i18n';
+import { DotTip } from '@wordpress/nux';
+
+/**
+ * Internal dependencies
+ */
+import PublishButtonLabel from './label';
+export class PostPublishButton extends Component {
+ constructor (props) {
+ super(props);
+ this.buttonNode = createRef();
+ }
+ componentDidMount () {
+ if (this.props.focusOnMount) {
+ this.buttonNode.current.focus();
+ }
+ }
+
+ render () {
+ const {
+ forceIsDirty,
+ forceIsSaving,
+ hasPublishAction,
+ isBeingScheduled,
+ isOpen,
+ isPostSavingLocked,
+ isPublishable,
+ isPublished,
+ isSaveable,
+ isSaving,
+ isToggle,
+ onSave,
+ onStatusChange,
+ onSubmit = noop,
+ onToggle,
+ visibility,
+ } = this.props;
+ const isButtonDisabled =
+ isSaving ||
+ forceIsSaving ||
+ ! isSaveable ||
+ isPostSavingLocked ||
+ (! isPublishable && ! forceIsDirty);
+
+ const isToggleDisabled =
+ isPublished ||
+ isSaving ||
+ forceIsSaving ||
+ ! isSaveable ||
+ (! isPublishable && ! forceIsDirty);
+
+ let publishStatus;
+ if (! hasPublishAction) {
+ publishStatus = 'pending';
+ }
+ else if (isBeingScheduled) {
+ publishStatus = 'future';
+ }
+ else if (visibility === 'private') {
+ publishStatus = 'private';
+ }
+ else {
+ publishStatus = 'publish';
+ }
+
+ const onClick = () => {
+ onSubmit();
+ onStatusChange(publishStatus);
+ onSave();
+ };
+
+ const buttonProps = {
+ 'aria-disabled': isButtonDisabled,
+ className: 'editor-post-publish-button',
+ isBusy: isSaving && isPublished,
+ isLarge: true,
+ isPrimary: true,
+ onClick,
+ };
+
+ const toggleProps = {
+ 'aria-disabled': isToggleDisabled,
+ 'aria-expanded': isOpen,
+ className: 'editor-post-publish-panel__toggle',
+ isBusy: isSaving && isPublished,
+ isPrimary: true,
+ onClick: onToggle,
+ };
+
+ const toggleChildren = isBeingScheduled ? __('Schedule…') : __('Publish…');
+ const buttonChildren = ;
+
+ const componentProps = isToggle ? toggleProps : buttonProps;
+ const componentChildren = isToggle ? toggleChildren : buttonChildren;
+ return (
+
+ { componentChildren }
+
+ { __('Finished writing? That’s great, let’s get this published right now. Just click “Publish” and you’re good to go.') }
+
+
+ );
+ }
+}
+
+export default compose([
+ withSelect(select => {
+ const {
+ isSavingPost,
+ isEditedPostBeingScheduled,
+ getEditedPostVisibility,
+ isCurrentPostPublished,
+ isEditedPostSaveable,
+ isEditedPostPublishable,
+ isPostSavingLocked,
+ getCurrentPost,
+ getCurrentPostType,
+
+ // GUTENBERG JS
+ getEditorSettings,
+ } = select('core/editor');
+
+ // GUTENBERG JS
+ const { canPublish } = getEditorSettings();
+
+ return {
+ isSaving: isSavingPost(),
+ isBeingScheduled: isEditedPostBeingScheduled(),
+ visibility: getEditedPostVisibility(),
+ isSaveable: isEditedPostSaveable(),
+ isPostSavingLocked: isPostSavingLocked(),
+ isPublishable: isEditedPostPublishable(),
+ isPublished: isCurrentPostPublished(),
+ hasPublishAction: get(getCurrentPost(), [ '_links', 'wp:action-publish' ], false),
+ postType: getCurrentPostType(),
+
+ // GUTENBERG
+ canPublish,
+ };
+ }),
+ withDispatch(dispatch => {
+ const { editPost, savePost } = dispatch('core/editor');
+ return {
+ onStatusChange: status => editPost({ status }),
+ onSave: savePost,
+ };
+ }),
+
+ // GUTENBERG JS
+ // added the ifCondition to enable/disable
+ // the publish button according 'canPublish' setting
+ ifCondition(({ canPublish }) => canPublish),
+])(PostPublishButton);
diff --git a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-panel/toggle.js b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-panel/toggle.js
index 6e56d60..e955fb0 100644
--- a/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-panel/toggle.js
+++ b/src/js/gutenberg-overrides/@wordpress/editor/build-module/components/post-publish-panel/toggle.js
@@ -3,6 +3,7 @@
*/
import { Button } from '@wordpress/components';
import { compose, ifCondition } from '@wordpress/compose';
+import deprecated from '@wordpress/deprecated';
import { __ } from '@wordpress/i18n';
import { withSelect } from '@wordpress/data';
import { DotTip } from '@wordpress/nux';
@@ -16,10 +17,20 @@ export function PostPublishPanelToggle ({
onToggle,
isOpen,
forceIsSaving,
+ forceIsDirty,
}) {
- const isButtonEnabled = (
- ! isSaving && ! forceIsSaving && isPublishable && isSaveable
- ) || isPublished;
+ const isButtonDisabled =
+ isPublished ||
+ isSaving ||
+ forceIsSaving ||
+ ! isSaveable ||
+ (! isPublishable && ! forceIsDirty);
+
+ deprecated('PostPublishPanelToggle', {
+ version: '4.5',
+ alternative: 'PostPublishButton',
+ plugin: 'Gutenberg',
+ });
return (
{ isBeingScheduled ? __('Schedule…') : __('Publish…') }
diff --git a/src/js/gutenberg-overrides/@wordpress/notices/build/store/actions.js b/src/js/gutenberg-overrides/@wordpress/notices/build/store/actions.js
deleted file mode 100644
index 5d2ca79..0000000
--- a/src/js/gutenberg-overrides/@wordpress/notices/build/store/actions.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * External dependencies
- */
-import { uniqueId } from 'lodash';
-
-/**
- * Internal dependencies
- */
-import { DEFAULT_CONTEXT } from './constants';
-
-/**
- * Yields action objects used in signalling that a notice is to be created.
- *
- * @param {?string} status Notice status.
- * Defaults to `info`.
- * @param {string} content Notice message.
- * @param {?Object} options Notice options.
- * @param {?string} options.context Context under which to
- * group notice.
- * @param {?string} options.id Identifier for notice.
- * Automatically assigned
- * if not specified.
- * @param {?boolean} options.isDismissible Whether the notice can
- * be dismissed by user.
- * Defaults to `true`.
- * @param {?Array} options.actions User actions to be
- * presented with notice.
- */
-export function *createNotice (status = 'info', content, options = {}) {
- const {
- isDismissible = true,
- context = DEFAULT_CONTEXT,
- id = uniqueId(context),
- actions = [],
- } = options;
-
- yield { type: 'SPEAK', message: content };
-
- yield {
- type: 'CREATE_NOTICE',
- context,
- notice: {
- id,
- status,
- content,
- isDismissible,
- actions,
- },
- };
-}
-
-/**
- * Returns an action object used in signalling that a success notice is to be
- * created. Refer to `createNotice` for options documentation.
- *
- * @see createNotice
- *
- * @param {string} content Notice message.
- * @param {?Object} options Optional notice options.
- *
- * @return {Object} Action object.
- */
-export function createSuccessNotice (content, options) {
- return createNotice('success', content, options);
-}
-
-/**
- * Returns an action object used in signalling that an info notice is to be
- * created. Refer to `createNotice` for options documentation.
- *
- * @see createNotice
- *
- * @param {string} content Notice message.
- * @param {?Object} options Optional notice options.
- *
- * @return {Object} Action object.
- */
-export function createInfoNotice (content, options) {
- return createNotice('info', content, options);
-}
-
-/**
- * Returns an action object used in signalling that an error notice is to be
- * created. Refer to `createNotice` for options documentation.
- *
- * @see createNotice
- *
- * @param {string} content Notice message.
- * @param {?Object} options Optional notice options.
- *
- * @return {Object} Action object.
- */
-export function createErrorNotice (content, options) {
- return createNotice('error', content, options);
-}
-
-/**
- * Returns an action object used in signalling that a warning notice is to be
- * created. Refer to `createNotice` for options documentation.
- *
- * @see createNotice
- *
- * @param {string} content Notice message.
- * @param {?Object} options Optional notice options.
- *
- * @return {Object} Action object.
- */
-export function createWarningNotice (content, options) {
- return createNotice('warning', content, options);
-}
-
-/**
- * Returns an action object used in signalling that a notice is to be removed.
- *
- * @param {string} id Notice unique identifier.
- * @param {?string} context Optional context (grouping) in which the notice is
- * intended to appear. Defaults to default context.
- *
- * @return {Object} Action object.
- */
-export function removeNotice (id, context = DEFAULT_CONTEXT) {
- return {
- type: 'REMOVE_NOTICE',
- id,
- context,
- };
-}
diff --git a/src/js/index.js b/src/js/index.js
index 5116242..03d6bd2 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -7,35 +7,34 @@ import './init';
* WordPress dependencies
*/
import * as hooks from '@wordpress/hooks';
-import domReady from '@wordpress/dom-ready';
-import * as a11y from '@wordpress/a11y';
-import * as i18n from '@wordpress/i18n';
-// wp.i18n.setLocaleData
-
-import * as url from '@wordpress/url';
-import apiFetch from '@wordpress/api-fetch';
-import './scripts/api-fetch.js';
-
import * as autop from '@wordpress/autop';
import * as blob from '@wordpress/blob';
import * as blockSerializationDefaultParser from '@wordpress/block-serialization-default-parser';
-import deprecated from '@wordpress/deprecated';
+
import * as escapeHtml from '@wordpress/escape-html';
import * as element from '@wordpress/element';
import * as isShallowEqual from '@wordpress/is-shallow-equal';
import * as compose from '@wordpress/compose';
import * as reduxRoutine from '@wordpress/redux-routine';
-
import * as data from '@wordpress/data';
-import './scripts/data.js';
+import './scripts/data';
import * as dom from '@wordpress/dom';
+import * as htmlEntities from '@wordpress/html-entities';
+import * as i18n from '@wordpress/i18n';
+// wp.i18n.setLocaleData
import * as shortcode from '@wordpress/shortcode';
import * as blocks from '@wordpress/blocks';
// wp.blocks.setCategories
// wp.blocks.unstable__bootstrapServerSideBlockDefinitions
-import * as htmlEntities from '@wordpress/html-entities';
+import domReady from '@wordpress/dom-ready';
+import * as a11y from '@wordpress/a11y';
+import * as url from '@wordpress/url';
+import apiFetch from '@wordpress/api-fetch';
+import './scripts/api-fetch';
+
+import deprecated from '@wordpress/deprecated';
import * as keycodes from '@wordpress/keycodes';
import * as richText from '@wordpress/rich-text';
import * as components from '@wordpress/components';
@@ -54,6 +53,7 @@ import { editor, oldEditor } from './scripts/editor.js';
// window._wpGutenbergCodeEditorSettings
import * as plugins from '@wordpress/plugins';
+
import * as blockLibrary from '@wordpress/block-library';
import * as editPost from '@wordpress/edit-post';
import * as formatLibrary from '@wordpress/format-library';
diff --git a/src/scss/block-library.scss b/src/scss/block-library.scss
index 8773234..eda451b 100644
--- a/src/scss/block-library.scss
+++ b/src/scss/block-library.scss
@@ -3,8 +3,3 @@
/*
* TEMPORARY FIXES
*/
-
-// gutenberg/packages/block-library/src/media-text/style.scss
-.wp-block-media-text.has-media-on-the-right {
- grid-template-areas: "media-text-content media-text-media";
-}