UNPKG

@wordpress/editor

Version:
823 lines (707 loc) 23 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.setupEditor = setupEditor; exports.__experimentalTearDownEditor = __experimentalTearDownEditor; exports.resetPost = resetPost; exports.resetAutosave = resetAutosave; exports.__experimentalRequestPostUpdateStart = __experimentalRequestPostUpdateStart; exports.__experimentalRequestPostUpdateFinish = __experimentalRequestPostUpdateFinish; exports.updatePost = updatePost; exports.setupEditorState = setupEditorState; exports.editPost = editPost; exports.savePost = savePost; exports.refreshPost = refreshPost; exports.trashPost = trashPost; exports.autosave = autosave; exports.redo = redo; exports.undo = undo; exports.createUndoLevel = createUndoLevel; exports.updatePostLock = updatePostLock; exports.enablePublishSidebar = enablePublishSidebar; exports.disablePublishSidebar = disablePublishSidebar; exports.lockPostSaving = lockPostSaving; exports.unlockPostSaving = unlockPostSaving; exports.lockPostAutosaving = lockPostAutosaving; exports.unlockPostAutosaving = unlockPostAutosaving; exports.resetEditorBlocks = resetEditorBlocks; exports.updateEditorSettings = updateEditorSettings; exports.updateBlockListSettings = exports.insertDefaultBlock = exports.exitFormattedText = exports.enterFormattedText = exports.stopTyping = exports.startTyping = exports.toggleBlockMode = exports.removeBlock = exports.removeBlocks = exports.mergeBlocks = exports.synchronizeTemplate = exports.setTemplateValidity = exports.hideInsertionPoint = exports.showInsertionPoint = exports.insertBlocks = exports.insertBlock = exports.moveBlockToPosition = exports.moveBlocksUp = exports.moveBlocksDown = exports.replaceBlock = exports.replaceBlocks = exports.toggleSelection = exports.clearSelectedBlock = exports.multiSelect = exports.stopMultiSelect = exports.startMultiSelect = exports.selectBlock = exports.updateBlockAttributes = exports.updateBlock = exports.receiveBlocks = exports.resetBlocks = void 0; var _lodash = require("lodash"); var _deprecated = _interopRequireDefault(require("@wordpress/deprecated")); var _data = require("@wordpress/data"); var _dataControls = require("@wordpress/data-controls"); var _blocks = require("@wordpress/blocks"); var _notices = require("@wordpress/notices"); var _constants = require("./constants"); var _noticeBuilder = require("./utils/notice-builder"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Returns an action generator used in signalling that editor has initialized with * the specified post object and editor settings. * * @param {Object} post Post object. * @param {Object} edits Initial edited attributes object. * @param {Array?} template Block Template. */ function* setupEditor(post, edits, template) { // In order to ensure maximum of a single parse during setup, edits are // included as part of editor setup action. Assume edited content as // canonical if provided, falling back to post. let content; if ((0, _lodash.has)(edits, ['content'])) { content = edits.content; } else { content = post.content.raw; } let blocks = (0, _blocks.parse)(content); // Apply a template for new posts only, if exists. const isNewPost = post.status === 'auto-draft'; if (isNewPost && template) { blocks = (0, _blocks.synchronizeBlocksWithTemplate)(blocks, template); } yield resetPost(post); yield { type: 'SETUP_EDITOR', post, edits, template }; yield resetEditorBlocks(blocks, { __unstableShouldCreateUndoLevel: false }); yield setupEditorState(post); if (edits && Object.keys(edits).some(key => edits[key] !== ((0, _lodash.has)(post, [key, 'raw']) ? post[key].raw : post[key]))) { yield editPost(edits); } } /** * Returns an action object signalling that the editor is being destroyed and * that any necessary state or side-effect cleanup should occur. * * @return {Object} Action object. */ function __experimentalTearDownEditor() { return { type: 'TEAR_DOWN_EDITOR' }; } /** * Returns an action object used in signalling that the latest version of the * post has been received, either by initialization or save. * * @param {Object} post Post object. * * @return {Object} Action object. */ function resetPost(post) { return { type: 'RESET_POST', post }; } /** * Returns an action object used in signalling that the latest autosave of the * post has been received, by initialization or autosave. * * @deprecated since 5.6. Callers should use the `receiveAutosaves( postId, autosave )` * selector from the '@wordpress/core-data' package. * * @param {Object} newAutosave Autosave post object. * * @return {Object} Action object. */ function* resetAutosave(newAutosave) { (0, _deprecated.default)('resetAutosave action (`core/editor` store)', { since: '5.3', alternative: 'receiveAutosaves action (`core` store)' }); const postId = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPostId'); yield _data.controls.dispatch('core', 'receiveAutosaves', postId, newAutosave); return { type: '__INERT__' }; } /** * Action for dispatching that a post update request has started. * * @param {Object} options * * @return {Object} An action object */ function __experimentalRequestPostUpdateStart(options = {}) { return { type: 'REQUEST_POST_UPDATE_START', options }; } /** * Action for dispatching that a post update request has finished. * * @param {Object} options * * @return {Object} An action object */ function __experimentalRequestPostUpdateFinish(options = {}) { return { type: 'REQUEST_POST_UPDATE_FINISH', options }; } /** * Returns an action object used in signalling that a patch of updates for the * latest version of the post have been received. * * @return {Object} Action object. * @deprecated since Gutenberg 9.7.0. */ function updatePost() { (0, _deprecated.default)("wp.data.dispatch( 'core/editor' ).updatePost", { since: '5.7', alternative: 'User the core entitires store instead' }); return { type: 'DO_NOTHING' }; } /** * Returns an action object used to setup the editor state when first opening * an editor. * * @param {Object} post Post object. * * @return {Object} Action object. */ function setupEditorState(post) { return { type: 'SETUP_EDITOR_STATE', post }; } /** * Returns an action object used in signalling that attributes of the post have * been edited. * * @param {Object} edits Post attributes to edit. * @param {Object} options Options for the edit. * * @yield {Object} Action object or control. */ function* editPost(edits, options) { const { id, type } = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); yield _data.controls.dispatch('core', 'editEntityRecord', 'postType', type, id, edits, options); } /** * Action generator for saving the current post in the editor. * * @param {Object} options */ function* savePost(options = {}) { if (!(yield _data.controls.select(_constants.STORE_NAME, 'isEditedPostSaveable'))) { return; } let edits = { content: yield _data.controls.select(_constants.STORE_NAME, 'getEditedPostContent') }; if (!options.isAutosave) { yield _data.controls.dispatch(_constants.STORE_NAME, 'editPost', edits, { undoIgnore: true }); } yield __experimentalRequestPostUpdateStart(options); const previousRecord = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); edits = { id: previousRecord.id, ...(yield _data.controls.select('core', 'getEntityRecordNonTransientEdits', 'postType', previousRecord.type, previousRecord.id)), ...edits }; yield _data.controls.dispatch('core', 'saveEntityRecord', 'postType', previousRecord.type, edits, options); yield __experimentalRequestPostUpdateFinish(options); const error = yield _data.controls.select('core', 'getLastEntitySaveError', 'postType', previousRecord.type, previousRecord.id); if (error) { const args = (0, _noticeBuilder.getNotificationArgumentsForSaveFail)({ post: previousRecord, edits, error }); if (args.length) { yield _data.controls.dispatch(_notices.store, 'createErrorNotice', ...args); } } else { const updatedRecord = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); const args = (0, _noticeBuilder.getNotificationArgumentsForSaveSuccess)({ previousPost: previousRecord, post: updatedRecord, postType: yield _data.controls.resolveSelect('core', 'getPostType', updatedRecord.type), options }); if (args.length) { yield _data.controls.dispatch(_notices.store, 'createSuccessNotice', ...args); } // Make sure that any edits after saving create an undo level and are // considered for change detection. if (!options.isAutosave) { yield _data.controls.dispatch('core/block-editor', '__unstableMarkLastChangeAsPersistent'); } } } /** * Action generator for handling refreshing the current post. */ function* refreshPost() { const post = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); const postTypeSlug = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPostType'); const postType = yield _data.controls.resolveSelect('core', 'getPostType', postTypeSlug); const newPost = yield (0, _dataControls.apiFetch)({ // Timestamp arg allows caller to bypass browser caching, which is // expected for this specific function. path: `/wp/v2/${postType.rest_base}/${post.id}` + `?context=edit&_timestamp=${Date.now()}` }); yield _data.controls.dispatch(_constants.STORE_NAME, 'resetPost', newPost); } /** * Action generator for trashing the current post in the editor. */ function* trashPost() { const postTypeSlug = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPostType'); const postType = yield _data.controls.resolveSelect('core', 'getPostType', postTypeSlug); yield _data.controls.dispatch(_notices.store, 'removeNotice', _constants.TRASH_POST_NOTICE_ID); try { const post = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); yield (0, _dataControls.apiFetch)({ path: `/wp/v2/${postType.rest_base}/${post.id}`, method: 'DELETE' }); yield _data.controls.dispatch(_constants.STORE_NAME, 'savePost'); } catch (error) { yield _data.controls.dispatch(_notices.store, 'createErrorNotice', ...(0, _noticeBuilder.getNotificationArgumentsForTrashFail)({ error })); } } /** * Action generator used in signalling that the post should autosave. This * includes server-side autosaving (default) and client-side (a.k.a. local) * autosaving (e.g. on the Web, the post might be committed to Session * Storage). * * @param {Object?} options Extra flags to identify the autosave. */ function* autosave({ local = false, ...options } = {}) { if (local) { const post = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); const isPostNew = yield _data.controls.select(_constants.STORE_NAME, 'isEditedPostNew'); const title = yield _data.controls.select(_constants.STORE_NAME, 'getEditedPostAttribute', 'title'); const content = yield _data.controls.select(_constants.STORE_NAME, 'getEditedPostAttribute', 'content'); const excerpt = yield _data.controls.select(_constants.STORE_NAME, 'getEditedPostAttribute', 'excerpt'); yield { type: 'LOCAL_AUTOSAVE_SET', postId: post.id, isPostNew, title, content, excerpt }; } else { yield _data.controls.dispatch(_constants.STORE_NAME, 'savePost', { isAutosave: true, ...options }); } } /** * Returns an action object used in signalling that undo history should * restore last popped state. * * @yield {Object} Action object. */ function* redo() { yield _data.controls.dispatch('core', 'redo'); } /** * Returns an action object used in signalling that undo history should pop. * * @yield {Object} Action object. */ function* undo() { yield _data.controls.dispatch('core', 'undo'); } /** * Returns an action object used in signalling that undo history record should * be created. * * @return {Object} Action object. */ function createUndoLevel() { return { type: 'CREATE_UNDO_LEVEL' }; } /** * Returns an action object used to lock the editor. * * @param {Object} lock Details about the post lock status, user, and nonce. * * @return {Object} Action object. */ function updatePostLock(lock) { return { type: 'UPDATE_POST_LOCK', lock }; } /** * Returns an action object used in signalling that the user has enabled the * publish sidebar. * * @return {Object} Action object */ function enablePublishSidebar() { return { type: 'ENABLE_PUBLISH_SIDEBAR' }; } /** * Returns an action object used in signalling that the user has disabled the * publish sidebar. * * @return {Object} Action object */ function disablePublishSidebar() { return { type: 'DISABLE_PUBLISH_SIDEBAR' }; } /** * Returns an action object used to signal that post saving is locked. * * @param {string} lockName The lock name. * * @example * ``` * const { subscribe } = wp.data; * * const initialPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' ); * * // Only allow publishing posts that are set to a future date. * if ( 'publish' !== initialPostStatus ) { * * // Track locking. * let locked = false; * * // Watch for the publish event. * let unssubscribe = subscribe( () => { * const currentPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' ); * if ( 'publish' !== currentPostStatus ) { * * // Compare the post date to the current date, lock the post if the date isn't in the future. * const postDate = new Date( wp.data.select( 'core/editor' ).getEditedPostAttribute( 'date' ) ); * const currentDate = new Date(); * if ( postDate.getTime() <= currentDate.getTime() ) { * if ( ! locked ) { * locked = true; * wp.data.dispatch( 'core/editor' ).lockPostSaving( 'futurelock' ); * } * } else { * if ( locked ) { * locked = false; * wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'futurelock' ); * } * } * } * } ); * } * ``` * * @return {Object} Action object */ function lockPostSaving(lockName) { return { type: 'LOCK_POST_SAVING', lockName }; } /** * Returns an action object used to signal that post saving is unlocked. * * @param {string} lockName The lock name. * * @example * ``` * // Unlock post saving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'mylock' ); * ``` * * @return {Object} Action object */ function unlockPostSaving(lockName) { return { type: 'UNLOCK_POST_SAVING', lockName }; } /** * Returns an action object used to signal that post autosaving is locked. * * @param {string} lockName The lock name. * * @example * ``` * // Lock post autosaving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).lockPostAutosaving( 'mylock' ); * ``` * * @return {Object} Action object */ function lockPostAutosaving(lockName) { return { type: 'LOCK_POST_AUTOSAVING', lockName }; } /** * Returns an action object used to signal that post autosaving is unlocked. * * @param {string} lockName The lock name. * * @example * ``` * // Unlock post saving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).unlockPostAutosaving( 'mylock' ); * ``` * * @return {Object} Action object */ function unlockPostAutosaving(lockName) { return { type: 'UNLOCK_POST_AUTOSAVING', lockName }; } /** * Returns an action object used to signal that the blocks have been updated. * * @param {Array} blocks Block Array. * @param {?Object} options Optional options. * * @yield {Object} Action object */ function* resetEditorBlocks(blocks, options = {}) { const { __unstableShouldCreateUndoLevel, selection } = options; const edits = { blocks, selection }; if (__unstableShouldCreateUndoLevel !== false) { const { id, type } = yield _data.controls.select(_constants.STORE_NAME, 'getCurrentPost'); const noChange = (yield _data.controls.select('core', 'getEditedEntityRecord', 'postType', type, id)).blocks === edits.blocks; if (noChange) { return yield _data.controls.dispatch('core', '__unstableCreateUndoLevel', 'postType', type, id); } // We create a new function here on every persistent edit // to make sure the edit makes the post dirty and creates // a new undo level. edits.content = ({ blocks: blocksForSerialization = [] }) => (0, _blocks.__unstableSerializeAndClean)(blocksForSerialization); } yield* editPost(edits); } /* * Returns an action object used in signalling that the post editor settings have been updated. * * @param {Object} settings Updated settings * * @return {Object} Action object */ function updateEditorSettings(settings) { return { type: 'UPDATE_EDITOR_SETTINGS', settings }; } /** * Backward compatibility */ const getBlockEditorAction = name => function* (...args) { (0, _deprecated.default)("`wp.data.dispatch( 'core/editor' )." + name + '`', { since: '5.3', alternative: "`wp.data.dispatch( 'core/block-editor' )." + name + '`' }); yield _data.controls.dispatch('core/block-editor', name, ...args); }; /** * @see resetBlocks in core/block-editor store. */ const resetBlocks = getBlockEditorAction('resetBlocks'); /** * @see receiveBlocks in core/block-editor store. */ exports.resetBlocks = resetBlocks; const receiveBlocks = getBlockEditorAction('receiveBlocks'); /** * @see updateBlock in core/block-editor store. */ exports.receiveBlocks = receiveBlocks; const updateBlock = getBlockEditorAction('updateBlock'); /** * @see updateBlockAttributes in core/block-editor store. */ exports.updateBlock = updateBlock; const updateBlockAttributes = getBlockEditorAction('updateBlockAttributes'); /** * @see selectBlock in core/block-editor store. */ exports.updateBlockAttributes = updateBlockAttributes; const selectBlock = getBlockEditorAction('selectBlock'); /** * @see startMultiSelect in core/block-editor store. */ exports.selectBlock = selectBlock; const startMultiSelect = getBlockEditorAction('startMultiSelect'); /** * @see stopMultiSelect in core/block-editor store. */ exports.startMultiSelect = startMultiSelect; const stopMultiSelect = getBlockEditorAction('stopMultiSelect'); /** * @see multiSelect in core/block-editor store. */ exports.stopMultiSelect = stopMultiSelect; const multiSelect = getBlockEditorAction('multiSelect'); /** * @see clearSelectedBlock in core/block-editor store. */ exports.multiSelect = multiSelect; const clearSelectedBlock = getBlockEditorAction('clearSelectedBlock'); /** * @see toggleSelection in core/block-editor store. */ exports.clearSelectedBlock = clearSelectedBlock; const toggleSelection = getBlockEditorAction('toggleSelection'); /** * @see replaceBlocks in core/block-editor store. */ exports.toggleSelection = toggleSelection; const replaceBlocks = getBlockEditorAction('replaceBlocks'); /** * @see replaceBlock in core/block-editor store. */ exports.replaceBlocks = replaceBlocks; const replaceBlock = getBlockEditorAction('replaceBlock'); /** * @see moveBlocksDown in core/block-editor store. */ exports.replaceBlock = replaceBlock; const moveBlocksDown = getBlockEditorAction('moveBlocksDown'); /** * @see moveBlocksUp in core/block-editor store. */ exports.moveBlocksDown = moveBlocksDown; const moveBlocksUp = getBlockEditorAction('moveBlocksUp'); /** * @see moveBlockToPosition in core/block-editor store. */ exports.moveBlocksUp = moveBlocksUp; const moveBlockToPosition = getBlockEditorAction('moveBlockToPosition'); /** * @see insertBlock in core/block-editor store. */ exports.moveBlockToPosition = moveBlockToPosition; const insertBlock = getBlockEditorAction('insertBlock'); /** * @see insertBlocks in core/block-editor store. */ exports.insertBlock = insertBlock; const insertBlocks = getBlockEditorAction('insertBlocks'); /** * @see showInsertionPoint in core/block-editor store. */ exports.insertBlocks = insertBlocks; const showInsertionPoint = getBlockEditorAction('showInsertionPoint'); /** * @see hideInsertionPoint in core/block-editor store. */ exports.showInsertionPoint = showInsertionPoint; const hideInsertionPoint = getBlockEditorAction('hideInsertionPoint'); /** * @see setTemplateValidity in core/block-editor store. */ exports.hideInsertionPoint = hideInsertionPoint; const setTemplateValidity = getBlockEditorAction('setTemplateValidity'); /** * @see synchronizeTemplate in core/block-editor store. */ exports.setTemplateValidity = setTemplateValidity; const synchronizeTemplate = getBlockEditorAction('synchronizeTemplate'); /** * @see mergeBlocks in core/block-editor store. */ exports.synchronizeTemplate = synchronizeTemplate; const mergeBlocks = getBlockEditorAction('mergeBlocks'); /** * @see removeBlocks in core/block-editor store. */ exports.mergeBlocks = mergeBlocks; const removeBlocks = getBlockEditorAction('removeBlocks'); /** * @see removeBlock in core/block-editor store. */ exports.removeBlocks = removeBlocks; const removeBlock = getBlockEditorAction('removeBlock'); /** * @see toggleBlockMode in core/block-editor store. */ exports.removeBlock = removeBlock; const toggleBlockMode = getBlockEditorAction('toggleBlockMode'); /** * @see startTyping in core/block-editor store. */ exports.toggleBlockMode = toggleBlockMode; const startTyping = getBlockEditorAction('startTyping'); /** * @see stopTyping in core/block-editor store. */ exports.startTyping = startTyping; const stopTyping = getBlockEditorAction('stopTyping'); /** * @see enterFormattedText in core/block-editor store. */ exports.stopTyping = stopTyping; const enterFormattedText = getBlockEditorAction('enterFormattedText'); /** * @see exitFormattedText in core/block-editor store. */ exports.enterFormattedText = enterFormattedText; const exitFormattedText = getBlockEditorAction('exitFormattedText'); /** * @see insertDefaultBlock in core/block-editor store. */ exports.exitFormattedText = exitFormattedText; const insertDefaultBlock = getBlockEditorAction('insertDefaultBlock'); /** * @see updateBlockListSettings in core/block-editor store. */ exports.insertDefaultBlock = insertDefaultBlock; const updateBlockListSettings = getBlockEditorAction('updateBlockListSettings'); exports.updateBlockListSettings = updateBlockListSettings; //# sourceMappingURL=actions.js.map