@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
8 lines (7 loc) • 13.1 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../src/components/post-revisions-preview/revisions-canvas.js"],
"sourcesContent": ["import clsx from 'clsx';\nimport { Spinner } from '@wordpress/components';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { useContext, useEffect } from '@wordpress/element';\nimport { addFilter } from '@wordpress/hooks';\nimport { store as blocksStore } from '@wordpress/blocks';\nimport { sprintf, __ } from '@wordpress/i18n';\nimport { VisuallyHidden } from '@wordpress/ui';\nimport { unlock } from '../../lock-unlock';\nimport { store as editorStore } from '../../store';\nimport VisualEditor from '../visual-editor';\nimport {\n\tregisterDiffFormatTypes,\n\tunregisterDiffFormatTypes,\n\tDIFF_DESCRIPTION_IDS,\n} from './diff-format-types';\nimport { useDiffMarkers } from './diff-markers';\n\nconst { usePrivateStyleOverride, PrivateBlockContext } = unlock(\n\tblockEditorPrivateApis\n);\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\toutline: 3px solid #00a32a;\n\t\toutline-offset: 2px;\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-removed {\n\t\toutline: 3px dashed #d63638;\n\t\toutline-offset: 2px;\n\t}\n\t.is-revision-modified {\n\t\toutline: 3px dotted #9a7000 !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/* Reset UA <mark> styles so format markers keep the same look as before. */\n\tmark.revision-diff-format-added,\n\tmark.revision-diff-format-removed,\n\tmark.revision-diff-format-changed {\n\t\tbackground: transparent;\n\t\tcolor: inherit;\n\t\tpadding: 0;\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 * Returns an accessible label for a block based on its revision diff status.\n *\n * @param {string} status The diff status: 'added', 'removed', or 'modified'.\n * @param {string} blockTitle The human-readable block type name.\n * @return {string|undefined} The aria-label string, or undefined if not applicable.\n */\nfunction getDiffStatusLabel( status, blockTitle ) {\n\tswitch ( status ) {\n\t\tcase 'added':\n\t\t\t// translators: %s: block type name e.g. \"Paragraph\"\n\t\t\treturn sprintf( __( 'Added block: %s' ), blockTitle );\n\t\tcase 'removed':\n\t\t\t// translators: %s: block type name e.g. \"Paragraph\"\n\t\t\treturn sprintf( __( 'Removed block: %s' ), blockTitle );\n\t\tcase 'modified':\n\t\t\t// translators: %s: block type name e.g. \"Paragraph\"\n\t\t\treturn sprintf( __( 'Modified block: %s' ), blockTitle );\n\t}\n}\n\n/**\n * Overrides the wrapped block's aria-label with its diff status label.\n *\n * Only the block itself is affected: nested blocks set up their own private\n * context, so they don't inherit an ancestor's diff label.\n *\n * @param {Object} props Component props.\n * @param {string} props.status The diff status.\n * @param {string} props.name The block name.\n * @param {Object} props.attributes The block attributes.\n * @param {JSX.Element} props.children The block to label.\n * @return {JSX.Element} The labelled block.\n */\nfunction BlockDiffLabelProvider( { status, name, attributes, children } ) {\n\tconst context = useContext( PrivateBlockContext );\n\t// Resolve the variation-aware title (e.g. \"Row\" instead of \"Group\") so\n\t// blocks are announced by the name users know them as. The canvas's\n\t// default wrapper labels can't be reused here: in preview mode they\n\t// intentionally skip variation matching.\n\tconst blockTitle = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getActiveBlockVariation, getBlockType } =\n\t\t\t\tselect( blocksStore );\n\t\t\treturn (\n\t\t\t\tgetActiveBlockVariation( name, attributes )?.title ??\n\t\t\t\tgetBlockType( name )?.title\n\t\t\t);\n\t\t},\n\t\t[ name, attributes ]\n\t);\n\treturn (\n\t\t<PrivateBlockContext.Provider\n\t\t\tvalue={ {\n\t\t\t\t...context,\n\t\t\t\tariaLabel: blockTitle\n\t\t\t\t\t? getDiffStatusLabel( status, blockTitle )\n\t\t\t\t\t: undefined,\n\t\t\t} }\n\t\t>\n\t\t\t{ children }\n\t\t</PrivateBlockContext.Provider>\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 function WithRevisionDiffClasses( props ) {\n\t\tconst { block, className, name, attributes } = 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\t// This filter runs for every block in every editor, so the private\n\t\t// context is only overridden where a diff status actually applies.\n\t\tif ( ! diffStatus ) {\n\t\t\treturn (\n\t\t\t\t<BlockListBlock { ...props } className={ enhancedClassName } />\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<BlockDiffLabelProvider\n\t\t\t\tstatus={ diffStatus }\n\t\t\t\tname={ name }\n\t\t\t\tattributes={ attributes }\n\t\t\t>\n\t\t\t\t<BlockListBlock { ...props } className={ enhancedClassName } />\n\t\t\t</BlockDiffLabelProvider>\n\t\t);\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\n/**\n * Visually hidden descriptions that diff marks (<del>, <ins>, <mark>)\n * reference via `aria-describedby`. They must be rendered inside the\n * canvas iframe because `aria-describedby` cannot reference an element\n * across a document/iframe boundary. This is more reliable than `title`,\n * which some screen readers ignore in low-verbosity modes.\n */\nfunction DiffDescriptions() {\n\treturn (\n\t\t<VisuallyHidden>\n\t\t\t<span id={ DIFF_DESCRIPTION_IDS.removed }>{ __( 'Removed' ) }</span>\n\t\t\t<span id={ DIFF_DESCRIPTION_IDS.added }>{ __( 'Added' ) }</span>\n\t\t\t<span id={ DIFF_DESCRIPTION_IDS.formatAdded }>\n\t\t\t\t{ __( 'Format added' ) }\n\t\t\t</span>\n\t\t\t<span id={ DIFF_DESCRIPTION_IDS.formatRemoved }>\n\t\t\t\t{ __( 'Format removed' ) }\n\t\t\t</span>\n\t\t\t<span id={ DIFF_DESCRIPTION_IDS.formatChanged }>\n\t\t\t\t{ __( 'Format changed' ) }\n\t\t\t</span>\n\t\t</VisuallyHidden>\n\t);\n}\n\nfunction CanvasContent( { showDiff } ) {\n\tconst [ contentRef, diffMarkers ] = useDiffMarkers();\n\treturn (\n\t\t<>\n\t\t\t{ showDiff && <DiffDescriptions /> }\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"],
"mappings": "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",
"names": ["blockEditorPrivateApis", "blocksStore", "clsx", "VisualEditor", "editorStore"]
}