diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 288bef1580038f..98615b93b8a176 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -69,13 +69,13 @@ jobs: - name: Compare performance with base branch if: github.event_name == 'push' # The base hash used here need to be a commit that is compatible with the current WP version - # The current one is 9725060a5b18904c6cc5fdbe4b06fbde7419e02c and it needs to be updated every WP major release. + # The current one is 5f4c9c853b15092ed885d5280edefb973c37d9e9 and it needs to be updated every WP major release. # It is used as a base comparison point to avoid fluctuation in the performance metrics. run: | WP_VERSION=$(awk -F ': ' '/^Tested up to/{print $2}' readme.txt) IFS=. read -ra WP_VERSION_ARRAY <<< "$WP_VERSION" WP_MAJOR="${WP_VERSION_ARRAY[0]}.${WP_VERSION_ARRAY[1]}" - ./bin/plugin/cli.js perf $GITHUB_SHA 9725060a5b18904c6cc5fdbe4b06fbde7419e02c --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" + ./bin/plugin/cli.js perf $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" - name: Compare performance with custom branches if: github.event_name == 'workflow_dispatch' @@ -101,7 +101,7 @@ jobs: CODEHEALTH_PROJECT_TOKEN: ${{ secrets.CODEHEALTH_PROJECT_TOKEN }} run: | COMMITTED_AT=$(git show -s $GITHUB_SHA --format="%cI") - ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 9725060a5b18904c6cc5fdbe4b06fbde7419e02c $COMMITTED_AT + ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 $COMMITTED_AT - name: Archive debug artifacts (screenshots, HTML snapshots) uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 diff --git a/changelog.txt b/changelog.txt index 412d6184d76604..b7bbdf821f374e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,40 +1,14 @@ == Changelog == -= 18.9.0-rc.1 = - += 18.9.0 = ## Changelog -### Features - -- change: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) - -#### Global Styles -- Adding Font size presets UI. ([63057](https://github.com/WordPress/gutenberg/pull/63057)) - - ### Enhancements -- Background tool: Fix double border. ([63559](https://github.com/WordPress/gutenberg/pull/63559)) -- Core Data: Mark 'canUser' related actions resolvers as resolved. ([63435](https://github.com/WordPress/gutenberg/pull/63435)) -- Core Data: Resolve user capabilities when fetching an entity. ([63430](https://github.com/WordPress/gutenberg/pull/63430)) -- Core Data: Support entities in the 'canUser' selector. ([63322](https://github.com/WordPress/gutenberg/pull/63322)) -- Core Data: Support entity queries in the 'useResourcePermissions' hook. ([63653](https://github.com/WordPress/gutenberg/pull/63653)) -- DataViews: Update pagination icons. ([63594](https://github.com/WordPress/gutenberg/pull/63594)) -- Embeds: Add 'Embed' to title for clarity. ([63371](https://github.com/WordPress/gutenberg/pull/63371)) -- Polish "Delete" modal. ([63392](https://github.com/WordPress/gutenberg/pull/63392)) -- Run sync when issue is labeled with Sync Backport Changelog. ([63793](https://github.com/WordPress/gutenberg/pull/63793)) -- Update JSON Schemas to Draft 7. ([63583](https://github.com/WordPress/gutenberg/pull/63583)) -- Update: Grid layout: Allow users to adjust grid density. ([63367](https://github.com/WordPress/gutenberg/pull/63367)) -- Update: Include avatars on list view. ([63309](https://github.com/WordPress/gutenberg/pull/63309)) -- Update: List / Table layout – selected item stroke should be tinted blue. ([63312](https://github.com/WordPress/gutenberg/pull/63312)) -- Update: Make changing order an action on the ellipsis menu. ([62189](https://github.com/WordPress/gutenberg/pull/62189)) -- Update: Pages: Trash view should default to table layout try 2. ([63652](https://github.com/WordPress/gutenberg/pull/63652)) -- Update: Simplify some permission checks. ([63812](https://github.com/WordPress/gutenberg/pull/63812)) -- Use entity details when calling 'canUser' selectors. ([63415](https://github.com/WordPress/gutenberg/pull/63415)) - #### Block Library - Add Clear button for Overlay color option in Cover Block. ([63580](https://github.com/WordPress/gutenberg/pull/63580)) +- Embeds: Add 'Embed' to title for clarity. ([63371](https://github.com/WordPress/gutenberg/pull/63371)) - Columns block: Fix block preview. ([63609](https://github.com/WordPress/gutenberg/pull/63609)) - Gallery: Add border block support. ([63428](https://github.com/WordPress/gutenberg/pull/63428)) - Image block: Show placeholder when uploading HEIC files. ([63643](https://github.com/WordPress/gutenberg/pull/63643)) @@ -50,21 +24,10 @@ - Query Loop: Change default query loop variations. ([63353](https://github.com/WordPress/gutenberg/pull/63353)) - Set query loop to have the inherit value by default. ([63362](https://github.com/WordPress/gutenberg/pull/63362)) - Social Links: Add border block support. ([63629](https://github.com/WordPress/gutenberg/pull/63629)) +- Social Links: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) +- Social Links: Update Facebook's color to match brand guidelines. ([60424](https://github.com/WordPress/gutenberg/pull/60424)) - Term Description: Add border block support. ([63630](https://github.com/WordPress/gutenberg/pull/63630)) -#### Components -- CustomSelectControl V2 legacy adapter: Stabilize experimental props. ([63248](https://github.com/WordPress/gutenberg/pull/63248)) -- CustomSelectControl: Switch to ariakit-based implementation. ([63258](https://github.com/WordPress/gutenberg/pull/63258)) -- CustomSelectControlV2: Animate select popover appearance. ([63343](https://github.com/WordPress/gutenberg/pull/63343)) -- CustomSelectControlV2: Do not flip popover if legacy adapter. ([63357](https://github.com/WordPress/gutenberg/pull/63357)) -- DropdownMenuV2: Invert animation direction. ([63443](https://github.com/WordPress/gutenberg/pull/63443)) -- FontSizePicker: Tidy up internal logic. ([63553](https://github.com/WordPress/gutenberg/pull/63553)) -- FormTokenField: Deprecate bottom margin. ([63491](https://github.com/WordPress/gutenberg/pull/63491)) -- SelectControl: Add "minimal" variant. ([63265](https://github.com/WordPress/gutenberg/pull/63265)) -- Tabs: Hyphenate tab labels. ([63337](https://github.com/WordPress/gutenberg/pull/63337)) -- Tabs: Keep full opacity of focus ring on disabled tabs. ([63754](https://github.com/WordPress/gutenberg/pull/63754)) -- Update HeightControl component to label inputs. ([63761](https://github.com/WordPress/gutenberg/pull/63761)) - #### Design Tools - Background Image: Make panel appear in a consistent location. ([63551](https://github.com/WordPress/gutenberg/pull/63551)) - Buttons: Add border, color, and padding block supports. ([63538](https://github.com/WordPress/gutenberg/pull/63538)) @@ -77,15 +40,21 @@ #### Data Views - DataViews: Allow column re-ordering. ([63416](https://github.com/WordPress/gutenberg/pull/63416)) +- DataViews: Update pagination icons. ([63594](https://github.com/WordPress/gutenberg/pull/63594)) - DataViews: Rename the header property of fields to label. ([63843](https://github.com/WordPress/gutenberg/pull/63843)) - DataViews: Support combined fields. ([63236](https://github.com/WordPress/gutenberg/pull/63236)) - Dataviews List: Update item layout. ([63299](https://github.com/WordPress/gutenberg/pull/63299)) - Increase column-gap between fields in List layout. ([63603](https://github.com/WordPress/gutenberg/pull/63603)) -- Pages: Trash view should default to table layout. ([63138](https://github.com/WordPress/gutenberg/pull/63138)) - Update 'Front page' badge. ([63752](https://github.com/WordPress/gutenberg/pull/63752)) +- Update: Pages: Trash view should default to table layout try 2. ([63652](https://github.com/WordPress/gutenberg/pull/63652)) +- Update: Grid layout: Allow users to adjust grid density. ([63367](https://github.com/WordPress/gutenberg/pull/63367)) +- Update: Include avatars on list view. ([63309](https://github.com/WordPress/gutenberg/pull/63309)) +- Update: List / Table layout – selected item stroke should be tinted blue. ([63312](https://github.com/WordPress/gutenberg/pull/63312)) +- Update: Make changing order an action on the ellipsis menu. ([62189](https://github.com/WordPress/gutenberg/pull/62189)) #### Global Styles - Add colors and typograpghy to the browse styles section. ([63173](https://github.com/WordPress/gutenberg/pull/63173)) +- Adding Font size presets UI. ([63057](https://github.com/WordPress/gutenberg/pull/63057)) - Apply same styles to block previews on inserter and Global Styles. ([63177](https://github.com/WordPress/gutenberg/pull/63177)) - Background: Add background attachment to top level styles. ([61382](https://github.com/WordPress/gutenberg/pull/61382)) - Move background panel under color panel. ([63888](https://github.com/WordPress/gutenberg/pull/63888)) @@ -112,55 +81,60 @@ #### Block Locking - Tweak Block Locking UI. ([63881](https://github.com/WordPress/gutenberg/pull/63881)) -#### Icons +#### General UI +- Polish "Delete" modal. ([63392](https://github.com/WordPress/gutenberg/pull/63392)) - Update close icon. ([63597](https://github.com/WordPress/gutenberg/pull/63597)) +- Site Editor: Reduce navigation sidebar width. ([63431](https://github.com/WordPress/gutenberg/pull/63431)) #### Block bindings - Bootstrap sources defined in the server. ([63470](https://github.com/WordPress/gutenberg/pull/63470)) -#### Site Editor -- Reduce navigation sidebar width. ([63431](https://github.com/WordPress/gutenberg/pull/63431)) - #### Patterns - Limit pattern shuffling to theme and user patterns only. ([62677](https://github.com/WordPress/gutenberg/pull/62677)) +#### Components +- CustomSelectControl V2 legacy adapter: Stabilize experimental props. ([63248](https://github.com/WordPress/gutenberg/pull/63248)) +- CustomSelectControl: Switch to ariakit-based implementation. ([63258](https://github.com/WordPress/gutenberg/pull/63258)) +- CustomSelectControlV2: Animate select popover appearance. ([63343](https://github.com/WordPress/gutenberg/pull/63343)) +- CustomSelectControlV2: Do not flip popover if legacy adapter. ([63357](https://github.com/WordPress/gutenberg/pull/63357)) +- DropdownMenuV2: Invert animation direction. ([63443](https://github.com/WordPress/gutenberg/pull/63443)) +- FontSizePicker: Tidy up internal logic. ([63553](https://github.com/WordPress/gutenberg/pull/63553)) +- FormTokenField: Deprecate bottom margin. ([63491](https://github.com/WordPress/gutenberg/pull/63491)) +- SelectControl: Add "minimal" variant. ([63265](https://github.com/WordPress/gutenberg/pull/63265)) +- Tabs: Hyphenate tab labels. ([63337](https://github.com/WordPress/gutenberg/pull/63337)) +- Tabs: Keep full opacity of focus ring on disabled tabs. ([63754](https://github.com/WordPress/gutenberg/pull/63754)) +- Update HeightControl component to label inputs. ([63761](https://github.com/WordPress/gutenberg/pull/63761)) + +#### Core Data +- Core Data: Mark 'canUser' related actions resolvers as resolved. ([63435](https://github.com/WordPress/gutenberg/pull/63435)) +- Core Data: Resolve user capabilities when fetching an entity. ([63430](https://github.com/WordPress/gutenberg/pull/63430)) +- Core Data: Support entities in the 'canUser' selector. ([63322](https://github.com/WordPress/gutenberg/pull/63322)) +- Core Data: Support entity queries in the 'useResourcePermissions' hook. ([63653](https://github.com/WordPress/gutenberg/pull/63653)) + +#### JSON Schemas +- Update JSON Schemas to Draft 7. ([63583](https://github.com/WordPress/gutenberg/pull/63583)) ### New APIs #### Block bindings - Unify `getValue`/`getValues` and `setValue`/`setValues` APIs. ([63185](https://github.com/WordPress/gutenberg/pull/63185)) - ### Bug Fixes -- Add: Permission checks to avoid 403 errors on non admin roles. ([63296](https://github.com/WordPress/gutenberg/pull/63296)) -- DataViews: Do not render bulk actions Dropdown if no actions are available. ([63575](https://github.com/WordPress/gutenberg/pull/63575)) -- DataViews: Fix uncontrolled selection. ([63741](https://github.com/WordPress/gutenberg/pull/63741)) -- Disallow scrolling the block preview. ([63558](https://github.com/WordPress/gutenberg/pull/63558)) -- Discussions panel: Distinguish between verb and adjective form of open for internationalization. ([63791](https://github.com/WordPress/gutenberg/pull/63791)) -- Fix canvas issues by removing VisualEditor’s height. ([63724](https://github.com/WordPress/gutenberg/pull/63724)) -- Fix mobile styles for inserter pattern and media tab navigation. ([63451](https://github.com/WordPress/gutenberg/pull/63451)) -- Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector. ([63818](https://github.com/WordPress/gutenberg/pull/63818)) -- Footnotes: Register format within the init function. ([63554](https://github.com/WordPress/gutenberg/pull/63554)) -- InnerBlocks: Make sure blockType is set before trying to use it. ([63351](https://github.com/WordPress/gutenberg/pull/63351)) -- Prepare JSON schemas for Draft 7 update. ([63582](https://github.com/WordPress/gutenberg/pull/63582)) -- Revert "Pages: Trash view should default to table layout.". ([63481](https://github.com/WordPress/gutenberg/pull/63481)) -- Sync backport changelog action: Use outputs instead of env. ([63792](https://github.com/WordPress/gutenberg/pull/63792)) -- core-data: Fix `canUser` allowed methods handling. ([63615](https://github.com/WordPress/gutenberg/pull/63615)) -- useBlockElement: Return null until ref callback has time to clean up the old element. ([63565](https://github.com/WordPress/gutenberg/pull/63565)) - #### Data Views +- DataViews: Do not render bulk actions Dropdown if no actions are available. ([63575](https://github.com/WordPress/gutenberg/pull/63575)) - DataViews: Fix default layouts in the pages data views. ([63427](https://github.com/WordPress/gutenberg/pull/63427)) - DataViews: Fix featured image height regression. ([63424](https://github.com/WordPress/gutenberg/pull/63424)) - DataViews: Fix field rendering. ([63452](https://github.com/WordPress/gutenberg/pull/63452)) - DataViews: Fix pattens list selection. ([63733](https://github.com/WordPress/gutenberg/pull/63733)) +- DataViews: Fix uncontrolled selection. ([63741](https://github.com/WordPress/gutenberg/pull/63741)) - DataViews: Only show elligible actions in the bulk editing menu. ([63473](https://github.com/WordPress/gutenberg/pull/63473)) - Fix patterns sorting by `title`. ([63710](https://github.com/WordPress/gutenberg/pull/63710)) - Fix selected row styles in table layout. ([63811](https://github.com/WordPress/gutenberg/pull/63811)) - Fix: DataViews: Layout resets for patterns each time a new pattern category is selected. ([63711](https://github.com/WordPress/gutenberg/pull/63711)) - Fix: Inconsistent field spacing in Grid layout. ([63363](https://github.com/WordPress/gutenberg/pull/63363)) - Templates DataViews: Set the right context for the preview field. ([63488](https://github.com/WordPress/gutenberg/pull/63488)) - +- #### Block Editor - Fix user patterns disabling sync filter. ([63828](https://github.com/WordPress/gutenberg/pull/63828)) - ImageURLInputUI: Make onSetLightbox and resetLightbox optional. ([63573](https://github.com/WordPress/gutenberg/pull/63573)) @@ -169,11 +143,14 @@ - Prevent empty void at the bottom of editor when block directory results are present. ([63397](https://github.com/WordPress/gutenberg/pull/63397)) - Remove double shadow on Inserter category panel when zoomed out. ([63516](https://github.com/WordPress/gutenberg/pull/63516)) - Tabs: Vertical Tabs should be 40px min height. ([63446](https://github.com/WordPress/gutenberg/pull/63446)) -- Zoom out mode: Translate toolbar delete button. ([63476](https://github.com/WordPress/gutenberg/pull/63476)) +- Fix mobile styles for inserter pattern and media tab navigation. ([63451](https://github.com/WordPress/gutenberg/pull/63451)) +- useBlockElement: Return null until ref callback has time to clean up the old element. ([63565](https://github.com/WordPress/gutenberg/pull/63565)) +- Remove hint in the Settings tab. ([63515](https://github.com/WordPress/gutenberg/pull/63515)) #### Block Library - Avoid stripping attributes via group block migration when no layout is specified. ([63837](https://github.com/WordPress/gutenberg/pull/63837)) - Fix default unit issue for tag cloud block. ([59122](https://github.com/WordPress/gutenberg/pull/59122)) +- Footnotes: Register format within the init function. ([63554](https://github.com/WordPress/gutenberg/pull/63554)) - Image lightbox: Remove duplicate image when lightbox is opened. ([63381](https://github.com/WordPress/gutenberg/pull/63381)) - Query Loop: Fix 'block' scoped variations to get the `query` defaults. ([63477](https://github.com/WordPress/gutenberg/pull/63477)) - Query Loop: Fix passing of `namespace` when selecting from suggested patterns. ([63402](https://github.com/WordPress/gutenberg/pull/63402)) @@ -181,6 +158,7 @@ - Update Inherited Query Loop value from Template Settings changes. ([63358](https://github.com/WordPress/gutenberg/pull/63358)) #### Site Editor +- Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector. ([63818](https://github.com/WordPress/gutenberg/pull/63818)) - Fix error when duplicating a template part. ([63663](https://github.com/WordPress/gutenberg/pull/63663)) - Fix: Add Template Modal layout in mobile view. ([63627](https://github.com/WordPress/gutenberg/pull/63627)) - Make hover block outlines not present in Distraction Free. ([63819](https://github.com/WordPress/gutenberg/pull/63819)) @@ -192,6 +170,7 @@ - Ensure that we only enter zoom out mode if the experiment is enabled. ([63417](https://github.com/WordPress/gutenberg/pull/63417)) - Fix crash due to absence of selected block. ([63642](https://github.com/WordPress/gutenberg/pull/63642)) - Fix vertical toolbar position. ([63745](https://github.com/WordPress/gutenberg/pull/63745)) +- Translate toolbar delete button. ([63476](https://github.com/WordPress/gutenberg/pull/63476)) #### Components - Button: Never apply `aria-disabled` to anchor. ([63376](https://github.com/WordPress/gutenberg/pull/63376)) @@ -201,6 +180,7 @@ #### Global Styles - Disable "Reset styles" button when there are no changes. ([63562](https://github.com/WordPress/gutenberg/pull/63562)) +- Disallow scrolling the block preview. ([63558](https://github.com/WordPress/gutenberg/pull/63558)) - Ensure root selector (body) is not wrapped in :root :Where(). ([63726](https://github.com/WordPress/gutenberg/pull/63726)) - Global styles block previews: Fix scaling. ([63596](https://github.com/WordPress/gutenberg/pull/63596)) - Style variations: Don't display the default if its the only variation. ([63555](https://github.com/WordPress/gutenberg/pull/63555)) @@ -219,9 +199,11 @@ #### Design Tools - Background image block support: Fix dropzone size. ([63588](https://github.com/WordPress/gutenberg/pull/63588)) +- Background tool: Fix double border. ([63559](https://github.com/WordPress/gutenberg/pull/63559)) -#### Layout -- Don't remount the block when rendering grid tools. ([63557](https://github.com/WordPress/gutenberg/pull/63557)) +#### General interface +- Discussions panel: Distinguish between verb and adjective form of open for internationalization. ([63791](https://github.com/WordPress/gutenberg/pull/63791)) +- Fix canvas issues by removing VisualEditor’s height. ([63724](https://github.com/WordPress/gutenberg/pull/63724)) #### Block Transforms - Block Switcher Preview: Adjust the position and enable pattern list preview in mobile viewport. ([63512](https://github.com/WordPress/gutenberg/pull/63512)) @@ -232,6 +214,9 @@ #### Block Directory - Memoize store selectors. ([63346](https://github.com/WordPress/gutenberg/pull/63346)) +#### Inner blocks +- InnerBlocks: Make sure blockType is set before trying to use it. ([63351](https://github.com/WordPress/gutenberg/pull/63351)) + #### Widgets Editor - Widgets: Memoize 'getWidgets' store selector. ([63338](https://github.com/WordPress/gutenberg/pull/63338)) @@ -244,12 +229,16 @@ #### Media - Lock post saving during image uploads. ([41120](https://github.com/WordPress/gutenberg/pull/41120)) +#### JSON Schemas +- Prepare JSON schemas for Draft 7 update. ([63582](https://github.com/WordPress/gutenberg/pull/63582)) -### Accessibility +#### Security +- Add: Permission checks to avoid 403 errors on non admin roles. ([63296](https://github.com/WordPress/gutenberg/pull/63296)) -- Align checkbox, radio, and toggle input design. ([63490](https://github.com/WordPress/gutenberg/pull/63490)) +### Accessibility #### Components +- Align checkbox, radio, and toggle input design. ([63490](https://github.com/WordPress/gutenberg/pull/63490)) - Fix ComboboxControl reset button when using the keyboard. ([63410](https://github.com/WordPress/gutenberg/pull/63410)) #### Post Editor @@ -267,18 +256,17 @@ ### Experiments -#### Layout +#### Grid layout - Disable in-between inserter in Manual grids. ([63391](https://github.com/WordPress/gutenberg/pull/63391)) - Don't display default appender inside Manual grid. ([63395](https://github.com/WordPress/gutenberg/pull/63395)) - Fix responsive behaviour so both column start and column span are taken into account. ([63464](https://github.com/WordPress/gutenberg/pull/63464)) -- Grid: Better looking block movers. ([63394](https://github.com/WordPress/gutenberg/pull/63394)) -- Grid: Place new block after currently selected block when using slash inserter and splitting text. ([63333](https://github.com/WordPress/gutenberg/pull/63333)) +- Better looking block movers. ([63394](https://github.com/WordPress/gutenberg/pull/63394)) +- Place new block after currently selected block when using slash inserter and splitting text. ([63333](https://github.com/WordPress/gutenberg/pull/63333)) - Move visualizer popover to slot under the canvas. ([63389](https://github.com/WordPress/gutenberg/pull/63389)) +- Don't remount the block when rendering grid tools. ([63557](https://github.com/WordPress/gutenberg/pull/63557)) #### Data Views - Quick Edit: Support bulk selection. ([63841](https://github.com/WordPress/gutenberg/pull/63841)) - -#### Site Editor - DataViews: Bootstrap Quick Edit. ([63600](https://github.com/WordPress/gutenberg/pull/63600)) @@ -314,11 +302,15 @@ - Block editor settings: Add missing global styles links dependencies. ([63823](https://github.com/WordPress/gutenberg/pull/63823)) - Core Data: Remove leftover 'todo' comment. ([63842](https://github.com/WordPress/gutenberg/pull/63842)) - Core Data: Use meta-store actions for resolution status. ([63469](https://github.com/WordPress/gutenberg/pull/63469)) +- core-data: Fix `canUser` allowed methods handling. ([63615](https://github.com/WordPress/gutenberg/pull/63615)) - DataViews: Move PostList component to its own folder. ([63334](https://github.com/WordPress/gutenberg/pull/63334)) - JSON Schema Reorganization and Fixes. ([63591](https://github.com/WordPress/gutenberg/pull/63591)) - Update: Simplify and do not pass renderingMode on editor SidebarContent. ([63814](https://github.com/WordPress/gutenberg/pull/63814)) - Use Base Focus Styles for Region Focus. ([62881](https://github.com/WordPress/gutenberg/pull/62881)) - Use static 'key' when filtering BlockEdit components. ([63590](https://github.com/WordPress/gutenberg/pull/63590)) +- Update: Simplify some permission checks. ([63812](https://github.com/WordPress/gutenberg/pull/63812)) +- Use entity details when calling 'canUser' selectors. ([63415](https://github.com/WordPress/gutenberg/pull/63415)) +- HTML API: Backport updates from Core. ([63723](https://github.com/WordPress/gutenberg/pull/63723)) #### Block Library - Image block: Remove unnecessary variables on expand on click implementation. ([63290](https://github.com/WordPress/gutenberg/pull/63290)) @@ -375,34 +367,25 @@ #### Block Directory - Remove 'edit-post' package dependency. ([63349](https://github.com/WordPress/gutenberg/pull/63349)) - ### Tools -- Bug: Eslint `recommended-with-formatting` allows for unnecessary spaces. ([63549](https://github.com/WordPress/gutenberg/pull/63549)) +#### Project Management - Issue template: Use checkboxes instead of dropdown. ([63523](https://github.com/WordPress/gutenberg/pull/63523)) -- Scripts: Include variations paths in build. ([63098](https://github.com/WordPress/gutenberg/pull/63098)) -- Scripts: Remove now-obsolete `getRenderPropPaths()`. ([63661](https://github.com/WordPress/gutenberg/pull/63661)) +- Sync backport changelog action: Use outputs instead of env. ([63792](https://github.com/WordPress/gutenberg/pull/63792)) +- Run sync when issue is labeled with Sync Backport Changelog. ([63793](https://github.com/WordPress/gutenberg/pull/63793)) #### Testing - Downgrade node 22(.5) unit tests to 22.4. ([63728](https://github.com/WordPress/gutenberg/pull/63728)) - Font Library: Fix flaky end-to-end tests. ([63904](https://github.com/WordPress/gutenberg/pull/63904)) - Upgrade Playwright to v1.45. ([61443](https://github.com/WordPress/gutenberg/pull/61443)) +- Bug: Eslint `recommended-with-formatting` allows for unnecessary spaces. ([63549](https://github.com/WordPress/gutenberg/pull/63549)) -#### Build Tooling +#### Build Tooling & Plugin - Fix broken license check script. ([61868](https://github.com/WordPress/gutenberg/pull/61868)) - React: Restore umd builds. ([63602](https://github.com/WordPress/gutenberg/pull/63602)) - - -### Various - -- HTML API: Backport updates from Core. ([63723](https://github.com/WordPress/gutenberg/pull/63723)) - Upgrade TypeScript to 5.5. ([63012](https://github.com/WordPress/gutenberg/pull/63012)) - -#### Block Editor -- Remove hint in the Settings tab. ([63515](https://github.com/WordPress/gutenberg/pull/63515)) - -#### Block Library -- Social Links: Update Facebook's color to match brand guidelines. ([60424](https://github.com/WordPress/gutenberg/pull/60424)) +- Scripts: Remove now-obsolete `getRenderPropPaths()`. ([63661](https://github.com/WordPress/gutenberg/pull/63661)) +- Scripts: Include variations paths in build. ([63098](https://github.com/WordPress/gutenberg/pull/63098)) ## First-time contributors diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index dfe0f224c8f360..72281a53c3dd18 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -237,7 +237,7 @@ Displays a title with the number of comments. ([Source](https://github.com/WordP - **Category:** theme - **Ancestor:** core/comments - **Supports:** align, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~anchor~~, ~~html~~ -- **Attributes:** level, showCommentsCount, showPostTitle, textAlign +- **Attributes:** level, levelOptions, showCommentsCount, showPostTitle, textAlign ## Cover @@ -410,7 +410,7 @@ Display a list of your most recent posts. ([Source](https://github.com/WordPress ## List -Create a bulleted or numbered list. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list)) +An organized collection of items displayed in a specific order. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list)) - **Name:** core/list - **Category:** text @@ -420,7 +420,7 @@ Create a bulleted or numbered list. ([Source](https://github.com/WordPress/guten ## List item -Create a list item. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list-item)) +An individual item within a list. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list-item)) - **Name:** core/list-item - **Category:** text @@ -689,7 +689,7 @@ Displays the title of a post, page, or any other content-type. ([Source](https:/ - **Name:** core/post-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** isLink, level, linkTarget, rel, textAlign +- **Attributes:** isLink, level, levelOptions, linkTarget, rel, textAlign ## Preformatted @@ -775,7 +775,7 @@ Display the query title. ([Source](https://github.com/WordPress/gutenberg/tree/t - **Name:** core/query-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** level, showPrefix, showSearchTerm, textAlign, type +- **Attributes:** level, levelOptions, showPrefix, showSearchTerm, textAlign, type ## Quote @@ -847,7 +847,7 @@ Describe in a few words what the site is about. The tagline can be used in searc - **Name:** core/site-tagline - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** level, textAlign +- **Attributes:** level, levelOptions, textAlign ## Site Title @@ -856,7 +856,7 @@ Displays the name of this site. Update the block, and the changes apply everywhe - **Name:** core/site-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** isLink, level, linkTarget, textAlign +- **Attributes:** isLink, level, levelOptions, linkTarget, textAlign ## Social Icon @@ -908,7 +908,7 @@ Summarize your post with a list of headings. Add HTML anchors to Heading blocks ## Tag Cloud -A cloud of your most used tags. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/tag-cloud)) +A cloud of popular keywords, each sized by how often it appears. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/tag-cloud)) - **Name:** core/tag-cloud - **Category:** widgets diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index a2153e639db3ba..2231cb0f11538f 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -764,8 +764,18 @@ private static function style_variation_has_scope( $variation, $scope ) { * @return array */ public static function get_style_variations( $scope = 'theme' ) { + return static::get_style_variations_from_directory( get_stylesheet_directory(), $scope ); + } + + /** + * Returns the style variation files defined by the theme (parent and child). + * + * @since 6.7.0 + * + * @return array An array of style variation files. + */ + protected static function get_style_variation_files_from_current_theme() { $variation_files = array(); - $variations = array(); $base_directory = get_stylesheet_directory() . '/styles'; $template_directory = get_template_directory() . '/styles'; if ( is_dir( $base_directory ) ) { @@ -783,6 +793,29 @@ public static function get_style_variations( $scope = 'theme' ) { } $variation_files = array_merge( $variation_files, $variation_files_parent ); } + + return $variation_files; + } + + /** + * Returns the style variations in the given directory. + * + * @since 6.7.0 + * + * @param string $directory The directory to get the style variations from. + * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc. + * @return array + */ + public static function get_style_variations_from_directory( $directory, $scope = 'theme' ) { + $variation_files = array(); + $variations = array(); + if ( is_dir( $directory ) ) { + if ( get_stylesheet_directory() === $directory ) { + $variation_files = static::get_style_variation_files_from_current_theme(); + } else { + $variation_files = static::recursively_iterate_json( $directory ); + } + } ksort( $variation_files ); foreach ( $variation_files as $path => $file ) { $decoded_file = self::read_json_file( $path ); diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 065264fd124e8c..c34984baa0a619 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -43,12 +43,28 @@ function gutenberg_enable_experiments() { /** * Sets a global JS variable used to trigger the availability of form & input blocks. + * + * @deprecated 19.0.0 Use gutenberg_enable_block_experiments(). */ function gutenberg_enable_form_input_blocks() { + _deprecated_function( __FUNCTION__, 'Gutenberg 19.0.0', 'gutenberg_enable_block_experiments' ); +} + +/** + * Sets global JS variables used to enable various block experiments. + */ +function gutenberg_enable_block_experiments() { $gutenberg_experiments = get_option( 'gutenberg-experiments' ); + + // Experimental form blocks. if ( $gutenberg_experiments && array_key_exists( 'gutenberg-form-blocks', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableFormBlocks = true', 'before' ); } + + // General experimental blocks that are not in the default block library. + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-experiments', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableBlockExperiments = true', 'before' ); + } } -add_action( 'admin_init', 'gutenberg_enable_form_input_blocks' ); +add_action( 'admin_init', 'gutenberg_enable_block_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index acb095b47fde30..b27f6fc2726a2a 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -79,6 +79,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-block-experiments', + __( 'Experimental blocks', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable experimental blocks.

(Warning: these blocks may have significant changes during development that cause validation errors and display issues.)

', 'gutenberg' ), + 'id' => 'gutenberg-block-experiments', + ) + ); + add_settings_field( 'gutenberg-form-blocks', __( 'Form and input blocks ', 'gutenberg' ), diff --git a/package-lock.json b/package-lock.json index 6680025d768bef..4e7e660619249b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 412ff34b91d8c1..9234bf92cc9172 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index b26d70b7299f9f..97eb513cf38aeb 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -90,7 +90,7 @@ $sidebar-width: 280px; $content-width: 840px; $wide-content-width: 1100px; $widget-area-width: 700px; - +$secondary-sidebar-width: 350px; /** * Block & Editor UI. diff --git a/packages/block-editor/src/components/grid/grid-item-resizer.js b/packages/block-editor/src/components/grid/grid-item-resizer.js index 28d9678772f76c..da3eb824fe92e5 100644 --- a/packages/block-editor/src/components/grid/grid-item-resizer.js +++ b/packages/block-editor/src/components/grid/grid-item-resizer.js @@ -119,6 +119,15 @@ function GridItemResizerInner( { } } bounds={ bounds } boundsByDirection + onPointerDown={ ( { target, pointerId } ) => { + /* + * Captures the pointer to avoid hiccups while dragging over objects + * like iframes and ensures that the event to end the drag is + * captured by the target (resize handle) whether or not it’s under + * the pointer. + */ + target.setPointerCapture( pointerId ); + } } onResizeStart={ ( event, direction ) => { /* * The container justification and alignment need to be set @@ -126,21 +135,6 @@ function GridItemResizerInner( { * so that it resizes in the right direction. */ setResizeDirection( direction ); - - /* - * The mouseup event on the resize handle doesn't trigger if the mouse - * isn't directly above the handle, so we try to detect if it happens - * outside the grid and dispatch a mouseup event on the handle. - */ - blockElement.ownerDocument.addEventListener( - 'mouseup', - () => { - event.target.dispatchEvent( - new Event( 'mouseup', { bubbles: true } ) - ); - }, - { once: true } - ); } } onResizeStop={ ( event, direction, boxElement ) => { const columnGap = parseFloat( diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index a379f4719556b2..6a02cf1a170c45 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -1,11 +1,13 @@ /** * WordPress dependencies */ +import { usePrevious, useReducedMotion } from '@wordpress/compose'; import { isRTL } from '@wordpress/i18n'; import { __experimentalHStack as HStack, FlexBlock, privateApis as componentsPrivateApis, + __unstableMotion as motion, } from '@wordpress/components'; import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; @@ -22,6 +24,17 @@ function CategoryTabs( { onSelectCategory, children, } ) { + // Copied from InterfaceSkeleton. + const ANIMATION_DURATION = 0.25; + const disableMotion = useReducedMotion(); + const defaultTransition = { + type: 'tween', + duration: disableMotion ? 0 : ANIMATION_DURATION, + ease: [ 0.6, 0, 0.4, 1 ], + }; + + const previousSelectedCategory = usePrevious( selectedCategory ); + return ( - { children } + + { children } + ) ) } diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index c7398aadb56ba5..960ca8b48cdf90 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -1,5 +1,5 @@ $block-inserter-preview-height: 350px; -$block-inserter-width: 350px; +$block-quick-inserter-width: 350px; $block-inserter-tabs-height: 44px; .block-editor-inserter { @@ -24,6 +24,12 @@ $block-inserter-tabs-height: 44px; &.show-as-tabs { gap: 0; } + + .block-editor-tabbed-sidebar { + @include break-medium() { + width: $secondary-sidebar-width; + } + } } .block-editor-inserter__popover.is-quick { @@ -85,6 +91,12 @@ $block-inserter-tabs-height: 44px; height: 100%; position: relative; overflow: visible; + + &.show-panel { + @include break-medium() { + width: $secondary-sidebar-width + $sidebar-width; + } + } } .block-editor-inserter__inline-elements { @@ -299,14 +311,13 @@ $block-inserter-tabs-height: 44px; @include break-medium { border-left: $border-width solid $gray-200; padding: 0; - left: 100%; - width: 300px; + left: $secondary-sidebar-width; + width: $sidebar-width; position: absolute; top: -$border-width; height: calc(100% + #{$border-width}); background: $gray-100; border-top: $border-width solid $gray-200; - box-shadow: $border-width $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. .block-editor-inserter__media-list, .block-editor-block-patterns-list { @@ -366,7 +377,7 @@ $block-inserter-tabs-height: 44px; max-width: 100%; @include break-medium { - width: $block-inserter-width; + width: $block-quick-inserter-width; } } @@ -679,12 +690,6 @@ $block-inserter-tabs-height: 44px; height: 100%; } } - - // Remove doubled-up shadow that occurs when categories panel is opened, only in zoom out. - // Shadow cannot be removed from the source, as it is required when not zoomed out. - .block-editor-inserter__category-panel { - box-shadow: none; - } } .show-icon-labels { diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index e392cf955ed06c..374a012173e230 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -1,13 +1,10 @@ .block-editor-tabbed-sidebar { + background-color: $white; height: 100%; display: flex; flex-direction: column; flex-grow: 1; overflow: hidden; - - @include break-medium() { - width: 350px; - } } .block-editor-tabbed-sidebar__tablist-and-close-button { diff --git a/packages/block-library/src/comments-title/block.json b/packages/block-library/src/comments-title/block.json index f8a02f2e5089b5..b66b741e1916a0 100644 --- a/packages/block-library/src/comments-title/block.json +++ b/packages/block-library/src/comments-title/block.json @@ -23,6 +23,9 @@ "level": { "type": "number", "default": 2 + }, + "levelOptions": { + "type": "array" } }, "supports": { diff --git a/packages/block-library/src/comments-title/edit.js b/packages/block-library/src/comments-title/edit.js index 07149607bfc393..f2a9d23ddf6cae 100644 --- a/packages/block-library/src/comments-title/edit.js +++ b/packages/block-library/src/comments-title/edit.js @@ -23,7 +23,13 @@ import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; export default function Edit( { - attributes: { textAlign, showPostTitle, showCommentsCount, level }, + attributes: { + textAlign, + showPostTitle, + showCommentsCount, + level, + levelOptions, + }, setAttributes, context: { postType, postId }, } ) { @@ -95,6 +101,7 @@ export default function Edit( { /> setAttributes( { level: newLevel } ) } diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index 6110df530bf5e0..32a552c3779cd3 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -6,7 +6,7 @@ "category": "text", "parent": [ "core/list" ], "allowedBlocks": [ "core/list" ], - "description": "Create a list item.", + "description": "An individual item within a list.", "textdomain": "default", "attributes": { "placeholder": { @@ -25,8 +25,8 @@ "color": { "gradients": true, "link": true, + "background": true, "__experimentalDefaultControls": { - "background": true, "text": true } }, diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index 157aaf7c0cf633..8b100071c15ea9 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -5,7 +5,7 @@ "title": "List", "category": "text", "allowedBlocks": [ "core/list-item" ], - "description": "Create a bulleted or numbered list.", + "description": "An organized collection of items displayed in a specific order.", "keywords": [ "bullet list", "ordered list", "numbered list" ], "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/list/ordered-list-settings.js b/packages/block-library/src/list/ordered-list-settings.js index 8c433a465638ff..66817669806233 100644 --- a/packages/block-library/src/list/ordered-list-settings.js +++ b/packages/block-library/src/list/ordered-list-settings.js @@ -13,25 +13,10 @@ import { const OrderedListSettings = ( { setAttributes, reversed, start, type } ) => ( - { - const int = parseInt( value, 10 ); - - setAttributes( { - // It should be possible to unset the value, - // e.g. with an empty string. - start: isNaN( int ) ? undefined : int, - } ); - } } - value={ Number.isInteger( start ) ? start.toString( 10 ) : '' } - step="1" - /> ( value={ type } onChange={ ( newValue ) => setAttributes( { type: newValue } ) } /> + { + const int = parseInt( value, 10 ); + + setAttributes( { + // It should be possible to unset the value, + // e.g. with an empty string. + start: isNaN( int ) ? undefined : int, + } ); + } } + value={ Number.isInteger( start ) ? start.toString( 10 ) : '' } + step="1" + /> { setAttributes( { diff --git a/packages/block-library/src/list/test/edit.native.js b/packages/block-library/src/list/test/edit.native.js index a33bce32e5bca0..2393f2820cfc2e 100644 --- a/packages/block-library/src/list/test/edit.native.js +++ b/packages/block-library/src/list/test/edit.native.js @@ -289,9 +289,7 @@ describe( 'List block', () => { () => screen.getByTestId( 'block-settings-modal' ).props.isVisible ); - const reverseButton = screen.getByLabelText( - /Reverse list numbering\. Off/ - ); + const reverseButton = screen.getByLabelText( /Reverse order\. Off/ ); fireEvent.press( reverseButton ); expect( getEditorHtml() ).toMatchSnapshot(); diff --git a/packages/block-library/src/post-content/block.json b/packages/block-library/src/post-content/block.json index 5ca3892f567a54..1b9de707cb3220 100644 --- a/packages/block-library/src/post-content/block.json +++ b/packages/block-library/src/post-content/block.json @@ -54,5 +54,6 @@ } } }, + "style": "wp-block-post-content", "editorStyle": "wp-block-post-content-editor" } diff --git a/packages/block-library/src/post-content/style.scss b/packages/block-library/src/post-content/style.scss new file mode 100644 index 00000000000000..96e27d04679d44 --- /dev/null +++ b/packages/block-library/src/post-content/style.scss @@ -0,0 +1,5 @@ +.wp-block-post-content::after { + content: ""; + display: table; + clear: both; +} diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index 9c3ba3e214e4b1..ecb5053d6cd39e 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -15,6 +15,9 @@ "type": "number", "default": 2 }, + "levelOptions": { + "type": "array" + }, "isLink": { "type": "boolean", "default": false diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index 3963016e342822..d24455f0956358 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -22,7 +22,7 @@ import { useEntityProp, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; export default function PostTitleEdit( { - attributes: { level, textAlign, isLink, rel, linkTarget }, + attributes: { level, levelOptions, textAlign, isLink, rel, linkTarget }, setAttributes, context: { postType, postId, queryId }, insertBlocksAfter, @@ -125,6 +125,7 @@ export default function PostTitleEdit( { setAttributes( { level: newLevel } ) } diff --git a/packages/block-library/src/query-title/block.json b/packages/block-library/src/query-title/block.json index 674daadee3bb69..2a3c7d9f236995 100644 --- a/packages/block-library/src/query-title/block.json +++ b/packages/block-library/src/query-title/block.json @@ -17,6 +17,9 @@ "type": "number", "default": 1 }, + "levelOptions": { + "type": "array" + }, "showPrefix": { "type": "boolean", "default": true diff --git a/packages/block-library/src/query-title/edit.js b/packages/block-library/src/query-title/edit.js index 71f0e26d706842..845809a9300137 100644 --- a/packages/block-library/src/query-title/edit.js +++ b/packages/block-library/src/query-title/edit.js @@ -25,7 +25,14 @@ import { useArchiveLabel } from './use-archive-label'; const SUPPORTED_TYPES = [ 'archive', 'search' ]; export default function QueryTitleEdit( { - attributes: { type, level, textAlign, showPrefix, showSearchTerm }, + attributes: { + type, + level, + levelOptions, + textAlign, + showPrefix, + showSearchTerm, + }, setAttributes, } ) { const { archiveTypeLabel, archiveNameLabel } = useArchiveLabel(); @@ -130,6 +137,7 @@ export default function QueryTitleEdit( { setAttributes( { level: newLevel } ) } diff --git a/packages/block-library/src/query/edit/inspector-controls/sticky-control.js b/packages/block-library/src/query/edit/inspector-controls/sticky-control.js index 98bec75ad933b6..ee7ee31ba977a9 100644 --- a/packages/block-library/src/query/edit/inspector-controls/sticky-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/sticky-control.js @@ -20,7 +20,7 @@ export default function StickyControl( { value, onChange } ) { value={ value } onChange={ onChange } help={ __( - 'Blog posts can be “stickied”, a feature that places them at the top of the front page of posts, keeping it there until new sticky posts are published.' + 'Sticky posts always appear first, regardless of their publish date.' ) } /> ); diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json index 25b3840cd663a0..d42b7bcd4bed64 100644 --- a/packages/block-library/src/site-tagline/block.json +++ b/packages/block-library/src/site-tagline/block.json @@ -14,6 +14,10 @@ "level": { "type": "number", "default": 0 + }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] } }, "example": { diff --git a/packages/block-library/src/site-tagline/edit.js b/packages/block-library/src/site-tagline/edit.js index 15f8a789dfbe99..52b9c761ba4f54 100644 --- a/packages/block-library/src/site-tagline/edit.js +++ b/packages/block-library/src/site-tagline/edit.js @@ -18,14 +18,12 @@ import { import { __ } from '@wordpress/i18n'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; -const HEADING_LEVELS = [ 0, 1, 2, 3, 4, 5, 6 ]; - export default function SiteTaglineEdit( { attributes, setAttributes, insertBlocksAfter, } ) { - const { textAlign, level } = attributes; + const { textAlign, level, levelOptions } = attributes; const { canUserEdit, tagline } = useSelect( ( select ) => { const { canUser, getEntityRecord, getEditedEntityRecord } = select( coreStore ); @@ -82,8 +80,8 @@ export default function SiteTaglineEdit( { <> setAttributes( { level: newLevel } ) } diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index 95d8deb1e43b9d..c75b1bc229beb9 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -11,6 +11,10 @@ "type": "number", "default": 1 }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] + }, "textAlign": { "type": "string" }, diff --git a/packages/block-library/src/site-title/edit.js b/packages/block-library/src/site-title/edit.js index 76519ac1297b14..82e3c1d7f7bb40 100644 --- a/packages/block-library/src/site-title/edit.js +++ b/packages/block-library/src/site-title/edit.js @@ -21,14 +21,12 @@ import { ToggleControl, PanelBody } from '@wordpress/components'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; import { decodeEntities } from '@wordpress/html-entities'; -const HEADING_LEVELS = [ 0, 1, 2, 3, 4, 5, 6 ]; - export default function SiteTitleEdit( { attributes, setAttributes, insertBlocksAfter, } ) { - const { level, textAlign, isLink, linkTarget } = attributes; + const { level, levelOptions, textAlign, isLink, linkTarget } = attributes; const { canUserEdit, title } = useSelect( ( select ) => { const { canUser, getEntityRecord, getEditedEntityRecord } = select( coreStore ); @@ -97,8 +95,8 @@ export default function SiteTitleEdit( { <> setAttributes( { level: newLevel } ) } diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index db9d033d915db8..8f17cd7a50f55c 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -30,6 +30,7 @@ @import "./paragraph/style.scss"; @import "./post-author/style.scss"; @import "./post-comments-form/style.scss"; +@import "./post-content/style.scss"; @import "./post-date/style.scss"; @import "./post-excerpt/style.scss"; @import "./post-featured-image/style.scss"; diff --git a/packages/block-library/src/tag-cloud/block.json b/packages/block-library/src/tag-cloud/block.json index b95e02204faa29..0c2095bff2a152 100644 --- a/packages/block-library/src/tag-cloud/block.json +++ b/packages/block-library/src/tag-cloud/block.json @@ -4,7 +4,7 @@ "name": "core/tag-cloud", "title": "Tag Cloud", "category": "widgets", - "description": "A cloud of your most used tags.", + "description": "A cloud of popular keywords, each sized by how often it appears.", "textdomain": "default", "attributes": { "numberOfTags": { diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 29f4823a19b425..17ca150bc4d75f 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -12,6 +12,7 @@ import { __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, Disabled, + BaseControl, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -111,6 +112,7 @@ function TagCloudEdit( { attributes, setAttributes } ) { - - setAttributes( { showTagCounts: ! showTagCounts } ) - } - /> + + + + { + onFontSizeChange( + 'smallestFontSize', + value + ); + } } + units={ units } + min={ MIN_FONT_SIZE } + max={ MAX_FONT_SIZE } + size="__unstable-large" + /> + + + { + onFontSizeChange( + 'largestFontSize', + value + ); + } } + units={ units } + min={ MIN_FONT_SIZE } + max={ MAX_FONT_SIZE } + size="__unstable-large" + /> + + + - - - { - onFontSizeChange( 'smallestFontSize', value ); - } } - units={ units } - min={ MIN_FONT_SIZE } - max={ MAX_FONT_SIZE } - /> - - - { - onFontSizeChange( 'largestFontSize', value ); - } } - units={ units } - min={ MIN_FONT_SIZE } - max={ MAX_FONT_SIZE } - /> - - + + setAttributes( { showTagCounts: ! showTagCounts } ) + } + /> ); diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index 0cb6cfc8996ce9..ba3e8f57136d60 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -128,7 +128,7 @@ export default function TemplatePartEdit( { area, onNavigateToEntityRecord, title, - canEditTemplate, + canUserEdit, } = useSelect( ( select ) => { const { getEditedEntityRecord, hasFinishedResolution } = @@ -151,10 +151,13 @@ export default function TemplatePartEdit( { ) : false; - const _canEditTemplate = select( coreStore ).canUser( 'create', { - kind: 'postType', - name: 'wp_template_part', - } ); + const _canUserEdit = hasResolvedEntity + ? select( coreStore ).canUser( 'update', { + kind: 'postType', + name: 'wp_template_part', + id: templatePartId, + } ) + : false; return { hasInnerBlocks: getBlockCount( clientId ) > 0, @@ -167,7 +170,7 @@ export default function TemplatePartEdit( { onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, title: entityRecord?.title, - canEditTemplate: !! _canEditTemplate, + canUserEdit: !! _canUserEdit, }; }, [ templatePartId, attributes.area, clientId ] @@ -237,7 +240,7 @@ export default function TemplatePartEdit( { { isEntityAvailable && onNavigateToEntityRecord && - canEditTemplate && ( + canUserEdit && ( diff --git a/packages/block-library/src/template-part/edit/inner-blocks.js b/packages/block-library/src/template-part/edit/inner-blocks.js index ef7d85948626dd..2c246809ab2d49 100644 --- a/packages/block-library/src/template-part/edit/inner-blocks.js +++ b/packages/block-library/src/template-part/edit/inner-blocks.js @@ -129,15 +129,17 @@ export default function TemplatePartInnerBlocks( { return { canViewTemplatePart: !! select( coreStore ).canUser( 'read', { kind: 'postType', - name: 'wp_template', + name: 'wp_template_part', + id, } ), - canEditTemplatePart: !! select( coreStore ).canUser( 'create', { + canEditTemplatePart: !! select( coreStore ).canUser( 'update', { kind: 'postType', - name: 'wp_template', + name: 'wp_template_part', + id, } ), }; }, - [] + [ id ] ); if ( ! canViewTemplatePart ) { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7de4fcf90b0e95..e6e1dbbf50a1f5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,9 +6,11 @@ - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). +- `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). ### Enhancements +- `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). ### Internal diff --git a/packages/components/src/button/stories/e2e/index.story.tsx b/packages/components/src/button/stories/e2e/index.story.tsx index a4fcfdeac5ca48..d2651e8df1ec18 100644 --- a/packages/components/src/button/stories/e2e/index.story.tsx +++ b/packages/components/src/button/stories/e2e/index.story.tsx @@ -31,28 +31,110 @@ export const VariantStates: StoryFn< typeof Button > = ( 'link', ]; - return ( -
- { variants.map( ( variant ) => ( -
{ + return ( + + -
- ) ) } -
+ { name } + + { variants.map( ( variant ) => ( + + + + + + + ) } diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index b157057062c9d1..0e2e85ba9f72dd 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -1,7 +1,7 @@ .edit-site-editor__editor-interface { opacity: 1; transition: opacity 0.1s ease-out; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); &.is-loading { opacity: 0; @@ -17,3 +17,60 @@ display: flex; justify-content: center; } + +.edit-site-editor__view-mode-toggle { + /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */ + view-transition-name: toggle; + /* stylelint-enable */ + position: fixed; + top: 0; + left: 0; + height: $header-height; + width: $header-height; + z-index: 100; + + .components-button { + color: $white; + height: 100%; + width: 100%; + border-radius: 0; + overflow: hidden; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + &:hover, + &:active { + color: $white; + } + + &:focus { + box-shadow: none; + } + } + + .edit-site-editor__view-mode-toggle-icon { + svg, + img { + background: $gray-900; + display: block; + } + } +} + +.edit-site-editor__back-icon { + position: absolute; + top: 0; + left: 0; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + background-color: hsla(0, 0%, 80%); + pointer-events: none; + + &.has-site-icon { + background-color: hsla(0, 0%, 100%, 0.6); + } +} diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index f6610d0457bbae..6a554b136317dd 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -26,7 +26,7 @@ import { unlock } from '../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); function FontFamilies() { - const { baseCustomFonts, modalTabOpen, setModalTabOpen, setNotice } = + const { baseCustomFonts, modalTabOpen, setModalTabOpen } = useContext( FontLibraryContext ); const [ fontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); const [ baseFontFamilies ] = useGlobalSetting( @@ -112,8 +112,6 @@ function FontFamilies() { variant="secondary" __next40pxDefaultSize onClick={ () => { - // Reset notice when opening the modal. - setNotice( null ); setModalTabOpen( hasInstalledFonts ? 'installed-fonts' diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/context.js b/packages/edit-site/src/components/global-styles/font-library-modal/context.js index e02dcb2e8a0af5..abfb5484e44bf5 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/context.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/context.js @@ -54,7 +54,6 @@ function FontLibraryProvider( { children } ) { const [ isInstalling, setIsInstalling ] = useState( false ); const [ refreshKey, setRefreshKey ] = useState( 0 ); - const [ notice, setNotice ] = useState( null ); const refreshLibrary = () => { setRefreshKey( Date.now() ); @@ -139,8 +138,6 @@ function FontLibraryProvider( { children } ) { }, [ modalTabOpen ] ); const handleSetLibraryFontSelected = ( font ) => { - setNotice( null ); - // If font is null, reset the selected font if ( ! font ) { setLibraryFontSelected( null ); @@ -527,8 +524,6 @@ function FontLibraryProvider( { children } ) { modalTabOpen, setModalTabOpen, refreshLibrary, - notice, - setNotice, saveFontFamilies, isResolvingLibrary, isInstalling, diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index cf6857b30c59e6..6f8a27a8aa8927 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -63,20 +63,15 @@ function FontCollection( { slug } ) { }; const [ selectedFont, setSelectedFont ] = useState( null ); + const [ notice, setNotice ] = useState( false ); const [ fontsToInstall, setFontsToInstall ] = useState( [] ); const [ page, setPage ] = useState( 1 ); const [ filters, setFilters ] = useState( {} ); const [ renderConfirmDialog, setRenderConfirmDialog ] = useState( requiresPermission && ! getGoogleFontsPermissionFromStorage() ); - const { - collections, - getFontCollection, - installFonts, - isInstalling, - notice, - setNotice, - } = useContext( FontLibraryContext ); + const { collections, getFontCollection, installFonts, isInstalling } = + useContext( FontLibraryContext ); const selectedCollection = collections.find( ( collection ) => collection.slug === slug ); @@ -116,8 +111,7 @@ function FontCollection( { slug } ) { useEffect( () => { setSelectedFont( null ); - setNotice( null ); - }, [ slug, setNotice ] ); + }, [ slug ] ); useEffect( () => { // If the selected fonts change, reset the selected fonts to install diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/index.js index 80edc1596f08cd..5af4be90fecdcf 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/index.js @@ -44,7 +44,7 @@ function FontLibraryModal( { onRequestClose, defaultTabId = 'installed-fonts', } ) { - const { collections, setNotice } = useContext( FontLibraryContext ); + const { collections } = useContext( FontLibraryContext ); const canUserCreate = useSelect( ( select ) => { return select( coreStore ).canUser( 'create', { kind: 'postType', @@ -59,11 +59,6 @@ function FontLibraryModal( { tabs.push( ...tabsFromCollections( collections || [] ) ); } - // Reset notice when new tab is selected. - const onSelect = () => { - setNotice( null ); - }; - return (
- + { tabs.map( ( { id, title } ) => ( diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 6602a778dc66c3..7ca2a9218c3bb0 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -53,14 +53,13 @@ function InstalledFonts() { isInstalling, saveFontFamilies, getFontFacesActivated, - notice, - setNotice, } = useContext( FontLibraryContext ); const [ fontFamilies, setFontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); const [ isConfirmDeleteOpen, setIsConfirmDeleteOpen ] = useState( false ); + const [ notice, setNotice ] = useState( false ); const [ baseFontFamilies ] = useGlobalSetting( 'typography.fontFamilies', undefined, @@ -120,6 +119,24 @@ function InstalledFonts() { setIsConfirmDeleteOpen( true ); }; + const handleUpdate = async () => { + setNotice( null ); + try { + await saveFontFamilies( fontFamilies ); + setNotice( { + type: 'success', + message: __( 'Font family updated successfully.' ), + } ); + } catch ( error ) { + setNotice( { + type: 'error', + message: + __( 'There was an error updating the font family. ' ) + + error.message, + } ); + } + }; + const getFontFacesToDisplay = ( font ) => { if ( ! font ) { return []; @@ -265,6 +282,7 @@ function InstalledFonts() { font ) } onClick={ () => { + setNotice( null ); handleSetLibraryFontSelected( font ); @@ -305,6 +323,7 @@ function InstalledFonts() { font ) } onClick={ () => { + setNotice( null ); handleSetLibraryFontSelected( font ); @@ -337,6 +356,7 @@ function InstalledFonts() { size="small" onClick={ () => { handleSetLibraryFontSelected( null ); + setNotice( null ); } } label={ __( 'Back' ) } /> @@ -406,9 +426,7 @@ function InstalledFonts() { ) }
) } diff --git a/packages/editor/src/components/post-url/panel.js b/packages/editor/src/components/post-url/panel.js index be32b40eaf1046..aca36566c04727 100644 --- a/packages/editor/src/components/post-url/panel.js +++ b/packages/editor/src/components/post-url/panel.js @@ -3,7 +3,11 @@ */ import { useMemo, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; -import { Dropdown, Button } from '@wordpress/components'; +import { + Dropdown, + Button, + __experimentalTruncate as Truncate, +} from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { safeDecodeURIComponent } from '@wordpress/url'; import { store as coreStore } from '@wordpress/core-data'; @@ -86,7 +90,9 @@ function PostURLToggle( { isOpen, onClick } ) { aria-label={ sprintf( __( 'Change link: %s' ), decodedSlug ) } onClick={ onClick } > - { isFrontPage ? postLink : <>/{ decodedSlug } } + + { isFrontPage ? postLink : `/${ decodedSlug }` } + ); } diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index 18a61827d573da..fae61eda6b8013 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -1,6 +1,6 @@ .editor-visual-editor { position: relative; - display: block; + display: flex; background-color: $gray-300; // Centralize the editor horizontally (flex-direction is column). diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts index 6679b2d7d1b8f1..04addcb1cde4d2 100644 --- a/packages/editor/src/dataviews/actions/index.ts +++ b/packages/editor/src/dataviews/actions/index.ts @@ -11,6 +11,7 @@ import exportPattern from './export-pattern'; import resetPost from './reset-post'; import trashPost from './trash-post'; import permanentlyDeletePost from './permanently-delete-post'; +import restorePost from './restore-post'; // @ts-ignore import { store as editorStore } from '../../store'; @@ -23,6 +24,7 @@ export default function registerDefaultActions() { registerEntityAction( 'postType', 'wp_block', exportPattern ); registerEntityAction( 'postType', '*', resetPost ); + registerEntityAction( 'postType', '*', restorePost ); registerEntityAction( 'postType', '*', deletePost ); registerEntityAction( 'postType', '*', trashPost ); registerEntityAction( 'postType', '*', permanentlyDeletePost ); diff --git a/packages/editor/src/dataviews/actions/restore-post.tsx b/packages/editor/src/dataviews/actions/restore-post.tsx new file mode 100644 index 00000000000000..874eca91fee113 --- /dev/null +++ b/packages/editor/src/dataviews/actions/restore-post.tsx @@ -0,0 +1,134 @@ +/** + * WordPress dependencies + */ +import { backup } from '@wordpress/icons'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const restorePost: Action< PostWithPermissions > = { + id: 'restore', + label: __( 'Restore' ), + isPrimary: true, + icon: backup, + supportsBulk: true, + isEligible( item ) { + return ( + ! isTemplateOrTemplatePart( item ) && + item.type !== 'wp_block' && + item.status === 'trash' && + item.permissions?.update + ); + }, + async callback( posts, { registry, onActionPerformed } ) { + const { createSuccessNotice, createErrorNotice } = + registry.dispatch( noticesStore ); + const { editEntityRecord, saveEditedEntityRecord } = + registry.dispatch( coreStore ); + await Promise.allSettled( + posts.map( ( post ) => { + return editEntityRecord( 'postType', post.type, post.id, { + status: 'draft', + } ); + } ) + ); + const promiseResult = await Promise.allSettled( + posts.map( ( post ) => { + return saveEditedEntityRecord( 'postType', post.type, post.id, { + throwOnError: true, + } ); + } ) + ); + + if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( posts.length === 1 ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '"%s" has been restored.' ), + getItemTitle( posts[ 0 ] ) + ); + } else if ( posts[ 0 ].type === 'page' ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d pages have been restored.' ), + posts.length + ); + } else { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d posts have been restored.' ), + posts.length + ); + } + createSuccessNotice( successMessage, { + type: 'snackbar', + id: 'restore-post-action', + } ); + if ( onActionPerformed ) { + onActionPerformed( posts ); + } + } else { + // If there was at lease one failure. + let errorMessage; + // If we were trying to move a single post to the trash. + if ( promiseResult.length === 1 ) { + const typedError = promiseResult[ 0 ] as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessage = typedError.reason.message; + } else { + errorMessage = __( + 'An error occurred while restoring the post.' + ); + } + // If we were trying to move multiple posts to the trash + } else { + const errorMessages = new Set(); + const failedPromises = promiseResult.filter( + ( { status } ) => status === 'rejected' + ); + for ( const failedPromise of failedPromises ) { + const typedError = failedPromise as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( typedError.reason.message ); + } + } + if ( errorMessages.size === 0 ) { + errorMessage = __( + 'An error occurred while restoring the posts.' + ); + } else if ( errorMessages.size === 1 ) { + errorMessage = sprintf( + /* translators: %s: an error message */ + __( 'An error occurred while restoring the posts: %s' ), + [ ...errorMessages ][ 0 ] + ); + } else { + errorMessage = sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while restoring the posts: %s' + ), + [ ...errorMessages ].join( ',' ) + ); + } + } + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + }, +}; + +export default restorePost; diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index ed4672bc435cdc..6a6c8702a02217 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -110,7 +110,10 @@ export const getPostIcon = createRegistrySelector( // `icon` is the `menu_icon` property of a post type. We // only handle `dashicons` for now, even if the `menu_icon` // also supports urls and svg as values. - if ( postTypeEntity?.icon?.startsWith( 'dashicons-' ) ) { + if ( + typeof postTypeEntity?.icon === 'string' && + postTypeEntity.icon.startsWith( 'dashicons-' ) + ) { return postTypeEntity.icon.slice( 10 ); } return pageIcon; diff --git a/packages/format-library/src/image/index.js b/packages/format-library/src/image/index.js index 794af776c88e76..7f8e33550770d0 100644 --- a/packages/format-library/src/image/index.js +++ b/packages/format-library/src/image/index.js @@ -6,8 +6,11 @@ import { SVG, Popover, Button, - __experimentalNumberControl as NumberControl, + ExternalLink, __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalNumberControl as NumberControl, + TextareaControl, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; @@ -17,7 +20,6 @@ import { RichTextToolbarButton, MediaUploadCheck, } from '@wordpress/block-editor'; -import { keyboardReturn } from '@wordpress/icons'; const ALLOWED_MEDIA_TYPES = [ 'image' ]; @@ -41,8 +43,11 @@ export const image = { }; function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { - const { style } = activeObjectAttributes; - const [ width, setWidth ] = useState( style?.replace( /\D/g, '' ) ); + const { style, alt } = activeObjectAttributes; + const width = style?.replace( /\D/g, '' ); + const [ editedWidth, setEditedWidth ] = useState( width ); + const [ editedAlt, setEditedAlt ] = useState( alt ); + const hasChanged = editedWidth !== width || editedAlt !== alt; const popoverAnchor = useAnchor( { editableContentElement: contentRef.current, settings: image, @@ -64,7 +69,8 @@ function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { type: name, attributes: { ...activeObjectAttributes, - style: width ? `width: ${ width }px;` : '', + style: width ? `width: ${ editedWidth }px;` : '', + alt: editedAlt, }, }; @@ -76,21 +82,54 @@ function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { event.preventDefault(); } } > - + setWidth( newWidth ) } - size="__unstable-large" + onChange={ ( newWidth ) => { + setEditedWidth( newWidth ); + } } /> - + + ); diff --git a/packages/format-library/src/image/style.scss b/packages/format-library/src/image/style.scss index 7e9809e52f3bf2..1e0b922fdf4c8f 100644 --- a/packages/format-library/src/image/style.scss +++ b/packages/format-library/src/image/style.scss @@ -2,7 +2,7 @@ z-index: z-index(".block-editor-format-toolbar__image-popover"); .block-editor-format-toolbar__image-container-content { - width: 200px; + width: 260px; padding: $grid-unit-20; } } diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js index ed4d98cdf7637f..14b2a87ba5203d 100644 --- a/packages/interface/src/components/interface-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -182,30 +182,32 @@ function InterfaceSkeleton( ariaLabel={ mergedLabels.secondarySidebar } as={ motion.div } initial="closed" - animate={ - isMobileViewport ? 'mobileOpen' : 'open' - } + animate="open" exit="closed" variants={ { open: { width: secondarySidebarSize.width }, closed: { width: 0 }, - mobileOpen: { width: '100vw' }, } } transition={ defaultTransition } > -
{ secondarySidebarResizeListener } { secondarySidebar } -
+ ) } diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 295d02978f120f..55319a752b61e6 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -95,6 +95,7 @@ function fail_if_died( $message ) { 'gutenberg-widget-experiments' => '1', 'gutenberg-full-site-editing' => 1, 'gutenberg-form-blocks' => 1, + 'gutenberg-block-experiments' => 1, ), ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 36b8218785f216..8d2f470efe60fe 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -46,6 +46,52 @@ public static function set_up_before_class() { static::$user_id = self::factory()->user->create(); } + /** + * Pretty print CSS in test assertions so that it provides a better diff when a test fails. + * Without this: the failing test outputs the entire css string as being different. + * With this: the failing test only highlights the specific CSS rule that is different. + * + * @param string $css A string of raw css with no line breaks. + * @return string The css with line breaks. + */ + private static function pretty_print_css( $css ) { + $css = str_replace( '{', " {\n", $css ); + $css = str_replace( '}', "}\n\n", $css ); + $css = str_replace( ';', ";\n", $css ); + return $css; + } + + /** + * Asserts that two CSS strings are equivalent, but outputs + * pretty printed test failures along with the raw css. + * + * - The pretty printed assertions are useful for understanding what actually changed. + * - The raw css is included as it's useful for updating the test case's expected CSS. + * + * Inspired by: + * https://stackoverflow.com/questions/6832263/phpunit-assertion-failed-but-i-want-to-continue-testing + * + * @param string $expected The expected CSS. + * @param string $actual The actual CSS. + */ + private function assertSameCSS( $expected, $actual, $message = '' ) { + $pretty_expected = self::pretty_print_css( $expected ); + $pretty_actual = self::pretty_print_css( $actual ); + + try { + $this->assertSame( $pretty_expected, $pretty_actual, $message ); + } catch ( PHPUnit_Framework_ExpectationFailedException $e ) { + // Test failures are thrown as exceptions by PHPUnit. + // Catch the exception and re-throw it, but with the + // raw css appended. + $raw_actual_output = + "\n\nIf the change is expected, update the test case to this CSS:\n$actual"; + throw new PHPUnit_Framework_ExpectationFailedException( + "$e$raw_actual_output" + ); + } + } + public function test_get_settings() { $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -556,10 +602,10 @@ public function test_get_stylesheet() { $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-big-font-size{font-size: var(--wp--preset--font-size--big) !important;}.has-arial-font-family{font-family: var(--wp--preset--font-family--arial) !important;}'; $all = $variables . $styles . $presets; - $this->assertSame( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); - $this->assertSame( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( $all, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); + $this->assertSameCSS( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); + $this->assertSameCSS( $all, $theme_json->get_stylesheet() ); } public function test_get_styles_for_block_support_for_shorthand_and_longhand_values() { @@ -618,8 +664,8 @@ public function test_get_styles_for_block_support_for_shorthand_and_longhand_val $group_styles = ':root :where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}'; $image_styles = ':root :where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; - $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ) ); - $this->assertSame( $image_styles, $theme_json->get_styles_for_block( $image_node ) ); + $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ) ); + $this->assertSameCSS( $image_styles, $theme_json->get_styles_for_block( $image_node ) ); } public function test_get_stylesheet_skips_disabled_protected_properties() { @@ -647,8 +693,8 @@ public function test_get_stylesheet_skips_disabled_protected_properties() { ); $expected = static::$base_styles . ':where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } public function test_get_stylesheet_renders_enabled_protected_properties() { @@ -669,8 +715,8 @@ public function test_get_stylesheet_renders_enabled_protected_properties() { ); $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } public function test_get_stylesheet_preset_classes_work_with_compounded_selectors() { @@ -694,7 +740,7 @@ public function test_get_stylesheet_preset_classes_work_with_compounded_selector ) ); - $this->assertSame( + $this->assertSameCSS( '.wp-block-heading.has-white-color{color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}', $theme_json->get_stylesheet( array( 'presets' ) ) ); @@ -736,10 +782,10 @@ public function test_get_stylesheet_preset_rules_come_after_block_rules() { $all = $variables . $styles . $presets; - $this->assertSame( $all, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); - $this->assertSame( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); + $this->assertSameCSS( $all, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $styles, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); + $this->assertSameCSS( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); } public function test_get_stylesheet_generates_proper_classes_and_css_vars_from_slugs() { @@ -774,11 +820,11 @@ public function test_get_stylesheet_generates_proper_classes_and_css_vars_from_s ) ); - $this->assertSame( + $this->assertSameCSS( '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-dark-grey-color{color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-color{color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-color{color: var(--wp--preset--color--white-2-black) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-background-color{background-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-background-color{background-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-background-color{background-color: var(--wp--preset--color--white-2-black) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-border-color{border-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-border-color{border-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-border-color{border-color: var(--wp--preset--color--white-2-black) !important;}', $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( + $this->assertSameCSS( ':root{--wp--preset--color--grey: grey;--wp--preset--color--dark-grey: grey;--wp--preset--color--light-grey: grey;--wp--preset--color--white-2-black: grey;--wp--custom--white-2-black: value;}', $theme_json->get_stylesheet( array( 'variables' ) ) ); @@ -834,9 +880,9 @@ public function test_get_styles_for_block_handles_whitelisted_element_pseudo_sel $hover_style = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}'; $focus_style = ':root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - $this->assertSame( $link_style, $theme_json->get_styles_for_block( $link_node ) ); - $this->assertSame( $hover_style, $theme_json->get_styles_for_block( $hover_node ) ); - $this->assertSame( $focus_style, $theme_json->get_styles_for_block( $focus_node ) ); + $this->assertSameCSS( $link_style, $theme_json->get_styles_for_block( $link_node ) ); + $this->assertSameCSS( $hover_style, $theme_json->get_styles_for_block( $hover_node ) ); + $this->assertSameCSS( $focus_style, $theme_json->get_styles_for_block( $focus_node ) ); } /** @@ -872,8 +918,7 @@ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given ); $expected = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() { @@ -906,8 +951,7 @@ public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_ ); $expected = 'h4{background-color: red;color: green;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { @@ -940,8 +984,7 @@ public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { ); $expected = 'a:where(:not(.wp-element-button)){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); $this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -987,8 +1030,7 @@ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elemen ); $expected = ':root :where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -1032,8 +1074,7 @@ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { $block_styles = ':root :where(.wp-block-calendar){font-size: 3em;}:root :where(.wp-block-calendar table, .wp-block-calendar th){color: green;}'; $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; $expected = $base_styles . $block_styles . $preset_styles; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -1063,8 +1104,7 @@ public function test_get_stylesheet_with_block_json_selectors() { ); $expected = ':root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-radius: 374px;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_generates_layout_styles() { @@ -1090,7 +1130,7 @@ public function test_get_stylesheet_generates_layout_styles() { ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); @@ -1119,7 +1159,7 @@ public function test_get_stylesheet_generates_layout_styles_with_spacing_presets ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-flex {gap: var(--wp--preset--spacing--60);}.is-layout-grid {gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); @@ -1149,7 +1189,7 @@ public function test_get_stylesheet_generates_fallback_gap_layout_styles() { $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $stylesheet ); @@ -1170,7 +1210,7 @@ public function test_get_stylesheet_generates_base_fallback_gap_layout_styles() $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) ); // Note the `base-layout-styles` includes a fallback gap for the Columns block for backwards compatibility. - $this->assertSame( + $this->assertSameCSS( ':where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}', $stylesheet ); @@ -1193,7 +1233,7 @@ public function test_get_stylesheet_skips_layout_styles() { remove_theme_support( 'disable-layout-styles' ); // All Layout styles should be skipped. - $this->assertSame( + $this->assertSameCSS( '', $stylesheet ); @@ -1243,7 +1283,7 @@ public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_n 'default' ); - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-flex {gap: 1rem;}.is-layout-grid {gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}' . ':root :where(.wp-block-post-content){color: gray;}.wp-block-social-links-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-flex {gap: 0;}.wp-block-social-links-is-layout-grid {gap: 0;}.wp-block-buttons-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-flex {gap: 0;}.wp-block-buttons-is-layout-grid {gap: 0;}', $theme_json->get_stylesheet() @@ -1279,7 +1319,7 @@ public function test_get_stylesheet_returns_outline_styles() { $expected = ':root :where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_custom_root_selector() { @@ -1302,7 +1342,7 @@ public function test_get_stylesheet_custom_root_selector() { ); $actual = $theme_json->get_stylesheet( array( 'styles' ), null, $options ); - $this->assertSame( + $this->assertSameCSS( ':root :where(.custom){color: teal;}', $actual ); @@ -1360,7 +1400,7 @@ public function test_get_stylesheet_generates_fluid_typography_values() { unregister_block_type( 'test/clamp-me' ); - $this->assertSame( + $this->assertSameCSS( ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}body{font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}h1{font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', $theme_json->get_stylesheet( array( 'styles', 'variables', 'presets' ), null, array( 'skip_root_layout_styles' => true ) ) ); @@ -3419,7 +3459,7 @@ public function test_get_property_value_valid() { ); $expected = 'body{background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3496,7 +3536,7 @@ public function test_get_property_value_loop() { ); $expected = 'body{background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3528,7 +3568,7 @@ public function test_get_property_value_recursion() { ); $expected = 'body{background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3551,7 +3591,7 @@ public function test_get_property_value_self() { ); $expected = 'body{background-color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_styles_for_block_with_padding_aware_alignments() { @@ -3582,7 +3622,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); + $this->assertSameCSS( $expected, $root_rules . $style_rules ); } public function test_get_styles_for_block_without_padding_aware_alignments() { @@ -3610,7 +3650,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { $expected = static::$base_styles . 'body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); + $this->assertSameCSS( $expected, $root_rules . $style_rules ); } public function test_get_styles_with_content_width() { @@ -3632,7 +3672,7 @@ public function test_get_styles_with_content_width() { ); $expected = ':root { --wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ) ); + $this->assertSameCSS( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_get_styles_with_appearance_tools() { @@ -3651,7 +3691,7 @@ public function test_get_styles_with_appearance_tools() { ); $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); + $this->assertSameCSS( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_sanitization() { @@ -4717,8 +4757,8 @@ public function test_shadow_preset_styles() { ); $expected_styles = ':root{--wp--preset--shadow--natural: 5px 5px 5px 0 black;--wp--preset--shadow--sharp: 5px 5px black;}'; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" does not match expectations' ); - $this->assertSame( $expected_styles, $theme_json->get_stylesheet( array( 'variables' ) ), 'Styles returned from "::get_stylesheet()" when requiring "variables" type does not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" does not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet( array( 'variables' ) ), 'Styles returned from "::get_stylesheet()" when requiring "variables" type does not match expectations' ); } public function test_get_shadow_styles_for_blocks() { @@ -4756,7 +4796,7 @@ public function test_get_shadow_styles_for_blocks() { $variable_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}'; $element_styles = 'a:where(:not(.wp-element-button)){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(p){box-shadow: var(--wp--preset--shadow--natural);}'; $expected_styles = $variable_styles . $element_styles; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_top_level_background_image_styles() { @@ -4783,7 +4823,7 @@ public function test_get_top_level_background_image_styles() { ); $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; - $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -4801,7 +4841,7 @@ public function test_get_top_level_background_image_styles() { ); $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; - $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); } public function test_get_block_background_image_styles() { @@ -4844,7 +4884,7 @@ public function test_get_block_background_image_styles() { ); $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}"; - $this->assertSame( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' ); + $this->assertSameCSS( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' ); $group_node = array( 'name' => 'core/group', @@ -4856,7 +4896,7 @@ public function test_get_block_background_image_styles() { ); $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;background-attachment: fixed;}"; - $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); + $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); } /** diff --git a/readme.txt b/readme.txt index 3fe6e3aaf1dc4d..c5ef1231b183ee 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === Gutenberg === Contributors: matveb, joen, karmatosed -Tested up to: 6.5 +Tested up to: 6.6 Stable tag: V.V.V License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html diff --git a/test/e2e/specs/editor/various/adding-inline-tokens.spec.js b/test/e2e/specs/editor/various/adding-inline-tokens.spec.js index 15f9d9ea877320..c7826ebf262822 100644 --- a/test/e2e/specs/editor/various/adding-inline-tokens.spec.js +++ b/test/e2e/specs/editor/various/adding-inline-tokens.spec.js @@ -64,13 +64,16 @@ test.describe( 'adding inline tokens', () => { await pageUtils.pressKeys( 'shift+ArrowLeft' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); - await page.fill( 'role=spinbutton[name="WIDTH"i]', '20' ); + await expect( + page.locator( 'role=spinbutton[name="Width"i]' ) + ).toBeFocused(); + await page.fill( 'role=spinbutton[name="Width"i]', '20' ); + await page.fill( 'role=textbox[name="Alternative text"i]', 'Alt' ); await page.click( 'role=button[name="Apply"i]' ); // Check the content. const contentRegex2 = new RegExp( - `a ` + `a Alt` ); await expect.poll( editor.getBlocks ).toMatchObject( [ diff --git a/test/integration/fixtures/blocks/core__site-tagline.json b/test/integration/fixtures/blocks/core__site-tagline.json index e504bc75df30c7..fe837d41df43bf 100644 --- a/test/integration/fixtures/blocks/core__site-tagline.json +++ b/test/integration/fixtures/blocks/core__site-tagline.json @@ -3,7 +3,8 @@ "name": "core/site-tagline", "isValid": true, "attributes": { - "level": 0 + "level": 0, + "levelOptions": [ 0, 1, 2, 3, 4, 5, 6 ] }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__site-title.json b/test/integration/fixtures/blocks/core__site-title.json index 12f32615473cc8..8ca7091f30d5e7 100644 --- a/test/integration/fixtures/blocks/core__site-title.json +++ b/test/integration/fixtures/blocks/core__site-title.json @@ -4,6 +4,7 @@ "isValid": true, "attributes": { "level": 1, + "levelOptions": [ 0, 1, 2, 3, 4, 5, 6 ], "isLink": true, "linkTarget": "_self" },