diff --git a/.github/setup-node/action.yml b/.github/setup-node/action.yml index 22cb81618a1efb..fccce2e4e93bcf 100644 --- a/.github/setup-node/action.yml +++ b/.github/setup-node/action.yml @@ -14,6 +14,7 @@ runs: with: node-version-file: '.nvmrc' node-version: ${{ inputs.node-version }} + check-latest: true cache: npm - name: Get Node.js and npm version diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 8f649f1e15889d..a2628bf7af6160 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -174,6 +174,7 @@ jobs: uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version-file: '.nvmrc' + check-latest: true cache: npm - name: Build Gutenberg plugin ZIP file @@ -336,6 +337,7 @@ jobs: with: node-version-file: 'main/.nvmrc' registry-url: 'https://registry.npmjs.org' + check-latest: true - name: Publish packages to npm ("latest" dist-tag) run: | diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 3b4d51bddbda0b..23b245cb6f114b 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -46,6 +46,7 @@ jobs: uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version-file: '.nvmrc' + check-latest: true cache: npm - uses: preactjs/compressed-size-action@8119d3d31b6e57b167e09c81dfa877eada3bcb35 # v2.5.0 diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 0e4325b53f69da..d817ac1e0be976 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -14,14 +14,14 @@ concurrency: jobs: checks: - name: Checks + name: Checks w/Node.js ${{ matrix.node }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: ['16'] - os: [macos-latest, ubuntu-latest, windows-latest] + node: ['20', '21'] + os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index ddbf714cb50232..d065bf8afad44d 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -20,8 +20,6 @@ jobs: name: Puppeteer runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} - strategy: - fail-fast: false steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 18bdb63a6c3770..163012451d6002 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -71,6 +71,7 @@ jobs: with: node-version-file: 'cli/.nvmrc' registry-url: 'https://registry.npmjs.org' + check-latest: true - name: Setup Node.js (for WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} @@ -78,6 +79,7 @@ jobs: with: node-version-file: 'publish/.nvmrc' registry-url: 'https://registry.npmjs.org' + check-latest: true - name: Publish development packages to npm ("next" dist-tag) if: ${{ github.event.inputs.release_type == 'development' }} diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index b8154e335776a2..785b42a19054db 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -8,9 +8,6 @@ jobs: pull-request-automation: runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' }} - strategy: - matrix: - node: ['16'] steps: # Checkout defaults to using the branch which triggered the event, which @@ -23,7 +20,8 @@ jobs: - name: Use desired version of Node.js uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: - node-version: ${{ matrix.node }} + node-version-file: '.nvmrc' + check-latest: true - name: Cache NPM packages uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index ff8c27b14e39e8..2465f357a97cf0 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -30,6 +30,7 @@ jobs: uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version-file: '.nvmrc' + check-latest: true cache: npm - name: Npm install diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 78f70cc4ed9f74..b6d5465ab43a6c 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -21,14 +21,13 @@ concurrency: jobs: unit-js: - name: JavaScript + name: JavaScript (Node.js ${{ matrix.node }}) runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} - strategy: fail-fast: false matrix: - node: ['16'] + node: ['20', '21'] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -40,7 +39,7 @@ jobs: with: node-version: ${{ matrix.node }} - - name: Npm build + - name: npm build # It's not necessary to run the full build, since Jest can interpret # source files with `babel-jest`. Some packages have their own custom # build tasks, however. These must be run. diff --git a/.nvmrc b/.nvmrc index b6a7d89c68e0ca..209e3ef4b6247c 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16 +20 diff --git a/changelog.txt b/changelog.txt index c8aa6254923aab..0b70b68c9377ee 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,342 @@ == Changelog == += 17.3.0 = + + + +## Changelog + +### Bug Fixes + +- (edit-site)(use-init-edited-entity-from-url) Safely access `toString()` on `siteData`'s `page_on_front`. ([57035](https://github.com/WordPress/gutenberg/pull/57035)) + +#### Components +- Fix form token field suggestion list reopening after blurring the input. ([57002](https://github.com/WordPress/gutenberg/pull/57002)) + + + + +## Contributors + +The following contributors merged PRs in this release: + +@fullofcaffeine @talldan + += 17.3.0-rc.1 = + + +## Changelog + +### Enhancements + +- Components: Replace `TabPanel` with `Tabs` in the editor's `ColorPanel`. ([56878](https://github.com/WordPress/gutenberg/pull/56878)) +- Editor: Move the edit template blocks notification to editor package. ([56901](https://github.com/WordPress/gutenberg/pull/56901)) +- Editor: Unify the preview dropdown between post and site editors. ([56921](https://github.com/WordPress/gutenberg/pull/56921)) +- Editor: Use the same PostTemplatePanel between post and site editors. ([56817](https://github.com/WordPress/gutenberg/pull/56817)) +- Tabs: Replace `id` with new `tabId` prop. ([56883](https://github.com/WordPress/gutenberg/pull/56883)) +- Update main toolbar buttons to all be compact. ([56635](https://github.com/WordPress/gutenberg/pull/56635), [56729](https://github.com/WordPress/gutenberg/pull/56729)) +- Update preferences organization. ([56481](https://github.com/WordPress/gutenberg/pull/56481)) + +#### Components +- FocalPointPicker with __next40pxDefaultSize. ([56021](https://github.com/WordPress/gutenberg/pull/56021)) +- Font Library: Improve usability of font variant selection. ([56158](https://github.com/WordPress/gutenberg/pull/56158)) +- Tabs: Sync browser focus to selected tab in controlled mode. ([56658](https://github.com/WordPress/gutenberg/pull/56658)) +- Use consistent styling for duotone panels. ([56801](https://github.com/WordPress/gutenberg/pull/56801)) +- `BorderControl`: Fix button styles. ([56730](https://github.com/WordPress/gutenberg/pull/56730)) +- `DimensionControl`: Add __next40pxDefaultSize prop. ([56805](https://github.com/WordPress/gutenberg/pull/56805)) +- `FontSizePicker`: Add opt-in prop for 40px default size. ([56804](https://github.com/WordPress/gutenberg/pull/56804)) +- `QueryControls`: Add opt-in prop for 40px default size. ([56576](https://github.com/WordPress/gutenberg/pull/56576)) + +#### Block Library +- Control dimensions (margin and padding) of the list-item block. ([55874](https://github.com/WordPress/gutenberg/pull/55874)) +- Consistent default typography controls across blocks. ([55208](https://github.com/WordPress/gutenberg/pull/55208)) +- Social Icons: Add Gravatar service. ([56544](https://github.com/WordPress/gutenberg/pull/56544)) +- Tweak table block placeholder with __next40pxDefaultSize props. ([56935](https://github.com/WordPress/gutenberg/pull/56935)) + +#### Site Editor +- Merge the post only mode and the post editor. ([56671](https://github.com/WordPress/gutenberg/pull/56671)) +- Site Editor Sidebar: Add "Areas" details panel to all templates and update icon. ([55677](https://github.com/WordPress/gutenberg/pull/55677)) + +#### Block Editor +- Allow dragging between adjacent container blocks based on a threshold. ([56466](https://github.com/WordPress/gutenberg/pull/56466)) +- Components: Replace `TabPanel` with `Tabs` in the editor's `ColorGradientControl`. ([56351](https://github.com/WordPress/gutenberg/pull/56351)) + +#### Data Views +- Update data view layout. ([56786](https://github.com/WordPress/gutenberg/pull/56786)) + +#### Layout +- Match the front end layout classname in the editor. ([56774](https://github.com/WordPress/gutenberg/pull/56774)) + +#### Global Styles +- Global style revisions: Show change summary on selected item. ([56577](https://github.com/WordPress/gutenberg/pull/56577)) + +#### Icons +- Another round of HiDPI icon tweaks. ([56532](https://github.com/WordPress/gutenberg/pull/56532)) + +#### Media +- Update external images panel in post publish sidebar. ([55524](https://github.com/WordPress/gutenberg/pull/55524)) + +#### Post Editor +- Implement `Tabs` in editor settings. ([55360](https://github.com/WordPress/gutenberg/pull/55360)) + + +### Bug Fixes + +- Create-block-interactive-template: Add all files to the generated plugin zip. ([56943](https://github.com/WordPress/gutenberg/pull/56943)) +- Create-block-interactive-template: Prevent crash when Gutenberg plugin is not installed. ([56941](https://github.com/WordPress/gutenberg/pull/56941)) +- Fix end-to-end test: Update how we find the template title to match markup changes. ([56992](https://github.com/WordPress/gutenberg/pull/56992)) +- Fix: Fatal php error if a template was created by an author that was deleted. ([56990](https://github.com/WordPress/gutenberg/pull/56990)) +- Fix: PHP 8.1 deprecated warning strpos(). ([56171](https://github.com/WordPress/gutenberg/pull/56171)) +- Fix: Use span on template list titles. ([56955](https://github.com/WordPress/gutenberg/pull/56955)) +- Font Library: Add font family and font face preview keys to schema. ([56793](https://github.com/WordPress/gutenberg/pull/56793)) +- Remove unnecessary CSS for shrinking central header area. ([56220](https://github.com/WordPress/gutenberg/pull/56220)) +- Revert format types hook refactor. ([56859](https://github.com/WordPress/gutenberg/pull/56859)) +- Show template center UI when no block is selected. ([56217](https://github.com/WordPress/gutenberg/pull/56217)) +- setImmutably: Don't clone all objects. ([56612](https://github.com/WordPress/gutenberg/pull/56612)) + +#### Block Library +- Fix error when using a navigation block that returns an empty fallback result. ([56629](https://github.com/WordPress/gutenberg/pull/56629)) +- Fixture Tests: Correctly generate fixture files for form-related blocks. ([56719](https://github.com/WordPress/gutenberg/pull/56719)) +- Image: Fix resetting behaviour for alt image text. ([56809](https://github.com/WordPress/gutenberg/pull/56809)) +- Social Links Block: Prevent Theme Styles Distorting Size. ([56301](https://github.com/WordPress/gutenberg/pull/56301)) +- Update image block save to only save align none class. ([56449](https://github.com/WordPress/gutenberg/pull/56449)) + +#### Components +- DropdownMenuV2Ariakit: Prevent prefix collapsing if all radios or checkboxes are unselected. ([56720](https://github.com/WordPress/gutenberg/pull/56720)) +- FormToggle: Do not use "/" math operator. ([56672](https://github.com/WordPress/gutenberg/pull/56672)) +- PaletteEdit: Temporary custom gradient not saving. ([56896](https://github.com/WordPress/gutenberg/pull/56896)) +- `ToggleGroupControl`: React correctly to external controlled updates. ([56678](https://github.com/WordPress/gutenberg/pull/56678)) + +#### Block Editor +- Apply __next40pxDefaultSize to TextControl and Button component in renaming UIs. ([56933](https://github.com/WordPress/gutenberg/pull/56933)) +- Pattern inserter: Fix Broken preview layout. ([56814](https://github.com/WordPress/gutenberg/pull/56814)) +- Patterns: Keep synced pattern when added via drag and drop. ([56924](https://github.com/WordPress/gutenberg/pull/56924)) + +#### Design Tools +- Background image support: Fix duplicate output of styling rules. ([56997](https://github.com/WordPress/gutenberg/pull/56997)) +- Fix sticky position in classic themes with appearance tools support. ([56743](https://github.com/WordPress/gutenberg/pull/56743)) + +#### Post Editor +- Editor Canvas: Fix animation when device type changes. ([56970](https://github.com/WordPress/gutenberg/pull/56970)) +- Editor: Fix display of edit template blocks notification. ([56978](https://github.com/WordPress/gutenberg/pull/56978)) + +#### Site Editor +- Fix active edited post. ([56863](https://github.com/WordPress/gutenberg/pull/56863)) +- Show back button when editing navigation and template area in-place with no URL params. ([56741](https://github.com/WordPress/gutenberg/pull/56741)) + +#### Typography +- Fix order of typography sizes and families. ([56659](https://github.com/WordPress/gutenberg/pull/56659)) +- Font Library: Fix font uninstallation. ([56762](https://github.com/WordPress/gutenberg/pull/56762)) + +#### Navigation in Site View +- Navigation editor: Fix content mode. ([56856](https://github.com/WordPress/gutenberg/pull/56856)) + +#### Patterns +- Fix top position and height of Pattern Modal Sidebar. ([56787](https://github.com/WordPress/gutenberg/pull/56787)) + +#### Interactivity API +- Start using modules in the interactive create-block template. ([56694](https://github.com/WordPress/gutenberg/pull/56694)) + +#### Layout +- Fix input not showing when switching to "Fixed" width. ([56660](https://github.com/WordPress/gutenberg/pull/56660)) + +#### Data Views +- Align data view icon usage. ([56602](https://github.com/WordPress/gutenberg/pull/56602)) + +#### Block Styles +- Consolidate and resolve display issues between InserterPreviewPanel and BlockStylesPreviewPanel. ([56011](https://github.com/WordPress/gutenberg/pull/56011)) + +#### Inspector Controls +- Decode some characters if used in taxonomy name so it's displayed correctly in Query Loop filters. ([50376](https://github.com/WordPress/gutenberg/pull/50376)) + + +### Accessibility + +#### Data Views +- Add scroll padding to dataviews container. ([56946](https://github.com/WordPress/gutenberg/pull/56946)) +- Adding `aria-sort` to table view headers. ([56860](https://github.com/WordPress/gutenberg/pull/56860)) +- Fix: Use span instead of heading for the template titles. ([56785](https://github.com/WordPress/gutenberg/pull/56785)) + +#### Post Editor +- Avoid to show unnecessary Tooltip for the Post Schedule button. ([56759](https://github.com/WordPress/gutenberg/pull/56759)) + +#### Block Editor +- Increase right padding of URL field to take the Submit button into account. ([56685](https://github.com/WordPress/gutenberg/pull/56685)) + +#### Site Editor +- Shorter screen reader announcement after changing pages. ([56339](https://github.com/WordPress/gutenberg/pull/56339)) + +#### Components +- Use tooltip for the Timezone only when necessary. ([56214](https://github.com/WordPress/gutenberg/pull/56214)) + + +### Performance + +- Block editor: Make all BlockEdit hooks pure. ([56813](https://github.com/WordPress/gutenberg/pull/56813)) +- Block editor: Remove 4 useSelect in favour of context. ([56915](https://github.com/WordPress/gutenberg/pull/56915)) +- Block editor: hooks: Avoid BlockEdit filter for content locking UI. ([56957](https://github.com/WordPress/gutenberg/pull/56957)) +- Block editor: hooks: Share block settings. ([56852](https://github.com/WordPress/gutenberg/pull/56852)) +- Keycodes: Avoid regex for capital case. ([56822](https://github.com/WordPress/gutenberg/pull/56822)) +- Measure typing without inspector. ([56753](https://github.com/WordPress/gutenberg/pull/56753)) +- Media upload component: Lazy mount. ([56958](https://github.com/WordPress/gutenberg/pull/56958)) +- Paragraph: Store subscription for selected block only. ([56967](https://github.com/WordPress/gutenberg/pull/56967)) +- Perf: Reopen inspector for remaining tests. ([56780](https://github.com/WordPress/gutenberg/pull/56780)) +- useBlockProps: Combine store subscriptions. ([56847](https://github.com/WordPress/gutenberg/pull/56847)) + +#### Block Editor +- Improve opening inserter in post editor. ([57006](https://github.com/WordPress/gutenberg/pull/57006)) +- hooks: Subscribe only to relevant attributes. ([56783](https://github.com/WordPress/gutenberg/pull/56783)) + +#### Site Editor +- Fix typing performance by not rendering sidebar. ([56927](https://github.com/WordPress/gutenberg/pull/56927)) + +#### Components +- ToolsPanel: Fix deregister/register on type. ([56770](https://github.com/WordPress/gutenberg/pull/56770)) + +#### Modules API +- Load the import map polyfill only when there is an import map. ([56699](https://github.com/WordPress/gutenberg/pull/56699)) + +#### Post Editor +- Editor: Avoid double parsing content in 'getSuggestedPostFormat' selelector. ([56679](https://github.com/WordPress/gutenberg/pull/56679)) + + +### Experiments + +#### Data Views +- DataViews: Add story. ([56761](https://github.com/WordPress/gutenberg/pull/56761)) +- DataViews: Add support for `NOT IN` operator in filter. ([56479](https://github.com/WordPress/gutenberg/pull/56479)) +- DataViews: Centralize the view definition and rename `list` to `table`. ([56693](https://github.com/WordPress/gutenberg/pull/56693)) +- DataViews: Do not export strings constants. ([56754](https://github.com/WordPress/gutenberg/pull/56754)) +- DataViews: Export the view components as defaults. ([56677](https://github.com/WordPress/gutenberg/pull/56677)) +- DataViews: Fix dropdown menu actions with modal. ([56760](https://github.com/WordPress/gutenberg/pull/56760)) +- DataViews: Hide pagination if we have only one page. ([56948](https://github.com/WordPress/gutenberg/pull/56948)) +- DataViews: Implement `NOT IN` operator for author filter in templates. ([56777](https://github.com/WordPress/gutenberg/pull/56777)) +- DataViews: Iterate on list view. ([56746](https://github.com/WordPress/gutenberg/pull/56746)) +- DataViews: Make `Actions` styles the same as any other column header. ([56654](https://github.com/WordPress/gutenberg/pull/56654)) +- DataViews: Make `mediaField` not hidable. ([56643](https://github.com/WordPress/gutenberg/pull/56643)) +- DataViews: Rename view components. ([56709](https://github.com/WordPress/gutenberg/pull/56709)) +- DataViews: Render data async conditionally. ([56851](https://github.com/WordPress/gutenberg/pull/56851)) +- DataViews: Set proper role for AddFilter's items. ([56714](https://github.com/WordPress/gutenberg/pull/56714)) +- DataViews: Set proper semantics for dropdown items. ([56676](https://github.com/WordPress/gutenberg/pull/56676)) +- DataViews: Update sorting semantics. ([56717](https://github.com/WordPress/gutenberg/pull/56717)) +- Dataviews: Extract to dedicated bundled package. ([56721](https://github.com/WordPress/gutenberg/pull/56721)) + +#### Block Validation/Deprecation +- Input Field Block: Use `useblockProps` hook in save function. ([56507](https://github.com/WordPress/gutenberg/pull/56507)) + +#### Patterns +- Implement partially synced patterns behind an experimental flag. ([56235](https://github.com/WordPress/gutenberg/pull/56235)) + + +### Documentation + +- Add the nested blocks chapter to the platform documentation. ([56689](https://github.com/WordPress/gutenberg/pull/56689)) +- Components: Update CHANGELOG.md. ([56960](https://github.com/WordPress/gutenberg/pull/56960)) +- Doc: Search Control - add Storybook link. ([56815](https://github.com/WordPress/gutenberg/pull/56815)) +- Doc: Spinner - add Storybook link. ([56818](https://github.com/WordPress/gutenberg/pull/56818)) +- Docs: Add storybook link for spinner component. ([56953](https://github.com/WordPress/gutenberg/pull/56953)) +- Docs: Fix {% end %} tab position to show the text. ([56735](https://github.com/WordPress/gutenberg/pull/56735)) +- Docs: Fundamentals of Block Development - Minor fixes - registration-of-a-block. ([56731](https://github.com/WordPress/gutenberg/pull/56731)) +- Docs: Fundamentals of Block Development - add links. ([56700](https://github.com/WordPress/gutenberg/pull/56700)) +- Docs: Fundamentals of Block Development ---- Small fixes for "Block wrapper". ([56651](https://github.com/WordPress/gutenberg/pull/56651)) +- Link to Dashicons. ([56872](https://github.com/WordPress/gutenberg/pull/56872)) +- Platform Docs: Add trusted by section. ([56749](https://github.com/WordPress/gutenberg/pull/56749)) +- Revert "Doc: Spinner - add Storybook link". ([56913](https://github.com/WordPress/gutenberg/pull/56913)) +- Update Getting Started Guide for Gutenberg 17.2. ([56674](https://github.com/WordPress/gutenberg/pull/56674)) +- Update InnerBlocks defaultblock doc usage. ([56728](https://github.com/WordPress/gutenberg/pull/56728)) +- Update formatting and fix grammar in the Block Editor Handbook readme. ([56798](https://github.com/WordPress/gutenberg/pull/56798)) + + +### Code Quality + +- Block editor: hooks: Avoid getEditWrapperProps. ([56912](https://github.com/WordPress/gutenberg/pull/56912)) +- Block lib: Use RichText.isEmpty where forgotten. ([56726](https://github.com/WordPress/gutenberg/pull/56726)) +- Block library: Reusable caption component util. ([56606](https://github.com/WordPress/gutenberg/pull/56606)) +- Core data revisions: Remove hardcoded supports constant. ([56701](https://github.com/WordPress/gutenberg/pull/56701)) +- Editor: Cleanup default editor mode handling. ([56819](https://github.com/WordPress/gutenberg/pull/56819)) +- Editor: Move the BlockCanvas component within the EditorCanvas component. ([56850](https://github.com/WordPress/gutenberg/pull/56850)) +- Editor: Move the device type state to the editor package. ([56866](https://github.com/WordPress/gutenberg/pull/56866)) +- Editor: Unify device preview styles. ([56904](https://github.com/WordPress/gutenberg/pull/56904)) +- Fix PHP linter failing. ([56905](https://github.com/WordPress/gutenberg/pull/56905)) +- Framework: Bundle the BlockTools component within BlockCanvas. ([56996](https://github.com/WordPress/gutenberg/pull/56996)) +- Move `useDebouncedInput` hook to @wordpress/compose package. ([56744](https://github.com/WordPress/gutenberg/pull/56744)) +- Post Editor: Rely on the editor store for the template mode state. ([56716](https://github.com/WordPress/gutenberg/pull/56716)) +- Refactor . ([56335](https://github.com/WordPress/gutenberg/pull/56335)) +- Remove Block Tools BackCompat. ([56874](https://github.com/WordPress/gutenberg/pull/56874)) +- Site and Post Editor: Unify the DocumentBar component. ([56778](https://github.com/WordPress/gutenberg/pull/56778)) +- getValueFromObjectPath: Remove memize. ([56711](https://github.com/WordPress/gutenberg/pull/56711)) + +#### Block Editor +- Don't render undefined classname in useBlockProps hook. ([56923](https://github.com/WordPress/gutenberg/pull/56923)) +- One hook to rule them all: Preparation for a block supports API. ([56862](https://github.com/WordPress/gutenberg/pull/56862)) +- RichText: Pass value to store. ([43204](https://github.com/WordPress/gutenberg/pull/43204)) +- hooks: Manage BlockListBlock filters in one place. ([56875](https://github.com/WordPress/gutenberg/pull/56875)) + +#### Global Styles +- Command Palette: Use getRevisions instead of deprecated selector. ([56738](https://github.com/WordPress/gutenberg/pull/56738)) +- Global styles revisions: Remove PHP unit tests that are running in Core. ([56492](https://github.com/WordPress/gutenberg/pull/56492)) + +#### Components +- Site editor: Do not use navigator's internal classname. ([56911](https://github.com/WordPress/gutenberg/pull/56911)) + +#### Data Views +- DataViews: Remove TanStack. ([56873](https://github.com/WordPress/gutenberg/pull/56873)) + + +### Tools + +- Env: Migrate to Compose V2. ([51339](https://github.com/WordPress/gutenberg/pull/51339)) +- Scripts: Fix CSS imports not minified. ([56516](https://github.com/WordPress/gutenberg/pull/56516)) +- wp-env: Make env-cwd option work on Windows. ([56265](https://github.com/WordPress/gutenberg/pull/56265)) + +#### Testing +- Migrate 'editor multi entity saving' end-to-end tests to Playwright. ([56670](https://github.com/WordPress/gutenberg/pull/56670)) +- Migrate 'inner-blocks-locking-all-embed' end-to-end tests to Playwright. ([56673](https://github.com/WordPress/gutenberg/pull/56673)) +- Migrate 'site editor export' end-to-end tests to Playwright. ([56675](https://github.com/WordPress/gutenberg/pull/56675)) +- RN: Add watch mode for native tests. ([56788](https://github.com/WordPress/gutenberg/pull/56788)) +- Scripts: Enable skipping Playwright browser installation. ([56594](https://github.com/WordPress/gutenberg/pull/56594)) +- Tabs: Implement `ariakit/test` in unit tests. ([56835](https://github.com/WordPress/gutenberg/pull/56835)) +- `CustomSelectControl`: Add additional unit tests. ([56575](https://github.com/WordPress/gutenberg/pull/56575)) + + +### Copy + +- Copy/fix capitalization of WordPress. ([56834](https://github.com/WordPress/gutenberg/pull/56834)) + +#### Site Editor +- Improve text and design of the block removal warnings. ([56869](https://github.com/WordPress/gutenberg/pull/56869)) + +#### Global Styles +- Global styles welcome guide: Add a space between translated strings. ([56839](https://github.com/WordPress/gutenberg/pull/56839)) + +#### Block Library +- Simplify page list edit warning. ([56829](https://github.com/WordPress/gutenberg/pull/56829)) + +#### Patterns +- End pattern page descriptions with a period. ([56828](https://github.com/WordPress/gutenberg/pull/56828)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @benoitchantre: Scripts: Fix CSS imports not minified. ([56516](https://github.com/WordPress/gutenberg/pull/56516)) +- @kmanijak: Decode some characters if used in taxonomy name so it's displayed correctly in Query Loop filters. ([50376](https://github.com/WordPress/gutenberg/pull/50376)) +- @lithrel: Env: Migrate to Compose V2. ([51339](https://github.com/WordPress/gutenberg/pull/51339)) +- @nk-o: Fix: PHP 8.1 deprecated warning strpos(). ([56171](https://github.com/WordPress/gutenberg/pull/56171)) +- @taylorgorman: Link to Dashicons. ([56872](https://github.com/WordPress/gutenberg/pull/56872)) +- @valerogarte: #55702 - Control dimensions (margin and padding) of the list-item block. ([55874](https://github.com/WordPress/gutenberg/pull/55874)) + + +## Contributors + +The following contributors merged PRs in this release: + +@afercia @ajlende @alexstine @andrewhayward @andrewserong @apeatling @atachibana @Aurorum @benoitchantre @bph @brookewp @chad1008 @ciampo @colorful-tones @dcalhoun @derekblank @draganescu @ellatrix @fluiddot @geriux @getdave @jameskoster @jasmussen @jeherve @jeryj @jffng @jonathanbossenger @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @kmanijak @lithrel @luisherranz @Mamaduka @matiasbenedetto @mikachan @miminari @mtias @ndiego @nk-o @ntsekouras @oandregal @ramonjd @richtabor @scruffian @SiobhyB @t-hamano @talldan @taylorgorman @tellthemachines @tyxla @valerogarte @WunderBart @youknowriad + + + + = 17.2.3 = ## Changelog diff --git a/docs/README.md b/docs/README.md index 222b54209c7d62..ba6b35a761f6e0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,20 +27,18 @@ Besides offering an [enhanced editing experience](https://wordpress.org/gutenber This handbook is focused on block development and is divided into five sections, each serving a different purpose. -- [**Getting Started**](https://developer.wordpress.org/block-editor/getting-started/) - For those just starting out with block development, this is where you can get set up with a [development environment](https://developer.wordpress.org/block-editor/getting-started/devenv/) and learn the [fundamentals of block development](https://developer.wordpress.org/block-editor/getting-started/create-block/). Its [Glossary of terms](https://developer.wordpress.org/block-editor/getting-started/glossary/) and [FAQs](https://developer.wordpress.org/block-editor/getting-started/faq/) should answer any outstanding questions you may have. +- [**Getting Started**](https://developer.wordpress.org/block-editor/getting-started/) - For those just starting out with block development, this is where you can get set up with a [development environment](https://developer.wordpress.org/block-editor/getting-started/devenv/) and learn the [fundamentals of block development](https://developer.wordpress.org/block-editor/getting-started/fundamentals/). Its [Quick Start Guide](https://developer.wordpress.org/block-editor/getting-started/quick-start-guide/) and [Tutorial: Build your first block](https://developer.wordpress.org/block-editor/getting-started/tutorial/) are probably the best places to start learning block development. -- [**How-to Guides**](https://developer.wordpress.org/block-editor/how-to-guides/) - Here, you can build on what you learned in the Getting Started section and learn how to solve particular problems you might encounter. You can also get tutorials and example code that you can reuse for projects such as [building a full-featured block](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/) or [working with WordPress’ data](https://developer.wordpress.org/block-editor/how-to-guides/data-basics/). In addition, you can learn [How to use JavaScript with the Block Editor](https://developer.wordpress.org/block-editor/how-to-guides/javascript/). +- [**How-to Guides**](https://developer.wordpress.org/block-editor/how-to-guides/) - Here, you can build on what you learned in the Getting Started section and learn how to solve particular problems you might encounter. You can also get tutorials and example code that you can reuse for projects such as [working with WordPress’ data](https://developer.wordpress.org/block-editor/how-to-guides/data-basics/) or [Curating the Editor Experience](https://developer.wordpress.org/block-editor/how-to-guides/curating-the-editor-experience/). - [**Reference Guides**](https://developer.wordpress.org/block-editor/reference-guides/) - This section is the heart of the handbook and is where you can get down to the nitty-gritty and look up the details of the particular API you’re working with or need information on. Among other things, the [Block API Reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/) covers most of what you will want to do with a block, and each [component](https://developer.wordpress.org/block-editor/reference-guides/components/) and [package](https://developer.wordpress.org/block-editor/reference-guides/packages/) is also documented here. _Components are also documented via [Storybook](https://wordpress.github.io/gutenberg/?path=/story/docs-introduction--page)._ - - [**Explanations**](https://developer.wordpress.org/block-editor/explanations/) - This section enables you to go deeper and reinforce your practical knowledge with a theoretical understanding of the [Architecture](https://developer.wordpress.org/block-editor/explanations/architecture/) of the block editor. - [**Contributor Guide**](https://developer.wordpress.org/block-editor/contributors/) - Gutenberg is open source software, and anyone is welcome to contribute to the project. This section details how to contribute and can help you choose in which way you want to contribute, whether with [code](https://developer.wordpress.org/block-editor/contributors/code/), [design](https://developer.wordpress.org/block-editor/contributors/design/), [documentation](https://developer.wordpress.org/block-editor/contributors/documentation/), or in some other way. - ## Further resources This handbook should be considered the canonical resource for all things related to block development. However, there are other resources that can help you. @@ -48,7 +46,7 @@ This handbook should be considered the canonical resource for all things related - [**WordPress Developer Blog**](https://developer.wordpress.org/news/) - An ever-growing resource of technical articles covering specific topics related to block development and a wide variety of use cases. The blog is also an excellent way to [keep up with the latest developments in WordPress](https://developer.wordpress.org/news/tag/roundup/). - [**Learn WordPress**](https://learn.wordpress.org/) - The WordPress hub for learning resources where you can find courses like [Introduction to Block Development: Build your first custom block](https://learn.wordpress.org/course/introduction-to-block-development-build-your-first-custom-block/), [Converting a Shortcode to a Block](https://learn.wordpress.org/course/converting-a-shortcode-to-a-block/) or [Using the WordPress Data Layer](https://learn.wordpress.org/course/using-the-wordpress-data-layer/) - [**WordPress.tv**](https://wordpress.tv/) - A hub of WordPress-related videos (from talks at WordCamps to recordings of online workshops) curated and moderated by the WordPress.org community. You’re sure to find something to aid your learning about [block development](https://wordpress.tv/?s=block%20development&sort=newest) or the [Block Editor](https://wordpress.tv/?s=block%20editor&sort=relevance) here. -- [**Gutenberg repository**](https://github.com/WordPress/gutenberg/) - Development of the block editor project is carried out in this GitHub repository. It contains the code of interesting packages such as [`block-library`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src) (core blocks) or [`components`](https://github.com/WordPress/gutenberg/tree/trunk/packages/components) (common UI elements). _The [gutenberg-examples](https://github.com/WordPress/gutenberg-examples) repository is another useful reference._ +- [**Gutenberg repository**](https://github.com/WordPress/gutenberg/) - Development of the block editor project is carried out in this GitHub repository. It contains the code of interesting packages such as [`block-library`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src) (core blocks) or [`components`](https://github.com/WordPress/gutenberg/tree/trunk/packages/components) (common UI elements). _The [block-development-examples](https://github.com/WordPress/block-development-examples) repository is another useful reference._ - [**End User Documentation**](https://wordpress.org/documentation/) - This documentation site is targeted to the end user (not developers), where you can also find documentation about the [Block Editor](https://wordpress.org/documentation/category/block-editor/) and [working with blocks](https://wordpress.org/documentation/article/work-with-blocks/). ## Are you in the right place? diff --git a/docs/contributors/code/getting-started-with-code-contribution.md b/docs/contributors/code/getting-started-with-code-contribution.md index c3282c0f8003da..30a78037ab75e3 100644 --- a/docs/contributors/code/getting-started-with-code-contribution.md +++ b/docs/contributors/code/getting-started-with-code-contribution.md @@ -5,7 +5,7 @@ The following guide is for setting up your local environment to contribute to th ## Prerequisites - Node.js - Gutenberg is a JavaScript project and requires [Node.js](https://nodejs.org/). The project is built using Node.js v16, and npm v8. See the [LTS release schedule](https://github.com/nodejs/Release#release-schedule) for details. + Gutenberg is a JavaScript project that requires [Node.js](https://nodejs.org/). The project is currently built using Node.js v20 and npm v10. Though best efforts are made to always use the Active LTS version of Node.js, this will not always be the case. For more details, please refer to the [Node.js release schedule](https://github.com/nodejs/Release#release-schedule). We recommend using the [Node Version Manager](https://github.com/nvm-sh/nvm) (nvm) since it is the easiest way to install and manage node for macOS, Linux, and Windows 10 using WSL2. See [our Development Tools guide](/docs/getting-started/devenv/README.md#development-tools) or the Nodejs site for additional installation instructions. diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 136caa5607e487..b45a740c2a58cd 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -1,6 +1,21 @@ # Getting Started -Welcome! Let's get started building with blocks. Blocks are at the core of extending WordPress. You can create custom blocks, your own block patterns, or combine them together to build a block theme. At a high level, here are a few ways to begin your journey but read on to explore more: +Welcome! Let's get started building with blocks. Blocks are at the core of extending WordPress. You can create custom blocks, your own block patterns, or combine them together to build a block theme. + +## Navigating this chapter + +For those starting with block development, this section is the perfect starting point as it provides the knowledge you need to start creating your own custom blocks. + +- [**Block Development Environment**](https://developer.wordpress.org/block-editor/getting-started/devenv/) - Set up the right development environment to create blocks and get introduced to basic tools for block development such as [`wp-env`](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/), [`create-block`](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-create-block/) and [`wp-scripts`](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-create-block/) +- [**Quick Start Guide**](https://developer.wordpress.org/block-editor/getting-started/quick-start-guide/) - Get a block up and running in less than 1 min. +- [**Tutorial: Build your first block**](https://developer.wordpress.org/block-editor/getting-started/tutorial/) - The tutorial will guide you, step by step, through the complete process of creating a fully functional custom block. +- [**Fundamentals of Block Development**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/) - This section provides an introduction to the most relevant concepts in Block Development. +- [**Glossary**](https://developer.wordpress.org/block-editor/getting-started/glossary/) - Glossary of terms related to the Block Editor and Full Site Editing +- [**Frequently Asked Questions**](https://developer.wordpress.org/block-editor/getting-started/faq/) - Set of questions (and answers) that have come up from the last few years of Gutenberg development. + +## Getting Started on the WordPress project and Gutenberg + +At a high level, here are a few ways to begin your journey but read on to explore more: - Learn more about where this work is going by [reviewing the long term roadmap](https://wordpress.org/about/roadmap/). - Explore the [GitHub repo](https://github.com/WordPress/gutenberg/) to see the latest issues and PRs folks are working on, especially [Good First Issues](https://github.com/WordPress/gutenberg/issues?q=is%3Aopen+is%3Aissue+label%3A%22Good+First+Issue%22). @@ -9,15 +24,21 @@ Welcome! Let's get started building with blocks. Blocks are at the core of exten - Expand your knowledge by reviewing more developer docs at the overall [developer.wordpress.org resource](https://developer.wordpress.org/). - Subscribe to [updates on Make Core](https://make.wordpress.org/core/), the main site where ongoing project updates happen. -## Tutorials +### Ways to Stay Informed + +New features and changes are important to keep up to date on as the Gutenberg project continues. Each person will have their own unique needs in keeping up with a project of this scale. What follows is more of a catalogue of ways to keep up rather than a recommendation for how to do so. -[Development Environment](/docs/getting-started/devenv/README.md) - A guide to setup your local environment for JavaScript development for creating plugins, themes, and the tools you will need to extend WordPress or contribute to the block editor. +- [Keeping up with Gutenberg](https://make.wordpress.org/core/handbook/references/keeping-up-with-gutenberg-index/) - compilation of Gutenberg-related team posts of Core, Core-Editor, Core-js, Core-css, Design, Meta, and Themes, and other teams. +- [“What’s New In Gutenberg?” release posts](https://make.wordpress.org/core/tag/gutenberg-new/). These updates are wrangled by the Core Editor team and focus on what’s been released in each biweekly Gutenberg release. They include the most relevant features released and a full changelog. +- [Core Editor meetings](https://make.wordpress.org/core/tag/core-editor-summary/). These meetings are wrangled by volunteer members in the #core-editor Slack channel. [Agendas](https://make.wordpress.org/core/tag/core-editor-summary/) and [summaries](https://make.wordpress.org/core/tag/core-editor-summary/) are shared on the [Make Core blog](https://make.wordpress.org/core/). They focus on task coordination and relevant discussions around Gutenberg releases. There is an Open Floor period in each chat where people can suggest topics to discuss. +- Checking in on [issues](https://github.com/WordPress/gutenberg/issues) and [PRs](https://github.com/WordPress/gutenberg/pulls) on GitHub. This will give you a nearly real-time understanding of what’s being worked on by the developers and designers. -[Create a Block Tutorial](/docs/getting-started/create-block/README.md) - Learn how to create your first block for the WordPress block editor. -## Learn WordPress Courses +## Additional Resources -At [Learn WordPress](https://learn.wordpress.org/), you can find [tutorials](https://learn.wordpress.org/tutorials/), [courses](https://learn.wordpress.org/courses/), and [online workshops](https://learn.wordpress.org/online-workshops/) to learn more about developing for the Block Editor. Here is a selection of current offerings. +The [block-development-examples](https://github.com/wptrainingteam/block-development-examples) repo is the central hub of examples for block development referenced from this handbook. + +At [Learn WordPress](https://learn.wordpress.org/), you can find [tutorials](https://learn.wordpress.org/tutorials/), [courses](https://learn.wordpress.org/courses/), and [online workshops](https://learn.wordpress.org/online-workshops/) to learn more about developing for the Block Editor. Here is a selection of current offerings: - [Intro to Block Development: Build Your First Custom Block](https://learn.wordpress.org/course/introduction-to-block-development-build-your-first-custom-block/) - [Converting a Shortcode to a Block](https://learn.wordpress.org/course/converting-a-shortcode-to-a-block/) @@ -25,40 +46,3 @@ At [Learn WordPress](https://learn.wordpress.org/), you can find [tutorials](htt - [Registering Block Patterns](https://learn.wordpress.org/workshop/registering-block-patterns/) - [Intro to Gutenberg Block Development](https://learn.wordpress.org/workshop/intro-to-gutenberg-block-development/) - [Intro to Publishing with the Block Editor](https://learn.wordpress.org/workshop/intro-to-publishing-with-the-block-editor/) - -## Ways to Stay Informed - -New features and changes are important to keep up to date on as the Gutenberg project continues. Each person will have their own unique needs in keeping up with a project of this scale. What follows is more of a catalogue of ways to keep up rather than a recommendation for how to do so. - -**Yearly:** - -The [WordPress.org Roadmap](https://wordpress.org/about/roadmap/) with Four Phases of Gutenberg updated by project leadership. This is the highest level overview of the changes coming to WordPress. - -**Quarterly:** - -[Quarterly Updates](https://make.wordpress.org/updates/tag/quarterly-updates/) from Contribution Teams. These updates give an overview on what each team is working on, struggling with, and how to get involved. - -**Monthly:** - -[“What’s Next In Gutenberg?” posts](https://make.wordpress.org/core/tag/gutenberg-next/). These updates are wrangled by the Core Editor team and highlight areas of work aligned with the Gutenberg roadmap for contributors to help, how to get involved, and more. - -[Block Based Themes Meeting](https://make.wordpress.org/themes/tags/block-based-meeting/). These meetings are currently wrangled in the #themereview Slack channel and are dedicated to sharing FSE changes that will specifically impact themes. Agendas and summaries are shared on the [Make Themes blog](https://make.wordpress.org/themes/). - -**Biweekly:** - -[“What’s New In Gutenberg?” release posts](https://make.wordpress.org/core/tag/gutenberg-new/). These updates are wrangled by the Core Editor team and focus on what’s been released in each biweekly Gutenberg release. They include the most relevant features released and a full changelog. - -**Weekly:** - -[Core Editor meetings](https://make.wordpress.org/core/tag/core-editor-summary/). These meetings are wrangled by volunteer members in the #core-editor Slack channel. [Agendas](https://make.wordpress.org/core/tag/core-editor-summary/) and [summaries](https://make.wordpress.org/core/tag/core-editor-summary/) are shared on the [Make Core blog](https://make.wordpress.org/core/). They focus on task coordination and relevant discussions around Gutenberg releases. There is an Open Floor period in each chat where people can suggest topics to discuss. - -[Weekly Theme Related Gutenberg Updates](https://make.wordpress.org/themes/tags/gutenberg-themes-roundup/). These posts are focused on themes, including everything from current discussions to recent changes, as well as helpful resources for theme authors. - -**Daily:** - -Checking in on [issues](https://github.com/WordPress/gutenberg/issues) and [PRs](https://github.com/WordPress/gutenberg/pulls) on GitHub. This will give you a nearly real-time understanding of what’s being worked on by the developers and designers. - -- [Glossary](/docs/getting-started/glossary.md) -- [Frequently Asked Questions](/docs/getting-started/faq.md) -- [Project History](/docs/explanations/history.md) -- [Gutenberg related Make posts](https://make.wordpress.org/core/handbook/references/keeping-up-with-gutenberg-index/) \ No newline at end of file diff --git a/docs/getting-started/fundamentals/README.md b/docs/getting-started/fundamentals/README.md index 4fde0f3a0d1009..799ff89aa39419 100644 --- a/docs/getting-started/fundamentals/README.md +++ b/docs/getting-started/fundamentals/README.md @@ -9,4 +9,5 @@ In this section, you will learn: 1. [**Registration of a block**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block) - How a block is registered in both the server and the client. 1. [**Block wrapper**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-wrapper) - How to set proper attributes to the block's markup wrapper. 1. [**The block in the Editor**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-in-the-editor) - The block as a React component loaded in the Block Editor and its possibilities. +1. [**Markup representation of a block**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/markup-representation-block) - How blocks are represented in the DB or in templates. 1. [**Javascript in the Block Editor**](https://developer.wordpress.org/block-editor/getting-started/fundamentals/javascript-in-the-block-editor) - How to work with Javascript for the Block Editor. \ No newline at end of file diff --git a/docs/getting-started/fundamentals/block-in-the-editor.md b/docs/getting-started/fundamentals/block-in-the-editor.md index 99f5d26304a7ee..56ba72c283bdf7 100644 --- a/docs/getting-started/fundamentals/block-in-the-editor.md +++ b/docs/getting-started/fundamentals/block-in-the-editor.md @@ -48,9 +48,9 @@ A good workflow when using a component for the Block Editor is: To simplify block customization and ensure a consistent experience for users, there are a number of built-in UI patterns to help generate the editor preview. -### Block Toolbar +![Diagram showing the Block Toolbar and the Settings Sidebar when a Paragraph block is selected](https://developer.wordpress.org/files/2023/12/block-toolbar-settings-sidebar.png) -Screenshot of the rich text toolbar applied to a Paragraph block inside the block editor +### Block Toolbar When the user selects a block, a number of control buttons may be shown in a toolbar above the selected block. Some of these block-level controls may be included automatically but you can also customize the toolbar to include controls specific to your block type. If the return value of your block type's `edit` function includes a `BlockControls` element, those controls will be shown in the selected block's toolbar. @@ -98,8 +98,6 @@ Note that `BlockControls` is only visible when the block is currently selected a ### Settings Sidebar -Screenshot of the inspector panel focused on the settings for a Paragraph block - The Settings Sidebar is used to display less-often-used settings or settings that require more screen space. The Settings Sidebar should be used for **block-level settings only**. If you have settings that affects only selected content inside a block (example: the "bold" setting for selected text inside a paragraph): **do not place it inside the Settings Sidebar**. The Settings Sidebar is displayed even when editing a block in HTML mode, so it should only contain block-level settings. diff --git a/docs/getting-started/fundamentals/block-json.md b/docs/getting-started/fundamentals/block-json.md index d06d2579969f4a..f659564f0cfc3c 100644 --- a/docs/getting-started/fundamentals/block-json.md +++ b/docs/getting-started/fundamentals/block-json.md @@ -73,7 +73,9 @@ _Example: Atributes stored in the Markup representation of the block_ x ``` -These [attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#attributes) are passed to the React component `Edit`(to display in the Block Editor), and the `save` function (to return the markup saved to the database) of the block, and to any server-side render definition for the block (see the `render` property above). +### Reading and updating attributes + +These [attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#attributes) are passed to the React component `Edit`(to display in the Block Editor) and the `save` function (to return the markup saved to the database) of the block, and to any server-side render definition for the block (see the `render` property above). The `Edit` component receives exclusively the capability of updating the attributes via the [`setAttributes`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#setattributes) function. diff --git a/docs/getting-started/fundamentals/block-wrapper.md b/docs/getting-started/fundamentals/block-wrapper.md index 6ecebbe8303864..1f2404eca9b031 100644 --- a/docs/getting-started/fundamentals/block-wrapper.md +++ b/docs/getting-started/fundamentals/block-wrapper.md @@ -5,7 +5,7 @@ Each block's markup is wrapped by a container HTML tag that needs to have the pr Ensuring proper attributes to the block wrapper is especially important when using custom styling or features like `supports`.
-The use of supports generates a set of properties that need to be manually added to the wrapping element of the block so they're properly stored as part of the block data +The use of supports generates a set of properties that need to be manually added to the wrapping element of the block so they're properly stored as part of the block data.
A block can have three sets of markup defined, each one of them with a specific target and purpose: @@ -16,7 +16,7 @@ A block can have three sets of markup defined, each one of them with a specific - The one used to **dynamically render the markup of the block** returned to the front end on request, defined through the `render_callback` on [`register_block_type`](https://developer.wordpress.org/reference/functions/register_block_type/) or the [`render`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#render) PHP file in `block.json` - If defined, this server-side generated markup will be returned to the front end, ignoring the markup stored in DB. -For the [`edit` React component and the `save` function](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/), the block wrapper element should be a native DOM element (like `
`) or a React component that forwards any additional props to native DOM elements. Using a or component, for instance, would be invalid. +For the [`edit` React component and the `save` function](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/), the block wrapper element should be a native DOM element (like `
`) or a React component that forwards any additional props to native DOM elements. Using a `` or `` component, for instance, would be invalid. ## The Edit component's markup @@ -60,7 +60,7 @@ _(see the [code above](https://github.com/WordPress/block-development-examples/b >Hello World - Block Editor

``` -Any additional classes and attributes for the `Edit` component of the block should be passed as an argument of `useBlockProps` (see [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/edit.js)). When you add `support` for any feature, they get added to the object returned by the `useBlockProps` hook. +Any additional classes and attributes for the `Edit` component of the block should be passed as an argument of `useBlockProps` (see [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/edit.js)). When you add `supports` for any feature, they get added to the object returned by the `useBlockProps` hook. ## The Save component's markup @@ -89,7 +89,7 @@ _(see the [code above](https://github.com/WordPress/block-development-examples/b Any additional classes and attributes for the `save` function of the block should be passed as an argument of `useBlockProps.save()` (see [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/save.js)). -When you add `support` for any feature, the proper classes get added to the object returned by the `useBlockProps.save()` hook. +When you add `supports` for any feature, the proper classes get added to the object returned by the `useBlockProps.save()` hook. ```html

+ +``` + +The [markup representation of a block is parsed for the Block Editor](https://developer.wordpress.org/block-editor/explanations/architecture/data-flow/) and the block's output for the front end: +- In the editor, WordPress parses this block markup, captures its data and loads its `edit` version +- In the front end, WordPress parses this block markup, captures its data and generates its final HTML markup + +Whenever a block is saved, the `save` function, defined when the [block is registered in the client](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/#registration-of-the-block-with-javascript-client-side), is called to return the markup that will be saved into the database within the block delimiter's comment. If `save` is `null` (common case for blocks with dynamic rendering), only a single line block delimiter's comment is stored, along with any attributes + +The Post Editor checks that the markup created by the `save` function is identical to the block's markup saved to the database: +- If there are any differences, the Post Editor trigger a **block validation error**. +- Block validation errors usually happen when a block’s `save` function is updated to change the markup produced by the block. +- A block developer can mitigate these issues by adding a [**block deprecation**](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-deprecation/) to register the change in the block. + +The markup of a **block with dynamic rendering** is expected to change so the markup of these blocks is not saved to the database. What is saved in the DB as representation of the block, for blocks with dynamic rendering, is a single line of HTML consisting on just the block delimiter's comment (including block attributes values). That HTML is not subject to the Post Editor’s validation. + +_Example: Markup representation of a block with dynamic rendering (`save` = `null`) and attributes_ + + +```html + +``` + +## Additional Resources + +- [Data Flow and Data Format](https://developer.wordpress.org/block-editor/explanations/architecture/data-flow/) +- [Static vs. dynamic blocks: What’s the difference?](https://developer.wordpress.org/news/2023/02/27/static-vs-dynamic-blocks-whats-the-difference/) +- [Block deprecation – a tutorial](https://developer.wordpress.org/news/2023/03/10/block-deprecation-a-tutorial/) +- [Introduction to Templates > Block markup](https://developer.wordpress.org/themes/templates/introduction-to-templates/#block-markup) | Theme Handbook \ No newline at end of file diff --git a/docs/how-to-guides/platform/README.md b/docs/how-to-guides/platform/README.md index 2ed96d6c83d876..731ae26a1ead58 100644 --- a/docs/how-to-guides/platform/README.md +++ b/docs/how-to-guides/platform/README.md @@ -57,4 +57,5 @@ For more info, see the [Getting Started with JavaScript tutorial](/docs/how-to-g The [`@wordpress/block-editor` package](https://developer.wordpress.org/block-editor/packages/packages-block-editor/) allows you to create and use standalone block editors. -You can learn more by reading the [tutorial "Building a custom block editor"](/docs/how-to-guides/platform/custom-block-editor/README.md). +You can learn more by reading the [tutorial "Building a custom block editor"](/docs/how-to-guides/platform/custom-block-editor.md). + diff --git a/docs/manifest.json b/docs/manifest.json index fb6d8550fa7ec9..7bb1e847ce03fd 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -89,6 +89,12 @@ "markdown_source": "../docs/getting-started/fundamentals/block-in-the-editor.md", "parent": "fundamentals" }, + { + "title": "Markup representation of a block", + "slug": "markup-representation-block", + "markdown_source": "../docs/getting-started/fundamentals/markup-representation-block.md", + "parent": "fundamentals" + }, { "title": "Working with Javascript for the Block Editor", "slug": "javascript-in-the-block-editor", diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 2ba78177e9ec60..9f25ad0a594b89 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -341,7 +341,7 @@ Gather blocks in a layout container. ([Source](https://github.com/WordPress/gute - **Name:** core/group - **Category:** design -- **Supports:** align (full, wide), anchor, ariaLabel, background (backgroundImage), color (background, button, gradients, heading, link, text), dimensions (minHeight), layout (allowSizingOnChildren), position (sticky), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align (full, wide), anchor, ariaLabel, background (backgroundImage, backgroundSize), color (background, button, gradients, heading, link, text), dimensions (minHeight), layout (allowSizingOnChildren), position (sticky), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** allowedBlocks, tagName, templateLock ## Heading diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index e269ba9ef19917..4c7e3df7cec128 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -116,7 +116,7 @@ wp.hooks.addFilter( ); ``` -#### `blocks.getSaveContent.extraProps` +### `blocks.getSaveContent.extraProps` A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example: to add a className, an id, or any valid prop for this element. @@ -229,7 +229,7 @@ const withMyPluginControls = createHigherOrderComponent( ( BlockEdit ) => { }, 'withMyPluginControls' ); ``` -#### `editor.BlockListBlock` +### `editor.BlockListBlock` Used to modify the block's wrapper component containing the block's `edit` component and all toolbars. It receives the original `BlockListBlock` component and returns a new wrapped component. diff --git a/docs/toc.json b/docs/toc.json index 4b4f5bbd69a5f6..961fc88fae4f52 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -39,6 +39,9 @@ { "docs/getting-started/fundamentals/block-in-the-editor.md": [] }, + { + "docs/getting-started/fundamentals/markup-representation-block.md": [] + }, { "docs/getting-started/fundamentals/javascript-in-the-block-editor.md": [] } diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index ab2fa84361fc20..c43603046c0c08 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -54,6 +54,8 @@ function gutenberg_render_background_support( $block_content, $block ) { $background_image_source = $block_attributes['style']['background']['backgroundImage']['source'] ?? null; $background_image_url = $block_attributes['style']['background']['backgroundImage']['url'] ?? null; $background_size = $block_attributes['style']['background']['backgroundSize'] ?? 'cover'; + $background_position = $block_attributes['style']['background']['backgroundPosition'] ?? null; + $background_repeat = $block_attributes['style']['background']['backgroundRepeat'] ?? null; $background_block_styles = array(); @@ -64,8 +66,15 @@ function gutenberg_render_background_support( $block_content, $block ) { // Set file based background URL. // TODO: In a follow-up, similar logic could be added to inject a featured image url. $background_block_styles['backgroundImage']['url'] = $background_image_url; - // Only output the background size when an image url is set. - $background_block_styles['backgroundSize'] = $background_size; + // Only output the background size and repeat when an image url is set. + $background_block_styles['backgroundSize'] = $background_size; + $background_block_styles['backgroundRepeat'] = $background_repeat; + $background_block_styles['backgroundPosition'] = $background_position; + + // If the background size is set to `contain` and no position is set, set the position to `center`. + if ( 'contain' === $background_size && ! isset( $background_position ) ) { + $background_block_styles['backgroundPosition'] = 'center'; + } } $styles = gutenberg_style_engine_get_styles( array( 'background' => $background_block_styles ) ); diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 43a3772a1c3af0..4fe5a3a3bf6a88 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -354,6 +354,7 @@ class WP_Theme_JSON_Gutenberg { 'useRootPaddingAwareAlignments' => null, 'background' => array( 'backgroundImage' => null, + 'backgroundSize' => null, ), 'border' => array( 'color' => null, @@ -650,6 +651,7 @@ public static function get_element_class_name( $element ) { */ const APPEARANCE_TOOLS_OPT_INS = array( array( 'background', 'backgroundImage' ), + array( 'background', 'backgroundSize' ), array( 'border', 'color' ), array( 'border', 'radius' ), array( 'border', 'style' ), diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 950d9e00e6243f..189d411db2257f 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -322,9 +322,6 @@ public static function get_theme_data( $deprecated = array(), $options = array() } $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients; - // Classic themes without a theme.json don't support global duotone. - $theme_support_data['settings']['color']['defaultDuotone'] = false; - // Allow themes to enable all border settings via theme_support. if ( current_theme_supports( 'border' ) ) { $theme_support_data['settings']['border']['color'] = true; diff --git a/lib/compat/wordpress-6.4/block-patterns.php b/lib/compat/wordpress-6.4/block-patterns.php deleted file mode 100644 index 65c31fb7a22af4..00000000000000 --- a/lib/compat/wordpress-6.4/block-patterns.php +++ /dev/null @@ -1,36 +0,0 @@ -= 6.4. - * - * @see https://github.com/WordPress/gutenberg/pull/53163 - * - * @return void - */ -function gutenberg_register_taxonomy_patterns() { - $args = array( - 'public' => false, - 'publicly_queryable' => false, - 'hierarchical' => false, - 'labels' => array( - 'name' => _x( 'Pattern Categories', 'taxonomy general name' ), - 'singular_name' => _x( 'Pattern Category', 'taxonomy singular name' ), - ), - 'query_var' => false, - 'rewrite' => false, - 'show_ui' => true, - '_builtin' => true, - 'show_in_nav_menus' => false, - 'show_in_rest' => true, - 'show_admin_column' => true, - ); - register_taxonomy( 'wp_pattern_category', array( 'wp_block' ), $args ); -} -add_action( 'init', 'gutenberg_register_taxonomy_patterns' ); diff --git a/lib/compat/wordpress-6.5/block-patterns.php b/lib/compat/wordpress-6.5/block-patterns.php index 4521d5e4e578f3..f43acda2a1035c 100644 --- a/lib/compat/wordpress-6.5/block-patterns.php +++ b/lib/compat/wordpress-6.5/block-patterns.php @@ -31,3 +31,49 @@ function gutenberg_register_media_pattern_categories() { ); } add_action( 'init', 'gutenberg_register_media_pattern_categories' ); + +/** + * Adds a new taxonomy for organizing user created patterns. + * + * @see https://github.com/WordPress/gutenberg/pull/53163 + * + * @return void + */ +function gutenberg_register_taxonomy_patterns() { + $args = array( + 'public' => false, + 'publicly_queryable' => false, + 'hierarchical' => false, + 'labels' => array( + 'name' => _x( 'Pattern Categories', 'taxonomy general name' ), + 'singular_name' => _x( 'Pattern Category', 'taxonomy singular name' ), + 'add_new_item' => __( 'Add New Category' ), + 'add_or_remove_items' => __( 'Add or remove pattern categories' ), + 'back_to_items' => __( '← Go to pattern categories' ), + 'choose_from_most_used' => __( 'Choose from the most used pattern categories' ), + 'edit_item' => __( 'Edit Pattern Category' ), + 'item_link' => __( 'Pattern Category Link' ), + 'item_link_description' => __( 'A link to a pattern category.' ), + 'items_list' => __( 'Pattern Categories list' ), + 'items_list_navigation' => __( 'Pattern Categories list navigation' ), + 'new_item_name' => __( 'New Pattern Category Name' ), + 'no_terms' => __( 'No pattern categories' ), + 'not_found' => __( 'No pattern categories found.' ), + 'popular_items' => __( 'Popular Pattern Categories' ), + 'search_items' => __( 'Search Pattern Categories' ), + 'separate_items_with_commas' => __( 'Separate pattern categories with commas' ), + 'update_item' => __( 'Update Pattern Category' ), + 'view_item' => __( 'View Pattern Category' ), + ), + 'query_var' => false, + 'rewrite' => false, + 'show_ui' => true, + '_builtin' => true, + 'show_in_nav_menus' => false, + 'show_in_rest' => true, + 'show_admin_column' => true, + 'show_tagcloud' => false, + ); + register_taxonomy( 'wp_pattern_category', array( 'wp_block' ), $args ); +} +add_action( 'init', 'gutenberg_register_taxonomy_patterns' ); diff --git a/lib/compat/wordpress-6.5/kses.php b/lib/compat/wordpress-6.5/kses.php new file mode 100644 index 00000000000000..038d78645786f7 --- /dev/null +++ b/lib/compat/wordpress-6.5/kses.php @@ -0,0 +1,18 @@ +rest_base = 'font-collections'; + $this->namespace = 'wp/v2'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @since 6.5.0 + */ + public function register_routes() { + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_font_collections' ), + 'permission_callback' => array( $this, 'update_font_library_permissions_check' ), + ), + ) + ); + + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/(?P[\/\w-]+)', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_font_collection' ), + 'permission_callback' => array( $this, 'update_font_library_permissions_check' ), + ), + ) + ); + } + + /** + * Gets a font collection. + * + * @since 6.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_font_collection( $request ) { + $id = $request->get_param( 'id' ); + $collection = WP_Font_Library::get_font_collection( $id ); + // If the collection doesn't exist returns a 404. + if ( is_wp_error( $collection ) ) { + $collection->add_data( array( 'status' => 404 ) ); + return $collection; + } + $collection_with_data = $collection->get_data(); + // If there was an error getting the collection data, return the error. + if ( is_wp_error( $collection_with_data ) ) { + $collection_with_data->add_data( array( 'status' => 500 ) ); + return $collection_with_data; + } + return new WP_REST_Response( $collection_with_data ); + } + + /** + * Gets the font collections available. + * + * @since 6.5.0 + * + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_font_collections() { + $collections = array(); + foreach ( WP_Font_Library::get_font_collections() as $collection ) { + $collections[] = $collection->get_config(); + } + + return new WP_REST_Response( $collections, 200 ); + } + + /** + * Checks whether the user has permissions to update the Font Library. + * + * @since 6.5.0 + * + * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. + */ + public function update_font_library_permissions_check() { + if ( ! current_user_can( 'edit_theme_options' ) ) { + return new WP_Error( + 'rest_cannot_update_font_library', + __( 'Sorry, you are not allowed to update the Font Library on this site.', 'gutenberg' ), + array( + 'status' => rest_authorization_required_code(), + ) + ); + } + return true; + } +} diff --git a/lib/experimental/fonts/font-library/class-wp-rest-font-library-controller.php b/lib/experimental/fonts/font-library/class-wp-rest-font-families-controller.php similarity index 84% rename from lib/experimental/fonts/font-library/class-wp-rest-font-library-controller.php rename to lib/experimental/fonts/font-library/class-wp-rest-font-families-controller.php index 9655178d706679..c92a0d2697f315 100644 --- a/lib/experimental/fonts/font-library/class-wp-rest-font-library-controller.php +++ b/lib/experimental/fonts/font-library/class-wp-rest-font-families-controller.php @@ -1,24 +1,24 @@ rest_base = 'fonts'; + $this->rest_base = 'font-families'; $this->namespace = 'wp/v2'; + $this->post_type = 'wp_font_family'; } /** @@ -36,6 +37,19 @@ public function __construct() { * @since 6.5.0 */ public function register_routes() { + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => function () { + return true;}, + ), + ) + ); + register_rest_route( $this->namespace, '/' . $this->rest_base, @@ -67,71 +81,6 @@ public function register_routes() { ), ) ); - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/collections', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_font_collections' ), - 'permission_callback' => array( $this, 'update_font_library_permissions_check' ), - ), - ) - ); - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/collections' . '/(?P[\/\w-]+)', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_font_collection' ), - 'permission_callback' => array( $this, 'update_font_library_permissions_check' ), - ), - ) - ); - } - - /** - * Gets a font collection. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_font_collection( $request ) { - $id = $request->get_param( 'id' ); - $collection = WP_Font_Library::get_font_collection( $id ); - // If the collection doesn't exist returns a 404. - if ( is_wp_error( $collection ) ) { - $collection->add_data( array( 'status' => 404 ) ); - return $collection; - } - $collection_with_data = $collection->get_data(); - // If there was an error getting the collection data, return the error. - if ( is_wp_error( $collection_with_data ) ) { - $collection_with_data->add_data( array( 'status' => 500 ) ); - return $collection_with_data; - } - return new WP_REST_Response( $collection_with_data ); - } - - /** - * Gets the font collections available. - * - * @since 6.5.0 - * - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_font_collections() { - $collections = array(); - foreach ( WP_Font_Library::get_font_collections() as $collection ) { - $collections[] = $collection->get_config(); - } - - return new WP_REST_Response( $collections, 200 ); } /** diff --git a/lib/experimental/fonts/font-library/font-library.php b/lib/experimental/fonts/font-library/font-library.php index 6c31c02d409f7a..709f63e9126cbc 100644 --- a/lib/experimental/fonts/font-library/font-library.php +++ b/lib/experimental/fonts/font-library/font-library.php @@ -22,16 +22,19 @@ function gutenberg_init_font_library_routes() { // @core-merge: This code will go into Core's `create_initial_post_types()`. $args = array( - 'public' => false, - '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ - 'label' => 'Font Library', - 'show_in_rest' => true, + 'public' => false, + '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ + 'label' => 'Font Family', + 'show_in_rest' => true, + 'rest_base' => 'font-families', + 'rest_controller_class' => 'WP_REST_Font_Families_Controller', + 'autosave_rest_controller_class' => 'WP_REST_Autosave_Font_Families_Controller', ); register_post_type( 'wp_font_family', $args ); // @core-merge: This code will go into Core's `create_initial_rest_routes()`. - $font_library_controller = new WP_REST_Font_Library_Controller(); - $font_library_controller->register_routes(); + $font_collections_controller = new WP_REST_Font_Collections_Controller(); + $font_collections_controller->register_routes(); } add_action( 'rest_api_init', 'gutenberg_init_font_library_routes' ); diff --git a/lib/experimental/modules/class-gutenberg-modules.php b/lib/experimental/modules/class-gutenberg-modules.php index 5f847fa8c897ad..bbe51f1376a7db 100644 --- a/lib/experimental/modules/class-gutenberg-modules.php +++ b/lib/experimental/modules/class-gutenberg-modules.php @@ -20,64 +20,90 @@ class Gutenberg_Modules { private static $registered = array(); /** - * An array of queued modules. + * An array of module identifiers that were enqueued before registered. * - * @var string[] + * @var array */ - private static $enqueued = array(); + private static $enqueued_modules_before_register = array(); /** - * Registers the module if no module with that module identifier already - * exists. + * Registers the module if no module with that module identifier has already + * been registered. * - * @param string $module_identifier The identifier of the module. Should be unique. It will be used in the final import map. - * @param string $src Full URL of the module, or path of the script relative to the WordPress root directory. - * @param array $dependencies Optional. An array of module identifiers of the static and dynamic dependencies of this module. It can be an indexed array, in which case all the dependencies are static, or it can be an associative array, in which case it has to contain the keys `static` and `dynamic`. - * @param string|bool|null $version Optional. String specifying module version number. It is added to the URL as a query string for cache busting purposes. If SCRIPT_DEBUG is true, a timestamp is used. If it is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added. + * @param string $module_identifier The identifier of the module. Should be unique. It will be used in the final import map. + * @param string $src Full URL of the module, or path of the script relative to the WordPress root directory. + * @param array $dependencies Optional. An array of module identifiers of the dependencies of this module. The dependencies can be strings or arrays. If they are arrays, they need an `id` key with the module identifier, and can contain a `type` key with either `static` or `dynamic`. By default, dependencies that don't contain a type are considered static. + * @param string|false|null $version Optional. String specifying module version number. Defaults to false. It is added to the URL as a query string for cache busting purposes. If SCRIPT_DEBUG is true, the version is the current timestamp. If $version is set to false, the version number is the currently installed WordPress version. If $version is set to null, no version is added. */ public static function register( $module_identifier, $src, $dependencies = array(), $version = false ) { - // Register the module if it's not already registered. if ( ! isset( self::$registered[ $module_identifier ] ) ) { - $deps = array( - 'static' => isset( $dependencies['static'] ) || isset( $dependencies['dynamic'] ) ? $dependencies['static'] ?? array() : $dependencies, - 'dynamic' => isset( $dependencies['dynamic'] ) ? $dependencies['dynamic'] : array(), - ); + $deps = array(); + foreach ( $dependencies as $dependency ) { + if ( isset( $dependency['id'] ) ) { + $deps[] = array( + 'id' => $dependency['id'], + 'type' => isset( $dependency['type'] ) && 'dynamic' === $dependency['type'] ? 'dynamic' : 'static', + ); + } elseif ( is_string( $dependency ) ) { + $deps[] = array( + 'id' => $dependency, + 'type' => 'static', + ); + } + } self::$registered[ $module_identifier ] = array( 'src' => $src, 'version' => $version, + 'enqueued' => in_array( $module_identifier, self::$enqueued_modules_before_register, true ), 'dependencies' => $deps, ); } } /** - * Enqueues a module in the page. + * Marks the module to be enqueued in the page. * * @param string $module_identifier The identifier of the module. */ public static function enqueue( $module_identifier ) { - // Add the module to the queue if it's not already there. - if ( ! in_array( $module_identifier, self::$enqueued, true ) ) { - self::$enqueued[] = $module_identifier; + if ( isset( self::$registered[ $module_identifier ] ) ) { + self::$registered[ $module_identifier ]['enqueued'] = true; + } elseif ( ! in_array( $module_identifier, self::$enqueued_modules_before_register, true ) ) { + self::$enqueued_modules_before_register[] = $module_identifier; + } + } + + /** + * Unmarks the module so it is no longer enqueued in the page. + * + * @param string $module_identifier The identifier of the module. + */ + public static function dequeue( $module_identifier ) { + if ( isset( self::$registered[ $module_identifier ] ) ) { + self::$registered[ $module_identifier ]['enqueued'] = false; + } + $key = array_search( $module_identifier, self::$enqueued_modules_before_register, true ); + if ( false !== $key ) { + array_splice( self::$enqueued_modules_before_register, $key, 1 ); } } /** * Returns the import map array. * - * @return array Associative array with 'imports' key mapping to an array of module identifiers and their respective source strings. + * @return array Array with an 'imports' key mapping to an array of module identifiers and their respective source URLs, including the version query. */ public static function get_import_map() { $imports = array(); - foreach ( self::get_dependencies( self::$enqueued, array( 'static', 'dynamic' ) ) as $module_identifier => $module ) { + foreach ( self::get_dependencies( array_keys( self::get_enqueued() ) ) as $module_identifier => $module ) { $imports[ $module_identifier ] = $module['src'] . self::get_version_query_string( $module['version'] ); } return array( 'imports' => $imports ); } /** - * Prints the import map. + * Prints the import map using a script tag with an type="importmap" attribute. */ public static function print_import_map() { $import_map = self::get_import_map(); @@ -90,27 +116,30 @@ public static function print_import_map() { * Prints all the enqueued modules using