@wordpress/editor 14.41.2-next.v.202603161435.0 → 14.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/build/components/collaborators-overlay/compute-selection.cjs +10 -10
- package/build/components/collaborators-overlay/compute-selection.cjs.map +2 -2
- package/build/components/collaborators-overlay/overlay.cjs +11 -0
- package/build/components/collaborators-overlay/overlay.cjs.map +2 -2
- package/build/components/collaborators-overlay/timing-utils.cjs +46 -0
- package/build/components/collaborators-overlay/timing-utils.cjs.map +7 -0
- package/build/components/collaborators-overlay/use-render-cursors.cjs +1 -1
- package/build/components/collaborators-overlay/use-render-cursors.cjs.map +2 -2
- package/build/components/post-locked-modal/index.cjs +16 -3
- package/build/components/post-locked-modal/index.cjs.map +2 -2
- package/build/components/post-revisions-preview/block-diff.cjs +39 -11
- package/build/components/post-revisions-preview/block-diff.cjs.map +2 -2
- package/build/components/post-revisions-preview/diff-markers.cjs +2 -2
- package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
- package/build/components/post-revisions-preview/revisions-canvas.cjs +1 -1
- package/build/components/post-revisions-preview/revisions-canvas.cjs.map +2 -2
- package/build/components/post-template/block-theme.cjs +7 -4
- package/build/components/post-template/block-theme.cjs.map +2 -2
- package/build/components/post-template/hooks.cjs +39 -2
- package/build/components/post-template/hooks.cjs.map +2 -2
- package/build/components/post-template/panel.cjs +5 -42
- package/build/components/post-template/panel.cjs.map +3 -3
- package/build/components/provider/use-block-editor-settings.cjs +2 -0
- package/build/components/provider/use-block-editor-settings.cjs.map +3 -3
- package/build/components/revision-block-diff/index.cjs +84 -0
- package/build/components/revision-block-diff/index.cjs.map +7 -0
- package/build/components/sidebar/dataform-post-summary.cjs +17 -2
- package/build/components/sidebar/dataform-post-summary.cjs.map +2 -2
- package/build/components/sidebar/index.cjs +5 -1
- package/build/components/sidebar/index.cjs.map +3 -3
- package/build/components/{sync-connection-modal → sync-connection-error-modal}/index.cjs +87 -78
- package/build/components/sync-connection-error-modal/index.cjs.map +7 -0
- package/build/components/{sync-connection-modal → sync-connection-error-modal}/use-retry-countdown.cjs +14 -27
- package/build/components/sync-connection-error-modal/use-retry-countdown.cjs.map +7 -0
- package/build/components/visual-editor/index.cjs +2 -2
- package/build/components/visual-editor/index.cjs.map +2 -2
- package/build/store/actions.cjs +1 -3
- package/build/store/actions.cjs.map +2 -2
- package/build/utils/media-finalize/index.cjs +43 -0
- package/build/utils/media-finalize/index.cjs.map +7 -0
- package/build/utils/sync-error-messages.cjs +29 -16
- package/build/utils/sync-error-messages.cjs.map +3 -3
- package/build-module/components/collaborators-overlay/compute-selection.mjs +10 -10
- package/build-module/components/collaborators-overlay/compute-selection.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/overlay.mjs +11 -0
- package/build-module/components/collaborators-overlay/overlay.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/timing-utils.mjs +21 -0
- package/build-module/components/collaborators-overlay/timing-utils.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/use-render-cursors.mjs +1 -1
- package/build-module/components/collaborators-overlay/use-render-cursors.mjs.map +2 -2
- package/build-module/components/post-locked-modal/index.mjs +16 -3
- package/build-module/components/post-locked-modal/index.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/block-diff.mjs +39 -11
- package/build-module/components/post-revisions-preview/block-diff.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/diff-markers.mjs +2 -2
- package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/revisions-canvas.mjs +1 -1
- package/build-module/components/post-revisions-preview/revisions-canvas.mjs.map +2 -2
- package/build-module/components/post-template/block-theme.mjs +7 -4
- package/build-module/components/post-template/block-theme.mjs.map +2 -2
- package/build-module/components/post-template/hooks.mjs +37 -1
- package/build-module/components/post-template/hooks.mjs.map +2 -2
- package/build-module/components/post-template/panel.mjs +5 -42
- package/build-module/components/post-template/panel.mjs.map +2 -2
- package/build-module/components/provider/use-block-editor-settings.mjs +2 -0
- package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
- package/build-module/components/revision-block-diff/index.mjs +53 -0
- package/build-module/components/revision-block-diff/index.mjs.map +7 -0
- package/build-module/components/sidebar/dataform-post-summary.mjs +17 -2
- package/build-module/components/sidebar/dataform-post-summary.mjs.map +2 -2
- package/build-module/components/sidebar/index.mjs +5 -1
- package/build-module/components/sidebar/index.mjs.map +2 -2
- package/build-module/components/sync-connection-error-modal/index.mjs +177 -0
- package/build-module/components/sync-connection-error-modal/index.mjs.map +7 -0
- package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs +36 -0
- package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs.map +7 -0
- package/build-module/components/visual-editor/index.mjs +2 -2
- package/build-module/components/visual-editor/index.mjs.map +2 -2
- package/build-module/store/actions.mjs +1 -3
- package/build-module/store/actions.mjs.map +2 -2
- package/build-module/utils/media-finalize/index.mjs +12 -0
- package/build-module/utils/media-finalize/index.mjs.map +7 -0
- package/build-module/utils/sync-error-messages.mjs +24 -16
- package/build-module/utils/sync-error-messages.mjs.map +3 -3
- package/build-style/style-rtl.css +24 -8
- package/build-style/style.css +24 -8
- package/build-types/components/collaborators-overlay/overlay.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/timing-utils.d.ts +11 -0
- package/build-types/components/collaborators-overlay/timing-utils.d.ts.map +1 -0
- package/build-types/components/post-locked-modal/index.d.ts +2 -2
- package/build-types/components/post-locked-modal/index.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/block-diff.d.ts.map +1 -1
- package/build-types/components/post-template/block-theme.d.ts +1 -3
- package/build-types/components/post-template/block-theme.d.ts.map +1 -1
- package/build-types/components/post-template/hooks.d.ts +1 -0
- package/build-types/components/post-template/hooks.d.ts.map +1 -1
- package/build-types/components/post-template/panel.d.ts.map +1 -1
- package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
- package/build-types/components/revision-block-diff/index.d.ts +6 -0
- package/build-types/components/revision-block-diff/index.d.ts.map +1 -0
- package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -1
- package/build-types/components/sidebar/index.d.ts.map +1 -1
- package/build-types/components/sync-connection-error-modal/index.d.ts +22 -0
- package/build-types/components/sync-connection-error-modal/index.d.ts.map +1 -0
- package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts +11 -0
- package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts.map +1 -0
- package/build-types/store/actions.d.ts.map +1 -1
- package/build-types/utils/media-finalize/index.d.ts +2 -0
- package/build-types/utils/media-finalize/index.d.ts.map +1 -0
- package/build-types/utils/sync-error-messages.d.ts +17 -3
- package/build-types/utils/sync-error-messages.d.ts.map +1 -1
- package/package.json +44 -44
- package/src/components/collaborators-overlay/compute-selection.ts +13 -13
- package/src/components/collaborators-overlay/overlay.tsx +19 -0
- package/src/components/collaborators-overlay/timing-utils.ts +30 -0
- package/src/components/collaborators-overlay/use-render-cursors.ts +1 -1
- package/src/components/post-locked-modal/index.js +21 -3
- package/src/components/post-revisions-preview/block-diff.js +59 -20
- package/src/components/post-revisions-preview/diff-markers.js +2 -2
- package/src/components/post-revisions-preview/revisions-canvas.js +1 -1
- package/src/components/post-revisions-preview/test/block-diff.js +69 -31
- package/src/components/post-template/block-theme.js +4 -1
- package/src/components/post-template/hooks.js +42 -0
- package/src/components/post-template/panel.js +5 -59
- package/src/components/provider/use-block-editor-settings.js +2 -0
- package/src/components/revision-block-diff/index.js +74 -0
- package/src/components/revision-block-diff/style.scss +13 -0
- package/src/components/sidebar/dataform-post-summary.js +37 -13
- package/src/components/sidebar/index.js +2 -0
- package/src/components/sync-connection-error-modal/index.tsx +265 -0
- package/src/components/sync-connection-error-modal/style.scss +14 -0
- package/src/components/sync-connection-error-modal/use-retry-countdown.ts +57 -0
- package/src/components/visual-editor/index.js +2 -2
- package/src/store/actions.js +1 -4
- package/src/style.scss +2 -1
- package/src/utils/media-finalize/index.js +11 -0
- package/src/utils/media-finalize/test/index.js +34 -0
- package/src/utils/sync-error-messages.ts +72 -0
- package/src/utils/test/sync-error-messages.js +9 -32
- package/build/components/sync-connection-modal/index.cjs.map +0 -7
- package/build/components/sync-connection-modal/use-retry-countdown.cjs.map +0 -7
- package/build-module/components/sync-connection-modal/index.mjs +0 -170
- package/build-module/components/sync-connection-modal/index.mjs.map +0 -7
- package/build-module/components/sync-connection-modal/use-retry-countdown.mjs +0 -49
- package/build-module/components/sync-connection-modal/use-retry-countdown.mjs.map +0 -7
- package/build-types/components/sync-connection-modal/index.d.ts +0 -8
- package/build-types/components/sync-connection-modal/index.d.ts.map +0 -1
- package/build-types/components/sync-connection-modal/use-retry-countdown.d.ts +0 -9
- package/build-types/components/sync-connection-modal/use-retry-countdown.d.ts.map +0 -1
- package/src/components/sync-connection-modal/index.js +0 -206
- package/src/components/sync-connection-modal/style.scss +0 -14
- package/src/components/sync-connection-modal/use-retry-countdown.js +0 -70
- package/src/utils/sync-error-messages.js +0 -58
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-revisions-preview/block-diff.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * External dependencies\n */\nimport { diffArrays } from 'diff/lib/diff/array';\nimport { diffWords } from 'diff/lib/diff/word';\n\n/**\n * WordPress dependencies\n */\nimport { parse as grammarParse } from '@wordpress/block-serialization-default-parser';\nimport {\n\tprivateApis as blocksPrivateApis,\n\tgetBlockType,\n} from '@wordpress/blocks';\nimport {\n\tRichTextData,\n\tcreate,\n\tslice,\n\tconcat,\n\tapplyFormat,\n} from '@wordpress/rich-text';\nimport { __, _n, sprintf } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { parseRawBlock } = unlock( blocksPrivateApis );\n\n/**\n * Calculate text similarity using word diff (semantically meaningful).\n * Returns ratio of unchanged words to total words.\n *\n * @param {string} text1 First text to compare.\n * @param {string} text2 Second text to compare.\n * @return {number} Similarity score between 0 and 1.\n */\nfunction textSimilarity( text1, text2 ) {\n\tif ( ! text1 && ! text2 ) {\n\t\treturn 1;\n\t}\n\tif ( ! text1 || ! text2 ) {\n\t\treturn 0;\n\t}\n\n\tconst changes = diffWords( text1, text2 );\n\tconst unchanged = changes\n\t\t.filter( ( c ) => ! c.added && ! c.removed )\n\t\t.reduce( ( sum, c ) => sum + c.value.length, 0 );\n\tconst total = Math.max( text1.length, text2.length );\n\treturn total > 0 ? unchanged / total : 0;\n}\n\n/**\n * Post-process diff result to pair similar removed/added blocks as modifications.\n * This catches modifications that LCS missed due to content changes.\n *\n * @param {Array} blocks Raw blocks with diff status.\n * @return {Array} Blocks with similar pairs converted to modifications.\n */\nfunction pairSimilarBlocks( blocks ) {\n\tconst removed = [];\n\tconst added = [];\n\n\t// Separate blocks by status, tracking original indices.\n\tblocks.forEach( ( block, index ) => {\n\t\tconst status = block.__revisionDiffStatus;\n\t\tif ( status === 'removed' ) {\n\t\t\tremoved.push( { block, index } );\n\t\t} else if ( status === 'added' ) {\n\t\t\tadded.push( { block, index } );\n\t\t}\n\t} );\n\n\t// If no removed or no added, nothing to pair.\n\tif ( removed.length === 0 || added.length === 0 ) {\n\t\treturn blocks;\n\t}\n\n\tconst pairedRemoved = new Set(); // Indices of removed blocks that were paired.\n\tconst modifications = new Map(); // Map from added block index to modified block.\n\tconst SIMILARITY_THRESHOLD = 0.3;\n\n\t// For each removed block, find best matching added block.\n\tfor ( const rem of removed ) {\n\t\tlet bestMatch = null;\n\t\tlet bestScore = 0;\n\n\t\tfor ( const add of added ) {\n\t\t\tif ( modifications.has( add.index ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( add.block.blockName !== rem.block.blockName ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst score = textSimilarity(\n\t\t\t\trem.block.innerHTML || '',\n\t\t\t\tadd.block.innerHTML || ''\n\t\t\t);\n\t\t\t// If content is identical (score=1), only pair if attrs differ.\n\t\t\t// Otherwise identical blocks are just position swaps, not modifications.\n\t\t\tconst attrsMatch =\n\t\t\t\tJSON.stringify( rem.block.attrs ) ===\n\t\t\t\tJSON.stringify( add.block.attrs );\n\t\t\tif (\n\t\t\t\tscore > bestScore &&\n\t\t\t\tscore > SIMILARITY_THRESHOLD &&\n\t\t\t\t( score < 1 || ! attrsMatch )\n\t\t\t) {\n\t\t\t\tbestScore = score;\n\t\t\t\tbestMatch = add;\n\t\t\t}\n\t\t}\n\n\t\tif ( bestMatch ) {\n\t\t\tpairedRemoved.add( rem.index );\n\n\t\t\t// Create modified block with previous content stored.\n\t\t\tmodifications.set( bestMatch.index, {\n\t\t\t\t...bestMatch.block,\n\t\t\t\t__revisionDiffStatus: 'modified',\n\t\t\t\t__previousRawBlock: rem.block,\n\t\t\t} );\n\t\t}\n\t}\n\n\t// Rebuild result: filter out paired removed, replace paired added with modified.\n\treturn blocks\n\t\t.map( ( block, index ) => {\n\t\t\t// Skip paired removed blocks.\n\t\t\tif ( pairedRemoved.has( index ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t// Replace paired added blocks with modified version.\n\t\t\tif ( modifications.has( index ) ) {\n\t\t\t\treturn modifications.get( index );\n\t\t\t}\n\t\t\treturn block;\n\t\t} )\n\t\t.filter( Boolean );\n}\n\n/**\n * Diff raw block arrays using LCS, recursively handling innerBlocks.\n * Detects modifications when exactly 1 block is removed and 1 is added\n * with the same blockName (1:1 replacement = modification).\n *\n * @param {Array} currentRaw Current revision's raw blocks.\n * @param {Array} previousRaw Previous revision's raw blocks.\n * @return {Array} Merged raw blocks with diff status injected.\n */\nfunction diffRawBlocks( currentRaw, previousRaw ) {\n\tconst createBlockSignature = ( rawBlock ) =>\n\t\tJSON.stringify( {\n\t\t\tname: rawBlock.blockName,\n\t\t\tattrs: rawBlock.attrs,\n\t\t\t// Use innerContent filtered to non-null and non-whitespace-only strings.\n\t\t\t// This excludes whitespace between inner blocks which changes based on count.\n\t\t\thtml: ( rawBlock.innerContent || [] ).filter(\n\t\t\t\t( c ) => c !== null && c.trim() !== ''\n\t\t\t),\n\t\t} );\n\tconst currentSigs = currentRaw.map( createBlockSignature );\n\tconst previousSigs = previousRaw.map( createBlockSignature );\n\n\tconst diff = diffArrays( previousSigs, currentSigs );\n\n\tconst result = [];\n\tlet currIdx = 0;\n\tlet prevIdx = 0;\n\n\tfor ( const part of diff ) {\n\t\tif ( part.added ) {\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\t...currentRaw[ currIdx++ ],\n\t\t\t\t\t__revisionDiffStatus: 'added',\n\t\t\t\t} );\n\t\t\t}\n\t\t} else if ( part.removed ) {\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\t...previousRaw[ prevIdx++ ],\n\t\t\t\t\t__revisionDiffStatus: 'removed',\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\t// Matched blocks - recursively diff their innerBlocks.\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tconst currBlock = currentRaw[ currIdx++ ];\n\t\t\t\tconst prevBlock = previousRaw[ prevIdx++ ];\n\n\t\t\t\t// Recursively diff inner blocks.\n\t\t\t\tconst diffedInnerBlocks = diffRawBlocks(\n\t\t\t\t\tcurrBlock.innerBlocks || [],\n\t\t\t\t\tprevBlock.innerBlocks || []\n\t\t\t\t);\n\n\t\t\t\tresult.push( {\n\t\t\t\t\t...currBlock,\n\t\t\t\t\tinnerBlocks: diffedInnerBlocks,\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Post-process to pair similar removed/added blocks as modifications.\n\treturn pairSimilarBlocks( result );\n}\n\n/**\n * Check if formatting has changed at specific character indices.\n *\n * @param {Array} currentFormats Current formats array.\n * @param {Array} previousFormats Previous formats array.\n * @param {number} currentIndex Character index in current.\n * @param {number} previousIndex Character index in previous.\n * @return {boolean} True if formatting changed at these indices.\n */\nfunction hasFormatChangedAtIndex(\n\tcurrentFormats,\n\tpreviousFormats,\n\tcurrentIndex,\n\tpreviousIndex\n) {\n\tconst currFmts = currentFormats[ currentIndex ] || [];\n\tconst prevFmts = previousFormats[ previousIndex ] || [];\n\n\tif ( currFmts.length !== prevFmts.length ) {\n\t\treturn true;\n\t}\n\n\t// Check if each format in current exists in previous\n\tfor ( const fmt of currFmts ) {\n\t\tconst match = prevFmts.find(\n\t\t\t( pf ) =>\n\t\t\t\tpf.type === fmt.type &&\n\t\t\t\tJSON.stringify( pf.attributes ) ===\n\t\t\t\t\tJSON.stringify( fmt.attributes )\n\t\t);\n\t\tif ( ! match ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Analyze what formatting changed between two character positions.\n * Returns both the change type (for styling) and a description (for tooltip).\n *\n * @param {Array} currentFormats Current formats array.\n * @param {Array} previousFormats Previous formats array.\n * @param {number} currIdx Character index in current.\n * @param {number} prevIdx Character index in previous.\n * @return {{ type: 'added'|'removed'|'changed', description: string }} Change info.\n */\nfunction describeFormatChange(\n\tcurrentFormats,\n\tpreviousFormats,\n\tcurrIdx,\n\tprevIdx\n) {\n\tconst currFmts = currentFormats[ currIdx ] || [];\n\tconst prevFmts = previousFormats[ prevIdx ] || [];\n\n\tlet addedCount = 0;\n\tlet removedCount = 0;\n\tlet changedCount = 0;\n\n\t// Find added formats and attribute changes\n\tfor ( const fmt of currFmts ) {\n\t\tconst match = prevFmts.find( ( pf ) => pf.type === fmt.type );\n\t\tif ( ! match ) {\n\t\t\taddedCount++;\n\t\t} else if (\n\t\t\tJSON.stringify( fmt.attributes ) !==\n\t\t\tJSON.stringify( match.attributes )\n\t\t) {\n\t\t\tchangedCount++;\n\t\t}\n\t}\n\n\t// Find removed formats\n\tfor ( const fmt of prevFmts ) {\n\t\tconst match = currFmts.find( ( cf ) => cf.type === fmt.type );\n\t\tif ( ! match ) {\n\t\t\tremovedCount++;\n\t\t}\n\t}\n\n\t// Determine primary change type for styling\n\tif ( addedCount > 0 && removedCount === 0 && changedCount === 0 ) {\n\t\treturn {\n\t\t\ttype: 'added',\n\t\t\tdescription: sprintf(\n\t\t\t\t/* translators: %d: number of formats added */\n\t\t\t\t_n( '%d format added', '%d formats added', addedCount ),\n\t\t\t\taddedCount\n\t\t\t),\n\t\t};\n\t}\n\tif ( removedCount > 0 && addedCount === 0 && changedCount === 0 ) {\n\t\treturn {\n\t\t\ttype: 'removed',\n\t\t\tdescription: sprintf(\n\t\t\t\t/* translators: %d: number of formats removed */\n\t\t\t\t_n( '%d format removed', '%d formats removed', removedCount ),\n\t\t\t\tremovedCount\n\t\t\t),\n\t\t};\n\t}\n\n\t// Mixed or attribute-only changes\n\tconst parts = [];\n\tif ( addedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats added */\n\t\t\t\t_n( '%d format added', '%d formats added', addedCount ),\n\t\t\t\taddedCount\n\t\t\t)\n\t\t);\n\t}\n\tif ( removedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats removed */\n\t\t\t\t_n( '%d format removed', '%d formats removed', removedCount ),\n\t\t\t\tremovedCount\n\t\t\t)\n\t\t);\n\t}\n\tif ( changedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats changed */\n\t\t\t\t_n( '%d format changed', '%d formats changed', changedCount ),\n\t\t\t\tchangedCount\n\t\t\t)\n\t\t);\n\t}\n\treturn {\n\t\ttype: 'changed',\n\t\tdescription: parts.join( ', ' ) || __( 'Formatting changed' ),\n\t};\n}\n\n/**\n * Apply inline diff formatting comparing two RichTextData values.\n * - Text changes: apply revision/diff-removed and revision/diff-added formats\n * - Format-only changes (text unchanged): apply revision/diff-format-changed format\n *\n * @param {RichTextData} currentRichText Current revision's rich text.\n * @param {RichTextData} previousRichText Previous revision's rich text.\n * @return {RichTextData} New rich text with diff formatting applied.\n */\nfunction applyRichTextDiff( currentRichText, previousRichText ) {\n\tconst currentText = currentRichText.toPlainText();\n\tconst previousText = previousRichText.toPlainText();\n\n\t// Diff the plain text (words for cleaner output)\n\tconst textDiff = diffWords( previousText, currentText );\n\n\tlet result = create( { text: '' } );\n\tlet currentIdx = 0;\n\tlet previousIdx = 0;\n\n\tfor ( const part of textDiff ) {\n\t\tif ( part.removed ) {\n\t\t\t// Text deleted - slice from PREVIOUS, apply <del>\n\t\t\tconst removedSlice = slice(\n\t\t\t\tpreviousRichText,\n\t\t\t\tpreviousIdx,\n\t\t\t\tpreviousIdx + part.value.length\n\t\t\t);\n\t\t\tconst formatted = applyFormat(\n\t\t\t\tremovedSlice,\n\t\t\t\t{\n\t\t\t\t\ttype: 'revision/diff-removed',\n\t\t\t\t\tattributes: { title: __( 'Removed' ) },\n\t\t\t\t},\n\t\t\t\t0,\n\t\t\t\tpart.value.length\n\t\t\t);\n\t\t\tresult = concat( result, formatted );\n\t\t\tpreviousIdx += part.value.length;\n\t\t} else if ( part.added ) {\n\t\t\t// Text added - slice from CURRENT, apply <ins>\n\t\t\tconst addedSlice = slice(\n\t\t\t\tcurrentRichText,\n\t\t\t\tcurrentIdx,\n\t\t\t\tcurrentIdx + part.value.length\n\t\t\t);\n\t\t\tconst formatted = applyFormat(\n\t\t\t\taddedSlice,\n\t\t\t\t{\n\t\t\t\t\ttype: 'revision/diff-added',\n\t\t\t\t\tattributes: { title: __( 'Added' ) },\n\t\t\t\t},\n\t\t\t\t0,\n\t\t\t\tpart.value.length\n\t\t\t);\n\t\t\tresult = concat( result, formatted );\n\t\t\tcurrentIdx += part.value.length;\n\t\t} else {\n\t\t\t// Text unchanged - check formatting at each character position.\n\t\t\t// Only apply <mark> to specific ranges where formatting differs.\n\t\t\tconst currentFormats = currentRichText.formats || [];\n\t\t\tconst previousFormats = previousRichText.formats || [];\n\t\t\tconst len = part.value.length;\n\n\t\t\t// Helper to check format change at offset within this unchanged part.\n\t\t\tconst checkFormatChanged = ( offset ) =>\n\t\t\t\thasFormatChangedAtIndex(\n\t\t\t\t\tcurrentFormats,\n\t\t\t\t\tpreviousFormats,\n\t\t\t\t\tcurrentIdx + offset,\n\t\t\t\t\tpreviousIdx + offset\n\t\t\t\t);\n\n\t\t\t// Find ranges of characters grouped by whether format changed.\n\t\t\tlet rangeStart = 0;\n\t\t\tlet rangeFormatChanged = checkFormatChanged( 0 );\n\n\t\t\tfor ( let i = 1; i <= len; i++ ) {\n\t\t\t\tconst formatChanged = i < len && checkFormatChanged( i );\n\n\t\t\t\t// When format-changed status changes or we reach the end, emit range.\n\t\t\t\tif ( i === len || formatChanged !== rangeFormatChanged ) {\n\t\t\t\t\tconst rangeSlice = slice(\n\t\t\t\t\t\tcurrentRichText,\n\t\t\t\t\t\tcurrentIdx + rangeStart,\n\t\t\t\t\t\tcurrentIdx + i\n\t\t\t\t\t);\n\n\t\t\t\t\tif ( rangeFormatChanged ) {\n\t\t\t\t\t\t// Get type and description of what changed\n\t\t\t\t\t\tconst { type, description } = describeFormatChange(\n\t\t\t\t\t\t\tcurrentFormats,\n\t\t\t\t\t\t\tpreviousFormats,\n\t\t\t\t\t\t\tcurrentIdx + rangeStart,\n\t\t\t\t\t\t\tpreviousIdx + rangeStart\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Map change type to format type for styling\n\t\t\t\t\t\tconst formatType = {\n\t\t\t\t\t\t\tadded: 'revision/diff-format-added',\n\t\t\t\t\t\t\tremoved: 'revision/diff-format-removed',\n\t\t\t\t\t\t\tchanged: 'revision/diff-format-changed',\n\t\t\t\t\t\t}[ type ];\n\n\t\t\t\t\t\tconst marked = applyFormat(\n\t\t\t\t\t\t\trangeSlice,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: formatType,\n\t\t\t\t\t\t\t\tattributes: { title: description },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\ti - rangeStart\n\t\t\t\t\t\t);\n\t\t\t\t\t\tresult = concat( result, marked );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = concat( result, rangeSlice );\n\t\t\t\t\t}\n\n\t\t\t\t\trangeStart = i;\n\t\t\t\t\trangeFormatChanged = formatChanged;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrentIdx += part.value.length;\n\t\t\tpreviousIdx += part.value.length;\n\t\t}\n\t}\n\n\treturn new RichTextData( result );\n}\n\n/**\n * Apply rich text diff to all rich-text attributes of a block.\n * Compares each rich-text attribute between current and previous parsed blocks.\n *\n * @param {Object} currentBlock Current parsed block.\n * @param {Object} previousBlock Previous parsed block.\n */\nfunction applyRichTextDiffToBlock( currentBlock, previousBlock ) {\n\tconst blockType = getBlockType( currentBlock.name );\n\tif ( ! blockType ) {\n\t\treturn;\n\t}\n\n\t// Find rich-text attributes and compare\n\tfor ( const [ attrName, attrDef ] of Object.entries(\n\t\tblockType.attributes\n\t) ) {\n\t\tif ( attrDef.source === 'rich-text' ) {\n\t\t\tconst currentRichText = currentBlock.attributes[ attrName ];\n\t\t\tconst previousRichText = previousBlock.attributes[ attrName ];\n\n\t\t\tif (\n\t\t\t\tcurrentRichText instanceof RichTextData &&\n\t\t\t\tpreviousRichText instanceof RichTextData\n\t\t\t) {\n\t\t\t\tcurrentBlock.attributes[ attrName ] = applyRichTextDiff(\n\t\t\t\t\tcurrentRichText,\n\t\t\t\t\tpreviousRichText\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Recursively apply diff status and rich text diff to blocks in the tree.\n * Copies __revisionDiffStatus from raw blocks to parsed blocks and applies\n * rich text diffs to modified blocks.\n *\n * @param {Object} parsedBlock Parsed block (with inner blocks).\n * @param {Object} rawBlock Raw block (with __revisionDiffStatus and __previousRawBlock).\n */\nfunction applyDiffRecursively( parsedBlock, rawBlock ) {\n\t// Copy diff status from raw block to parsed block.\n\tif ( rawBlock.__revisionDiffStatus ) {\n\t\tparsedBlock.__revisionDiffStatus = rawBlock.__revisionDiffStatus;\n\t}\n\n\t// Apply rich text diff if this block is modified and has a previous raw block.\n\tif (\n\t\trawBlock.__revisionDiffStatus === 'modified' &&\n\t\trawBlock.__previousRawBlock\n\t) {\n\t\tconst previousParsed = parseRawBlock( rawBlock.__previousRawBlock );\n\t\tif ( previousParsed ) {\n\t\t\tapplyRichTextDiffToBlock( parsedBlock, previousParsed );\n\t\t}\n\t}\n\n\t// Recursively process inner blocks.\n\tif ( parsedBlock.innerBlocks && rawBlock.innerBlocks ) {\n\t\tfor ( let i = 0; i < parsedBlock.innerBlocks.length; i++ ) {\n\t\t\tconst parsedInner = parsedBlock.innerBlocks[ i ];\n\t\t\tconst rawInner = rawBlock.innerBlocks[ i ];\n\t\t\tif ( parsedInner && rawInner ) {\n\t\t\t\tapplyDiffRecursively( parsedInner, rawInner );\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Diff two revision contents at the grammar level.\n *\n * @param {string} currentContent Current revision's raw content.\n * @param {string} previousContent Previous revision's raw content.\n * @return {Array} Array of parsed blocks with diff status attributes.\n */\nexport function diffRevisionContent( currentContent, previousContent ) {\n\t// Grammar parse both contents.\n\tconst currentRaw = grammarParse( currentContent || '' );\n\tconst previousRaw = grammarParse( previousContent || '' );\n\n\t// Diff the raw block arrays.\n\tconst mergedRaw = diffRawBlocks( currentRaw, previousRaw );\n\n\t// Parse each raw block and apply diff status.\n\treturn mergedRaw\n\t\t.map( ( rawBlock ) => {\n\t\t\tconst parsed = parseRawBlock( rawBlock );\n\t\t\tif ( parsed ) {\n\t\t\t\tapplyDiffRecursively( parsed, rawBlock );\n\t\t\t}\n\t\t\treturn parsed;\n\t\t} )\n\t\t.filter( Boolean );\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAA2B;AAC3B,kBAA0B;AAK1B,gDAAsC;AACtC,oBAGO;AACP,uBAMO;AACP,kBAAgC;AAKhC,yBAAuB;AAEvB,IAAM,EAAE,cAAc,QAAI,2BAAQ,cAAAA,WAAkB;
|
|
4
|
+
"sourcesContent": ["/**\n * External dependencies\n */\nimport { diffArrays } from 'diff/lib/diff/array';\nimport { diffWords } from 'diff/lib/diff/word';\n\n/**\n * WordPress dependencies\n */\nimport { parse as grammarParse } from '@wordpress/block-serialization-default-parser';\nimport {\n\tprivateApis as blocksPrivateApis,\n\tgetBlockType,\n} from '@wordpress/blocks';\nimport {\n\tRichTextData,\n\tcreate,\n\tslice,\n\tconcat,\n\tapplyFormat,\n} from '@wordpress/rich-text';\nimport { __, _n, sprintf } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { parseRawBlock } = unlock( blocksPrivateApis );\n\n/**\n * Safely stringifies a value for display and comparison.\n *\n * @param {*} value The value to stringify.\n * @return {string} The stringified value.\n */\nfunction stringifyValue( value ) {\n\tif ( value === null || value === undefined ) {\n\t\treturn '';\n\t}\n\tif ( typeof value === 'object' ) {\n\t\treturn JSON.stringify( value, null, 2 );\n\t}\n\treturn String( value );\n}\n\n/**\n * Calculate text similarity using word diff (semantically meaningful).\n * Returns ratio of unchanged words to total words.\n *\n * @param {string} text1 First text to compare.\n * @param {string} text2 Second text to compare.\n * @return {number} Similarity score between 0 and 1.\n */\nfunction textSimilarity( text1, text2 ) {\n\tif ( ! text1 && ! text2 ) {\n\t\treturn 1;\n\t}\n\tif ( ! text1 || ! text2 ) {\n\t\treturn 0;\n\t}\n\n\tconst changes = diffWords( text1, text2 );\n\tconst unchanged = changes\n\t\t.filter( ( c ) => ! c.added && ! c.removed )\n\t\t.reduce( ( sum, c ) => sum + c.value.length, 0 );\n\tconst total = Math.max( text1.length, text2.length );\n\treturn total > 0 ? unchanged / total : 0;\n}\n\n/**\n * Post-process diff result to pair similar removed/added blocks as modifications.\n * This catches modifications that LCS missed due to content changes.\n *\n * @param {Array} blocks Raw blocks with diff status.\n * @return {Array} Blocks with similar pairs converted to modifications.\n */\nfunction pairSimilarBlocks( blocks ) {\n\tconst removed = [];\n\tconst added = [];\n\n\t// Separate blocks by status, tracking original indices.\n\tblocks.forEach( ( block, index ) => {\n\t\tconst status = block.__revisionDiffStatus?.status;\n\t\tif ( status === 'removed' ) {\n\t\t\tremoved.push( { block, index } );\n\t\t} else if ( status === 'added' ) {\n\t\t\tadded.push( { block, index } );\n\t\t}\n\t} );\n\n\t// If no removed or no added, nothing to pair.\n\tif ( removed.length === 0 || added.length === 0 ) {\n\t\treturn blocks;\n\t}\n\n\tconst pairedRemoved = new Set(); // Indices of removed blocks that were paired.\n\tconst modifications = new Map(); // Map from added block index to modified block.\n\tconst SIMILARITY_THRESHOLD = 0.3;\n\n\t// For each removed block, find best matching added block.\n\tfor ( const rem of removed ) {\n\t\tlet bestMatch = null;\n\t\tlet bestScore = 0;\n\n\t\tfor ( const add of added ) {\n\t\t\tif ( modifications.has( add.index ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( add.block.blockName !== rem.block.blockName ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst score = textSimilarity(\n\t\t\t\trem.block.innerHTML || '',\n\t\t\t\tadd.block.innerHTML || ''\n\t\t\t);\n\t\t\t// If content is identical (score=1), only pair if attrs differ.\n\t\t\t// Otherwise identical blocks are just position swaps, not modifications.\n\t\t\tconst attrsMatch =\n\t\t\t\tJSON.stringify( rem.block.attrs ) ===\n\t\t\t\tJSON.stringify( add.block.attrs );\n\t\t\tif (\n\t\t\t\tscore > bestScore &&\n\t\t\t\tscore > SIMILARITY_THRESHOLD &&\n\t\t\t\t( score < 1 || ! attrsMatch )\n\t\t\t) {\n\t\t\t\tbestScore = score;\n\t\t\t\tbestMatch = add;\n\t\t\t}\n\t\t}\n\n\t\tif ( bestMatch ) {\n\t\t\tpairedRemoved.add( rem.index );\n\n\t\t\t// Create modified block with previous content stored.\n\t\t\tmodifications.set( bestMatch.index, {\n\t\t\t\t...bestMatch.block,\n\t\t\t\t__revisionDiffStatus: { status: 'modified' },\n\t\t\t\t__previousRawBlock: rem.block,\n\t\t\t} );\n\t\t}\n\t}\n\n\t// Rebuild result: filter out paired removed, replace paired added with modified.\n\treturn blocks\n\t\t.map( ( block, index ) => {\n\t\t\t// Skip paired removed blocks.\n\t\t\tif ( pairedRemoved.has( index ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t// Replace paired added blocks with modified version.\n\t\t\tif ( modifications.has( index ) ) {\n\t\t\t\treturn modifications.get( index );\n\t\t\t}\n\t\t\treturn block;\n\t\t} )\n\t\t.filter( Boolean );\n}\n\n/**\n * Diff raw block arrays using LCS, recursively handling innerBlocks.\n * Detects modifications when exactly 1 block is removed and 1 is added\n * with the same blockName (1:1 replacement = modification).\n *\n * @param {Array} currentRaw Current revision's raw blocks.\n * @param {Array} previousRaw Previous revision's raw blocks.\n * @return {Array} Merged raw blocks with diff status injected.\n */\nfunction diffRawBlocks( currentRaw, previousRaw ) {\n\tconst createBlockSignature = ( rawBlock ) =>\n\t\tJSON.stringify( {\n\t\t\tname: rawBlock.blockName,\n\t\t\tattrs: rawBlock.attrs,\n\t\t\t// Use innerContent filtered to non-null and non-whitespace-only strings.\n\t\t\t// This excludes whitespace between inner blocks which changes based on count.\n\t\t\thtml: ( rawBlock.innerContent || [] ).filter(\n\t\t\t\t( c ) => c !== null && c.trim() !== ''\n\t\t\t),\n\t\t} );\n\tconst currentSigs = currentRaw.map( createBlockSignature );\n\tconst previousSigs = previousRaw.map( createBlockSignature );\n\n\tconst diff = diffArrays( previousSigs, currentSigs );\n\n\tconst result = [];\n\tlet currIdx = 0;\n\tlet prevIdx = 0;\n\n\tfor ( const part of diff ) {\n\t\tif ( part.added ) {\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\t...currentRaw[ currIdx++ ],\n\t\t\t\t\t__revisionDiffStatus: { status: 'added' },\n\t\t\t\t} );\n\t\t\t}\n\t\t} else if ( part.removed ) {\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\t...previousRaw[ prevIdx++ ],\n\t\t\t\t\t__revisionDiffStatus: { status: 'removed' },\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\t// Matched blocks - recursively diff their innerBlocks.\n\t\t\tfor ( let i = 0; i < part.count; i++ ) {\n\t\t\t\tconst currBlock = currentRaw[ currIdx++ ];\n\t\t\t\tconst prevBlock = previousRaw[ prevIdx++ ];\n\n\t\t\t\t// Recursively diff inner blocks.\n\t\t\t\tconst diffedInnerBlocks = diffRawBlocks(\n\t\t\t\t\tcurrBlock.innerBlocks || [],\n\t\t\t\t\tprevBlock.innerBlocks || []\n\t\t\t\t);\n\n\t\t\t\tresult.push( {\n\t\t\t\t\t...currBlock,\n\t\t\t\t\tinnerBlocks: diffedInnerBlocks,\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Post-process to pair similar removed/added blocks as modifications.\n\treturn pairSimilarBlocks( result );\n}\n\n/**\n * Check if formatting has changed at specific character indices.\n *\n * @param {Array} currentFormats Current formats array.\n * @param {Array} previousFormats Previous formats array.\n * @param {number} currentIndex Character index in current.\n * @param {number} previousIndex Character index in previous.\n * @return {boolean} True if formatting changed at these indices.\n */\nfunction hasFormatChangedAtIndex(\n\tcurrentFormats,\n\tpreviousFormats,\n\tcurrentIndex,\n\tpreviousIndex\n) {\n\tconst currFmts = currentFormats[ currentIndex ] || [];\n\tconst prevFmts = previousFormats[ previousIndex ] || [];\n\n\tif ( currFmts.length !== prevFmts.length ) {\n\t\treturn true;\n\t}\n\n\t// Check if each format in current exists in previous\n\tfor ( const fmt of currFmts ) {\n\t\tconst match = prevFmts.find(\n\t\t\t( pf ) =>\n\t\t\t\tpf.type === fmt.type &&\n\t\t\t\tJSON.stringify( pf.attributes ) ===\n\t\t\t\t\tJSON.stringify( fmt.attributes )\n\t\t);\n\t\tif ( ! match ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Analyze what formatting changed between two character positions.\n * Returns both the change type (for styling) and a description (for tooltip).\n *\n * @param {Array} currentFormats Current formats array.\n * @param {Array} previousFormats Previous formats array.\n * @param {number} currIdx Character index in current.\n * @param {number} prevIdx Character index in previous.\n * @return {{ type: 'added'|'removed'|'changed', description: string }} Change info.\n */\nfunction describeFormatChange(\n\tcurrentFormats,\n\tpreviousFormats,\n\tcurrIdx,\n\tprevIdx\n) {\n\tconst currFmts = currentFormats[ currIdx ] || [];\n\tconst prevFmts = previousFormats[ prevIdx ] || [];\n\n\tlet addedCount = 0;\n\tlet removedCount = 0;\n\tlet changedCount = 0;\n\n\t// Find added formats and attribute changes\n\tfor ( const fmt of currFmts ) {\n\t\tconst match = prevFmts.find( ( pf ) => pf.type === fmt.type );\n\t\tif ( ! match ) {\n\t\t\taddedCount++;\n\t\t} else if (\n\t\t\tJSON.stringify( fmt.attributes ) !==\n\t\t\tJSON.stringify( match.attributes )\n\t\t) {\n\t\t\tchangedCount++;\n\t\t}\n\t}\n\n\t// Find removed formats\n\tfor ( const fmt of prevFmts ) {\n\t\tconst match = currFmts.find( ( cf ) => cf.type === fmt.type );\n\t\tif ( ! match ) {\n\t\t\tremovedCount++;\n\t\t}\n\t}\n\n\t// Determine primary change type for styling\n\tif ( addedCount > 0 && removedCount === 0 && changedCount === 0 ) {\n\t\treturn {\n\t\t\ttype: 'added',\n\t\t\tdescription: sprintf(\n\t\t\t\t/* translators: %d: number of formats added */\n\t\t\t\t_n( '%d format added', '%d formats added', addedCount ),\n\t\t\t\taddedCount\n\t\t\t),\n\t\t};\n\t}\n\tif ( removedCount > 0 && addedCount === 0 && changedCount === 0 ) {\n\t\treturn {\n\t\t\ttype: 'removed',\n\t\t\tdescription: sprintf(\n\t\t\t\t/* translators: %d: number of formats removed */\n\t\t\t\t_n( '%d format removed', '%d formats removed', removedCount ),\n\t\t\t\tremovedCount\n\t\t\t),\n\t\t};\n\t}\n\n\t// Mixed or attribute-only changes\n\tconst parts = [];\n\tif ( addedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats added */\n\t\t\t\t_n( '%d format added', '%d formats added', addedCount ),\n\t\t\t\taddedCount\n\t\t\t)\n\t\t);\n\t}\n\tif ( removedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats removed */\n\t\t\t\t_n( '%d format removed', '%d formats removed', removedCount ),\n\t\t\t\tremovedCount\n\t\t\t)\n\t\t);\n\t}\n\tif ( changedCount > 0 ) {\n\t\tparts.push(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %d: number of formats changed */\n\t\t\t\t_n( '%d format changed', '%d formats changed', changedCount ),\n\t\t\t\tchangedCount\n\t\t\t)\n\t\t);\n\t}\n\treturn {\n\t\ttype: 'changed',\n\t\tdescription: parts.join( ', ' ) || __( 'Formatting changed' ),\n\t};\n}\n\n/**\n * Apply inline diff formatting comparing two RichTextData values.\n * - Text changes: apply revision/diff-removed and revision/diff-added formats\n * - Format-only changes (text unchanged): apply revision/diff-format-changed format\n *\n * @param {RichTextData} currentRichText Current revision's rich text.\n * @param {RichTextData} previousRichText Previous revision's rich text.\n * @return {RichTextData} New rich text with diff formatting applied.\n */\nfunction applyRichTextDiff( currentRichText, previousRichText ) {\n\tconst currentText = currentRichText.toPlainText();\n\tconst previousText = previousRichText.toPlainText();\n\n\t// Diff the plain text (words for cleaner output)\n\tconst textDiff = diffWords( previousText, currentText );\n\n\tlet result = create( { text: '' } );\n\tlet currentIdx = 0;\n\tlet previousIdx = 0;\n\n\tfor ( const part of textDiff ) {\n\t\tif ( part.removed ) {\n\t\t\t// Text deleted - slice from PREVIOUS, apply <del>\n\t\t\tconst removedSlice = slice(\n\t\t\t\tpreviousRichText,\n\t\t\t\tpreviousIdx,\n\t\t\t\tpreviousIdx + part.value.length\n\t\t\t);\n\t\t\tconst formatted = applyFormat(\n\t\t\t\tremovedSlice,\n\t\t\t\t{\n\t\t\t\t\ttype: 'revision/diff-removed',\n\t\t\t\t\tattributes: { title: __( 'Removed' ) },\n\t\t\t\t},\n\t\t\t\t0,\n\t\t\t\tpart.value.length\n\t\t\t);\n\t\t\tresult = concat( result, formatted );\n\t\t\tpreviousIdx += part.value.length;\n\t\t} else if ( part.added ) {\n\t\t\t// Text added - slice from CURRENT, apply <ins>\n\t\t\tconst addedSlice = slice(\n\t\t\t\tcurrentRichText,\n\t\t\t\tcurrentIdx,\n\t\t\t\tcurrentIdx + part.value.length\n\t\t\t);\n\t\t\tconst formatted = applyFormat(\n\t\t\t\taddedSlice,\n\t\t\t\t{\n\t\t\t\t\ttype: 'revision/diff-added',\n\t\t\t\t\tattributes: { title: __( 'Added' ) },\n\t\t\t\t},\n\t\t\t\t0,\n\t\t\t\tpart.value.length\n\t\t\t);\n\t\t\tresult = concat( result, formatted );\n\t\t\tcurrentIdx += part.value.length;\n\t\t} else {\n\t\t\t// Text unchanged - check formatting at each character position.\n\t\t\t// Only apply <mark> to specific ranges where formatting differs.\n\t\t\tconst currentFormats = currentRichText.formats || [];\n\t\t\tconst previousFormats = previousRichText.formats || [];\n\t\t\tconst len = part.value.length;\n\n\t\t\t// Helper to check format change at offset within this unchanged part.\n\t\t\tconst checkFormatChanged = ( offset ) =>\n\t\t\t\thasFormatChangedAtIndex(\n\t\t\t\t\tcurrentFormats,\n\t\t\t\t\tpreviousFormats,\n\t\t\t\t\tcurrentIdx + offset,\n\t\t\t\t\tpreviousIdx + offset\n\t\t\t\t);\n\n\t\t\t// Find ranges of characters grouped by whether format changed.\n\t\t\tlet rangeStart = 0;\n\t\t\tlet rangeFormatChanged = checkFormatChanged( 0 );\n\n\t\t\tfor ( let i = 1; i <= len; i++ ) {\n\t\t\t\tconst formatChanged = i < len && checkFormatChanged( i );\n\n\t\t\t\t// When format-changed status changes or we reach the end, emit range.\n\t\t\t\tif ( i === len || formatChanged !== rangeFormatChanged ) {\n\t\t\t\t\tconst rangeSlice = slice(\n\t\t\t\t\t\tcurrentRichText,\n\t\t\t\t\t\tcurrentIdx + rangeStart,\n\t\t\t\t\t\tcurrentIdx + i\n\t\t\t\t\t);\n\n\t\t\t\t\tif ( rangeFormatChanged ) {\n\t\t\t\t\t\t// Get type and description of what changed\n\t\t\t\t\t\tconst { type, description } = describeFormatChange(\n\t\t\t\t\t\t\tcurrentFormats,\n\t\t\t\t\t\t\tpreviousFormats,\n\t\t\t\t\t\t\tcurrentIdx + rangeStart,\n\t\t\t\t\t\t\tpreviousIdx + rangeStart\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Map change type to format type for styling\n\t\t\t\t\t\tconst formatType = {\n\t\t\t\t\t\t\tadded: 'revision/diff-format-added',\n\t\t\t\t\t\t\tremoved: 'revision/diff-format-removed',\n\t\t\t\t\t\t\tchanged: 'revision/diff-format-changed',\n\t\t\t\t\t\t}[ type ];\n\n\t\t\t\t\t\tconst marked = applyFormat(\n\t\t\t\t\t\t\trangeSlice,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: formatType,\n\t\t\t\t\t\t\t\tattributes: { title: description },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\ti - rangeStart\n\t\t\t\t\t\t);\n\t\t\t\t\t\tresult = concat( result, marked );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = concat( result, rangeSlice );\n\t\t\t\t\t}\n\n\t\t\t\t\trangeStart = i;\n\t\t\t\t\trangeFormatChanged = formatChanged;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrentIdx += part.value.length;\n\t\t\tpreviousIdx += part.value.length;\n\t\t}\n\t}\n\n\treturn new RichTextData( result );\n}\n\n/**\n * Apply diffs to a modified block's attributes.\n * - Rich-text attributes: applies inline diff formatting (ins/del marks).\n * - Other attributes: computes word-level diffs for the sidebar panel.\n *\n * @param {Object} currentBlock Current parsed block.\n * @param {Object} previousBlock Previous parsed block.\n * @param {Object} diffStatus The __revisionDiffStatus object to attach changedAttributes to.\n */\nfunction applyDiffToBlock( currentBlock, previousBlock, diffStatus ) {\n\tconst blockType = getBlockType( currentBlock.name );\n\tif ( ! blockType ) {\n\t\treturn;\n\t}\n\n\tconst changedAttributes = {};\n\n\tfor ( const [ attrName, attrDef ] of Object.entries(\n\t\tblockType.attributes\n\t) ) {\n\t\tif ( attrDef.source === 'rich-text' ) {\n\t\t\tconst currentRichText = currentBlock.attributes[ attrName ];\n\t\t\tconst previousRichText = previousBlock.attributes[ attrName ];\n\t\t\tif (\n\t\t\t\tcurrentRichText instanceof RichTextData &&\n\t\t\t\tpreviousRichText instanceof RichTextData\n\t\t\t) {\n\t\t\t\tcurrentBlock.attributes[ attrName ] = applyRichTextDiff(\n\t\t\t\t\tcurrentRichText,\n\t\t\t\t\tpreviousRichText\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tconst currStr = stringifyValue(\n\t\t\t\tcurrentBlock.attributes[ attrName ]\n\t\t\t);\n\t\t\tconst prevStr = stringifyValue(\n\t\t\t\tpreviousBlock.attributes[ attrName ]\n\t\t\t);\n\t\t\tif ( currStr !== prevStr ) {\n\t\t\t\tchangedAttributes[ attrName ] = diffWords( prevStr, currStr );\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( Object.keys( changedAttributes ).length > 0 ) {\n\t\tdiffStatus.changedAttributes = changedAttributes;\n\t}\n}\n\n/**\n * Recursively apply diff status and rich text diff to blocks in the tree.\n * Copies __revisionDiffStatus from raw blocks to parsed blocks and applies\n * rich text diffs to modified blocks.\n *\n * @param {Object} parsedBlock Parsed block (with inner blocks).\n * @param {Object} rawBlock Raw block (with __revisionDiffStatus and __previousRawBlock).\n */\nfunction applyDiffRecursively( parsedBlock, rawBlock ) {\n\t// Copy diff status from raw block to parsed block.\n\tif ( rawBlock.__revisionDiffStatus ) {\n\t\t// Apply diffs if this block is modified and has a previous raw block.\n\t\tif (\n\t\t\trawBlock.__revisionDiffStatus.status === 'modified' &&\n\t\t\trawBlock.__previousRawBlock\n\t\t) {\n\t\t\tconst previousParsed = parseRawBlock( rawBlock.__previousRawBlock );\n\t\t\tif ( previousParsed ) {\n\t\t\t\tapplyDiffToBlock(\n\t\t\t\t\tparsedBlock,\n\t\t\t\t\tpreviousParsed,\n\t\t\t\t\trawBlock.__revisionDiffStatus\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tparsedBlock.__revisionDiffStatus = rawBlock.__revisionDiffStatus;\n\t\t// Also store in attributes so it survives block-editor store normalization.\n\t\tparsedBlock.attributes.__revisionDiffStatus =\n\t\t\trawBlock.__revisionDiffStatus;\n\t}\n\n\t// Recursively process inner blocks.\n\tif ( parsedBlock.innerBlocks && rawBlock.innerBlocks ) {\n\t\tfor ( let i = 0; i < parsedBlock.innerBlocks.length; i++ ) {\n\t\t\tconst parsedInner = parsedBlock.innerBlocks[ i ];\n\t\t\tconst rawInner = rawBlock.innerBlocks[ i ];\n\t\t\tif ( parsedInner && rawInner ) {\n\t\t\t\tapplyDiffRecursively( parsedInner, rawInner );\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Diff two revision contents at the grammar level.\n *\n * @param {string} currentContent Current revision's raw content.\n * @param {string} previousContent Previous revision's raw content.\n * @return {Array} Array of parsed blocks with diff status attributes.\n */\nexport function diffRevisionContent( currentContent, previousContent ) {\n\t// Grammar parse both contents.\n\tconst currentRaw = grammarParse( currentContent || '' );\n\tconst previousRaw = grammarParse( previousContent || '' );\n\n\t// Diff the raw block arrays.\n\tconst mergedRaw = diffRawBlocks( currentRaw, previousRaw );\n\n\t// Parse each raw block and apply diff status.\n\treturn mergedRaw\n\t\t.map( ( rawBlock ) => {\n\t\t\tconst parsed = parseRawBlock( rawBlock );\n\t\t\tif ( parsed ) {\n\t\t\t\tapplyDiffRecursively( parsed, rawBlock );\n\t\t\t}\n\t\t\treturn parsed;\n\t\t} )\n\t\t.filter( Boolean );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["blocksPrivateApis", "grammarParse"]
|
|
7
7
|
}
|
|
@@ -34,10 +34,10 @@ var { useBlockElementRef } = (0, import_lock_unlock.unlock)(import_block_editor.
|
|
|
34
34
|
function collectDiffBlocks(blocks) {
|
|
35
35
|
const result = [];
|
|
36
36
|
for (const block of blocks) {
|
|
37
|
-
if (block.__revisionDiffStatus) {
|
|
37
|
+
if (block.__revisionDiffStatus?.status) {
|
|
38
38
|
result.push({
|
|
39
39
|
clientId: block.clientId,
|
|
40
|
-
status: block.__revisionDiffStatus
|
|
40
|
+
status: block.__revisionDiffStatus.status
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
if (block.innerBlocks?.length) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-revisions-preview/diff-markers.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tuseState,\n\tuseMemo,\n\tuseRef,\n\tuseCallback,\n\tuseEffect,\n} from '@wordpress/element';\nimport { useRefEffect, useMergeRefs } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport {\n\tprivateApis as blockEditorPrivateApis,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { useBlockElementRef } = unlock( blockEditorPrivateApis );\n\n/**\n * Recursively collect blocks with diff status.\n *\n * @param {Array} blocks The blocks to search.\n * @return {Array} Blocks with __revisionDiffStatus.\n */\nfunction collectDiffBlocks( blocks ) {\n\tconst result = [];\n\tfor ( const block of blocks ) {\n\t\tif ( block.__revisionDiffStatus ) {\n\t\t\tresult.push( {\n\t\t\t\tclientId: block.clientId,\n\t\t\t\tstatus: block.__revisionDiffStatus,\n\t\t\t} );\n\t\t}\n\t\tif ( block.innerBlocks?.length ) {\n\t\t\tresult.push( ...collectDiffBlocks( block.innerBlocks ) );\n\t\t}\n\t}\n\treturn result;\n}\n\nconst STATUS_LABELS = {\n\tadded: __( 'Go to added block' ),\n\tremoved: __( 'Go to removed block' ),\n\tmodified: __( 'Go to modified block' ),\n};\n\nfunction calculatePosition( el ) {\n\tif ( ! el ) {\n\t\treturn null;\n\t}\n\tconst doc = el.ownerDocument;\n\tconst scrollHeight = doc.documentElement.scrollHeight;\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollTop = doc.documentElement.scrollTop;\n\tconst top = rect.top + scrollTop;\n\treturn {\n\t\ttop: ( top / scrollHeight ) * 100,\n\t\theight: ( rect.height / scrollHeight ) * 100,\n\t};\n}\n\n/**\n * Button component for a single diff marker.\n *\n * @param {Object} props Component props.\n * @param {string} props.clientId The block client ID.\n * @param {string} props.status The diff status (added/removed/modified).\n * @param {Function} props.subscribe Function to subscribe to position updates.\n * @return {React.JSX.Element} The diff marker button or null if position not calculated.\n */\nfunction DiffMarkerButton( { clientId, status, subscribe } ) {\n\tconst blockRef = useRef();\n\tuseBlockElementRef( clientId, blockRef );\n\tconst [ position, setPosition ] = useState( () =>\n\t\tcalculatePosition( blockRef.current )\n\t);\n\n\tuseEffect( () => {\n\t\treturn subscribe( () => {\n\t\t\tsetPosition( calculatePosition( blockRef.current ) );\n\t\t} );\n\t}, [ subscribe ] );\n\n\tuseEffect( () => {\n\t\tsetPosition( calculatePosition( blockRef.current ) );\n\t}, [ status ] );\n\n\tif ( ! position ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<button\n\t\t\tclassName={ `revision-diff-marker is-${ status }` }\n\t\t\tstyle={ {\n\t\t\t\ttop: `${ position.top }%`,\n\t\t\t\theight: `${ Math.max( position.height, 0.5 ) }%`,\n\t\t\t} }\n\t\t\tonClick={ () => blockRef.current?.focus() }\n\t\t\taria-label={ STATUS_LABELS[ status ] }\n\t\t/>\n\t);\n}\n\n/**\n * Hook that provides diff markers functionality.\n * Returns a ref callback for the content element and a DiffMarkers component.\n * Must be used inside a BlockEditorProvider context.\n *\n * @return {Array} Tuple of [contentRef, DiffMarkersComponent].\n */\nexport function useDiffMarkers() {\n\tconst [ isMounted, setIsMounted ] = useState( false );\n\tconst subscribersRef = useRef( new Set() );\n\tconst blocks = useSelect(\n\t\t( select ) => select( blockEditorStore ).getBlocks(),\n\t\t[]\n\t);\n\tconst diffBlocks = useMemo( () => collectDiffBlocks( blocks ), [ blocks ] );\n\tconst subscribe = useCallback( ( callback ) => {\n\t\tsubscribersRef.current.add( callback );\n\t\treturn () => subscribersRef.current.delete( callback );\n\t}, [] );\n\tconst contentRef = useRefEffect( ( element ) => {\n\t\tconst { ownerDocument } = element;\n\t\tconst { defaultView } = ownerDocument;\n\t\tconst resizeObserver = new defaultView.ResizeObserver( () => {\n\t\t\tsubscribersRef.current.forEach( ( cb ) => cb() );\n\t\t} );\n\t\tresizeObserver.observe( ownerDocument.body );\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, [] );\n\treturn [\n\t\tuseMergeRefs( [ contentRef, setIsMounted ] ),\n\t\t<div\n\t\t\tkey=\"diff-markers\"\n\t\t\tclassName=\"revision-diff-markers\"\n\t\t\trole=\"navigation\"\n\t\t\taria-label={ __( 'Diff markers' ) }\n\t\t>\n\t\t\t{ isMounted &&\n\t\t\t\tdiffBlocks.map( ( { clientId, status } ) => (\n\t\t\t\t\t<DiffMarkerButton\n\t\t\t\t\t\tkey={ clientId }\n\t\t\t\t\t\tclientId={ clientId }\n\t\t\t\t\t\tstatus={ status }\n\t\t\t\t\t\tsubscribe={ subscribe }\n\t\t\t\t\t/>\n\t\t\t\t) ) }\n\t\t</div>,\n\t];\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAMO;AACP,qBAA2C;AAC3C,kBAA0B;AAC1B,0BAGO;AACP,kBAAmB;AAKnB,yBAAuB;AA8ErB;AA5EF,IAAM,EAAE,mBAAmB,QAAI,2BAAQ,oBAAAA,WAAuB;AAQ9D,SAAS,kBAAmB,QAAS;AACpC,QAAM,SAAS,CAAC;AAChB,aAAY,SAAS,QAAS;AAC7B,QAAK,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tuseState,\n\tuseMemo,\n\tuseRef,\n\tuseCallback,\n\tuseEffect,\n} from '@wordpress/element';\nimport { useRefEffect, useMergeRefs } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport {\n\tprivateApis as blockEditorPrivateApis,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { useBlockElementRef } = unlock( blockEditorPrivateApis );\n\n/**\n * Recursively collect blocks with diff status.\n *\n * @param {Array} blocks The blocks to search.\n * @return {Array} Blocks with __revisionDiffStatus.\n */\nfunction collectDiffBlocks( blocks ) {\n\tconst result = [];\n\tfor ( const block of blocks ) {\n\t\tif ( block.__revisionDiffStatus?.status ) {\n\t\t\tresult.push( {\n\t\t\t\tclientId: block.clientId,\n\t\t\t\tstatus: block.__revisionDiffStatus.status,\n\t\t\t} );\n\t\t}\n\t\tif ( block.innerBlocks?.length ) {\n\t\t\tresult.push( ...collectDiffBlocks( block.innerBlocks ) );\n\t\t}\n\t}\n\treturn result;\n}\n\nconst STATUS_LABELS = {\n\tadded: __( 'Go to added block' ),\n\tremoved: __( 'Go to removed block' ),\n\tmodified: __( 'Go to modified block' ),\n};\n\nfunction calculatePosition( el ) {\n\tif ( ! el ) {\n\t\treturn null;\n\t}\n\tconst doc = el.ownerDocument;\n\tconst scrollHeight = doc.documentElement.scrollHeight;\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollTop = doc.documentElement.scrollTop;\n\tconst top = rect.top + scrollTop;\n\treturn {\n\t\ttop: ( top / scrollHeight ) * 100,\n\t\theight: ( rect.height / scrollHeight ) * 100,\n\t};\n}\n\n/**\n * Button component for a single diff marker.\n *\n * @param {Object} props Component props.\n * @param {string} props.clientId The block client ID.\n * @param {string} props.status The diff status (added/removed/modified).\n * @param {Function} props.subscribe Function to subscribe to position updates.\n * @return {React.JSX.Element} The diff marker button or null if position not calculated.\n */\nfunction DiffMarkerButton( { clientId, status, subscribe } ) {\n\tconst blockRef = useRef();\n\tuseBlockElementRef( clientId, blockRef );\n\tconst [ position, setPosition ] = useState( () =>\n\t\tcalculatePosition( blockRef.current )\n\t);\n\n\tuseEffect( () => {\n\t\treturn subscribe( () => {\n\t\t\tsetPosition( calculatePosition( blockRef.current ) );\n\t\t} );\n\t}, [ subscribe ] );\n\n\tuseEffect( () => {\n\t\tsetPosition( calculatePosition( blockRef.current ) );\n\t}, [ status ] );\n\n\tif ( ! position ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<button\n\t\t\tclassName={ `revision-diff-marker is-${ status }` }\n\t\t\tstyle={ {\n\t\t\t\ttop: `${ position.top }%`,\n\t\t\t\theight: `${ Math.max( position.height, 0.5 ) }%`,\n\t\t\t} }\n\t\t\tonClick={ () => blockRef.current?.focus() }\n\t\t\taria-label={ STATUS_LABELS[ status ] }\n\t\t/>\n\t);\n}\n\n/**\n * Hook that provides diff markers functionality.\n * Returns a ref callback for the content element and a DiffMarkers component.\n * Must be used inside a BlockEditorProvider context.\n *\n * @return {Array} Tuple of [contentRef, DiffMarkersComponent].\n */\nexport function useDiffMarkers() {\n\tconst [ isMounted, setIsMounted ] = useState( false );\n\tconst subscribersRef = useRef( new Set() );\n\tconst blocks = useSelect(\n\t\t( select ) => select( blockEditorStore ).getBlocks(),\n\t\t[]\n\t);\n\tconst diffBlocks = useMemo( () => collectDiffBlocks( blocks ), [ blocks ] );\n\tconst subscribe = useCallback( ( callback ) => {\n\t\tsubscribersRef.current.add( callback );\n\t\treturn () => subscribersRef.current.delete( callback );\n\t}, [] );\n\tconst contentRef = useRefEffect( ( element ) => {\n\t\tconst { ownerDocument } = element;\n\t\tconst { defaultView } = ownerDocument;\n\t\tconst resizeObserver = new defaultView.ResizeObserver( () => {\n\t\t\tsubscribersRef.current.forEach( ( cb ) => cb() );\n\t\t} );\n\t\tresizeObserver.observe( ownerDocument.body );\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, [] );\n\treturn [\n\t\tuseMergeRefs( [ contentRef, setIsMounted ] ),\n\t\t<div\n\t\t\tkey=\"diff-markers\"\n\t\t\tclassName=\"revision-diff-markers\"\n\t\t\trole=\"navigation\"\n\t\t\taria-label={ __( 'Diff markers' ) }\n\t\t>\n\t\t\t{ isMounted &&\n\t\t\t\tdiffBlocks.map( ( { clientId, status } ) => (\n\t\t\t\t\t<DiffMarkerButton\n\t\t\t\t\t\tkey={ clientId }\n\t\t\t\t\t\tclientId={ clientId }\n\t\t\t\t\t\tstatus={ status }\n\t\t\t\t\t\tsubscribe={ subscribe }\n\t\t\t\t\t/>\n\t\t\t\t) ) }\n\t\t</div>,\n\t];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["blockEditorPrivateApis", "blockEditorStore"]
|
|
7
7
|
}
|
|
@@ -102,7 +102,7 @@ var REVISION_DIFF_STYLES = `
|
|
|
102
102
|
function withRevisionDiffClasses(BlockListBlock) {
|
|
103
103
|
return (props) => {
|
|
104
104
|
const { block, className } = props;
|
|
105
|
-
const diffStatus = block?.__revisionDiffStatus;
|
|
105
|
+
const diffStatus = block?.__revisionDiffStatus?.status;
|
|
106
106
|
const enhancedClassName = (0, import_clsx.default)(className, {
|
|
107
107
|
"is-revision-added": diffStatus === "added",
|
|
108
108
|
"is-revision-removed": diffStatus === "removed",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-revisions-preview/revisions-canvas.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { Spinner } from '@wordpress/components';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { useEffect } from '@wordpress/element';\nimport { addFilter } from '@wordpress/hooks';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\nimport { store as editorStore } from '../../store';\nimport VisualEditor from '../visual-editor';\nimport {\n\tregisterDiffFormatTypes,\n\tunregisterDiffFormatTypes,\n} from './diff-format-types';\nimport { useDiffMarkers } from './diff-markers';\n\nconst { usePrivateStyleOverride } = unlock( blockEditorPrivateApis );\n\n// SVG filter for removed blocks: grayscale + red tint\nconst REVISION_REMOVED_FILTER_SVG = `\n<svg\n\txmlns=\"http://www.w3.org/2000/svg\"\n\tviewBox=\"0 0 0 0\"\n\twidth=\"0\"\n\theight=\"0\"\n\tfocusable=\"false\"\n\trole=\"none\"\n\taria-hidden=\"true\"\n\tstyle=\"visibility: hidden; position: absolute; left: -9999px; overflow: hidden;\"\n>\n\t<defs>\n\t\t<filter id=\"revision-removed-filter\" x=\"0\" y=\"0\" width=\"100%\" height=\"100%\">\n\t\t\t<!-- Desaturate and add red tint -->\n\t\t\t<feColorMatrix type=\"matrix\"\n\t\t\t\tvalues=\"0.5 0.3 0.2 0 0.15\n\t\t\t\t 0.2 0.2 0.1 0 0\n\t\t\t\t 0.2 0.2 0.1 0 0\n\t\t\t\t 0 0 0 0.8 0\"/>\n\t\t</filter>\n\t</defs>\n</svg>\n`;\n\n/**\n * CSS for revision diff indicators, injected into the iframe.\n * Uses color-mix() to blend diff colors with currentColor for better integration.\n */\nconst REVISION_DIFF_STYLES = `\n\t.is-revision-added {\n\t\tbox-shadow: inset 0 0 0 9999px color-mix(in srgb, currentColor 5%, #00a32a 15%), 0 0 0 4px color-mix(in srgb, currentColor 5%, #00a32a 15%);\n\t}\n\t.is-revision-removed,\n\t.revision-diff-removed {\n\t\ttext-decoration: line-through;\n\t\tfilter: url(#revision-removed-filter);\n\t}\n\t.is-revision-modified {\n\t\toutline: 2px solid color-mix(in srgb, currentColor 30%, #dba617 70%) !important;\n\t\toutline-offset: 2px;\n\t}\n\t.revision-diff-added {\n\t\tbackground-color: color-mix(in srgb, currentColor 5%, #00a32a 15%);\n\t\ttext-decoration: none;\n\t}\n\t.revision-diff-format-added {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 30%, #00a32a 70%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n\t.revision-diff-format-removed {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 20%, #d63638 80%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n\t.revision-diff-format-changed {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 30%, #dba617 70%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n`;\n\n/**\n * Filter to add diff status CSS classes to blocks.\n *\n * @param {Object} BlockListBlock The original block list block component.\n * @return {Function} Enhanced component with diff status classes.\n */\nfunction withRevisionDiffClasses( BlockListBlock ) {\n\treturn ( props ) => {\n\t\tconst { block, className } = props;\n\t\tconst diffStatus = block?.__revisionDiffStatus;\n\n\t\tconst enhancedClassName = clsx( className, {\n\t\t\t'is-revision-added': diffStatus === 'added',\n\t\t\t'is-revision-removed': diffStatus === 'removed',\n\t\t\t'is-revision-modified': diffStatus === 'modified',\n\t\t} );\n\n\t\treturn <BlockListBlock { ...props } className={ enhancedClassName } />;\n\t};\n}\n\nconst FILTER_NAME = 'editor/revisions-canvas/withRevisionDiffClasses';\n\n// Register the filter at module level to ensure it's available before first render.\naddFilter( 'editor.BlockListBlock', FILTER_NAME, withRevisionDiffClasses );\n\n/**\n * Component to inject diff styles via style overrides.\n * Must be rendered inside ExperimentalBlockEditorProvider.\n *\n * @param {Object} props Component props.\n * @param {boolean} props.showDiff Whether to show diff highlighting.\n */\nfunction DiffStyleOverrides( { showDiff } ) {\n\tusePrivateStyleOverride( {\n\t\tcss: showDiff ? REVISION_DIFF_STYLES : '',\n\t} );\n\tusePrivateStyleOverride( {\n\t\tassets: showDiff ? REVISION_REMOVED_FILTER_SVG : '',\n\t\t__unstableType: 'svgs',\n\t} );\n\treturn null;\n}\n\nfunction CanvasContent( { showDiff } ) {\n\tconst [ contentRef, diffMarkers ] = useDiffMarkers();\n\treturn (\n\t\t<>\n\t\t\t<VisualEditor contentRef={ contentRef } />\n\t\t\t{ showDiff && diffMarkers }\n\t\t</>\n\t);\n}\n\n/**\n * Canvas component that renders a post revision in read-only mode.\n * Block preparation and settings are handled by the parent EditorProvider.\n *\n * @return {React.JSX.Element} The revisions canvas component.\n */\nexport default function RevisionsCanvas() {\n\tuseEffect( () => {\n\t\tregisterDiffFormatTypes();\n\t\treturn () => {\n\t\t\tunregisterDiffFormatTypes();\n\t\t};\n\t}, [] );\n\n\tconst { revision, showDiff } = useSelect( ( select ) => {\n\t\tconst { getCurrentRevision, isShowingRevisionDiff } = unlock(\n\t\t\tselect( editorStore )\n\t\t);\n\t\treturn {\n\t\t\trevision: getCurrentRevision(),\n\t\t\tshowDiff: isShowingRevisionDiff(),\n\t\t};\n\t}, [] );\n\n\treturn revision ? (\n\t\t<>\n\t\t\t<DiffStyleOverrides showDiff={ showDiff } />\n\t\t\t<div className=\"editor-revisions-canvas__content\">\n\t\t\t\t<CanvasContent showDiff={ showDiff } />\n\t\t\t</div>\n\t\t</>\n\t) : (\n\t\t<div className=\"editor-revisions-canvas__loading\">\n\t\t\t<Spinner />\n\t\t</div>\n\t);\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAiB;AAKjB,wBAAwB;AACxB,0BAAsD;AACtD,kBAA0B;AAC1B,qBAA0B;AAC1B,mBAA0B;AAK1B,yBAAuB;AACvB,mBAAqC;AACrC,2BAAyB;AACzB,+BAGO;AACP,0BAA+B;AAiFtB;AA/ET,IAAM,EAAE,wBAAwB,QAAI,2BAAQ,oBAAAA,WAAuB;AAGnE,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BpC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqC7B,SAAS,wBAAyB,gBAAiB;AAClD,SAAO,CAAE,UAAW;AACnB,UAAM,EAAE,OAAO,UAAU,IAAI;AAC7B,UAAM,aAAa,OAAO;
|
|
4
|
+
"sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { Spinner } from '@wordpress/components';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { useEffect } from '@wordpress/element';\nimport { addFilter } from '@wordpress/hooks';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\nimport { store as editorStore } from '../../store';\nimport VisualEditor from '../visual-editor';\nimport {\n\tregisterDiffFormatTypes,\n\tunregisterDiffFormatTypes,\n} from './diff-format-types';\nimport { useDiffMarkers } from './diff-markers';\n\nconst { usePrivateStyleOverride } = unlock( blockEditorPrivateApis );\n\n// SVG filter for removed blocks: grayscale + red tint\nconst REVISION_REMOVED_FILTER_SVG = `\n<svg\n\txmlns=\"http://www.w3.org/2000/svg\"\n\tviewBox=\"0 0 0 0\"\n\twidth=\"0\"\n\theight=\"0\"\n\tfocusable=\"false\"\n\trole=\"none\"\n\taria-hidden=\"true\"\n\tstyle=\"visibility: hidden; position: absolute; left: -9999px; overflow: hidden;\"\n>\n\t<defs>\n\t\t<filter id=\"revision-removed-filter\" x=\"0\" y=\"0\" width=\"100%\" height=\"100%\">\n\t\t\t<!-- Desaturate and add red tint -->\n\t\t\t<feColorMatrix type=\"matrix\"\n\t\t\t\tvalues=\"0.5 0.3 0.2 0 0.15\n\t\t\t\t 0.2 0.2 0.1 0 0\n\t\t\t\t 0.2 0.2 0.1 0 0\n\t\t\t\t 0 0 0 0.8 0\"/>\n\t\t</filter>\n\t</defs>\n</svg>\n`;\n\n/**\n * CSS for revision diff indicators, injected into the iframe.\n * Uses color-mix() to blend diff colors with currentColor for better integration.\n */\nconst REVISION_DIFF_STYLES = `\n\t.is-revision-added {\n\t\tbox-shadow: inset 0 0 0 9999px color-mix(in srgb, currentColor 5%, #00a32a 15%), 0 0 0 4px color-mix(in srgb, currentColor 5%, #00a32a 15%);\n\t}\n\t.is-revision-removed,\n\t.revision-diff-removed {\n\t\ttext-decoration: line-through;\n\t\tfilter: url(#revision-removed-filter);\n\t}\n\t.is-revision-modified {\n\t\toutline: 2px solid color-mix(in srgb, currentColor 30%, #dba617 70%) !important;\n\t\toutline-offset: 2px;\n\t}\n\t.revision-diff-added {\n\t\tbackground-color: color-mix(in srgb, currentColor 5%, #00a32a 15%);\n\t\ttext-decoration: none;\n\t}\n\t.revision-diff-format-added {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 30%, #00a32a 70%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n\t.revision-diff-format-removed {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 20%, #d63638 80%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n\t.revision-diff-format-changed {\n\t\ttext-decoration: underline wavy color-mix(in srgb, currentColor 30%, #dba617 70%);\n\t\ttext-decoration-thickness: 2px;\n\t}\n`;\n\n/**\n * Filter to add diff status CSS classes to blocks.\n *\n * @param {Object} BlockListBlock The original block list block component.\n * @return {Function} Enhanced component with diff status classes.\n */\nfunction withRevisionDiffClasses( BlockListBlock ) {\n\treturn ( props ) => {\n\t\tconst { block, className } = props;\n\t\tconst diffStatus = block?.__revisionDiffStatus?.status;\n\n\t\tconst enhancedClassName = clsx( className, {\n\t\t\t'is-revision-added': diffStatus === 'added',\n\t\t\t'is-revision-removed': diffStatus === 'removed',\n\t\t\t'is-revision-modified': diffStatus === 'modified',\n\t\t} );\n\n\t\treturn <BlockListBlock { ...props } className={ enhancedClassName } />;\n\t};\n}\n\nconst FILTER_NAME = 'editor/revisions-canvas/withRevisionDiffClasses';\n\n// Register the filter at module level to ensure it's available before first render.\naddFilter( 'editor.BlockListBlock', FILTER_NAME, withRevisionDiffClasses );\n\n/**\n * Component to inject diff styles via style overrides.\n * Must be rendered inside ExperimentalBlockEditorProvider.\n *\n * @param {Object} props Component props.\n * @param {boolean} props.showDiff Whether to show diff highlighting.\n */\nfunction DiffStyleOverrides( { showDiff } ) {\n\tusePrivateStyleOverride( {\n\t\tcss: showDiff ? REVISION_DIFF_STYLES : '',\n\t} );\n\tusePrivateStyleOverride( {\n\t\tassets: showDiff ? REVISION_REMOVED_FILTER_SVG : '',\n\t\t__unstableType: 'svgs',\n\t} );\n\treturn null;\n}\n\nfunction CanvasContent( { showDiff } ) {\n\tconst [ contentRef, diffMarkers ] = useDiffMarkers();\n\treturn (\n\t\t<>\n\t\t\t<VisualEditor contentRef={ contentRef } />\n\t\t\t{ showDiff && diffMarkers }\n\t\t</>\n\t);\n}\n\n/**\n * Canvas component that renders a post revision in read-only mode.\n * Block preparation and settings are handled by the parent EditorProvider.\n *\n * @return {React.JSX.Element} The revisions canvas component.\n */\nexport default function RevisionsCanvas() {\n\tuseEffect( () => {\n\t\tregisterDiffFormatTypes();\n\t\treturn () => {\n\t\t\tunregisterDiffFormatTypes();\n\t\t};\n\t}, [] );\n\n\tconst { revision, showDiff } = useSelect( ( select ) => {\n\t\tconst { getCurrentRevision, isShowingRevisionDiff } = unlock(\n\t\t\tselect( editorStore )\n\t\t);\n\t\treturn {\n\t\t\trevision: getCurrentRevision(),\n\t\t\tshowDiff: isShowingRevisionDiff(),\n\t\t};\n\t}, [] );\n\n\treturn revision ? (\n\t\t<>\n\t\t\t<DiffStyleOverrides showDiff={ showDiff } />\n\t\t\t<div className=\"editor-revisions-canvas__content\">\n\t\t\t\t<CanvasContent showDiff={ showDiff } />\n\t\t\t</div>\n\t\t</>\n\t) : (\n\t\t<div className=\"editor-revisions-canvas__loading\">\n\t\t\t<Spinner />\n\t\t</div>\n\t);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAiB;AAKjB,wBAAwB;AACxB,0BAAsD;AACtD,kBAA0B;AAC1B,qBAA0B;AAC1B,mBAA0B;AAK1B,yBAAuB;AACvB,mBAAqC;AACrC,2BAAyB;AACzB,+BAGO;AACP,0BAA+B;AAiFtB;AA/ET,IAAM,EAAE,wBAAwB,QAAI,2BAAQ,oBAAAA,WAAuB;AAGnE,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BpC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqC7B,SAAS,wBAAyB,gBAAiB;AAClD,SAAO,CAAE,UAAW;AACnB,UAAM,EAAE,OAAO,UAAU,IAAI;AAC7B,UAAM,aAAa,OAAO,sBAAsB;AAEhD,UAAM,wBAAoB,YAAAC,SAAM,WAAW;AAAA,MAC1C,qBAAqB,eAAe;AAAA,MACpC,uBAAuB,eAAe;AAAA,MACtC,wBAAwB,eAAe;AAAA,IACxC,CAAE;AAEF,WAAO,4CAAC,kBAAiB,GAAG,OAAQ,WAAY,mBAAoB;AAAA,EACrE;AACD;AAEA,IAAM,cAAc;AAAA,IAGpB,wBAAW,yBAAyB,aAAa,uBAAwB;AASzE,SAAS,mBAAoB,EAAE,SAAS,GAAI;AAC3C,0BAAyB;AAAA,IACxB,KAAK,WAAW,uBAAuB;AAAA,EACxC,CAAE;AACF,0BAAyB;AAAA,IACxB,QAAQ,WAAW,8BAA8B;AAAA,IACjD,gBAAgB;AAAA,EACjB,CAAE;AACF,SAAO;AACR;AAEA,SAAS,cAAe,EAAE,SAAS,GAAI;AACtC,QAAM,CAAE,YAAY,WAAY,QAAI,oCAAe;AACnD,SACC,4EACC;AAAA,gDAAC,qBAAAC,SAAA,EAAa,YAA0B;AAAA,IACtC,YAAY;AAAA,KACf;AAEF;AAQe,SAAR,kBAAmC;AACzC,gCAAW,MAAM;AAChB,0DAAwB;AACxB,WAAO,MAAM;AACZ,8DAA0B;AAAA,IAC3B;AAAA,EACD,GAAG,CAAC,CAAE;AAEN,QAAM,EAAE,UAAU,SAAS,QAAI,uBAAW,CAAE,WAAY;AACvD,UAAM,EAAE,oBAAoB,sBAAsB,QAAI;AAAA,MACrD,OAAQ,aAAAC,KAAY;AAAA,IACrB;AACA,WAAO;AAAA,MACN,UAAU,mBAAmB;AAAA,MAC7B,UAAU,sBAAsB;AAAA,IACjC;AAAA,EACD,GAAG,CAAC,CAAE;AAEN,SAAO,WACN,4EACC;AAAA,gDAAC,sBAAmB,UAAsB;AAAA,IAC1C,4CAAC,SAAI,WAAU,oCACd,sDAAC,iBAAc,UAAsB,GACtC;AAAA,KACD,IAEA,4CAAC,SAAI,WAAU,oCACd,sDAAC,6BAAQ,GACV;AAEF;",
|
|
6
6
|
"names": ["blockEditorPrivateApis", "clsx", "VisualEditor", "editorStore"]
|
|
7
7
|
}
|
|
@@ -49,18 +49,20 @@ var import_reset_default_template = __toESM(require("./reset-default-template.cj
|
|
|
49
49
|
var import_lock_unlock = require("../../lock-unlock.cjs");
|
|
50
50
|
var import_create_new_template = __toESM(require("./create-new-template.cjs"));
|
|
51
51
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
52
|
-
function BlockThemeControl(
|
|
52
|
+
function BlockThemeControl() {
|
|
53
53
|
const {
|
|
54
54
|
isTemplateHidden,
|
|
55
55
|
onNavigateToEntityRecord,
|
|
56
56
|
getEditorSettings,
|
|
57
57
|
hasGoBack,
|
|
58
|
-
hasSpecificTemplate
|
|
58
|
+
hasSpecificTemplate,
|
|
59
|
+
id
|
|
59
60
|
} = (0, import_data.useSelect)((select) => {
|
|
60
61
|
const {
|
|
61
62
|
getRenderingMode,
|
|
62
63
|
getEditorSettings: _getEditorSettings,
|
|
63
|
-
getCurrentPost
|
|
64
|
+
getCurrentPost,
|
|
65
|
+
getCurrentTemplateId
|
|
64
66
|
} = (0, import_lock_unlock.unlock)(select(import_store.store));
|
|
65
67
|
const editorSettings = _getEditorSettings();
|
|
66
68
|
const currentPost = getCurrentPost();
|
|
@@ -71,7 +73,8 @@ function BlockThemeControl({ id }) {
|
|
|
71
73
|
hasGoBack: editorSettings.hasOwnProperty(
|
|
72
74
|
"onNavigateToPreviousEntityRecord"
|
|
73
75
|
),
|
|
74
|
-
hasSpecificTemplate: !!currentPost.template
|
|
76
|
+
hasSpecificTemplate: !!currentPost.template,
|
|
77
|
+
id: getCurrentTemplateId()
|
|
75
78
|
};
|
|
76
79
|
}, []);
|
|
77
80
|
const { get: getPreference } = (0, import_data.useSelect)(import_preferences.store);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-template/block-theme.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';\nimport { useState, useMemo } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\nimport { useEntityRecord, store as coreStore } from '@wordpress/core-data';\nimport { check } from '@wordpress/icons';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { store as preferencesStore } from '@wordpress/preferences';\n\n/**\n * Internal dependencies\n */\nimport PostPanelRow from '../post-panel-row';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\nimport SwapTemplateButton from './swap-template-button';\nimport ResetDefaultTemplate from './reset-default-template';\nimport { unlock } from '../../lock-unlock';\nimport CreateNewTemplate from './create-new-template';\n\nexport default function BlockThemeControl(
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAuC;AACvC,2BAA+B;AAC/B,wBAAkD;AAClD,qBAAkC;AAClC,kBAAmB;AACnB,uBAAoD;AACpD,mBAAsB;AACtB,qBAAsC;AACtC,yBAA0C;AAK1C,4BAAyB;AAKzB,mBAAqC;AACrC,kCAA+B;AAC/B,oCAAiC;AACjC,yBAAuB;AACvB,iCAA8B;
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';\nimport { useState, useMemo } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\nimport { useEntityRecord, store as coreStore } from '@wordpress/core-data';\nimport { check } from '@wordpress/icons';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { store as preferencesStore } from '@wordpress/preferences';\n\n/**\n * Internal dependencies\n */\nimport PostPanelRow from '../post-panel-row';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\nimport SwapTemplateButton from './swap-template-button';\nimport ResetDefaultTemplate from './reset-default-template';\nimport { unlock } from '../../lock-unlock';\nimport CreateNewTemplate from './create-new-template';\n\nexport default function BlockThemeControl() {\n\tconst {\n\t\tisTemplateHidden,\n\t\tonNavigateToEntityRecord,\n\t\tgetEditorSettings,\n\t\thasGoBack,\n\t\thasSpecificTemplate,\n\t\tid,\n\t} = useSelect( ( select ) => {\n\t\tconst {\n\t\t\tgetRenderingMode,\n\t\t\tgetEditorSettings: _getEditorSettings,\n\t\t\tgetCurrentPost,\n\t\t\tgetCurrentTemplateId,\n\t\t} = unlock( select( editorStore ) );\n\t\tconst editorSettings = _getEditorSettings();\n\t\tconst currentPost = getCurrentPost();\n\t\treturn {\n\t\t\tisTemplateHidden: getRenderingMode() === 'post-only',\n\t\t\tonNavigateToEntityRecord: editorSettings.onNavigateToEntityRecord,\n\t\t\tgetEditorSettings: _getEditorSettings,\n\t\t\thasGoBack: editorSettings.hasOwnProperty(\n\t\t\t\t'onNavigateToPreviousEntityRecord'\n\t\t\t),\n\t\t\thasSpecificTemplate: !! currentPost.template,\n\t\t\tid: getCurrentTemplateId(),\n\t\t};\n\t}, [] );\n\n\tconst { get: getPreference } = useSelect( preferencesStore );\n\n\tconst { editedRecord: template, hasResolved } = useEntityRecord(\n\t\t'postType',\n\t\t'wp_template',\n\t\tid\n\t);\n\tconst { getEntityRecord } = useSelect( coreStore );\n\tconst { editEntityRecord } = useDispatch( coreStore );\n\tconst { createSuccessNotice } = useDispatch( noticesStore );\n\tconst { setRenderingMode, setDefaultRenderingMode } = unlock(\n\t\tuseDispatch( editorStore )\n\t);\n\n\tconst canCreateTemplate = useSelect(\n\t\t( select ) =>\n\t\t\t!! select( coreStore ).canUser( 'create', {\n\t\t\t\tkind: 'postType',\n\t\t\t\tname: 'wp_template',\n\t\t\t} ),\n\t\t[]\n\t);\n\n\tconst [ popoverAnchor, setPopoverAnchor ] = useState( null );\n\t// Memoize popoverProps to avoid returning a new object every time.\n\tconst popoverProps = useMemo(\n\t\t() => ( {\n\t\t\t// Anchor the popover to the middle of the entire row so that it doesn't\n\t\t\t// move around when the label changes.\n\t\t\tanchor: popoverAnchor,\n\t\t\tclassName: 'editor-post-template__dropdown',\n\t\t\tplacement: 'left-start',\n\t\t\toffset: 36,\n\t\t\tshift: true,\n\t\t} ),\n\t\t[ popoverAnchor ]\n\t);\n\n\tif ( ! hasResolved ) {\n\t\treturn null;\n\t}\n\n\t// The site editor does not have a `onNavigateToPreviousEntityRecord` setting as it uses its own routing\n\t// and assigns its own backlink to focusMode pages.\n\tconst notificationAction = hasGoBack\n\t\t? [\n\t\t\t\t{\n\t\t\t\t\tlabel: __( 'Go back' ),\n\t\t\t\t\tonClick: () =>\n\t\t\t\t\t\tgetEditorSettings().onNavigateToPreviousEntityRecord(),\n\t\t\t\t},\n\t\t ]\n\t\t: undefined;\n\n\tconst mayShowTemplateEditNotice = () => {\n\t\tif ( ! getPreference( 'core/edit-site', 'welcomeGuideTemplate' ) ) {\n\t\t\tcreateSuccessNotice(\n\t\t\t\t__(\n\t\t\t\t\t'Editing template. Changes made here affect all posts and pages that use the template.'\n\t\t\t\t),\n\t\t\t\t{ type: 'snackbar', actions: notificationAction }\n\t\t\t);\n\t\t}\n\t};\n\treturn (\n\t\t<PostPanelRow label={ __( 'Template' ) } ref={ setPopoverAnchor }>\n\t\t\t<DropdownMenu\n\t\t\t\tpopoverProps={ popoverProps }\n\t\t\t\tfocusOnMount\n\t\t\t\ttoggleProps={ {\n\t\t\t\t\tsize: 'compact',\n\t\t\t\t\tvariant: 'tertiary',\n\t\t\t\t\ttooltipPosition: 'middle left',\n\t\t\t\t} }\n\t\t\t\tlabel={ __( 'Template options' ) }\n\t\t\t\ttext={ decodeEntities( template.title ) }\n\t\t\t\ticon={ null }\n\t\t\t>\n\t\t\t\t{ ( { onClose } ) => (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<MenuGroup>\n\t\t\t\t\t\t\t{ canCreateTemplate && (\n\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\tonClick={ async () => {\n\t\t\t\t\t\t\t\t\t\tonNavigateToEntityRecord( {\n\t\t\t\t\t\t\t\t\t\t\tpostId: template.id,\n\t\t\t\t\t\t\t\t\t\t\tpostType: 'wp_template',\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t// When editing a global template,\n\t\t\t\t\t\t\t\t\t\t// activate the auto-draft. This is not\n\t\t\t\t\t\t\t\t\t\t// immediately live (we're not saving\n\t\t\t\t\t\t\t\t\t\t// site options), and when nothing is\n\t\t\t\t\t\t\t\t\t\t// saved, the setting will be ignored.\n\t\t\t\t\t\t\t\t\t\t// In the future, we should make the\n\t\t\t\t\t\t\t\t\t\t// duplication explicit, so there\n\t\t\t\t\t\t\t\t\t\t// wouldn't be an \"edit\" button for\n\t\t\t\t\t\t\t\t\t\t// static theme templates.\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t! hasSpecificTemplate &&\n\t\t\t\t\t\t\t\t\t\t\twindow?.__experimentalTemplateActivate\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\tconst activeTemplates =\n\t\t\t\t\t\t\t\t\t\t\t\tawait getEntityRecord(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'root',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'site'\n\t\t\t\t\t\t\t\t\t\t\t\t).active_templates;\n\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\tactiveTemplates[\n\t\t\t\t\t\t\t\t\t\t\t\t\ttemplate.slug\n\t\t\t\t\t\t\t\t\t\t\t\t] !== template.id\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\teditEntityRecord(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'root',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'site',\n\t\t\t\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tactive_templates: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...activeTemplates,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[ template.slug ]:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttemplate.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t\tmayShowTemplateEditNotice();\n\t\t\t\t\t\t\t\t\t} }\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{ __( 'Edit template' ) }\n\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t) }\n\n\t\t\t\t\t\t\t<SwapTemplateButton onClick={ onClose } />\n\t\t\t\t\t\t\t<ResetDefaultTemplate onClick={ onClose } />\n\t\t\t\t\t\t\t{ canCreateTemplate && <CreateNewTemplate /> }\n\t\t\t\t\t\t</MenuGroup>\n\t\t\t\t\t\t<MenuGroup>\n\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\ticon={ ! isTemplateHidden ? check : undefined }\n\t\t\t\t\t\t\t\tisSelected={ ! isTemplateHidden }\n\t\t\t\t\t\t\t\trole=\"menuitemcheckbox\"\n\t\t\t\t\t\t\t\tonClick={ () => {\n\t\t\t\t\t\t\t\t\tconst newRenderingMode = isTemplateHidden\n\t\t\t\t\t\t\t\t\t\t? 'template-locked'\n\t\t\t\t\t\t\t\t\t\t: 'post-only';\n\t\t\t\t\t\t\t\t\tsetRenderingMode( newRenderingMode );\n\t\t\t\t\t\t\t\t\tsetDefaultRenderingMode( newRenderingMode );\n\t\t\t\t\t\t\t\t} }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{ __( 'Show template' ) }\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t</MenuGroup>\n\t\t\t\t\t</>\n\t\t\t\t) }\n\t\t\t</DropdownMenu>\n\t\t</PostPanelRow>\n\t);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["editorStore", "preferencesStore", "coreStore", "noticesStore", "PostPanelRow", "SwapTemplateButton", "ResetDefaultTemplate", "CreateNewTemplate"]
|
|
7
7
|
}
|
|
@@ -23,7 +23,8 @@ __export(hooks_exports, {
|
|
|
23
23
|
useAllowSwitchingTemplates: () => useAllowSwitchingTemplates,
|
|
24
24
|
useAvailableTemplates: () => useAvailableTemplates,
|
|
25
25
|
useCurrentTemplateSlug: () => useCurrentTemplateSlug,
|
|
26
|
-
useEditedPostContext: () => useEditedPostContext
|
|
26
|
+
useEditedPostContext: () => useEditedPostContext,
|
|
27
|
+
usePostTemplatePanelMode: () => usePostTemplatePanelMode
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(hooks_exports);
|
|
29
30
|
var import_data = require("@wordpress/data");
|
|
@@ -82,6 +83,41 @@ function useAvailableTemplates(postType) {
|
|
|
82
83
|
[templates, currentTemplateSlug, allowSwitchingTemplate]
|
|
83
84
|
);
|
|
84
85
|
}
|
|
86
|
+
function usePostTemplatePanelMode() {
|
|
87
|
+
return (0, import_data.useSelect)((select) => {
|
|
88
|
+
const { getEditorSettings, getCurrentTemplateId, getCurrentPostType } = select(import_store.store);
|
|
89
|
+
const { getPostType, canUser } = select(import_core_data.store);
|
|
90
|
+
const postTypeSlug = getCurrentPostType();
|
|
91
|
+
const postType = getPostType(postTypeSlug);
|
|
92
|
+
const settings = getEditorSettings();
|
|
93
|
+
const isBlockTheme = settings.__unstableIsBlockBasedTheme;
|
|
94
|
+
const hasTemplates = !!settings.availableTemplates && Object.keys(settings.availableTemplates).length > 0;
|
|
95
|
+
let isVisible;
|
|
96
|
+
if (!postType?.viewable) {
|
|
97
|
+
isVisible = false;
|
|
98
|
+
} else if (hasTemplates) {
|
|
99
|
+
isVisible = true;
|
|
100
|
+
} else if (!settings.supportsTemplateMode) {
|
|
101
|
+
isVisible = false;
|
|
102
|
+
} else {
|
|
103
|
+
isVisible = canUser("create", {
|
|
104
|
+
kind: "postType",
|
|
105
|
+
name: "wp_template"
|
|
106
|
+
}) ?? false;
|
|
107
|
+
}
|
|
108
|
+
const canViewTemplates = isVisible ? !!canUser("read", {
|
|
109
|
+
kind: "postType",
|
|
110
|
+
name: "wp_template"
|
|
111
|
+
}) : false;
|
|
112
|
+
if ((!isBlockTheme || !canViewTemplates) && isVisible) {
|
|
113
|
+
return "classic";
|
|
114
|
+
}
|
|
115
|
+
if (isBlockTheme && !!getCurrentTemplateId()) {
|
|
116
|
+
return "block-theme";
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}, []);
|
|
120
|
+
}
|
|
85
121
|
function useCurrentTemplateSlug() {
|
|
86
122
|
const { postType, postId } = useEditedPostContext();
|
|
87
123
|
const templates = useTemplates(postType);
|
|
@@ -106,6 +142,7 @@ function useCurrentTemplateSlug() {
|
|
|
106
142
|
useAllowSwitchingTemplates,
|
|
107
143
|
useAvailableTemplates,
|
|
108
144
|
useCurrentTemplateSlug,
|
|
109
|
-
useEditedPostContext
|
|
145
|
+
useEditedPostContext,
|
|
146
|
+
usePostTemplatePanelMode
|
|
110
147
|
});
|
|
111
148
|
//# sourceMappingURL=hooks.cjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-template/hooks.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { useMemo } from '@wordpress/element';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\n\nexport function useEditedPostContext() {\n\treturn useSelect( ( select ) => {\n\t\tconst { getCurrentPostId, getCurrentPostType } = select( editorStore );\n\t\treturn {\n\t\t\tpostId: getCurrentPostId(),\n\t\t\tpostType: getCurrentPostType(),\n\t\t};\n\t}, [] );\n}\nexport function useAllowSwitchingTemplates() {\n\tconst { postType, postId } = useEditedPostContext();\n\treturn useSelect(\n\t\t( select ) => {\n\t\t\tconst { canUser, getEntityRecord, getEntityRecords } =\n\t\t\t\tselect( coreStore );\n\t\t\tconst siteSettings = canUser( 'read', {\n\t\t\t\tkind: 'root',\n\t\t\t\tname: 'site',\n\t\t\t} )\n\t\t\t\t? getEntityRecord( 'root', 'site' )\n\t\t\t\t: undefined;\n\n\t\t\tconst isPostsPage = +postId === siteSettings?.page_for_posts;\n\t\t\tconst isFrontPage =\n\t\t\t\tpostType === 'page' && +postId === siteSettings?.page_on_front;\n\t\t\t// If current page is set front page or posts page, we also need\n\t\t\t// to check if the current theme has a template for it. If not\n\t\t\tconst templates = isFrontPage\n\t\t\t\t? getEntityRecords( 'postType', 'wp_template', {\n\t\t\t\t\t\tper_page: -1,\n\t\t\t\t } )\n\t\t\t\t: [];\n\t\t\tconst hasFrontPage =\n\t\t\t\tisFrontPage &&\n\t\t\t\t!! templates?.some( ( { slug } ) => slug === 'front-page' );\n\t\t\treturn ! isPostsPage && ! hasFrontPage;\n\t\t},\n\t\t[ postId, postType ]\n\t);\n}\n\nfunction useTemplates( postType ) {\n\treturn useSelect(\n\t\t( select ) =>\n\t\t\tselect( coreStore ).getEntityRecords( 'postType', 'wp_template', {\n\t\t\t\tper_page: -1,\n\t\t\t\tpost_type: postType,\n\t\t\t\t// We look at the combined templates for now (old endpoint)\n\t\t\t\t// because posts only accept slugs for templates, not IDs.\n\t\t\t} ),\n\t\t[ postType ]\n\t);\n}\n\nexport function useAvailableTemplates( postType ) {\n\tconst currentTemplateSlug = useCurrentTemplateSlug();\n\tconst allowSwitchingTemplate = useAllowSwitchingTemplates();\n\tconst templates = useTemplates( postType );\n\treturn useMemo(\n\t\t() =>\n\t\t\tallowSwitchingTemplate &&\n\t\t\ttemplates?.filter(\n\t\t\t\t( template ) =>\n\t\t\t\t\ttemplate.is_custom &&\n\t\t\t\t\ttemplate.slug !== currentTemplateSlug &&\n\t\t\t\t\t!! template.content.raw // Skip empty templates.\n\t\t\t),\n\t\t[ templates, currentTemplateSlug, allowSwitchingTemplate ]\n\t);\n}\n\nexport function useCurrentTemplateSlug() {\n\tconst { postType, postId } = useEditedPostContext();\n\tconst templates = useTemplates( postType );\n\tconst entityTemplate = useSelect(\n\t\t( select ) => {\n\t\t\tconst post = select( coreStore ).getEditedEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\tpostType,\n\t\t\t\tpostId\n\t\t\t);\n\t\t\treturn post?.template;\n\t\t},\n\t\t[ postType, postId ]\n\t);\n\n\tif ( ! entityTemplate ) {\n\t\treturn;\n\t}\n\t// If a page has a `template` set and is not included in the list\n\t// of the theme's templates, do not return it, in order to resolve\n\t// to the current theme's default template.\n\treturn templates?.find( ( template ) => template.slug === entityTemplate )\n\t\t?.slug;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA0B;AAC1B,qBAAwB;AACxB,uBAAmC;AAKnC,mBAAqC;AAE9B,SAAS,uBAAuB;AACtC,aAAO,uBAAW,CAAE,WAAY;AAC/B,UAAM,EAAE,kBAAkB,mBAAmB,IAAI,OAAQ,aAAAA,KAAY;AACrE,WAAO;AAAA,MACN,QAAQ,iBAAiB;AAAA,MACzB,UAAU,mBAAmB;AAAA,IAC9B;AAAA,EACD,GAAG,CAAC,CAAE;AACP;AACO,SAAS,6BAA6B;AAC5C,QAAM,EAAE,UAAU,OAAO,IAAI,qBAAqB;AAClD,aAAO;AAAA,IACN,CAAE,WAAY;AACb,YAAM,EAAE,SAAS,iBAAiB,iBAAiB,IAClD,OAAQ,iBAAAC,KAAU;AACnB,YAAM,eAAe,QAAS,QAAQ;AAAA,QACrC,MAAM;AAAA,QACN,MAAM;AAAA,MACP,CAAE,IACC,gBAAiB,QAAQ,MAAO,IAChC;AAEH,YAAM,cAAc,CAAC,WAAW,cAAc;AAC9C,YAAM,cACL,aAAa,UAAU,CAAC,WAAW,cAAc;AAGlD,YAAM,YAAY,cACf,iBAAkB,YAAY,eAAe;AAAA,QAC7C,UAAU;AAAA,MACV,CAAE,IACF,CAAC;AACJ,YAAM,eACL,eACA,CAAC,CAAE,WAAW,KAAM,CAAE,EAAE,KAAK,MAAO,SAAS,YAAa;AAC3D,aAAO,CAAE,eAAe,CAAE;AAAA,IAC3B;AAAA,IACA,CAAE,QAAQ,QAAS;AAAA,EACpB;AACD;AAEA,SAAS,aAAc,UAAW;AACjC,aAAO;AAAA,IACN,CAAE,WACD,OAAQ,iBAAAA,KAAU,EAAE,iBAAkB,YAAY,eAAe;AAAA,MAChE,UAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA,IAGZ,CAAE;AAAA,IACH,CAAE,QAAS;AAAA,EACZ;AACD;AAEO,SAAS,sBAAuB,UAAW;AACjD,QAAM,sBAAsB,uBAAuB;AACnD,QAAM,yBAAyB,2BAA2B;AAC1D,QAAM,YAAY,aAAc,QAAS;AACzC,aAAO;AAAA,IACN,MACC,0BACA,WAAW;AAAA,MACV,CAAE,aACD,SAAS,aACT,SAAS,SAAS,uBAClB,CAAC,CAAE,SAAS,QAAQ;AAAA;AAAA,IACtB;AAAA,IACD,CAAE,WAAW,qBAAqB,sBAAuB;AAAA,EAC1D;AACD;AAEO,SAAS,yBAAyB;AACxC,QAAM,EAAE,UAAU,OAAO,IAAI,qBAAqB;AAClD,QAAM,YAAY,aAAc,QAAS;AACzC,QAAM,qBAAiB;AAAA,IACtB,CAAE,WAAY;AACb,YAAM,OAAO,OAAQ,iBAAAA,KAAU,EAAE;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA,aAAO,MAAM;AAAA,IACd;AAAA,IACA,CAAE,UAAU,MAAO;AAAA,EACpB;AAEA,MAAK,CAAE,gBAAiB;AACvB;AAAA,EACD;AAIA,SAAO,WAAW,KAAM,CAAE,aAAc,SAAS,SAAS,cAAe,GACtE;AACJ;",
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { useMemo } from '@wordpress/element';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\n\nexport function useEditedPostContext() {\n\treturn useSelect( ( select ) => {\n\t\tconst { getCurrentPostId, getCurrentPostType } = select( editorStore );\n\t\treturn {\n\t\t\tpostId: getCurrentPostId(),\n\t\t\tpostType: getCurrentPostType(),\n\t\t};\n\t}, [] );\n}\nexport function useAllowSwitchingTemplates() {\n\tconst { postType, postId } = useEditedPostContext();\n\treturn useSelect(\n\t\t( select ) => {\n\t\t\tconst { canUser, getEntityRecord, getEntityRecords } =\n\t\t\t\tselect( coreStore );\n\t\t\tconst siteSettings = canUser( 'read', {\n\t\t\t\tkind: 'root',\n\t\t\t\tname: 'site',\n\t\t\t} )\n\t\t\t\t? getEntityRecord( 'root', 'site' )\n\t\t\t\t: undefined;\n\n\t\t\tconst isPostsPage = +postId === siteSettings?.page_for_posts;\n\t\t\tconst isFrontPage =\n\t\t\t\tpostType === 'page' && +postId === siteSettings?.page_on_front;\n\t\t\t// If current page is set front page or posts page, we also need\n\t\t\t// to check if the current theme has a template for it. If not\n\t\t\tconst templates = isFrontPage\n\t\t\t\t? getEntityRecords( 'postType', 'wp_template', {\n\t\t\t\t\t\tper_page: -1,\n\t\t\t\t } )\n\t\t\t\t: [];\n\t\t\tconst hasFrontPage =\n\t\t\t\tisFrontPage &&\n\t\t\t\t!! templates?.some( ( { slug } ) => slug === 'front-page' );\n\t\t\treturn ! isPostsPage && ! hasFrontPage;\n\t\t},\n\t\t[ postId, postType ]\n\t);\n}\n\nfunction useTemplates( postType ) {\n\treturn useSelect(\n\t\t( select ) =>\n\t\t\tselect( coreStore ).getEntityRecords( 'postType', 'wp_template', {\n\t\t\t\tper_page: -1,\n\t\t\t\tpost_type: postType,\n\t\t\t\t// We look at the combined templates for now (old endpoint)\n\t\t\t\t// because posts only accept slugs for templates, not IDs.\n\t\t\t} ),\n\t\t[ postType ]\n\t);\n}\n\nexport function useAvailableTemplates( postType ) {\n\tconst currentTemplateSlug = useCurrentTemplateSlug();\n\tconst allowSwitchingTemplate = useAllowSwitchingTemplates();\n\tconst templates = useTemplates( postType );\n\treturn useMemo(\n\t\t() =>\n\t\t\tallowSwitchingTemplate &&\n\t\t\ttemplates?.filter(\n\t\t\t\t( template ) =>\n\t\t\t\t\ttemplate.is_custom &&\n\t\t\t\t\ttemplate.slug !== currentTemplateSlug &&\n\t\t\t\t\t!! template.content.raw // Skip empty templates.\n\t\t\t),\n\t\t[ templates, currentTemplateSlug, allowSwitchingTemplate ]\n\t);\n}\n\nexport function usePostTemplatePanelMode() {\n\treturn useSelect( ( select ) => {\n\t\tconst { getEditorSettings, getCurrentTemplateId, getCurrentPostType } =\n\t\t\tselect( editorStore );\n\t\tconst { getPostType, canUser } = select( coreStore );\n\t\tconst postTypeSlug = getCurrentPostType();\n\t\tconst postType = getPostType( postTypeSlug );\n\t\tconst settings = getEditorSettings();\n\t\tconst isBlockTheme = settings.__unstableIsBlockBasedTheme;\n\t\tconst hasTemplates =\n\t\t\t!! settings.availableTemplates &&\n\t\t\tObject.keys( settings.availableTemplates ).length > 0;\n\t\tlet isVisible;\n\t\tif ( ! postType?.viewable ) {\n\t\t\tisVisible = false;\n\t\t} else if ( hasTemplates ) {\n\t\t\tisVisible = true;\n\t\t} else if ( ! settings.supportsTemplateMode ) {\n\t\t\tisVisible = false;\n\t\t} else {\n\t\t\tisVisible =\n\t\t\t\tcanUser( 'create', {\n\t\t\t\t\tkind: 'postType',\n\t\t\t\t\tname: 'wp_template',\n\t\t\t\t} ) ?? false;\n\t\t}\n\t\tconst canViewTemplates = isVisible\n\t\t\t? !! canUser( 'read', {\n\t\t\t\t\tkind: 'postType',\n\t\t\t\t\tname: 'wp_template',\n\t\t\t } )\n\t\t\t: false;\n\t\tif ( ( ! isBlockTheme || ! canViewTemplates ) && isVisible ) {\n\t\t\treturn 'classic';\n\t\t}\n\t\tif ( isBlockTheme && !! getCurrentTemplateId() ) {\n\t\t\treturn 'block-theme';\n\t\t}\n\t\treturn null;\n\t}, [] );\n}\n\nexport function useCurrentTemplateSlug() {\n\tconst { postType, postId } = useEditedPostContext();\n\tconst templates = useTemplates( postType );\n\tconst entityTemplate = useSelect(\n\t\t( select ) => {\n\t\t\tconst post = select( coreStore ).getEditedEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\tpostType,\n\t\t\t\tpostId\n\t\t\t);\n\t\t\treturn post?.template;\n\t\t},\n\t\t[ postType, postId ]\n\t);\n\n\tif ( ! entityTemplate ) {\n\t\treturn;\n\t}\n\t// If a page has a `template` set and is not included in the list\n\t// of the theme's templates, do not return it, in order to resolve\n\t// to the current theme's default template.\n\treturn templates?.find( ( template ) => template.slug === entityTemplate )\n\t\t?.slug;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["editorStore", "coreStore"]
|
|
7
7
|
}
|
|
@@ -33,54 +33,17 @@ __export(panel_exports, {
|
|
|
33
33
|
default: () => PostTemplatePanel
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(panel_exports);
|
|
36
|
-
var
|
|
37
|
-
var import_core_data = require("@wordpress/core-data");
|
|
38
|
-
var import_store = require("../../store/index.cjs");
|
|
36
|
+
var import_hooks = require("./hooks.cjs");
|
|
39
37
|
var import_classic_theme = __toESM(require("./classic-theme.cjs"));
|
|
40
38
|
var import_block_theme = __toESM(require("./block-theme.cjs"));
|
|
41
39
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
42
40
|
function PostTemplatePanel() {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
templateId: getCurrentTemplateId(),
|
|
47
|
-
isBlockTheme: getEditorSettings().__unstableIsBlockBasedTheme
|
|
48
|
-
};
|
|
49
|
-
}, []);
|
|
50
|
-
const isVisible = (0, import_data.useSelect)((select) => {
|
|
51
|
-
const postTypeSlug = select(import_store.store).getCurrentPostType();
|
|
52
|
-
const postType = select(import_core_data.store).getPostType(postTypeSlug);
|
|
53
|
-
if (!postType?.viewable) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
const settings = select(import_store.store).getEditorSettings();
|
|
57
|
-
const hasTemplates = !!settings.availableTemplates && Object.keys(settings.availableTemplates).length > 0;
|
|
58
|
-
if (hasTemplates) {
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
if (!settings.supportsTemplateMode) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
const canCreateTemplates = select(import_core_data.store).canUser("create", {
|
|
65
|
-
kind: "postType",
|
|
66
|
-
name: "wp_template"
|
|
67
|
-
}) ?? false;
|
|
68
|
-
return canCreateTemplates;
|
|
69
|
-
}, []);
|
|
70
|
-
const canViewTemplates = (0, import_data.useSelect)(
|
|
71
|
-
(select) => {
|
|
72
|
-
return isVisible ? select(import_core_data.store).canUser("read", {
|
|
73
|
-
kind: "postType",
|
|
74
|
-
name: "wp_template"
|
|
75
|
-
}) : false;
|
|
76
|
-
},
|
|
77
|
-
[isVisible]
|
|
78
|
-
);
|
|
79
|
-
if ((!isBlockTheme || !canViewTemplates) && isVisible) {
|
|
41
|
+
const mode = (0, import_hooks.usePostTemplatePanelMode)();
|
|
42
|
+
if (mode === "classic") {
|
|
80
43
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_classic_theme.default, {});
|
|
81
44
|
}
|
|
82
|
-
if (
|
|
83
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_theme.default, {
|
|
45
|
+
if (mode === "block-theme") {
|
|
46
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_theme.default, {});
|
|
84
47
|
}
|
|
85
48
|
return null;
|
|
86
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/post-template/panel.js"],
|
|
4
|
-
"sourcesContent": ["/**\n *
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["/**\n * Internal dependencies\n */\nimport { usePostTemplatePanelMode } from './hooks';\nimport ClassicThemeControl from './classic-theme';\nimport BlockThemeControl from './block-theme';\n\n/**\n * Displays the template controls based on the current editor settings and user permissions.\n *\n * @return {React.ReactNode} The rendered PostTemplatePanel component.\n */\nexport default function PostTemplatePanel() {\n\tconst mode = usePostTemplatePanelMode();\n\tif ( mode === 'classic' ) {\n\t\treturn <ClassicThemeControl />;\n\t}\n\tif ( mode === 'block-theme' ) {\n\t\treturn <BlockThemeControl />;\n\t}\n\treturn null;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAAyC;AACzC,2BAAgC;AAChC,yBAA8B;AAUrB;AAHM,SAAR,oBAAqC;AAC3C,QAAM,WAAO,uCAAyB;AACtC,MAAK,SAAS,WAAY;AACzB,WAAO,4CAAC,qBAAAA,SAAA,EAAoB;AAAA,EAC7B;AACA,MAAK,SAAS,eAAgB;AAC7B,WAAO,4CAAC,mBAAAC,SAAA,EAAkB;AAAA,EAC3B;AACA,SAAO;AACR;",
|
|
6
|
+
"names": ["ClassicThemeControl", "BlockThemeControl"]
|
|
7
7
|
}
|
|
@@ -45,6 +45,7 @@ var import_media_categories = __toESM(require("../media-categories/index.cjs"));
|
|
|
45
45
|
var import_utils = require("../../utils/index.cjs");
|
|
46
46
|
var import_on_success = __toESM(require("../../utils/media-upload/on-success.cjs"));
|
|
47
47
|
var import_media_sideload = __toESM(require("../../utils/media-sideload/index.cjs"));
|
|
48
|
+
var import_media_finalize = __toESM(require("../../utils/media-finalize/index.cjs"));
|
|
48
49
|
var import_store = require("../../store/index.cjs");
|
|
49
50
|
var import_lock_unlock = require("../../lock-unlock.cjs");
|
|
50
51
|
var import_global_styles_provider = require("../global-styles-provider/index.cjs");
|
|
@@ -294,6 +295,7 @@ function useBlockEditorSettings(settings, postType, postId, renderingMode) {
|
|
|
294
295
|
mediaUpload: hasUploadPermissions ? import_utils.mediaUpload : void 0,
|
|
295
296
|
[mediaUploadOnSuccessKey]: hasUploadPermissions ? import_on_success.default : void 0,
|
|
296
297
|
mediaSideload: hasUploadPermissions ? import_media_sideload.default : void 0,
|
|
298
|
+
mediaFinalize: hasUploadPermissions ? import_media_finalize.default : void 0,
|
|
297
299
|
__experimentalBlockPatterns: blockPatterns,
|
|
298
300
|
[selectBlockPatternsKey]: (select) => {
|
|
299
301
|
const { hasFinishedResolution, getBlockPatternsForPostType } = (0, import_lock_unlock.unlock)(select(import_core_data.store));
|