diff --git a/.github/workflows/reusable-phpunit-tests-v3.yml b/.github/workflows/reusable-phpunit-tests-v3.yml index 34fffdfad4f99..7a51389765c75 100644 --- a/.github/workflows/reusable-phpunit-tests-v3.yml +++ b/.github/workflows/reusable-phpunit-tests-v3.yml @@ -165,9 +165,6 @@ jobs: - name: Install npm dependencies run: npm ci - - name: Build WordPress - run: npm run build:dev - - name: General debug information run: | npm --version diff --git a/.github/workflows/reusable-test-core-build-process.yml b/.github/workflows/reusable-test-core-build-process.yml index d4cd2e4bce89a..54db09f4fda4e 100644 --- a/.github/workflows/reusable-test-core-build-process.yml +++ b/.github/workflows/reusable-test-core-build-process.yml @@ -39,7 +39,6 @@ on: env: PUPPETEER_SKIP_DOWNLOAD: ${{ true }} - NODE_OPTIONS: --max-old-space-size=4096 # Disable permissions for all available scopes by default. # Any needed permissions should be configured at the job level. diff --git a/.github/workflows/reusable-test-gutenberg-build-process.yml b/.github/workflows/reusable-test-gutenberg-build-process.yml new file mode 100644 index 0000000000000..a0e74d6d00bf5 --- /dev/null +++ b/.github/workflows/reusable-test-gutenberg-build-process.yml @@ -0,0 +1,100 @@ +## +# A reusable workflow that tests the Gutenberg plugin build process when run within a wordpress-develop checkout. +## +name: Test the Gutenberg plugin Build Process + +on: + workflow_call: + inputs: + os: + description: 'Operating system to run tests on' + required: false + type: 'string' + default: 'ubuntu-24.04' + directory: + description: 'Directory to run WordPress from. Valid values are `src` or `build`' + required: false + type: 'string' + default: 'src' + +env: + GUTENBERG_DIRECTORY: ${{ inputs.directory == 'build' && 'build' || 'src' }}/wp-content/plugins/gutenberg + PUPPETEER_SKIP_DOWNLOAD: ${{ true }} + NODE_OPTIONS: '--max-old-space-size=8192' + +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + +jobs: + # Verifies that installing npm dependencies and building the Gutenberg plugin works as expected. + # + # Performs the following steps: + # - Checks out the repository. + # - Checks out the Gutenberg plugin into the plugins directory. + # - Sets up Node.js. + # - Logs debug information about the GitHub Action runner. + # - Installs Gutenberg npm dependencies. + # - Runs the Gutenberg build process. + # - Installs Core npm dependencies. + # - Builds WordPress to run from the relevant location (src or build). + # - Builds Gutenberg. + # - Ensures version-controlled files are not modified or deleted. + build-process-tests: + name: ${{ contains( inputs.os, 'macos-' ) && 'MacOS' || contains( inputs.os, 'windows-' ) && 'Windows' || 'Linux' }} + permissions: + contents: read + runs-on: ${{ inputs.os }} + timeout-minutes: 30 + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + persist-credentials: false + + - name: Checkout Gutenberg plugin + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: 'WordPress/gutenberg' + path: ${{ env.GUTENBERG_DIRECTORY }} + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version-file: '.nvmrc' + cache: npm + cache-dependency-path: | + package-lock.json + ${{ env.GUTENBERG_DIRECTORY }}/package-lock.json + + - name: Log debug information + run: | + npm --version + node --version + curl --version + git --version + + - name: Install Gutenberg Dependencies + run: npm ci + working-directory: ${{ env.GUTENBERG_DIRECTORY }} + + - name: Build Gutenberg + run: npm run build + working-directory: ${{ env.GUTENBERG_DIRECTORY }} + + - name: Install Core Dependencies + run: npm ci + + - name: Build WordPress to run from ${{ inputs.directory }} + run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }} + + - name: Run Gutenberg build script after building Core to run from ${{ inputs.directory }} + run: npm run build + working-directory: ${{ env.GUTENBERG_DIRECTORY }} + + - name: Ensure version-controlled files are not modified or deleted during building + run: git diff --exit-code diff --git a/.github/workflows/reusable-test-local-docker-environment-v1.yml b/.github/workflows/reusable-test-local-docker-environment-v1.yml index a9f2b448e4340..acdd7622f6136 100644 --- a/.github/workflows/reusable-test-local-docker-environment-v1.yml +++ b/.github/workflows/reusable-test-local-docker-environment-v1.yml @@ -120,9 +120,6 @@ jobs: - name: Install npm dependencies run: npm ci - - name: Build WordPress - run: npm run build:dev - - name: General debug information run: | npm --version diff --git a/.github/workflows/test-build-processes.yml b/.github/workflows/test-build-processes.yml index 150c36ef0893c..b33443367c846 100644 --- a/.github/workflows/test-build-processes.yml +++ b/.github/workflows/test-build-processes.yml @@ -32,6 +32,7 @@ on: # Confirm any changes to relevant workflow files. - '.github/workflows/test-build-processes.yml' - '.github/workflows/reusable-test-core-build-process.yml' + - '.github/workflows/reusable-test-gutenberg-build-process.yml' workflow_dispatch: # Cancels all previous workflow runs for pull requests that have not completed. @@ -97,13 +98,54 @@ jobs: os: ${{ matrix.os }} directory: ${{ matrix.directory }} + # Tests the Gutenberg plugin build process within a wordpress-develop checkout. + test-gutenberg-build-process: + name: Gutenberg running from ${{ matrix.directory }} + uses: ./.github/workflows/reusable-test-gutenberg-build-process.yml + permissions: + contents: read + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-24.04' ] + directory: [ 'src', 'build' ] + with: + os: ${{ matrix.os }} + directory: ${{ matrix.directory }} + + # Tests the Gutenberg plugin build process on additional operating systems. + # + # This is separate from the job above in order to use stricter conditions when determining when to test additional + # operating systems. This avoids unintentionally consuming excessive minutes. Windows-based jobs consume minutes at a + # 2x rate, and MacOS-based jobs at a 10x rate. + # See https://docs.github.com/en/billing/concepts/product-billing/github-actions#per-minute-rates. + # + # The `matrix` and `runner` contexts are not available for use within `if` expressions. So there is + # currently no way to determine the OS being used on a given job. + # See https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability. + test-gutenberg-build-process-additional-os: + name: Gutenberg running from ${{ matrix.directory }} + uses: ./.github/workflows/reusable-test-gutenberg-build-process.yml + permissions: + contents: read + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + strategy: + fail-fast: false + matrix: + os: [ 'macos-15', 'windows-2025' ] + directory: [ 'src', 'build' ] + with: + os: ${{ matrix.os }} + directory: ${{ matrix.directory }} + slack-notifications: name: Slack Notifications uses: ./.github/workflows/slack-notifications.yml permissions: actions: read contents: read - needs: [ test-core-build-process, test-core-build-process-additional-os ] + needs: [ test-core-build-process, test-core-build-process-additional-os, test-gutenberg-build-process, test-gutenberg-build-process-additional-os ] if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} with: calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }} diff --git a/.gitignore b/.gitignore index 901a775c5af23..01314e1a67139 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,6 @@ wp-tests-config.php /node_modules /npm-debug.log /build -/gutenberg /tests/phpunit/build /wp-cli.local.yml /jsdoc @@ -31,17 +30,15 @@ wp-tests-config.php /src/wp-admin/css/colors/*/*.css /src/wp-admin/js /src/wp-includes/assets/* +!/src/wp-includes/assets/script-loader-packages.min.php +!/src/wp-includes/assets/script-modules-packages.min.php /src/wp-includes/js /src/wp-includes/css/dist /src/wp-includes/css/*.min.css /src/wp-includes/css/*-rtl.css -/src/wp-includes/blocks/* -!/src/wp-includes/blocks/index.php -/src/wp-includes/build -/src/wp-includes/class-wp-block-parser.php -/src/wp-includes/class-wp-block-parser-block.php -/src/wp-includes/class-wp-block-parser-frame.php -/src/wp-includes/theme.json +/src/wp-includes/blocks/**/*.css +/src/wp-includes/blocks/**/*.js +/src/wp-includes/blocks/**/*.js.map /packagehash.txt /artifacts /setup.log diff --git a/Gruntfile.js b/Gruntfile.js index 708169a9b6f28..fd6e1f9051591 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -3,6 +3,7 @@ /* globals Set */ var webpackConfig = require( './webpack.config' ); var installChanged = require( 'install-changed' ); +var json2php = require( 'json2php' ); module.exports = function(grunt) { var path = require('path'), @@ -1278,14 +1279,6 @@ module.exports = function(grunt) { BUILD_DIR + 'wp-includes/js/dist/commands.js', ], dest: BUILD_DIR + 'wp-includes/js/dist/' - }, - { - expand: true, - flatten: true, - src: [ - BUILD_DIR + 'wp-includes/js/dist/vendor/**/*.js' - ], - dest: BUILD_DIR + 'wp-includes/js/dist/vendor/' } ] } @@ -1421,58 +1414,6 @@ module.exports = function(grunt) { grunt.task.run( 'wp-packages:refresh-deps' ); } ); - // Gutenberg integration tasks. - grunt.registerTask( 'gutenberg-checkout', 'Checks out the Gutenberg repository.', function() { - const done = this.async(); - grunt.util.spawn( { - cmd: 'node', - args: [ 'tools/gutenberg/checkout-gutenberg.js' ], - opts: { stdio: 'inherit' } - }, function( error ) { - done( ! error ); - } ); - } ); - - grunt.registerTask( 'gutenberg-build', 'Builds the Gutenberg repository.', function() { - const done = this.async(); - grunt.util.spawn( { - cmd: 'node', - args: [ 'tools/gutenberg/build-gutenberg.js' ], - opts: { stdio: 'inherit' } - }, function( error ) { - done( ! error ); - } ); - } ); - - grunt.registerTask( 'gutenberg-copy', 'Copies Gutenberg build output to WordPress Core.', function() { - const done = this.async(); - const buildDir = grunt.option( 'dev' ) ? 'src' : 'build'; - grunt.util.spawn( { - cmd: 'node', - args: [ 'tools/gutenberg/copy-gutenberg-build.js', `--build-dir=${ buildDir }` ], - opts: { stdio: 'inherit' } - }, function( error ) { - done( ! error ); - } ); - } ); - - grunt.registerTask( 'gutenberg-integrate', 'Complete Gutenberg integration workflow.', [ - 'gutenberg-build', - 'gutenberg-copy' - ] ); - - grunt.registerTask( 'copy-vendor-scripts', 'Copies vendor scripts from node_modules to wp-includes/js/dist/vendor/.', function() { - const done = this.async(); - const buildDir = grunt.option( 'dev' ) ? 'src' : 'build'; - grunt.util.spawn( { - cmd: 'node', - args: [ 'tools/vendors/copy-vendors.js', `--build-dir=${ buildDir }` ], - opts: { stdio: 'inherit' } - }, function( error ) { - done( ! error ); - } ); - } ); - grunt.renameTask( 'watch', '_watch' ); grunt.registerTask( 'watch', function() { @@ -1628,6 +1569,23 @@ module.exports = function(grunt) { } } ); + grunt.registerTask( 'copy:block-json', 'Copies block.json file contents to block-json.php.', function() { + var blocks = {}; + grunt.file.recurse( SOURCE_DIR + 'wp-includes/blocks', function( abspath, rootdir, subdir, filename ) { + if ( /^block\.json$/.test( filename ) ) { + blocks[ subdir ] = grunt.file.readJSON( abspath ); + } + } ); + grunt.file.write( + SOURCE_DIR + 'wp-includes/blocks/blocks-json.php', + '=20.10.0", @@ -106,11 +184,45 @@ "node": ">=6.0.0" } }, + "node_modules/@ariakit/core": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.14.tgz", + "integrity": "sha512-hpzZvyYzGhP09S9jW1XGsU/FD5K3BKsH1eG/QJ8rfgEeUdPS7BvHPt5lHbOeJ2cMrRzBEvsEzLi1ivfDifHsVA==" + }, + "node_modules/@ariakit/react": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.15.tgz", + "integrity": "sha512-0V2LkNPFrGRT+SEIiObx/LQjR6v3rR+mKEDUu/3tq7jfCZ+7+6Q6EMR1rFaK+XMkaRY1RWUcj/rRDWAUWnsDww==", + "dependencies": { + "@ariakit/react-core": "0.4.15" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ariakit" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@ariakit/react-core": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.15.tgz", + "integrity": "sha512-Up8+U97nAPJdyUh9E8BCEhJYTA+eVztWpHoo1R9zZfHd4cnBWAg5RHxEmMH+MamlvuRxBQA71hFKY/735fDg+A==", + "dependencies": { + "@ariakit/core": "0.4.14", + "@floating-ui/dom": "^1.0.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -209,7 +321,6 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", - "dev": true, "dependencies": { "@babel/parser": "^7.26.5", "@babel/types": "^7.26.5", @@ -225,7 +336,6 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -376,7 +486,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" @@ -474,7 +583,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -484,7 +592,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -531,7 +638,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.5" @@ -1973,7 +2079,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1983,7 +2088,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -1998,7 +2102,6 @@ "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", @@ -2016,7 +2119,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -2188,6 +2290,12 @@ "postcss-selector-parser": "^7.0.0" } }, + "node_modules/@date-fns/tz": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz", + "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==", + "license": "MIT" + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -2208,6 +2316,163 @@ "url": "https://github.com/sponsors/JounQin" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/cache": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "dependencies": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/css": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.10.6.tgz", + "integrity": "sha512-88Sr+3heKAKpj9PCqq5A1hAmAkoSIvwEq1O2TwDij7fUtsJpdkV4jMTISSTouFeRvsGvXIpuSuDQ4C1YdfNGXw==", + "dependencies": { + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "node_modules/@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/styled/node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.41.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", @@ -2343,6 +2608,46 @@ "resolved": "https://registry.npmjs.org/@financial-times/useragent_parser/-/useragent_parser-1.6.3.tgz", "integrity": "sha512-TlQiXt/vS5ZwY0V3salvlyQzIzMGZEyw9inmJA25A8heL2kBVENbToiEc64R6ETNf5YHa2lwnc2I7iNHP9SqeQ==" }, + "node_modules/@floating-ui/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", + "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "dependencies": { + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom/node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", + "dependencies": { + "@floating-ui/dom": "^1.6.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", + "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==", + "license": "MIT" + }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.2.tgz", @@ -3419,7 +3724,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -3428,7 +3732,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -3463,14 +3766,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -4008,12 +4309,150 @@ "node": ">=18" } }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.6.1.tgz", + "integrity": "sha512-95DXXJxNkpYu+sqmpDp7vbw9JCyiNpHuCsvuMuOgVFrKQlwEIn9Y1+NNIQJq+zFL+eWyxw6htthB5CtdwJupNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "anser": "^2.1.1", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "@types/webpack": "5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": "^5.0.0", + "webpack-dev-server": "^4.8.0 || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.24", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz", "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==", "dev": true }, + "node_modules/@preact/signals": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.2.tgz", + "integrity": "sha512-naxcJgUJ6BTOROJ7C3QML7KvwKwCXQJYTc5L/b0eEsdYgPB6SxwoQ1vDGcS0Q7GVjAenVq/tXrybVdFShHYZWg==", + "license": "MIT", + "dependencies": { + "@preact/signals-core": "^1.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": "10.x" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.12.1.tgz", + "integrity": "sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/@puppeteer/browsers": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz", @@ -4200,6 +4639,396 @@ "node": ">=12" } }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-spring/animated": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.1.tgz", + "integrity": "sha512-EX5KAD9y7sD43TnLeTNG1MgUVpuRO1YaSJRPawHNRgUWYfILge3s85anny4S4eTJGpdp5OoFV2kx9fsfeo0qsw==", + "dependencies": { + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.1.tgz", + "integrity": "sha512-8K9/FaRn5VvMa24mbwYxwkALnAAyMRdmQXrARZLcBW2vxLJ6uw9Cy3d06Z8M12kEqF2bDlccaCSDsn2bSz+Q4A==", + "dependencies": { + "@react-spring/animated": "~9.7.1", + "@react-spring/rafz": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.1.tgz", + "integrity": "sha512-JSsrRfbEJvuE3w/uvU3mCTuWwpQcBXkwoW14lBgzK9XJhuxmscGo59AgJUpFkGOiGAVXFBGB+nEXtSinFsopgw==" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.1.tgz", + "integrity": "sha512-R2kZ+VOO6IBeIAYTIA3C1XZ0ZVg/dDP5FKtWaY8k5akMer9iqf5H9BU0jyt3Qtxn0qQY7whQdf6MTcWtKeaawg==", + "dependencies": { + "@react-spring/rafz": "~9.7.1", + "@react-spring/types": "~9.7.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.1.tgz", + "integrity": "sha512-yBcyfKUeZv9wf/ZFrQszvhSPuDx6Py6yMJzpMnS+zxcZmhXPeOCKZSHwqrUz1WxvuRckUhlgb7eNI/x5e1e8CA==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.1.tgz", + "integrity": "sha512-6uUE5MyKqdrJnIJqlDN/AXf3i8PjOQzUuT26nkpsYxUGOk7c+vZVPcfrExLSoKzTb9kF0i66DcqzO5fXz/Z1AA==", + "dependencies": { + "@react-spring/animated": "~9.7.1", + "@react-spring/core": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4925,6 +5754,39 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@tannin/compile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", + "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", + "dependencies": { + "@tannin/evaluate": "^1.2.0", + "@tannin/postfix": "^1.1.0" + } + }, + "node_modules/@tannin/evaluate": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", + "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==" + }, + "node_modules/@tannin/plural-forms": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", + "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", + "dependencies": { + "@tannin/compile": "^1.1.0" + } + }, + "node_modules/@tannin/postfix": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", + "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==" + }, + "node_modules/@tannin/sprintf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@tannin/sprintf/-/sprintf-1.3.3.tgz", + "integrity": "sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==", + "license": "MIT" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -5090,6 +5952,17 @@ "@types/node": "*" } }, + "node_modules/@types/gradient-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/gradient-parser/-/gradient-parser-1.1.0.tgz", + "integrity": "sha512-SaEcbgQscHtGJ1QL+ajgDTmmqU2f6T+00jZRcFlVHUW2Asivc84LNUev/UQFyu117AsdyrtI+qpwLvgjJXJxmw==", + "license": "MIT" + }, + "node_modules/@types/highlight-words-core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/highlight-words-core/-/highlight-words-core-1.2.1.tgz", + "integrity": "sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==" + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -5188,11 +6061,15 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "node_modules/@types/mousetrap": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.11.tgz", + "integrity": "sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ==" + }, "node_modules/@types/node": { "version": "14.14.20", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", - "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", - "dev": true + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==" }, "node_modules/@types/node-forge": { "version": "1.3.11", @@ -5212,8 +6089,12 @@ "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/q": { "version": "1.5.4", @@ -5234,6 +6115,23 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/react": { + "version": "18.3.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", + "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", @@ -5277,6 +6175,15 @@ "@types/node": "*" } }, + "node_modules/@types/simple-peer": { + "version": "9.11.9", + "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.9.tgz", + "integrity": "sha512-6Gdl7TSS5oh9nuwKD4Pl8cSmaxWycYeZz9HLnJBNvIwWjZuGVsmHe9RwW3+9RxfhC1aIR9Z83DvaJoMw6rhkbg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sockjs": { "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", @@ -5569,6 +6476,22 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -5774,6 +6697,93 @@ } } }, + "node_modules/@wordpress/a11y": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/a11y/-/a11y-4.33.1.tgz", + "integrity": "sha512-W/MeUMZPSsgYnF6/0cXTYq1JBnCd22dBsWtYJw+Ujgx7s4h52LMnx/dIGE1Xi3XzT4nPUD1DvSw0U3lIMWW5Fg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/dom-ready": "^4.33.1", + "@wordpress/i18n": "^6.6.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/admin-ui": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wordpress/admin-ui/-/admin-ui-1.1.4.tgz", + "integrity": "sha512-AoAuc+YeFKO9bdHKgPqem3Z1viggsG/txOogFunu/RudDGmmhKbqSlUzvnAQIAP6imUI1xeWnaWSgbGqOeIvsg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^6.9.1", + "@wordpress/components": "^30.6.4", + "@wordpress/element": "^6.33.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/annotations": { + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/@wordpress/annotations/-/annotations-3.33.2.tgz", + "integrity": "sha512-lVpLQdct1svaSk3ptCO74Qf9hS9fKo5rIQo+k9PKZAIzC5GafVoimRFKqShxohNQE27P+2evJMk2+rLk6EeBAQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/data": "^10.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/rich-text": "^7.33.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/annotations/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/api-fetch": { + "version": "7.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-7.33.1.tgz", + "integrity": "sha512-kxk7Og2CZLOMUZtDfOXSGapem4ToP15JB24PfixJLS0dKfrlUBci4ShjJ3z3jdIx01gf1gfP4NFjqzicJKb+Rg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/i18n": "^6.6.1", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/autop": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/autop/-/autop-4.33.1.tgz", + "integrity": "sha512-X3DMHzAIB5lHC3vXrRiH4H+11uTrLU8PnsM5ykizk59/VgbNNRjSurvxHvM2/GM7geOxngDCDlNAz3foisnmHw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/babel-preset-default": { "version": "8.33.1", "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-8.33.1.tgz", @@ -5802,13 +6812,263 @@ "version": "6.9.1", "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-6.9.1.tgz", "integrity": "sha512-UCtTANAdym5jpTEZS17WHrKLu7R52gQRgKuwsRm5uZWUb4g4Vq8NX52CBIesF1viFyKfM++HpmteFkrL7p0SMg==", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, + "node_modules/@wordpress/blob": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/blob/-/blob-4.33.1.tgz", + "integrity": "sha512-3a0gY6+f1UcF82mbviSFzRDzQ8dEACwISkXNrwvV7Y70ke5F1UHWWkux4S15f7OcaeTs/L4SWTqZ0y5ufzHioA==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/block-directory": { + "version": "5.33.9", + "resolved": "https://registry.npmjs.org/@wordpress/block-directory/-/block-directory-5.33.9.tgz", + "integrity": "sha512-ZVmOo6O4a6pSDyUmIF99g8zsr+bKLK7/e3nd0WO7OF+xO7+L0HoSRiTVA7jtiyDFygxafSswNT79YLrRMtLG0A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/editor": "^14.33.9", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/plugins": "^7.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1", + "change-case": "^4.1.2", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/block-editor": { + "version": "15.6.7", + "resolved": "https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-15.6.7.tgz", + "integrity": "sha512-r/eKqxC0meRjvourvPq/fiYKa3CaDZMIb/26HjZJKAyb/FvU9yimeV8i9LAN0jXNND2AjACrV+2rMOhV5tHPcA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "@react-spring/web": "^9.4.5", + "@wordpress/a11y": "^4.33.1", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-serialization-default-parser": "^5.33.1", + "@wordpress/blocks": "^15.6.2", + "@wordpress/commands": "^1.33.4", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/date": "^5.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/escape-html": "^3.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/interactivity": "^6.33.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/preferences": "^4.33.4", + "@wordpress/priority-queue": "^3.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/style-engine": "^2.33.1", + "@wordpress/token-list": "^3.33.1", + "@wordpress/upload-media": "^0.18.4", + "@wordpress/url": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "@wordpress/wordcount": "^4.33.1", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "deepmerge": "^4.3.0", + "diff": "^4.0.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "parsel-js": "^1.1.2", + "postcss": "^8.4.21", + "postcss-prefix-selector": "^1.16.0", + "postcss-urlrebase": "^1.4.0", + "react-autosize-textarea": "^7.1.0", + "react-easy-crop": "^5.0.6", + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/block-library": { + "version": "9.33.8", + "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-9.33.8.tgz", + "integrity": "sha512-7rGpAKbiKsG72xk7vckb8uxJfHjbOnb3VjEEf9Ot9Iw72A2P/b6MsSQO7j93LEC55PNhTTKsJ+59c6VK7OXoSg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/autop": "^4.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/date": "^5.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/escape-html": "^3.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/interactivity": "^6.33.1", + "@wordpress/interactivity-router": "^2.33.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/latex-to-mathml": "^1.1.2", + "@wordpress/notices": "^5.33.1", + "@wordpress/patterns": "^2.33.7", + "@wordpress/primitives": "^4.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/reusable-blocks": "^5.33.7", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/server-side-render": "^6.9.4", + "@wordpress/url": "^4.33.1", + "@wordpress/viewport": "^6.33.1", + "@wordpress/wordcount": "^4.33.1", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "escape-html": "^1.0.3", + "fast-average-color": "^9.1.1", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/block-library/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/block-serialization-default-parser": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/block-serialization-default-parser/-/block-serialization-default-parser-5.33.1.tgz", + "integrity": "sha512-qzkF9t6JAklS38WHrHSN6N/cbJe8FRnIsjDCLYrfH3dSrEcxrbctJa7mY9urqqCKuUVjWdOszPU/1mkZR0jh5w==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/blocks": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/@wordpress/blocks/-/blocks-15.6.2.tgz", + "integrity": "sha512-A8b7dBiarUjr8CEoVpbqyDnsmlhFRQgQhsySdIr3j9aImVzpVFGn/htoO+0Axj37zK9LNkNEeod4w7/COtrUCQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/autop": "^4.33.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-serialization-default-parser": "^5.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/shortcode": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "change-case": "^4.1.2", + "colord": "^2.7.0", + "fast-deep-equal": "^3.1.3", + "hpq": "^1.3.0", + "is-plain-object": "^5.0.0", + "memize": "^2.1.0", + "react-is": "^18.3.0", + "remove-accents": "^0.5.0", + "showdown": "^1.9.1", + "simple-html-tokenizer": "^0.5.7", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/blocks/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@wordpress/browserslist-config": { "version": "6.33.1", "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-6.33.1.tgz", @@ -5820,6 +7080,360 @@ "npm": ">=8.19.2" } }, + "node_modules/@wordpress/commands": { + "version": "1.33.4", + "resolved": "https://registry.npmjs.org/@wordpress/commands/-/commands-1.33.4.tgz", + "integrity": "sha512-RunvR3cv+vvAm9g04ikHcb36ZX25dpfQgUSJMVNwaEfNPcQV5BtWjR+7RhRva9hwTlDeOzoL6WmPXb0PtKVPuA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^6.9.1", + "@wordpress/components": "^30.6.4", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "clsx": "^2.1.1", + "cmdk": "^1.0.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/components": { + "version": "30.6.4", + "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-30.6.4.tgz", + "integrity": "sha512-D/NYNnoXx9BdH8w9E65BaTRh5T/mgeJjpkxQ5PsFEkU/QIVh0jfsS921U3jMA2S0piwULe2hCzXH8SehawGu7Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ariakit/react": "^0.4.15", + "@emotion/cache": "^11.7.1", + "@emotion/css": "^11.7.1", + "@emotion/react": "^11.7.1", + "@emotion/serialize": "^1.0.2", + "@emotion/styled": "^11.6.0", + "@emotion/utils": "^1.0.0", + "@floating-ui/react-dom": "2.0.8", + "@types/gradient-parser": "1.1.0", + "@types/highlight-words-core": "1.2.1", + "@use-gesture/react": "^10.3.1", + "@wordpress/a11y": "^4.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/compose": "^7.33.1", + "@wordpress/date": "^5.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/escape-html": "^3.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/primitives": "^4.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/warning": "^3.33.1", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "date-fns": "^3.6.0", + "deepmerge": "^4.3.0", + "fast-deep-equal": "^3.1.3", + "framer-motion": "^11.15.0", + "gradient-parser": "1.1.1", + "highlight-words-core": "^1.2.2", + "is-plain-object": "^5.0.0", + "memize": "^2.1.0", + "path-to-regexp": "^6.2.1", + "re-resizable": "^6.4.0", + "react-colorful": "^5.3.1", + "react-day-picker": "^9.7.0", + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/components/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/compose": { + "version": "7.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-7.33.1.tgz", + "integrity": "sha512-1satS+7EKlzZOCR++uP8mAy3BJPKX2eeTZHVW3669n0xM1xdmzl9JXyEbtEqaFVYhI3dHTq5kLwrm+aSpn0zag==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@types/mousetrap": "^1.6.8", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/priority-queue": "^3.33.1", + "@wordpress/undo-manager": "^1.33.1", + "change-case": "^4.1.2", + "clipboard": "^2.0.11", + "mousetrap": "^1.6.5", + "use-memo-one": "^1.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/core-commands": { + "version": "1.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/core-commands/-/core-commands-1.33.7.tgz", + "integrity": "sha512-hjAu6MP6WiTg+Ai/40hswT3qLKZMXc34z3tWZ5iagAKHH5vVqfbGhNJauNyXK/Tftfq1yCFBDZGZ5Tq2bP9s4A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/block-editor": "^15.6.7", + "@wordpress/commands": "^1.33.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/router": "^1.33.1", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/core-data": { + "version": "7.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/core-data/-/core-data-7.33.7.tgz", + "integrity": "sha512-i7r1hMKPs2Z/inK8SUQ44uIwpqSVNlXPliq8Ov4p3DN44xBz0TyN7hKu4mKe61PFrQxv0rwkqXBVRj04I4JieA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/sync": "^1.33.1", + "@wordpress/undo-manager": "^1.33.1", + "@wordpress/url": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "change-case": "^4.1.2", + "equivalent-key-map": "^0.2.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/core-data/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/customize-widgets": { + "version": "5.33.8", + "resolved": "https://registry.npmjs.org/@wordpress/customize-widgets/-/customize-widgets-5.33.8.tgz", + "integrity": "sha512-Nf5oL/3wDzU8FicSq2/h19MPt7aLvFGsZ9j3MXpn9zbiUSYBG7zTrch1d0bUm2RGT7Y65XRbiFPUtjTeLl96+Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/block-library": "^9.33.8", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/interface": "^9.18.4", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/media-utils": "^5.33.1", + "@wordpress/preferences": "^4.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/widgets": "^4.33.7", + "clsx": "^2.1.1", + "fast-deep-equal": "^3.1.3" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/data": { + "version": "10.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/data/-/data-10.33.1.tgz", + "integrity": "sha512-Y+GlNYFds2ICgkAfwT3UsLCXlagibtUFADBf/UXmTgEvc07/O/lOBHeIW72BiRkb/O4oCqf2ZeXgGkNgJLlyiQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/compose": "^7.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "@wordpress/priority-queue": "^3.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/redux-routine": "^5.33.1", + "deepmerge": "^4.3.0", + "equivalent-key-map": "^0.2.2", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "redux": "^5.0.1", + "rememo": "^4.0.2", + "use-memo-one": "^1.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/data-controls": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-4.33.1.tgz", + "integrity": "sha512-+gD47q6WuZ2MYMxwUBwBTYACMayrZoyG6W6OR1Q2ggOfkmoQb4OlxEWJPdCIC8GxJJwVh8ej9HjzzI3S/tDsJg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/dataviews": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/dataviews/-/dataviews-10.1.6.tgz", + "integrity": "sha512-hDACJEzCSSJxpxvxEXHd7Gh3BzfUMkaB98QVqzZK6rQ+aXcRYCj3J1LruT0ku+FCB2MAcrTjLdmc7Sw/jqtajw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ariakit/react": "^0.4.15", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/date": "^5.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/primitives": "^4.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "date-fns": "^4.1.0", + "deepmerge": "4.3.1", + "fast-deep-equal": "^3.1.3", + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/dataviews/node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/@wordpress/date": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/date/-/date-5.33.1.tgz", + "integrity": "sha512-8M25DKrC39v3IgjWScy722NiNYdlodjUawjLJBjdtaO73ZEtPXrWVocT+HKFqDVAoTGqF/J43IFxxW020+udXA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/deprecated": "^4.33.1", + "moment": "^2.29.4", + "moment-timezone": "^0.5.40" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/dependency-extraction-webpack-plugin": { "version": "6.33.1", "resolved": "https://registry.npmjs.org/@wordpress/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-6.33.1.tgz", @@ -5844,6 +7458,42 @@ "dev": true, "license": "BSD" }, + "node_modules/@wordpress/deprecated": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.33.1.tgz", + "integrity": "sha512-dDOGfYtebSj0iSmOAJD7HiqXacx6lLJZkhRKPeffXG8e990EBVa2qgcRt2jcQHaSO/h9gmOsGmC7trEG66YzMA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/hooks": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/dom": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-4.33.1.tgz", + "integrity": "sha512-1ow6ikYbE+p2xMCykZecGqRmZBqz0Z90KQ06EbKFr9tJ9tSgp05Jm6J7Op3VclJxJ+6as5js+28ppps3eVzGcg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/deprecated": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/dom-ready": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-4.33.1.tgz", + "integrity": "sha512-jrHN/arTKp2iuYj24byFgabBhZsZ3WUXCSKT16d/1MZUXGQt876XXu6r5rwpLtnVsX2gFiZ/DzdRKCL4RV9Wpg==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/e2e-test-utils-playwright": { "version": "1.33.2", "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-1.33.2.tgz", @@ -5895,6 +7545,269 @@ "node": ">=10.0.0" } }, + "node_modules/@wordpress/edit-post": { + "version": "8.33.9", + "resolved": "https://registry.npmjs.org/@wordpress/edit-post/-/edit-post-8.33.9.tgz", + "integrity": "sha512-Oix8XpI93B5KPlVyI8JUwPpTcu21M1fV3PTDo4IpEMN3wOxjSa4BquKyGCmN0DqhXlxVUYiFYU/FdP3f/G+Whg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/admin-ui": "^1.1.4", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/block-library": "^9.33.8", + "@wordpress/blocks": "^15.6.2", + "@wordpress/commands": "^1.33.4", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/editor": "^14.33.9", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/plugins": "^7.33.4", + "@wordpress/preferences": "^4.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1", + "@wordpress/viewport": "^6.33.1", + "@wordpress/warning": "^3.33.1", + "@wordpress/widgets": "^4.33.7", + "clsx": "^2.1.1", + "memize": "^2.1.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/edit-site": { + "version": "6.33.9", + "resolved": "https://registry.npmjs.org/@wordpress/edit-site/-/edit-site-6.33.9.tgz", + "integrity": "sha512-8dkNDoJY1abBe964ODdM/+Xi44S+7s5flCnPdz9RvGOaAeZWq4WYNGgsljlNP43wzPr8Eq+iPkqjbzpx3bInfA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@react-spring/web": "^9.4.5", + "@wordpress/a11y": "^4.33.1", + "@wordpress/admin-ui": "^1.1.4", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/block-library": "^9.33.8", + "@wordpress/blocks": "^15.6.2", + "@wordpress/commands": "^1.33.4", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/dataviews": "^10.1.6", + "@wordpress/date": "^5.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/editor": "^14.33.9", + "@wordpress/element": "^6.33.1", + "@wordpress/escape-html": "^3.33.1", + "@wordpress/fields": "^0.25.9", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/media-utils": "^5.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/patterns": "^2.33.7", + "@wordpress/plugins": "^7.33.4", + "@wordpress/preferences": "^4.33.4", + "@wordpress/primitives": "^4.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/reusable-blocks": "^5.33.7", + "@wordpress/router": "^1.33.1", + "@wordpress/style-engine": "^2.33.1", + "@wordpress/url": "^4.33.1", + "@wordpress/viewport": "^6.33.1", + "@wordpress/views": "^1.0.7", + "@wordpress/widgets": "^4.33.7", + "@wordpress/wordcount": "^4.33.1", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.9.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "react-autosize-textarea": "^7.1.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/edit-widgets": { + "version": "6.33.8", + "resolved": "https://registry.npmjs.org/@wordpress/edit-widgets/-/edit-widgets-6.33.8.tgz", + "integrity": "sha512-SFsvQwMwu15WYUemUug0K9ITWIFx46CoDBAYyAbRV7Jy+torSoCrq8VjkiZsal7KYMhDJ/25ectvi4TYV/DOZQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/block-library": "^9.33.8", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/interface": "^9.18.4", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/media-utils": "^5.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/patterns": "^2.33.7", + "@wordpress/plugins": "^7.33.4", + "@wordpress/preferences": "^4.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/reusable-blocks": "^5.33.7", + "@wordpress/url": "^4.33.1", + "@wordpress/widgets": "^4.33.7", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/editor": { + "version": "14.33.9", + "resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-14.33.9.tgz", + "integrity": "sha512-E1OU5u6PxCOHKxNOl1xWU3tjrsjWGYbaN77u5k0OfL3jGonOmL+XV+GO2Uh50m+/+eKr/9fReQoBv5erIseTEA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@floating-ui/react-dom": "2.0.8", + "@wordpress/a11y": "^4.33.1", + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/commands": "^1.33.4", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/dataviews": "^10.1.6", + "@wordpress/date": "^5.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/dom": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/fields": "^0.25.9", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/interface": "^9.18.4", + "@wordpress/keyboard-shortcuts": "^5.33.1", + "@wordpress/keycodes": "^4.33.1", + "@wordpress/media-utils": "^5.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/patterns": "^2.33.7", + "@wordpress/plugins": "^7.33.4", + "@wordpress/preferences": "^4.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/reusable-blocks": "^5.33.7", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/server-side-render": "^6.9.4", + "@wordpress/url": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "@wordpress/wordcount": "^4.33.1", + "change-case": "^4.1.2", + "client-zip": "^2.4.5", + "clsx": "^2.1.1", + "date-fns": "^3.6.0", + "deepmerge": "^4.3.0", + "fast-deep-equal": "^3.1.3", + "is-plain-object": "^5.0.0", + "memize": "^2.1.0", + "react-autosize-textarea": "^7.1.0", + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/editor/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/element": { + "version": "6.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-6.33.1.tgz", + "integrity": "sha512-8Y2TEkduT1cAGVfh5HoERpJIVvCcfHI1k+PGgG3wzy85me6hjgA/P7l90yBt/9i9Omt5+buGfnklobstECR8zg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "@wordpress/escape-html": "^3.33.1", + "change-case": "^4.1.2", + "is-plain-object": "^5.0.0", + "react": "^18.3.0", + "react-dom": "^18.3.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/escape-html": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-3.33.1.tgz", + "integrity": "sha512-HMBYhNta/2UwopSwwZRD4MvmDOHd9VaxjHS40ay6riPOZk47BkN7ntbnYm9I/vC66Pw1btH+rnhvf8zvtkjm2A==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/eslint-plugin": { "version": "22.19.1", "resolved": "https://registry.npmjs.org/@wordpress/eslint-plugin/-/eslint-plugin-22.19.1.tgz", @@ -5955,6 +7868,200 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@wordpress/fields": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@wordpress/fields/-/fields-0.25.9.tgz", + "integrity": "sha512-HOpF3NGSiy3AmmnW4THvVvR0JQ0Q9GWUkMxxpFkouPsKJKPE6TntlCYqGPjEobmHh9qNbUPFIRevCD4xpAK5Aw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/dataviews": "^10.1.6", + "@wordpress/date": "^5.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/media-utils": "^5.33.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/patterns": "^2.33.7", + "@wordpress/primitives": "^4.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/router": "^1.33.1", + "@wordpress/url": "^4.33.1", + "@wordpress/warning": "^3.33.1", + "change-case": "4.1.2", + "client-zip": "^2.4.5", + "clsx": "2.1.1", + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/format-library": { + "version": "5.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/format-library/-/format-library-5.33.7.tgz", + "integrity": "sha512-t8QJP7CKWEUvRhyQEI4nbYVYg19W0FN+3EmpzlxNSI5qahDsWH/8B+NilrT7Uclym+pMRk40WE2eHFAj02Twvg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/latex-to-mathml": "^1.1.2", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/rich-text": "^7.33.2", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/hooks": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.33.1.tgz", + "integrity": "sha512-p9RbNsZJnsGY45MEV3QfYHS4dMmKe0B1f/RUXEL8ZLa36aUWZrUX7PJxvmmpeuPrboHQwT4MDps9kwHO4V6GVg==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/html-entities": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-4.33.1.tgz", + "integrity": "sha512-HdpnRRvTMstX58U4Yr+UisIrFLcG97PGegAczMxeq9Q1n3ol5FCkEegBTQIJffAZ5IadBsPZ77fjoVtLK7RViQ==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/i18n": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.6.1.tgz", + "integrity": "sha512-aEFSF+5dp0UhdMGHyNUwhcL0Sg/kp0NtCSMrfcQrXRM6uD/+y8ih0mHeULww5V919NUrzXIZSZGfOaOIiQVXXg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.33.1", + "gettext-parser": "^1.3.1", + "memize": "^2.1.0", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/icons": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-11.0.1.tgz", + "integrity": "sha512-vXkWiAxwDjWBcj72oXbJyuDtIvNvk1JnnmYzQUpIjKjvScRPcj+Kt40nFYk/5kPnNAhBqVNcZ7tWK7NctSslJA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/element": "^6.33.1", + "@wordpress/primitives": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/interactivity": { + "version": "6.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/interactivity/-/interactivity-6.33.1.tgz", + "integrity": "sha512-MSnOhE7oMlFYWhRrw56j0NS5L8d2hltiKLz1+YP5aHX75MVH3rH00ULqFshlRfHrhqFXlEufmKRoQBD7g3MMHQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@preact/signals": "^1.3.0", + "preact": "^10.24.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/interactivity-router": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/interactivity-router/-/interactivity-router-2.33.1.tgz", + "integrity": "sha512-j+JfkwkwEylFWk24wYsIo0V6Jd7bonmnwryI1G7Vh0h8buV7XaCvakmItQ7PUliIKA7SRQPNcoFjSrsca719tw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/interactivity": "^6.33.1", + "es-module-lexer": "^1.5.4" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/interface": { + "version": "9.18.4", + "resolved": "https://registry.npmjs.org/@wordpress/interface/-/interface-9.18.4.tgz", + "integrity": "sha512-dm882d3Jvy+/ItaJvB3G4GUTHQPs9zsgnxSRNoHAaBz1G+wwueD0trxGcjzgW90jbc/qacKQCJ0rPQfnGWJ9/A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/admin-ui": "^1.1.4", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/plugins": "^7.33.4", + "@wordpress/preferences": "^4.33.4", + "@wordpress/viewport": "^6.33.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/is-shallow-equal": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-5.33.1.tgz", + "integrity": "sha512-QMOwATwFjFr6Z9geS8EjuEVGN0gkpANypjqIBE8iTDtfKhY99LTtxbTaguviqKfVP7l73v1B0GJfHtkPExhJkA==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/jest-console": { "version": "8.33.1", "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-8.33.1.tgz", @@ -5991,6 +8098,108 @@ "jest": ">=29" } }, + "node_modules/@wordpress/keyboard-shortcuts": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/keyboard-shortcuts/-/keyboard-shortcuts-5.33.1.tgz", + "integrity": "sha512-ql+qQ+AW9rnaS6jBv3J5MT8ku0qijAYCq6rIvfEiA1W84i5+LB9JYxxzrFH8v5uGU4ZjqqRQEmcDd+lorlT4Vg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/keycodes": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/keycodes": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-4.33.1.tgz", + "integrity": "sha512-acuH0ogiY92ClslUpezZyEzfm1Ubx2bftevn/PxbsVq52UCOu14CAKgnO9sYqVuMpXT+zXveRMySixyKHB1wnA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/i18n": "^6.6.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/latex-to-mathml": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/latex-to-mathml/-/latex-to-mathml-1.1.2.tgz", + "integrity": "sha512-+nTj1Lw/jOyIaYCRfqFlIGxAjxwRg5dTkgSxgtB53wtGGv0kieeeHDLVJdO/C/yU04pAStHMT+25Oi4DXUKRBw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "temml": "^0.10.33" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/list-reusable-blocks": { + "version": "5.33.4", + "resolved": "https://registry.npmjs.org/@wordpress/list-reusable-blocks/-/list-reusable-blocks-5.33.4.tgz", + "integrity": "sha512-Szfb9AMHzjVK+ITj0HzDHXowaqLiVh/Y3rDcmpmQOhhVWTabEea1ls00aFjOWRpa9k6jm+7vqYtAEnWd2bIlLQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "change-case": "^4.1.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/media-utils": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/media-utils/-/media-utils-5.33.1.tgz", + "integrity": "sha512-Ty4gPDoKesy3nTu6b2nU2bee1Vqk90Cf1MHsoalo+6lw/UDlvX+RsogUzTVwUH9n2jG4rYQFPZY1KI/1pxj1rg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/private-apis": "^1.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/notices": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/notices/-/notices-5.33.1.tgz", + "integrity": "sha512-bvw97KGiToFZv9/EHPhom2va7pDXCUR2BNfSuxT3lSAt1tX5DUD5i1+6aa5TIybSAtZNGisCySH4fL/paMDMjQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/data": "^10.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/@wordpress/npm-package-json-lint-config": { "version": "5.33.1", "resolved": "https://registry.npmjs.org/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-5.33.1.tgz", @@ -6005,6 +8214,85 @@ "npm-package-json-lint": ">=6.0.0" } }, + "node_modules/@wordpress/nux": { + "version": "9.33.4", + "resolved": "https://registry.npmjs.org/@wordpress/nux/-/nux-9.33.4.tgz", + "integrity": "sha512-bXGRX4uMrR0bWciCkzXYxClCvFGBUUMs2qUlxbIBdgKxiEbLKY6xpfdroRZHnDzDhE5tr7D1t5Zc3a0gxmQX7g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^6.9.1", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/patterns": { + "version": "2.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/patterns/-/patterns-2.33.7.tgz", + "integrity": "sha512-dq2sCLNK1WWDhCpIfy65e3Z4Eyd9EXe5hE588TuaOmOHhU7uJBcpZnNKOJOBE8Cl9xR43Q8/l60f/nYKsOWiKA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/html-entities": "^4.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/plugins": { + "version": "7.33.4", + "resolved": "https://registry.npmjs.org/@wordpress/plugins/-/plugins-7.33.4.tgz", + "integrity": "sha512-1FBLXXOaS27sCqbeaMd8QNgK8Utr0tJtqakKRQQrsKxuOBL6oncMbqsRkq68TVZF/rGOflzcXhaHhwqLylD8iw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/hooks": "^4.33.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/is-shallow-equal": "^5.33.1", + "memize": "^2.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/postcss-plugins-preset": { "version": "5.33.1", "resolved": "https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-5.33.1.tgz", @@ -6024,6 +8312,46 @@ "postcss": "^8.0.0" } }, + "node_modules/@wordpress/preferences": { + "version": "4.33.4", + "resolved": "https://registry.npmjs.org/@wordpress/preferences/-/preferences-4.33.4.tgz", + "integrity": "sha512-WfAKKTWbWVPvNFerwrgQtjWxLMq2Kuj4J6mxK/NwBCzu3dWQZXVMlrzuEx8NA4VgKOzGV00a1Jqr9/HUX7DwCQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/private-apis": "^1.33.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/preferences-persistence": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/preferences-persistence/-/preferences-persistence-2.33.1.tgz", + "integrity": "sha512-AqMq1eiCqmwRkMqhn9EUjjd9IkCPZjPaQiYDTmISoL5wLcOrUS3rtnJsuvL3kYWJY8LYuETWJJg/bEQb79QlSg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/prettier-config": { "version": "4.33.1", "resolved": "https://registry.npmjs.org/@wordpress/prettier-config/-/prettier-config-4.33.1.tgz", @@ -6038,6 +8366,138 @@ "prettier": ">=3" } }, + "node_modules/@wordpress/primitives": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-4.33.1.tgz", + "integrity": "sha512-CVdk+tyyGVB4ube6O/uS9BgdDly2imImqE6SM/Aa5N4O6BI6mIgLhLQoKqj7WBKIdI0qTMndyGHfqqoUWBD5wA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/element": "^6.33.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/priority-queue": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-3.33.1.tgz", + "integrity": "sha512-m3S+bfVIGmDHVrCzTdQu5oHP6aBIM0pf5AYVpfdA2addJHLICtAMrPYdD+4MXekh8a38DzPekZa03vGv3ws3zQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "requestidlecallback": "^0.3.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/private-apis": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/private-apis/-/private-apis-1.33.1.tgz", + "integrity": "sha512-7y6nbTMu8C7XdRPV0YJnNVBnfYJ9Ioa5cPxR6TxTkbxxK/xrdQwnrRJRLXrSQ8SOE+WIsuGHe9n7IYDJy0W0aw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/redux-routine": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-5.33.1.tgz", + "integrity": "sha512-PdoYe5+78U3JcBVxFa/vxOAJ7ahdQTqr3/25WACRB/bHreeN/3r1CE1YaUiBTUFBVpu4iWQVojFswjkNlSG36w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "rungen": "^0.3.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "redux": ">=4" + } + }, + "node_modules/@wordpress/reusable-blocks": { + "version": "5.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/reusable-blocks/-/reusable-blocks-5.33.7.tgz", + "integrity": "sha512-APZVYydkXtfYDaWRPX7BgXEeog/uhm+XAQWJL+kbTFLWVamCQq0bnhEuD4Pi53Yz7XZRBvw8tzEQqm0cm2YWaw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/notices": "^5.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/rich-text": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-7.33.2.tgz", + "integrity": "sha512-jy8DPBN6f0WeQM1jL+yGX29xHgzDdyrGoXYEGrGt2ngpGYMca2ZrG9ZLcpQlU6S3sLV/n1jtjZntWrFFYRzgQA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/a11y": "^4.33.1", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/escape-html": "^3.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/keycodes": "^4.33.1", + "colord": "2.9.3", + "memize": "^2.1.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/router": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/router/-/router-1.33.1.tgz", + "integrity": "sha512-QuC4D4zyPcMJDcZOjXVtl6XhXQ9I8urwgXTPDBIzK6I+jad7tJw54d+X8aEKMP5Ce4NoyegOZY7GaqX4DMjPww==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/compose": "^7.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1", + "history": "^5.3.0", + "route-recognizer": "^0.3.4" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/@wordpress/scripts": { "version": "30.26.2", "resolved": "https://registry.npmjs.org/@wordpress/scripts/-/scripts-30.26.2.tgz", @@ -7243,6 +9703,57 @@ "node": ">=8" } }, + "node_modules/@wordpress/server-side-render": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-6.9.4.tgz", + "integrity": "sha512-/2z7nA5eZ6rW54f0LtjYMmFIY5LKnAw3jOjQKLyQ2sZD0OrKe7byfSRcO1pIAmAaQbwry8fI6+hsREAM841xxA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/deprecated": "^4.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/url": "^4.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/shortcode": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/shortcode/-/shortcode-4.33.1.tgz", + "integrity": "sha512-NEcIcHYc5C7egdTUYWZoCuRb8rccuPZTPQRYjg2UuV/eH56EPzsMpl9iRfBDQQyp575zLDOqwdnRog8v4Ni2Zw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "memize": "^2.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/style-engine": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/style-engine/-/style-engine-2.33.1.tgz", + "integrity": "sha512-S55fZu1Zp8NpvsSz9q990hgcbbfQB6unHTljOxneYrHVe4R0oSy0POOk/ngLqbDJEhcantgCUbbLWdZKnAYsPg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "change-case": "^4.1.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/stylelint-config": { "version": "23.25.1", "resolved": "https://registry.npmjs.org/@wordpress/stylelint-config/-/stylelint-config-23.25.1.tgz", @@ -7263,11 +9774,181 @@ "stylelint-scss": "^6.4.0" } }, + "node_modules/@wordpress/sync": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/sync/-/sync-1.33.1.tgz", + "integrity": "sha512-N1O8lTO+NvRI9A2WjWBGAg67XbaQUkGhT+cR3j1PuhUB7IxQHXZiZy0xW/eDiM76U/VMZ3wteOuu6ufgCv3VJQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@types/simple-peer": "^9.11.5", + "@wordpress/hooks": "^4.33.1", + "@wordpress/url": "^4.33.1", + "import-locals": "^2.0.0", + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-indexeddb": "~9.0.11", + "y-protocols": "^1.0.5", + "y-webrtc": "~10.2.5", + "yjs": "~13.6.6" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/token-list": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/token-list/-/token-list-3.33.1.tgz", + "integrity": "sha512-q89DOrcCL7o6ezCCkM4tD5sPV6rV7IosaMa+FH5qT2OK+++wFBGQsojgxyRZCm+tln7m2As58OJOBsmO9J458Q==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/undo-manager": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/undo-manager/-/undo-manager-1.33.1.tgz", + "integrity": "sha512-oIaZFjPSIy78ELLEdiQZDr68SRfsbr7WnrBX3V6GDZ3WEzhW7qKodQ0RiXn9vpwaax4fEobsW/z7j7D/pY6+Aw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/is-shallow-equal": "^5.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/upload-media": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/@wordpress/upload-media/-/upload-media-0.18.4.tgz", + "integrity": "sha512-/slxbD9v3XrYSPTaqCtQ0NqmyeLSBKU43Dk/7M2QOSww2i7ih3tBYU3Lym9QIyr08TZASY/LUY84Rli369WY0w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/blob": "^4.33.1", + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/preferences": "^4.33.4", + "@wordpress/private-apis": "^1.33.1", + "@wordpress/url": "^4.33.1", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/upload-media/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@wordpress/url": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-4.33.1.tgz", + "integrity": "sha512-t4MKPofYLHTIVE+NV36WBmlnzHsnZFkXsACdu/InF0u5pmyc/ZgXmq44qi6h/PmbGoUKnRQisulMIvGfEVBTeA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/viewport": { + "version": "6.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/viewport/-/viewport-6.33.1.tgz", + "integrity": "sha512-UmXx/UhJZqRYYCj+ZbG2XpObUa/UP2ydxC7hAVj3uc/xYrB8M3OOcYnQ+WQejAoyNs4sTe6VpzDZRn/rdcExMw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/compose": "^7.33.1", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@wordpress/views": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@wordpress/views/-/views-1.0.7.tgz", + "integrity": "sha512-rYMKl1+vRIR2u627P9kkyUgEwRuUlEGCUkikHugek7WiayhMzuNqBQhbgb2rNIp7LHjt5kjVGwZ6sZ+qXNAwmg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/data": "^10.33.1", + "@wordpress/dataviews": "^10.1.6", + "@wordpress/element": "^6.33.1", + "@wordpress/preferences": "^4.33.4", + "dequal": "^2.0.3" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/warning": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-3.33.1.tgz", "integrity": "sha512-ciDPM0AEu1s3xjDUwiTRxWiY0sTKTXI4R8NYO57g9+RuP4M5JnLK5/mdLVFCiWNo27tkUPFAgzHop7ssj3inew==", - "dev": true, + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/widgets": { + "version": "4.33.7", + "resolved": "https://registry.npmjs.org/@wordpress/widgets/-/widgets-4.33.7.tgz", + "integrity": "sha512-UlFtCJWWCGwgvqxdRGA5g9n785GbdERgzIrYeI77l2+NLX81UFGBOwLfMittEPPXTrt2JLQ8/jIKUYTKNtbdtA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/api-fetch": "^7.33.1", + "@wordpress/base-styles": "^6.9.1", + "@wordpress/block-editor": "^15.6.7", + "@wordpress/blocks": "^15.6.2", + "@wordpress/components": "^30.6.4", + "@wordpress/compose": "^7.33.1", + "@wordpress/core-data": "^7.33.7", + "@wordpress/data": "^10.33.1", + "@wordpress/element": "^6.33.1", + "@wordpress/i18n": "^6.6.1", + "@wordpress/icons": "^11.0.1", + "@wordpress/notices": "^5.33.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@wordpress/wordcount": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@wordpress/wordcount/-/wordcount-4.33.1.tgz", + "integrity": "sha512-Qg9+Ah9rEH8vOZAThF8CQS+TrWOmpKbGtRy+ZgLghc+mr2FGpyal3hwsoS3yFW6CUSf23YTWw2k2osEeTf2erQ==", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -7449,6 +10130,13 @@ "ajv": "^6.9.1" } }, + "node_modules/anser": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/anser/-/anser-2.3.2.tgz", + "integrity": "sha512-PMqBCBvrOVDRqLGooQb+z+t1Q0PiPyurUQeZRR5uHBOVZcW8B04KMmnT12USnhpNX2wCPagWzLVppQMUG3u0Dw==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -7510,11 +10198,18 @@ "ansi-html": "bin/ansi-html" } }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -7607,6 +10302,17 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -8006,6 +10712,11 @@ "postcss": "^8.1.0" } }, + "node_modules/autosize": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.4.tgz", + "integrity": "sha512-5yxLQ22O0fCRGoxGfeLSNt3J8LB1v+umtpMnPW6XjkTWXKoN0AmXAIhelJcDtFT/Y/wYWmfE+oqU10Q0b8FhaQ==" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -8282,6 +10993,20 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.12", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", @@ -8450,7 +11175,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -9345,7 +12069,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -9354,7 +12077,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" @@ -9364,7 +12086,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "engines": { "node": ">=6" } @@ -9432,7 +12153,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -9490,7 +12210,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, "dependencies": { "camel-case": "^4.1.2", "capital-case": "^1.0.4", @@ -9842,6 +12561,12 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, + "node_modules/client-zip": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/client-zip/-/client-zip-2.5.0.tgz", + "integrity": "sha512-ydG4nDZesbFurnNq0VVCp/yyomIBh+X/1fZPI/P24zbnG4dtC4tQAfI5uQsomigsUMeiRO2wiTPizLWQh+IAyQ==", + "license": "MIT" + }, "node_modules/clipboard": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", @@ -9852,6 +12577,16 @@ "tiny-emitter": "^2.0.0" } }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, "node_modules/clone-deep": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", @@ -9890,6 +12625,27 @@ "mimic-response": "^1.0.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cmdk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", + "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", + "dependencies": { + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -9967,7 +12723,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -9976,14 +12731,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "license": "MIT" }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -10096,6 +12849,11 @@ "node": ">= 0.6" } }, + "node_modules/computed-style": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/computed-style/-/computed-style-0.1.4.tgz", + "integrity": "sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -10162,7 +12920,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -10200,8 +12957,7 @@ "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { "version": "0.7.1", @@ -10228,6 +12984,96 @@ "node": ">=0.10.0" } }, + "node_modules/copy-webpack-plugin": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz", + "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2", + "tinyglobby": "^0.2.12" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/core-js": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", @@ -10278,7 +13124,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -10715,6 +13560,11 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, "node_modules/currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -10868,6 +13718,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, "node_modules/date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -10893,7 +13758,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -10911,7 +13775,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11219,7 +14082,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11448,6 +14310,15 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/desandro-matches-selector": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz", @@ -11502,12 +14373,25 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, "node_modules/devtools-protocol": { "version": "0.0.1312386", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", "dev": true }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -11645,7 +14529,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -11845,6 +14728,11 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -11864,6 +14752,14 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -11951,6 +14847,17 @@ "node": ">=4" } }, + "node_modules/equivalent-key-map": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz", + "integrity": "sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew==" + }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", + "license": "MIT" + }, "node_modules/error": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", @@ -11964,7 +14871,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -12097,7 +15003,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { @@ -12171,8 +15076,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "1.0.5", @@ -13771,11 +16675,18 @@ "node >=0.6.0" ] }, + "node_modules/fast-average-color": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.3.0.tgz", + "integrity": "sha512-FlPROSqDMOnoBgkFhWMHJODPvpS0Od0WDpedcKq4U/t0JVapGAkblNwxOr75qT+ZNd0dQM4qlgqrtnXbCJ8cNg==", + "engines": { + "node": ">= 12" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -13956,6 +16867,21 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/fetch-blob": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", @@ -14346,6 +17272,22 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/find-versions": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", @@ -14748,6 +17690,33 @@ "node": ">=0.10.0" } }, + "node_modules/framer-motion": { + "version": "11.18.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", + "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", + "license": "MIT", + "dependencies": { + "motion-dom": "^11.18.1", + "motion-utils": "^11.18.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -14844,7 +17813,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14899,11 +17867,16 @@ "node": ">=6.9.0" } }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "license": "MIT" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -14933,6 +17906,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -15068,6 +18049,15 @@ "assert-plus": "^1.0.0" } }, + "node_modules/gettext-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", + "integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==", + "dependencies": { + "encoding": "^0.1.12", + "safe-buffer": "^5.1.1" + } + }, "node_modules/gifsicle": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-4.0.1.tgz", @@ -15191,7 +18181,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -15348,6 +18337,14 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/gradient-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gradient-parser/-/gradient-parser-1.1.1.tgz", + "integrity": "sha512-Hu0YfNU+38EsTmnUfLXUKFMXq9yz7htGYpF4x+dlbBhUCvIvzLt0yVLT/gJRmvLKFJdqNFrz4eKkIUjIXSr7Tw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -16734,7 +19731,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -16746,12 +19742,38 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, "dependencies": { "capital-case": "^1.0.4", "tslib": "^2.0.3" } }, + "node_modules/highlight-words-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz", + "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==" + }, + "node_modules/history": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.6" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -16803,6 +19825,11 @@ "wbuf": "^1.1.0" } }, + "node_modules/hpq": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/hpq/-/hpq-1.3.0.tgz", + "integrity": "sha512-fvYTvdCFOWQupGxqkahrkA+ERBuMdzkxwtUdKrxR6rmMd4Pfl+iZ1QiQYoaZ0B/v0y59MOMnz3XFUWbT50/NWA==" + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -17117,7 +20144,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -17141,7 +20167,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -17443,7 +20468,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -17474,6 +20498,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-locals": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-locals/-/import-locals-2.0.0.tgz", + "integrity": "sha512-1/bPE89IZhyf7dr5Pkz7b4UyVXy5pEt7PTEfye15UEn3AK8+2zwcDCfKk9Pwun4ltfhOSszOrReSsFcDKw/yoA==", + "license": "MIT" + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -17671,6 +20701,14 @@ "node": ">=4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -17755,8 +20793,7 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "node_modules/is-async-function": { "version": "2.1.1", @@ -17858,7 +20895,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -17995,7 +21031,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -18157,7 +21192,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18178,6 +21212,12 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -18444,6 +21484,16 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -21131,7 +24181,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -21203,8 +24252,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -21418,6 +24466,27 @@ "node": ">= 0.8.0" } }, + "node_modules/lib0": { + "version": "0.2.114", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz", + "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==", + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/lie": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", @@ -21849,11 +24918,21 @@ "url": "https://github.com/sponsors/antonk52" } }, + "node_modules/line-height": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/line-height/-/line-height-0.3.1.tgz", + "integrity": "sha512-YExecgqPwnp5gplD2+Y8e8A5+jKpr25+DzMbFdI1/1UAr0FJrTFv4VkHLf8/6B590i1wUPJWMKKldkd/bdQ//w==", + "dependencies": { + "computed-style": "~0.1.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/linkify-it": { "version": "3.0.3", @@ -21958,6 +25037,18 @@ "lie": "3.1.1" } }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -22170,7 +25261,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -22641,6 +25731,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/memize/-/memize-2.1.0.tgz", + "integrity": "sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg==" + }, "node_modules/meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -23029,6 +26124,37 @@ "node": "*" } }, + "node_modules/moment-timezone": { + "version": "0.5.40", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", + "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/motion-dom": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", + "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", + "license": "MIT", + "dependencies": { + "motion-utils": "^11.18.1" + } + }, + "node_modules/motion-utils": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", + "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", + "license": "MIT" + }, + "node_modules/mousetrap": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -23041,8 +26167,7 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -23067,7 +26192,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -23191,7 +26315,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -23306,6 +26429,11 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" + }, "node_modules/npm-bundled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", @@ -23802,7 +26930,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -24287,7 +27414,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -24298,6 +27424,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/p-map-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", @@ -24361,7 +27498,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -24438,7 +27574,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -24448,7 +27583,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -24480,7 +27614,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -24527,6 +27660,11 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/parsel-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/parsel-js/-/parsel-js-1.1.2.tgz", + "integrity": "sha512-D66DG2nKx4Yoq66TMEyCUHlR2STGqO7vsBrX7tgyS9cfQyO6XD5JyzOiflwmWN6a4wbUAqpmHqmrxlTQVGZcbA==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -24540,7 +27678,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -24559,7 +27696,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -24571,6 +27707,14 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -24594,8 +27738,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-root": { "version": "0.1.1", @@ -24622,14 +27765,12 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -24650,7 +27791,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -24829,6 +27969,29 @@ "node": ">=12" } }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -24851,7 +28014,6 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -25410,6 +28572,14 @@ "postcss": "^8.4.32" } }, + "node_modules/postcss-prefix-selector": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz", + "integrity": "sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==", + "peerDependencies": { + "postcss": ">4 <9" + } + }, "node_modules/postcss-reduce-initial": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-7.0.5.tgz", @@ -25763,11 +28933,31 @@ "node": ">=4" } }, + "node_modules/postcss-urlrebase": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", + "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.3.0" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/preact": { + "version": "10.27.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz", + "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -25893,7 +29083,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -25903,8 +29092,7 @@ "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/proto-list": { "version": "1.2.4", @@ -26437,6 +29625,26 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", @@ -26483,7 +29691,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -26526,6 +29733,15 @@ "node": ">=0.10.0" } }, + "node_modules/re-resizable": { + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.9.tgz", + "integrity": "sha512-l+MBlKZffv/SicxDySKEEh42hR6m5bAHfNu3Tvxks2c4Ah+ldnWjfnVRwxo/nxF27SsUsxDS0raAzFuJNKABXA==", + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -26537,6 +29753,60 @@ "node": ">=0.10.0" } }, + "node_modules/react-autosize-textarea": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/react-autosize-textarea/-/react-autosize-textarea-7.1.0.tgz", + "integrity": "sha512-BHpjCDkuOlllZn3nLazY2F8oYO1tS2jHnWhcjTWQdcKiiMU6gHLNt/fzmqMSyerR0eTdKtfSIqtSeTtghNwS+g==", + "dependencies": { + "autosize": "^4.0.2", + "line-height": "^0.3.1", + "prop-types": "^15.5.6" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16.0.0", + "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-day-picker": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.11.1.tgz", + "integrity": "sha512-l3ub6o8NlchqIjPKrRFUCkTUEq6KwemQlfv3XZzzwpUeGwmDJ+0u0Upmt38hJyd7D/vn2dQoOoLV/qAp0o3uUw==", + "license": "MIT", + "dependencies": { + "@date-fns/tz": "^1.4.1", + "date-fns": "^4.1.0", + "date-fns-jalali": "^4.1.0-0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/react-day-picker/node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -26549,6 +29819,19 @@ "react": "^18.3.1" } }, + "node_modules/react-easy-crop": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.7.tgz", + "integrity": "sha512-6d5IUt09M3HwdDGwrcjPVgfrOfYWAOku8sCTn/xU7b1vkEg+lExMLwW8UbR39L8ybQi0hJZTU57yprF9h5Q5Ig==", + "dependencies": { + "normalize-wheel": "^1.0.1", + "tslib": "^2.0.1" + }, + "peerDependencies": { + "react": ">=16.4.0", + "react-dom": ">=16.4.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -26563,6 +29846,73 @@ "node": ">=0.10.0" } }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -26754,6 +30104,11 @@ "node": ">=0.10.0" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -26876,6 +30231,16 @@ "regjsparser": "bin/parser" } }, + "node_modules/rememo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rememo/-/rememo-4.0.2.tgz", + "integrity": "sha512-NVfSP9NstE3QPNs/TnegQY0vnJnstKQSpcrsI2kBTB3dB2PkdfKdTa+abbjMIDqpc63fE5LfjLgfMst0ULMFxQ==" + }, + "node_modules/remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" + }, "node_modules/repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -26980,11 +30345,16 @@ "uuid": "bin/uuid" } }, + "node_modules/requestidlecallback": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz", + "integrity": "sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==", + "license": "MIT" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -26998,6 +30368,11 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -27027,7 +30402,6 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", @@ -27090,7 +30464,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -27205,6 +30578,12 @@ "node": ">=10.0.0" } }, + "node_modules/route-recognizer": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz", + "integrity": "sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==", + "license": "MIT" + }, "node_modules/rtlcss": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-2.6.2.tgz", @@ -27321,6 +30700,12 @@ } ] }, + "node_modules/rungen": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/rungen/-/rungen-0.3.2.tgz", + "integrity": "sha512-zWl10xu2D7zoR8zSC2U6bg5bYF6T/Wk7rxwp8IPaJH7f0Ge21G03kNHVgHR7tyVkSSfAOG0Rqf/Cl38JftSmtw==", + "license": "MIT" + }, "node_modules/rxjs": { "version": "5.5.12", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", @@ -27371,7 +30756,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -27444,8 +30828,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { "version": "1.94.0", @@ -27720,7 +31103,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -27830,6 +31212,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -27993,6 +31380,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/showdown": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz", + "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==", + "dependencies": { + "yargs": "^14.2" + }, + "bin": { + "showdown": "bin/showdown.js" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -28071,6 +31469,78 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-html-tokenizer": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz", + "integrity": "sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==" + }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/simple-peer/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/sinon": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz", @@ -28236,7 +31706,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -28456,7 +31925,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -28466,7 +31934,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -28947,6 +32414,19 @@ "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", "dev": true }, + "node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -29057,6 +32537,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -29727,6 +33218,11 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -29783,7 +33279,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -29971,6 +33466,14 @@ "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", "dev": true }, + "node_modules/tannin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", + "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", + "dependencies": { + "@tannin/plural-forms": "^1.1.0" + } + }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", @@ -30047,6 +33550,15 @@ "streamx": "^2.15.0" } }, + "node_modules/temml": { + "version": "0.10.34", + "resolved": "https://registry.npmjs.org/temml/-/temml-0.10.34.tgz", + "integrity": "sha512-f3b5CaPwPvMviA+CtHy0qoIGWvzpRrNpXmGRc/Y1jc9gAYy+xOlndJFyn7Vfcz7cBcS8QRvv8z0EEH59sHCQxg==", + "license": "MIT", + "engines": { + "node": ">=18.13.0" + } + }, "node_modules/temp-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", @@ -30309,6 +33821,36 @@ "ms": "^2.1.1" } }, + "node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tldts-core": { "version": "6.1.75", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.75.tgz", @@ -30513,8 +34055,7 @@ "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -30946,7 +34487,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -30955,7 +34495,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -31062,6 +34601,63 @@ "node": ">=0.10.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -31706,6 +35302,24 @@ } } }, + "node_modules/webpack-livereload-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/webpack-livereload-plugin/-/webpack-livereload-plugin-3.0.2.tgz", + "integrity": "sha512-5JeZ2dgsvSNG+clrkD/u2sEiPcNk4qwCVZZmW8KpqKcNlkGv7IJjdVrq13+etAmMZYaCF1EGXdHkVFuLgP4zfw==", + "dev": true, + "dependencies": { + "anymatch": "^3.1.1", + "portfinder": "^1.0.17", + "schema-utils": ">1.0.0", + "tiny-lr": "^1.1.1" + }, + "engines": { + "node": ">= 10.18.0" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -31974,6 +35588,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + }, "node_modules/which-typed-array": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", @@ -32008,6 +35627,19 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -32105,6 +35737,100 @@ "node": ">=0.4" } }, + "node_modules/y-indexeddb": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/y-indexeddb/-/y-indexeddb-9.0.12.tgz", + "integrity": "sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.74" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-protocols": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz", + "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-webrtc": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.2.6.tgz", + "integrity": "sha512-1kZ4YYwksFZi8+l8mTebVX9vW6Q5MnqxMkvNU700X5dBE38usurt/JgeXSIQRpK3NwUYYb9y63Jn9FMpMH6/vA==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-protocols": "^1.0.6" + }, + "bin": { + "y-webrtc-signaling": "bin/server.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + }, + "optionalDependencies": { + "ws": "^8.14.2" + }, + "peerDependencies": { + "yjs": "^13.6.8" + } + }, + "node_modules/y-webrtc/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -32115,11 +35841,37 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, "engines": { "node": ">= 6" } }, + "node_modules/yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dependencies": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "node_modules/yargs-parser": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", + "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -32130,6 +35882,23 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yjs": { + "version": "13.6.27", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.27.tgz", + "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ā¤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 7ae0193bfe6c3..5981ed7d27b80 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,6 @@ "type": "svn", "url": "https://develop.svn.wordpress.org/trunk" }, - "gutenberg": { - "ref": "892bfad51d2261f44f3a21f934b1c72bd29a2449" - }, "engines": { "node": ">=20.10.0", "npm": ">=10.2.3" @@ -29,12 +26,16 @@ "devDependencies": { "@lodder/grunt-postcss": "^3.1.1", "@playwright/test": "1.56.1", + "@pmmmwh/react-refresh-webpack-plugin": "0.6.1", + "@wordpress/babel-preset-default": "8.33.1", + "@wordpress/dependency-extraction-webpack-plugin": "6.33.1", "@wordpress/e2e-test-utils-playwright": "1.33.2", "@wordpress/prettier-config": "4.33.1", "@wordpress/scripts": "30.26.2", "autoprefixer": "10.4.22", "chalk": "5.6.2", "check-node-version": "4.2.1", + "copy-webpack-plugin": "13.0.1", "cssnano": "7.1.2", "dotenv": "17.2.3", "dotenv-expand": "12.0.3", @@ -61,16 +62,91 @@ "postcss": "8.5.6", "prettier": "npm:wp-prettier@3.0.3", "qunit": "~2.24.2", + "react-refresh": "0.14.0", "sass": "1.94.0", "sinon": "16.1.3", "sinon-test": "~3.1.6", "source-map-loader": "5.0.0", "terser-webpack-plugin": "5.3.14", + "uglify-js": "^3.19.3", "uuid": "13.0.0", "wait-on": "9.0.3", - "webpack": "5.98.0" + "webpack": "5.98.0", + "webpack-livereload-plugin": "3.0.2" }, "dependencies": { + "@wordpress/a11y": "4.33.1", + "@wordpress/admin-ui": "1.1.4", + "@wordpress/annotations": "3.33.2", + "@wordpress/api-fetch": "7.33.1", + "@wordpress/autop": "4.33.1", + "@wordpress/base-styles": "6.9.1", + "@wordpress/blob": "4.33.1", + "@wordpress/block-directory": "5.33.9", + "@wordpress/block-editor": "15.6.7", + "@wordpress/block-library": "9.33.8", + "@wordpress/block-serialization-default-parser": "5.33.1", + "@wordpress/blocks": "15.6.2", + "@wordpress/commands": "1.33.4", + "@wordpress/components": "30.6.4", + "@wordpress/compose": "7.33.1", + "@wordpress/core-commands": "1.33.7", + "@wordpress/core-data": "7.33.7", + "@wordpress/customize-widgets": "5.33.8", + "@wordpress/data": "10.33.1", + "@wordpress/data-controls": "4.33.1", + "@wordpress/dataviews": "10.1.6", + "@wordpress/date": "5.33.1", + "@wordpress/deprecated": "4.33.1", + "@wordpress/dom": "4.33.1", + "@wordpress/dom-ready": "4.33.1", + "@wordpress/edit-post": "8.33.9", + "@wordpress/edit-site": "6.33.9", + "@wordpress/edit-widgets": "6.33.8", + "@wordpress/editor": "14.33.9", + "@wordpress/element": "6.33.1", + "@wordpress/escape-html": "3.33.1", + "@wordpress/fields": "0.25.9", + "@wordpress/format-library": "5.33.7", + "@wordpress/hooks": "4.33.1", + "@wordpress/html-entities": "4.33.1", + "@wordpress/i18n": "6.6.1", + "@wordpress/icons": "11.0.1", + "@wordpress/interactivity": "6.33.1", + "@wordpress/interactivity-router": "2.33.1", + "@wordpress/interface": "9.18.4", + "@wordpress/is-shallow-equal": "5.33.1", + "@wordpress/keyboard-shortcuts": "5.33.1", + "@wordpress/keycodes": "4.33.1", + "@wordpress/latex-to-mathml": "1.1.2", + "@wordpress/list-reusable-blocks": "5.33.4", + "@wordpress/media-utils": "5.33.1", + "@wordpress/notices": "5.33.1", + "@wordpress/nux": "9.33.4", + "@wordpress/patterns": "2.33.7", + "@wordpress/plugins": "7.33.4", + "@wordpress/preferences": "4.33.4", + "@wordpress/preferences-persistence": "2.33.1", + "@wordpress/primitives": "4.33.1", + "@wordpress/priority-queue": "3.33.1", + "@wordpress/private-apis": "1.33.1", + "@wordpress/redux-routine": "5.33.1", + "@wordpress/reusable-blocks": "5.33.7", + "@wordpress/rich-text": "7.33.2", + "@wordpress/router": "1.33.1", + "@wordpress/server-side-render": "6.9.4", + "@wordpress/shortcode": "4.33.1", + "@wordpress/style-engine": "2.33.1", + "@wordpress/sync": "1.33.1", + "@wordpress/token-list": "3.33.1", + "@wordpress/undo-manager": "1.33.1", + "@wordpress/upload-media": "0.18.4", + "@wordpress/url": "4.33.1", + "@wordpress/viewport": "6.33.1", + "@wordpress/views": "1.0.7", + "@wordpress/warning": "3.33.1", + "@wordpress/widgets": "4.33.7", + "@wordpress/wordcount": "4.33.1", "backbone": "1.6.0", "clipboard": "2.0.11", "core-js-url-browser": "3.6.4", @@ -97,7 +173,6 @@ "wicg-inert": "3.1.3" }, "scripts": { - "postinstall": "npm run gutenberg:checkout", "build": "grunt build", "build:dev": "grunt build --dev", "dev": "grunt watch --dev", @@ -121,11 +196,6 @@ "test:coverage": "npm run test:php -- --coverage-html ./coverage/html/ --coverage-php ./coverage/php/report.php --coverage-text=./coverage/text/report.txt", "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js", "test:visual": "wp-scripts test-playwright --config tests/visual-regression/playwright.config.js", - "gutenberg:checkout": "node tools/gutenberg/checkout-gutenberg.js", - "gutenberg:build": "node tools/gutenberg/build-gutenberg.js", - "gutenberg:copy": "node tools/gutenberg/copy-gutenberg-build.js", - "gutenberg:integrate": "npm run gutenberg:checkout && npm run gutenberg:build && npm run gutenberg:copy", - "vendor:copy": "node tools/vendors/copy-vendors.js", "sync-gutenberg-packages": "grunt sync-gutenberg-packages", "postsync-gutenberg-packages": "grunt wp-packages:sync-stable-blocks && grunt build --dev && grunt build" } diff --git a/src/wp-admin/font-library.php b/src/wp-admin/font-library.php deleted file mode 100644 index 5c9fe21264997..0000000000000 --- a/src/wp-admin/font-library.php +++ /dev/null @@ -1,38 +0,0 @@ -' . __( 'You need a higher level of permission.' ) . '' . - '

' . __( 'Sorry, you are not allowed to manage fonts on this site.' ) . '

', - 403 - ); -} - -// Check if Gutenberg build files are available -if ( ! function_exists( 'font_library_wp_admin_render_page' ) ) { - wp_die( - '

' . __( 'Font Library is not available.' ) . '

' . - '

' . __( 'The Font Library requires Gutenberg integration. Please run npm run gutenberg:integrate to build the necessary files.' ) . '

', - 503 - ); -} - -// Set the page title -$title = _x( 'Fonts', 'Font Library admin page title' ); - -require_once ABSPATH . 'wp-admin/admin-header.php'; - -// Render the Font Library page -font_library_wp_admin_render_page(); - -require_once ABSPATH . 'wp-admin/admin-footer.php'; diff --git a/src/wp-admin/includes/update-core.php b/src/wp-admin/includes/update-core.php index 2f8045e8d193f..14262d337e354 100644 --- a/src/wp-admin/includes/update-core.php +++ b/src/wp-admin/includes/update-core.php @@ -837,6 +837,8 @@ 'wp-includes/blocks/post-template/editor.min.css', 'wp-includes/blocks/post-template/editor-rtl.css', 'wp-includes/blocks/post-template/editor-rtl.min.css', + 'wp-includes/js/dist/undo-manager.js', + 'wp-includes/js/dist/undo-manager.min.js', 'wp-includes/js/dist/fields.min.js', 'wp-includes/js/dist/fields.js', // 6.9 diff --git a/src/wp-admin/menu.php b/src/wp-admin/menu.php index c9187399cec7a..f7dfd9270ddca 100644 --- a/src/wp-admin/menu.php +++ b/src/wp-admin/menu.php @@ -236,9 +236,6 @@ } } -// Font Library menu item. -$submenu['themes.php'][8] = array( __( 'Fonts' ), 'edit_theme_options', 'font-library.php' ); - $customize_url = add_query_arg( 'return', urlencode( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ), 'customize.php' ); // Hide Customize link on block themes unless a plugin or theme diff --git a/src/wp-includes/assets/script-loader-packages.min.php b/src/wp-includes/assets/script-loader-packages.min.php new file mode 100644 index 0000000000000..9650b17034884 --- /dev/null +++ b/src/wp-includes/assets/script-loader-packages.min.php @@ -0,0 +1 @@ + array('dependencies' => array('wp-dom-ready', 'wp-i18n'), 'version' => 'cb460b4676c94bd228ed'), 'admin-ui.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-components', 'wp-element'), 'version' => 'bc5db43f7e3f0d8adcc8'), 'annotations.min.js' => array('dependencies' => array('wp-data', 'wp-hooks', 'wp-i18n', 'wp-rich-text'), 'version' => '758b80d8a795a222601b'), 'api-fetch.min.js' => array('dependencies' => array('wp-i18n', 'wp-url'), 'version' => '3a4d9af2b423048b0dee'), 'autop.min.js' => array('dependencies' => array(), 'version' => '9fb50649848277dd318d'), 'base-styles.min.js' => array('dependencies' => array(), 'version' => '7529f773be5cb229e3c4'), 'blob.min.js' => array('dependencies' => array(), 'version' => '9113eed771d446f4a556'), 'block-directory.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-primitives', 'wp-url'), 'version' => '55bdef7bd3137eee623d'), 'block-editor.min.js' => array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-blob', 'wp-block-serialization-default-parser', 'wp-blocks', 'wp-commands', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-notices', 'wp-preferences', 'wp-primitives', 'wp-priority-queue', 'wp-private-apis', 'wp-rich-text', 'wp-style-engine', 'wp-token-list', 'wp-url', 'wp-warning'), 'version' => '5fc3ad11235679e29400'), 'block-library.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-autop', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-escape-html', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-latex-to-mathml', 'wp-notices', 'wp-patterns', 'wp-primitives', 'wp-private-apis', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-wordcount'), 'version' => 'f7cd30dd531f20693fdb'), 'block-serialization-default-parser.min.js' => array('dependencies' => array(), 'version' => '14d44daebf663d05d330'), 'blocks.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-autop', 'wp-blob', 'wp-block-serialization-default-parser', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-private-apis', 'wp-rich-text', 'wp-shortcode', 'wp-warning'), 'version' => 'de131db49fa830bc97da'), 'commands.min.js' => array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-primitives', 'wp-private-apis'), 'version' => 'cac8f4817ab7cea0ac49'), 'components.min.js' => array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-compose', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-escape-html', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keycodes', 'wp-primitives', 'wp-private-apis', 'wp-rich-text', 'wp-warning'), 'version' => 'ad5cb4227f07a3d422ad'), 'compose.min.js' => array('dependencies' => array('react', 'react-jsx-runtime', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-is-shallow-equal', 'wp-keycodes', 'wp-priority-queue'), 'version' => '7a9b375d8c19cf9d3d9b'), 'core-commands.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-commands', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-private-apis', 'wp-router', 'wp-url'), 'version' => 'effe2d88d7f0c50a8ce9'), 'core-data.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-private-apis', 'wp-rich-text', 'wp-url', 'wp-warning'), 'version' => '15baadfe6e1374188072'), 'customize-widgets.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-widgets'), 'version' => 'd824213342f5e84c8ea3'), 'data.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-compose', 'wp-deprecated', 'wp-element', 'wp-is-shallow-equal', 'wp-priority-queue', 'wp-private-apis', 'wp-redux-routine'), 'version' => 'f940198280891b0b6318'), 'data-controls.min.js' => array('dependencies' => array('wp-api-fetch', 'wp-data', 'wp-deprecated'), 'version' => '49f5587e8b90f9e7cc7e'), 'date.min.js' => array('dependencies' => array('moment', 'wp-deprecated'), 'version' => '795a56839718d3ff7eae'), 'deprecated.min.js' => array('dependencies' => array('wp-hooks'), 'version' => 'e1f84915c5e8ae38964c'), 'dom.min.js' => array('dependencies' => array('wp-deprecated'), 'version' => '26edef3be6483da3de2e'), 'dom-ready.min.js' => array('dependencies' => array(), 'version' => 'f77871ff7694fffea381'), 'edit-post.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-commands', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-deprecated', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-notices', 'wp-plugins', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-url', 'wp-widgets'), 'version' => 'f011f5ec0075a555ea9c'), 'edit-site.min.js' => array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-blob', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-commands', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-patterns', 'wp-plugins', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-router', 'wp-url', 'wp-warning', 'wp-widgets'), 'version' => 'b877e769e7f2bce85569'), 'edit-widgets.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-patterns', 'wp-plugins', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-url', 'wp-viewport', 'wp-widgets'), 'version' => 'f0347fefaf37fa0d99ca'), 'editor.min.js' => array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-commands', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-patterns', 'wp-plugins', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-viewport', 'wp-warning', 'wp-wordcount'), 'version' => 'eb03723c7a53aaeea8fd'), 'element.min.js' => array('dependencies' => array('react', 'react-dom', 'wp-escape-html'), 'version' => '6a582b0c827fa25df3dd'), 'escape-html.min.js' => array('dependencies' => array(), 'version' => '6561a406d2d232a6fbd2'), 'format-library.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-a11y', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-latex-to-mathml', 'wp-primitives', 'wp-private-apis', 'wp-rich-text', 'wp-url'), 'version' => '0811ed891b276a89737b'), 'hooks.min.js' => array('dependencies' => array(), 'version' => 'dd5603f07f9220ed27f1'), 'html-entities.min.js' => array('dependencies' => array(), 'version' => 'e8b78b18a162491d5e5f'), 'i18n.min.js' => array('dependencies' => array('wp-hooks'), 'version' => 'c26c3dc7bed366793375'), 'is-shallow-equal.min.js' => array('dependencies' => array(), 'version' => 'e0f9f1d78d83f5196979'), 'keyboard-shortcuts.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-data', 'wp-element', 'wp-keycodes'), 'version' => 'fbc45a34ce65c5723afa'), 'keycodes.min.js' => array('dependencies' => array('wp-i18n'), 'version' => '34c8fb5e7a594a1c8037'), 'latex-to-mathml.min.js' => array('dependencies' => array(), 'version' => '960cef31b586960935b4'), 'list-reusable-blocks.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-blob', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n'), 'version' => 'f203c56da0f227808035'), 'media-utils.min.js' => array('dependencies' => array('wp-api-fetch', 'wp-blob', 'wp-element', 'wp-i18n', 'wp-private-apis'), 'version' => 'c66754bed5498afe7050'), 'notices.min.js' => array('dependencies' => array('wp-data'), 'version' => 'f62fbf15dcc23301922f'), 'nux.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'df0a4e75f0b99fb17077'), 'patterns.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-a11y', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-private-apis', 'wp-url'), 'version' => '4131f04a041db58120d8'), 'plugins.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-compose', 'wp-deprecated', 'wp-element', 'wp-hooks', 'wp-is-shallow-equal', 'wp-primitives'), 'version' => '039ed87b5b9f7036ceee'), 'preferences.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-a11y', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-private-apis'), 'version' => '2ca086aed510c242a1ed'), 'preferences-persistence.min.js' => array('dependencies' => array('wp-api-fetch'), 'version' => 'e954d3a4426d311f7d1a'), 'primitives.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-element'), 'version' => '0b5dcc337aa7cbf75570'), 'priority-queue.min.js' => array('dependencies' => array(), 'version' => '2d59d091223ee9a33838'), 'private-apis.min.js' => array('dependencies' => array(), 'version' => '4f465748bda624774139'), 'redux-routine.min.js' => array('dependencies' => array(), 'version' => '8bb92d45458b29590f53'), 'reusable-blocks.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url'), 'version' => '6c0ec6e24f166c9b36e7'), 'rich-text.min.js' => array('dependencies' => array('wp-a11y', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-escape-html', 'wp-i18n', 'wp-keycodes'), 'version' => '5bdbb44f3039529e3645'), 'router.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-compose', 'wp-element', 'wp-private-apis', 'wp-url'), 'version' => '2dfc4b954318a03e6a76'), 'server-side-render.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '7db2472793a2abb97aa5'), 'shortcode.min.js' => array('dependencies' => array(), 'version' => '0b3174183b858f2df320'), 'style-engine.min.js' => array('dependencies' => array(), 'version' => '7c6fcedc37dadafb8a81'), 'token-list.min.js' => array('dependencies' => array(), 'version' => 'cfdf635a436c3953a965'), 'url.min.js' => array('dependencies' => array(), 'version' => '9e178c9516d1222dc834'), 'viewport.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-compose', 'wp-data'), 'version' => 'f07b4909c08cfe9de4e2'), 'views.min.js' => array('dependencies' => array('wp-data', 'wp-element', 'wp-preferences'), 'version' => 'ffb9f0d96ccb2a0d04bd'), 'warning.min.js' => array('dependencies' => array(), 'version' => 'd69bc18c456d01c11d5a'), 'widgets.min.js' => array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives'), 'version' => 'c0e4adfacd4c628b1d02'), 'wordcount.min.js' => array('dependencies' => array(), 'version' => 'c5b97f11206928ea9130')); diff --git a/src/wp-includes/assets/script-modules-packages.min.php b/src/wp-includes/assets/script-modules-packages.min.php new file mode 100644 index 0000000000000..b1a803991701d --- /dev/null +++ b/src/wp-includes/assets/script-modules-packages.min.php @@ -0,0 +1 @@ + array('dependencies' => array(), 'version' => '90f16bd7fc9472806570', 'type' => 'module'), 'interactivity/debug.min.js' => array('dependencies' => array(), 'version' => 'dea7da43ce140b662d0f', 'type' => 'module'), 'interactivity-router/index.min.js' => array('dependencies' => array('@wordpress/interactivity', array('id' => '@wordpress/a11y', 'import' => 'dynamic')), 'version' => '765a6ee8162122b48e6c', 'type' => 'module'), 'a11y/index.min.js' => array('dependencies' => array(), 'version' => 'b7d06936b8bc23cff2ad', 'type' => 'module'), 'block-library/accordion/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '3a414634555a20667d6c', 'type' => 'module'), 'block-library/file/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => 'f9665632b48682075277', 'type' => 'module'), 'block-library/form/view.min.js' => array('dependencies' => array(), 'version' => 'baaf25398238b4f2a821', 'type' => 'module'), 'block-library/image/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '292ec2cc397d10d98f6a', 'type' => 'module'), 'block-library/navigation/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => 'b0f909c3ec791c383210', 'type' => 'module'), 'block-library/query/view.min.js' => array('dependencies' => array('@wordpress/interactivity', array('id' => '@wordpress/interactivity-router', 'import' => 'dynamic')), 'version' => 'f55e93a1ad4806e91785', 'type' => 'module'), 'block-library/search/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '94fc611a7464b5de290a', 'type' => 'module'), 'block-editor/utils/fit-text-frontend.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => 'd6b553b57c3908edc8f8', 'type' => 'module')); diff --git a/src/wp-includes/blocks/accordion-heading/block.json b/src/wp-includes/blocks/accordion-heading/block.json new file mode 100644 index 0000000000000..1fbb33f7e407c --- /dev/null +++ b/src/wp-includes/blocks/accordion-heading/block.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/accordion-heading", + "title": "Accordion Heading", + "category": "design", + "description": "Displays a heading that toggles the accordion panel.", + "parent": [ "core/accordion-item" ], + "usesContext": [ + "core/accordion-icon-position", + "core/accordion-show-icon", + "core/accordion-heading-level" + ], + "supports": { + "anchor": true, + "color": { + "background": true, + "gradients": true + }, + "align": false, + "interactivity": true, + "spacing": { + "padding": true, + "__experimentalDefaultControls": { + "padding": true + }, + "__experimentalSkipSerialization": true, + "__experimentalSelector": ".wp-block-accordion-heading__toggle" + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "typography": { + "__experimentalSkipSerialization": [ + "textDecoration", + "letterSpacing" + ], + "fontSize": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true, + "fontFamily": true + } + }, + "shadow": true, + "blockVisibility": false, + "lock": false + }, + "selectors": { + "typography": { + "letterSpacing": ".wp-block-accordion-heading .wp-block-accordion-heading__toggle-title", + "textDecoration": ".wp-block-accordion-heading .wp-block-accordion-heading__toggle-title" + } + }, + "attributes": { + "openByDefault": { + "type": "boolean", + "default": false + }, + "title": { + "type": "rich-text", + "source": "rich-text", + "selector": ".wp-block-accordion-heading__toggle-title", + "role": "content" + }, + "level": { + "type": "number" + }, + "iconPosition": { + "type": "string", + "enum": [ "left", "right" ], + "default": "right" + }, + "showIcon": { + "type": "boolean", + "default": true + } + }, + "textdomain": "default" +} diff --git a/src/wp-includes/blocks/accordion-item.php b/src/wp-includes/blocks/accordion-item.php new file mode 100644 index 0000000000000..6b6df425111fa --- /dev/null +++ b/src/wp-includes/blocks/accordion-item.php @@ -0,0 +1,74 @@ + function () { + $context = wp_interactivity_get_context(); + return $context['openByDefault']; + }, + ) + ); + + if ( $p->next_tag( array( 'class_name' => 'wp-block-accordion-item' ) ) ) { + $open_by_default = $attributes['openByDefault'] ? 'true' : 'false'; + $p->set_attribute( 'data-wp-context', '{ "id": "' . $unique_id . '", "openByDefault": ' . $open_by_default . ' }' ); + $p->set_attribute( 'data-wp-class--is-open', 'state.isOpen' ); + $p->set_attribute( 'data-wp-init', 'callbacks.initAccordionItems' ); + + if ( $p->next_tag( array( 'class_name' => 'wp-block-accordion-heading__toggle' ) ) ) { + $p->set_attribute( 'data-wp-on--click', 'actions.toggle' ); + $p->set_attribute( 'data-wp-on--keydown', 'actions.handleKeyDown' ); + $p->set_attribute( 'id', $unique_id ); + $p->set_attribute( 'aria-controls', $unique_id . '-panel' ); + $p->set_attribute( 'data-wp-bind--aria-expanded', 'state.isOpen' ); + + if ( $p->next_tag( array( 'class_name' => 'wp-block-accordion-panel' ) ) ) { + $p->set_attribute( 'id', $unique_id . '-panel' ); + $p->set_attribute( 'aria-labelledby', $unique_id ); + $p->set_attribute( 'data-wp-bind--inert', '!state.isOpen' ); + + // Only modify content if all directives have been set. + $content = $p->get_updated_html(); + } + } + } + + return $content; +} + +/** + * Registers the `core/accordion-item` block on server. + * + * @since 6.9.0 + */ +function register_block_core_accordion_item() { + register_block_type_from_metadata( + __DIR__ . '/accordion-item', + array( + 'render_callback' => 'block_core_accordion_item_render', + ) + ); +} +add_action( 'init', 'register_block_core_accordion_item' ); diff --git a/src/wp-includes/blocks/accordion-item/block.json b/src/wp-includes/blocks/accordion-item/block.json new file mode 100644 index 0000000000000..4958a5fde17ae --- /dev/null +++ b/src/wp-includes/blocks/accordion-item/block.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/accordion-item", + "title": "Accordion Item", + "category": "design", + "description": "Wraps the heading and panel in one unit.", + "parent": [ "core/accordion" ], + "allowedBlocks": [ "core/accordion-heading", "core/accordion-panel" ], + "supports": { + "html": false, + "color": { + "background": true, + "gradients": true + }, + "interactivity": true, + "spacing": { + "margin": [ "top", "bottom" ], + "blockGap": true + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "shadow": true, + "layout": { + "allowEditing": false + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "contentRole": true + }, + "attributes": { + "openByDefault": { + "type": "boolean", + "default": false + } + }, + "textdomain": "default", + "style": "wp-block-accordion-item" +} diff --git a/src/wp-includes/blocks/accordion-panel/block.json b/src/wp-includes/blocks/accordion-panel/block.json new file mode 100644 index 0000000000000..d6b6602619447 --- /dev/null +++ b/src/wp-includes/blocks/accordion-panel/block.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/accordion-panel", + "title": "Accordion Panel", + "category": "design", + "description": "Contains the hidden or revealed content beneath the heading.", + "parent": [ "core/accordion-item" ], + "supports": { + "html": false, + "color": { + "background": true, + "gradients": true + }, + "interactivity": true, + "spacing": { + "padding": true, + "blockGap": true, + "__experimentalDefaultControls": { + "padding": true, + "blockGap": true + } + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "shadow": true, + "layout": { + "allowEditing": false + }, + "blockVisibility": false, + "contentRole": true, + "allowedBlocks": true, + "lock": false + }, + "attributes": { + "templateLock": { + "type": [ "string", "boolean" ], + "enum": [ "all", "insert", "contentOnly", false ], + "default": false + }, + "openByDefault": { + "type": "boolean", + "default": false + }, + "isSelected": { + "type": "boolean", + "default": false + } + }, + "textdomain": "default", + "style": "wp-block-accordion-panel" +} diff --git a/src/wp-includes/blocks/accordion.php b/src/wp-includes/blocks/accordion.php new file mode 100644 index 0000000000000..537904a6e402d --- /dev/null +++ b/src/wp-includes/blocks/accordion.php @@ -0,0 +1,45 @@ +next_tag( array( 'class_name' => 'wp-block-accordion' ) ) ) { + $p->set_attribute( 'data-wp-interactive', 'core/accordion' ); + $p->set_attribute( 'data-wp-context', '{ "autoclose": ' . $autoclose . ', "accordionItems": [] }' ); + + // Only modify content if directives have been set. + $content = $p->get_updated_html(); + } + + return $content; +} + +/** + * Registers the `core/accordion` block on server. + * + * @since 6.9.0 + */ +function register_block_core_accordion() { + register_block_type_from_metadata( + __DIR__ . '/accordion', + array( + 'render_callback' => 'render_block_core_accordion', + ) + ); +} +add_action( 'init', 'register_block_core_accordion' ); diff --git a/src/wp-includes/blocks/accordion/block.json b/src/wp-includes/blocks/accordion/block.json new file mode 100644 index 0000000000000..4b44b1c9bfa4a --- /dev/null +++ b/src/wp-includes/blocks/accordion/block.json @@ -0,0 +1,89 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/accordion", + "title": "Accordion", + "category": "design", + "description": "Displays a foldable layout that groups content in collapsible sections.", + "example": {}, + "supports": { + "anchor": true, + "html": false, + "align": [ "wide", "full" ], + "background": { + "backgroundImage": true, + "backgroundSize": true, + "__experimentalDefaultControls": { + "backgroundImage": true + } + }, + "color": { + "background": true, + "gradients": true + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "spacing": { + "padding": true, + "margin": [ "top", "bottom" ], + "blockGap": true + }, + "shadow": true, + "layout": true, + "ariaLabel": true, + "interactivity": true, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "contentRole": true + }, + "attributes": { + "iconPosition": { + "type": "string", + "default": "right" + }, + "showIcon": { + "type": "boolean", + "default": true + }, + "autoclose": { + "type": "boolean", + "default": false + }, + "headingLevel": { + "type": "number", + "default": 3 + }, + "levelOptions": { + "type": "array" + } + }, + "providesContext": { + "core/accordion-icon-position": "iconPosition", + "core/accordion-show-icon": "showIcon", + "core/accordion-heading-level": "headingLevel" + }, + "allowedBlocks": [ "core/accordion-item" ], + "textdomain": "default", + "viewScriptModule": "@wordpress/block-library/accordion/view" +} diff --git a/src/wp-includes/blocks/archives.php b/src/wp-includes/blocks/archives.php new file mode 100644 index 0000000000000..077507f8c9e08 --- /dev/null +++ b/src/wp-includes/blocks/archives.php @@ -0,0 +1,174 @@ + $type, + 'format' => 'option', + 'show_post_count' => $show_post_count, + ) + ); + + $dropdown_args['echo'] = 0; + + $archives = wp_get_archives( $dropdown_args ); + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $class ) ); + + switch ( $dropdown_args['type'] ) { + case 'yearly': + $label = __( 'Select Year' ); + break; + case 'monthly': + $label = __( 'Select Month' ); + break; + case 'daily': + $label = __( 'Select Day' ); + break; + case 'weekly': + $label = __( 'Select Week' ); + break; + default: + $label = __( 'Select Post' ); + break; + } + + $show_label = empty( $attributes['showLabel'] ) ? ' screen-reader-text' : ''; + + $block_content = ' + '; + + // Inject the dropdown script immediately after the select dropdown. + $block_content .= block_core_archives_build_dropdown_script( $dropdown_id ); + + return sprintf( + '
%2$s
', + $wrapper_attributes, + $block_content + ); + } + + /** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */ + $archives_args = apply_filters( + 'widget_archives_args', + array( + 'type' => $type, + 'show_post_count' => $show_post_count, + ) + ); + + $archives_args['echo'] = 0; + + $archives = wp_get_archives( $archives_args ); + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $class ) ); + + if ( empty( $archives ) ) { + return sprintf( + '
%2$s
', + $wrapper_attributes, + __( 'No archives to show.' ) + ); + } + + return sprintf( + '', + $wrapper_attributes, + $archives + ); +} + +/** + * Generates the inline script for an archives dropdown field. + * + * @since 6.9.0 + * + * @param string $dropdown_id ID of the dropdown field. + * + * @return string Returns the dropdown onChange redirection script. + */ +function block_core_archives_build_dropdown_script( $dropdown_id ) { + ob_start(); + + $exports = array( $dropdown_id, home_url() ); + ?> + + ', '' ), '', ob_get_clean() ) ) . + "\n//# sourceURL=" . rawurlencode( __FUNCTION__ ) + ); +} + +/** + * Register archives block. + * + * @since 5.0.0 + */ +function register_block_core_archives() { + register_block_type_from_metadata( + __DIR__ . '/archives', + array( + 'render_callback' => 'render_block_core_archives', + ) + ); +} +add_action( 'init', 'register_block_core_archives' ); diff --git a/src/wp-includes/blocks/archives/block.json b/src/wp-includes/blocks/archives/block.json new file mode 100644 index 0000000000000..0351a4b694c00 --- /dev/null +++ b/src/wp-includes/blocks/archives/block.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/archives", + "title": "Archives", + "category": "widgets", + "description": "Display a date archive of your posts.", + "textdomain": "default", + "attributes": { + "displayAsDropdown": { + "type": "boolean", + "default": false + }, + "showLabel": { + "type": "boolean", + "default": true + }, + "showPostCounts": { + "type": "boolean", + "default": false + }, + "type": { + "type": "string", + "default": "monthly" + } + }, + "supports": { + "align": true, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "html": false, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-archives-editor" +} diff --git a/src/wp-includes/blocks/audio/block.json b/src/wp-includes/blocks/audio/block.json new file mode 100644 index 0000000000000..9b77efee23cce --- /dev/null +++ b/src/wp-includes/blocks/audio/block.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/audio", + "title": "Audio", + "category": "media", + "description": "Embed a simple audio player.", + "keywords": [ "music", "sound", "podcast", "recording" ], + "textdomain": "default", + "attributes": { + "blob": { + "type": "string", + "role": "local" + }, + "src": { + "type": "string", + "source": "attribute", + "selector": "audio", + "attribute": "src", + "role": "content" + }, + "caption": { + "type": "rich-text", + "source": "rich-text", + "selector": "figcaption", + "role": "content" + }, + "id": { + "type": "number", + "role": "content" + }, + "autoplay": { + "type": "boolean", + "source": "attribute", + "selector": "audio", + "attribute": "autoplay" + }, + "loop": { + "type": "boolean", + "source": "attribute", + "selector": "audio", + "attribute": "loop" + }, + "preload": { + "type": "string", + "source": "attribute", + "selector": "audio", + "attribute": "preload" + } + }, + "supports": { + "anchor": true, + "align": true, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-audio-editor", + "style": "wp-block-audio" +} diff --git a/src/wp-includes/blocks/avatar.php b/src/wp-includes/blocks/avatar.php new file mode 100644 index 0000000000000..d4a01c1c3a1e7 --- /dev/null +++ b/src/wp-includes/blocks/avatar.php @@ -0,0 +1,166 @@ +context['commentId'] ) ) { + if ( isset( $attributes['userId'] ) ) { + $author_id = $attributes['userId']; + } elseif ( isset( $block->context['postId'] ) ) { + $author_id = get_post_field( 'post_author', $block->context['postId'] ); + } else { + $author_id = get_query_var( 'author' ); + } + + if ( empty( $author_id ) ) { + return ''; + } + + $author_name = get_the_author_meta( 'display_name', $author_id ); + // translators: %s: Author name. + $alt = sprintf( __( '%s Avatar' ), $author_name ); + $avatar_block = get_avatar( + $author_id, + $size, + '', + $alt, + array( + 'extra_attr' => $image_styles, + 'class' => $image_classes, + ) + ); + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] ) { + $label = ''; + if ( '_blank' === $attributes['linkTarget'] ) { + // translators: %s is the Author name. + $label = 'aria-label="' . esc_attr( sprintf( __( '(%s author archive, opens in a new tab)' ), $author_name ) ) . '"'; + } + // translators: 1: Author archive link. 2: Link target. %3$s Aria label. %4$s Avatar image. + $avatar_block = sprintf( '%4$s', esc_url( get_author_posts_url( $author_id ) ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block ); + } + return sprintf( '
%2s
', $wrapper_attributes, $avatar_block ); + } + $comment = get_comment( $block->context['commentId'] ); + if ( ! $comment ) { + return ''; + } + /* translators: %s: Author name. */ + $alt = sprintf( __( '%s Avatar' ), $comment->comment_author ); + $avatar_block = get_avatar( + $comment, + $size, + '', + $alt, + array( + 'extra_attr' => $image_styles, + 'class' => $image_classes, + ) + ); + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] && isset( $comment->comment_author_url ) && '' !== $comment->comment_author_url ) { + $label = ''; + if ( '_blank' === $attributes['linkTarget'] ) { + // translators: %s: Comment author name. + $label = 'aria-label="' . esc_attr( sprintf( __( '(%s website link, opens in a new tab)' ), $comment->comment_author ) ) . '"'; + } + $avatar_block = sprintf( '%4$s', esc_url( $comment->comment_author_url ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block ); + } + return sprintf( '
%2s
', $wrapper_attributes, $avatar_block ); +} + +/** + * Generates class names and styles to apply the border support styles for + * the Avatar block. + * + * @since 6.3.0 + * + * @param array $attributes The block attributes. + * @return array The border-related classnames and styles for the block. + */ +function get_block_core_avatar_border_attributes( $attributes ) { + $border_styles = array(); + $sides = array( 'top', 'right', 'bottom', 'left' ); + + // Border radius. + if ( isset( $attributes['style']['border']['radius'] ) ) { + $border_styles['radius'] = $attributes['style']['border']['radius']; + } + + // Border style. + if ( isset( $attributes['style']['border']['style'] ) ) { + $border_styles['style'] = $attributes['style']['border']['style']; + } + + // Border width. + if ( isset( $attributes['style']['border']['width'] ) ) { + $border_styles['width'] = $attributes['style']['border']['width']; + } + + // Border color. + $preset_color = array_key_exists( 'borderColor', $attributes ) ? "var:preset|color|{$attributes['borderColor']}" : null; + $custom_color = $attributes['style']['border']['color'] ?? null; + $border_styles['color'] = $preset_color ? $preset_color : $custom_color; + + // Individual border styles e.g. top, left etc. + foreach ( $sides as $side ) { + $border = $attributes['style']['border'][ $side ] ?? null; + $border_styles[ $side ] = array( + 'color' => isset( $border['color'] ) ? $border['color'] : null, + 'style' => isset( $border['style'] ) ? $border['style'] : null, + 'width' => isset( $border['width'] ) ? $border['width'] : null, + ); + } + + $styles = wp_style_engine_get_styles( array( 'border' => $border_styles ) ); + $attributes = array(); + if ( ! empty( $styles['classnames'] ) ) { + $attributes['class'] = $styles['classnames']; + } + if ( ! empty( $styles['css'] ) ) { + $attributes['style'] = $styles['css']; + } + return $attributes; +} + +/** + * Registers the `core/avatar` block on the server. + * + * @since 6.0.0 + */ +function register_block_core_avatar() { + register_block_type_from_metadata( + __DIR__ . '/avatar', + array( + 'render_callback' => 'render_block_core_avatar', + ) + ); +} +add_action( 'init', 'register_block_core_avatar' ); diff --git a/src/wp-includes/blocks/avatar/block.json b/src/wp-includes/blocks/avatar/block.json new file mode 100644 index 0000000000000..5c13258bb3c11 --- /dev/null +++ b/src/wp-includes/blocks/avatar/block.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/avatar", + "title": "Avatar", + "category": "theme", + "description": "Add a user’s avatar.", + "textdomain": "default", + "attributes": { + "userId": { + "type": "number" + }, + "size": { + "type": "number", + "default": 96 + }, + "isLink": { + "type": "boolean", + "default": false + }, + "linkTarget": { + "type": "string", + "default": "_self" + } + }, + "usesContext": [ "postType", "postId", "commentId" ], + "supports": { + "html": false, + "align": true, + "alignWide": false, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "__experimentalBorder": { + "__experimentalSkipSerialization": true, + "radius": true, + "width": true, + "color": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true + } + }, + "color": { + "text": false, + "background": false + }, + "filter": { + "duotone": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "selectors": { + "border": ".wp-block-avatar img", + "filter": { + "duotone": ".wp-block-avatar img" + } + }, + "editorStyle": "wp-block-avatar-editor", + "style": "wp-block-avatar" +} diff --git a/src/wp-includes/blocks/block.php b/src/wp-includes/blocks/block.php new file mode 100644 index 0000000000000..f09d5367a9c89 --- /dev/null +++ b/src/wp-includes/blocks/block.php @@ -0,0 +1,131 @@ +post_type ) { + return ''; + } + + if ( isset( $seen_refs[ $attributes['ref'] ] ) ) { + // WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent + // is set in `wp_debug_mode()`. + $is_debug = WP_DEBUG && WP_DEBUG_DISPLAY; + + return $is_debug ? + // translators: Visible only in the front end, this warning takes the place of a faulty block. + __( '[block rendering halted]' ) : + ''; + } + + if ( 'publish' !== $reusable_block->post_status || ! empty( $reusable_block->post_password ) ) { + return ''; + } + + $seen_refs[ $attributes['ref'] ] = true; + + // Handle embeds for reusable blocks. + global $wp_embed; + $content = $wp_embed->run_shortcode( $reusable_block->post_content ); + $content = $wp_embed->autoembed( $content ); + + // Back compat. + // For blocks that have not been migrated in the editor, add some back compat + // so that front-end rendering continues to work. + + // This matches the `v2` deprecation. Removes the inner `values` property + // from every item. + if ( isset( $attributes['content'] ) ) { + foreach ( $attributes['content'] as &$content_data ) { + if ( isset( $content_data['values'] ) ) { + $is_assoc_array = is_array( $content_data['values'] ) && ! wp_is_numeric_array( $content_data['values'] ); + + if ( $is_assoc_array ) { + $content_data = $content_data['values']; + } + } + } + } + + // This matches the `v1` deprecation. Rename `overrides` to `content`. + if ( isset( $attributes['overrides'] ) && ! isset( $attributes['content'] ) ) { + $attributes['content'] = $attributes['overrides']; + } + + // Apply Block Hooks. + $content = apply_block_hooks_to_content_from_post_object( $content, $reusable_block ); + + /** + * We attach the blocks from $content as inner blocks to the Synced Pattern block instance. + * This ensures that block context available to the Synced Pattern block instance is provided to + * those blocks. + */ + $block_instance->parsed_block['innerBlocks'] = parse_blocks( $content ); + $block_instance->parsed_block['innerContent'] = array_fill( 0, count( $block_instance->parsed_block['innerBlocks'] ), null ); + if ( method_exists( $block_instance, 'refresh_context_dependents' ) ) { + // WP_Block::refresh_context_dependents() was introduced in WordPress 6.8. + $block_instance->refresh_context_dependents(); + } else { + // This branch can be removed once Gutenberg requires WordPress 6.8 or later. + if ( ! class_exists( 'WP_Block_Cloner' ) ) { + // phpcs:ignore Gutenberg.Commenting.SinceTag.MissingClassSinceTag + class WP_Block_Cloner extends WP_Block { + /** + * Static methods of subclasses have access to protected properties + * of instances of the parent class. + * In this case, this gives us access to `available_context` and `registry`. + */ + // phpcs:ignore Gutenberg.Commenting.SinceTag.MissingMethodSinceTag + public static function clone_instance( $instance ) { + return new WP_Block( + $instance->parsed_block, + $instance->available_context, + $instance->registry + ); + } + } + } + $block_instance = WP_Block_Cloner::clone_instance( $block_instance ); + } + + $content = $block_instance->render( array( 'dynamic' => false ) ); + unset( $seen_refs[ $attributes['ref'] ] ); + + return $content; +} + +/** + * Registers the `core/block` block. + * + * @since 5.3.0 + */ +function register_block_core_block() { + register_block_type_from_metadata( + __DIR__ . '/block', + array( + 'render_callback' => 'render_block_core_block', + ) + ); +} +add_action( 'init', 'register_block_core_block' ); diff --git a/src/wp-includes/blocks/block/block.json b/src/wp-includes/blocks/block/block.json new file mode 100644 index 0000000000000..fdce3bcc02e07 --- /dev/null +++ b/src/wp-includes/blocks/block/block.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/block", + "title": "Pattern", + "category": "reusable", + "description": "Reuse this design across your site.", + "keywords": [ "reusable" ], + "textdomain": "default", + "attributes": { + "ref": { + "type": "number" + }, + "content": { + "type": "object", + "default": {} + } + }, + "providesContext": { + "pattern/overrides": "content" + }, + "supports": { + "customClassName": false, + "html": false, + "inserter": false, + "renaming": false, + "interactivity": { + "clientNavigation": true + } + } +} diff --git a/src/wp-includes/blocks/blocks-json.php b/src/wp-includes/blocks/blocks-json.php new file mode 100644 index 0000000000000..74006dedb2e3f --- /dev/null +++ b/src/wp-includes/blocks/blocks-json.php @@ -0,0 +1,8198 @@ + array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/accordion', + 'title' => 'Accordion', + 'category' => 'design', + 'description' => 'Displays a foldable layout that groups content in collapsible sections.', + 'example' => array( + + ), + 'supports' => array( + 'anchor' => true, + 'html' => false, + 'align' => array( + 'wide', + 'full' + ), + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + 'color' => array( + 'background' => true, + 'gradients' => true + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'spacing' => array( + 'padding' => true, + 'margin' => array( + 'top', + 'bottom' + ), + 'blockGap' => true + ), + 'shadow' => true, + 'layout' => true, + 'ariaLabel' => true, + 'interactivity' => true, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'contentRole' => true + ), + 'attributes' => array( + 'iconPosition' => array( + 'type' => 'string', + 'default' => 'right' + ), + 'showIcon' => array( + 'type' => 'boolean', + 'default' => true + ), + 'autoclose' => array( + 'type' => 'boolean', + 'default' => false + ), + 'headingLevel' => array( + 'type' => 'number', + 'default' => 3 + ), + 'levelOptions' => array( + 'type' => 'array' + ) + ), + 'providesContext' => array( + 'core/accordion-icon-position' => 'iconPosition', + 'core/accordion-show-icon' => 'showIcon', + 'core/accordion-heading-level' => 'headingLevel' + ), + 'allowedBlocks' => array( + 'core/accordion-item' + ), + 'textdomain' => 'default', + 'viewScriptModule' => '@wordpress/block-library/accordion/view' + ), + 'accordion-heading' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/accordion-heading', + 'title' => 'Accordion Heading', + 'category' => 'design', + 'description' => 'Displays a heading that toggles the accordion panel.', + 'parent' => array( + 'core/accordion-item' + ), + 'usesContext' => array( + 'core/accordion-icon-position', + 'core/accordion-show-icon', + 'core/accordion-heading-level' + ), + 'supports' => array( + 'anchor' => true, + 'color' => array( + 'background' => true, + 'gradients' => true + ), + 'align' => false, + 'interactivity' => true, + 'spacing' => array( + 'padding' => true, + '__experimentalDefaultControls' => array( + 'padding' => true + ), + '__experimentalSkipSerialization' => true, + '__experimentalSelector' => '.wp-block-accordion-heading__toggle' + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'typography' => array( + '__experimentalSkipSerialization' => array( + 'textDecoration', + 'letterSpacing' + ), + 'fontSize' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true, + 'fontFamily' => true + ) + ), + 'shadow' => true, + 'blockVisibility' => false, + 'lock' => false + ), + 'selectors' => array( + 'typography' => array( + 'letterSpacing' => '.wp-block-accordion-heading .wp-block-accordion-heading__toggle-title', + 'textDecoration' => '.wp-block-accordion-heading .wp-block-accordion-heading__toggle-title' + ) + ), + 'attributes' => array( + 'openByDefault' => array( + 'type' => 'boolean', + 'default' => false + ), + 'title' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => '.wp-block-accordion-heading__toggle-title', + 'role' => 'content' + ), + 'level' => array( + 'type' => 'number' + ), + 'iconPosition' => array( + 'type' => 'string', + 'enum' => array( + 'left', + 'right' + ), + 'default' => 'right' + ), + 'showIcon' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'textdomain' => 'default' + ), + 'accordion-item' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/accordion-item', + 'title' => 'Accordion Item', + 'category' => 'design', + 'description' => 'Wraps the heading and panel in one unit.', + 'parent' => array( + 'core/accordion' + ), + 'allowedBlocks' => array( + 'core/accordion-heading', + 'core/accordion-panel' + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'background' => true, + 'gradients' => true + ), + 'interactivity' => true, + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ), + 'blockGap' => true + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'shadow' => true, + 'layout' => array( + 'allowEditing' => false + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'contentRole' => true + ), + 'attributes' => array( + 'openByDefault' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'textdomain' => 'default', + 'style' => 'wp-block-accordion-item' + ), + 'accordion-panel' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/accordion-panel', + 'title' => 'Accordion Panel', + 'category' => 'design', + 'description' => 'Contains the hidden or revealed content beneath the heading.', + 'parent' => array( + 'core/accordion-item' + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'background' => true, + 'gradients' => true + ), + 'interactivity' => true, + 'spacing' => array( + 'padding' => true, + 'blockGap' => true, + '__experimentalDefaultControls' => array( + 'padding' => true, + 'blockGap' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'shadow' => true, + 'layout' => array( + 'allowEditing' => false + ), + 'blockVisibility' => false, + 'contentRole' => true, + 'allowedBlocks' => true, + 'lock' => false + ), + 'attributes' => array( + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ), + 'default' => false + ), + 'openByDefault' => array( + 'type' => 'boolean', + 'default' => false + ), + 'isSelected' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'textdomain' => 'default', + 'style' => 'wp-block-accordion-panel' + ), + 'archives' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/archives', + 'title' => 'Archives', + 'category' => 'widgets', + 'description' => 'Display a date archive of your posts.', + 'textdomain' => 'default', + 'attributes' => array( + 'displayAsDropdown' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showLabel' => array( + 'type' => 'boolean', + 'default' => true + ), + 'showPostCounts' => array( + 'type' => 'boolean', + 'default' => false + ), + 'type' => array( + 'type' => 'string', + 'default' => 'monthly' + ) + ), + 'supports' => array( + 'align' => true, + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-archives-editor' + ), + 'audio' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/audio', + 'title' => 'Audio', + 'category' => 'media', + 'description' => 'Embed a simple audio player.', + 'keywords' => array( + 'music', + 'sound', + 'podcast', + 'recording' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'blob' => array( + 'type' => 'string', + 'role' => 'local' + ), + 'src' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'audio', + 'attribute' => 'src', + 'role' => 'content' + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'figcaption', + 'role' => 'content' + ), + 'id' => array( + 'type' => 'number', + 'role' => 'content' + ), + 'autoplay' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'audio', + 'attribute' => 'autoplay' + ), + 'loop' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'audio', + 'attribute' => 'loop' + ), + 'preload' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'audio', + 'attribute' => 'preload' + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-audio-editor', + 'style' => 'wp-block-audio' + ), + 'avatar' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/avatar', + 'title' => 'Avatar', + 'category' => 'theme', + 'description' => 'Add a user’s avatar.', + 'textdomain' => 'default', + 'attributes' => array( + 'userId' => array( + 'type' => 'number' + ), + 'size' => array( + 'type' => 'number', + 'default' => 96 + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self' + ) + ), + 'usesContext' => array( + 'postType', + 'postId', + 'commentId' + ), + 'supports' => array( + 'html' => false, + 'align' => true, + 'alignWide' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + '__experimentalBorder' => array( + '__experimentalSkipSerialization' => true, + 'radius' => true, + 'width' => true, + 'color' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true + ) + ), + 'color' => array( + 'text' => false, + 'background' => false + ), + 'filter' => array( + 'duotone' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'selectors' => array( + 'border' => '.wp-block-avatar img', + 'filter' => array( + 'duotone' => '.wp-block-avatar img' + ) + ), + 'editorStyle' => 'wp-block-avatar-editor', + 'style' => 'wp-block-avatar' + ), + 'block' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/block', + 'title' => 'Pattern', + 'category' => 'reusable', + 'description' => 'Reuse this design across your site.', + 'keywords' => array( + 'reusable' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'ref' => array( + 'type' => 'number' + ), + 'content' => array( + 'type' => 'object', + 'default' => array( + + ) + ) + ), + 'providesContext' => array( + 'pattern/overrides' => 'content' + ), + 'supports' => array( + 'customClassName' => false, + 'html' => false, + 'inserter' => false, + 'renaming' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'button' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/button', + 'title' => 'Button', + 'category' => 'design', + 'parent' => array( + 'core/buttons' + ), + 'description' => 'Prompt visitors to take action with a button-style link.', + 'keywords' => array( + 'link' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'tagName' => array( + 'type' => 'string', + 'enum' => array( + 'a', + 'button' + ), + 'default' => 'a' + ), + 'type' => array( + 'type' => 'string', + 'default' => 'button' + ), + 'textAlign' => array( + 'type' => 'string' + ), + 'url' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a', + 'attribute' => 'href', + 'role' => 'content' + ), + 'title' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a,button', + 'attribute' => 'title', + 'role' => 'content' + ), + 'text' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'a,button', + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a', + 'attribute' => 'target', + 'role' => 'content' + ), + 'rel' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a', + 'attribute' => 'rel', + 'role' => 'content' + ), + 'placeholder' => array( + 'type' => 'string' + ), + 'backgroundColor' => array( + 'type' => 'string' + ), + 'textColor' => array( + 'type' => 'string' + ), + 'gradient' => array( + 'type' => 'string' + ), + 'width' => array( + 'type' => 'number' + ) + ), + 'supports' => array( + 'anchor' => true, + 'splitting' => true, + 'align' => false, + 'alignWide' => false, + 'color' => array( + '__experimentalSkipSerialization' => true, + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + '__experimentalSkipSerialization' => array( + 'fontSize', + 'lineHeight', + 'fontFamily', + 'fontWeight', + 'fontStyle', + 'textTransform', + 'textDecoration', + 'letterSpacing' + ), + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'reusable' => false, + 'shadow' => array( + '__experimentalSkipSerialization' => true + ), + 'spacing' => array( + '__experimentalSkipSerialization' => true, + 'padding' => array( + 'horizontal', + 'vertical' + ), + '__experimentalDefaultControls' => array( + 'padding' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'styles' => array( + array( + 'name' => 'fill', + 'label' => 'Fill', + 'isDefault' => true + ), + array( + 'name' => 'outline', + 'label' => 'Outline' + ) + ), + 'editorStyle' => 'wp-block-button-editor', + 'style' => 'wp-block-button', + 'selectors' => array( + 'root' => '.wp-block-button .wp-block-button__link', + 'typography' => array( + 'writingMode' => '.wp-block-button' + ) + ) + ), + 'buttons' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/buttons', + 'title' => 'Buttons', + 'category' => 'design', + 'allowedBlocks' => array( + 'core/button' + ), + 'description' => 'Prompt visitors to take action with a group of button-style links.', + 'keywords' => array( + 'link' + ), + 'textdomain' => 'default', + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + '__experimentalExposeControlsToChildren' => true, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'spacing' => array( + 'blockGap' => array( + 'horizontal', + 'vertical' + ), + 'padding' => true, + 'margin' => array( + 'top', + 'bottom' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'default' => array( + 'type' => 'flex' + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'contentRole' => true + ), + 'editorStyle' => 'wp-block-buttons-editor', + 'style' => 'wp-block-buttons' + ), + 'calendar' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/calendar', + 'title' => 'Calendar', + 'category' => 'widgets', + 'description' => 'A calendar of your site’s posts.', + 'keywords' => array( + 'posts', + 'archive' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'month' => array( + 'type' => 'integer' + ), + 'year' => array( + 'type' => 'integer' + ) + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'color' => array( + 'link' => true, + '__experimentalSkipSerialization' => array( + 'text', + 'background' + ), + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ), + '__experimentalSelector' => 'table, th' + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-calendar' + ), + 'categories' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/categories', + 'title' => 'Terms List', + 'category' => 'widgets', + 'description' => 'Display a list of all terms of a given taxonomy.', + 'keywords' => array( + 'categories' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'taxonomy' => array( + 'type' => 'string', + 'default' => 'category' + ), + 'displayAsDropdown' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showHierarchy' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showPostCounts' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showOnlyTopLevel' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showEmpty' => array( + 'type' => 'boolean', + 'default' => false + ), + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'showLabel' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'usesContext' => array( + 'enhancedPagination' + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'editorStyle' => 'wp-block-categories-editor', + 'style' => 'wp-block-categories' + ), + 'code' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/code', + 'title' => 'Code', + 'category' => 'text', + 'description' => 'Display code snippets that respect your spacing and tabs.', + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'code', + '__unstablePreserveWhiteSpace' => true, + 'role' => 'content' + ) + ), + 'supports' => array( + 'align' => array( + 'wide' + ), + 'anchor' => true, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ), + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'width' => true, + 'color' => true + ) + ), + 'color' => array( + 'text' => true, + 'background' => true, + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-code' + ), + 'column' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/column', + 'title' => 'Column', + 'category' => 'design', + 'parent' => array( + 'core/columns' + ), + 'description' => 'A single column within a columns block.', + 'textdomain' => 'default', + 'attributes' => array( + 'verticalAlignment' => array( + 'type' => 'string' + ), + 'width' => array( + 'type' => 'string' + ), + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ) + ) + ), + 'supports' => array( + '__experimentalOnEnter' => true, + 'anchor' => true, + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'button' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'shadow' => true, + 'spacing' => array( + 'blockGap' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'padding' => true, + 'blockGap' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'layout' => true, + 'interactivity' => array( + 'clientNavigation' => true + ), + 'allowedBlocks' => true + ) + ), + 'columns' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/columns', + 'title' => 'Columns', + 'category' => 'design', + 'allowedBlocks' => array( + 'core/column' + ), + 'description' => 'Display content in multiple columns, with blocks added to each column.', + 'textdomain' => 'default', + 'attributes' => array( + 'verticalAlignment' => array( + 'type' => 'string' + ), + 'isStackedOnMobile' => array( + 'type' => 'boolean', + 'default' => true + ), + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ) + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + 'heading' => true, + 'button' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'blockGap' => array( + '__experimentalDefault' => '2em', + 'sides' => array( + 'horizontal', + 'vertical' + ) + ), + 'margin' => array( + 'top', + 'bottom' + ), + 'padding' => true, + '__experimentalDefaultControls' => array( + 'padding' => true, + 'blockGap' => true + ) + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'allowEditing' => false, + 'default' => array( + 'type' => 'flex', + 'flexWrap' => 'nowrap' + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'shadow' => true + ), + 'editorStyle' => 'wp-block-columns-editor', + 'style' => 'wp-block-columns' + ), + 'comment-author-name' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-author-name', + 'title' => 'Comment Author Name', + 'category' => 'theme', + 'ancestor' => array( + 'core/comment-template' + ), + 'description' => 'Displays the name of the author of the comment.', + 'textdomain' => 'default', + 'attributes' => array( + 'isLink' => array( + 'type' => 'boolean', + 'default' => true + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self' + ), + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'commentId' + ), + 'supports' => array( + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-comment-author-name' + ), + 'comment-content' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-content', + 'title' => 'Comment Content', + 'category' => 'theme', + 'ancestor' => array( + 'core/comment-template' + ), + 'description' => 'Displays the contents of a comment.', + 'textdomain' => 'default', + 'usesContext' => array( + 'commentId' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'spacing' => array( + 'padding' => array( + 'horizontal', + 'vertical' + ), + '__experimentalDefaultControls' => array( + 'padding' => true + ) + ), + 'html' => false + ), + 'style' => 'wp-block-comment-content' + ), + 'comment-date' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-date', + 'title' => 'Comment Date', + 'category' => 'theme', + 'ancestor' => array( + 'core/comment-template' + ), + 'description' => 'Displays the date on which the comment was posted.', + 'textdomain' => 'default', + 'attributes' => array( + 'format' => array( + 'type' => 'string' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'usesContext' => array( + 'commentId' + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-comment-date' + ), + 'comment-edit-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-edit-link', + 'title' => 'Comment Edit Link', + 'category' => 'theme', + 'ancestor' => array( + 'core/comment-template' + ), + 'description' => 'Displays a link to edit the comment in the WordPress Dashboard. This link is only visible to users with the edit comment capability.', + 'textdomain' => 'default', + 'usesContext' => array( + 'commentId' + ), + 'attributes' => array( + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self' + ), + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'link' => true, + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'style' => 'wp-block-comment-edit-link' + ), + 'comment-reply-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-reply-link', + 'title' => 'Comment Reply Link', + 'category' => 'theme', + 'ancestor' => array( + 'core/comment-template' + ), + 'description' => 'Displays a link to reply to a comment.', + 'textdomain' => 'default', + 'usesContext' => array( + 'commentId' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'color' => array( + 'gradients' => true, + 'link' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'html' => false + ), + 'style' => 'wp-block-comment-reply-link' + ), + 'comment-template' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comment-template', + 'title' => 'Comment Template', + 'category' => 'design', + 'parent' => array( + 'core/comments' + ), + 'description' => 'Contains the block elements used to display a comment, like the title, date, author, avatar and more.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId' + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'reusable' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-comment-template' + ), + 'comments' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments', + 'title' => 'Comments', + 'category' => 'theme', + 'description' => 'An advanced block that allows displaying post comments using different visual configurations.', + 'textdomain' => 'default', + 'attributes' => array( + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ), + 'legacy' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'editorStyle' => 'wp-block-comments-editor', + 'usesContext' => array( + 'postId', + 'postType' + ) + ), + 'comments-pagination' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments-pagination', + 'title' => 'Comments Pagination', + 'category' => 'theme', + 'parent' => array( + 'core/comments' + ), + 'allowedBlocks' => array( + 'core/comments-pagination-previous', + 'core/comments-pagination-numbers', + 'core/comments-pagination-next' + ), + 'description' => 'Displays a paginated navigation to next/previous set of comments, when applicable.', + 'textdomain' => 'default', + 'attributes' => array( + 'paginationArrow' => array( + 'type' => 'string', + 'default' => 'none' + ) + ), + 'example' => array( + 'attributes' => array( + 'paginationArrow' => 'none' + ) + ), + 'providesContext' => array( + 'comments/paginationArrow' => 'paginationArrow' + ), + 'supports' => array( + 'align' => true, + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'default' => array( + 'type' => 'flex' + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-comments-pagination-editor', + 'style' => 'wp-block-comments-pagination' + ), + 'comments-pagination-next' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments-pagination-next', + 'title' => 'Comments Next Page', + 'category' => 'theme', + 'parent' => array( + 'core/comments-pagination' + ), + 'description' => 'Displays the next comment\'s page link.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'postId', + 'comments/paginationArrow' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'comments-pagination-numbers' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments-pagination-numbers', + 'title' => 'Comments Page Numbers', + 'category' => 'theme', + 'parent' => array( + 'core/comments-pagination' + ), + 'description' => 'Displays a list of page numbers for comments pagination.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'comments-pagination-previous' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments-pagination-previous', + 'title' => 'Comments Previous Page', + 'category' => 'theme', + 'parent' => array( + 'core/comments-pagination' + ), + 'description' => 'Displays the previous comment\'s page link.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'postId', + 'comments/paginationArrow' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'comments-title' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/comments-title', + 'title' => 'Comments Title', + 'category' => 'theme', + 'ancestor' => array( + 'core/comments' + ), + 'description' => 'Displays a title with the number of comments.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId', + 'postType' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'showPostTitle' => array( + 'type' => 'boolean', + 'default' => true + ), + 'showCommentsCount' => array( + 'type' => 'boolean', + 'default' => true + ), + 'level' => array( + 'type' => 'number', + 'default' => 2 + ), + 'levelOptions' => array( + 'type' => 'array' + ) + ), + 'supports' => array( + 'anchor' => false, + 'align' => true, + 'html' => false, + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true, + '__experimentalFontFamily' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'cover' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/cover', + 'title' => 'Cover', + 'category' => 'media', + 'description' => 'Add an image or video with a text overlay.', + 'textdomain' => 'default', + 'attributes' => array( + 'url' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'useFeaturedImage' => array( + 'type' => 'boolean', + 'default' => false + ), + 'id' => array( + 'type' => 'number' + ), + 'alt' => array( + 'type' => 'string', + 'default' => '' + ), + 'hasParallax' => array( + 'type' => 'boolean', + 'default' => false + ), + 'isRepeated' => array( + 'type' => 'boolean', + 'default' => false + ), + 'dimRatio' => array( + 'type' => 'number', + 'default' => 100 + ), + 'overlayColor' => array( + 'type' => 'string' + ), + 'customOverlayColor' => array( + 'type' => 'string' + ), + 'isUserOverlayColor' => array( + 'type' => 'boolean' + ), + 'backgroundType' => array( + 'type' => 'string', + 'default' => 'image' + ), + 'focalPoint' => array( + 'type' => 'object' + ), + 'minHeight' => array( + 'type' => 'number' + ), + 'minHeightUnit' => array( + 'type' => 'string' + ), + 'gradient' => array( + 'type' => 'string' + ), + 'customGradient' => array( + 'type' => 'string' + ), + 'contentPosition' => array( + 'type' => 'string' + ), + 'isDark' => array( + 'type' => 'boolean', + 'default' => true + ), + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ) + ), + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ), + 'sizeSlug' => array( + 'type' => 'string' + ), + 'poster' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'poster' + ) + ), + 'usesContext' => array( + 'postId', + 'postType' + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + 'html' => false, + 'shadow' => true, + 'spacing' => array( + 'padding' => true, + 'margin' => array( + 'top', + 'bottom' + ), + 'blockGap' => true, + '__experimentalDefaultControls' => array( + 'padding' => true, + 'blockGap' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'color' => array( + 'heading' => true, + 'text' => true, + 'background' => false, + '__experimentalSkipSerialization' => array( + 'gradients' + ), + 'enableContrastChecker' => false + ), + 'dimensions' => array( + 'aspectRatio' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'layout' => array( + 'allowJustification' => false + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'filter' => array( + 'duotone' => true + ), + 'allowedBlocks' => true + ), + 'selectors' => array( + 'filter' => array( + 'duotone' => '.wp-block-cover > .wp-block-cover__image-background, .wp-block-cover > .wp-block-cover__video-background' + ) + ), + 'editorStyle' => 'wp-block-cover-editor', + 'style' => 'wp-block-cover' + ), + 'details' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/details', + 'title' => 'Details', + 'category' => 'text', + 'description' => 'Hide and show additional content.', + 'keywords' => array( + 'summary', + 'toggle', + 'disclosure' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'showContent' => array( + 'type' => 'boolean', + 'default' => false + ), + 'summary' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'summary', + 'role' => 'content' + ), + 'name' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'name', + 'selector' => '.wp-block-details' + ), + 'placeholder' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + '__experimentalOnEnter' => true, + 'align' => array( + 'wide', + 'full' + ), + 'anchor' => true, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'width' => true, + 'style' => true + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + 'blockGap' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'layout' => array( + 'allowEditing' => false + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'allowedBlocks' => true + ), + 'editorStyle' => 'wp-block-details-editor', + 'style' => 'wp-block-details' + ), + 'embed' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/embed', + 'title' => 'Embed', + 'category' => 'embed', + 'description' => 'Add a block that displays content pulled from other sites, like Twitter or YouTube.', + 'textdomain' => 'default', + 'attributes' => array( + 'url' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'figcaption', + 'role' => 'content' + ), + 'type' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'providerNameSlug' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'allowResponsive' => array( + 'type' => 'boolean', + 'default' => true + ), + 'responsive' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'previewable' => array( + 'type' => 'boolean', + 'default' => true, + 'role' => 'content' + ) + ), + 'supports' => array( + 'align' => true, + 'spacing' => array( + 'margin' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-embed-editor', + 'style' => 'wp-block-embed' + ), + 'file' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/file', + 'title' => 'File', + 'category' => 'media', + 'description' => 'Add a link to a downloadable file.', + 'keywords' => array( + 'document', + 'pdf', + 'download' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'id' => array( + 'type' => 'number' + ), + 'blob' => array( + 'type' => 'string', + 'role' => 'local' + ), + 'href' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'fileId' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a:not([download])', + 'attribute' => 'id' + ), + 'fileName' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'a:not([download])', + 'role' => 'content' + ), + 'textLinkHref' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a:not([download])', + 'attribute' => 'href', + 'role' => 'content' + ), + 'textLinkTarget' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'a:not([download])', + 'attribute' => 'target' + ), + 'showDownloadButton' => array( + 'type' => 'boolean', + 'default' => true + ), + 'downloadButtonText' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'a[download]', + 'role' => 'content' + ), + 'displayPreview' => array( + 'type' => 'boolean' + ), + 'previewHeight' => array( + 'type' => 'number', + 'default' => 600 + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true, + 'link' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'interactivity' => true + ), + 'editorStyle' => 'wp-block-file-editor', + 'style' => 'wp-block-file' + ), + 'footnotes' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/footnotes', + 'title' => 'Footnotes', + 'category' => 'text', + 'description' => 'Display footnotes added to the page.', + 'keywords' => array( + 'references' + ), + 'textdomain' => 'default', + 'usesContext' => array( + 'postId', + 'postType' + ), + 'supports' => array( + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => false, + 'color' => false, + 'width' => false, + 'style' => false + ) + ), + 'color' => array( + 'background' => true, + 'link' => true, + 'text' => true, + '__experimentalDefaultControls' => array( + 'link' => true, + 'text' => true + ) + ), + 'html' => false, + 'multiple' => false, + 'reusable' => false, + 'inserter' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalTextDecoration' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-footnotes' + ), + 'freeform' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/freeform', + 'title' => 'Classic', + 'category' => 'text', + 'description' => 'Use the classic WordPress editor.', + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'string', + 'source' => 'raw' + ) + ), + 'supports' => array( + 'html' => false, + 'className' => false, + 'customClassName' => false, + 'lock' => false, + 'reusable' => false, + 'renaming' => false, + 'blockVisibility' => false + ), + 'editorStyle' => 'wp-block-freeform-editor' + ), + 'gallery' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/gallery', + 'title' => 'Gallery', + 'category' => 'media', + 'allowedBlocks' => array( + 'core/image' + ), + 'description' => 'Display multiple images in a rich gallery.', + 'keywords' => array( + 'images', + 'photos' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'images' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => '.blocks-gallery-item', + 'query' => array( + 'url' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'src' + ), + 'fullUrl' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'data-full-url' + ), + 'link' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'data-link' + ), + 'alt' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'alt', + 'default' => '' + ), + 'id' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'data-id' + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => '.blocks-gallery-item__caption' + ) + ) + ), + 'ids' => array( + 'type' => 'array', + 'items' => array( + 'type' => 'number' + ), + 'default' => array( + + ) + ), + 'shortCodeTransforms' => array( + 'type' => 'array', + 'items' => array( + 'type' => 'object' + ), + 'default' => array( + + ) + ), + 'columns' => array( + 'type' => 'number', + 'minimum' => 1, + 'maximum' => 8 + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => '.blocks-gallery-caption', + 'role' => 'content' + ), + 'imageCrop' => array( + 'type' => 'boolean', + 'default' => true + ), + 'randomOrder' => array( + 'type' => 'boolean', + 'default' => false + ), + 'fixedHeight' => array( + 'type' => 'boolean', + 'default' => true + ), + 'linkTarget' => array( + 'type' => 'string' + ), + 'linkTo' => array( + 'type' => 'string' + ), + 'sizeSlug' => array( + 'type' => 'string', + 'default' => 'large' + ), + 'allowResize' => array( + 'type' => 'boolean', + 'default' => false + ), + 'aspectRatio' => array( + 'type' => 'string', + 'default' => 'auto' + ) + ), + 'providesContext' => array( + 'allowResize' => 'allowResize', + 'imageCrop' => 'imageCrop', + 'fixedHeight' => 'fixedHeight' + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true + ) + ), + 'html' => false, + 'units' => array( + 'px', + 'em', + 'rem', + 'vh', + 'vw' + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + 'blockGap' => array( + 'horizontal', + 'vertical' + ), + '__experimentalSkipSerialization' => array( + 'blockGap' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true, + 'margin' => false, + 'padding' => false + ) + ), + 'color' => array( + 'text' => false, + 'background' => true, + 'gradients' => true + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'allowEditing' => false, + 'default' => array( + 'type' => 'flex' + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-gallery-editor', + 'style' => 'wp-block-gallery' + ), + 'group' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/group', + 'title' => 'Group', + 'category' => 'design', + 'description' => 'Gather blocks in a layout container.', + 'keywords' => array( + 'container', + 'wrapper', + 'row', + 'section' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ), + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ) + ) + ), + 'supports' => array( + '__experimentalOnEnter' => true, + '__experimentalOnMerge' => true, + '__experimentalSettings' => true, + 'align' => array( + 'wide', + 'full' + ), + 'anchor' => true, + 'ariaLabel' => true, + 'html' => false, + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'button' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'shadow' => true, + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ), + 'padding' => true, + 'blockGap' => true, + '__experimentalDefaultControls' => array( + 'padding' => true, + 'blockGap' => true + ) + ), + 'dimensions' => array( + 'minHeight' => true + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'position' => array( + 'sticky' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'layout' => array( + 'allowSizingOnChildren' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'allowedBlocks' => true + ), + 'editorStyle' => 'wp-block-group-editor', + 'style' => 'wp-block-group' + ), + 'heading' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/heading', + 'title' => 'Heading', + 'category' => 'text', + 'description' => 'Introduce new sections and organize content to help visitors (and search engines) understand the structure of your content.', + 'keywords' => array( + 'title', + 'subtitle' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'h1,h2,h3,h4,h5,h6', + 'role' => 'content' + ), + 'level' => array( + 'type' => 'number', + 'default' => 2 + ), + 'levelOptions' => array( + 'type' => 'array' + ), + 'placeholder' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'anchor' => true, + 'className' => true, + 'splitting' => true, + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalWritingMode' => true, + 'fitText' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__unstablePasteTextInline' => true, + '__experimentalSlashInserter' => true, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-heading-editor', + 'style' => 'wp-block-heading' + ), + 'home-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/home-link', + 'category' => 'design', + 'parent' => array( + 'core/navigation' + ), + 'title' => 'Home Link', + 'description' => 'Create a link that always points to the homepage of the site. Usually not necessary if there is already a site title link present in the header.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ) + ), + 'usesContext' => array( + 'textColor', + 'customTextColor', + 'backgroundColor', + 'customBackgroundColor', + 'fontSize', + 'customFontSize', + 'style' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-home-link-editor', + 'style' => 'wp-block-home-link' + ), + 'html' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/html', + 'title' => 'Custom HTML', + 'category' => 'widgets', + 'description' => 'Add custom HTML code and preview it as you edit.', + 'keywords' => array( + 'embed' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'string', + 'source' => 'raw', + 'role' => 'content' + ) + ), + 'supports' => array( + 'customClassName' => false, + 'className' => false, + 'html' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-html-editor' + ), + 'image' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/image', + 'title' => 'Image', + 'category' => 'media', + 'usesContext' => array( + 'allowResize', + 'imageCrop', + 'fixedHeight', + 'postId', + 'postType', + 'queryId' + ), + 'description' => 'Insert an image to make a visual statement.', + 'keywords' => array( + 'img', + 'photo', + 'picture' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'blob' => array( + 'type' => 'string', + 'role' => 'local' + ), + 'url' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'src', + 'role' => 'content' + ), + 'alt' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'alt', + 'default' => '', + 'role' => 'content' + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'figcaption', + 'role' => 'content' + ), + 'lightbox' => array( + 'type' => 'object', + 'enabled' => array( + 'type' => 'boolean' + ) + ), + 'title' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'img', + 'attribute' => 'title', + 'role' => 'content' + ), + 'href' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure > a', + 'attribute' => 'href', + 'role' => 'content' + ), + 'rel' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure > a', + 'attribute' => 'rel' + ), + 'linkClass' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure > a', + 'attribute' => 'class' + ), + 'id' => array( + 'type' => 'number', + 'role' => 'content' + ), + 'width' => array( + 'type' => 'string' + ), + 'height' => array( + 'type' => 'string' + ), + 'aspectRatio' => array( + 'type' => 'string' + ), + 'scale' => array( + 'type' => 'string' + ), + 'sizeSlug' => array( + 'type' => 'string' + ), + 'linkDestination' => array( + 'type' => 'string' + ), + 'linkTarget' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure > a', + 'attribute' => 'target' + ) + ), + 'supports' => array( + 'interactivity' => true, + 'align' => array( + 'left', + 'center', + 'right', + 'wide', + 'full' + ), + 'anchor' => true, + 'color' => array( + 'text' => false, + 'background' => false + ), + 'filter' => array( + 'duotone' => true + ), + 'spacing' => array( + 'margin' => true + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'width' => true + ) + ), + 'shadow' => array( + '__experimentalSkipSerialization' => true + ) + ), + 'selectors' => array( + 'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder', + 'shadow' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder', + 'filter' => array( + 'duotone' => '.wp-block-image img, .wp-block-image .components-placeholder' + ) + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'rounded', + 'label' => 'Rounded' + ) + ), + 'editorStyle' => 'wp-block-image-editor', + 'style' => 'wp-block-image' + ), + 'latest-comments' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/latest-comments', + 'title' => 'Latest Comments', + 'category' => 'widgets', + 'description' => 'Display a list of your most recent comments.', + 'keywords' => array( + 'recent comments' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'commentsToShow' => array( + 'type' => 'number', + 'default' => 5, + 'minimum' => 1, + 'maximum' => 100 + ), + 'displayAvatar' => array( + 'type' => 'boolean', + 'default' => true + ), + 'displayDate' => array( + 'type' => 'boolean', + 'default' => true + ), + 'displayExcerpt' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'supports' => array( + 'align' => true, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-latest-comments-editor', + 'style' => 'wp-block-latest-comments' + ), + 'latest-posts' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/latest-posts', + 'title' => 'Latest Posts', + 'category' => 'widgets', + 'description' => 'Display a list of your most recent posts.', + 'keywords' => array( + 'recent posts' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'categories' => array( + 'type' => 'array', + 'items' => array( + 'type' => 'object' + ) + ), + 'selectedAuthor' => array( + 'type' => 'number' + ), + 'postsToShow' => array( + 'type' => 'number', + 'default' => 5 + ), + 'displayPostContent' => array( + 'type' => 'boolean', + 'default' => false + ), + 'displayPostContentRadio' => array( + 'type' => 'string', + 'default' => 'excerpt' + ), + 'excerptLength' => array( + 'type' => 'number', + 'default' => 55 + ), + 'displayAuthor' => array( + 'type' => 'boolean', + 'default' => false + ), + 'displayPostDate' => array( + 'type' => 'boolean', + 'default' => false + ), + 'postLayout' => array( + 'type' => 'string', + 'default' => 'list' + ), + 'columns' => array( + 'type' => 'number', + 'default' => 3 + ), + 'order' => array( + 'type' => 'string', + 'default' => 'desc' + ), + 'orderBy' => array( + 'type' => 'string', + 'default' => 'date' + ), + 'displayFeaturedImage' => array( + 'type' => 'boolean', + 'default' => false + ), + 'featuredImageAlign' => array( + 'type' => 'string', + 'enum' => array( + 'left', + 'center', + 'right' + ) + ), + 'featuredImageSizeSlug' => array( + 'type' => 'string', + 'default' => 'thumbnail' + ), + 'featuredImageSizeWidth' => array( + 'type' => 'number', + 'default' => null + ), + 'featuredImageSizeHeight' => array( + 'type' => 'number', + 'default' => null + ), + 'addLinkToFeaturedImage' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-latest-posts-editor', + 'style' => 'wp-block-latest-posts' + ), + 'legacy-widget' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/legacy-widget', + 'title' => 'Legacy Widget', + 'category' => 'widgets', + 'description' => 'Display a legacy widget.', + 'textdomain' => 'default', + 'attributes' => array( + 'id' => array( + 'type' => 'string', + 'default' => null + ), + 'idBase' => array( + 'type' => 'string', + 'default' => null + ), + 'instance' => array( + 'type' => 'object', + 'default' => null + ) + ), + 'supports' => array( + 'html' => false, + 'customClassName' => false, + 'reusable' => false + ), + 'editorStyle' => 'wp-block-legacy-widget-editor' + ), + 'list' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/list', + 'title' => 'List', + 'category' => 'text', + 'allowedBlocks' => array( + 'core/list-item' + ), + 'description' => 'An organized collection of items displayed in a specific order.', + 'keywords' => array( + 'bullet list', + 'ordered list', + 'numbered list' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'ordered' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'values' => array( + 'type' => 'string', + 'source' => 'html', + 'selector' => 'ol,ul', + 'multiline' => 'li', + 'default' => '', + 'role' => 'content' + ), + 'type' => array( + 'type' => 'string' + ), + 'start' => array( + 'type' => 'number' + ), + 'reversed' => array( + 'type' => 'boolean' + ), + 'placeholder' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'anchor' => true, + 'html' => false, + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + '__unstablePasteTextInline' => true, + '__experimentalOnMerge' => true, + '__experimentalSlashInserter' => true, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'selectors' => array( + 'border' => '.wp-block-list:not(.wp-block-list .wp-block-list)' + ), + 'editorStyle' => 'wp-block-list-editor', + 'style' => 'wp-block-list' + ), + 'list-item' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/list-item', + 'title' => 'List Item', + 'category' => 'text', + 'parent' => array( + 'core/list' + ), + 'allowedBlocks' => array( + 'core/list' + ), + 'description' => 'An individual item within a list.', + 'textdomain' => 'default', + 'attributes' => array( + 'placeholder' => array( + 'type' => 'string' + ), + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'li', + 'role' => 'content' + ) + ), + 'supports' => array( + 'anchor' => true, + 'className' => false, + 'splitting' => true, + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + 'background' => true, + '__experimentalDefaultControls' => array( + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'selectors' => array( + 'root' => '.wp-block-list > li', + 'border' => '.wp-block-list:not(.wp-block-list .wp-block-list) > li' + ) + ), + 'loginout' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/loginout', + 'title' => 'Login/out', + 'category' => 'theme', + 'description' => 'Show login & logout links.', + 'keywords' => array( + 'login', + 'logout', + 'form' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'displayLoginAsForm' => array( + 'type' => 'boolean', + 'default' => false + ), + 'redirectToCurrent' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'className' => true, + 'color' => array( + 'background' => true, + 'text' => false, + 'gradients' => true, + 'link' => true + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-loginout' + ), + 'math' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/math', + 'title' => 'Math', + 'category' => 'text', + 'description' => 'Display mathematical notation using LaTeX.', + 'keywords' => array( + 'equation', + 'formula', + 'latex', + 'mathematics' + ), + 'textdomain' => 'default', + 'supports' => array( + 'html' => false + ), + 'attributes' => array( + 'latex' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'mathML' => array( + 'type' => 'string', + 'source' => 'html', + 'selector' => 'math' + ) + ) + ), + 'media-text' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/media-text', + 'title' => 'Media & Text', + 'category' => 'media', + 'description' => 'Set media and words side-by-side for a richer layout.', + 'keywords' => array( + 'image', + 'video' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'align' => array( + 'type' => 'string', + 'default' => 'none' + ), + 'mediaAlt' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure img', + 'attribute' => 'alt', + 'default' => '', + 'role' => 'content' + ), + 'mediaPosition' => array( + 'type' => 'string', + 'default' => 'left' + ), + 'mediaId' => array( + 'type' => 'number', + 'role' => 'content' + ), + 'mediaUrl' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure video,figure img', + 'attribute' => 'src', + 'role' => 'content' + ), + 'mediaLink' => array( + 'type' => 'string' + ), + 'linkDestination' => array( + 'type' => 'string' + ), + 'linkTarget' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure a', + 'attribute' => 'target' + ), + 'href' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure a', + 'attribute' => 'href', + 'role' => 'content' + ), + 'rel' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure a', + 'attribute' => 'rel' + ), + 'linkClass' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'figure a', + 'attribute' => 'class' + ), + 'mediaType' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'mediaWidth' => array( + 'type' => 'number', + 'default' => 50 + ), + 'mediaSizeSlug' => array( + 'type' => 'string' + ), + 'isStackedOnMobile' => array( + 'type' => 'boolean', + 'default' => true + ), + 'verticalAlignment' => array( + 'type' => 'string' + ), + 'imageFill' => array( + 'type' => 'boolean' + ), + 'focalPoint' => array( + 'type' => 'object' + ), + 'useFeaturedImage' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'usesContext' => array( + 'postId', + 'postType' + ), + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'allowedBlocks' => true + ), + 'editorStyle' => 'wp-block-media-text-editor', + 'style' => 'wp-block-media-text' + ), + 'missing' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/missing', + 'title' => 'Unsupported', + 'category' => 'text', + 'description' => 'Your site doesn’t include support for this block.', + 'textdomain' => 'default', + 'attributes' => array( + 'originalName' => array( + 'type' => 'string' + ), + 'originalUndelimitedContent' => array( + 'type' => 'string' + ), + 'originalContent' => array( + 'type' => 'string', + 'source' => 'raw' + ) + ), + 'supports' => array( + 'className' => false, + 'customClassName' => false, + 'inserter' => false, + 'html' => false, + 'lock' => false, + 'reusable' => false, + 'renaming' => false, + 'blockVisibility' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'more' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/more', + 'title' => 'More', + 'category' => 'design', + 'description' => 'Content before this block will be shown in the excerpt on your archives page.', + 'keywords' => array( + 'read more' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'customText' => array( + 'type' => 'string', + 'default' => '', + 'role' => 'content' + ), + 'noTeaser' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'supports' => array( + 'customClassName' => false, + 'className' => false, + 'html' => false, + 'multiple' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-more-editor' + ), + 'navigation' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/navigation', + 'title' => 'Navigation', + 'category' => 'theme', + 'allowedBlocks' => array( + 'core/navigation-link', + 'core/search', + 'core/social-links', + 'core/page-list', + 'core/spacer', + 'core/home-link', + 'core/site-title', + 'core/site-logo', + 'core/navigation-submenu', + 'core/loginout', + 'core/buttons' + ), + 'description' => 'A collection of blocks that allow visitors to get around your site.', + 'keywords' => array( + 'menu', + 'navigation', + 'links' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'ref' => array( + 'type' => 'number' + ), + 'textColor' => array( + 'type' => 'string' + ), + 'customTextColor' => array( + 'type' => 'string' + ), + 'rgbTextColor' => array( + 'type' => 'string' + ), + 'backgroundColor' => array( + 'type' => 'string' + ), + 'customBackgroundColor' => array( + 'type' => 'string' + ), + 'rgbBackgroundColor' => array( + 'type' => 'string' + ), + 'showSubmenuIcon' => array( + 'type' => 'boolean', + 'default' => true + ), + 'openSubmenusOnClick' => array( + 'type' => 'boolean', + 'default' => false + ), + 'overlayMenu' => array( + 'type' => 'string', + 'default' => 'mobile' + ), + 'icon' => array( + 'type' => 'string', + 'default' => 'handle' + ), + 'hasIcon' => array( + 'type' => 'boolean', + 'default' => true + ), + '__unstableLocation' => array( + 'type' => 'string' + ), + 'overlayBackgroundColor' => array( + 'type' => 'string' + ), + 'customOverlayBackgroundColor' => array( + 'type' => 'string' + ), + 'overlayTextColor' => array( + 'type' => 'string' + ), + 'customOverlayTextColor' => array( + 'type' => 'string' + ), + 'maxNestingLevel' => array( + 'type' => 'number', + 'default' => 5 + ), + 'templateLock' => array( + 'type' => array( + 'string', + 'boolean' + ), + 'enum' => array( + 'all', + 'insert', + 'contentOnly', + false + ) + ) + ), + 'providesContext' => array( + 'textColor' => 'textColor', + 'customTextColor' => 'customTextColor', + 'backgroundColor' => 'backgroundColor', + 'customBackgroundColor' => 'customBackgroundColor', + 'overlayTextColor' => 'overlayTextColor', + 'customOverlayTextColor' => 'customOverlayTextColor', + 'overlayBackgroundColor' => 'overlayBackgroundColor', + 'customOverlayBackgroundColor' => 'customOverlayBackgroundColor', + 'fontSize' => 'fontSize', + 'customFontSize' => 'customFontSize', + 'showSubmenuIcon' => 'showSubmenuIcon', + 'openSubmenusOnClick' => 'openSubmenusOnClick', + 'style' => 'style', + 'maxNestingLevel' => 'maxNestingLevel' + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'ariaLabel' => true, + 'html' => false, + 'inserter' => true, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalTextTransform' => true, + '__experimentalFontFamily' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextDecoration' => true, + '__experimentalSkipSerialization' => array( + 'textDecoration' + ), + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'spacing' => array( + 'blockGap' => true, + 'units' => array( + 'px', + 'em', + 'rem', + 'vh', + 'vw' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true + ) + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'allowVerticalAlignment' => false, + 'allowSizingOnChildren' => true, + 'default' => array( + 'type' => 'flex' + ) + ), + 'interactivity' => true, + 'renaming' => false, + 'contentRole' => true + ), + 'editorStyle' => 'wp-block-navigation-editor', + 'style' => 'wp-block-navigation' + ), + 'navigation-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/navigation-link', + 'title' => 'Custom Link', + 'category' => 'design', + 'parent' => array( + 'core/navigation' + ), + 'allowedBlocks' => array( + 'core/navigation-link', + 'core/navigation-submenu', + 'core/page-list' + ), + 'description' => 'Add a page, link, or another item to your navigation.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'type' => array( + 'type' => 'string' + ), + 'description' => array( + 'type' => 'string' + ), + 'rel' => array( + 'type' => 'string' + ), + 'id' => array( + 'type' => 'number' + ), + 'opensInNewTab' => array( + 'type' => 'boolean', + 'default' => false + ), + 'url' => array( + 'type' => 'string' + ), + 'title' => array( + 'type' => 'string' + ), + 'kind' => array( + 'type' => 'string' + ), + 'isTopLevelLink' => array( + 'type' => 'boolean' + ) + ), + 'usesContext' => array( + 'textColor', + 'customTextColor', + 'backgroundColor', + 'customBackgroundColor', + 'overlayTextColor', + 'customOverlayTextColor', + 'overlayBackgroundColor', + 'customOverlayBackgroundColor', + 'fontSize', + 'customFontSize', + 'showSubmenuIcon', + 'maxNestingLevel', + 'style' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + '__experimentalSlashInserter' => true, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'renaming' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-navigation-link-editor', + 'style' => 'wp-block-navigation-link' + ), + 'navigation-submenu' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/navigation-submenu', + 'title' => 'Submenu', + 'category' => 'design', + 'parent' => array( + 'core/navigation' + ), + 'description' => 'Add a submenu to your navigation.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'type' => array( + 'type' => 'string' + ), + 'description' => array( + 'type' => 'string' + ), + 'rel' => array( + 'type' => 'string' + ), + 'id' => array( + 'type' => 'number' + ), + 'opensInNewTab' => array( + 'type' => 'boolean', + 'default' => false + ), + 'url' => array( + 'type' => 'string' + ), + 'title' => array( + 'type' => 'string' + ), + 'kind' => array( + 'type' => 'string' + ), + 'isTopLevelItem' => array( + 'type' => 'boolean' + ) + ), + 'usesContext' => array( + 'textColor', + 'customTextColor', + 'backgroundColor', + 'customBackgroundColor', + 'overlayTextColor', + 'customOverlayTextColor', + 'overlayBackgroundColor', + 'customOverlayBackgroundColor', + 'fontSize', + 'customFontSize', + 'showSubmenuIcon', + 'maxNestingLevel', + 'openSubmenusOnClick', + 'style' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-navigation-submenu-editor', + 'style' => 'wp-block-navigation-submenu' + ), + 'nextpage' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/nextpage', + 'title' => 'Page Break', + 'category' => 'design', + 'description' => 'Separate your content into a multi-page experience.', + 'keywords' => array( + 'next page', + 'pagination' + ), + 'parent' => array( + 'core/post-content' + ), + 'textdomain' => 'default', + 'supports' => array( + 'customClassName' => false, + 'className' => false, + 'html' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-nextpage-editor' + ), + 'page-list' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/page-list', + 'title' => 'Page List', + 'category' => 'widgets', + 'allowedBlocks' => array( + 'core/page-list-item' + ), + 'description' => 'Display a list of all pages.', + 'keywords' => array( + 'menu', + 'navigation' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'parentPageID' => array( + 'type' => 'integer', + 'default' => 0 + ), + 'isNested' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'usesContext' => array( + 'textColor', + 'customTextColor', + 'backgroundColor', + 'customBackgroundColor', + 'overlayTextColor', + 'customOverlayTextColor', + 'overlayBackgroundColor', + 'customOverlayBackgroundColor', + 'fontSize', + 'customFontSize', + 'showSubmenuIcon', + 'style', + 'openSubmenusOnClick' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'color' => array( + 'text' => true, + 'background' => true, + 'link' => true, + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'spacing' => array( + 'padding' => true, + 'margin' => true, + '__experimentalDefaultControls' => array( + 'padding' => false, + 'margin' => false + ) + ), + 'contentRole' => true + ), + 'editorStyle' => 'wp-block-page-list-editor', + 'style' => 'wp-block-page-list' + ), + 'page-list-item' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/page-list-item', + 'title' => 'Page List Item', + 'category' => 'widgets', + 'parent' => array( + 'core/page-list' + ), + 'description' => 'Displays a page inside a list of all pages.', + 'keywords' => array( + 'page', + 'menu', + 'navigation' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'id' => array( + 'type' => 'number' + ), + 'label' => array( + 'type' => 'string' + ), + 'title' => array( + 'type' => 'string' + ), + 'link' => array( + 'type' => 'string' + ), + 'hasChildren' => array( + 'type' => 'boolean' + ) + ), + 'usesContext' => array( + 'textColor', + 'customTextColor', + 'backgroundColor', + 'customBackgroundColor', + 'overlayTextColor', + 'customOverlayTextColor', + 'overlayBackgroundColor', + 'customOverlayBackgroundColor', + 'fontSize', + 'customFontSize', + 'showSubmenuIcon', + 'style', + 'openSubmenusOnClick' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'lock' => false, + 'inserter' => false, + '__experimentalToolbar' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-page-list-editor', + 'style' => 'wp-block-page-list' + ), + 'paragraph' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/paragraph', + 'title' => 'Paragraph', + 'category' => 'text', + 'description' => 'Start with the basic building block of all narrative.', + 'keywords' => array( + 'text' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'align' => array( + 'type' => 'string' + ), + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'p', + 'role' => 'content' + ), + 'dropCap' => array( + 'type' => 'boolean', + 'default' => false + ), + 'placeholder' => array( + 'type' => 'string' + ), + 'direction' => array( + 'type' => 'string', + 'enum' => array( + 'ltr', + 'rtl' + ) + ) + ), + 'supports' => array( + 'splitting' => true, + 'anchor' => true, + 'className' => false, + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalTextDecoration' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalWritingMode' => true, + 'fitText' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalSelector' => 'p', + '__unstablePasteTextInline' => true, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-paragraph-editor', + 'style' => 'wp-block-paragraph' + ), + 'pattern' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/pattern', + 'title' => 'Pattern Placeholder', + 'category' => 'theme', + 'description' => 'Show a block pattern.', + 'supports' => array( + 'html' => false, + 'inserter' => false, + 'renaming' => false, + 'blockVisibility' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'textdomain' => 'default', + 'attributes' => array( + 'slug' => array( + 'type' => 'string' + ) + ) + ), + 'post-author' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-author', + 'title' => 'Author', + 'category' => 'theme', + 'description' => 'Display post author details such as name, avatar, and bio.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'avatarSize' => array( + 'type' => 'number', + 'default' => 48 + ), + 'showAvatar' => array( + 'type' => 'boolean', + 'default' => true + ), + 'showBio' => array( + 'type' => 'boolean' + ), + 'byline' => array( + 'type' => 'string' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ) + ), + 'usesContext' => array( + 'postType', + 'postId', + 'queryId' + ), + 'supports' => array( + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'filter' => array( + 'duotone' => true + ) + ), + 'selectors' => array( + 'filter' => array( + 'duotone' => '.wp-block-post-author .wp-block-post-author__avatar img' + ) + ), + 'editorStyle' => 'wp-block-post-author-editor', + 'style' => 'wp-block-post-author' + ), + 'post-author-biography' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-author-biography', + 'title' => 'Author Biography', + 'category' => 'theme', + 'description' => 'The author biography.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'postType', + 'postId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-author-biography' + ), + 'post-author-name' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-author-name', + 'title' => 'Author Name', + 'category' => 'theme', + 'description' => 'The author name.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ) + ), + 'usesContext' => array( + 'postType', + 'postId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-author-name' + ), + 'post-comments-count' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-comments-count', + 'title' => 'Comments Count', + 'category' => 'theme', + 'description' => 'Display a post\'s comments count.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'postId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-post-comments-count' + ), + 'post-comments-form' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-comments-form', + 'title' => 'Comments Form', + 'category' => 'theme', + 'description' => 'Display a post\'s comments form.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'postId', + 'postType' + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'editorStyle' => 'wp-block-post-comments-form-editor', + 'style' => array( + 'wp-block-post-comments-form', + 'wp-block-buttons', + 'wp-block-button' + ), + 'example' => array( + 'attributes' => array( + 'textAlign' => 'center' + ) + ) + ), + 'post-comments-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-comments-link', + 'title' => 'Comments Link', + 'category' => 'theme', + 'description' => 'Displays the link to the current post comments.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postType', + 'postId' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'link' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-comments-link' + ), + 'post-content' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-content', + 'title' => 'Content', + 'category' => 'theme', + 'description' => 'Displays the contents of a post or page.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId', + 'postType', + 'queryId' + ), + 'attributes' => array( + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ) + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'layout' => true, + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + 'dimensions' => array( + 'minHeight' => true + ), + 'spacing' => array( + 'blockGap' => true, + 'padding' => true, + 'margin' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => false, + 'text' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-content', + 'editorStyle' => 'wp-block-post-content-editor' + ), + 'post-date' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-date', + 'title' => 'Date', + 'category' => 'theme', + 'description' => 'Display a custom date.', + 'textdomain' => 'default', + 'attributes' => array( + 'datetime' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'textAlign' => array( + 'type' => 'string' + ), + 'format' => array( + 'type' => 'string' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ) + ), + 'usesContext' => array( + 'postId', + 'postType', + 'queryId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ) + ), + 'post-excerpt' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-excerpt', + 'title' => 'Excerpt', + 'category' => 'theme', + 'description' => 'Display the excerpt.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'moreText' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'showMoreOnNewLine' => array( + 'type' => 'boolean', + 'default' => true + ), + 'excerptLength' => array( + 'type' => 'number', + 'default' => 55 + ) + ), + 'usesContext' => array( + 'postId', + 'postType', + 'queryId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'editorStyle' => 'wp-block-post-excerpt-editor', + 'style' => 'wp-block-post-excerpt' + ), + 'post-featured-image' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-featured-image', + 'title' => 'Featured Image', + 'category' => 'theme', + 'description' => 'Display a post\'s featured image.', + 'textdomain' => 'default', + 'attributes' => array( + 'isLink' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'aspectRatio' => array( + 'type' => 'string' + ), + 'width' => array( + 'type' => 'string' + ), + 'height' => array( + 'type' => 'string' + ), + 'scale' => array( + 'type' => 'string', + 'default' => 'cover' + ), + 'sizeSlug' => array( + 'type' => 'string' + ), + 'rel' => array( + 'type' => 'string', + 'attribute' => 'rel', + 'default' => '', + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ), + 'overlayColor' => array( + 'type' => 'string' + ), + 'customOverlayColor' => array( + 'type' => 'string' + ), + 'dimRatio' => array( + 'type' => 'number', + 'default' => 0 + ), + 'gradient' => array( + 'type' => 'string' + ), + 'customGradient' => array( + 'type' => 'string' + ), + 'useFirstImageFromPost' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'usesContext' => array( + 'postId', + 'postType', + 'queryId' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'align' => array( + 'left', + 'right', + 'center', + 'wide', + 'full' + ), + 'color' => array( + 'text' => false, + 'background' => false + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'width' => true + ) + ), + 'filter' => array( + 'duotone' => true + ), + 'shadow' => array( + '__experimentalSkipSerialization' => true + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'selectors' => array( + 'border' => '.wp-block-post-featured-image img, .wp-block-post-featured-image .block-editor-media-placeholder, .wp-block-post-featured-image .wp-block-post-featured-image__overlay', + 'shadow' => '.wp-block-post-featured-image img, .wp-block-post-featured-image .components-placeholder', + 'filter' => array( + 'duotone' => '.wp-block-post-featured-image img, .wp-block-post-featured-image .wp-block-post-featured-image__placeholder, .wp-block-post-featured-image .components-placeholder__illustration, .wp-block-post-featured-image .components-placeholder::before' + ) + ), + 'editorStyle' => 'wp-block-post-featured-image-editor', + 'style' => 'wp-block-post-featured-image' + ), + 'post-navigation-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-navigation-link', + 'title' => 'Post Navigation Link', + 'category' => 'theme', + 'description' => 'Displays the next or previous post link that is adjacent to the current post.', + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'type' => array( + 'type' => 'string', + 'default' => 'next' + ), + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'showTitle' => array( + 'type' => 'boolean', + 'default' => false + ), + 'linkLabel' => array( + 'type' => 'boolean', + 'default' => false + ), + 'arrow' => array( + 'type' => 'string', + 'default' => 'none' + ), + 'taxonomy' => array( + 'type' => 'string', + 'default' => '' + ) + ), + 'usesContext' => array( + 'postType' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'link' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-post-navigation-link' + ), + 'post-template' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-template', + 'title' => 'Post Template', + 'category' => 'theme', + 'ancestor' => array( + 'core/query' + ), + 'description' => 'Contains the block elements used to render a post, like the title, date, featured image, content or excerpt, and more.', + 'textdomain' => 'default', + 'usesContext' => array( + 'queryId', + 'query', + 'displayLayout', + 'templateSlug', + 'previewPostType', + 'enhancedPagination', + 'postType' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'align' => array( + 'wide', + 'full' + ), + 'layout' => true, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + 'blockGap' => array( + '__experimentalDefault' => '1.25em' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true, + 'padding' => false, + 'margin' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'style' => 'wp-block-post-template', + 'editorStyle' => 'wp-block-post-template-editor' + ), + 'post-terms' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-terms', + 'title' => 'Post Terms', + 'category' => 'theme', + 'description' => 'Post terms.', + 'textdomain' => 'default', + 'attributes' => array( + 'term' => array( + 'type' => 'string' + ), + 'textAlign' => array( + 'type' => 'string' + ), + 'separator' => array( + 'type' => 'string', + 'default' => ', ' + ), + 'prefix' => array( + 'type' => 'string', + 'default' => '', + 'role' => 'content' + ), + 'suffix' => array( + 'type' => 'string', + 'default' => '', + 'role' => 'content' + ) + ), + 'usesContext' => array( + 'postId', + 'postType' + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-terms' + ), + 'post-time-to-read' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-time-to-read', + 'title' => 'Time to Read', + 'category' => 'theme', + 'description' => 'Show minutes required to finish reading the post. Can also show a word count.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId', + 'postType' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'displayAsRange' => array( + 'type' => 'boolean', + 'default' => true + ), + 'displayMode' => array( + 'type' => 'string', + 'default' => 'time' + ), + 'averageReadingSpeed' => array( + 'type' => 'number', + 'default' => 189 + ) + ), + 'supports' => array( + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'post-title' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/post-title', + 'title' => 'Title', + 'category' => 'theme', + 'description' => 'Displays the title of a post, page, or any other content-type.', + 'textdomain' => 'default', + 'usesContext' => array( + 'postId', + 'postType', + 'queryId' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'level' => array( + 'type' => 'number', + 'default' => 2 + ), + 'levelOptions' => array( + 'type' => 'array' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false, + 'role' => 'content' + ), + 'rel' => array( + 'type' => 'string', + 'attribute' => 'rel', + 'default' => '', + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ) + ), + 'example' => array( + 'viewportWidth' => 350 + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-post-title' + ), + 'preformatted' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/preformatted', + 'title' => 'Preformatted', + 'category' => 'text', + 'description' => 'Add text that respects your spacing and tabs, and also allows styling.', + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'pre', + '__unstablePreserveWhiteSpace' => true, + 'role' => 'content' + ) + ), + 'supports' => array( + 'anchor' => true, + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'padding' => true, + 'margin' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-preformatted' + ), + 'pullquote' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/pullquote', + 'title' => 'Pullquote', + 'category' => 'text', + 'description' => 'Give special visual emphasis to a quote from your text.', + 'textdomain' => 'default', + 'attributes' => array( + 'value' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'p', + 'role' => 'content' + ), + 'citation' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'cite', + 'role' => 'content' + ), + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'left', + 'right', + 'wide', + 'full' + ), + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'background' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'dimensions' => array( + 'minHeight' => true, + '__experimentalDefaultControls' => array( + 'minHeight' => false + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + '__experimentalStyle' => array( + 'typography' => array( + 'fontSize' => '1.5em', + 'lineHeight' => '1.6' + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-pullquote-editor', + 'style' => 'wp-block-pullquote' + ), + 'query' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query', + 'title' => 'Query Loop', + 'category' => 'theme', + 'description' => 'An advanced block that allows displaying post types based on different query parameters and visual configurations.', + 'keywords' => array( + 'posts', + 'list', + 'blog', + 'blogs', + 'custom post types' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'queryId' => array( + 'type' => 'number' + ), + 'query' => array( + 'type' => 'object', + 'default' => array( + 'perPage' => null, + 'pages' => 0, + 'offset' => 0, + 'postType' => 'post', + 'order' => 'desc', + 'orderBy' => 'date', + 'author' => '', + 'search' => '', + 'exclude' => array( + + ), + 'sticky' => '', + 'inherit' => true, + 'taxQuery' => null, + 'parents' => array( + + ), + 'format' => array( + + ) + ) + ), + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ), + 'namespace' => array( + 'type' => 'string' + ), + 'enhancedPagination' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'usesContext' => array( + 'templateSlug' + ), + 'providesContext' => array( + 'queryId' => 'queryId', + 'query' => 'query', + 'displayLayout' => 'displayLayout', + 'enhancedPagination' => 'enhancedPagination' + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'layout' => true, + 'interactivity' => true, + 'contentRole' => true + ), + 'editorStyle' => 'wp-block-query-editor' + ), + 'query-no-results' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-no-results', + 'title' => 'No Results', + 'category' => 'theme', + 'description' => 'Contains the block elements used to render content when no query results are found.', + 'ancestor' => array( + 'core/query' + ), + 'textdomain' => 'default', + 'usesContext' => array( + 'queryId', + 'query' + ), + 'supports' => array( + 'align' => true, + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'query-pagination' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-pagination', + 'title' => 'Pagination', + 'category' => 'theme', + 'ancestor' => array( + 'core/query' + ), + 'allowedBlocks' => array( + 'core/query-pagination-previous', + 'core/query-pagination-numbers', + 'core/query-pagination-next' + ), + 'description' => 'Displays a paginated navigation to next/previous set of posts, when applicable.', + 'textdomain' => 'default', + 'attributes' => array( + 'paginationArrow' => array( + 'type' => 'string', + 'default' => 'none' + ), + 'showLabel' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'usesContext' => array( + 'queryId', + 'query' + ), + 'providesContext' => array( + 'paginationArrow' => 'paginationArrow', + 'showLabel' => 'showLabel' + ), + 'supports' => array( + 'align' => true, + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'default' => array( + 'type' => 'flex' + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-query-pagination-editor', + 'style' => 'wp-block-query-pagination' + ), + 'query-pagination-next' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-pagination-next', + 'title' => 'Next Page', + 'category' => 'theme', + 'parent' => array( + 'core/query-pagination' + ), + 'description' => 'Displays the next posts page link.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'queryId', + 'query', + 'paginationArrow', + 'showLabel', + 'enhancedPagination' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'query-pagination-numbers' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-pagination-numbers', + 'title' => 'Page Numbers', + 'category' => 'theme', + 'parent' => array( + 'core/query-pagination' + ), + 'description' => 'Displays a list of page numbers for pagination.', + 'textdomain' => 'default', + 'attributes' => array( + 'midSize' => array( + 'type' => 'number', + 'default' => 2 + ) + ), + 'usesContext' => array( + 'queryId', + 'query', + 'enhancedPagination' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-query-pagination-numbers-editor' + ), + 'query-pagination-previous' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-pagination-previous', + 'title' => 'Previous Page', + 'category' => 'theme', + 'parent' => array( + 'core/query-pagination' + ), + 'description' => 'Displays the previous posts page link.', + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'queryId', + 'query', + 'paginationArrow', + 'showLabel', + 'enhancedPagination' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ) + ), + 'query-title' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-title', + 'title' => 'Query Title', + 'category' => 'theme', + 'description' => 'Display the query title.', + 'textdomain' => 'default', + 'attributes' => array( + 'type' => array( + 'type' => 'string' + ), + 'textAlign' => array( + 'type' => 'string' + ), + 'level' => array( + 'type' => 'number', + 'default' => 1 + ), + 'levelOptions' => array( + 'type' => 'array' + ), + 'showPrefix' => array( + 'type' => 'boolean', + 'default' => true + ), + 'showSearchTerm' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'example' => array( + 'attributes' => array( + 'type' => 'search' + ) + ), + 'usesContext' => array( + 'query' + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-query-title' + ), + 'query-total' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/query-total', + 'title' => 'Query Total', + 'category' => 'theme', + 'ancestor' => array( + 'core/query' + ), + 'description' => 'Display the total number of results in a query.', + 'textdomain' => 'default', + 'attributes' => array( + 'displayType' => array( + 'type' => 'string', + 'default' => 'total-results' + ) + ), + 'usesContext' => array( + 'queryId', + 'query' + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-query-total' + ), + 'quote' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/quote', + 'title' => 'Quote', + 'category' => 'text', + 'description' => 'Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Julio CortĆ”zar', + 'keywords' => array( + 'blockquote', + 'cite' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'value' => array( + 'type' => 'string', + 'source' => 'html', + 'selector' => 'blockquote', + 'multiline' => 'p', + 'default' => '', + 'role' => 'content' + ), + 'citation' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'cite', + 'role' => 'content' + ), + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'left', + 'right', + 'wide', + 'full' + ), + 'html' => false, + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true + ) + ), + 'dimensions' => array( + 'minHeight' => true, + '__experimentalDefaultControls' => array( + 'minHeight' => false + ) + ), + '__experimentalOnEnter' => true, + '__experimentalOnMerge' => true, + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'heading' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'layout' => array( + 'allowEditing' => false + ), + 'spacing' => array( + 'blockGap' => true, + 'padding' => true, + 'margin' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'allowedBlocks' => true + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'plain', + 'label' => 'Plain' + ) + ), + 'editorStyle' => 'wp-block-quote-editor', + 'style' => 'wp-block-quote' + ), + 'read-more' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/read-more', + 'title' => 'Read More', + 'category' => 'theme', + 'description' => 'Displays the link of a post, page, or any other content-type.', + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self' + ) + ), + 'usesContext' => array( + 'postId' + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + 'text' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextDecoration' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true, + 'textDecoration' => true + ) + ), + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ), + 'padding' => true, + '__experimentalDefaultControls' => array( + 'padding' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'width' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-read-more' + ), + 'rss' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/rss', + 'title' => 'RSS', + 'category' => 'widgets', + 'description' => 'Display entries from any RSS or Atom feed.', + 'keywords' => array( + 'atom', + 'feed' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'columns' => array( + 'type' => 'number', + 'default' => 2 + ), + 'blockLayout' => array( + 'type' => 'string', + 'default' => 'list' + ), + 'feedURL' => array( + 'type' => 'string', + 'default' => '', + 'role' => 'content' + ), + 'itemsToShow' => array( + 'type' => 'number', + 'default' => 5 + ), + 'displayExcerpt' => array( + 'type' => 'boolean', + 'default' => false + ), + 'displayAuthor' => array( + 'type' => 'boolean', + 'default' => false + ), + 'displayDate' => array( + 'type' => 'boolean', + 'default' => false + ), + 'excerptLength' => array( + 'type' => 'number', + 'default' => 55 + ), + 'openInNewTab' => array( + 'type' => 'boolean', + 'default' => false + ), + 'rel' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'padding' => false, + 'margin' => false + ) + ), + 'color' => array( + 'background' => true, + 'text' => true, + 'gradients' => true, + 'link' => true + ) + ), + 'editorStyle' => 'wp-block-rss-editor', + 'style' => 'wp-block-rss' + ), + 'search' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/search', + 'title' => 'Search', + 'category' => 'widgets', + 'description' => 'Help visitors find your content.', + 'keywords' => array( + 'find' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'showLabel' => array( + 'type' => 'boolean', + 'default' => true + ), + 'placeholder' => array( + 'type' => 'string', + 'default' => '', + 'role' => 'content' + ), + 'width' => array( + 'type' => 'number' + ), + 'widthUnit' => array( + 'type' => 'string' + ), + 'buttonText' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'buttonPosition' => array( + 'type' => 'string', + 'default' => 'button-outside' + ), + 'buttonUseIcon' => array( + 'type' => 'boolean', + 'default' => false + ), + 'query' => array( + 'type' => 'object', + 'default' => array( + + ) + ), + 'isSearchFieldHidden' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'supports' => array( + 'align' => array( + 'left', + 'center', + 'right' + ), + 'color' => array( + 'gradients' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'interactivity' => true, + 'typography' => array( + '__experimentalSkipSerialization' => true, + '__experimentalSelector' => '.wp-block-search__label, .wp-block-search__input, .wp-block-search__button', + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'width' => true + ) + ), + 'spacing' => array( + 'margin' => true + ), + 'html' => false + ), + 'editorStyle' => 'wp-block-search-editor', + 'style' => 'wp-block-search' + ), + 'separator' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/separator', + 'title' => 'Separator', + 'category' => 'design', + 'description' => 'Create a break between ideas or sections with a horizontal separator.', + 'keywords' => array( + 'horizontal-line', + 'hr', + 'divider' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'opacity' => array( + 'type' => 'string', + 'default' => 'alpha-channel' + ), + 'tagName' => array( + 'type' => 'string', + 'enum' => array( + 'hr', + 'div' + ), + 'default' => 'hr' + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => array( + 'center', + 'wide', + 'full' + ), + 'color' => array( + 'enableContrastChecker' => false, + '__experimentalSkipSerialization' => true, + 'gradients' => true, + 'background' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => true + ) + ), + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'wide', + 'label' => 'Wide Line' + ), + array( + 'name' => 'dots', + 'label' => 'Dots' + ) + ), + 'editorStyle' => 'wp-block-separator-editor', + 'style' => 'wp-block-separator' + ), + 'shortcode' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/shortcode', + 'title' => 'Shortcode', + 'category' => 'widgets', + 'description' => 'Insert additional custom elements with a WordPress shortcode.', + 'textdomain' => 'default', + 'attributes' => array( + 'text' => array( + 'type' => 'string', + 'source' => 'raw', + 'role' => 'content' + ) + ), + 'supports' => array( + 'className' => false, + 'customClassName' => false, + 'html' => false + ), + 'editorStyle' => 'wp-block-shortcode-editor' + ), + 'site-logo' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/site-logo', + 'title' => 'Site Logo', + 'category' => 'theme', + 'description' => 'Display an image to represent this site. Update this block and the changes apply everywhere.', + 'textdomain' => 'default', + 'attributes' => array( + 'width' => array( + 'type' => 'number' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => true, + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ), + 'shouldSyncIcon' => array( + 'type' => 'boolean' + ) + ), + 'example' => array( + 'viewportWidth' => 500, + 'attributes' => array( + 'width' => 350, + 'className' => 'block-editor-block-types-list__site-logo-example' + ) + ), + 'supports' => array( + 'html' => false, + 'align' => true, + 'alignWide' => false, + 'color' => array( + 'text' => false, + 'background' => false + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + 'filter' => array( + 'duotone' => true + ) + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'rounded', + 'label' => 'Rounded' + ) + ), + 'selectors' => array( + 'filter' => array( + 'duotone' => '.wp-block-site-logo img, .wp-block-site-logo .components-placeholder__illustration, .wp-block-site-logo .components-placeholder::before' + ) + ), + 'editorStyle' => 'wp-block-site-logo-editor', + 'style' => 'wp-block-site-logo' + ), + 'site-tagline' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/site-tagline', + 'title' => 'Site Tagline', + 'category' => 'theme', + 'description' => 'Describe in a few words what this site is about. This is important for search results, sharing on social media, and gives overall clarity to visitors.', + 'keywords' => array( + 'description' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'level' => array( + 'type' => 'number', + 'default' => 0 + ), + 'levelOptions' => array( + 'type' => 'array', + 'default' => array( + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ) + ) + ), + 'example' => array( + 'viewportWidth' => 350, + 'attributes' => array( + 'textAlign' => 'center' + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'contentRole' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'editorStyle' => 'wp-block-site-tagline-editor', + 'style' => 'wp-block-site-tagline' + ), + 'site-title' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/site-title', + 'title' => 'Site Title', + 'category' => 'theme', + 'description' => 'Displays the name of this site. Update the block, and the changes apply everywhere it’s used. This will also appear in the browser title bar and in search results.', + 'textdomain' => 'default', + 'attributes' => array( + 'level' => array( + 'type' => 'number', + 'default' => 1 + ), + 'levelOptions' => array( + 'type' => 'array', + 'default' => array( + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ) + ), + 'textAlign' => array( + 'type' => 'string' + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => true, + 'role' => 'content' + ), + 'linkTarget' => array( + 'type' => 'string', + 'default' => '_self', + 'role' => 'content' + ) + ), + 'example' => array( + 'viewportWidth' => 500 + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'padding' => true, + 'margin' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'editorStyle' => 'wp-block-site-title-editor', + 'style' => 'wp-block-site-title' + ), + 'social-link' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/social-link', + 'title' => 'Social Icon', + 'category' => 'widgets', + 'parent' => array( + 'core/social-links' + ), + 'description' => 'Display an icon linking to a social profile or site.', + 'textdomain' => 'default', + 'attributes' => array( + 'url' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'service' => array( + 'type' => 'string' + ), + 'label' => array( + 'type' => 'string', + 'role' => 'content' + ), + 'rel' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'openInNewTab', + 'showLabels', + 'iconColor', + 'iconColorValue', + 'iconBackgroundColor', + 'iconBackgroundColorValue' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-social-link-editor' + ), + 'social-links' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/social-links', + 'title' => 'Social Icons', + 'category' => 'widgets', + 'allowedBlocks' => array( + 'core/social-link' + ), + 'description' => 'Display icons linking to your social profiles or sites.', + 'keywords' => array( + 'links' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'iconColor' => array( + 'type' => 'string' + ), + 'customIconColor' => array( + 'type' => 'string' + ), + 'iconColorValue' => array( + 'type' => 'string' + ), + 'iconBackgroundColor' => array( + 'type' => 'string' + ), + 'customIconBackgroundColor' => array( + 'type' => 'string' + ), + 'iconBackgroundColorValue' => array( + 'type' => 'string' + ), + 'openInNewTab' => array( + 'type' => 'boolean', + 'default' => false + ), + 'showLabels' => array( + 'type' => 'boolean', + 'default' => false + ), + 'size' => array( + 'type' => 'string' + ) + ), + 'providesContext' => array( + 'openInNewTab' => 'openInNewTab', + 'showLabels' => 'showLabels', + 'iconColor' => 'iconColor', + 'iconColorValue' => 'iconColorValue', + 'iconBackgroundColor' => 'iconBackgroundColor', + 'iconBackgroundColorValue' => 'iconBackgroundColorValue' + ), + 'supports' => array( + 'align' => array( + 'left', + 'center', + 'right' + ), + 'anchor' => true, + 'html' => false, + '__experimentalExposeControlsToChildren' => true, + 'layout' => array( + 'allowSwitching' => false, + 'allowInheriting' => false, + 'allowVerticalAlignment' => false, + 'default' => array( + 'type' => 'flex' + ) + ), + 'color' => array( + 'enableContrastChecker' => false, + 'background' => true, + 'gradients' => true, + 'text' => false, + '__experimentalDefaultControls' => array( + 'background' => false + ) + ), + 'spacing' => array( + 'blockGap' => array( + 'horizontal', + 'vertical' + ), + 'margin' => true, + 'padding' => true, + 'units' => array( + 'px', + 'em', + 'rem', + 'vh', + 'vw' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true, + 'margin' => true, + 'padding' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'contentRole' => true + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'logos-only', + 'label' => 'Logos Only' + ), + array( + 'name' => 'pill-shape', + 'label' => 'Pill Shape' + ) + ), + 'editorStyle' => 'wp-block-social-links-editor', + 'style' => 'wp-block-social-links' + ), + 'spacer' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/spacer', + 'title' => 'Spacer', + 'category' => 'design', + 'description' => 'Add white space between blocks and customize its height.', + 'textdomain' => 'default', + 'attributes' => array( + 'height' => array( + 'type' => 'string', + 'default' => '100px' + ), + 'width' => array( + 'type' => 'string' + ) + ), + 'usesContext' => array( + 'orientation' + ), + 'supports' => array( + 'anchor' => true, + 'spacing' => array( + 'margin' => array( + 'top', + 'bottom' + ), + '__experimentalDefaultControls' => array( + 'margin' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-spacer-editor', + 'style' => 'wp-block-spacer' + ), + 'table' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/table', + 'title' => 'Table', + 'category' => 'text', + 'description' => 'Create structured content in rows and columns to display information.', + 'textdomain' => 'default', + 'attributes' => array( + 'hasFixedLayout' => array( + 'type' => 'boolean', + 'default' => true + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'figcaption', + 'role' => 'content' + ), + 'head' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'thead tr', + 'query' => array( + 'cells' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'td,th', + 'query' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'role' => 'content' + ), + 'tag' => array( + 'type' => 'string', + 'default' => 'td', + 'source' => 'tag' + ), + 'scope' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'scope' + ), + 'align' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'data-align' + ), + 'colspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'colspan' + ), + 'rowspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'rowspan' + ) + ) + ) + ) + ), + 'body' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'tbody tr', + 'query' => array( + 'cells' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'td,th', + 'query' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'role' => 'content' + ), + 'tag' => array( + 'type' => 'string', + 'default' => 'td', + 'source' => 'tag' + ), + 'scope' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'scope' + ), + 'align' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'data-align' + ), + 'colspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'colspan' + ), + 'rowspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'rowspan' + ) + ) + ) + ) + ), + 'foot' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'tfoot tr', + 'query' => array( + 'cells' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'td,th', + 'query' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'role' => 'content' + ), + 'tag' => array( + 'type' => 'string', + 'default' => 'td', + 'source' => 'tag' + ), + 'scope' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'scope' + ), + 'align' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'data-align' + ), + 'colspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'colspan' + ), + 'rowspan' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'rowspan' + ) + ) + ) + ) + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + 'color' => array( + '__experimentalSkipSerialization' => true, + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + '__experimentalBorder' => array( + '__experimentalSkipSerialization' => true, + 'color' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'style' => true, + 'width' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'selectors' => array( + 'root' => '.wp-block-table > table', + 'spacing' => '.wp-block-table' + ), + 'styles' => array( + array( + 'name' => 'regular', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'stripes', + 'label' => 'Stripes' + ) + ), + 'editorStyle' => 'wp-block-table-editor', + 'style' => 'wp-block-table' + ), + 'tag-cloud' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/tag-cloud', + 'title' => 'Tag Cloud', + 'category' => 'widgets', + 'description' => 'A cloud of popular keywords, each sized by how often it appears.', + 'textdomain' => 'default', + 'attributes' => array( + 'numberOfTags' => array( + 'type' => 'number', + 'default' => 45, + 'minimum' => 1, + 'maximum' => 100 + ), + 'taxonomy' => array( + 'type' => 'string', + 'default' => 'post_tag' + ), + 'showTagCounts' => array( + 'type' => 'boolean', + 'default' => false + ), + 'smallestFontSize' => array( + 'type' => 'string', + 'default' => '8pt' + ), + 'largestFontSize' => array( + 'type' => 'string', + 'default' => '22pt' + ) + ), + 'styles' => array( + array( + 'name' => 'default', + 'label' => 'Default', + 'isDefault' => true + ), + array( + 'name' => 'outline', + 'label' => 'Outline' + ) + ), + 'supports' => array( + 'html' => false, + 'align' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true + ), + 'typography' => array( + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalLetterSpacing' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'editorStyle' => 'wp-block-tag-cloud-editor' + ), + 'template-part' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/template-part', + 'title' => 'Template Part', + 'category' => 'theme', + 'description' => 'Edit the different global regions of your site, like the header, footer, sidebar, or create your own.', + 'textdomain' => 'default', + 'attributes' => array( + 'slug' => array( + 'type' => 'string' + ), + 'theme' => array( + 'type' => 'string' + ), + 'tagName' => array( + 'type' => 'string' + ), + 'area' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'align' => true, + 'html' => false, + 'reusable' => false, + 'renaming' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-template-part-editor' + ), + 'term-count' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/term-count', + 'title' => 'Term Count', + 'category' => 'theme', + 'description' => 'Displays the post count of a taxonomy term.', + 'textdomain' => 'default', + 'usesContext' => array( + 'termId', + 'taxonomy' + ), + 'attributes' => array( + 'bracketType' => array( + 'type' => 'string', + 'enum' => array( + 'none', + 'round', + 'square', + 'curly', + 'angle' + ), + 'default' => 'round' + ) + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'gradients' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-term-count' + ), + 'term-description' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/term-description', + 'title' => 'Term Description', + 'category' => 'theme', + 'description' => 'Display the description of categories, tags and custom taxonomies when viewing an archive.', + 'textdomain' => 'default', + 'usesContext' => array( + 'termId', + 'taxonomy' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'spacing' => array( + 'padding' => true, + 'margin' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ) + ), + 'term-name' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/term-name', + 'title' => 'Term Name', + 'category' => 'theme', + 'description' => 'Displays the name of a taxonomy term.', + 'keywords' => array( + 'term title' + ), + 'textdomain' => 'default', + 'usesContext' => array( + 'termId', + 'taxonomy' + ), + 'attributes' => array( + 'textAlign' => array( + 'type' => 'string' + ), + 'level' => array( + 'type' => 'number', + 'default' => 0 + ), + 'isLink' => array( + 'type' => 'boolean', + 'default' => false + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true, + 'link' => true + ) + ), + 'spacing' => array( + 'padding' => true + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'width' => true, + 'style' => true + ) + ) + ), + 'style' => 'wp-block-term-name' + ), + 'term-template' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/term-template', + 'title' => 'Term Template', + 'category' => 'theme', + 'ancestor' => array( + 'core/terms-query' + ), + 'description' => 'Contains the block elements used to render a taxonomy term, like the name, description, and more.', + 'textdomain' => 'default', + 'usesContext' => array( + 'termQuery' + ), + 'supports' => array( + 'reusable' => false, + 'html' => false, + 'align' => array( + 'wide', + 'full' + ), + 'layout' => true, + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + '__experimentalFontFamily' => true, + '__experimentalFontWeight' => true, + '__experimentalFontStyle' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalLetterSpacing' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + 'blockGap' => array( + '__experimentalDefault' => '1.25em' + ), + '__experimentalDefaultControls' => array( + 'blockGap' => true, + 'padding' => false, + 'margin' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ), + '__experimentalBorder' => array( + 'radius' => true, + 'color' => true, + 'width' => true, + 'style' => true + ) + ), + 'style' => 'wp-block-term-template', + 'editorStyle' => 'wp-block-term-template-editor' + ), + 'terms-query' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/terms-query', + 'title' => 'Terms Query', + 'category' => 'theme', + 'description' => 'An advanced block that allows displaying taxonomy terms based on different query parameters and visual configurations.', + 'keywords' => array( + 'terms', + 'taxonomy', + 'categories', + 'tags', + 'list' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'termQuery' => array( + 'type' => 'object', + 'default' => array( + 'perPage' => 10, + 'taxonomy' => 'category', + 'order' => 'asc', + 'orderBy' => 'name', + 'include' => array( + + ), + 'hideEmpty' => true, + 'showNested' => false, + 'inherit' => false + ) + ), + 'tagName' => array( + 'type' => 'string', + 'default' => 'div' + ) + ), + 'usesContext' => array( + 'templateSlug' + ), + 'providesContext' => array( + 'termQuery' => 'termQuery' + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ), + 'html' => false, + 'layout' => true, + 'interactivity' => true + ) + ), + 'text-columns' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/text-columns', + 'title' => 'Text Columns (deprecated)', + 'icon' => 'columns', + 'category' => 'design', + 'description' => 'This block is deprecated. Please use the Columns block instead.', + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'array', + 'source' => 'query', + 'selector' => 'p', + 'query' => array( + 'children' => array( + 'type' => 'string', + 'source' => 'html' + ) + ), + 'default' => array( + array( + + ), + array( + + ) + ) + ), + 'columns' => array( + 'type' => 'number', + 'default' => 2 + ), + 'width' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'inserter' => false, + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-text-columns-editor', + 'style' => 'wp-block-text-columns' + ), + 'verse' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/verse', + 'title' => 'Verse', + 'category' => 'text', + 'description' => 'Insert poetry. Use special spacing formats. Or quote song lyrics.', + 'keywords' => array( + 'poetry', + 'poem' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'content' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'pre', + '__unstablePreserveWhiteSpace' => true, + 'role' => 'content' + ), + 'textAlign' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'anchor' => true, + 'background' => array( + 'backgroundImage' => true, + 'backgroundSize' => true, + '__experimentalDefaultControls' => array( + 'backgroundImage' => true + ) + ), + 'color' => array( + 'gradients' => true, + 'link' => true, + '__experimentalDefaultControls' => array( + 'background' => true, + 'text' => true + ) + ), + 'dimensions' => array( + 'minHeight' => true, + '__experimentalDefaultControls' => array( + 'minHeight' => false + ) + ), + 'typography' => array( + 'fontSize' => true, + '__experimentalFontFamily' => true, + 'lineHeight' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextTransform' => true, + '__experimentalTextDecoration' => true, + '__experimentalWritingMode' => true, + '__experimentalDefaultControls' => array( + 'fontSize' => true + ) + ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + '__experimentalBorder' => array( + 'radius' => true, + 'width' => true, + 'color' => true, + 'style' => true + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'style' => 'wp-block-verse', + 'editorStyle' => 'wp-block-verse-editor' + ), + 'video' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/video', + 'title' => 'Video', + 'category' => 'media', + 'description' => 'Embed a video from your media library or upload a new one.', + 'keywords' => array( + 'movie' + ), + 'textdomain' => 'default', + 'attributes' => array( + 'autoplay' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'autoplay' + ), + 'caption' => array( + 'type' => 'rich-text', + 'source' => 'rich-text', + 'selector' => 'figcaption', + 'role' => 'content' + ), + 'controls' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'controls', + 'default' => true + ), + 'id' => array( + 'type' => 'number', + 'role' => 'content' + ), + 'loop' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'loop' + ), + 'muted' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'muted' + ), + 'poster' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'poster' + ), + 'preload' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'preload', + 'default' => 'metadata' + ), + 'blob' => array( + 'type' => 'string', + 'role' => 'local' + ), + 'src' => array( + 'type' => 'string', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'src', + 'role' => 'content' + ), + 'playsInline' => array( + 'type' => 'boolean', + 'source' => 'attribute', + 'selector' => 'video', + 'attribute' => 'playsinline' + ), + 'tracks' => array( + 'role' => 'content', + 'type' => 'array', + 'items' => array( + 'type' => 'object' + ), + 'default' => array( + + ) + ) + ), + 'supports' => array( + 'anchor' => true, + 'align' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + '__experimentalDefaultControls' => array( + 'margin' => false, + 'padding' => false + ) + ), + 'interactivity' => array( + 'clientNavigation' => true + ) + ), + 'editorStyle' => 'wp-block-video-editor', + 'style' => 'wp-block-video' + ), + 'widget-group' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 3, + 'name' => 'core/widget-group', + 'title' => 'Widget Group', + 'category' => 'widgets', + 'attributes' => array( + 'title' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'html' => false, + 'inserter' => true, + 'customClassName' => true, + 'reusable' => false + ), + 'editorStyle' => 'wp-block-widget-group-editor', + 'style' => 'wp-block-widget-group' + ) +); \ No newline at end of file diff --git a/src/wp-includes/blocks/button.php b/src/wp-includes/blocks/button.php new file mode 100644 index 0000000000000..0d03440b1cb0f --- /dev/null +++ b/src/wp-includes/blocks/button.php @@ -0,0 +1,79 @@ +` or `'; + + $body_content = preg_replace( '/]+>/', $button, $body_content ); + + add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' ); + + return $body_content; +} + +/** + * @since 6.5.0 + */ +function block_core_image_print_lightbox_overlay() { + $close_button_label = esc_attr__( 'Close' ); + + // If the current theme does NOT have a `theme.json`, or the colors are not + // defined, it needs to set the background color & close button color to some + // default values because it can't get them from the Global Styles. + $background_color = '#fff'; + $close_button_color = '#000'; + if ( wp_theme_has_theme_json() ) { + $global_styles_color = wp_get_global_styles( array( 'color' ) ); + if ( ! empty( $global_styles_color['background'] ) ) { + $background_color = esc_attr( $global_styles_color['background'] ); + } + if ( ! empty( $global_styles_color['text'] ) ) { + $close_button_color = esc_attr( $global_styles_color['text'] ); + } + } + + echo << + + + + + +HTML; +} + +/** + * Registers the `core/image` block on server. + * + * @since 5.9.0 + */ +function register_block_core_image() { + register_block_type_from_metadata( + __DIR__ . '/image', + array( + 'render_callback' => 'render_block_core_image', + ) + ); +} +add_action( 'init', 'register_block_core_image' ); diff --git a/src/wp-includes/blocks/image/block.json b/src/wp-includes/blocks/image/block.json new file mode 100644 index 0000000000000..26835df9e856c --- /dev/null +++ b/src/wp-includes/blocks/image/block.json @@ -0,0 +1,151 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/image", + "title": "Image", + "category": "media", + "usesContext": [ + "allowResize", + "imageCrop", + "fixedHeight", + "postId", + "postType", + "queryId" + ], + "description": "Insert an image to make a visual statement.", + "keywords": [ "img", "photo", "picture" ], + "textdomain": "default", + "attributes": { + "blob": { + "type": "string", + "role": "local" + }, + "url": { + "type": "string", + "source": "attribute", + "selector": "img", + "attribute": "src", + "role": "content" + }, + "alt": { + "type": "string", + "source": "attribute", + "selector": "img", + "attribute": "alt", + "default": "", + "role": "content" + }, + "caption": { + "type": "rich-text", + "source": "rich-text", + "selector": "figcaption", + "role": "content" + }, + "lightbox": { + "type": "object", + "enabled": { + "type": "boolean" + } + }, + "title": { + "type": "string", + "source": "attribute", + "selector": "img", + "attribute": "title", + "role": "content" + }, + "href": { + "type": "string", + "source": "attribute", + "selector": "figure > a", + "attribute": "href", + "role": "content" + }, + "rel": { + "type": "string", + "source": "attribute", + "selector": "figure > a", + "attribute": "rel" + }, + "linkClass": { + "type": "string", + "source": "attribute", + "selector": "figure > a", + "attribute": "class" + }, + "id": { + "type": "number", + "role": "content" + }, + "width": { + "type": "string" + }, + "height": { + "type": "string" + }, + "aspectRatio": { + "type": "string" + }, + "scale": { + "type": "string" + }, + "sizeSlug": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "linkTarget": { + "type": "string", + "source": "attribute", + "selector": "figure > a", + "attribute": "target" + } + }, + "supports": { + "interactivity": true, + "align": [ "left", "center", "right", "wide", "full" ], + "anchor": true, + "color": { + "text": false, + "background": false + }, + "filter": { + "duotone": true + }, + "spacing": { + "margin": true + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "width": true, + "__experimentalSkipSerialization": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "width": true + } + }, + "shadow": { + "__experimentalSkipSerialization": true + } + }, + "selectors": { + "border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder", + "shadow": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder", + "filter": { + "duotone": ".wp-block-image img, .wp-block-image .components-placeholder" + } + }, + "styles": [ + { + "name": "default", + "label": "Default", + "isDefault": true + }, + { "name": "rounded", "label": "Rounded" } + ], + "editorStyle": "wp-block-image-editor", + "style": "wp-block-image" +} diff --git a/src/wp-includes/blocks/image/view.asset.php b/src/wp-includes/blocks/image/view.asset.php new file mode 100644 index 0000000000000..58058b1408c81 --- /dev/null +++ b/src/wp-includes/blocks/image/view.asset.php @@ -0,0 +1 @@ + array(), 'version' => '7500eb032759d407a71d'); diff --git a/src/wp-includes/blocks/image/view.min.asset.php b/src/wp-includes/blocks/image/view.min.asset.php new file mode 100644 index 0000000000000..5b46fcb7d531e --- /dev/null +++ b/src/wp-includes/blocks/image/view.min.asset.php @@ -0,0 +1 @@ + array(), 'version' => 'ff354d5368d64857fef0'); diff --git a/src/wp-includes/blocks/latest-comments.php b/src/wp-includes/blocks/latest-comments.php new file mode 100644 index 0000000000000..bbe82b8b18f9a --- /dev/null +++ b/src/wp-includes/blocks/latest-comments.php @@ -0,0 +1,162 @@ + $attributes['commentsToShow'], + 'status' => 'approve', + 'post_status' => 'publish', + ), + array() + ) + ); + + $list_items_markup = ''; + if ( ! empty( $comments ) ) { + // Prime the cache for associated posts. This is copied from \WP_Widget_Recent_Comments::widget(). + $post_ids = array_unique( wp_list_pluck( $comments, 'comment_post_ID' ) ); + _prime_post_caches( $post_ids, strpos( get_option( 'permalink_structure' ), '%category%' ), false ); + + foreach ( $comments as $comment ) { + $list_items_markup .= '
  • '; + if ( $attributes['displayAvatar'] ) { + $avatar = get_avatar( + $comment, + 48, + '', + '', + array( + 'class' => 'wp-block-latest-comments__comment-avatar', + ) + ); + if ( $avatar ) { + $list_items_markup .= $avatar; + } + } + + $list_items_markup .= '
    '; + $list_items_markup .= ''; + if ( $attributes['displayExcerpt'] ) { + $list_items_markup .= '
    ' . wpautop( get_comment_excerpt( $comment ) ) . '
    '; + } + $list_items_markup .= '
  • '; + } + } + + $classnames = array(); + if ( $attributes['displayAvatar'] ) { + $classnames[] = 'has-avatars'; + } + if ( $attributes['displayDate'] ) { + $classnames[] = 'has-dates'; + } + if ( $attributes['displayExcerpt'] ) { + $classnames[] = 'has-excerpts'; + } + if ( empty( $comments ) ) { + $classnames[] = 'no-comments'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classnames ) ) ); + + return ! empty( $comments ) ? sprintf( + '
      %2$s
    ', + $wrapper_attributes, + $list_items_markup + ) : sprintf( + '
    %2$s
    ', + $wrapper_attributes, + __( 'No comments to show.' ) + ); +} + +/** + * Registers the `core/latest-comments` block. + * + * @since 5.3.0 + */ +function register_block_core_latest_comments() { + register_block_type_from_metadata( + __DIR__ . '/latest-comments', + array( + 'render_callback' => 'render_block_core_latest_comments', + ) + ); +} + +add_action( 'init', 'register_block_core_latest_comments' ); diff --git a/src/wp-includes/blocks/latest-comments/block.json b/src/wp-includes/blocks/latest-comments/block.json new file mode 100644 index 0000000000000..543512ddf3ce7 --- /dev/null +++ b/src/wp-includes/blocks/latest-comments/block.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/latest-comments", + "title": "Latest Comments", + "category": "widgets", + "description": "Display a list of your most recent comments.", + "keywords": [ "recent comments" ], + "textdomain": "default", + "attributes": { + "commentsToShow": { + "type": "number", + "default": 5, + "minimum": 1, + "maximum": 100 + }, + "displayAvatar": { + "type": "boolean", + "default": true + }, + "displayDate": { + "type": "boolean", + "default": true + }, + "displayExcerpt": { + "type": "boolean", + "default": true + } + }, + "supports": { + "align": true, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-latest-comments-editor", + "style": "wp-block-latest-comments" +} diff --git a/src/wp-includes/blocks/latest-posts.php b/src/wp-includes/blocks/latest-posts.php new file mode 100644 index 0000000000000..b970f486bb6a1 --- /dev/null +++ b/src/wp-includes/blocks/latest-posts.php @@ -0,0 +1,273 @@ + $attributes['postsToShow'], + 'post_status' => 'publish', + 'order' => $attributes['order'], + 'orderby' => $attributes['orderBy'], + 'ignore_sticky_posts' => true, + 'no_found_rows' => true, + ); + + $block_core_latest_posts_excerpt_length = $attributes['excerptLength']; + add_filter( 'excerpt_length', 'block_core_latest_posts_get_excerpt_length', 20 ); + + if ( ! empty( $attributes['categories'] ) ) { + $args['category__in'] = array_column( $attributes['categories'], 'id' ); + } + if ( isset( $attributes['selectedAuthor'] ) ) { + $args['author'] = $attributes['selectedAuthor']; + } + + $query = new WP_Query(); + $recent_posts = $query->query( $args ); + + if ( isset( $attributes['displayFeaturedImage'] ) && $attributes['displayFeaturedImage'] ) { + update_post_thumbnail_cache( $query ); + } + + $list_items_markup = ''; + + foreach ( $recent_posts as $post ) { + $post_link = esc_url( get_permalink( $post ) ); + $title = get_the_title( $post ); + + if ( ! $title ) { + $title = __( '(no title)' ); + } + + $list_items_markup .= '
  • '; + + if ( $attributes['displayFeaturedImage'] && has_post_thumbnail( $post ) ) { + $image_style = ''; + if ( isset( $attributes['featuredImageSizeWidth'] ) ) { + $image_style .= sprintf( 'max-width:%spx;', $attributes['featuredImageSizeWidth'] ); + } + if ( isset( $attributes['featuredImageSizeHeight'] ) ) { + $image_style .= sprintf( 'max-height:%spx;', $attributes['featuredImageSizeHeight'] ); + } + + $image_classes = 'wp-block-latest-posts__featured-image'; + if ( isset( $attributes['featuredImageAlign'] ) ) { + $image_classes .= ' align' . $attributes['featuredImageAlign']; + } + + $featured_image = get_the_post_thumbnail( + $post, + $attributes['featuredImageSizeSlug'], + array( + 'style' => esc_attr( $image_style ), + ) + ); + if ( $attributes['addLinkToFeaturedImage'] ) { + $featured_image = sprintf( + '%3$s', + esc_url( $post_link ), + esc_attr( $title ), + $featured_image + ); + } + $list_items_markup .= sprintf( + '
    %2$s
    ', + esc_attr( $image_classes ), + $featured_image + ); + } + + $list_items_markup .= sprintf( + '%2$s', + esc_url( $post_link ), + $title + ); + + if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) { + $author_display_name = get_the_author_meta( 'display_name', $post->post_author ); + + /* translators: byline. %s: author. */ + $byline = sprintf( __( 'by %s' ), $author_display_name ); + + if ( ! empty( $author_display_name ) ) { + $list_items_markup .= sprintf( + '', + $byline + ); + } + } + + if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) { + $list_items_markup .= sprintf( + '', + esc_attr( get_the_date( 'c', $post ) ), + get_the_date( '', $post ) + ); + } + + if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent'] + && isset( $attributes['displayPostContentRadio'] ) && 'excerpt' === $attributes['displayPostContentRadio'] ) { + + $trimmed_excerpt = get_the_excerpt( $post ); + + /* + * Adds a "Read more" link with screen reader text. + * […] is the default excerpt ending from wp_trim_excerpt() in Core. + */ + if ( str_ends_with( $trimmed_excerpt, ' […]' ) ) { + /** This filter is documented in wp-includes/formatting.php */ + $excerpt_length = (int) apply_filters( 'excerpt_length', $block_core_latest_posts_excerpt_length ); + if ( $excerpt_length <= $block_core_latest_posts_excerpt_length ) { + $trimmed_excerpt = substr( $trimmed_excerpt, 0, -11 ); + $trimmed_excerpt .= sprintf( + /* translators: 1: A URL to a post, 2: Hidden accessibility text: Post title */ + __( '… Read more: %2$s' ), + esc_url( $post_link ), + esc_html( $title ) + ); + } + } + + if ( post_password_required( $post ) ) { + $trimmed_excerpt = __( 'This content is password protected.' ); + } + + $list_items_markup .= sprintf( + '
    %1$s
    ', + $trimmed_excerpt + ); + } + + if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent'] + && isset( $attributes['displayPostContentRadio'] ) && 'full_post' === $attributes['displayPostContentRadio'] ) { + + $post_content = html_entity_decode( $post->post_content, ENT_QUOTES, get_option( 'blog_charset' ) ); + + if ( post_password_required( $post ) ) { + $post_content = __( 'This content is password protected.' ); + } + + $list_items_markup .= sprintf( + '
    %1$s
    ', + wp_kses_post( $post_content ) + ); + } + + $list_items_markup .= "
  • \n"; + } + + remove_filter( 'excerpt_length', 'block_core_latest_posts_get_excerpt_length', 20 ); + + $classes = array( 'wp-block-latest-posts__list' ); + if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) { + $classes[] = 'is-grid'; + } + if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) { + $classes[] = 'columns-' . $attributes['columns']; + } + if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) { + $classes[] = 'has-dates'; + } + if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) { + $classes[] = 'has-author'; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return sprintf( + '', + $wrapper_attributes, + $list_items_markup + ); +} + +/** + * Registers the `core/latest-posts` block on server. + * + * @since 5.0.0 + */ +function register_block_core_latest_posts() { + register_block_type_from_metadata( + __DIR__ . '/latest-posts', + array( + 'render_callback' => 'render_block_core_latest_posts', + ) + ); +} +add_action( 'init', 'register_block_core_latest_posts' ); + +/** + * Handles outdated versions of the `core/latest-posts` block by converting + * attribute `categories` from a numeric string to an array with key `id`. + * + * This is done to accommodate the changes introduced in #20781 that sought to + * add support for multiple categories to the block. However, given that this + * block is dynamic, the usual provisions for block migration are insufficient, + * as they only act when a block is loaded in the editor. + * + * TODO: Remove when and if the bottom client-side deprecation for this block + * is removed. + * + * @since 5.5.0 + * + * @param array $block A single parsed block object. + * + * @return array The migrated block object. + */ +function block_core_latest_posts_migrate_categories( $block ) { + if ( + 'core/latest-posts' === $block['blockName'] && + ! empty( $block['attrs']['categories'] ) && + is_string( $block['attrs']['categories'] ) + ) { + $block['attrs']['categories'] = array( + array( 'id' => absint( $block['attrs']['categories'] ) ), + ); + } + + return $block; +} +add_filter( 'render_block_data', 'block_core_latest_posts_migrate_categories' ); diff --git a/src/wp-includes/blocks/latest-posts/block.json b/src/wp-includes/blocks/latest-posts/block.json new file mode 100644 index 0000000000000..58b1c6da81ca3 --- /dev/null +++ b/src/wp-includes/blocks/latest-posts/block.json @@ -0,0 +1,132 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/latest-posts", + "title": "Latest Posts", + "category": "widgets", + "description": "Display a list of your most recent posts.", + "keywords": [ "recent posts" ], + "textdomain": "default", + "attributes": { + "categories": { + "type": "array", + "items": { + "type": "object" + } + }, + "selectedAuthor": { + "type": "number" + }, + "postsToShow": { + "type": "number", + "default": 5 + }, + "displayPostContent": { + "type": "boolean", + "default": false + }, + "displayPostContentRadio": { + "type": "string", + "default": "excerpt" + }, + "excerptLength": { + "type": "number", + "default": 55 + }, + "displayAuthor": { + "type": "boolean", + "default": false + }, + "displayPostDate": { + "type": "boolean", + "default": false + }, + "postLayout": { + "type": "string", + "default": "list" + }, + "columns": { + "type": "number", + "default": 3 + }, + "order": { + "type": "string", + "default": "desc" + }, + "orderBy": { + "type": "string", + "default": "date" + }, + "displayFeaturedImage": { + "type": "boolean", + "default": false + }, + "featuredImageAlign": { + "type": "string", + "enum": [ "left", "center", "right" ] + }, + "featuredImageSizeSlug": { + "type": "string", + "default": "thumbnail" + }, + "featuredImageSizeWidth": { + "type": "number", + "default": null + }, + "featuredImageSizeHeight": { + "type": "number", + "default": null + }, + "addLinkToFeaturedImage": { + "type": "boolean", + "default": false + } + }, + "supports": { + "align": true, + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-latest-posts-editor", + "style": "wp-block-latest-posts" +} diff --git a/src/wp-includes/blocks/legacy-widget.php b/src/wp-includes/blocks/legacy-widget.php new file mode 100644 index 0000000000000..bec1b16b6ba8c --- /dev/null +++ b/src/wp-includes/blocks/legacy-widget.php @@ -0,0 +1,157 @@ +get_widget_key( $id_base ); + $widget_object = $wp_widget_factory->get_widget_object( $id_base ); + + if ( ! $widget_key || ! $widget_object ) { + return ''; + } + + if ( isset( $attributes['instance']['encoded'], $attributes['instance']['hash'] ) ) { + $serialized_instance = base64_decode( $attributes['instance']['encoded'] ); + if ( ! hash_equals( wp_hash( $serialized_instance ), (string) $attributes['instance']['hash'] ) ) { + return ''; + } + $instance = unserialize( $serialized_instance ); + } else { + $instance = array(); + } + + $args = array( + 'widget_id' => $widget_object->id, + 'widget_name' => $widget_object->name, + ); + + ob_start(); + the_widget( $widget_key, $instance, $args ); + return ob_get_clean(); +} + +/** + * Registers the 'core/legacy-widget' block. + * + * @since 5.8.0 + */ +function register_block_core_legacy_widget() { + register_block_type_from_metadata( + __DIR__ . '/legacy-widget', + array( + 'render_callback' => 'render_block_core_legacy_widget', + ) + ); +} + +add_action( 'init', 'register_block_core_legacy_widget' ); + +/** + * Intercepts any request with legacy-widget-preview in the query param and, if + * set, renders a page containing a preview of the requested Legacy Widget + * block. + * + * @since 5.8.0 + */ +function handle_legacy_widget_preview_iframe() { + if ( empty( $_GET['legacy-widget-preview'] ) ) { + return; + } + + if ( ! current_user_can( 'edit_theme_options' ) ) { + return; + } + + define( 'IFRAME_REQUEST', true ); + + ?> + + > + + + + + + + + > +
    +
    + get_registered( 'core/legacy-widget' ); + echo $block->render( $_GET['legacy-widget-preview'] ); + ?> +
    +
    + + + + li", + "border": ".wp-block-list:not(.wp-block-list .wp-block-list) > li" + } +} diff --git a/src/wp-includes/blocks/list.php b/src/wp-includes/blocks/list.php new file mode 100644 index 0000000000000..1bffd81324857 --- /dev/null +++ b/src/wp-includes/blocks/list.php @@ -0,0 +1,54 @@ + is transformed to
      . + * + * @since 6.6.0 + * + * @see https://github.com/WordPress/gutenberg/issues/12420 + * + * @param array $attributes Attributes of the block being rendered. + * @param string $content Content of the block being rendered. + * + * @return string The content of the block being rendered. + */ +function block_core_list_render( $attributes, $content ) { + if ( ! $content ) { + return $content; + } + + $processor = new WP_HTML_Tag_Processor( $content ); + + $list_tags = array( 'OL', 'UL' ); + while ( $processor->next_tag() ) { + if ( in_array( $processor->get_tag(), $list_tags, true ) ) { + $processor->add_class( 'wp-block-list' ); + break; + } + } + + return $processor->get_updated_html(); +} + +/** + * Registers the `core/list` block on server. + * + * @since 6.6.0 + */ +function register_block_core_list() { + register_block_type_from_metadata( + __DIR__ . '/list', + array( + 'render_callback' => 'block_core_list_render', + ) + ); +} + +add_action( 'init', 'register_block_core_list' ); diff --git a/src/wp-includes/blocks/list/block.json b/src/wp-includes/blocks/list/block.json new file mode 100644 index 0000000000000..bd696c30c334c --- /dev/null +++ b/src/wp-includes/blocks/list/block.json @@ -0,0 +1,88 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/list", + "title": "List", + "category": "text", + "allowedBlocks": [ "core/list-item" ], + "description": "An organized collection of items displayed in a specific order.", + "keywords": [ "bullet list", "ordered list", "numbered list" ], + "textdomain": "default", + "attributes": { + "ordered": { + "type": "boolean", + "default": false, + "role": "content" + }, + "values": { + "type": "string", + "source": "html", + "selector": "ol,ul", + "multiline": "li", + "default": "", + "role": "content" + }, + "type": { + "type": "string" + }, + "start": { + "type": "number" + }, + "reversed": { + "type": "boolean" + }, + "placeholder": { + "type": "string" + } + }, + "supports": { + "anchor": true, + "html": false, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "__unstablePasteTextInline": true, + "__experimentalOnMerge": true, + "__experimentalSlashInserter": true, + "interactivity": { + "clientNavigation": true + } + }, + "selectors": { + "border": ".wp-block-list:not(.wp-block-list .wp-block-list)" + }, + "editorStyle": "wp-block-list-editor", + "style": "wp-block-list" +} diff --git a/src/wp-includes/blocks/loginout.php b/src/wp-includes/blocks/loginout.php new file mode 100644 index 0000000000000..f83d8be424ece --- /dev/null +++ b/src/wp-includes/blocks/loginout.php @@ -0,0 +1,61 @@ + false ) ); + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) ); + + return '
      ' . $contents . '
      '; +} + +/** + * Registers the `core/loginout` block on server. + * + * @since 5.8.0 + */ +function register_block_core_loginout() { + register_block_type_from_metadata( + __DIR__ . '/loginout', + array( + 'render_callback' => 'render_block_core_loginout', + ) + ); +} +add_action( 'init', 'register_block_core_loginout' ); diff --git a/src/wp-includes/blocks/loginout/block.json b/src/wp-includes/blocks/loginout/block.json new file mode 100644 index 0000000000000..f2aaafd60fde0 --- /dev/null +++ b/src/wp-includes/blocks/loginout/block.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/loginout", + "title": "Login/out", + "category": "theme", + "description": "Show login & logout links.", + "keywords": [ "login", "logout", "form" ], + "textdomain": "default", + "attributes": { + "displayLoginAsForm": { + "type": "boolean", + "default": false + }, + "redirectToCurrent": { + "type": "boolean", + "default": true + } + }, + "example": { + "viewportWidth": 350 + }, + "supports": { + "className": true, + "color": { + "background": true, + "text": false, + "gradients": true, + "link": true + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-loginout" +} diff --git a/src/wp-includes/blocks/math/block.json b/src/wp-includes/blocks/math/block.json new file mode 100644 index 0000000000000..4b47761307c4c --- /dev/null +++ b/src/wp-includes/blocks/math/block.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/math", + "title": "Math", + "category": "text", + "description": "Display mathematical notation using LaTeX.", + "keywords": [ "equation", "formula", "latex", "mathematics" ], + "textdomain": "default", + "supports": { + "html": false + }, + "attributes": { + "latex": { + "type": "string", + "role": "content" + }, + "mathML": { + "type": "string", + "source": "html", + "selector": "math" + } + } +} diff --git a/src/wp-includes/blocks/media-text.php b/src/wp-includes/blocks/media-text.php new file mode 100644 index 0000000000000..b65137b150ba5 --- /dev/null +++ b/src/wp-includes/blocks/media-text.php @@ -0,0 +1,131 @@ + 'div', + 'class_name' => 'wp-block-media-text', + ); + + while ( $block_tag_processor->next_tag( $block_query ) ) { + if ( $image_fill ) { + // The markup below does not work with the deprecated `is-image-fill` class. + $block_tag_processor->remove_class( 'is-image-fill' ); + $block_tag_processor->add_class( 'is-image-fill-element' ); + } + } + + $content = $block_tag_processor->get_updated_html(); + + $media_tag_processor = new WP_HTML_Tag_Processor( $content ); + $wrapping_figure_query = array( + 'tag_name' => 'figure', + 'class_name' => 'wp-block-media-text__media', + ); + + if ( $has_media_on_right ) { + // Loop through all the figure tags and set a bookmark on the last figure tag. + while ( $media_tag_processor->next_tag( $wrapping_figure_query ) ) { + $media_tag_processor->set_bookmark( 'last_figure' ); + } + if ( $media_tag_processor->has_bookmark( 'last_figure' ) ) { + $media_tag_processor->seek( 'last_figure' ); + // Insert a unique ID to identify the figure tag. + $media_tag_processor->set_attribute( 'id', $unique_id ); + } + } else { + if ( $media_tag_processor->next_tag( $wrapping_figure_query ) ) { + // Insert a unique ID to identify the figure tag. + $media_tag_processor->set_attribute( 'id', $unique_id ); + } + } + + $content = $media_tag_processor->get_updated_html(); + + // Add the image tag inside the figure tag, and update the image attributes + // in order to display the featured image. + $media_size_slug = isset( $attributes['mediaSizeSlug'] ) ? $attributes['mediaSizeSlug'] : 'full'; + $image_tag = ''; + $content = preg_replace( + '/()/', + '$1' . $image_tag, + $content + ); + + $image_tag_processor = new WP_HTML_Tag_Processor( $content ); + if ( $image_tag_processor->next_tag( + array( + 'tag_name' => 'figure', + 'id' => $unique_id, + ) + ) ) { + // The ID is only used to ensure that the correct figure tag is selected, + // and can now be removed. + $image_tag_processor->remove_attribute( 'id' ); + if ( $image_tag_processor->next_tag( + array( + 'tag_name' => 'img', + 'class_name' => 'wp-block-media-text__featured_image', + ) + ) ) { + $image_tag_processor->set_attribute( 'src', esc_url( $current_featured_image ) ); + $image_tag_processor->set_attribute( 'class', 'wp-image-' . get_post_thumbnail_id() . ' size-' . $media_size_slug ); + $image_tag_processor->set_attribute( 'alt', trim( strip_tags( get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ) ) ) ); + if ( $image_fill ) { + $image_tag_processor->set_attribute( 'style', 'object-position:' . $focal_point . ';' ); + } + + $content = $image_tag_processor->get_updated_html(); + } + } + + return $content; +} + +/** + * Registers the `core/media-text` block renderer on server. + * + * @since 6.6.0 + */ +function register_block_core_media_text() { + register_block_type_from_metadata( + __DIR__ . '/media-text', + array( + 'render_callback' => 'render_block_core_media_text', + ) + ); +} +add_action( 'init', 'register_block_core_media_text' ); diff --git a/src/wp-includes/blocks/media-text/block.json b/src/wp-includes/blocks/media-text/block.json new file mode 100644 index 0000000000000..249a5d43032c8 --- /dev/null +++ b/src/wp-includes/blocks/media-text/block.json @@ -0,0 +1,148 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/media-text", + "title": "Media & Text", + "category": "media", + "description": "Set media and words side-by-side for a richer layout.", + "keywords": [ "image", "video" ], + "textdomain": "default", + "attributes": { + "align": { + "type": "string", + "default": "none" + }, + "mediaAlt": { + "type": "string", + "source": "attribute", + "selector": "figure img", + "attribute": "alt", + "default": "", + "role": "content" + }, + "mediaPosition": { + "type": "string", + "default": "left" + }, + "mediaId": { + "type": "number", + "role": "content" + }, + "mediaUrl": { + "type": "string", + "source": "attribute", + "selector": "figure video,figure img", + "attribute": "src", + "role": "content" + }, + "mediaLink": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "linkTarget": { + "type": "string", + "source": "attribute", + "selector": "figure a", + "attribute": "target" + }, + "href": { + "type": "string", + "source": "attribute", + "selector": "figure a", + "attribute": "href", + "role": "content" + }, + "rel": { + "type": "string", + "source": "attribute", + "selector": "figure a", + "attribute": "rel" + }, + "linkClass": { + "type": "string", + "source": "attribute", + "selector": "figure a", + "attribute": "class" + }, + "mediaType": { + "type": "string", + "role": "content" + }, + "mediaWidth": { + "type": "number", + "default": 50 + }, + "mediaSizeSlug": { + "type": "string" + }, + "isStackedOnMobile": { + "type": "boolean", + "default": true + }, + "verticalAlignment": { + "type": "string" + }, + "imageFill": { + "type": "boolean" + }, + "focalPoint": { + "type": "object" + }, + "useFeaturedImage": { + "type": "boolean", + "default": false + } + }, + "usesContext": [ "postId", "postType" ], + "supports": { + "anchor": true, + "align": [ "wide", "full" ], + "html": false, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "color": { + "gradients": true, + "heading": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "allowedBlocks": true + }, + "editorStyle": "wp-block-media-text-editor", + "style": "wp-block-media-text" +} diff --git a/src/wp-includes/blocks/missing/block.json b/src/wp-includes/blocks/missing/block.json new file mode 100644 index 0000000000000..94051f20be7e5 --- /dev/null +++ b/src/wp-includes/blocks/missing/block.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/missing", + "title": "Unsupported", + "category": "text", + "description": "Your site doesn’t include support for this block.", + "textdomain": "default", + "attributes": { + "originalName": { + "type": "string" + }, + "originalUndelimitedContent": { + "type": "string" + }, + "originalContent": { + "type": "string", + "source": "raw" + } + }, + "supports": { + "className": false, + "customClassName": false, + "inserter": false, + "html": false, + "lock": false, + "reusable": false, + "renaming": false, + "blockVisibility": false, + "interactivity": { + "clientNavigation": true + } + } +} diff --git a/src/wp-includes/blocks/more/block.json b/src/wp-includes/blocks/more/block.json new file mode 100644 index 0000000000000..01c4b3ce961e5 --- /dev/null +++ b/src/wp-includes/blocks/more/block.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/more", + "title": "More", + "category": "design", + "description": "Content before this block will be shown in the excerpt on your archives page.", + "keywords": [ "read more" ], + "textdomain": "default", + "attributes": { + "customText": { + "type": "string", + "default": "", + "role": "content" + }, + "noTeaser": { + "type": "boolean", + "default": false + } + }, + "supports": { + "customClassName": false, + "className": false, + "html": false, + "multiple": false, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-more-editor" +} diff --git a/src/wp-includes/blocks/navigation-link.php b/src/wp-includes/blocks/navigation-link.php new file mode 100644 index 0000000000000..111598ea4c486 --- /dev/null +++ b/src/wp-includes/blocks/navigation-link.php @@ -0,0 +1,446 @@ + array(), + 'inline_styles' => '', + ); + + // Text color. + $named_text_color = null; + $custom_text_color = null; + + if ( $is_sub_menu && array_key_exists( 'customOverlayTextColor', $context ) ) { + $custom_text_color = $context['customOverlayTextColor']; + } elseif ( $is_sub_menu && array_key_exists( 'overlayTextColor', $context ) ) { + $named_text_color = $context['overlayTextColor']; + } elseif ( array_key_exists( 'customTextColor', $context ) ) { + $custom_text_color = $context['customTextColor']; + } elseif ( array_key_exists( 'textColor', $context ) ) { + $named_text_color = $context['textColor']; + } elseif ( isset( $context['style']['color']['text'] ) ) { + $custom_text_color = $context['style']['color']['text']; + } + + // If has text color. + if ( ! is_null( $named_text_color ) ) { + // Add the color class. + array_push( $colors['css_classes'], 'has-text-color', sprintf( 'has-%s-color', $named_text_color ) ); + } elseif ( ! is_null( $custom_text_color ) ) { + // Add the custom color inline style. + $colors['css_classes'][] = 'has-text-color'; + $colors['inline_styles'] .= sprintf( 'color: %s;', $custom_text_color ); + } + + // Background color. + $named_background_color = null; + $custom_background_color = null; + + if ( $is_sub_menu && array_key_exists( 'customOverlayBackgroundColor', $context ) ) { + $custom_background_color = $context['customOverlayBackgroundColor']; + } elseif ( $is_sub_menu && array_key_exists( 'overlayBackgroundColor', $context ) ) { + $named_background_color = $context['overlayBackgroundColor']; + } elseif ( array_key_exists( 'customBackgroundColor', $context ) ) { + $custom_background_color = $context['customBackgroundColor']; + } elseif ( array_key_exists( 'backgroundColor', $context ) ) { + $named_background_color = $context['backgroundColor']; + } elseif ( isset( $context['style']['color']['background'] ) ) { + $custom_background_color = $context['style']['color']['background']; + } + + // If has background color. + if ( ! is_null( $named_background_color ) ) { + // Add the background-color class. + array_push( $colors['css_classes'], 'has-background', sprintf( 'has-%s-background-color', $named_background_color ) ); + } elseif ( ! is_null( $custom_background_color ) ) { + // Add the custom background-color inline style. + $colors['css_classes'][] = 'has-background'; + $colors['inline_styles'] .= sprintf( 'background-color: %s;', $custom_background_color ); + } + + return $colors; +} + +/** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the navigation markup in the front-end. + * + * @since 5.9.0 + * + * @param array $context Navigation block context. + * @return array Font size CSS classes and inline styles. + */ +function block_core_navigation_link_build_css_font_sizes( $context ) { + // CSS classes. + $font_sizes = array( + 'css_classes' => array(), + 'inline_styles' => '', + ); + + $has_named_font_size = array_key_exists( 'fontSize', $context ); + $has_custom_font_size = isset( $context['style']['typography']['fontSize'] ); + + if ( $has_named_font_size ) { + // Add the font size class. + $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); + } elseif ( $has_custom_font_size ) { + // Add the custom font size inline style. + $font_sizes['inline_styles'] = sprintf( + 'font-size: %s;', + wp_get_typography_font_size_value( + array( + 'size' => $context['style']['typography']['fontSize'], + ) + ) + ); + } + + return $font_sizes; +} + +/** + * Returns the top-level submenu SVG chevron icon. + * + * @since 5.9.0 + * + * @return string + */ +function block_core_navigation_link_render_submenu_icon() { + return ''; +} + +/** + * Decodes a url if it's encoded, returning the same url if not. + * + * @since 6.2.0 + * + * @param string $url The url to decode. + * + * @return string $url Returns the decoded url. + */ +function block_core_navigation_link_maybe_urldecode( $url ) { + $is_url_encoded = false; + $query = parse_url( $url, PHP_URL_QUERY ); + $query_params = wp_parse_args( $query ); + + foreach ( $query_params as $query_param ) { + $can_query_param_be_encoded = is_string( $query_param ) && ! empty( $query_param ); + if ( ! $can_query_param_be_encoded ) { + continue; + } + if ( rawurldecode( $query_param ) !== $query_param ) { + $is_url_encoded = true; + break; + } + } + + if ( $is_url_encoded ) { + return rawurldecode( $url ); + } + + return $url; +} + + +/** + * Renders the `core/navigation-link` block. + * + * @since 5.9.0 + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ +function render_block_core_navigation_link( $attributes, $content, $block ) { + $navigation_link_has_id = isset( $attributes['id'] ) && is_numeric( $attributes['id'] ); + $is_post_type = isset( $attributes['kind'] ) && 'post-type' === $attributes['kind']; + $is_post_type = $is_post_type || isset( $attributes['type'] ) && ( 'post' === $attributes['type'] || 'page' === $attributes['type'] ); + + // Don't render the block's subtree if it is a draft or if the ID does not exist. + if ( $is_post_type && $navigation_link_has_id ) { + $post = get_post( $attributes['id'] ); + /** + * Filter allowed post_status for navigation link block to render. + * + * @since 6.8.0 + * + * @param array $post_status + * @param array $attributes + * @param WP_Block $block + */ + $allowed_post_status = (array) apply_filters( + 'render_block_core_navigation_link_allowed_post_status', + array( 'publish' ), + $attributes, + $block + ); + if ( ! $post || ! in_array( $post->post_status, $allowed_post_status, true ) ) { + return ''; + } + } + + // Don't render the block's subtree if it has no label. + if ( empty( $attributes['label'] ) ) { + return ''; + } + + $font_sizes = block_core_navigation_link_build_css_font_sizes( $block->context ); + $classes = array_merge( + $font_sizes['css_classes'] + ); + $style_attribute = $font_sizes['inline_styles']; + + $css_classes = trim( implode( ' ', $classes ) ); + $has_submenu = count( $block->inner_blocks ) > 0; + $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] ); + $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind ); + + if ( is_post_type_archive() && ! empty( $attributes['url'] ) ) { + $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); + if ( $attributes['url'] === $queried_archive_link ) { + $is_active = true; + } + } + + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => $css_classes . ' wp-block-navigation-item' . ( $has_submenu ? ' has-child' : '' ) . + ( $is_active ? ' current-menu-item' : '' ), + 'style' => $style_attribute, + ) + ); + $html = '
    1. ' . + ''; + + if ( isset( $attributes['label'] ) ) { + $html .= wp_kses_post( $attributes['label'] ); + } + + $html .= ''; + + // Add description if available. + if ( ! empty( $attributes['description'] ) ) { + $html .= ''; + $html .= wp_kses_post( $attributes['description'] ); + $html .= ''; + } + + $html .= ''; + // End anchor tag content. + + if ( isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon'] && $has_submenu ) { + // The submenu icon can be hidden by a CSS rule on the Navigation Block. + $html .= '' . block_core_navigation_link_render_submenu_icon() . ''; + } + + if ( $has_submenu ) { + $inner_blocks_html = ''; + foreach ( $block->inner_blocks as $inner_block ) { + $inner_blocks_html .= $inner_block->render(); + } + + $html .= sprintf( + '
        %s
      ', + $inner_blocks_html + ); + } + + $html .= '
    2. '; + + return $html; +} + +/** + * Returns a navigation link variation + * + * @since 5.9.0 + * + * @param WP_Taxonomy|WP_Post_Type $entity post type or taxonomy entity. + * @param string $kind string of value 'taxonomy' or 'post-type'. + * + * @return array + */ +function build_variation_for_navigation_link( $entity, $kind ) { + $title = ''; + $description = ''; + + if ( property_exists( $entity->labels, 'item_link' ) ) { + $title = $entity->labels->item_link; + } + if ( property_exists( $entity->labels, 'item_link_description' ) ) { + $description = $entity->labels->item_link_description; + } + + $variation = array( + 'name' => $entity->name, + 'title' => $title, + 'description' => $description, + 'attributes' => array( + 'type' => $entity->name, + 'kind' => $kind, + ), + ); + + // Tweak some value for the variations. + $variation_overrides = array( + 'post_tag' => array( + 'name' => 'tag', + 'attributes' => array( + 'type' => 'tag', + 'kind' => $kind, + ), + ), + 'post_format' => array( + // The item_link and item_link_description for post formats is the + // same as for tags, so need to be overridden. + 'title' => __( 'Post Format Link' ), + 'description' => __( 'A link to a post format' ), + 'attributes' => array( + 'type' => 'post_format', + 'kind' => $kind, + ), + ), + ); + + if ( array_key_exists( $entity->name, $variation_overrides ) ) { + $variation = array_merge( + $variation, + $variation_overrides[ $entity->name ] + ); + } + + return $variation; +} + +/** + * Filters the registered variations for a block type. + * Returns the dynamically built variations for all post-types and taxonomies. + * + * @since 6.5.0 + * + * @param array $variations Array of registered variations for a block type. + * @param WP_Block_Type $block_type The full block type object. + */ +function block_core_navigation_link_filter_variations( $variations, $block_type ) { + if ( 'core/navigation-link' !== $block_type->name ) { + return $variations; + } + + $generated_variations = block_core_navigation_link_build_variations(); + return array_merge( $variations, $generated_variations ); +} + +/** + * Returns an array of variations for the navigation link block. + * + * @since 6.5.0 + * + * @return array + */ +function block_core_navigation_link_build_variations() { + $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' ); + $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' ); + + /* + * Use two separate arrays as a way to order the variations in the UI. + * Known variations (like Post Link and Page Link) are added to the + * `built_ins` array. Variations for custom post types and taxonomies are + * added to the `variations` array and will always appear after `built-ins. + */ + $built_ins = array(); + $variations = array(); + + if ( $post_types ) { + foreach ( $post_types as $post_type ) { + $variation = build_variation_for_navigation_link( $post_type, 'post-type' ); + if ( $post_type->_builtin ) { + $built_ins[] = $variation; + } else { + $variations[] = $variation; + } + } + } + if ( $taxonomies ) { + foreach ( $taxonomies as $taxonomy ) { + $variation = build_variation_for_navigation_link( $taxonomy, 'taxonomy' ); + if ( $taxonomy->_builtin ) { + $built_ins[] = $variation; + } else { + $variations[] = $variation; + } + } + } + + return array_merge( $built_ins, $variations ); +} + +/** + * Registers the navigation link block. + * + * @since 5.9.0 + * + * @uses render_block_core_navigation_link() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ +function register_block_core_navigation_link() { + register_block_type_from_metadata( + __DIR__ . '/navigation-link', + array( + 'render_callback' => 'render_block_core_navigation_link', + ) + ); +} +add_action( 'init', 'register_block_core_navigation_link' ); +/** + * Creates all variations for post types / taxonomies dynamically (= each time when variations are requested). + * Do not use variation_callback, to also account for unregistering post types/taxonomies later on. + */ +add_action( 'get_block_type_variations', 'block_core_navigation_link_filter_variations', 10, 2 ); diff --git a/src/wp-includes/blocks/navigation-link/block.json b/src/wp-includes/blocks/navigation-link/block.json new file mode 100644 index 0000000000000..5f2d10b97dabe --- /dev/null +++ b/src/wp-includes/blocks/navigation-link/block.json @@ -0,0 +1,88 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/navigation-link", + "title": "Custom Link", + "category": "design", + "parent": [ "core/navigation" ], + "allowedBlocks": [ + "core/navigation-link", + "core/navigation-submenu", + "core/page-list" + ], + "description": "Add a page, link, or another item to your navigation.", + "textdomain": "default", + "attributes": { + "label": { + "type": "string", + "role": "content" + }, + "type": { + "type": "string" + }, + "description": { + "type": "string" + }, + "rel": { + "type": "string" + }, + "id": { + "type": "number" + }, + "opensInNewTab": { + "type": "boolean", + "default": false + }, + "url": { + "type": "string" + }, + "title": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "isTopLevelLink": { + "type": "boolean" + } + }, + "usesContext": [ + "textColor", + "customTextColor", + "backgroundColor", + "customBackgroundColor", + "overlayTextColor", + "customOverlayTextColor", + "overlayBackgroundColor", + "customOverlayBackgroundColor", + "fontSize", + "customFontSize", + "showSubmenuIcon", + "maxNestingLevel", + "style" + ], + "supports": { + "reusable": false, + "html": false, + "__experimentalSlashInserter": true, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "renaming": false, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-navigation-link-editor", + "style": "wp-block-navigation-link" +} diff --git a/src/wp-includes/blocks/navigation-submenu.php b/src/wp-includes/blocks/navigation-submenu.php new file mode 100644 index 0000000000000..77f2c1fa635fc --- /dev/null +++ b/src/wp-includes/blocks/navigation-submenu.php @@ -0,0 +1,300 @@ + array(), + 'inline_styles' => '', + ); + + $has_named_font_size = array_key_exists( 'fontSize', $context ); + $has_custom_font_size = isset( $context['style']['typography']['fontSize'] ); + + if ( $has_named_font_size ) { + // Add the font size class. + $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); + } elseif ( $has_custom_font_size ) { + // Add the custom font size inline style. + $font_sizes['inline_styles'] = sprintf( + 'font-size: %s;', + wp_get_typography_font_size_value( + array( + 'size' => $context['style']['typography']['fontSize'], + ) + ) + ); + } + + return $font_sizes; +} + +/** + * Returns the top-level submenu SVG chevron icon. + * + * @since 5.9.0 + * + * @return string + */ +function block_core_navigation_submenu_render_submenu_icon() { + return ''; +} + +/** + * Renders the `core/navigation-submenu` block. + * + * @since 5.9.0 + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ +function render_block_core_navigation_submenu( $attributes, $content, $block ) { + $navigation_link_has_id = isset( $attributes['id'] ) && is_numeric( $attributes['id'] ); + $is_post_type = isset( $attributes['kind'] ) && 'post-type' === $attributes['kind']; + $is_post_type = $is_post_type || isset( $attributes['type'] ) && ( 'post' === $attributes['type'] || 'page' === $attributes['type'] ); + + // Don't render the block's subtree if it is a draft. + if ( $is_post_type && $navigation_link_has_id && 'publish' !== get_post_status( $attributes['id'] ) ) { + return ''; + } + + // Don't render the block's subtree if it has no label. + if ( empty( $attributes['label'] ) ) { + return ''; + } + + $font_sizes = block_core_navigation_submenu_build_css_font_sizes( $block->context ); + $style_attribute = $font_sizes['inline_styles']; + + $has_submenu = count( $block->inner_blocks ) > 0; + $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] ); + $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind ); + + if ( is_post_type_archive() && ! empty( $attributes['url'] ) ) { + $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); + if ( $attributes['url'] === $queried_archive_link ) { + $is_active = true; + } + } + + $show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon']; + $open_on_click = isset( $block->context['openSubmenusOnClick'] ) && $block->context['openSubmenusOnClick']; + $open_on_hover_and_click = isset( $block->context['openSubmenusOnClick'] ) && ! $block->context['openSubmenusOnClick'] && + $show_submenu_indicators; + + $classes = array( + 'wp-block-navigation-item', + ); + $classes = array_merge( + $classes, + $font_sizes['css_classes'] + ); + if ( $has_submenu ) { + $classes[] = 'has-child'; + } + if ( $open_on_click ) { + $classes[] = 'open-on-click'; + } + if ( $open_on_hover_and_click ) { + $classes[] = 'open-on-hover-click'; + } + if ( $is_active ) { + $classes[] = 'current-menu-item'; + } + + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => implode( ' ', $classes ), + 'style' => $style_attribute, + ) + ); + + $label = ''; + + if ( isset( $attributes['label'] ) ) { + $label .= wp_kses_post( $attributes['label'] ); + } + + $aria_label = sprintf( + /* translators: Accessibility text. %s: Parent page title. */ + __( '%s submenu' ), + wp_strip_all_tags( $label ) + ); + + $html = '
    3. '; + + // If Submenus open on hover, we render an anchor tag with attributes. + // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click. + if ( ! $open_on_click ) { + $item_url = isset( $attributes['url'] ) ? $attributes['url'] : ''; + // Start appending HTML attributes to anchor tag. + $html .= '
    4. ' . $title . ''; + } + + if ( isset( $page['children'] ) ) { + if ( $is_navigation_child && $show_submenu_icons && ! $open_submenus_on_click ) { + $markup .= ''; + } + $markup .= '
        '; + $markup .= block_core_page_list_render_nested_page_list( $open_submenus_on_click, $show_submenu_icons, $is_navigation_child, $page['children'], $is_nested, $active_page_ancestor_ids, $colors, $depth + 1 ); + $markup .= '
      '; + } + $markup .= '
    5. '; + } + return $markup; +} + +/** + * Outputs nested array of pages + * + * @since 5.8.0 + * + * @param array $current_level The level being iterated through. + * @param array $children The children grouped by parent post ID. + * + * @return array The nested array of pages. + */ +function block_core_page_list_nest_pages( $current_level, $children ) { + if ( empty( $current_level ) ) { + return; + } + foreach ( (array) $current_level as $key => $current ) { + if ( isset( $children[ $key ] ) ) { + $current_level[ $key ]['children'] = block_core_page_list_nest_pages( $children[ $key ], $children ); + } + } + return $current_level; +} + +/** + * Renders the `core/page-list` block on server. + * + * @since 5.8.0 + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the page list markup. + */ +function render_block_core_page_list( $attributes, $content, $block ) { + static $block_id = 0; + ++$block_id; + + $parent_page_id = $attributes['parentPageID']; + $is_nested = $attributes['isNested']; + + $all_pages = get_pages( + array( + 'sort_column' => 'menu_order,post_title', + 'order' => 'asc', + ) + ); + + // If there are no pages, there is nothing to show. + if ( empty( $all_pages ) ) { + return; + } + + $top_level_pages = array(); + + $pages_with_children = array(); + + $active_page_ancestor_ids = array(); + + foreach ( (array) $all_pages as $page ) { + $is_active = ! empty( $page->ID ) && ( get_queried_object_id() === $page->ID ); + + if ( $is_active ) { + $active_page_ancestor_ids = get_post_ancestors( $page->ID ); + } + + if ( $page->post_parent ) { + $pages_with_children[ $page->post_parent ][ $page->ID ] = array( + 'page_id' => $page->ID, + 'title' => $page->post_title, + 'link' => get_permalink( $page ), + 'is_active' => $is_active, + ); + } else { + $top_level_pages[ $page->ID ] = array( + 'page_id' => $page->ID, + 'title' => $page->post_title, + 'link' => get_permalink( $page ), + 'is_active' => $is_active, + ); + + } + } + + $colors = block_core_page_list_build_css_colors( $attributes, $block->context ); + $font_sizes = block_core_page_list_build_css_font_sizes( $block->context ); + $classes = array_merge( + $colors['css_classes'], + $font_sizes['css_classes'] + ); + $style_attribute = ( $colors['inline_styles'] . $font_sizes['inline_styles'] ); + $css_classes = trim( implode( ' ', $classes ) ); + + $nested_pages = block_core_page_list_nest_pages( $top_level_pages, $pages_with_children ); + + if ( 0 !== $parent_page_id ) { + // If the parent page has no child pages, there is nothing to show. + if ( ! array_key_exists( $parent_page_id, $pages_with_children ) ) { + return; + } + + $nested_pages = block_core_page_list_nest_pages( + $pages_with_children[ $parent_page_id ], + $pages_with_children + ); + } + + $is_navigation_child = array_key_exists( 'showSubmenuIcon', $block->context ); + + $open_submenus_on_click = array_key_exists( 'openSubmenusOnClick', $block->context ) ? $block->context['openSubmenusOnClick'] : false; + + $show_submenu_icons = array_key_exists( 'showSubmenuIcon', $block->context ) ? $block->context['showSubmenuIcon'] : false; + + $wrapper_markup = $is_nested ? '%2$s' : '
        %2$s
      '; + + $items_markup = block_core_page_list_render_nested_page_list( $open_submenus_on_click, $show_submenu_icons, $is_navigation_child, $nested_pages, $is_nested, $active_page_ancestor_ids, $colors ); + + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => $css_classes, + 'style' => $style_attribute, + ) + ); + + return sprintf( + $wrapper_markup, + $wrapper_attributes, + $items_markup + ); +} + +/** + * Registers the `core/pages` block on server. + * + * @since 5.8.0 + */ +function register_block_core_page_list() { + register_block_type_from_metadata( + __DIR__ . '/page-list', + array( + 'render_callback' => 'render_block_core_page_list', + ) + ); +} +add_action( 'init', 'register_block_core_page_list' ); diff --git a/src/wp-includes/blocks/page-list/block.json b/src/wp-includes/blocks/page-list/block.json new file mode 100644 index 0000000000000..317502b1200b4 --- /dev/null +++ b/src/wp-includes/blocks/page-list/block.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/page-list", + "title": "Page List", + "category": "widgets", + "allowedBlocks": [ "core/page-list-item" ], + "description": "Display a list of all pages.", + "keywords": [ "menu", "navigation" ], + "textdomain": "default", + "attributes": { + "parentPageID": { + "type": "integer", + "default": 0 + }, + "isNested": { + "type": "boolean", + "default": false + } + }, + "usesContext": [ + "textColor", + "customTextColor", + "backgroundColor", + "customBackgroundColor", + "overlayTextColor", + "customOverlayTextColor", + "overlayBackgroundColor", + "customOverlayBackgroundColor", + "fontSize", + "customFontSize", + "showSubmenuIcon", + "style", + "openSubmenusOnClick" + ], + "supports": { + "reusable": false, + "html": false, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "color": { + "text": true, + "background": true, + "link": true, + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "spacing": { + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "padding": false, + "margin": false + } + }, + "contentRole": true + }, + "editorStyle": "wp-block-page-list-editor", + "style": "wp-block-page-list" +} diff --git a/src/wp-includes/blocks/paragraph/block.json b/src/wp-includes/blocks/paragraph/block.json new file mode 100644 index 0000000000000..9617627ef5d0d --- /dev/null +++ b/src/wp-includes/blocks/paragraph/block.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/paragraph", + "title": "Paragraph", + "category": "text", + "description": "Start with the basic building block of all narrative.", + "keywords": [ "text" ], + "textdomain": "default", + "attributes": { + "align": { + "type": "string" + }, + "content": { + "type": "rich-text", + "source": "rich-text", + "selector": "p", + "role": "content" + }, + "dropCap": { + "type": "boolean", + "default": false + }, + "placeholder": { + "type": "string" + }, + "direction": { + "type": "string", + "enum": [ "ltr", "rtl" ] + } + }, + "supports": { + "splitting": true, + "anchor": true, + "className": false, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalTextDecoration": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalWritingMode": true, + "fitText": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalSelector": "p", + "__unstablePasteTextInline": true, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-paragraph-editor", + "style": "wp-block-paragraph" +} diff --git a/src/wp-includes/blocks/pattern.php b/src/wp-includes/blocks/pattern.php new file mode 100644 index 0000000000000..870313eb5e86d --- /dev/null +++ b/src/wp-includes/blocks/pattern.php @@ -0,0 +1,72 @@ + 'render_block_core_pattern', + ) + ); +} + +/** + * Renders the `core/pattern` block on the server. + * + * @since 6.3.0 Backwards compatibility: blocks with no `syncStatus` attribute do not receive block wrapper. + * + * @global WP_Embed $wp_embed Used to process embedded content within patterns + * + * @param array $attributes Block attributes. + * + * @return string Returns the output of the pattern. + */ +function render_block_core_pattern( $attributes ) { + static $seen_refs = array(); + + if ( empty( $attributes['slug'] ) ) { + return ''; + } + + $slug = $attributes['slug']; + $registry = WP_Block_Patterns_Registry::get_instance(); + + if ( ! $registry->is_registered( $slug ) ) { + return ''; + } + + if ( isset( $seen_refs[ $attributes['slug'] ] ) ) { + // WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent + // is set in `wp_debug_mode()`. + $is_debug = WP_DEBUG && WP_DEBUG_DISPLAY; + + return $is_debug ? + // translators: Visible only in the front end, this warning takes the place of a faulty block. %s represents a pattern's slug. + sprintf( __( '[block rendering halted for pattern "%s"]' ), $slug ) : + ''; + } + + $pattern = $registry->get_registered( $slug ); + $content = $pattern['content']; + + $seen_refs[ $attributes['slug'] ] = true; + + $content = do_blocks( $content ); + + global $wp_embed; + $content = $wp_embed->autoembed( $content ); + + unset( $seen_refs[ $attributes['slug'] ] ); + return $content; +} + +add_action( 'init', 'register_block_core_pattern' ); diff --git a/src/wp-includes/blocks/pattern/block.json b/src/wp-includes/blocks/pattern/block.json new file mode 100644 index 0000000000000..2a761dfd643ba --- /dev/null +++ b/src/wp-includes/blocks/pattern/block.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/pattern", + "title": "Pattern Placeholder", + "category": "theme", + "description": "Show a block pattern.", + "supports": { + "html": false, + "inserter": false, + "renaming": false, + "blockVisibility": false, + "interactivity": { + "clientNavigation": true + } + }, + "textdomain": "default", + "attributes": { + "slug": { + "type": "string" + } + } +} diff --git a/src/wp-includes/blocks/post-author-biography.php b/src/wp-includes/blocks/post-author-biography.php new file mode 100644 index 0000000000000..bd983f79e7609 --- /dev/null +++ b/src/wp-includes/blocks/post-author-biography.php @@ -0,0 +1,53 @@ +context['postId'] ) ) { + $author_id = get_post_field( 'post_author', $block->context['postId'] ); + } else { + $author_id = get_query_var( 'author' ); + } + + if ( empty( $author_id ) ) { + return ''; + } + + $author_biography = get_the_author_meta( 'description', $author_id ); + if ( empty( $author_biography ) ) { + return ''; + } + + $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}"; + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $align_class_name ) ); + + return sprintf( '
      ', $wrapper_attributes ) . $author_biography . '
      '; +} + +/** + * Registers the `core/post-author-biography` block on the server. + * + * @since 6.0.0 + */ +function register_block_core_post_author_biography() { + register_block_type_from_metadata( + __DIR__ . '/post-author-biography', + array( + 'render_callback' => 'render_block_core_post_author_biography', + ) + ); +} +add_action( 'init', 'register_block_core_post_author_biography' ); diff --git a/src/wp-includes/blocks/post-author-biography/block.json b/src/wp-includes/blocks/post-author-biography/block.json new file mode 100644 index 0000000000000..c6e27bc484dfd --- /dev/null +++ b/src/wp-includes/blocks/post-author-biography/block.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-author-biography", + "title": "Author Biography", + "category": "theme", + "description": "The author biography.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + } + }, + "usesContext": [ "postType", "postId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "spacing": { + "margin": true, + "padding": true + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-author-biography" +} diff --git a/src/wp-includes/blocks/post-author-name.php b/src/wp-includes/blocks/post-author-name.php new file mode 100644 index 0000000000000..ac514401f5cc2 --- /dev/null +++ b/src/wp-includes/blocks/post-author-name.php @@ -0,0 +1,63 @@ +context['postId'] ) ) { + $author_id = get_post_field( 'post_author', $block->context['postId'] ); + } else { + $author_id = get_query_var( 'author' ); + } + + if ( empty( $author_id ) ) { + return ''; + } + + if ( isset( $block->context['postType'] ) && ! post_type_supports( $block->context['postType'], 'author' ) ) { + return ''; + } + + $author_name = get_the_author_meta( 'display_name', $author_id ); + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] ) { + $author_name = sprintf( '', get_author_posts_url( $author_id ), esc_attr( $attributes['linkTarget'] ), $author_name ); + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return sprintf( '
      %2$s
      ', $wrapper_attributes, $author_name ); +} + +/** + * Registers the `core/post-author-name` block on the server. + * + * @since 6.2.0 + */ +function register_block_core_post_author_name() { + register_block_type_from_metadata( + __DIR__ . '/post-author-name', + array( + 'render_callback' => 'render_block_core_post_author_name', + ) + ); +} +add_action( 'init', 'register_block_core_post_author_name' ); diff --git a/src/wp-includes/blocks/post-author-name/block.json b/src/wp-includes/blocks/post-author-name/block.json new file mode 100644 index 0000000000000..23211f0bf5bf4 --- /dev/null +++ b/src/wp-includes/blocks/post-author-name/block.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-author-name", + "title": "Author Name", + "category": "theme", + "description": "The author name.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + }, + "isLink": { + "type": "boolean", + "default": false, + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + } + }, + "usesContext": [ "postType", "postId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-author-name" +} diff --git a/src/wp-includes/blocks/post-author.php b/src/wp-includes/blocks/post-author.php new file mode 100644 index 0000000000000..a4880f8a9e744 --- /dev/null +++ b/src/wp-includes/blocks/post-author.php @@ -0,0 +1,81 @@ +context['postId'] ) ) { + $author_id = get_query_var( 'author' ); + } else { + $author_id = get_post_field( 'post_author', $block->context['postId'] ); + } + + if ( empty( $author_id ) ) { + return ''; + } + + if ( isset( $block->context['postType'] ) && ! post_type_supports( $block->context['postType'], 'author' ) ) { + return ''; + } + + $avatar = ! empty( $attributes['avatarSize'] ) ? get_avatar( + $author_id, + $attributes['avatarSize'] + ) : null; + + $link = get_author_posts_url( $author_id ); + $author_name = get_the_author_meta( 'display_name', $author_id ); + if ( ! empty( $attributes['isLink'] && ! empty( $attributes['linkTarget'] ) ) ) { + $author_name = sprintf( '%3$s', esc_url( $link ), esc_attr( $attributes['linkTarget'] ), $author_name ); + } + + $byline = ! empty( $attributes['byline'] ) ? $attributes['byline'] : false; + $classes = array(); + if ( isset( $attributes['itemsJustification'] ) ) { + $classes[] = 'items-justified-' . $attributes['itemsJustification']; + } + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return sprintf( '
      ', $wrapper_attributes ) . + ( ! empty( $attributes['showAvatar'] ) ? '' : '' ) . + '' . + '
      '; +} + +/** + * Registers the `core/post-author` block on the server. + * + * @since 5.9.0 + */ +function register_block_core_post_author() { + register_block_type_from_metadata( + __DIR__ . '/post-author', + array( + 'render_callback' => 'render_block_core_post_author', + ) + ); +} +add_action( 'init', 'register_block_core_post_author' ); diff --git a/src/wp-includes/blocks/post-author/block.json b/src/wp-includes/blocks/post-author/block.json new file mode 100644 index 0000000000000..a83bb48bd840a --- /dev/null +++ b/src/wp-includes/blocks/post-author/block.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-author", + "title": "Author", + "category": "theme", + "description": "Display post author details such as name, avatar, and bio.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + }, + "avatarSize": { + "type": "number", + "default": 48 + }, + "showAvatar": { + "type": "boolean", + "default": true + }, + "showBio": { + "type": "boolean" + }, + "byline": { + "type": "string" + }, + "isLink": { + "type": "boolean", + "default": false, + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + } + }, + "usesContext": [ "postType", "postId", "queryId" ], + "supports": { + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "filter": { + "duotone": true + } + }, + "selectors": { + "filter": { + "duotone": ".wp-block-post-author .wp-block-post-author__avatar img" + } + }, + "editorStyle": "wp-block-post-author-editor", + "style": "wp-block-post-author" +} diff --git a/src/wp-includes/blocks/post-comments-count.php b/src/wp-includes/blocks/post-comments-count.php new file mode 100644 index 0000000000000..bf12d6f0f9c4c --- /dev/null +++ b/src/wp-includes/blocks/post-comments-count.php @@ -0,0 +1,49 @@ +context['postId'] ) ) { + return ''; + } + + $classes = ''; + if ( isset( $attributes['textAlign'] ) ) { + $classes .= 'has-text-align-' . $attributes['textAlign']; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) ); + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + get_comments_number( $block->context['postId'] ) + ); +} + +/** + * Registers the `core/post-comments-count` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_post_comments_count() { + register_block_type_from_metadata( + __DIR__ . '/post-comments-count', + array( + 'render_callback' => 'render_block_core_post_comments_count', + ) + ); +} +add_action( 'init', 'register_block_core_post_comments_count' ); diff --git a/src/wp-includes/blocks/post-comments-count/block.json b/src/wp-includes/blocks/post-comments-count/block.json new file mode 100644 index 0000000000000..fa8ade2f2c12f --- /dev/null +++ b/src/wp-includes/blocks/post-comments-count/block.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-comments-count", + "title": "Comments Count", + "category": "theme", + "description": "Display a post's comments count.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + } + }, + "usesContext": [ "postId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-post-comments-count" +} diff --git a/src/wp-includes/blocks/post-comments-form.php b/src/wp-includes/blocks/post-comments-form.php new file mode 100644 index 0000000000000..dfbf4c59f264a --- /dev/null +++ b/src/wp-includes/blocks/post-comments-form.php @@ -0,0 +1,88 @@ +context['postId'] ) ) { + return ''; + } + + if ( post_password_required( $block->context['postId'] ) ) { + return; + } + + $classes = array( 'comment-respond' ); // See comment further below. + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + add_filter( 'comment_form_defaults', 'post_comments_form_block_form_defaults' ); + + ob_start(); + comment_form( array(), $block->context['postId'] ); + $form = ob_get_clean(); + + remove_filter( 'comment_form_defaults', 'post_comments_form_block_form_defaults' ); + + // We use the outermost wrapping `
      ` returned by `comment_form()` + // which is identified by its default classname `comment-respond` to inject + // our wrapper attributes. This way, it is guaranteed that all styling applied + // to the block is carried along when the comment form is moved to the location + // of the 'Reply' link that the user clicked by Core's `comment-reply.js` script. + $form = str_replace( 'class="comment-respond"', $wrapper_attributes, $form ); + + // Enqueue the comment-reply script. + wp_enqueue_script( 'comment-reply' ); + + return $form; +} + +/** + * Registers the `core/post-comments-form` block on the server. + * + * @since 6.0.0 + */ +function register_block_core_post_comments_form() { + register_block_type_from_metadata( + __DIR__ . '/post-comments-form', + array( + 'render_callback' => 'render_block_core_post_comments_form', + ) + ); +} +add_action( 'init', 'register_block_core_post_comments_form' ); + +/** + * Use the button block classes for the form-submit button. + * + * @since 6.0.0 + * + * @param array $fields The default comment form arguments. + * + * @return array Returns the modified fields. + */ +function post_comments_form_block_form_defaults( $fields ) { + if ( wp_is_block_theme() ) { + $fields['submit_button'] = ''; + $fields['submit_field'] = '

      %1$s %2$s

      '; + } + + return $fields; +} diff --git a/src/wp-includes/blocks/post-comments-form/block.json b/src/wp-includes/blocks/post-comments-form/block.json new file mode 100644 index 0000000000000..4b6b333b75cfa --- /dev/null +++ b/src/wp-includes/blocks/post-comments-form/block.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-comments-form", + "title": "Comments Form", + "category": "theme", + "description": "Display a post's comments form.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + } + }, + "usesContext": [ "postId", "postType" ], + "supports": { + "html": false, + "color": { + "gradients": true, + "heading": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "editorStyle": "wp-block-post-comments-form-editor", + "style": [ + "wp-block-post-comments-form", + "wp-block-buttons", + "wp-block-button" + ], + "example": { + "attributes": { + "textAlign": "center" + } + } +} diff --git a/src/wp-includes/blocks/post-comments-link.php b/src/wp-includes/blocks/post-comments-link.php new file mode 100644 index 0000000000000..c6d33eb0cd65c --- /dev/null +++ b/src/wp-includes/blocks/post-comments-link.php @@ -0,0 +1,75 @@ +context['postId'] ) || + isset( $block->context['postId'] ) && + ! comments_open( $block->context['postId'] ) + ) { + return ''; + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + $comments_number = (int) get_comments_number( $block->context['postId'] ); + $comments_link = get_comments_link( $block->context['postId'] ); + $post_title = get_the_title( $block->context['postId'] ); + $comment_html = ''; + + if ( 0 === $comments_number ) { + $comment_html = sprintf( + /* translators: %s post title */ + __( 'No comments on %s' ), + $post_title + ); + } else { + $comment_html = sprintf( + /* translators: 1: Number of comments, 2: post title */ + _n( + '%1$s comment on %2$s', + '%1$s comments on %2$s', + $comments_number + ), + esc_html( number_format_i18n( $comments_number ) ), + $post_title + ); + } + + return '
      ' . $comment_html . '
      '; +} + +/** + * Registers the `core/post-comments-link` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_post_comments_link() { + register_block_type_from_metadata( + __DIR__ . '/post-comments-link', + array( + 'render_callback' => 'render_block_core_post_comments_link', + ) + ); +} +add_action( 'init', 'register_block_core_post_comments_link' ); diff --git a/src/wp-includes/blocks/post-comments-link/block.json b/src/wp-includes/blocks/post-comments-link/block.json new file mode 100644 index 0000000000000..e0dcdb9afa03d --- /dev/null +++ b/src/wp-includes/blocks/post-comments-link/block.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-comments-link", + "title": "Comments Link", + "category": "theme", + "description": "Displays the link to the current post comments.", + "textdomain": "default", + "usesContext": [ "postType", "postId" ], + "attributes": { + "textAlign": { + "type": "string" + } + }, + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "color": { + "link": true, + "text": false, + "__experimentalDefaultControls": { + "background": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-comments-link" +} diff --git a/src/wp-includes/blocks/post-content.php b/src/wp-includes/blocks/post-content.php new file mode 100644 index 0000000000000..0be1a8730f605 --- /dev/null +++ b/src/wp-includes/blocks/post-content.php @@ -0,0 +1,86 @@ +context['postId'] ) ) { + return ''; + } + + $post_id = $block->context['postId']; + + if ( isset( $seen_ids[ $post_id ] ) ) { + // WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent + // is set in `wp_debug_mode()`. + $is_debug = WP_DEBUG && WP_DEBUG_DISPLAY; + + return $is_debug ? + // translators: Visible only in the front end, this warning takes the place of a faulty block. + __( '[block rendering halted]' ) : + ''; + } + + $seen_ids[ $post_id ] = true; + + // When inside the main loop, we want to use queried object + // so that `the_preview` for the current post can apply. + // We force this behavior by omitting the third argument (post ID) from the `get_the_content`. + $content = get_the_content(); + // Check for nextpage to display page links for paginated posts. + if ( has_block( 'core/nextpage' ) ) { + $content .= wp_link_pages( array( 'echo' => 0 ) ); + } + + /** This filter is documented in wp-includes/post-template.php */ + $content = apply_filters( 'the_content', str_replace( ']]>', ']]>', $content ) ); + unset( $seen_ids[ $post_id ] ); + + if ( empty( $content ) ) { + return ''; + } + + $tag_name = 'div'; + + if ( ! empty( $attributes['tagName'] ) && tag_escape( $attributes['tagName'] ) === $attributes['tagName'] ) { + $tag_name = $attributes['tagName']; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => 'entry-content' ) ); + + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/post-content` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_content() { + register_block_type_from_metadata( + __DIR__ . '/post-content', + array( + 'render_callback' => 'render_block_core_post_content', + ) + ); +} +add_action( 'init', 'register_block_core_post_content' ); diff --git a/src/wp-includes/blocks/post-content/block.json b/src/wp-includes/blocks/post-content/block.json new file mode 100644 index 0000000000000..264f6959304fe --- /dev/null +++ b/src/wp-includes/blocks/post-content/block.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-content", + "title": "Content", + "category": "theme", + "description": "Displays the contents of a post or page.", + "textdomain": "default", + "usesContext": [ "postId", "postType", "queryId" ], + "attributes": { + "tagName": { + "type": "string", + "default": "div" + } + }, + "example": { + "viewportWidth": 350 + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "layout": true, + "background": { + "backgroundImage": true, + "backgroundSize": true, + "__experimentalDefaultControls": { + "backgroundImage": true + } + }, + "dimensions": { + "minHeight": true + }, + "spacing": { + "blockGap": true, + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "color": { + "gradients": true, + "heading": true, + "link": true, + "__experimentalDefaultControls": { + "background": false, + "text": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-content", + "editorStyle": "wp-block-post-content-editor" +} diff --git a/src/wp-includes/blocks/post-date.php b/src/wp-includes/blocks/post-date.php new file mode 100644 index 0000000000000..e12a26eda7c12 --- /dev/null +++ b/src/wp-includes/blocks/post-date.php @@ -0,0 +1,109 @@ + 'modified', + ); + } else { + $source_args = array( + 'field' => 'date', + ); + } + $attributes['datetime'] = $source->get_value( $source_args, $block, 'datetime' ); + } + + if ( isset( $source_args['field'] ) && 'modified' === $source_args['field'] ) { + $classes[] = 'wp-block-post-date__modified-date'; + } + + if ( empty( $attributes['datetime'] ) ) { + // If the `datetime` attribute is set but empty, it could be because Block Bindings + // set it that way. This can happen e.g. if the block is bound to the + // post's last modified date, and the latter lies before the publish date. + // (See https://github.com/WordPress/gutenberg/pull/46839 where this logic was originally + // implemented.) + // In this case, we have to respect and return the empty value. + return ''; + } + + $unformatted_date = $attributes['datetime']; + $post_timestamp = strtotime( $unformatted_date ); + + if ( isset( $attributes['format'] ) && 'human-diff' === $attributes['format'] ) { + if ( $post_timestamp > time() ) { + // translators: %s: human-readable time difference. + $formatted_date = sprintf( __( '%s from now' ), human_time_diff( $post_timestamp ) ); + } else { + // translators: %s: human-readable time difference. + $formatted_date = sprintf( __( '%s ago' ), human_time_diff( $post_timestamp ) ); + } + } else { + $format = empty( $attributes['format'] ) ? get_option( 'date_format' ) : $attributes['format']; + $formatted_date = wp_date( $format, $post_timestamp ); + } + + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] && isset( $block->context['postId'] ) ) { + $formatted_date = sprintf( '%2s', get_the_permalink( $block->context['postId'] ), $formatted_date ); + } + + return sprintf( + '
      ', + $wrapper_attributes, + $unformatted_date, + $formatted_date + ); +} + +/** + * Registers the `core/post-date` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_date() { + register_block_type_from_metadata( + __DIR__ . '/post-date', + array( + 'render_callback' => 'render_block_core_post_date', + ) + ); +} +add_action( 'init', 'register_block_core_post_date' ); diff --git a/src/wp-includes/blocks/post-date/block.json b/src/wp-includes/blocks/post-date/block.json new file mode 100644 index 0000000000000..ea99f6ab5ff8d --- /dev/null +++ b/src/wp-includes/blocks/post-date/block.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-date", + "title": "Date", + "category": "theme", + "description": "Display a custom date.", + "textdomain": "default", + "attributes": { + "datetime": { + "type": "string", + "role": "content" + }, + "textAlign": { + "type": "string" + }, + "format": { + "type": "string" + }, + "isLink": { + "type": "boolean", + "default": false, + "role": "content" + } + }, + "usesContext": [ "postId", "postType", "queryId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + } +} diff --git a/src/wp-includes/blocks/post-excerpt.php b/src/wp-includes/blocks/post-excerpt.php new file mode 100644 index 0000000000000..28aab46a01294 --- /dev/null +++ b/src/wp-includes/blocks/post-excerpt.php @@ -0,0 +1,103 @@ +context['postId'] ) ) { + return ''; + } + + $more_text = ! empty( $attributes['moreText'] ) ? '' . wp_kses_post( $attributes['moreText'] ) . '' : ''; + $filter_excerpt_more = static function ( $more ) use ( $more_text ) { + return empty( $more_text ) ? $more : ''; + }; + /** + * Some themes might use `excerpt_more` filter to handle the + * `more` link displayed after a trimmed excerpt. Since the + * block has a `more text` attribute we have to check and + * override if needed the return value from this filter. + * So if the block's attribute is not empty override the + * `excerpt_more` filter and return nothing. This will + * result in showing only one `read more` link at a time. + * + * This hook needs to be applied before the excerpt is retrieved with get_the_excerpt. + * Otherwise, the read more link filter from the theme is not removed. + */ + add_filter( 'excerpt_more', $filter_excerpt_more ); + + /* + * The purpose of the excerpt length setting is to limit the length of both + * automatically generated and user-created excerpts. + * Because the excerpt_length filter only applies to auto generated excerpts, + * wp_trim_words is used instead. + */ + $excerpt_length = $attributes['excerptLength']; + $excerpt = get_the_excerpt( $block->context['postId'] ); + if ( isset( $excerpt_length ) ) { + $excerpt = wp_trim_words( $excerpt, $excerpt_length ); + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + $content = '

      ' . $excerpt; + $show_more_on_new_line = ! isset( $attributes['showMoreOnNewLine'] ) || $attributes['showMoreOnNewLine']; + if ( $show_more_on_new_line && ! empty( $more_text ) ) { + $content .= '

      ' . $more_text . '

      '; + } else { + $content .= " $more_text

      "; + } + remove_filter( 'excerpt_more', $filter_excerpt_more ); + return sprintf( '
      %2$s
      ', $wrapper_attributes, $content ); +} + +/** + * Registers the `core/post-excerpt` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_excerpt() { + register_block_type_from_metadata( + __DIR__ . '/post-excerpt', + array( + 'render_callback' => 'render_block_core_post_excerpt', + ) + ); +} +add_action( 'init', 'register_block_core_post_excerpt' ); + +/** + * If themes or plugins filter the excerpt_length, we need to + * override the filter in the editor, otherwise + * the excerpt length block setting has no effect. + * Returns 100 because 100 is the max length in the setting. + */ +if ( is_admin() || + defined( 'REST_REQUEST' ) && REST_REQUEST ) { + add_filter( + 'excerpt_length', + static function () { + return 100; + }, + PHP_INT_MAX + ); +} diff --git a/src/wp-includes/blocks/post-excerpt/block.json b/src/wp-includes/blocks/post-excerpt/block.json new file mode 100644 index 0000000000000..c0037b0e5b39c --- /dev/null +++ b/src/wp-includes/blocks/post-excerpt/block.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-excerpt", + "title": "Excerpt", + "category": "theme", + "description": "Display the excerpt.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + }, + "moreText": { + "type": "string", + "role": "content" + }, + "showMoreOnNewLine": { + "type": "boolean", + "default": true + }, + "excerptLength": { + "type": "number", + "default": 55 + } + }, + "usesContext": [ "postId", "postType", "queryId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "editorStyle": "wp-block-post-excerpt-editor", + "style": "wp-block-post-excerpt" +} diff --git a/src/wp-includes/blocks/post-featured-image.php b/src/wp-includes/blocks/post-featured-image.php new file mode 100644 index 0000000000000..dc8bcba194a79 --- /dev/null +++ b/src/wp-includes/blocks/post-featured-image.php @@ -0,0 +1,269 @@ +context['postId'] ) ) { + return ''; + } + $post_ID = $block->context['postId']; + + $is_link = isset( $attributes['isLink'] ) && $attributes['isLink']; + $size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail'; + $attr = get_block_core_post_featured_image_border_attributes( $attributes ); + $overlay_markup = get_block_core_post_featured_image_overlay_element_markup( $attributes ); + + if ( $is_link ) { + $title = get_the_title( $post_ID ); + if ( $title ) { + $attr['alt'] = trim( strip_tags( $title ) ); + } else { + $attr['alt'] = sprintf( + // translators: %d is the post ID. + __( 'Untitled post %d' ), + $post_ID + ); + } + } + + $extra_styles = ''; + + // Aspect ratio with a height set needs to override the default width/height. + if ( ! empty( $attributes['aspectRatio'] ) ) { + $extra_styles .= 'width:100%;height:100%;'; + } elseif ( ! empty( $attributes['height'] ) ) { + $extra_styles .= "height:{$attributes['height']};"; + } + + if ( ! empty( $attributes['scale'] ) ) { + $extra_styles .= "object-fit:{$attributes['scale']};"; + } + if ( ! empty( $attributes['style']['shadow'] ) ) { + $shadow_styles = wp_style_engine_get_styles( array( 'shadow' => $attributes['style']['shadow'] ) ); + + if ( ! empty( $shadow_styles['css'] ) ) { + $extra_styles .= $shadow_styles['css']; + } + } + + if ( ! empty( $extra_styles ) ) { + $attr['style'] = empty( $attr['style'] ) ? $extra_styles : $attr['style'] . $extra_styles; + } + + $featured_image = get_the_post_thumbnail( $post_ID, $size_slug, $attr ); + + // Get the first image from the post. + if ( $attributes['useFirstImageFromPost'] && ! $featured_image ) { + $content_post = get_post( $post_ID ); + $content = $content_post->post_content; + $processor = new WP_HTML_Tag_Processor( $content ); + + /* + * Transfer the image tag from the post into a new text snippet. + * Because the HTML API doesn't currently expose a way to extract + * HTML substrings this is necessary as a workaround. Of note, this + * is different than directly extracting the IMG tag: + * - If there are duplicate attributes in the source there will only be one in the output. + * - If there are single-quoted or unquoted attributes they will be double-quoted in the output. + * - If there are named character references in the attribute values they may be replaced with their direct code points. E.g. `…` becomes `…`. + * In the future there will likely be a mechanism to copy snippets of HTML from + * one document into another, via the HTML Processor's `get_outer_html()` or + * equivalent. When that happens it would be appropriate to replace this custom + * code with that canonical code. + */ + if ( $processor->next_tag( 'img' ) ) { + $tag_html = new WP_HTML_Tag_Processor( '' ); + $tag_html->next_tag(); + foreach ( $processor->get_attribute_names_with_prefix( '' ) as $name ) { + $tag_html->set_attribute( $name, $processor->get_attribute( $name ) ); + } + $featured_image = $tag_html->get_updated_html(); + } + } + + if ( ! $featured_image ) { + return ''; + } + + if ( $is_link ) { + $link_target = $attributes['linkTarget']; + $rel = ! empty( $attributes['rel'] ) ? 'rel="' . esc_attr( $attributes['rel'] ) . '"' : ''; + $height = ! empty( $attributes['height'] ) ? 'style="' . esc_attr( safecss_filter_attr( 'height:' . $attributes['height'] ) ) . '"' : ''; + $featured_image = sprintf( + '%5$s%6$s', + get_the_permalink( $post_ID ), + esc_attr( $link_target ), + $rel, + $height, + $featured_image, + $overlay_markup + ); + } else { + $featured_image = $featured_image . $overlay_markup; + } + + $aspect_ratio = ! empty( $attributes['aspectRatio'] ) + ? esc_attr( safecss_filter_attr( 'aspect-ratio:' . $attributes['aspectRatio'] ) ) . ';' + : ''; + $width = ! empty( $attributes['width'] ) + ? esc_attr( safecss_filter_attr( 'width:' . $attributes['width'] ) ) . ';' + : ''; + $height = ! empty( $attributes['height'] ) + ? esc_attr( safecss_filter_attr( 'height:' . $attributes['height'] ) ) . ';' + : ''; + if ( ! $height && ! $width && ! $aspect_ratio ) { + $wrapper_attributes = get_block_wrapper_attributes(); + } else { + $wrapper_attributes = get_block_wrapper_attributes( array( 'style' => $aspect_ratio . $width . $height ) ); + } + return "
      {$featured_image}
      "; +} + +/** + * Generate markup for the HTML element that will be used for the overlay. + * + * @since 6.1.0 + * + * @param array $attributes Block attributes. + * + * @return string HTML markup in string format. + */ +function get_block_core_post_featured_image_overlay_element_markup( $attributes ) { + $has_dim_background = isset( $attributes['dimRatio'] ) && $attributes['dimRatio']; + $has_gradient = isset( $attributes['gradient'] ) && $attributes['gradient']; + $has_custom_gradient = isset( $attributes['customGradient'] ) && $attributes['customGradient']; + $has_solid_overlay = isset( $attributes['overlayColor'] ) && $attributes['overlayColor']; + $has_custom_overlay = isset( $attributes['customOverlayColor'] ) && $attributes['customOverlayColor']; + $class_names = array( 'wp-block-post-featured-image__overlay' ); + $styles = array(); + + if ( ! $has_dim_background ) { + return ''; + } + + // Apply border classes and styles. + $border_attributes = get_block_core_post_featured_image_border_attributes( $attributes ); + + if ( ! empty( $border_attributes['class'] ) ) { + $class_names[] = $border_attributes['class']; + } + + if ( ! empty( $border_attributes['style'] ) ) { + $styles[] = $border_attributes['style']; + } + + // Apply overlay and gradient classes. + if ( $has_dim_background ) { + $class_names[] = 'has-background-dim'; + $class_names[] = "has-background-dim-{$attributes['dimRatio']}"; + } + + if ( $has_solid_overlay ) { + $class_names[] = "has-{$attributes['overlayColor']}-background-color"; + } + + if ( $has_gradient || $has_custom_gradient ) { + $class_names[] = 'has-background-gradient'; + } + + if ( $has_gradient ) { + $class_names[] = "has-{$attributes['gradient']}-gradient-background"; + } + + // Apply background styles. + if ( $has_custom_gradient ) { + $styles[] = sprintf( 'background-image: %s;', $attributes['customGradient'] ); + } + + if ( $has_custom_overlay ) { + $styles[] = sprintf( 'background-color: %s;', $attributes['customOverlayColor'] ); + } + + return sprintf( + '', + esc_attr( implode( ' ', $class_names ) ), + esc_attr( safecss_filter_attr( implode( ' ', $styles ) ) ) + ); +} + +/** + * Generates class names and styles to apply the border support styles for + * the Post Featured Image block. + * + * @since 6.1.0 + * + * @param array $attributes The block attributes. + * @return array The border-related classnames and styles for the block. + */ +function get_block_core_post_featured_image_border_attributes( $attributes ) { + $border_styles = array(); + $sides = array( 'top', 'right', 'bottom', 'left' ); + + // Border radius. + if ( isset( $attributes['style']['border']['radius'] ) ) { + $border_styles['radius'] = $attributes['style']['border']['radius']; + } + + // Border style. + if ( isset( $attributes['style']['border']['style'] ) ) { + $border_styles['style'] = $attributes['style']['border']['style']; + } + + // Border width. + if ( isset( $attributes['style']['border']['width'] ) ) { + $border_styles['width'] = $attributes['style']['border']['width']; + } + + // Border color. + $preset_color = array_key_exists( 'borderColor', $attributes ) ? "var:preset|color|{$attributes['borderColor']}" : null; + $custom_color = $attributes['style']['border']['color'] ?? null; + $border_styles['color'] = $preset_color ? $preset_color : $custom_color; + + // Individual border styles e.g. top, left etc. + foreach ( $sides as $side ) { + $border = $attributes['style']['border'][ $side ] ?? null; + $border_styles[ $side ] = array( + 'color' => isset( $border['color'] ) ? $border['color'] : null, + 'style' => isset( $border['style'] ) ? $border['style'] : null, + 'width' => isset( $border['width'] ) ? $border['width'] : null, + ); + } + + $styles = wp_style_engine_get_styles( array( 'border' => $border_styles ) ); + $attributes = array(); + if ( ! empty( $styles['classnames'] ) ) { + $attributes['class'] = $styles['classnames']; + } + if ( ! empty( $styles['css'] ) ) { + $attributes['style'] = $styles['css']; + } + return $attributes; +} + +/** + * Registers the `core/post-featured-image` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_featured_image() { + register_block_type_from_metadata( + __DIR__ . '/post-featured-image', + array( + 'render_callback' => 'render_block_core_post_featured_image', + ) + ); +} +add_action( 'init', 'register_block_core_post_featured_image' ); diff --git a/src/wp-includes/blocks/post-featured-image/block.json b/src/wp-includes/blocks/post-featured-image/block.json new file mode 100644 index 0000000000000..3cd144caa0cf4 --- /dev/null +++ b/src/wp-includes/blocks/post-featured-image/block.json @@ -0,0 +1,108 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-featured-image", + "title": "Featured Image", + "category": "theme", + "description": "Display a post's featured image.", + "textdomain": "default", + "attributes": { + "isLink": { + "type": "boolean", + "default": false, + "role": "content" + }, + "aspectRatio": { + "type": "string" + }, + "width": { + "type": "string" + }, + "height": { + "type": "string" + }, + "scale": { + "type": "string", + "default": "cover" + }, + "sizeSlug": { + "type": "string" + }, + "rel": { + "type": "string", + "attribute": "rel", + "default": "", + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + }, + "overlayColor": { + "type": "string" + }, + "customOverlayColor": { + "type": "string" + }, + "dimRatio": { + "type": "number", + "default": 0 + }, + "gradient": { + "type": "string" + }, + "customGradient": { + "type": "string" + }, + "useFirstImageFromPost": { + "type": "boolean", + "default": false + } + }, + "usesContext": [ "postId", "postType", "queryId" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "align": [ "left", "right", "center", "wide", "full" ], + "color": { + "text": false, + "background": false + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "width": true, + "__experimentalSkipSerialization": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "width": true + } + }, + "filter": { + "duotone": true + }, + "shadow": { + "__experimentalSkipSerialization": true + }, + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "selectors": { + "border": ".wp-block-post-featured-image img, .wp-block-post-featured-image .block-editor-media-placeholder, .wp-block-post-featured-image .wp-block-post-featured-image__overlay", + "shadow": ".wp-block-post-featured-image img, .wp-block-post-featured-image .components-placeholder", + "filter": { + "duotone": ".wp-block-post-featured-image img, .wp-block-post-featured-image .wp-block-post-featured-image__placeholder, .wp-block-post-featured-image .components-placeholder__illustration, .wp-block-post-featured-image .components-placeholder::before" + } + }, + "editorStyle": "wp-block-post-featured-image-editor", + "style": "wp-block-post-featured-image" +} diff --git a/src/wp-includes/blocks/post-navigation-link.php b/src/wp-includes/blocks/post-navigation-link.php new file mode 100644 index 0000000000000..8162b74d8af17 --- /dev/null +++ b/src/wp-includes/blocks/post-navigation-link.php @@ -0,0 +1,139 @@ + $classes, + ) + ); + // Set default values. + $format = '%link'; + $link = 'next' === $navigation_type ? _x( 'Next', 'label for next post link' ) : _x( 'Previous', 'label for previous post link' ); + $label = ''; + + // Only use hardcoded values here, otherwise we need to add escaping where these values are used. + $arrow_map = array( + 'none' => '', + 'arrow' => array( + 'next' => '→', + 'previous' => '←', + ), + 'chevron' => array( + 'next' => 'Ā»', + 'previous' => 'Ā«', + ), + ); + + // If a custom label is provided, make this a link. + // `$label` is used to prepend the provided label, if we want to show the page title as well. + if ( isset( $attributes['label'] ) && ! empty( $attributes['label'] ) ) { + $label = "{$attributes['label']}"; + $link = $label; + } + + // If we want to also show the page title, make the page title a link and prepend the label. + if ( isset( $attributes['showTitle'] ) && $attributes['showTitle'] ) { + /* + * If the label link option is not enabled but there is a custom label, + * display the custom label as text before the linked title. + */ + if ( ! $attributes['linkLabel'] ) { + if ( $label ) { + $format = '' . wp_kses_post( $label ) . ' %link'; + } + $link = '%title'; + } elseif ( isset( $attributes['linkLabel'] ) && $attributes['linkLabel'] ) { + // If the label link option is enabled and there is a custom label, display it before the title. + if ( $label ) { + $link = '' . wp_kses_post( $label ) . ' %title'; + } else { + /* + * If the label link option is enabled and there is no custom label, + * add a colon between the label and the post title. + */ + $label = 'next' === $navigation_type ? _x( 'Next:', 'label before the title of the next post' ) : _x( 'Previous:', 'label before the title of the previous post' ); + $link = sprintf( + '%1$s %2$s', + wp_kses_post( $label ), + '%title' + ); + } + } + } + + // Display arrows. + if ( isset( $attributes['arrow'] ) && 'none' !== $attributes['arrow'] && isset( $arrow_map[ $attributes['arrow'] ] ) ) { + $arrow = $arrow_map[ $attributes['arrow'] ][ $navigation_type ]; + + if ( 'next' === $navigation_type ) { + $format = '%link'; + } else { + $format = '%link'; + } + } + + /* + * The dynamic portion of the function name, `$navigation_type`, + * Refers to the type of adjacency, 'next' or 'previous'. + * + * @see https://developer.wordpress.org/reference/functions/get_previous_post_link/ + * @see https://developer.wordpress.org/reference/functions/get_next_post_link/ + */ + $get_link_function = "get_{$navigation_type}_post_link"; + + if ( ! empty( $attributes['taxonomy'] ) ) { + $content = $get_link_function( $format, $link, true, '', $attributes['taxonomy'] ); + } else { + $content = $get_link_function( $format, $link ); + } + + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/post-navigation-link` block on the server. + * + * @since 5.9.0 + */ +function register_block_core_post_navigation_link() { + register_block_type_from_metadata( + __DIR__ . '/post-navigation-link', + array( + 'render_callback' => 'render_block_core_post_navigation_link', + ) + ); +} +add_action( 'init', 'register_block_core_post_navigation_link' ); diff --git a/src/wp-includes/blocks/post-navigation-link/block.json b/src/wp-includes/blocks/post-navigation-link/block.json new file mode 100644 index 0000000000000..2fda6a01cf516 --- /dev/null +++ b/src/wp-includes/blocks/post-navigation-link/block.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-navigation-link", + "title": "Post Navigation Link", + "category": "theme", + "description": "Displays the next or previous post link that is adjacent to the current post.", + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + }, + "type": { + "type": "string", + "default": "next" + }, + "label": { + "type": "string", + "role": "content" + }, + "showTitle": { + "type": "boolean", + "default": false + }, + "linkLabel": { + "type": "boolean", + "default": false + }, + "arrow": { + "type": "string", + "default": "none" + }, + "taxonomy": { + "type": "string", + "default": "" + } + }, + "usesContext": [ "postType" ], + "supports": { + "reusable": false, + "html": false, + "color": { + "link": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalWritingMode": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-post-navigation-link" +} diff --git a/src/wp-includes/blocks/post-template.php b/src/wp-includes/blocks/post-template.php new file mode 100644 index 0000000000000..9126355c096a5 --- /dev/null +++ b/src/wp-includes/blocks/post-template.php @@ -0,0 +1,162 @@ +name ) { + return true; + } + if ( + 'core/cover' === $block->name && + ! empty( $block->attributes['useFeaturedImage'] ) + ) { + return true; + } + if ( $block->inner_blocks && block_core_post_template_uses_featured_image( $block->inner_blocks ) ) { + return true; + } + } + + return false; +} + +/** + * Renders the `core/post-template` block on the server. + * + * @since 6.3.0 Changed render_block_context priority to `1`. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the output of the query, structured using the layout defined by the block's inner blocks. + */ +function render_block_core_post_template( $attributes, $content, $block ) { + $page_key = isset( $block->context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $enhanced_pagination = isset( $block->context['enhancedPagination'] ) && $block->context['enhancedPagination']; + $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; + + // Use global query if needed. + $use_global_query = ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ); + if ( $use_global_query ) { + global $wp_query; + + /* + * If already in the main query loop, duplicate the query instance to not tamper with the main instance. + * Since this is a nested query, it should start at the beginning, therefore rewind posts. + * Otherwise, the main query loop has not started yet and this block is responsible for doing so. + */ + if ( in_the_loop() ) { + $query = clone $wp_query; + $query->rewind_posts(); + } else { + $query = $wp_query; + } + } else { + $query_args = build_query_vars_from_query_block( $block, $page ); + $query = new WP_Query( $query_args ); + } + + if ( ! $query->have_posts() ) { + return ''; + } + + if ( block_core_post_template_uses_featured_image( $block->inner_blocks ) ) { + update_post_thumbnail_cache( $query ); + } + + $classnames = ''; + if ( isset( $block->context['displayLayout'] ) && isset( $block->context['query'] ) ) { + if ( isset( $block->context['displayLayout']['type'] ) && 'flex' === $block->context['displayLayout']['type'] ) { + $classnames = "is-flex-container columns-{$block->context['displayLayout']['columns']}"; + } + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classnames .= ' has-link-color'; + } + + // Ensure backwards compatibility by flagging the number of columns via classname when using grid layout. + if ( isset( $attributes['layout']['type'] ) && 'grid' === $attributes['layout']['type'] && ! empty( $attributes['layout']['columnCount'] ) ) { + $classnames .= ' ' . sanitize_title( 'columns-' . $attributes['layout']['columnCount'] ); + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( $classnames ) ) ); + + $content = ''; + while ( $query->have_posts() ) { + $query->the_post(); + + // Get an instance of the current Post Template block. + $block_instance = $block->parsed_block; + + // Set the block name to one that does not correspond to an existing registered block. + // This ensures that for the inner instances of the Post Template block, we do not render any block supports. + $block_instance['blockName'] = 'core/null'; + + $post_id = get_the_ID(); + $post_type = get_post_type(); + $filter_block_context = static function ( $context ) use ( $post_id, $post_type ) { + $context['postType'] = $post_type; + $context['postId'] = $post_id; + return $context; + }; + + // Use an early priority to so that other 'render_block_context' filters have access to the values. + add_filter( 'render_block_context', $filter_block_context, 1 ); + // Render the inner blocks of the Post Template block with `dynamic` set to `false` to prevent calling + // `render_callback` and ensure that no wrapper markup is included. + $block_content = ( new WP_Block( $block_instance ) )->render( array( 'dynamic' => false ) ); + remove_filter( 'render_block_context', $filter_block_context, 1 ); + + // Wrap the render inner blocks in a `li` element with the appropriate post classes. + $post_classes = implode( ' ', get_post_class( 'wp-block-post' ) ); + + $inner_block_directives = $enhanced_pagination ? ' data-wp-key="post-template-item-' . $post_id . '"' : ''; + + $content .= '' . $block_content . ''; + } + + /* + * Use this function to restore the context of the template tags + * from a secondary query loop back to the main query loop. + * Since we use two custom loops, it's safest to always restore. + */ + wp_reset_postdata(); + + return sprintf( + '
        %2$s
      ', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/post-template` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_template() { + register_block_type_from_metadata( + __DIR__ . '/post-template', + array( + 'render_callback' => 'render_block_core_post_template', + 'skip_inner_blocks' => true, + ) + ); +} +add_action( 'init', 'register_block_core_post_template' ); diff --git a/src/wp-includes/blocks/post-template/block.json b/src/wp-includes/blocks/post-template/block.json new file mode 100644 index 0000000000000..d379a46d3142f --- /dev/null +++ b/src/wp-includes/blocks/post-template/block.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-template", + "title": "Post Template", + "category": "theme", + "ancestor": [ "core/query" ], + "description": "Contains the block elements used to render a post, like the title, date, featured image, content or excerpt, and more.", + "textdomain": "default", + "usesContext": [ + "queryId", + "query", + "displayLayout", + "templateSlug", + "previewPostType", + "enhancedPagination", + "postType" + ], + "supports": { + "reusable": false, + "html": false, + "align": [ "wide", "full" ], + "layout": true, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "blockGap": { + "__experimentalDefault": "1.25em" + }, + "__experimentalDefaultControls": { + "blockGap": true, + "padding": false, + "margin": false + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "style": "wp-block-post-template", + "editorStyle": "wp-block-post-template-editor" +} diff --git a/src/wp-includes/blocks/post-terms.php b/src/wp-includes/blocks/post-terms.php new file mode 100644 index 0000000000000..3e7a05f10117e --- /dev/null +++ b/src/wp-includes/blocks/post-terms.php @@ -0,0 +1,130 @@ +context['postId'] ) || ! isset( $attributes['term'] ) ) { + return ''; + } + + if ( ! is_taxonomy_viewable( $attributes['term'] ) ) { + return ''; + } + + $classes = array( 'taxonomy-' . $attributes['term'] ); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + + $separator = empty( $attributes['separator'] ) ? ' ' : $attributes['separator']; + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + $prefix = "
      "; + if ( isset( $attributes['prefix'] ) && $attributes['prefix'] ) { + $prefix .= '' . $attributes['prefix'] . ''; + } + + $suffix = '
      '; + if ( isset( $attributes['suffix'] ) && $attributes['suffix'] ) { + $suffix = '' . $attributes['suffix'] . '' . $suffix; + } + + $post_terms = get_the_term_list( + $block->context['postId'], + $attributes['term'], + wp_kses_post( $prefix ), + '' . esc_html( $separator ) . '', + wp_kses_post( $suffix ) + ); + + if ( is_wp_error( $post_terms ) || empty( $post_terms ) ) { + return ''; + } + + return $post_terms; +} + +/** + * Returns the available variations for the `core/post-terms` block. + * + * @since 6.5.0 + * + * @return array The available variations for the block. + */ +function block_core_post_terms_build_variations() { + $taxonomies = get_taxonomies( + array( + 'publicly_queryable' => true, + 'show_in_rest' => true, + ), + 'objects' + ); + + // Split the available taxonomies to `built_in` and custom ones, + // in order to prioritize the `built_in` taxonomies at the + // search results. + $built_ins = array(); + $custom_variations = array(); + + // Create and register the eligible taxonomies variations. + foreach ( $taxonomies as $taxonomy ) { + $variation = array( + 'name' => $taxonomy->name, + 'title' => $taxonomy->label, + 'description' => sprintf( + /* translators: %s: taxonomy's label */ + __( 'Display a list of assigned terms from the taxonomy: %s' ), + $taxonomy->label + ), + 'attributes' => array( + 'term' => $taxonomy->name, + ), + 'isActive' => array( 'term' ), + 'scope' => array( 'inserter', 'transform' ), + ); + // Set the category variation as the default one. + if ( 'category' === $taxonomy->name ) { + $variation['isDefault'] = true; + } + if ( $taxonomy->_builtin ) { + $built_ins[] = $variation; + } else { + $custom_variations[] = $variation; + } + } + + return array_merge( $built_ins, $custom_variations ); +} + +/** + * Registers the `core/post-terms` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_terms() { + register_block_type_from_metadata( + __DIR__ . '/post-terms', + array( + 'render_callback' => 'render_block_core_post_terms', + 'variation_callback' => 'block_core_post_terms_build_variations', + ) + ); +} +add_action( 'init', 'register_block_core_post_terms' ); diff --git a/src/wp-includes/blocks/post-terms/block.json b/src/wp-includes/blocks/post-terms/block.json new file mode 100644 index 0000000000000..e7567ba657c3b --- /dev/null +++ b/src/wp-includes/blocks/post-terms/block.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-terms", + "title": "Post Terms", + "category": "theme", + "description": "Post terms.", + "textdomain": "default", + "attributes": { + "term": { + "type": "string" + }, + "textAlign": { + "type": "string" + }, + "separator": { + "type": "string", + "default": ", " + }, + "prefix": { + "type": "string", + "default": "", + "role": "content" + }, + "suffix": { + "type": "string", + "default": "", + "role": "content" + } + }, + "usesContext": [ "postId", "postType" ], + "example": { + "viewportWidth": 350 + }, + "supports": { + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-terms" +} diff --git a/src/wp-includes/blocks/post-time-to-read.php b/src/wp-includes/blocks/post-time-to-read.php new file mode 100644 index 0000000000000..bce545a2927d2 --- /dev/null +++ b/src/wp-includes/blocks/post-time-to-read.php @@ -0,0 +1,185 @@ + '/<\/?[a-z][^>]*?>/i', + 'html_comment_regexp' => '//', + 'space_regexp' => '/ | /i', + 'html_entity_regexp' => '/&\S+?;/', + 'connector_regexp' => "/--|\x{2014}/u", + 'remove_regexp' => "/[\x{0021}-\x{0040}\x{005B}-\x{0060}\x{007B}-\x{007E}\x{0080}-\x{00BF}\x{00D7}\x{00F7}\x{2000}-\x{2BFF}\x{2E00}-\x{2E7F}]/u", + 'astral_regexp' => "/[\x{010000}-\x{10FFFF}]/u", + 'words_regexp' => '/\S\s+/u', + 'characters_excluding_spaces_regexp' => '/\S/u', + 'characters_including_spaces_regexp' => "/[^\f\n\r\t\v\x{00AD}\x{2028}\x{2029}]/u", + ); + + $count = 0; + + if ( '' === trim( $text ) ) { + return $count; + } + + // Sanitize type to one of three possibilities: 'words', 'characters_excluding_spaces' or 'characters_including_spaces'. + if ( 'characters_excluding_spaces' !== $type && 'characters_including_spaces' !== $type ) { + $type = 'words'; + } + + $text .= "\n"; + + // Replace all HTML with a new-line. + $text = preg_replace( $settings['html_regexp'], "\n", $text ); + + // Remove all HTML comments. + $text = preg_replace( $settings['html_comment_regexp'], '', $text ); + + // If a shortcode regular expression has been provided use it to remove shortcodes. + if ( ! empty( $settings['shortcodes_regexp'] ) ) { + $text = preg_replace( $settings['shortcodes_regexp'], "\n", $text ); + } + + // Normalize non-breaking space to a normal space. + $text = preg_replace( $settings['space_regexp'], ' ', $text ); + + if ( 'words' === $type ) { + // Remove HTML Entities. + $text = preg_replace( $settings['html_entity_regexp'], '', $text ); + + // Convert connectors to spaces to count attached text as words. + $text = preg_replace( $settings['connector_regexp'], ' ', $text ); + + // Remove unwanted characters. + $text = preg_replace( $settings['remove_regexp'], '', $text ); + } else { + // Convert HTML Entities to "a". + $text = preg_replace( $settings['html_entity_regexp'], 'a', $text ); + + // Remove surrogate points. + $text = preg_replace( $settings['astral_regexp'], 'a', $text ); + } + + // Match with the selected type regular expression to count the items. + return (int) preg_match_all( $settings[ $type . '_regexp' ], $text ); +} + +/** + * Renders the `core/post-time-to-read` block on the server. + * + * @since 6.9.0 + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the rendered post author name block. + */ +function render_block_core_post_time_to_read( $attributes, $content, $block ) { + if ( ! isset( $block->context['postId'] ) ) { + return ''; + } + + $content = get_the_content(); + $average_reading_rate = isset( $attributes['averageReadingSpeed'] ) ? $attributes['averageReadingSpeed'] : 189; + + $display_mode = isset( $attributes['displayMode'] ) ? $attributes['displayMode'] : 'time'; + + $word_count_type = wp_get_word_count_type(); + $total_words = block_core_post_time_to_read_word_count( $content, $word_count_type ); + + $parts = array(); + + // Add "time to read" part, if enabled. + if ( 'time' === $display_mode ) { + if ( ! empty( $attributes['displayAsRange'] ) ) { + // Calculate faster reading rate with 20% speed = lower minutes, + // and slower reading rate with 20% speed = higher minutes. + $min_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 0.8 ) ); + $max_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 1.2 ) ); + if ( $min_minutes === $max_minutes ) { + $max_minutes = $min_minutes + 1; + } + /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */ + $time_string = sprintf( + /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */ + _x( '%1$s–%2$s minutes', 'Range of minutes to read' ), + $min_minutes, + $max_minutes + ); + } else { + $minutes_to_read = max( 1, (int) round( $total_words / $average_reading_rate ) ); + $time_string = sprintf( + /* translators: %s: the number of minutes to read the post. */ + _n( '%s minute', '%s minutes', $minutes_to_read ), + $minutes_to_read + ); + } + $parts[] = $time_string; + } + + // Add "word count" part, if enabled. + if ( 'words' === $display_mode ) { + $word_count_string = 'words' === $word_count_type ? sprintf( + /* translators: %s: the number of words in the post. */ + _n( '%s word', '%s words', $total_words ), + number_format_i18n( $total_words ) + ) : sprintf( + /* translators: %s: the number of characters in the post. */ + _n( '%s character', '%s characters', $total_words ), + number_format_i18n( $total_words ) + ); + $parts[] = $word_count_string; + } + + $display_string = implode( '
      ', $parts ); + + $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}"; + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $align_class_name ) ); + + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $display_string + ); +} + + +/** + * Registers the `core/post-time-to-read` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_post_time_to_read() { + register_block_type_from_metadata( + __DIR__ . '/post-time-to-read', + array( + 'render_callback' => 'render_block_core_post_time_to_read', + ) + ); +} + +add_action( 'init', 'register_block_core_post_time_to_read' ); diff --git a/src/wp-includes/blocks/post-time-to-read/block.json b/src/wp-includes/blocks/post-time-to-read/block.json new file mode 100644 index 0000000000000..386312e00434e --- /dev/null +++ b/src/wp-includes/blocks/post-time-to-read/block.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-time-to-read", + "title": "Time to Read", + "category": "theme", + "description": "Show minutes required to finish reading the post. Can also show a word count.", + "textdomain": "default", + "usesContext": [ "postId", "postType" ], + "attributes": { + "textAlign": { + "type": "string" + }, + "displayAsRange": { + "type": "boolean", + "default": true + }, + "displayMode": { + "type": "string", + "default": "time" + }, + "averageReadingSpeed": { + "type": "number", + "default": 189 + } + }, + "supports": { + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "html": false, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } +} diff --git a/src/wp-includes/blocks/post-title.php b/src/wp-includes/blocks/post-title.php new file mode 100644 index 0000000000000..ed27f2e4158eb --- /dev/null +++ b/src/wp-includes/blocks/post-title.php @@ -0,0 +1,74 @@ +context['postId'] ) ) { + return ''; + } + + /** + * The `$post` argument is intentionally omitted so that changes are reflected when previewing a post. + * See: https://github.com/WordPress/gutenberg/pull/37622#issuecomment-1000932816. + */ + $title = get_the_title(); + + if ( ! $title ) { + return ''; + } + + $tag_name = 'h2'; + if ( isset( $attributes['level'] ) ) { + $tag_name = 0 === $attributes['level'] ? 'p' : 'h' . (int) $attributes['level']; + } + + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] ) { + $rel = ! empty( $attributes['rel'] ) ? 'rel="' . esc_attr( $attributes['rel'] ) . '"' : ''; + $title = sprintf( '%4$s', esc_url( get_the_permalink( $block->context['postId'] ) ), esc_attr( $attributes['linkTarget'] ), $rel, $title ); + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + $title + ); +} + +/** + * Registers the `core/post-title` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_post_title() { + register_block_type_from_metadata( + __DIR__ . '/post-title', + array( + 'render_callback' => 'render_block_core_post_title', + ) + ); +} +add_action( 'init', 'register_block_core_post_title' ); diff --git a/src/wp-includes/blocks/post-title/block.json b/src/wp-includes/blocks/post-title/block.json new file mode 100644 index 0000000000000..5587d71b148d0 --- /dev/null +++ b/src/wp-includes/blocks/post-title/block.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/post-title", + "title": "Title", + "category": "theme", + "description": "Displays the title of a post, page, or any other content-type.", + "textdomain": "default", + "usesContext": [ "postId", "postType", "queryId" ], + "attributes": { + "textAlign": { + "type": "string" + }, + "level": { + "type": "number", + "default": 2 + }, + "levelOptions": { + "type": "array" + }, + "isLink": { + "type": "boolean", + "default": false, + "role": "content" + }, + "rel": { + "type": "string", + "attribute": "rel", + "default": "", + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + } + }, + "example": { + "viewportWidth": 350 + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-post-title" +} diff --git a/src/wp-includes/blocks/preformatted/block.json b/src/wp-includes/blocks/preformatted/block.json new file mode 100644 index 0000000000000..c25b8ce37093a --- /dev/null +++ b/src/wp-includes/blocks/preformatted/block.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/preformatted", + "title": "Preformatted", + "category": "text", + "description": "Add text that respects your spacing and tabs, and also allows styling.", + "textdomain": "default", + "attributes": { + "content": { + "type": "rich-text", + "source": "rich-text", + "selector": "pre", + "__unstablePreserveWhiteSpace": true, + "role": "content" + } + }, + "supports": { + "anchor": true, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "padding": true, + "margin": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-preformatted" +} diff --git a/src/wp-includes/blocks/pullquote/block.json b/src/wp-includes/blocks/pullquote/block.json new file mode 100644 index 0000000000000..271bba74d0252 --- /dev/null +++ b/src/wp-includes/blocks/pullquote/block.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/pullquote", + "title": "Pullquote", + "category": "text", + "description": "Give special visual emphasis to a quote from your text.", + "textdomain": "default", + "attributes": { + "value": { + "type": "rich-text", + "source": "rich-text", + "selector": "p", + "role": "content" + }, + "citation": { + "type": "rich-text", + "source": "rich-text", + "selector": "cite", + "role": "content" + }, + "textAlign": { + "type": "string" + } + }, + "supports": { + "anchor": true, + "align": [ "left", "right", "wide", "full" ], + "background": { + "backgroundImage": true, + "backgroundSize": true, + "__experimentalDefaultControls": { + "backgroundImage": true + } + }, + "color": { + "gradients": true, + "background": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "dimensions": { + "minHeight": true, + "__experimentalDefaultControls": { + "minHeight": false + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "__experimentalStyle": { + "typography": { + "fontSize": "1.5em", + "lineHeight": "1.6" + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-pullquote-editor", + "style": "wp-block-pullquote" +} diff --git a/src/wp-includes/blocks/query-no-results.php b/src/wp-includes/blocks/query-no-results.php new file mode 100644 index 0000000000000..34d6b321cbd6b --- /dev/null +++ b/src/wp-includes/blocks/query-no-results.php @@ -0,0 +1,65 @@ +context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; + + // Override the custom query with the global query if needed. + $use_global_query = ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ); + if ( $use_global_query ) { + global $wp_query; + $query = $wp_query; + } else { + $query_args = build_query_vars_from_query_block( $block, $page ); + $query = new WP_Query( $query_args ); + } + + if ( $query->post_count > 0 ) { + return ''; + } + + $classes = ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) ? 'has-link-color' : ''; + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) ); + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/query-no-results` block on the server. + * + * @since 6.0.0 + */ +function register_block_core_query_no_results() { + register_block_type_from_metadata( + __DIR__ . '/query-no-results', + array( + 'render_callback' => 'render_block_core_query_no_results', + ) + ); +} +add_action( 'init', 'register_block_core_query_no_results' ); diff --git a/src/wp-includes/blocks/query-no-results/block.json b/src/wp-includes/blocks/query-no-results/block.json new file mode 100644 index 0000000000000..44d2ceef987e2 --- /dev/null +++ b/src/wp-includes/blocks/query-no-results/block.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-no-results", + "title": "No Results", + "category": "theme", + "description": "Contains the block elements used to render content when no query results are found.", + "ancestor": [ "core/query" ], + "textdomain": "default", + "usesContext": [ "queryId", "query" ], + "supports": { + "align": true, + "reusable": false, + "html": false, + "color": { + "gradients": true, + "link": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + } +} diff --git a/src/wp-includes/blocks/query-pagination-next.php b/src/wp-includes/blocks/query-pagination-next.php new file mode 100644 index 0000000000000..d574f94093846 --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-next.php @@ -0,0 +1,102 @@ +context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $enhanced_pagination = isset( $block->context['enhancedPagination'] ) && $block->context['enhancedPagination']; + $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; + $max_page = isset( $block->context['query']['pages'] ) ? (int) $block->context['query']['pages'] : 0; + + $wrapper_attributes = get_block_wrapper_attributes(); + $show_label = isset( $block->context['showLabel'] ) ? (bool) $block->context['showLabel'] : true; + $default_label = __( 'Next Page' ); + $label_text = isset( $attributes['label'] ) && ! empty( $attributes['label'] ) ? esc_html( $attributes['label'] ) : $default_label; + $label = $show_label ? $label_text : ''; + $pagination_arrow = get_query_pagination_arrow( $block, true ); + + if ( ! $label ) { + $wrapper_attributes .= ' aria-label="' . $label_text . '"'; + } + if ( $pagination_arrow ) { + $label .= $pagination_arrow; + } + $content = ''; + + // Check if the pagination is for Query that inherits the global context. + if ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ) { + $filter_link_attributes = static function () use ( $wrapper_attributes ) { + return $wrapper_attributes; + }; + add_filter( 'next_posts_link_attributes', $filter_link_attributes ); + // Take into account if we have set a bigger `max page` + // than what the query has. + global $wp_query; + if ( $max_page > $wp_query->max_num_pages ) { + $max_page = $wp_query->max_num_pages; + } + $content = get_next_posts_link( $label, $max_page ); + remove_filter( 'next_posts_link_attributes', $filter_link_attributes ); + } elseif ( ! $max_page || $max_page > $page ) { + $custom_query = new WP_Query( build_query_vars_from_query_block( $block, $page ) ); + $custom_query_max_pages = (int) $custom_query->max_num_pages; + if ( $custom_query_max_pages && $custom_query_max_pages !== $page ) { + $content = sprintf( + '%3$s', + esc_url( add_query_arg( $page_key, $page + 1 ) ), + $wrapper_attributes, + $label + ); + } + wp_reset_postdata(); // Restore original Post Data. + } + + if ( $enhanced_pagination && isset( $content ) ) { + $p = new WP_HTML_Tag_Processor( $content ); + if ( $p->next_tag( + array( + 'tag_name' => 'a', + 'class_name' => 'wp-block-query-pagination-next', + ) + ) ) { + $p->set_attribute( 'data-wp-key', 'query-pagination-next' ); + $p->set_attribute( 'data-wp-on--click', 'core/query::actions.navigate' ); + $p->set_attribute( 'data-wp-on--mouseenter', 'core/query::actions.prefetch' ); + $p->set_attribute( 'data-wp-watch', 'core/query::callbacks.prefetch' ); + $content = $p->get_updated_html(); + } + } + + return $content; +} + +/** + * Registers the `core/query-pagination-next` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query_pagination_next() { + register_block_type_from_metadata( + __DIR__ . '/query-pagination-next', + array( + 'render_callback' => 'render_block_core_query_pagination_next', + ) + ); +} +add_action( 'init', 'register_block_core_query_pagination_next' ); diff --git a/src/wp-includes/blocks/query-pagination-next/block.json b/src/wp-includes/blocks/query-pagination-next/block.json new file mode 100644 index 0000000000000..ec56125ee3b76 --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-next/block.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-pagination-next", + "title": "Next Page", + "category": "theme", + "parent": [ "core/query-pagination" ], + "description": "Displays the next posts page link.", + "textdomain": "default", + "attributes": { + "label": { + "type": "string" + } + }, + "usesContext": [ + "queryId", + "query", + "paginationArrow", + "showLabel", + "enhancedPagination" + ], + "supports": { + "reusable": false, + "html": false, + "color": { + "gradients": true, + "text": false, + "__experimentalDefaultControls": { + "background": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + } +} diff --git a/src/wp-includes/blocks/query-pagination-numbers.php b/src/wp-includes/blocks/query-pagination-numbers.php new file mode 100644 index 0000000000000..fddf28660fe4f --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-numbers.php @@ -0,0 +1,133 @@ +context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $enhanced_pagination = isset( $block->context['enhancedPagination'] ) && $block->context['enhancedPagination']; + $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; + $max_page = isset( $block->context['query']['pages'] ) ? (int) $block->context['query']['pages'] : 0; + + $wrapper_attributes = get_block_wrapper_attributes(); + $content = ''; + global $wp_query; + $mid_size = isset( $block->attributes['midSize'] ) ? (int) $block->attributes['midSize'] : null; + if ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ) { + // Take into account if we have set a bigger `max page` + // than what the query has. + $total = ! $max_page || $max_page > $wp_query->max_num_pages ? $wp_query->max_num_pages : $max_page; + $paginate_args = array( + 'prev_next' => false, + 'total' => $total, + ); + if ( null !== $mid_size ) { + $paginate_args['mid_size'] = $mid_size; + } + $content = paginate_links( $paginate_args ); + } else { + $block_query = new WP_Query( build_query_vars_from_query_block( $block, $page ) ); + // `paginate_links` works with the global $wp_query, so we have to + // temporarily switch it with our custom query. + $prev_wp_query = $wp_query; + $wp_query = $block_query; + $total = ! $max_page || $max_page > $wp_query->max_num_pages ? $wp_query->max_num_pages : $max_page; + $paginate_args = array( + 'base' => '%_%', + 'format' => "?$page_key=%#%", + 'current' => max( 1, $page ), + 'total' => $total, + 'prev_next' => false, + ); + if ( null !== $mid_size ) { + $paginate_args['mid_size'] = $mid_size; + } + if ( 1 !== $page ) { + /** + * `paginate_links` doesn't use the provided `format` when the page is `1`. + * This is great for the main query as it removes the extra query params + * making the URL shorter, but in the case of multiple custom queries is + * problematic. It results in returning an empty link which ends up with + * a link to the current page. + * + * A way to address this is to add a `fake` query arg with no value that + * is the same for all custom queries. This way the link is not empty and + * preserves all the other existent query args. + * + * @see https://developer.wordpress.org/reference/functions/paginate_links/ + * + * The proper fix of this should be in core. Track Ticket: + * @see https://core.trac.wordpress.org/ticket/53868 + * + * TODO: After two WP versions (starting from the WP version the core patch landed), + * we should remove this and call `paginate_links` with the proper new arg. + */ + $paginate_args['add_args'] = array( 'cst' => '' ); + } + // We still need to preserve `paged` query param if exists, as is used + // for Queries that inherit from global context. + $paged = empty( $_GET['paged'] ) ? null : (int) $_GET['paged']; + if ( $paged ) { + $paginate_args['add_args'] = array( 'paged' => $paged ); + } + $content = paginate_links( $paginate_args ); + wp_reset_postdata(); // Restore original Post Data. + $wp_query = $prev_wp_query; + } + + if ( empty( $content ) ) { + return ''; + } + + if ( $enhanced_pagination ) { + $p = new WP_HTML_Tag_Processor( $content ); + $tag_index = 0; + while ( $p->next_tag( + array( 'class_name' => 'page-numbers' ) + ) ) { + if ( null === $p->get_attribute( 'data-wp-key' ) ) { + $p->set_attribute( 'data-wp-key', 'index-' . $tag_index++ ); + } + if ( 'A' === $p->get_tag() ) { + $p->set_attribute( 'data-wp-on--click', 'core/query::actions.navigate' ); + } + } + $content = $p->get_updated_html(); + } + + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/query-pagination-numbers` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query_pagination_numbers() { + register_block_type_from_metadata( + __DIR__ . '/query-pagination-numbers', + array( + 'render_callback' => 'render_block_core_query_pagination_numbers', + ) + ); +} +add_action( 'init', 'register_block_core_query_pagination_numbers' ); diff --git a/src/wp-includes/blocks/query-pagination-numbers/block.json b/src/wp-includes/blocks/query-pagination-numbers/block.json new file mode 100644 index 0000000000000..8a9f0ee69f14e --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-numbers/block.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-pagination-numbers", + "title": "Page Numbers", + "category": "theme", + "parent": [ "core/query-pagination" ], + "description": "Displays a list of page numbers for pagination.", + "textdomain": "default", + "attributes": { + "midSize": { + "type": "number", + "default": 2 + } + }, + "usesContext": [ "queryId", "query", "enhancedPagination" ], + "supports": { + "reusable": false, + "html": false, + "color": { + "gradients": true, + "text": false, + "__experimentalDefaultControls": { + "background": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-query-pagination-numbers-editor" +} diff --git a/src/wp-includes/blocks/query-pagination-previous.php b/src/wp-includes/blocks/query-pagination-previous.php new file mode 100644 index 0000000000000..ec3de8921d519 --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-previous.php @@ -0,0 +1,95 @@ +context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $enhanced_pagination = isset( $block->context['enhancedPagination'] ) && $block->context['enhancedPagination']; + $max_page = isset( $block->context['query']['pages'] ) ? (int) $block->context['query']['pages'] : 0; + $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; + $wrapper_attributes = get_block_wrapper_attributes(); + $show_label = isset( $block->context['showLabel'] ) ? (bool) $block->context['showLabel'] : true; + $default_label = __( 'Previous Page' ); + $label_text = isset( $attributes['label'] ) && ! empty( $attributes['label'] ) ? esc_html( $attributes['label'] ) : $default_label; + $label = $show_label ? $label_text : ''; + $pagination_arrow = get_query_pagination_arrow( $block, false ); + if ( ! $label ) { + $wrapper_attributes .= ' aria-label="' . $label_text . '"'; + } + if ( $pagination_arrow ) { + $label = $pagination_arrow . $label; + } + $content = ''; + // Check if the pagination is for Query that inherits the global context + // and handle appropriately. + if ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ) { + $filter_link_attributes = static function () use ( $wrapper_attributes ) { + return $wrapper_attributes; + }; + + add_filter( 'previous_posts_link_attributes', $filter_link_attributes ); + $content = get_previous_posts_link( $label ); + remove_filter( 'previous_posts_link_attributes', $filter_link_attributes ); + } else { + $block_query = new WP_Query( build_query_vars_from_query_block( $block, $page ) ); + $block_max_pages = $block_query->max_num_pages; + $total = ! $max_page || $max_page > $block_max_pages ? $block_max_pages : $max_page; + wp_reset_postdata(); + + if ( 1 < $page && $page <= $total ) { + $content = sprintf( + '%3$s', + esc_url( add_query_arg( $page_key, $page - 1 ) ), + $wrapper_attributes, + $label + ); + } + } + + if ( $enhanced_pagination && isset( $content ) ) { + $p = new WP_HTML_Tag_Processor( $content ); + if ( $p->next_tag( + array( + 'tag_name' => 'a', + 'class_name' => 'wp-block-query-pagination-previous', + ) + ) ) { + $p->set_attribute( 'data-wp-key', 'query-pagination-previous' ); + $p->set_attribute( 'data-wp-on--click', 'core/query::actions.navigate' ); + $p->set_attribute( 'data-wp-on--mouseenter', 'core/query::actions.prefetch' ); + $p->set_attribute( 'data-wp-watch', 'core/query::callbacks.prefetch' ); + $content = $p->get_updated_html(); + } + } + + return $content; +} + +/** + * Registers the `core/query-pagination-previous` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query_pagination_previous() { + register_block_type_from_metadata( + __DIR__ . '/query-pagination-previous', + array( + 'render_callback' => 'render_block_core_query_pagination_previous', + ) + ); +} +add_action( 'init', 'register_block_core_query_pagination_previous' ); diff --git a/src/wp-includes/blocks/query-pagination-previous/block.json b/src/wp-includes/blocks/query-pagination-previous/block.json new file mode 100644 index 0000000000000..d1e34c8630250 --- /dev/null +++ b/src/wp-includes/blocks/query-pagination-previous/block.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-pagination-previous", + "title": "Previous Page", + "category": "theme", + "parent": [ "core/query-pagination" ], + "description": "Displays the previous posts page link.", + "textdomain": "default", + "attributes": { + "label": { + "type": "string" + } + }, + "usesContext": [ + "queryId", + "query", + "paginationArrow", + "showLabel", + "enhancedPagination" + ], + "supports": { + "reusable": false, + "html": false, + "color": { + "gradients": true, + "text": false, + "__experimentalDefaultControls": { + "background": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + } +} diff --git a/src/wp-includes/blocks/query-pagination.php b/src/wp-includes/blocks/query-pagination.php new file mode 100644 index 0000000000000..acafe968c0bec --- /dev/null +++ b/src/wp-includes/blocks/query-pagination.php @@ -0,0 +1,51 @@ + __( 'Pagination' ), + 'class' => $classes, + ) + ); + + return sprintf( + '', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/query-pagination` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query_pagination() { + register_block_type_from_metadata( + __DIR__ . '/query-pagination', + array( + 'render_callback' => 'render_block_core_query_pagination', + ) + ); +} +add_action( 'init', 'register_block_core_query_pagination' ); diff --git a/src/wp-includes/blocks/query-pagination/block.json b/src/wp-includes/blocks/query-pagination/block.json new file mode 100644 index 0000000000000..355b188e442d8 --- /dev/null +++ b/src/wp-includes/blocks/query-pagination/block.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-pagination", + "title": "Pagination", + "category": "theme", + "ancestor": [ "core/query" ], + "allowedBlocks": [ + "core/query-pagination-previous", + "core/query-pagination-numbers", + "core/query-pagination-next" + ], + "description": "Displays a paginated navigation to next/previous set of posts, when applicable.", + "textdomain": "default", + "attributes": { + "paginationArrow": { + "type": "string", + "default": "none" + }, + "showLabel": { + "type": "boolean", + "default": true + } + }, + "usesContext": [ "queryId", "query" ], + "providesContext": { + "paginationArrow": "paginationArrow", + "showLabel": "showLabel" + }, + "supports": { + "align": true, + "reusable": false, + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "layout": { + "allowSwitching": false, + "allowInheriting": false, + "default": { + "type": "flex" + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-query-pagination-editor", + "style": "wp-block-query-pagination" +} diff --git a/src/wp-includes/blocks/query-title.php b/src/wp-includes/blocks/query-title.php new file mode 100644 index 0000000000000..980e1c5f58f44 --- /dev/null +++ b/src/wp-includes/blocks/query-title.php @@ -0,0 +1,103 @@ +context['query']['postType'] ) ? $block->context['query']['postType'] : get_post_type(); + + if ( ! $type || + ( 'archive' === $type && ! $is_archive ) || + ( 'search' === $type && ! $is_search ) || + ( 'post-type' === $type && ! $post_type ) + ) { + return ''; + } + $title = ''; + if ( $is_archive ) { + $show_prefix = isset( $attributes['showPrefix'] ) ? $attributes['showPrefix'] : true; + if ( ! $show_prefix ) { + add_filter( 'get_the_archive_title_prefix', '__return_empty_string', 1 ); + $title = get_the_archive_title(); + remove_filter( 'get_the_archive_title_prefix', '__return_empty_string', 1 ); + } else { + $title = get_the_archive_title(); + } + } + if ( $is_search ) { + $title = __( 'Search results' ); + + if ( isset( $attributes['showSearchTerm'] ) && $attributes['showSearchTerm'] ) { + $title = sprintf( + /* translators: %s is the search term. */ + __( 'Search results for: "%s"' ), + get_search_query() + ); + } + } + if ( 'post-type' === $type ) { + $post_type_object = get_post_type_object( $post_type ); + + if ( ! $post_type_object ) { + return ''; + } + + $post_type_name = $post_type_object->labels->singular_name; + $show_prefix = isset( $attributes['showPrefix'] ) ? $attributes['showPrefix'] : true; + + if ( $show_prefix ) { + $title = sprintf( + /* translators: %s is the post type name. */ + __( 'Post Type: "%s"' ), + $post_type_name + ); + } else { + $title = $post_type_name; + } + } + + $level = isset( $attributes['level'] ) ? (int) $attributes['level'] : 1; + $tag_name = 0 === $level ? 'p' : 'h' . (int) $attributes['level']; + + $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}"; + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $align_class_name ) ); + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + $title + ); +} + +/** + * Registers the `core/query-title` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query_title() { + register_block_type_from_metadata( + __DIR__ . '/query-title', + array( + 'render_callback' => 'render_block_core_query_title', + ) + ); +} +add_action( 'init', 'register_block_core_query_title' ); diff --git a/src/wp-includes/blocks/query-title/block.json b/src/wp-includes/blocks/query-title/block.json new file mode 100644 index 0000000000000..549451bbfc67b --- /dev/null +++ b/src/wp-includes/blocks/query-title/block.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-title", + "title": "Query Title", + "category": "theme", + "description": "Display the query title.", + "textdomain": "default", + "attributes": { + "type": { + "type": "string" + }, + "textAlign": { + "type": "string" + }, + "level": { + "type": "number", + "default": 1 + }, + "levelOptions": { + "type": "array" + }, + "showPrefix": { + "type": "boolean", + "default": true + }, + "showSearchTerm": { + "type": "boolean", + "default": true + } + }, + "example": { + "attributes": { + "type": "search" + } + }, + "usesContext": [ "query" ], + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-query-title" +} diff --git a/src/wp-includes/blocks/query-total.php b/src/wp-includes/blocks/query-total.php new file mode 100644 index 0000000000000..f63bb1b98eac0 --- /dev/null +++ b/src/wp-includes/blocks/query-total.php @@ -0,0 +1,90 @@ +context['query']['inherit'] ) && $block->context['query']['inherit'] ) { + $query_to_use = $wp_query; + $current_page = max( 1, (int) get_query_var( 'paged', 1 ) ); + } else { + $page_key = isset( $block->context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $current_page = isset( $_GET[ $page_key ] ) ? (int) $_GET[ $page_key ] : 1; + $query_to_use = new WP_Query( build_query_vars_from_query_block( $block, $current_page ) ); + } + + $max_rows = $query_to_use->found_posts; + $posts_per_page = (int) $query_to_use->get( 'posts_per_page' ); + + // Calculate the range of posts being displayed. + $start = ( 0 === $max_rows ) ? 0 : ( ( $current_page - 1 ) * $posts_per_page + 1 ); + $end = min( $start + $posts_per_page - 1, $max_rows ); + + // Prepare the display based on the `displayType` attribute. + $output = ''; + switch ( $attributes['displayType'] ) { + case 'range-display': + if ( $start === $end ) { + $output = sprintf( + /* translators: 1: Start index of posts, 2: Total number of posts */ + __( 'Displaying %1$s of %2$s' ), + $start, + $max_rows + ); + } else { + $output = sprintf( + /* translators: 1: Start index of posts, 2: End index of posts, 3: Total number of posts */ + __( 'Displaying %1$s – %2$s of %3$s' ), + $start, + $end, + $max_rows + ); + } + + break; + + case 'total-results': + default: + // translators: %d: number of results. + $output = sprintf( _n( '%d result found', '%d results found', $max_rows ), $max_rows ); + break; + } + + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $output + ); +} + +/** + * Registers the `query-total` block. + * + * @since 6.8.0 + */ +function register_block_core_query_total() { + register_block_type_from_metadata( + __DIR__ . '/query-total', + array( + 'render_callback' => 'render_block_core_query_total', + ) + ); +} +add_action( 'init', 'register_block_core_query_total' ); diff --git a/src/wp-includes/blocks/query-total/block.json b/src/wp-includes/blocks/query-total/block.json new file mode 100644 index 0000000000000..21f6ba0673903 --- /dev/null +++ b/src/wp-includes/blocks/query-total/block.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-total", + "title": "Query Total", + "category": "theme", + "ancestor": [ "core/query" ], + "description": "Display the total number of results in a query.", + "textdomain": "default", + "attributes": { + "displayType": { + "type": "string", + "default": "total-results" + } + }, + "usesContext": [ "queryId", "query" ], + "supports": { + "align": [ "wide", "full" ], + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-query-total" +} diff --git a/src/wp-includes/blocks/query.php b/src/wp-includes/blocks/query.php new file mode 100644 index 0000000000000..6b544cd99ae8c --- /dev/null +++ b/src/wp-includes/blocks/query.php @@ -0,0 +1,152 @@ +next_tag() ) { + // Add the necessary directives. + $p->set_attribute( 'data-wp-interactive', 'core/query' ); + $p->set_attribute( 'data-wp-router-region', 'query-' . $attributes['queryId'] ); + $p->set_attribute( 'data-wp-context', '{}' ); + $p->set_attribute( 'data-wp-key', $attributes['queryId'] ); + $content = $p->get_updated_html(); + } + } + + // Add the styles to the block type if the block is interactive and remove + // them if it's not. + $style_asset = 'wp-block-query'; + if ( ! wp_style_is( $style_asset ) ) { + $style_handles = $block->block_type->style_handles; + // If the styles are not needed, and they are still in the `style_handles`, remove them. + if ( ! $is_interactive && in_array( $style_asset, $style_handles, true ) ) { + $block->block_type->style_handles = array_diff( $style_handles, array( $style_asset ) ); + } + // If the styles are needed, but they were previously removed, add them again. + if ( $is_interactive && ! in_array( $style_asset, $style_handles, true ) ) { + $block->block_type->style_handles = array_merge( $style_handles, array( $style_asset ) ); + } + } + + return $content; +} + +/** + * Registers the `core/query` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_query() { + register_block_type_from_metadata( + __DIR__ . '/query', + array( + 'render_callback' => 'render_block_core_query', + ) + ); +} +add_action( 'init', 'register_block_core_query' ); + +/** + * Traverse the tree of blocks looking for any plugin block (i.e., a block from + * an installed plugin) inside a Query block with the enhanced pagination + * enabled. If at least one is found, the enhanced pagination is effectively + * disabled to prevent any potential incompatibilities. + * + * @since 6.4.0 + * + * @param array $parsed_block The block being rendered. + * @return array Returns the parsed block, unmodified. + */ +function block_core_query_disable_enhanced_pagination( $parsed_block ) { + static $enhanced_query_stack = array(); + static $dirty_enhanced_queries = array(); + static $render_query_callback = null; + + $block_name = $parsed_block['blockName']; + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); + $has_enhanced_pagination = isset( $parsed_block['attrs']['enhancedPagination'] ) && true === $parsed_block['attrs']['enhancedPagination'] && isset( $parsed_block['attrs']['queryId'] ); + /* + * Client side navigation can be true in two states: + * - supports.interactivity = true; + * - supports.interactivity.clientNavigation = true; + */ + $supports_client_navigation = ( isset( $block_type->supports['interactivity']['clientNavigation'] ) && true === $block_type->supports['interactivity']['clientNavigation'] ) + || ( isset( $block_type->supports['interactivity'] ) && true === $block_type->supports['interactivity'] ); + + if ( 'core/query' === $block_name && $has_enhanced_pagination ) { + $enhanced_query_stack[] = $parsed_block['attrs']['queryId']; + + if ( ! isset( $render_query_callback ) ) { + /** + * Filter that disables the enhanced pagination feature during block + * rendering when a plugin block has been found inside. It does so + * by adding an attribute called `data-wp-navigation-disabled` which + * is later handled by the front-end logic. + * + * @param string $content The block content. + * @param array $block The full block, including name and attributes. + * @return string Returns the modified output of the query block. + */ + $render_query_callback = static function ( $content, $block ) use ( &$enhanced_query_stack, &$dirty_enhanced_queries, &$render_query_callback ) { + $has_enhanced_pagination = isset( $block['attrs']['enhancedPagination'] ) && true === $block['attrs']['enhancedPagination'] && isset( $block['attrs']['queryId'] ); + + if ( ! $has_enhanced_pagination ) { + return $content; + } + + if ( isset( $dirty_enhanced_queries[ $block['attrs']['queryId'] ] ) ) { + // Disable navigation in the router store config. + wp_interactivity_config( 'core/router', array( 'clientNavigationDisabled' => true ) ); + $dirty_enhanced_queries[ $block['attrs']['queryId'] ] = null; + } + + array_pop( $enhanced_query_stack ); + + if ( empty( $enhanced_query_stack ) ) { + remove_filter( 'render_block_core/query', $render_query_callback ); + $render_query_callback = null; + } + + return $content; + }; + + add_filter( 'render_block_core/query', $render_query_callback, 10, 2 ); + } + } elseif ( + ! empty( $enhanced_query_stack ) && + isset( $block_name ) && + ( ! $supports_client_navigation ) + ) { + foreach ( $enhanced_query_stack as $query_id ) { + $dirty_enhanced_queries[ $query_id ] = true; + } + } + + return $parsed_block; +} + +add_filter( 'render_block_data', 'block_core_query_disable_enhanced_pagination', 10, 1 ); diff --git a/src/wp-includes/blocks/query/block.json b/src/wp-includes/blocks/query/block.json new file mode 100644 index 0000000000000..33ba8bfd925ca --- /dev/null +++ b/src/wp-includes/blocks/query/block.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query", + "title": "Query Loop", + "category": "theme", + "description": "An advanced block that allows displaying post types based on different query parameters and visual configurations.", + "keywords": [ "posts", "list", "blog", "blogs", "custom post types" ], + "textdomain": "default", + "attributes": { + "queryId": { + "type": "number" + }, + "query": { + "type": "object", + "default": { + "perPage": null, + "pages": 0, + "offset": 0, + "postType": "post", + "order": "desc", + "orderBy": "date", + "author": "", + "search": "", + "exclude": [], + "sticky": "", + "inherit": true, + "taxQuery": null, + "parents": [], + "format": [] + } + }, + "tagName": { + "type": "string", + "default": "div" + }, + "namespace": { + "type": "string" + }, + "enhancedPagination": { + "type": "boolean", + "default": false + } + }, + "usesContext": [ "templateSlug" ], + "providesContext": { + "queryId": "queryId", + "query": "query", + "displayLayout": "displayLayout", + "enhancedPagination": "enhancedPagination" + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "layout": true, + "interactivity": true, + "contentRole": true + }, + "editorStyle": "wp-block-query-editor" +} diff --git a/src/wp-includes/blocks/query/view.asset.php b/src/wp-includes/blocks/query/view.asset.php new file mode 100644 index 0000000000000..30c0410598e62 --- /dev/null +++ b/src/wp-includes/blocks/query/view.asset.php @@ -0,0 +1 @@ + array(), 'version' => 'ee101e08820687c9c07f'); diff --git a/src/wp-includes/blocks/query/view.min.asset.php b/src/wp-includes/blocks/query/view.min.asset.php new file mode 100644 index 0000000000000..305a626497b32 --- /dev/null +++ b/src/wp-includes/blocks/query/view.min.asset.php @@ -0,0 +1 @@ + array(), 'version' => '490915f92cc794ea16e1'); diff --git a/src/wp-includes/blocks/quote/block.json b/src/wp-includes/blocks/quote/block.json new file mode 100644 index 0000000000000..52609ee57d12a --- /dev/null +++ b/src/wp-includes/blocks/quote/block.json @@ -0,0 +1,105 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/quote", + "title": "Quote", + "category": "text", + "description": "Give quoted text visual emphasis. \"In quoting others, we cite ourselves.\" — Julio CortĆ”zar", + "keywords": [ "blockquote", "cite" ], + "textdomain": "default", + "attributes": { + "value": { + "type": "string", + "source": "html", + "selector": "blockquote", + "multiline": "p", + "default": "", + "role": "content" + }, + "citation": { + "type": "rich-text", + "source": "rich-text", + "selector": "cite", + "role": "content" + }, + "textAlign": { + "type": "string" + } + }, + "supports": { + "anchor": true, + "align": [ "left", "right", "wide", "full" ], + "html": false, + "background": { + "backgroundImage": true, + "backgroundSize": true, + "__experimentalDefaultControls": { + "backgroundImage": true + } + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "style": true, + "width": true + } + }, + "dimensions": { + "minHeight": true, + "__experimentalDefaultControls": { + "minHeight": false + } + }, + "__experimentalOnEnter": true, + "__experimentalOnMerge": true, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "color": { + "gradients": true, + "heading": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "layout": { + "allowEditing": false + }, + "spacing": { + "blockGap": true, + "padding": true, + "margin": true + }, + "interactivity": { + "clientNavigation": true + }, + "allowedBlocks": true + }, + "styles": [ + { + "name": "default", + "label": "Default", + "isDefault": true + }, + { "name": "plain", "label": "Plain" } + ], + "editorStyle": "wp-block-quote-editor", + "style": "wp-block-quote" +} diff --git a/src/wp-includes/blocks/read-more.php b/src/wp-includes/blocks/read-more.php new file mode 100644 index 0000000000000..c01a0a377fc93 --- /dev/null +++ b/src/wp-includes/blocks/read-more.php @@ -0,0 +1,63 @@ +context['postId'] ) ) { + return ''; + } + + $post_ID = $block->context['postId']; + $post_title = get_the_title( $post_ID ); + if ( '' === $post_title ) { + $post_title = sprintf( + /* translators: %s is post ID to describe the link for screen readers. */ + __( 'untitled post %s' ), + $post_ID + ); + } + $screen_reader_text = sprintf( + /* translators: %s is either the post title or post ID to describe the link for screen readers. */ + __( ': %s' ), + $post_title + ); + $justify_class_name = empty( $attributes['justifyContent'] ) ? '' : "is-justified-{$attributes['justifyContent']}"; + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $justify_class_name ) ); + $more_text = ! empty( $attributes['content'] ) ? wp_kses_post( $attributes['content'] ) : __( 'Read more' ); + return sprintf( + '%4s%5s', + $wrapper_attributes, + get_the_permalink( $post_ID ), + esc_attr( $attributes['linkTarget'] ), + $more_text, + $screen_reader_text + ); +} + +/** + * Registers the `core/read-more` block on the server. + * + * @since 6.0.0 + */ +function register_block_core_read_more() { + register_block_type_from_metadata( + __DIR__ . '/read-more', + array( + 'render_callback' => 'render_block_core_read_more', + ) + ); +} +add_action( 'init', 'register_block_core_read_more' ); diff --git a/src/wp-includes/blocks/read-more/block.json b/src/wp-includes/blocks/read-more/block.json new file mode 100644 index 0000000000000..eabc7acf3e3a3 --- /dev/null +++ b/src/wp-includes/blocks/read-more/block.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/read-more", + "title": "Read More", + "category": "theme", + "description": "Displays the link of a post, page, or any other content-type.", + "textdomain": "default", + "attributes": { + "content": { + "type": "string", + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self" + } + }, + "usesContext": [ "postId" ], + "supports": { + "html": false, + "color": { + "gradients": true, + "text": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalLetterSpacing": true, + "__experimentalTextDecoration": true, + "__experimentalDefaultControls": { + "fontSize": true, + "textDecoration": true + } + }, + "spacing": { + "margin": [ "top", "bottom" ], + "padding": true, + "__experimentalDefaultControls": { + "padding": true + } + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "width": true, + "__experimentalDefaultControls": { + "width": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-read-more" +} diff --git a/src/wp-includes/blocks/require-dynamic-blocks.php b/src/wp-includes/blocks/require-dynamic-blocks.php new file mode 100644 index 0000000000000..df5be6face017 --- /dev/null +++ b/src/wp-includes/blocks/require-dynamic-blocks.php @@ -0,0 +1,80 @@ +
      ' . __( 'Adding an RSS feed to this site’s homepage is not supported, as it could lead to a loop that slows down your site. Try using another block, like the Latest Posts block, to list posts from the site.' ) . '
      '; + } + + $rss = fetch_feed( $attributes['feedURL'] ); + + if ( is_wp_error( $rss ) ) { + return '
      ' . __( 'RSS Error:' ) . ' ' . esc_html( $rss->get_error_message() ) . '
      '; + } + + if ( ! $rss->get_item_quantity() ) { + return '
      ' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '
      '; + } + + $rss_items = $rss->get_items( 0, $attributes['itemsToShow'] ); + $list_items = ''; + + $open_in_new_tab = ! empty( $attributes['openInNewTab'] ); + $rel = ! empty( $attributes['rel'] ) ? trim( $attributes['rel'] ) : ''; + + $link_attributes = ''; + + if ( $open_in_new_tab ) { + $link_attributes .= ' target="_blank"'; + } + + if ( '' !== $rel ) { + $link_attributes .= ' rel="' . esc_attr( $rel ) . '"'; + } + + foreach ( $rss_items as $item ) { + $title = esc_html( trim( strip_tags( html_entity_decode( $item->get_title() ) ) ) ); + + if ( empty( $title ) ) { + $title = __( '(no title)' ); + } + $link = $item->get_link(); + $link = esc_url( $link ); + + if ( $link ) { + $title = "{$title}"; + } + $title = "
      {$title}
      "; + + $date_markup = ''; + if ( ! empty( $attributes['displayDate'] ) ) { + $timestamp = $item->get_date( 'U' ); + + if ( $timestamp ) { + $gmt_offset = get_option( 'gmt_offset' ); + $timestamp += (int) ( (float) $gmt_offset * HOUR_IN_SECONDS ); + + $date_markup = sprintf( + ' ', + esc_attr( date_i18n( 'c', $timestamp ) ), + esc_html( date_i18n( get_option( 'date_format' ), $timestamp ) ) + ); + } + } + + $author = ''; + if ( $attributes['displayAuthor'] ) { + $author = $item->get_author(); + if ( is_object( $author ) ) { + $author = $author->get_name(); + if ( ! empty( $author ) ) { + $author = '' . sprintf( + /* translators: byline. %s: author. */ + __( 'by %s' ), + esc_html( strip_tags( $author ) ) + ) . ''; + } + } + } + + $excerpt = ''; + $description = $item->get_description(); + if ( $attributes['displayExcerpt'] && ! empty( $description ) ) { + $excerpt = html_entity_decode( $description, ENT_QUOTES, get_option( 'blog_charset' ) ); + $excerpt = esc_attr( wp_trim_words( $excerpt, $attributes['excerptLength'], ' […]' ) ); + + // Change existing [...] to […]. + if ( '[...]' === substr( $excerpt, -5 ) ) { + $excerpt = substr( $excerpt, 0, -5 ) . '[…]'; + } + + $excerpt = '
      ' . esc_html( $excerpt ) . '
      '; + } + + $list_items .= "
    6. {$title}{$date_markup}{$author}{$excerpt}
    7. "; + } + + $classnames = array(); + if ( isset( $attributes['blockLayout'] ) && 'grid' === $attributes['blockLayout'] ) { + $classnames[] = 'is-grid'; + } + if ( isset( $attributes['columns'] ) && 'grid' === $attributes['blockLayout'] ) { + $classnames[] = 'columns-' . $attributes['columns']; + } + if ( $attributes['displayDate'] ) { + $classnames[] = 'has-dates'; + } + if ( $attributes['displayAuthor'] ) { + $classnames[] = 'has-authors'; + } + if ( $attributes['displayExcerpt'] ) { + $classnames[] = 'has-excerpts'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classnames ) ) ); + + return sprintf( '
        %s
      ', $wrapper_attributes, $list_items ); +} + +/** + * Registers the `core/rss` block on server. + * + * @since 5.2.0 + */ +function register_block_core_rss() { + register_block_type_from_metadata( + __DIR__ . '/rss', + array( + 'render_callback' => 'render_block_core_rss', + ) + ); +} +add_action( 'init', 'register_block_core_rss' ); diff --git a/src/wp-includes/blocks/rss/block.json b/src/wp-includes/blocks/rss/block.json new file mode 100644 index 0000000000000..fc49e1d858e89 --- /dev/null +++ b/src/wp-includes/blocks/rss/block.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/rss", + "title": "RSS", + "category": "widgets", + "description": "Display entries from any RSS or Atom feed.", + "keywords": [ "atom", "feed" ], + "textdomain": "default", + "attributes": { + "columns": { + "type": "number", + "default": 2 + }, + "blockLayout": { + "type": "string", + "default": "list" + }, + "feedURL": { + "type": "string", + "default": "", + "role": "content" + }, + "itemsToShow": { + "type": "number", + "default": 5 + }, + "displayExcerpt": { + "type": "boolean", + "default": false + }, + "displayAuthor": { + "type": "boolean", + "default": false + }, + "displayDate": { + "type": "boolean", + "default": false + }, + "excerptLength": { + "type": "number", + "default": 55 + }, + "openInNewTab": { + "type": "boolean", + "default": false + }, + "rel": { + "type": "string" + } + }, + "supports": { + "align": true, + "html": false, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "padding": false, + "margin": false + } + }, + "color": { + "background": true, + "text": true, + "gradients": true, + "link": true + } + }, + "editorStyle": "wp-block-rss-editor", + "style": "wp-block-rss" +} diff --git a/src/wp-includes/blocks/search.php b/src/wp-includes/blocks/search.php new file mode 100644 index 0000000000000..7073d6ce8ab3f --- /dev/null +++ b/src/wp-includes/blocks/search.php @@ -0,0 +1,621 @@ +`. Support these by defaulting an undefined label and + // buttonText to `__( 'Search' )`. + $attributes = wp_parse_args( + $attributes, + array( + 'label' => __( 'Search' ), + 'buttonText' => __( 'Search' ), + ) + ); + + $input_id = wp_unique_id( 'wp-block-search__input-' ); + $classnames = classnames_for_block_core_search( $attributes ); + $show_label = ! empty( $attributes['showLabel'] ); + $use_icon_button = ! empty( $attributes['buttonUseIcon'] ); + $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true; + $button_position = $show_button ? $attributes['buttonPosition'] : null; + $query_params = ( ! empty( $attributes['query'] ) ) ? $attributes['query'] : array(); + $button = ''; + $query_params_markup = ''; + $inline_styles = styles_for_block_core_search( $attributes ); + $color_classes = get_color_classes_for_block_core_search( $attributes ); + $typography_classes = get_typography_classes_for_block_core_search( $attributes ); + $is_button_inside = ! empty( $attributes['buttonPosition'] ) && + 'button-inside' === $attributes['buttonPosition']; + // Border color classes need to be applied to the elements that have a border color. + $border_color_classes = get_border_color_classes_for_block_core_search( $attributes ); + // This variable is a constant and its value is always false at this moment. + // It is defined this way because some values depend on it, in case it changes in the future. + $open_by_default = false; + + $label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] ); + $label = new WP_HTML_Tag_Processor( sprintf( '', $inline_styles['label'], $label_inner_html ) ); + if ( $label->next_tag() ) { + $label->set_attribute( 'for', $input_id ); + $label->add_class( 'wp-block-search__label' ); + if ( $show_label && ! empty( $attributes['label'] ) ) { + if ( ! empty( $typography_classes ) ) { + $label->add_class( $typography_classes ); + } + } else { + $label->add_class( 'screen-reader-text' ); + } + } + + $input = new WP_HTML_Tag_Processor( sprintf( '', $inline_styles['input'] ) ); + $input_classes = array( 'wp-block-search__input' ); + if ( ! $is_button_inside && ! empty( $border_color_classes ) ) { + $input_classes[] = $border_color_classes; + } + if ( ! empty( $typography_classes ) ) { + $input_classes[] = $typography_classes; + } + if ( $input->next_tag() ) { + $input->add_class( implode( ' ', $input_classes ) ); + $input->set_attribute( 'id', $input_id ); + $input->set_attribute( 'value', get_search_query() ); + $input->set_attribute( 'placeholder', $attributes['placeholder'] ); + + // If it's interactive, enqueue the script module and add the directives. + $is_expandable_searchfield = 'button-only' === $button_position; + if ( $is_expandable_searchfield ) { + wp_enqueue_script_module( '@wordpress/block-library/search/view' ); + + $input->set_attribute( 'data-wp-bind--aria-hidden', '!context.isSearchInputVisible' ); + $input->set_attribute( 'data-wp-bind--tabindex', 'state.tabindex' ); + + // Adding these attributes manually is needed until the Interactivity API + // SSR logic is added to core. + $input->set_attribute( 'aria-hidden', 'true' ); + $input->set_attribute( 'tabindex', '-1' ); + } + } + + if ( count( $query_params ) > 0 ) { + foreach ( $query_params as $param => $value ) { + $query_params_markup .= sprintf( + '', + esc_attr( $param ), + esc_attr( $value ) + ); + } + } + + if ( $show_button ) { + $button_classes = array( 'wp-block-search__button' ); + $button_internal_markup = ''; + if ( ! empty( $color_classes ) ) { + $button_classes[] = $color_classes; + } + if ( ! empty( $typography_classes ) ) { + $button_classes[] = $typography_classes; + } + + if ( ! $is_button_inside && ! empty( $border_color_classes ) ) { + $button_classes[] = $border_color_classes; + } + if ( ! $use_icon_button ) { + if ( ! empty( $attributes['buttonText'] ) ) { + $button_internal_markup = wp_kses_post( $attributes['buttonText'] ); + } + } else { + $button_classes[] = 'has-icon'; + $button_internal_markup = + ' + + '; + } + + // Include the button element class. + $button_classes[] = wp_theme_get_element_class_name( 'button' ); + $button = new WP_HTML_Tag_Processor( sprintf( '', $inline_styles['button'], $button_internal_markup ) ); + + if ( $button->next_tag() ) { + $button->add_class( implode( ' ', $button_classes ) ); + if ( 'button-only' === $attributes['buttonPosition'] ) { + $button->set_attribute( 'data-wp-bind--aria-label', 'state.ariaLabel' ); + $button->set_attribute( 'data-wp-bind--aria-controls', 'state.ariaControls' ); + $button->set_attribute( 'data-wp-bind--aria-expanded', 'context.isSearchInputVisible' ); + $button->set_attribute( 'data-wp-bind--type', 'state.type' ); + $button->set_attribute( 'data-wp-on--click', 'actions.openSearchInput' ); + + // Adding these attributes manually is needed until the Interactivity + // API SSR logic is added to core. + $button->set_attribute( 'aria-label', __( 'Expand search field' ) ); + $button->set_attribute( 'aria-controls', 'wp-block-search__input-' . $input_id ); + $button->set_attribute( 'aria-expanded', 'false' ); + $button->set_attribute( 'type', 'button' ); + } else { + $button->set_attribute( 'aria-label', wp_strip_all_tags( $attributes['buttonText'] ) ); + } + } + } + + $field_markup_classes = array( + 'wp-block-search__inside-wrapper', + ); + if ( $is_button_inside && ! empty( $border_color_classes ) ) { + $field_markup_classes[] = $border_color_classes; + } + $field_markup = sprintf( + '
      %s
      ', + esc_attr( implode( ' ', $field_markup_classes ) ), + $inline_styles['wrapper'], + $input . $query_params_markup . $button + ); + $wrapper_attributes = get_block_wrapper_attributes( + array( 'class' => $classnames ) + ); + $form_directives = ''; + + // If it's interactive, add the directives. + if ( $is_expandable_searchfield ) { + $aria_label_expanded = __( 'Submit Search' ); + $aria_label_collapsed = __( 'Expand search field' ); + $form_context = wp_interactivity_data_wp_context( + array( + 'isSearchInputVisible' => $open_by_default, + 'inputId' => $input_id, + 'ariaLabelExpanded' => $aria_label_expanded, + 'ariaLabelCollapsed' => $aria_label_collapsed, + ) + ); + $form_directives = ' + data-wp-interactive="core/search" + ' . $form_context . ' + data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible" + data-wp-on--keydown="actions.handleSearchKeydown" + data-wp-on--focusout="actions.handleSearchFocusout" + '; + } + + return sprintf( + '
      %4s
      ', + esc_url( home_url( '/' ) ), + $wrapper_attributes, + $form_directives, + $label . $field_markup + ); +} + +/** + * Registers the `core/search` block on the server. + * + * @since 5.2.0 + */ +function register_block_core_search() { + register_block_type_from_metadata( + __DIR__ . '/search', + array( + 'render_callback' => 'render_block_core_search', + ) + ); +} +add_action( 'init', 'register_block_core_search' ); + +/** + * Builds the correct top level classnames for the 'core/search' block. + * + * @since 5.6.0 + * + * @param array $attributes The block attributes. + * + * @return string The classnames used in the block. + */ +function classnames_for_block_core_search( $attributes ) { + $classnames = array(); + + if ( ! empty( $attributes['buttonPosition'] ) ) { + if ( 'button-inside' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-inside'; + } + + if ( 'button-outside' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-outside'; + } + + if ( 'no-button' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__no-button'; + } + + if ( 'button-only' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-only wp-block-search__searchfield-hidden'; + } + } + + if ( isset( $attributes['buttonUseIcon'] ) ) { + if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) { + if ( $attributes['buttonUseIcon'] ) { + $classnames[] = 'wp-block-search__icon-button'; + } else { + $classnames[] = 'wp-block-search__text-button'; + } + } + } + + return implode( ' ', $classnames ); +} + +/** + * This generates a CSS rule for the given border property and side if provided. + * Based on whether the Search block is configured to display the button inside + * or not, the generated rule is injected into the appropriate collection of + * styles for later application in the block's markup. + * + * @since 6.1.0 + * + * @param array $attributes The block attributes. + * @param string $property Border property to generate rule for e.g. width or color. + * @param string $side Optional side border. The dictates the value retrieved and final CSS property. + * @param array $wrapper_styles Current collection of wrapper styles. + * @param array $button_styles Current collection of button styles. + * @param array $input_styles Current collection of input styles. + */ +function apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) { + $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition']; + + $path = array( 'style', 'border', $property ); + + if ( $side ) { + array_splice( $path, 2, 0, $side ); + } + + $value = _wp_array_get( $attributes, $path, false ); + + if ( empty( $value ) ) { + return; + } + + if ( 'color' === $property && $side ) { + $has_color_preset = str_contains( $value, 'var:preset|color|' ); + if ( $has_color_preset ) { + $named_color_value = substr( $value, strrpos( $value, '|' ) + 1 ); + $value = sprintf( 'var(--wp--preset--color--%s)', $named_color_value ); + } + } + + $property_suffix = $side ? sprintf( '%s-%s', $side, $property ) : $property; + + if ( $is_button_inside ) { + $wrapper_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) ); + } else { + $button_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) ); + $input_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) ); + } +} + +/** + * This adds CSS rules for a given border property e.g. width or color. It + * injects rules into the provided wrapper, button and input style arrays for + * uniform "flat" borders or those with individual sides configured. + * + * @since 6.1.0 + * + * @param array $attributes The block attributes. + * @param string $property Border property to generate rule for e.g. width or color. + * @param array $wrapper_styles Current collection of wrapper styles. + * @param array $button_styles Current collection of button styles. + * @param array $input_styles Current collection of input styles. + */ +function apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) { + apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_style( $attributes, $property, 'top', $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_style( $attributes, $property, 'right', $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_style( $attributes, $property, 'bottom', $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_style( $attributes, $property, 'left', $wrapper_styles, $button_styles, $input_styles ); +} + +/** + * Builds an array of inline styles for the search block. + * + * The result will contain one entry for shared styles such as those for the + * inner input or button and a second for the inner wrapper should the block + * be positioning the button "inside". + * + * @since 5.8.0 + * + * @param array $attributes The block attributes. + * + * @return array Style HTML attribute. + */ +function styles_for_block_core_search( $attributes ) { + $wrapper_styles = array(); + $button_styles = array(); + $input_styles = array(); + $label_styles = array(); + $is_button_inside = ! empty( $attributes['buttonPosition'] ) && + 'button-inside' === $attributes['buttonPosition']; + $show_label = ( isset( $attributes['showLabel'] ) ) && false !== $attributes['showLabel']; + + // Add width styles. + $has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] ); + + if ( $has_width ) { + $wrapper_styles[] = sprintf( + 'width: %d%s;', + esc_attr( $attributes['width'] ), + esc_attr( $attributes['widthUnit'] ) + ); + } + + // Add border width and color styles. + apply_block_core_search_border_styles( $attributes, 'width', $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_styles( $attributes, 'color', $wrapper_styles, $button_styles, $input_styles ); + apply_block_core_search_border_styles( $attributes, 'style', $wrapper_styles, $button_styles, $input_styles ); + + // Add border radius styles. + $has_border_radius = ! empty( $attributes['style']['border']['radius'] ); + + if ( $has_border_radius ) { + $default_padding = '4px'; + $border_radius = $attributes['style']['border']['radius']; + + if ( is_array( $border_radius ) ) { + // Apply styles for individual corner border radii. + foreach ( $border_radius as $key => $value ) { + // Get border-radius CSS variable from preset value if provided. + if ( is_string( $value ) && str_contains( $value, 'var:preset|border-radius|' ) ) { + $index_to_splice = strrpos( $value, '|' ) + 1; + $slug = _wp_to_kebab_case( substr( $value, $index_to_splice ) ); + $value = "var(--wp--preset--border-radius--$slug)"; + } + + if ( null !== $value ) { + // Convert camelCase key to kebab-case. + $name = strtolower( preg_replace( '/(? ! empty( $input_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $input_styles ) ) ) ) : '', + 'button' => ! empty( $button_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $button_styles ) ) ) ) : '', + 'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $wrapper_styles ) ) ) ) : '', + 'label' => ! empty( $label_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $label_styles ) ) ) ) : '', + ); +} + +/** + * Returns typography classnames depending on whether there are named font sizes/families. + * + * @since 6.1.0 + * + * @param array $attributes The block attributes. + * + * @return string The typography color classnames to be applied to the block elements. + */ +function get_typography_classes_for_block_core_search( $attributes ) { + $typography_classes = array(); + $has_named_font_family = ! empty( $attributes['fontFamily'] ); + $has_named_font_size = ! empty( $attributes['fontSize'] ); + + if ( $has_named_font_size ) { + $typography_classes[] = sprintf( 'has-%s-font-size', esc_attr( $attributes['fontSize'] ) ); + } + + if ( $has_named_font_family ) { + $typography_classes[] = sprintf( 'has-%s-font-family', esc_attr( $attributes['fontFamily'] ) ); + } + + return implode( ' ', $typography_classes ); +} + +/** + * Returns typography styles to be included in an HTML style tag. + * This excludes text-decoration, which is applied only to the label and button elements of the search block. + * + * @since 6.1.0 + * + * @param array $attributes The block attributes. + * + * @return string A string of typography CSS declarations. + */ +function get_typography_styles_for_block_core_search( $attributes ) { + $typography_styles = array(); + + // Add typography styles. + if ( ! empty( $attributes['style']['typography']['fontSize'] ) ) { + $typography_styles[] = sprintf( + 'font-size: %s;', + wp_get_typography_font_size_value( + array( + 'size' => $attributes['style']['typography']['fontSize'], + ) + ) + ); + + } + + if ( ! empty( $attributes['style']['typography']['fontFamily'] ) ) { + $typography_styles[] = sprintf( 'font-family: %s;', $attributes['style']['typography']['fontFamily'] ); + } + + if ( ! empty( $attributes['style']['typography']['letterSpacing'] ) ) { + $typography_styles[] = sprintf( 'letter-spacing: %s;', $attributes['style']['typography']['letterSpacing'] ); + } + + if ( ! empty( $attributes['style']['typography']['fontWeight'] ) ) { + $typography_styles[] = sprintf( 'font-weight: %s;', $attributes['style']['typography']['fontWeight'] ); + } + + if ( ! empty( $attributes['style']['typography']['fontStyle'] ) ) { + $typography_styles[] = sprintf( 'font-style: %s;', $attributes['style']['typography']['fontStyle'] ); + } + + if ( ! empty( $attributes['style']['typography']['lineHeight'] ) ) { + $typography_styles[] = sprintf( 'line-height: %s;', $attributes['style']['typography']['lineHeight'] ); + } + + if ( ! empty( $attributes['style']['typography']['textTransform'] ) ) { + $typography_styles[] = sprintf( 'text-transform: %s;', $attributes['style']['typography']['textTransform'] ); + } + + return implode( '', $typography_styles ); +} + +/** + * Returns border color classnames depending on whether there are named or custom border colors. + * + * @since 5.9.0 + * + * @param array $attributes The block attributes. + * + * @return string The border color classnames to be applied to the block elements. + */ +function get_border_color_classes_for_block_core_search( $attributes ) { + $border_color_classes = array(); + $has_custom_border_color = ! empty( $attributes['style']['border']['color'] ); + $has_named_border_color = ! empty( $attributes['borderColor'] ); + + if ( $has_custom_border_color || $has_named_border_color ) { + $border_color_classes[] = 'has-border-color'; + } + + if ( $has_named_border_color ) { + $border_color_classes[] = sprintf( 'has-%s-border-color', esc_attr( $attributes['borderColor'] ) ); + } + + return implode( ' ', $border_color_classes ); +} + +/** + * Returns color classnames depending on whether there are named or custom text and background colors. + * + * @since 5.9.0 + * + * @param array $attributes The block attributes. + * + * @return string The color classnames to be applied to the block elements. + */ +function get_color_classes_for_block_core_search( $attributes ) { + $classnames = array(); + + // Text color. + $has_named_text_color = ! empty( $attributes['textColor'] ); + $has_custom_text_color = ! empty( $attributes['style']['color']['text'] ); + if ( $has_named_text_color ) { + $classnames[] = sprintf( 'has-text-color has-%s-color', $attributes['textColor'] ); + } elseif ( $has_custom_text_color ) { + // If a custom 'textColor' was selected instead of a preset, still add the generic `has-text-color` class. + $classnames[] = 'has-text-color'; + } + + // Background color. + $has_named_background_color = ! empty( $attributes['backgroundColor'] ); + $has_custom_background_color = ! empty( $attributes['style']['color']['background'] ); + $has_named_gradient = ! empty( $attributes['gradient'] ); + $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] ); + if ( + $has_named_background_color || + $has_custom_background_color || + $has_named_gradient || + $has_custom_gradient + ) { + $classnames[] = 'has-background'; + } + if ( $has_named_background_color ) { + $classnames[] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] ); + } + if ( $has_named_gradient ) { + $classnames[] = sprintf( 'has-%s-gradient-background', $attributes['gradient'] ); + } + + return implode( ' ', $classnames ); +} diff --git a/src/wp-includes/blocks/search/block.json b/src/wp-includes/blocks/search/block.json new file mode 100644 index 0000000000000..c5af5a29d21be --- /dev/null +++ b/src/wp-includes/blocks/search/block.json @@ -0,0 +1,95 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/search", + "title": "Search", + "category": "widgets", + "description": "Help visitors find your content.", + "keywords": [ "find" ], + "textdomain": "default", + "attributes": { + "label": { + "type": "string", + "role": "content" + }, + "showLabel": { + "type": "boolean", + "default": true + }, + "placeholder": { + "type": "string", + "default": "", + "role": "content" + }, + "width": { + "type": "number" + }, + "widthUnit": { + "type": "string" + }, + "buttonText": { + "type": "string", + "role": "content" + }, + "buttonPosition": { + "type": "string", + "default": "button-outside" + }, + "buttonUseIcon": { + "type": "boolean", + "default": false + }, + "query": { + "type": "object", + "default": {} + }, + "isSearchFieldHidden": { + "type": "boolean", + "default": false + } + }, + "supports": { + "align": [ "left", "center", "right" ], + "color": { + "gradients": true, + "__experimentalSkipSerialization": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "interactivity": true, + "typography": { + "__experimentalSkipSerialization": true, + "__experimentalSelector": ".wp-block-search__label, .wp-block-search__input, .wp-block-search__button", + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "width": true, + "__experimentalSkipSerialization": true, + "__experimentalDefaultControls": { + "color": true, + "radius": true, + "width": true + } + }, + "spacing": { + "margin": true + }, + "html": false + }, + "editorStyle": "wp-block-search-editor", + "style": "wp-block-search" +} diff --git a/src/wp-includes/blocks/search/view.asset.php b/src/wp-includes/blocks/search/view.asset.php new file mode 100644 index 0000000000000..e9b5021ae35c5 --- /dev/null +++ b/src/wp-includes/blocks/search/view.asset.php @@ -0,0 +1 @@ + array(), 'version' => '2a0784014283afdd3c25'); diff --git a/src/wp-includes/blocks/search/view.min.asset.php b/src/wp-includes/blocks/search/view.min.asset.php new file mode 100644 index 0000000000000..f9f2fddc7dd06 --- /dev/null +++ b/src/wp-includes/blocks/search/view.min.asset.php @@ -0,0 +1 @@ + array(), 'version' => '765a40956d200c79d99e'); diff --git a/src/wp-includes/blocks/separator/block.json b/src/wp-includes/blocks/separator/block.json new file mode 100644 index 0000000000000..926d978b7e4d5 --- /dev/null +++ b/src/wp-includes/blocks/separator/block.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/separator", + "title": "Separator", + "category": "design", + "description": "Create a break between ideas or sections with a horizontal separator.", + "keywords": [ "horizontal-line", "hr", "divider" ], + "textdomain": "default", + "attributes": { + "opacity": { + "type": "string", + "default": "alpha-channel" + }, + "tagName": { + "type": "string", + "enum": [ "hr", "div" ], + "default": "hr" + } + }, + "supports": { + "anchor": true, + "align": [ "center", "wide", "full" ], + "color": { + "enableContrastChecker": false, + "__experimentalSkipSerialization": true, + "gradients": true, + "background": true, + "text": false, + "__experimentalDefaultControls": { + "background": true + } + }, + "spacing": { + "margin": [ "top", "bottom" ] + }, + "interactivity": { + "clientNavigation": true + } + }, + "styles": [ + { "name": "default", "label": "Default", "isDefault": true }, + { "name": "wide", "label": "Wide Line" }, + { "name": "dots", "label": "Dots" } + ], + "editorStyle": "wp-block-separator-editor", + "style": "wp-block-separator" +} diff --git a/src/wp-includes/blocks/shortcode.php b/src/wp-includes/blocks/shortcode.php new file mode 100644 index 0000000000000..d96acfc55fa64 --- /dev/null +++ b/src/wp-includes/blocks/shortcode.php @@ -0,0 +1,35 @@ + 'render_block_core_shortcode', + ) + ); +} +add_action( 'init', 'register_block_core_shortcode' ); diff --git a/src/wp-includes/blocks/shortcode/block.json b/src/wp-includes/blocks/shortcode/block.json new file mode 100644 index 0000000000000..6e30210b7c081 --- /dev/null +++ b/src/wp-includes/blocks/shortcode/block.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/shortcode", + "title": "Shortcode", + "category": "widgets", + "description": "Insert additional custom elements with a WordPress shortcode.", + "textdomain": "default", + "attributes": { + "text": { + "type": "string", + "source": "raw", + "role": "content" + } + }, + "supports": { + "className": false, + "customClassName": false, + "html": false + }, + "editorStyle": "wp-block-shortcode-editor" +} diff --git a/src/wp-includes/blocks/site-logo.php b/src/wp-includes/blocks/site-logo.php new file mode 100644 index 0000000000000..915563461e30c --- /dev/null +++ b/src/wp-includes/blocks/site-logo.php @@ -0,0 +1,234 @@ +(.*?)#i', '\1', $custom_logo ); + } + + if ( $attributes['isLink'] && '_blank' === $attributes['linkTarget'] ) { + // Add the link target after the rel="home". + // Add an aria-label for informing that the page opens in a new tab. + $processor = new WP_HTML_Tag_Processor( $custom_logo ); + $processor->next_tag( 'a' ); + if ( 'home' === $processor->get_attribute( 'rel' ) ) { + $processor->set_attribute( 'aria-label', __( '(Home link, opens in a new tab)' ) ); + $processor->set_attribute( 'target', $attributes['linkTarget'] ); + } + $custom_logo = $processor->get_updated_html(); + } + + $classnames = array(); + if ( empty( $attributes['width'] ) ) { + $classnames[] = 'is-default-size'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classnames ) ) ); + $html = sprintf( '
      %s
      ', $wrapper_attributes, $custom_logo ); + return $html; +} + +/** + * Register a core site setting for a site logo + * + * @since 5.8.0 + */ +function register_block_core_site_logo_setting() { + register_setting( + 'general', + 'site_logo', + array( + 'show_in_rest' => array( + 'name' => 'site_logo', + ), + 'type' => 'integer', + 'label' => __( 'Logo' ), + 'description' => __( 'Site logo.' ), + ) + ); +} + +add_action( 'rest_api_init', 'register_block_core_site_logo_setting', 10 ); + +/** + * Register a core site setting for a site icon + * + * @since 5.9.0 + */ +function register_block_core_site_icon_setting() { + register_setting( + 'general', + 'site_icon', + array( + 'show_in_rest' => true, + 'type' => 'integer', + 'label' => __( 'Icon' ), + 'description' => __( 'Site icon.' ), + ) + ); +} + +add_action( 'rest_api_init', 'register_block_core_site_icon_setting', 10 ); + +/** + * Registers the `core/site-logo` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_site_logo() { + register_block_type_from_metadata( + __DIR__ . '/site-logo', + array( + 'render_callback' => 'render_block_core_site_logo', + ) + ); +} + +add_action( 'init', 'register_block_core_site_logo' ); + +/** + * Overrides the custom logo with a site logo, if the option is set. + * + * @since 5.8.0 + * + * @param string $custom_logo The custom logo set by a theme. + * + * @return string The site logo if set. + */ +function _override_custom_logo_theme_mod( $custom_logo ) { + $site_logo = get_option( 'site_logo' ); + return false === $site_logo ? $custom_logo : $site_logo; +} + +add_filter( 'theme_mod_custom_logo', '_override_custom_logo_theme_mod' ); + +/** + * Updates the site_logo option when the custom_logo theme-mod gets updated. + * + * @since 5.8.0 + * + * @param mixed $value Attachment ID of the custom logo or an empty value. + * @return mixed + */ +function _sync_custom_logo_to_site_logo( $value ) { + if ( empty( $value ) ) { + delete_option( 'site_logo' ); + } else { + update_option( 'site_logo', $value ); + } + + return $value; +} + +add_filter( 'pre_set_theme_mod_custom_logo', '_sync_custom_logo_to_site_logo' ); + +/** + * Deletes the site_logo when the custom_logo theme mod is removed. + * + * @since 5.8.0 + * + * @global array $_ignore_site_logo_changes + * + * @param array $old_value Previous theme mod settings. + * @param array $value Updated theme mod settings. + */ +function _delete_site_logo_on_remove_custom_logo( $old_value, $value ) { + global $_ignore_site_logo_changes; + + if ( $_ignore_site_logo_changes ) { + return; + } + + // If the custom_logo is being unset, it's being removed from theme mods. + if ( isset( $old_value['custom_logo'] ) && ! isset( $value['custom_logo'] ) ) { + delete_option( 'site_logo' ); + } +} + +/** + * Deletes the site logo when all theme mods are being removed. + * + * @since 5.8.0 + * + * @global array $_ignore_site_logo_changes + */ +function _delete_site_logo_on_remove_theme_mods() { + global $_ignore_site_logo_changes; + + if ( $_ignore_site_logo_changes ) { + return; + } + + if ( false !== get_theme_support( 'custom-logo' ) ) { + delete_option( 'site_logo' ); + } +} + +/** + * Hooks `_delete_site_logo_on_remove_custom_logo` in `update_option_theme_mods_$theme`. + * Hooks `_delete_site_logo_on_remove_theme_mods` in `delete_option_theme_mods_$theme`. + * + * Runs on `setup_theme` to account for dynamically-switched themes in the Customizer. + * + * @since 5.8.0 + */ +function _delete_site_logo_on_remove_custom_logo_on_setup_theme() { + $theme = get_option( 'stylesheet' ); + add_action( "update_option_theme_mods_$theme", '_delete_site_logo_on_remove_custom_logo', 10, 2 ); + add_action( "delete_option_theme_mods_$theme", '_delete_site_logo_on_remove_theme_mods' ); +} +add_action( 'setup_theme', '_delete_site_logo_on_remove_custom_logo_on_setup_theme', 11 ); + +/** + * Removes the custom_logo theme-mod when the site_logo option gets deleted. + * + * @since 5.9.0 + * + * @global array $_ignore_site_logo_changes + */ +function _delete_custom_logo_on_remove_site_logo() { + global $_ignore_site_logo_changes; + + // Prevent _delete_site_logo_on_remove_custom_logo and + // _delete_site_logo_on_remove_theme_mods from firing and causing an + // infinite loop. + $_ignore_site_logo_changes = true; + + // Remove the custom logo. + remove_theme_mod( 'custom_logo' ); + + $_ignore_site_logo_changes = false; +} +add_action( 'delete_option_site_logo', '_delete_custom_logo_on_remove_site_logo' ); diff --git a/src/wp-includes/blocks/site-logo/block.json b/src/wp-includes/blocks/site-logo/block.json new file mode 100644 index 0000000000000..b49588d3716fa --- /dev/null +++ b/src/wp-includes/blocks/site-logo/block.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/site-logo", + "title": "Site Logo", + "category": "theme", + "description": "Display an image to represent this site. Update this block and the changes apply everywhere.", + "textdomain": "default", + "attributes": { + "width": { + "type": "number" + }, + "isLink": { + "type": "boolean", + "default": true, + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + }, + "shouldSyncIcon": { + "type": "boolean" + } + }, + "example": { + "viewportWidth": 500, + "attributes": { + "width": 350, + "className": "block-editor-block-types-list__site-logo-example" + } + }, + "supports": { + "html": false, + "align": true, + "alignWide": false, + "color": { + "text": false, + "background": false + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "interactivity": { + "clientNavigation": true + }, + "filter": { + "duotone": true + } + }, + "styles": [ + { + "name": "default", + "label": "Default", + "isDefault": true + }, + { "name": "rounded", "label": "Rounded" } + ], + "selectors": { + "filter": { + "duotone": ".wp-block-site-logo img, .wp-block-site-logo .components-placeholder__illustration, .wp-block-site-logo .components-placeholder::before" + } + }, + "editorStyle": "wp-block-site-logo-editor", + "style": "wp-block-site-logo" +} diff --git a/src/wp-includes/blocks/site-tagline.php b/src/wp-includes/blocks/site-tagline.php new file mode 100644 index 0000000000000..b59e1e556c320 --- /dev/null +++ b/src/wp-includes/blocks/site-tagline.php @@ -0,0 +1,53 @@ + $align_class_name ) ); + + if ( isset( $attributes['level'] ) && 0 !== $attributes['level'] ) { + $tag_name = 'h' . (int) $attributes['level']; + } + + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + $site_tagline + ); +} + +/** + * Registers the `core/site-tagline` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_site_tagline() { + register_block_type_from_metadata( + __DIR__ . '/site-tagline', + array( + 'render_callback' => 'render_block_core_site_tagline', + ) + ); +} + +add_action( 'init', 'register_block_core_site_tagline' ); diff --git a/src/wp-includes/blocks/site-tagline/block.json b/src/wp-includes/blocks/site-tagline/block.json new file mode 100644 index 0000000000000..7f94d962e9cbc --- /dev/null +++ b/src/wp-includes/blocks/site-tagline/block.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/site-tagline", + "title": "Site Tagline", + "category": "theme", + "description": "Describe in a few words what this site is about. This is important for search results, sharing on social media, and gives overall clarity to visitors.", + "keywords": [ "description" ], + "textdomain": "default", + "attributes": { + "textAlign": { + "type": "string" + }, + "level": { + "type": "number", + "default": 0 + }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] + } + }, + "example": { + "viewportWidth": 350, + "attributes": { + "textAlign": "center" + } + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "contentRole": true, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalWritingMode": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "editorStyle": "wp-block-site-tagline-editor", + "style": "wp-block-site-tagline" +} diff --git a/src/wp-includes/blocks/site-title.php b/src/wp-includes/blocks/site-title.php new file mode 100644 index 0000000000000..297d99894e104 --- /dev/null +++ b/src/wp-includes/blocks/site-title.php @@ -0,0 +1,69 @@ +%4$s', + esc_url( home_url() ), + esc_attr( $link_target ), + $aria_current, + esc_html( $site_title ) + ); + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( $classes ) ) ); + + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + // already pre-escaped if it is a link. + $attributes['isLink'] ? $site_title : esc_html( $site_title ) + ); +} + +/** + * Registers the `core/site-title` block on the server. + * + * @since 5.8.0 + */ +function register_block_core_site_title() { + register_block_type_from_metadata( + __DIR__ . '/site-title', + array( + 'render_callback' => 'render_block_core_site_title', + ) + ); +} +add_action( 'init', 'register_block_core_site_title' ); diff --git a/src/wp-includes/blocks/site-title/block.json b/src/wp-includes/blocks/site-title/block.json new file mode 100644 index 0000000000000..8edf6b945f9ce --- /dev/null +++ b/src/wp-includes/blocks/site-title/block.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/site-title", + "title": "Site Title", + "category": "theme", + "description": "Displays the name of this site. Update the block, and the changes apply everywhere it’s used. This will also appear in the browser title bar and in search results.", + "textdomain": "default", + "attributes": { + "level": { + "type": "number", + "default": 1 + }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] + }, + "textAlign": { + "type": "string" + }, + "isLink": { + "type": "boolean", + "default": true, + "role": "content" + }, + "linkTarget": { + "type": "string", + "default": "_self", + "role": "content" + } + }, + "example": { + "viewportWidth": 500 + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalWritingMode": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "editorStyle": "wp-block-site-title-editor", + "style": "wp-block-site-title" +} diff --git a/src/wp-includes/blocks/social-link.php b/src/wp-includes/blocks/social-link.php new file mode 100644 index 0000000000000..3673504bc9396 --- /dev/null +++ b/src/wp-includes/blocks/social-link.php @@ -0,0 +1,408 @@ +context['openInNewTab'] ) ? $block->context['openInNewTab'] : false; + + $text = ! empty( $attributes['label'] ) ? trim( $attributes['label'] ) : ''; + + $service = isset( $attributes['service'] ) ? $attributes['service'] : 'Icon'; + $url = isset( $attributes['url'] ) ? $attributes['url'] : false; + $text = $text ? $text : block_core_social_link_get_name( $service ); + $rel = isset( $attributes['rel'] ) ? $attributes['rel'] : ''; + $show_labels = array_key_exists( 'showLabels', $block->context ) ? $block->context['showLabels'] : false; + + // Don't render a link if there is no URL set. + if ( ! $url ) { + return ''; + } + + /** + * Prepend emails with `mailto:` if not set. + * The `is_email` returns false for emails with schema. + */ + if ( is_email( $url ) ) { + $url = 'mailto:' . antispambot( $url ); + } + + /** + * Prepend URL with https:// if it doesn't appear to contain a scheme + * and it's not a relative link or a fragment. + */ + if ( ! parse_url( $url, PHP_URL_SCHEME ) && ! str_starts_with( $url, '//' ) && ! str_starts_with( $url, '#' ) ) { + $url = 'https://' . $url; + } + + $icon = block_core_social_link_get_icon( $service ); + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => 'wp-social-link wp-social-link-' . $service . block_core_social_link_get_color_classes( $block->context ), + 'style' => block_core_social_link_get_color_styles( $block->context ), + ) + ); + + $link = '
    8. '; + $link .= ''; + $link .= $icon; + $link .= '' . esc_html( $text ) . ''; + $link .= '
    9. '; + + $processor = new WP_HTML_Tag_Processor( $link ); + $processor->next_tag( 'a' ); + if ( $open_in_new_tab ) { + $processor->set_attribute( 'rel', trim( $rel . ' noopener nofollow' ) ); + $processor->set_attribute( 'target', '_blank' ); + } elseif ( '' !== $rel ) { + $processor->set_attribute( 'rel', trim( $rel ) ); + } + return $processor->get_updated_html(); +} + +/** + * Registers the `core/social-link` blocks. + * + * @since 5.4.0 + */ +function register_block_core_social_link() { + register_block_type_from_metadata( + __DIR__ . '/social-link', + array( + 'render_callback' => 'render_block_core_social_link', + ) + ); +} +add_action( 'init', 'register_block_core_social_link' ); + + +/** + * Returns the SVG for social link. + * + * @since 5.4.0 + * + * @param string $service The service icon. + * + * @return string SVG Element for service icon. + */ +function block_core_social_link_get_icon( $service ) { + $services = block_core_social_link_services(); + if ( isset( $services[ $service ] ) && isset( $services[ $service ]['icon'] ) ) { + return $services[ $service ]['icon']; + } + + return $services['share']['icon']; +} + +/** + * Returns the brand name for social link. + * + * @since 5.4.0 + * + * @param string $service The service icon. + * + * @return string Brand label. + */ +function block_core_social_link_get_name( $service ) { + $services = block_core_social_link_services(); + if ( isset( $services[ $service ] ) && isset( $services[ $service ]['name'] ) ) { + return $services[ $service ]['name']; + } + + return $services['share']['name']; +} + +/** + * Returns the SVG for social link. + * + * @since 5.4.0 + * + * @param string $service The service slug to extract data from. + * @param string $field The field ('name', 'icon', etc) to extract for a service. + * + * @return array|string + */ +function block_core_social_link_services( $service = '', $field = '' ) { + $services_data = array( + 'fivehundredpx' => array( + 'name' => _x( '500px', 'social link block variation name' ), + 'icon' => '', + ), + 'amazon' => array( + 'name' => _x( 'Amazon', 'social link block variation name' ), + 'icon' => '', + ), + 'bandcamp' => array( + 'name' => _x( 'Bandcamp', 'social link block variation name' ), + 'icon' => '', + ), + 'behance' => array( + 'name' => _x( 'Behance', 'social link block variation name' ), + 'icon' => '', + ), + 'bluesky' => array( + 'name' => _x( 'Bluesky', 'social link block variation name' ), + 'icon' => '', + ), + 'chain' => array( + 'name' => _x( 'Link', 'social link block variation name' ), + 'icon' => '', + ), + 'codepen' => array( + 'name' => _x( 'CodePen', 'social link block variation name' ), + 'icon' => '', + ), + 'deviantart' => array( + 'name' => _x( 'DeviantArt', 'social link block variation name' ), + 'icon' => '', + ), + 'discord' => array( + 'name' => _x( 'Discord', 'social link block variation name' ), + 'icon' => '', + ), + 'dribbble' => array( + 'name' => _x( 'Dribbble', 'social link block variation name' ), + 'icon' => '', + ), + 'dropbox' => array( + 'name' => _x( 'Dropbox', 'social link block variation name' ), + 'icon' => '', + ), + 'etsy' => array( + 'name' => _x( 'Etsy', 'social link block variation name' ), + 'icon' => '', + ), + 'facebook' => array( + 'name' => _x( 'Facebook', 'social link block variation name' ), + 'icon' => '', + ), + 'feed' => array( + 'name' => _x( 'RSS Feed', 'social link block variation name' ), + 'icon' => '', + ), + 'flickr' => array( + 'name' => _x( 'Flickr', 'social link block variation name' ), + 'icon' => '', + ), + 'foursquare' => array( + 'name' => _x( 'Foursquare', 'social link block variation name' ), + 'icon' => '', + ), + 'goodreads' => array( + 'name' => _x( 'Goodreads', 'social link block variation name' ), + 'icon' => '', + ), + 'google' => array( + 'name' => _x( 'Google', 'social link block variation name' ), + 'icon' => '', + ), + 'github' => array( + 'name' => _x( 'GitHub', 'social link block variation name' ), + 'icon' => '', + ), + 'gravatar' => array( + 'name' => _x( 'Gravatar', 'social link block variation name' ), + 'icon' => '', + ), + 'instagram' => array( + 'name' => _x( 'Instagram', 'social link block variation name' ), + 'icon' => '', + ), + 'lastfm' => array( + 'name' => _x( 'Last.fm', 'social link block variation name' ), + 'icon' => '', + ), + 'linkedin' => array( + 'name' => _x( 'LinkedIn', 'social link block variation name' ), + 'icon' => '', + ), + 'mail' => array( + 'name' => _x( 'Mail', 'social link block variation name' ), + 'icon' => '', + ), + 'mastodon' => array( + 'name' => _x( 'Mastodon', 'social link block variation name' ), + 'icon' => '', + ), + 'meetup' => array( + 'name' => _x( 'Meetup', 'social link block variation name' ), + 'icon' => '', + ), + 'medium' => array( + 'name' => _x( 'Medium', 'social link block variation name' ), + 'icon' => '', + ), + 'patreon' => array( + 'name' => _x( 'Patreon', 'social link block variation name' ), + 'icon' => '', + ), + 'pinterest' => array( + 'name' => _x( 'Pinterest', 'social link block variation name' ), + 'icon' => '', + ), + 'pocket' => array( + 'name' => _x( 'Pocket', 'social link block variation name' ), + 'icon' => '', + ), + 'reddit' => array( + 'name' => _x( 'Reddit', 'social link block variation name' ), + 'icon' => '', + ), + 'share' => array( + 'name' => _x( 'Share Icon', 'social link block variation name' ), + 'icon' => '', + ), + 'skype' => array( + 'name' => _x( 'Skype', 'social link block variation name' ), + 'icon' => '', + ), + 'snapchat' => array( + 'name' => _x( 'Snapchat', 'social link block variation name' ), + 'icon' => '', + ), + 'soundcloud' => array( + 'name' => _x( 'SoundCloud', 'social link block variation name' ), + 'icon' => '', + ), + 'spotify' => array( + 'name' => _x( 'Spotify', 'social link block variation name' ), + 'icon' => '', + ), + 'telegram' => array( + 'name' => _x( 'Telegram', 'social link block variation name' ), + 'icon' => '', + ), + 'threads' => array( + 'name' => _x( 'Threads', 'social link block variation name' ), + 'icon' => '', + ), + 'tiktok' => array( + 'name' => _x( 'TikTok', 'social link block variation name' ), + 'icon' => '', + ), + 'tumblr' => array( + 'name' => _x( 'Tumblr', 'social link block variation name' ), + 'icon' => '', + ), + 'twitch' => array( + 'name' => _x( 'Twitch', 'social link block variation name' ), + 'icon' => '', + ), + 'twitter' => array( + 'name' => _x( 'Twitter', 'social link block variation name' ), + 'icon' => '', + ), + 'vimeo' => array( + 'name' => _x( 'Vimeo', 'social link block variation name' ), + 'icon' => '', + ), + 'vk' => array( + 'name' => _x( 'VK', 'social link block variation name' ), + 'icon' => '', + ), + 'wordpress' => array( + 'name' => _x( 'WordPress', 'social link block variation name' ), + 'icon' => '', + ), + 'whatsapp' => array( + 'name' => _x( 'WhatsApp', 'social link block variation name' ), + 'icon' => '', + ), + 'x' => array( + 'name' => _x( 'X', 'social link block variation name' ), + 'icon' => '', + ), + 'yelp' => array( + 'name' => _x( 'Yelp', 'social link block variation name' ), + 'icon' => '', + ), + 'youtube' => array( + 'name' => _x( 'YouTube', 'social link block variation name' ), + 'icon' => '', + ), + ); + + /** + * Filter the list of available social service. + * + * This can be used to change icons or add custom icons (additionally to variations in the editor). + * Icons should be directly renderable - therefore SVGs work best. + * + * @since 6.9.0 + * + * @param array $services_data The list of services. Each item is an array containing a 'name' and 'icon' key. + * @return array The list of social services. + */ + $services_data = apply_filters( 'block_core_social_link_get_services', $services_data ); + + if ( ! empty( $service ) + && ! empty( $field ) + && isset( $services_data[ $service ] ) + && ( 'icon' === $field || 'name' === $field ) + ) { + return $services_data[ $service ][ $field ]; + } elseif ( ! empty( $service ) && isset( $services_data[ $service ] ) ) { + return $services_data[ $service ]; + } + + return $services_data; +} + +/** + * Returns CSS styles for icon and icon background colors. + * + * @since 5.7.0 + * + * @param array $context Block context passed to Social Link. + * + * @return string Inline CSS styles for link's icon and background colors. + */ +function block_core_social_link_get_color_styles( $context ) { + $styles = array(); + + if ( array_key_exists( 'iconColorValue', $context ) ) { + $styles[] = 'color:' . $context['iconColorValue'] . ';'; + } + + if ( array_key_exists( 'iconBackgroundColorValue', $context ) ) { + $styles[] = 'background-color:' . $context['iconBackgroundColorValue'] . ';'; + } + + return implode( '', $styles ); +} + +/** + * Returns CSS classes for icon and icon background colors. + * + * @since 6.3.0 + * + * @param array $context Block context passed to Social Sharing Link. + * + * @return string CSS classes for link's icon and background colors. + */ +function block_core_social_link_get_color_classes( $context ) { + $classes = array(); + + if ( array_key_exists( 'iconColor', $context ) ) { + $classes[] = 'has-' . $context['iconColor'] . '-color'; + } + + if ( array_key_exists( 'iconBackgroundColor', $context ) ) { + $classes[] = 'has-' . $context['iconBackgroundColor'] . '-background-color'; + } + + return ' ' . implode( ' ', $classes ); +} diff --git a/src/wp-includes/blocks/social-link/block.json b/src/wp-includes/blocks/social-link/block.json new file mode 100644 index 0000000000000..667fd74b208f2 --- /dev/null +++ b/src/wp-includes/blocks/social-link/block.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/social-link", + "title": "Social Icon", + "category": "widgets", + "parent": [ "core/social-links" ], + "description": "Display an icon linking to a social profile or site.", + "textdomain": "default", + "attributes": { + "url": { + "type": "string", + "role": "content" + }, + "service": { + "type": "string" + }, + "label": { + "type": "string", + "role": "content" + }, + "rel": { + "type": "string" + } + }, + "usesContext": [ + "openInNewTab", + "showLabels", + "iconColor", + "iconColorValue", + "iconBackgroundColor", + "iconBackgroundColorValue" + ], + "supports": { + "reusable": false, + "html": false, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-social-link-editor" +} diff --git a/src/wp-includes/blocks/social-links/block.json b/src/wp-includes/blocks/social-links/block.json new file mode 100644 index 0000000000000..8caa8f5bf8abb --- /dev/null +++ b/src/wp-includes/blocks/social-links/block.json @@ -0,0 +1,107 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/social-links", + "title": "Social Icons", + "category": "widgets", + "allowedBlocks": [ "core/social-link" ], + "description": "Display icons linking to your social profiles or sites.", + "keywords": [ "links" ], + "textdomain": "default", + "attributes": { + "iconColor": { + "type": "string" + }, + "customIconColor": { + "type": "string" + }, + "iconColorValue": { + "type": "string" + }, + "iconBackgroundColor": { + "type": "string" + }, + "customIconBackgroundColor": { + "type": "string" + }, + "iconBackgroundColorValue": { + "type": "string" + }, + "openInNewTab": { + "type": "boolean", + "default": false + }, + "showLabels": { + "type": "boolean", + "default": false + }, + "size": { + "type": "string" + } + }, + "providesContext": { + "openInNewTab": "openInNewTab", + "showLabels": "showLabels", + "iconColor": "iconColor", + "iconColorValue": "iconColorValue", + "iconBackgroundColor": "iconBackgroundColor", + "iconBackgroundColorValue": "iconBackgroundColorValue" + }, + "supports": { + "align": [ "left", "center", "right" ], + "anchor": true, + "html": false, + "__experimentalExposeControlsToChildren": true, + "layout": { + "allowSwitching": false, + "allowInheriting": false, + "allowVerticalAlignment": false, + "default": { + "type": "flex" + } + }, + "color": { + "enableContrastChecker": false, + "background": true, + "gradients": true, + "text": false, + "__experimentalDefaultControls": { + "background": false + } + }, + "spacing": { + "blockGap": [ "horizontal", "vertical" ], + "margin": true, + "padding": true, + "units": [ "px", "em", "rem", "vh", "vw" ], + "__experimentalDefaultControls": { + "blockGap": true, + "margin": true, + "padding": false + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "contentRole": true + }, + "styles": [ + { "name": "default", "label": "Default", "isDefault": true }, + { "name": "logos-only", "label": "Logos Only" }, + { "name": "pill-shape", "label": "Pill Shape" } + ], + "editorStyle": "wp-block-social-links-editor", + "style": "wp-block-social-links" +} diff --git a/src/wp-includes/blocks/spacer/block.json b/src/wp-includes/blocks/spacer/block.json new file mode 100644 index 0000000000000..447ea99cc0b67 --- /dev/null +++ b/src/wp-includes/blocks/spacer/block.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/spacer", + "title": "Spacer", + "category": "design", + "description": "Add white space between blocks and customize its height.", + "textdomain": "default", + "attributes": { + "height": { + "type": "string", + "default": "100px" + }, + "width": { + "type": "string" + } + }, + "usesContext": [ "orientation" ], + "supports": { + "anchor": true, + "spacing": { + "margin": [ "top", "bottom" ], + "__experimentalDefaultControls": { + "margin": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-spacer-editor", + "style": "wp-block-spacer" +} diff --git a/src/wp-includes/blocks/table/block.json b/src/wp-includes/blocks/table/block.json new file mode 100644 index 0000000000000..84f2783d3ff8c --- /dev/null +++ b/src/wp-includes/blocks/table/block.json @@ -0,0 +1,220 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/table", + "title": "Table", + "category": "text", + "description": "Create structured content in rows and columns to display information.", + "textdomain": "default", + "attributes": { + "hasFixedLayout": { + "type": "boolean", + "default": true + }, + "caption": { + "type": "rich-text", + "source": "rich-text", + "selector": "figcaption", + "role": "content" + }, + "head": { + "type": "array", + "default": [], + "source": "query", + "selector": "thead tr", + "query": { + "cells": { + "type": "array", + "default": [], + "source": "query", + "selector": "td,th", + "query": { + "content": { + "type": "rich-text", + "source": "rich-text", + "role": "content" + }, + "tag": { + "type": "string", + "default": "td", + "source": "tag" + }, + "scope": { + "type": "string", + "source": "attribute", + "attribute": "scope" + }, + "align": { + "type": "string", + "source": "attribute", + "attribute": "data-align" + }, + "colspan": { + "type": "string", + "source": "attribute", + "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" + } + } + } + } + }, + "body": { + "type": "array", + "default": [], + "source": "query", + "selector": "tbody tr", + "query": { + "cells": { + "type": "array", + "default": [], + "source": "query", + "selector": "td,th", + "query": { + "content": { + "type": "rich-text", + "source": "rich-text", + "role": "content" + }, + "tag": { + "type": "string", + "default": "td", + "source": "tag" + }, + "scope": { + "type": "string", + "source": "attribute", + "attribute": "scope" + }, + "align": { + "type": "string", + "source": "attribute", + "attribute": "data-align" + }, + "colspan": { + "type": "string", + "source": "attribute", + "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" + } + } + } + } + }, + "foot": { + "type": "array", + "default": [], + "source": "query", + "selector": "tfoot tr", + "query": { + "cells": { + "type": "array", + "default": [], + "source": "query", + "selector": "td,th", + "query": { + "content": { + "type": "rich-text", + "source": "rich-text", + "role": "content" + }, + "tag": { + "type": "string", + "default": "td", + "source": "tag" + }, + "scope": { + "type": "string", + "source": "attribute", + "attribute": "scope" + }, + "align": { + "type": "string", + "source": "attribute", + "attribute": "data-align" + }, + "colspan": { + "type": "string", + "source": "attribute", + "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" + } + } + } + } + } + }, + "supports": { + "anchor": true, + "align": true, + "color": { + "__experimentalSkipSerialization": true, + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "__experimentalBorder": { + "__experimentalSkipSerialization": true, + "color": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": true, + "style": true, + "width": true + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "selectors": { + "root": ".wp-block-table > table", + "spacing": ".wp-block-table" + }, + "styles": [ + { + "name": "regular", + "label": "Default", + "isDefault": true + }, + { "name": "stripes", "label": "Stripes" } + ], + "editorStyle": "wp-block-table-editor", + "style": "wp-block-table" +} diff --git a/src/wp-includes/blocks/tag-cloud.php b/src/wp-includes/blocks/tag-cloud.php new file mode 100644 index 0000000000000..8949dd8e5b11f --- /dev/null +++ b/src/wp-includes/blocks/tag-cloud.php @@ -0,0 +1,63 @@ +[a-z%]+)$/i', $smallest_font_size, $m ) ? $m['unit'] : 'pt' ); + + $args = array( + 'echo' => false, + 'unit' => $unit, + 'taxonomy' => $attributes['taxonomy'], + 'show_count' => $attributes['showTagCounts'], + 'number' => $attributes['numberOfTags'], + 'smallest' => floatVal( $attributes['smallestFontSize'] ), + 'largest' => floatVal( $attributes['largestFontSize'] ), + ); + $tag_cloud = wp_tag_cloud( $args ); + + if ( empty( $tag_cloud ) ) { + // Display placeholder content when there are no tags only in editor. + if ( wp_is_serving_rest_request() ) { + $tag_cloud = __( 'There’s no content to show here yet.' ); + } else { + return ''; + } + } + + $wrapper_attributes = get_block_wrapper_attributes(); + + return sprintf( + '

      %2$s

      ', + $wrapper_attributes, + $tag_cloud + ); +} + +/** + * Registers the `core/tag-cloud` block on server. + * + * @since 5.2.0 + */ +function register_block_core_tag_cloud() { + register_block_type_from_metadata( + __DIR__ . '/tag-cloud', + array( + 'render_callback' => 'render_block_core_tag_cloud', + ) + ); +} +add_action( 'init', 'register_block_core_tag_cloud' ); diff --git a/src/wp-includes/blocks/tag-cloud/block.json b/src/wp-includes/blocks/tag-cloud/block.json new file mode 100644 index 0000000000000..044bc0c533376 --- /dev/null +++ b/src/wp-includes/blocks/tag-cloud/block.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/tag-cloud", + "title": "Tag Cloud", + "category": "widgets", + "description": "A cloud of popular keywords, each sized by how often it appears.", + "textdomain": "default", + "attributes": { + "numberOfTags": { + "type": "number", + "default": 45, + "minimum": 1, + "maximum": 100 + }, + "taxonomy": { + "type": "string", + "default": "post_tag" + }, + "showTagCounts": { + "type": "boolean", + "default": false + }, + "smallestFontSize": { + "type": "string", + "default": "8pt" + }, + "largestFontSize": { + "type": "string", + "default": "22pt" + } + }, + "styles": [ + { "name": "default", "label": "Default", "isDefault": true }, + { "name": "outline", "label": "Outline" } + ], + "supports": { + "html": false, + "align": true, + "spacing": { + "margin": true, + "padding": true + }, + "typography": { + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalLetterSpacing": true + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + }, + "editorStyle": "wp-block-tag-cloud-editor" +} diff --git a/src/wp-includes/blocks/template-part.php b/src/wp-includes/blocks/template-part.php new file mode 100644 index 0000000000000..c73b64408733d --- /dev/null +++ b/src/wp-includes/blocks/template-part.php @@ -0,0 +1,303 @@ + 'wp_template_part', + 'post_status' => 'publish', + 'post_name__in' => array( $attributes['slug'] ), + 'tax_query' => array( + array( + 'taxonomy' => 'wp_theme', + 'field' => 'name', + 'terms' => $theme, + ), + ), + 'posts_per_page' => 1, + 'no_found_rows' => true, + 'lazy_load_term_meta' => false, // Do not lazy load term meta, as template parts only have one term. + ) + ); + $template_part_post = $template_part_query->have_posts() ? $template_part_query->next_post() : null; + if ( $template_part_post ) { + // A published post might already exist if this template part was customized elsewhere + // or if it's part of a customized template. + $block_template = _build_block_template_result_from_post( $template_part_post ); + $content = $block_template->content; + if ( isset( $block_template->area ) ) { + $area = $block_template->area; + } + /** + * Fires when a block template part is loaded from a template post stored in the database. + * + * @since 5.9.0 + * + * @param string $template_part_id The requested template part namespaced to the theme. + * @param array $attributes The block attributes. + * @param WP_Post $template_part_post The template part post object. + * @param string $content The template part content. + */ + do_action( 'render_block_core_template_part_post', $template_part_id, $attributes, $template_part_post, $content ); + } else { + $template_part_file_path = ''; + // Else, if the template part was provided by the active theme, + // render the corresponding file content. + if ( 0 === validate_file( $attributes['slug'] ) ) { + $block_template = get_block_file_template( $template_part_id, 'wp_template_part' ); + + if ( isset( $block_template->content ) ) { + $content = $block_template->content; + } + if ( isset( $block_template->area ) ) { + $area = $block_template->area; + } + + // Needed for the `render_block_core_template_part_file` and `render_block_core_template_part_none` actions below. + $block_template_file = _get_block_template_file( 'wp_template_part', $attributes['slug'] ); + if ( $block_template_file ) { + $template_part_file_path = $block_template_file['path']; + } + } + + if ( '' !== $content && null !== $content ) { + /** + * Fires when a block template part is loaded from a template part in the theme. + * + * @since 5.9.0 + * + * @param string $template_part_id The requested template part namespaced to the theme. + * @param array $attributes The block attributes. + * @param string $template_part_file_path Absolute path to the template path. + * @param string $content The template part content. + */ + do_action( 'render_block_core_template_part_file', $template_part_id, $attributes, $template_part_file_path, $content ); + } else { + /** + * Fires when a requested block template part does not exist in the database nor in the theme. + * + * @since 5.9.0 + * + * @param string $template_part_id The requested template part namespaced to the theme. + * @param array $attributes The block attributes. + * @param string $template_part_file_path Absolute path to the not found template path. + */ + do_action( 'render_block_core_template_part_none', $template_part_id, $attributes, $template_part_file_path ); + } + } + } + + // WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent + // is set in `wp_debug_mode()`. + $is_debug = WP_DEBUG && WP_DEBUG_DISPLAY; + + if ( is_null( $content ) ) { + if ( $is_debug && isset( $attributes['slug'] ) ) { + return sprintf( + /* translators: %s: Template part slug. */ + __( 'Template part has been deleted or is unavailable: %s' ), + $attributes['slug'] + ); + } + + return ''; + } + + if ( isset( $seen_ids[ $template_part_id ] ) ) { + return $is_debug ? + // translators: Visible only in the front end, this warning takes the place of a faulty block. + __( '[block rendering halted]' ) : + ''; + } + + // Look up area definition. + $area_definition = null; + $defined_areas = get_allowed_block_template_part_areas(); + foreach ( $defined_areas as $defined_area ) { + if ( $defined_area['area'] === $area ) { + $area_definition = $defined_area; + break; + } + } + + // If $area is not allowed, set it back to the uncategorized default. + if ( ! $area_definition ) { + $area = WP_TEMPLATE_PART_AREA_UNCATEGORIZED; + } + + // Run through the actions that are typically taken on the_content. + $content = shortcode_unautop( $content ); + $content = do_shortcode( $content ); + $seen_ids[ $template_part_id ] = true; + $content = do_blocks( $content ); + unset( $seen_ids[ $template_part_id ] ); + $content = wptexturize( $content ); + $content = convert_smilies( $content ); + $content = wp_filter_content_tags( $content, "template_part_{$area}" ); + + // Handle embeds for block template parts. + global $wp_embed; + $content = $wp_embed->autoembed( $content ); + + if ( empty( $attributes['tagName'] ) || tag_escape( $attributes['tagName'] ) !== $attributes['tagName'] ) { + $area_tag = 'div'; + if ( $area_definition && isset( $area_definition['area_tag'] ) ) { + $area_tag = $area_definition['area_tag']; + } + $html_tag = $area_tag; + } else { + $html_tag = esc_attr( $attributes['tagName'] ); + } + $wrapper_attributes = get_block_wrapper_attributes(); + + return "<$html_tag $wrapper_attributes>" . str_replace( ']]>', ']]>', $content ) . ""; +} + +/** + * Returns an array of area variation objects for the template part block. + * + * @since 6.1.0 + * + * @param array $instance_variations The variations for instances. + * + * @return array Array containing the block variation objects. + */ +function build_template_part_block_area_variations( $instance_variations ) { + $variations = array(); + $defined_areas = get_allowed_block_template_part_areas(); + + foreach ( $defined_areas as $area ) { + if ( 'uncategorized' !== $area['area'] ) { + $has_instance_for_area = false; + foreach ( $instance_variations as $variation ) { + if ( $variation['attributes']['area'] === $area['area'] ) { + $has_instance_for_area = true; + break; + } + } + + $scope = $has_instance_for_area ? array() : array( 'inserter' ); + + $variations[] = array( + 'name' => 'area_' . $area['area'], + 'title' => $area['label'], + 'description' => $area['description'], + 'attributes' => array( + 'area' => $area['area'], + ), + 'scope' => $scope, + 'icon' => $area['icon'], + ); + } + } + return $variations; +} + +/** + * Returns an array of instance variation objects for the template part block + * + * @since 6.1.0 + * + * @return array Array containing the block variation objects. + */ +function build_template_part_block_instance_variations() { + // Block themes are unavailable during installation. + if ( wp_installing() ) { + return array(); + } + + if ( ! current_theme_supports( 'block-templates' ) && ! current_theme_supports( 'block-template-parts' ) ) { + return array(); + } + + $variations = array(); + $template_parts = get_block_templates( + array( + 'post_type' => 'wp_template_part', + ), + 'wp_template_part' + ); + + $defined_areas = get_allowed_block_template_part_areas(); + $icon_by_area = array_combine( array_column( $defined_areas, 'area' ), array_column( $defined_areas, 'icon' ) ); + + foreach ( $template_parts as $template_part ) { + $variations[] = array( + 'name' => 'instance_' . sanitize_title( $template_part->slug ), + 'title' => $template_part->title, + // If there's no description for the template part don't show the + // block description. This is a bit hacky, but prevent the fallback + // by using a non-breaking space so that the value of description + // isn't falsey. + 'description' => $template_part->description || ' ', + 'attributes' => array( + 'slug' => $template_part->slug, + 'theme' => $template_part->theme, + 'area' => $template_part->area, + ), + 'scope' => array( 'inserter' ), + 'icon' => isset( $icon_by_area[ $template_part->area ] ) ? $icon_by_area[ $template_part->area ] : null, + 'example' => array( + 'attributes' => array( + 'slug' => $template_part->slug, + 'theme' => $template_part->theme, + 'area' => $template_part->area, + ), + ), + ); + } + return $variations; +} + +/** + * Returns an array of all template part block variations. + * + * @since 5.9.0 + * + * @return array Array containing the block variation objects. + */ +function build_template_part_block_variations() { + $instance_variations = build_template_part_block_instance_variations(); + $area_variations = build_template_part_block_area_variations( $instance_variations ); + return array_merge( $area_variations, $instance_variations ); +} + +/** + * Registers the `core/template-part` block on the server. + * + * @since 5.9.0 + */ +function register_block_core_template_part() { + register_block_type_from_metadata( + __DIR__ . '/template-part', + array( + 'render_callback' => 'render_block_core_template_part', + 'variation_callback' => 'build_template_part_block_variations', + ) + ); +} +add_action( 'init', 'register_block_core_template_part' ); diff --git a/src/wp-includes/blocks/template-part/block.json b/src/wp-includes/blocks/template-part/block.json new file mode 100644 index 0000000000000..9710bdeee2e53 --- /dev/null +++ b/src/wp-includes/blocks/template-part/block.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/template-part", + "title": "Template Part", + "category": "theme", + "description": "Edit the different global regions of your site, like the header, footer, sidebar, or create your own.", + "textdomain": "default", + "attributes": { + "slug": { + "type": "string" + }, + "theme": { + "type": "string" + }, + "tagName": { + "type": "string" + }, + "area": { + "type": "string" + } + }, + "supports": { + "align": true, + "html": false, + "reusable": false, + "renaming": false, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-template-part-editor" +} diff --git a/src/wp-includes/blocks/term-count.php b/src/wp-includes/blocks/term-count.php new file mode 100644 index 0000000000000..9794896524eb4 --- /dev/null +++ b/src/wp-includes/blocks/term-count.php @@ -0,0 +1,80 @@ +context['termId'] ) && isset( $block->context['taxonomy'] ) ) { + $term = get_term( $block->context['termId'], $block->context['taxonomy'] ); + } else { + $term = get_queried_object(); + if ( ! $term instanceof WP_Term ) { + $term = null; + } + } + + if ( ! $term || is_wp_error( $term ) ) { + return ''; + } + + $term_count = $term->count; + + // Format the term count based on bracket type. + switch ( $attributes['bracketType'] ) { + case 'none': + // No formatting needed. + break; + case 'round': + $term_count = "({$term_count})"; + break; + case 'square': + $term_count = "[{$term_count}]"; + break; + case 'curly': + $term_count = "{{$term_count}}"; + break; + case 'angle': + $term_count = "<{$term_count}>"; + break; + default: + // Default to no formatting for unknown types. + break; + } + + $wrapper_attributes = get_block_wrapper_attributes(); + + return sprintf( + '
      %2$s
      ', + $wrapper_attributes, + $term_count + ); +} + +/** + * Registers the `core/term-count` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_term_count() { + register_block_type_from_metadata( + __DIR__ . '/term-count', + array( + 'render_callback' => 'render_block_core_term_count', + ) + ); +} +add_action( 'init', 'register_block_core_term_count' ); diff --git a/src/wp-includes/blocks/term-count/block.json b/src/wp-includes/blocks/term-count/block.json new file mode 100644 index 0000000000000..c4de1e61f8d1f --- /dev/null +++ b/src/wp-includes/blocks/term-count/block.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/term-count", + "title": "Term Count", + "category": "theme", + "description": "Displays the post count of a taxonomy term.", + "textdomain": "default", + "usesContext": [ "termId", "taxonomy" ], + "attributes": { + "bracketType": { + "type": "string", + "enum": [ "none", "round", "square", "curly", "angle" ], + "default": "round" + } + }, + "supports": { + "html": false, + "color": { + "gradients": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-term-count" +} diff --git a/src/wp-includes/blocks/term-description.php b/src/wp-includes/blocks/term-description.php new file mode 100644 index 0000000000000..9f61dbba07fbc --- /dev/null +++ b/src/wp-includes/blocks/term-description.php @@ -0,0 +1,61 @@ +context['termId'] ) && isset( $block->context['taxonomy'] ) ) { + $term = get_term( $block->context['termId'], $block->context['taxonomy'] ); + if ( $term && ! is_wp_error( $term ) ) { + $term_description = $term->description; + } + } elseif ( is_category() || is_tag() || is_tax() ) { + $term_description = term_description(); + } + + if ( empty( $term_description ) ) { + return ''; + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return '
      ' . $term_description . '
      '; +} + +/** + * Registers the `core/term-description` block on the server. + * + * @since 5.9.0 + */ +function register_block_core_term_description() { + register_block_type_from_metadata( + __DIR__ . '/term-description', + array( + 'render_callback' => 'render_block_core_term_description', + ) + ); +} +add_action( 'init', 'register_block_core_term_description' ); diff --git a/src/wp-includes/blocks/term-description/block.json b/src/wp-includes/blocks/term-description/block.json new file mode 100644 index 0000000000000..a882625ad6f50 --- /dev/null +++ b/src/wp-includes/blocks/term-description/block.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/term-description", + "title": "Term Description", + "category": "theme", + "description": "Display the description of categories, tags and custom taxonomies when viewing an archive.", + "textdomain": "default", + "usesContext": [ "termId", "taxonomy" ], + "attributes": { + "textAlign": { + "type": "string" + } + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "padding": true, + "margin": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + } + } +} diff --git a/src/wp-includes/blocks/term-name.php b/src/wp-includes/blocks/term-name.php new file mode 100644 index 0000000000000..3a2bf18bb5f21 --- /dev/null +++ b/src/wp-includes/blocks/term-name.php @@ -0,0 +1,81 @@ +context['termId'] ) && isset( $block->context['taxonomy'] ) ) { + $term = get_term( $block->context['termId'], $block->context['taxonomy'] ); + } else { + $term = get_queried_object(); + if ( ! $term instanceof WP_Term ) { + $term = null; + } + } + + if ( ! $term || is_wp_error( $term ) ) { + return ''; + } + + $term_name = $term->name; + $level = isset( $attributes['level'] ) ? $attributes['level'] : 0; + $tag_name = 0 === $level ? 'p' : 'h' . (int) $level; + + if ( isset( $attributes['isLink'] ) && $attributes['isLink'] ) { + $term_link = get_term_link( $term ); + if ( ! is_wp_error( $term_link ) ) { + $term_name = sprintf( + '%2$s', + esc_url( $term_link ), + $term_name + ); + } + } + + $classes = array(); + if ( isset( $attributes['textAlign'] ) ) { + $classes[] = 'has-text-align-' . $attributes['textAlign']; + } + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classes[] = 'has-link-color'; + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) ); + + return sprintf( + '<%1$s %2$s>%3$s', + $tag_name, + $wrapper_attributes, + $term_name + ); +} + +/** + * Registers the `core/term-name` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_term_name() { + register_block_type_from_metadata( + __DIR__ . '/term-name', + array( + 'render_callback' => 'render_block_core_term_name', + ) + ); +} +add_action( 'init', 'register_block_core_term_name' ); diff --git a/src/wp-includes/blocks/term-name/block.json b/src/wp-includes/blocks/term-name/block.json new file mode 100644 index 0000000000000..29b0cbe22b77e --- /dev/null +++ b/src/wp-includes/blocks/term-name/block.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/term-name", + "title": "Term Name", + "category": "theme", + "description": "Displays the name of a taxonomy term.", + "keywords": [ "term title" ], + "textdomain": "default", + "usesContext": [ "termId", "taxonomy" ], + "attributes": { + "textAlign": { + "type": "string" + }, + "level": { + "type": "number", + "default": 0 + }, + "isLink": { + "type": "boolean", + "default": false + } + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, + "spacing": { + "padding": true + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "color": true, + "width": true, + "style": true + } + } + }, + "style": "wp-block-term-name" +} diff --git a/src/wp-includes/blocks/term-template.php b/src/wp-includes/blocks/term-template.php new file mode 100644 index 0000000000000..3cbe21f60c0d4 --- /dev/null +++ b/src/wp-includes/blocks/term-template.php @@ -0,0 +1,137 @@ +context ) || empty( $block->context['termQuery'] ) ) { + return ''; + } + + $query = $block->context['termQuery']; + + $query_args = array( + 'number' => $query['perPage'], + 'order' => $query['order'], + 'orderby' => $query['orderBy'], + 'hide_empty' => $query['hideEmpty'], + ); + + $inherit_query = isset( $query['inherit'] ) + && $query['inherit'] + && ( is_tax() || is_category() || is_tag() ); + + if ( $inherit_query ) { + // Get the current term and taxonomy from the queried object. + $queried_object = get_queried_object(); + + // For hierarchical taxonomies, show children of the current term. + // For non-hierarchical taxonomies, show all terms (don't set parent). + if ( is_taxonomy_hierarchical( $queried_object->taxonomy ) ) { + // If showNested is true, use child_of to include nested terms. + // Otherwise, use parent to show only direct children. + if ( ! empty( $query['showNested'] ) ) { + $query_args['child_of'] = $queried_object->term_id; + } else { + $query_args['parent'] = $queried_object->term_id; + } + } + $query_args['taxonomy'] = $queried_object->taxonomy; + } else { + // If not inheriting set `taxonomy` from the block attribute. + $query_args['taxonomy'] = $query['taxonomy']; + + // If we are including specific terms we ignore `showNested` argument. + if ( ! empty( $query['include'] ) ) { + $query_args['include'] = array_unique( array_map( 'intval', $query['include'] ) ); + $query_args['orderby'] = 'include'; + $query_args['order'] = 'asc'; + } elseif ( empty( $query['showNested'] ) ) { + // We set parent only when inheriting from the taxonomy archive context or not + // showing nested terms, otherwise nested terms are not displayed. + $query_args['parent'] = 0; + } + } + + $terms_query = new WP_Term_Query( $query_args ); + $terms = $terms_query->get_terms(); + + if ( ! $terms || is_wp_error( $terms ) ) { + return ''; + } + + $content = ''; + foreach ( $terms as $term ) { + // Get an instance of the current Term Template block. + $block_instance = $block->parsed_block; + + // Set the block name to one that does not correspond to an existing registered block. + // This ensures that for the inner instances of the Term Template block, we do not render any block supports. + $block_instance['blockName'] = 'core/null'; + + $term_id = $term->term_id; + $taxonomy = $term->taxonomy; + + $filter_block_context = static function ( $context ) use ( $term_id, $taxonomy ) { + $context['termId'] = $term_id; + $context['taxonomy'] = $taxonomy; + return $context; + }; + + // Use an early priority to so that other 'render_block_context' filters have access to the values. + add_filter( 'render_block_context', $filter_block_context, 1 ); + + // Render the inner blocks of the Term Template block with `dynamic` set to `false` to prevent calling + // `render_callback` and ensure that no wrapper markup is included. + $block_content = ( new WP_Block( $block_instance ) )->render( array( 'dynamic' => false ) ); + + remove_filter( 'render_block_context', $filter_block_context, 1 ); + + // Wrap the render inner blocks in a `li` element with the appropriate term classes. + $term_classes = "wp-block-term term-{$term->term_id} {$term->taxonomy} taxonomy-{$term->taxonomy}"; + + $content .= '
    10. ' . $block_content . '
    11. '; + } + + $classnames = ''; + + if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + $classnames .= 'has-link-color'; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( $classnames ) ) ); + + return sprintf( + '
        %s
      ', + $wrapper_attributes, + $content + ); +} + +/** + * Registers the `core/term-template` block on the server. + * + * @since 6.9.0 + */ +function register_block_core_term_template() { + register_block_type_from_metadata( + __DIR__ . '/term-template', + array( + 'render_callback' => 'render_block_core_term_template', + ) + ); +} +add_action( 'init', 'register_block_core_term_template' ); diff --git a/src/wp-includes/blocks/term-template/block.json b/src/wp-includes/blocks/term-template/block.json new file mode 100644 index 0000000000000..2f4b9838c71bd --- /dev/null +++ b/src/wp-includes/blocks/term-template/block.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/term-template", + "title": "Term Template", + "category": "theme", + "ancestor": [ "core/terms-query" ], + "description": "Contains the block elements used to render a taxonomy term, like the name, description, and more.", + "textdomain": "default", + "usesContext": [ "termQuery" ], + "supports": { + "reusable": false, + "html": false, + "align": [ "wide", "full" ], + "layout": true, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "blockGap": { + "__experimentalDefault": "1.25em" + }, + "__experimentalDefaultControls": { + "blockGap": true, + "padding": false, + "margin": false + } + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, + "style": "wp-block-term-template", + "editorStyle": "wp-block-term-template-editor" +} diff --git a/src/wp-includes/blocks/terms-query/block.json b/src/wp-includes/blocks/terms-query/block.json new file mode 100644 index 0000000000000..05b7a2c12e22f --- /dev/null +++ b/src/wp-includes/blocks/terms-query/block.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/terms-query", + "title": "Terms Query", + "category": "theme", + "description": "An advanced block that allows displaying taxonomy terms based on different query parameters and visual configurations.", + "keywords": [ "terms", "taxonomy", "categories", "tags", "list" ], + "textdomain": "default", + "attributes": { + "termQuery": { + "type": "object", + "default": { + "perPage": 10, + "taxonomy": "category", + "order": "asc", + "orderBy": "name", + "include": [], + "hideEmpty": true, + "showNested": false, + "inherit": false + } + }, + "tagName": { + "type": "string", + "default": "div" + } + }, + "usesContext": [ "templateSlug" ], + "providesContext": { + "termQuery": "termQuery" + }, + "supports": { + "align": [ "wide", "full" ], + "html": false, + "layout": true, + "interactivity": true + } +} diff --git a/src/wp-includes/blocks/text-columns/block.json b/src/wp-includes/blocks/text-columns/block.json new file mode 100644 index 0000000000000..2599df111d34b --- /dev/null +++ b/src/wp-includes/blocks/text-columns/block.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/text-columns", + "title": "Text Columns (deprecated)", + "icon": "columns", + "category": "design", + "description": "This block is deprecated. Please use the Columns block instead.", + "textdomain": "default", + "attributes": { + "content": { + "type": "array", + "source": "query", + "selector": "p", + "query": { + "children": { + "type": "string", + "source": "html" + } + }, + "default": [ {}, {} ] + }, + "columns": { + "type": "number", + "default": 2 + }, + "width": { + "type": "string" + } + }, + "supports": { + "inserter": false, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-text-columns-editor", + "style": "wp-block-text-columns" +} diff --git a/src/wp-includes/blocks/verse/block.json b/src/wp-includes/blocks/verse/block.json new file mode 100644 index 0000000000000..81cccd72965b1 --- /dev/null +++ b/src/wp-includes/blocks/verse/block.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/verse", + "title": "Verse", + "category": "text", + "description": "Insert poetry. Use special spacing formats. Or quote song lyrics.", + "keywords": [ "poetry", "poem" ], + "textdomain": "default", + "attributes": { + "content": { + "type": "rich-text", + "source": "rich-text", + "selector": "pre", + "__unstablePreserveWhiteSpace": true, + "role": "content" + }, + "textAlign": { + "type": "string" + } + }, + "supports": { + "anchor": true, + "background": { + "backgroundImage": true, + "backgroundSize": true, + "__experimentalDefaultControls": { + "backgroundImage": true + } + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "dimensions": { + "minHeight": true, + "__experimentalDefaultControls": { + "minHeight": false + } + }, + "typography": { + "fontSize": true, + "__experimentalFontFamily": true, + "lineHeight": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalWritingMode": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "__experimentalBorder": { + "radius": true, + "width": true, + "color": true, + "style": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "style": "wp-block-verse", + "editorStyle": "wp-block-verse-editor" +} diff --git a/src/wp-includes/blocks/video.php b/src/wp-includes/blocks/video.php new file mode 100644 index 0000000000000..3696bdca3b2e8 --- /dev/null +++ b/src/wp-includes/blocks/video.php @@ -0,0 +1,91 @@ + 0 && $metadata['height'] > 0 ) + ) { + return $content; + } + + // Locate the VIDEO tag to add the dimensions. + $p = new WP_HTML_Tag_Processor( $content ); + if ( ! $p->next_tag( array( 'tag_name' => 'VIDEO' ) ) ) { + return $content; + } + + $p->set_attribute( 'width', (string) $metadata['width'] ); + $p->set_attribute( 'height', (string) $metadata['height'] ); + + /* + * The aspect-ratio style is needed due to an issue with the CSS spec: . + * Note that a style rule using attr() like the following cannot currently be used: + * + * .wp-block-video video[width][height] { + * aspect-ratio: attr(width type()) / attr(height type()); + * } + * + * This is because this attr() is yet only implemented in Chromium: . + */ + $style = $p->get_attribute( 'style' ); + if ( ! is_string( $style ) ) { + $style = ''; + } + $aspect_ratio_style = sprintf( 'aspect-ratio: %d / %d;', $metadata['width'], $metadata['height'] ); + $p->set_attribute( 'style', $aspect_ratio_style . $style ); + + return $p->get_updated_html(); +} + +/** + * Registers the `core/video` block on server. + * + * @since 6.9.0 + */ +function register_block_core_video(): void { + register_block_type_from_metadata( + __DIR__ . '/video', + array( + 'render_callback' => 'render_block_core_video', + ) + ); +} +add_action( 'init', 'register_block_core_video' ); diff --git a/src/wp-includes/blocks/video/block.json b/src/wp-includes/blocks/video/block.json new file mode 100644 index 0000000000000..d2dcd95365c3b --- /dev/null +++ b/src/wp-includes/blocks/video/block.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/video", + "title": "Video", + "category": "media", + "description": "Embed a video from your media library or upload a new one.", + "keywords": [ "movie" ], + "textdomain": "default", + "attributes": { + "autoplay": { + "type": "boolean", + "source": "attribute", + "selector": "video", + "attribute": "autoplay" + }, + "caption": { + "type": "rich-text", + "source": "rich-text", + "selector": "figcaption", + "role": "content" + }, + "controls": { + "type": "boolean", + "source": "attribute", + "selector": "video", + "attribute": "controls", + "default": true + }, + "id": { + "type": "number", + "role": "content" + }, + "loop": { + "type": "boolean", + "source": "attribute", + "selector": "video", + "attribute": "loop" + }, + "muted": { + "type": "boolean", + "source": "attribute", + "selector": "video", + "attribute": "muted" + }, + "poster": { + "type": "string", + "source": "attribute", + "selector": "video", + "attribute": "poster" + }, + "preload": { + "type": "string", + "source": "attribute", + "selector": "video", + "attribute": "preload", + "default": "metadata" + }, + "blob": { + "type": "string", + "role": "local" + }, + "src": { + "type": "string", + "source": "attribute", + "selector": "video", + "attribute": "src", + "role": "content" + }, + "playsInline": { + "type": "boolean", + "source": "attribute", + "selector": "video", + "attribute": "playsinline" + }, + "tracks": { + "role": "content", + "type": "array", + "items": { + "type": "object" + }, + "default": [] + } + }, + "supports": { + "anchor": true, + "align": true, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "interactivity": { + "clientNavigation": true + } + }, + "editorStyle": "wp-block-video-editor", + "style": "wp-block-video" +} diff --git a/src/wp-includes/blocks/widget-group.php b/src/wp-includes/blocks/widget-group.php new file mode 100644 index 0000000000000..e8769612a2f17 --- /dev/null +++ b/src/wp-includes/blocks/widget-group.php @@ -0,0 +1,93 @@ +'; + $after_title = ''; + } + + $html = ''; + + if ( ! empty( $attributes['title'] ) ) { + $html .= $before_title . esc_html( $attributes['title'] ) . $after_title; + } + + $html .= '
      '; + foreach ( $block->inner_blocks as $inner_block ) { + $html .= $inner_block->render(); + } + $html .= '
      '; + + return $html; +} + +/** + * Registers the 'core/widget-group' block. + * + * @since 5.9.0 + */ +function register_block_core_widget_group() { + register_block_type_from_metadata( + __DIR__ . '/widget-group', + array( + 'render_callback' => 'render_block_core_widget_group', + ) + ); +} + +add_action( 'init', 'register_block_core_widget_group' ); + +/** + * Make a note of the sidebar being rendered before WordPress starts rendering + * it. This lets us get to the current sidebar in + * render_block_core_widget_group(). + * + * @since 5.9.0 + * + * @global int|string $_sidebar_being_rendered + * + * @param int|string $index Index, name, or ID of the dynamic sidebar. + */ +function note_sidebar_being_rendered( $index ) { + global $_sidebar_being_rendered; + $_sidebar_being_rendered = $index; +} +add_action( 'dynamic_sidebar_before', 'note_sidebar_being_rendered' ); + +/** + * Clear whatever we set in note_sidebar_being_rendered() after WordPress + * finishes rendering a sidebar. + * + * @since 5.9.0 + * + * @global int|string $_sidebar_being_rendered + */ +function discard_sidebar_being_rendered() { + global $_sidebar_being_rendered; + unset( $_sidebar_being_rendered ); +} +add_action( 'dynamic_sidebar_after', 'discard_sidebar_being_rendered' ); diff --git a/src/wp-includes/blocks/widget-group/block.json b/src/wp-includes/blocks/widget-group/block.json new file mode 100644 index 0000000000000..6e7ba57b38dbc --- /dev/null +++ b/src/wp-includes/blocks/widget-group/block.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/widget-group", + "title": "Widget Group", + "category": "widgets", + "attributes": { + "title": { + "type": "string" + } + }, + "supports": { + "html": false, + "inserter": true, + "customClassName": true, + "reusable": false + }, + "editorStyle": "wp-block-widget-group-editor", + "style": "wp-block-widget-group" +} diff --git a/src/wp-includes/class-wp-block-parser-block.php b/src/wp-includes/class-wp-block-parser-block.php new file mode 100644 index 0000000000000..97dd687c1ffe1 --- /dev/null +++ b/src/wp-includes/class-wp-block-parser-block.php @@ -0,0 +1,90 @@ + 3 ) + * + * @since 5.0.0 + * @var array|null + */ + public $attrs; + + /** + * List of inner blocks (of this same class) + * + * @since 5.0.0 + * @var WP_Block_Parser_Block[] + */ + public $innerBlocks; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + + /** + * Resultant HTML from inside block comment delimiters + * after removing inner blocks + * + * @example "...Just testing..." -> "Just testing..." + * + * @since 5.0.0 + * @var string + */ + public $innerHTML; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + + /** + * List of string fragments and null markers where inner blocks were found + * + * @example array( + * 'innerHTML' => 'BeforeInnerAfter', + * 'innerBlocks' => array( block, block ), + * 'innerContent' => array( 'Before', null, 'Inner', null, 'After' ), + * ) + * + * @since 5.0.0 + * @var array + */ + public $innerContent; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + + /** + * Constructor. + * + * Will populate object properties from the provided arguments. + * + * @since 5.0.0 + * + * @param string $name Name of block. + * @param array $attrs Optional set of attributes from block comment delimiters. + * @param array $inner_blocks List of inner blocks (of this same class). + * @param string $inner_html Resultant HTML from inside block comment delimiters after removing inner blocks. + * @param array $inner_content List of string fragments and null markers where inner blocks were found. + */ + public function __construct( $name, $attrs, $inner_blocks, $inner_html, $inner_content ) { + $this->blockName = $name; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + $this->attrs = $attrs; + $this->innerBlocks = $inner_blocks; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + $this->innerHTML = $inner_html; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + $this->innerContent = $inner_content; // phpcs:ignore WordPress.NamingConventions.ValidVariableName + } +} diff --git a/src/wp-includes/class-wp-block-parser-frame.php b/src/wp-includes/class-wp-block-parser-frame.php new file mode 100644 index 0000000000000..6ab5dd3087dfb --- /dev/null +++ b/src/wp-includes/class-wp-block-parser-frame.php @@ -0,0 +1,79 @@ +block = $block; + $this->token_start = $token_start; + $this->token_length = $token_length; + $this->prev_offset = isset( $prev_offset ) ? $prev_offset : $token_start + $token_length; + $this->leading_html_start = $leading_html_start; + } +} diff --git a/src/wp-includes/class-wp-block-parser.php b/src/wp-includes/class-wp-block-parser.php new file mode 100644 index 0000000000000..bf8a59249d99d --- /dev/null +++ b/src/wp-includes/class-wp-block-parser.php @@ -0,0 +1,404 @@ +This is inside a block!" + * + * @since 5.0.0 + * @var string + */ + public $document; + + /** + * Tracks parsing progress through document + * + * @since 5.0.0 + * @var int + */ + public $offset; + + /** + * List of parsed blocks + * + * @since 5.0.0 + * @var array[] + */ + public $output; + + /** + * Stack of partially-parsed structures in memory during parse + * + * @since 5.0.0 + * @var WP_Block_Parser_Frame[] + */ + public $stack; + + /** + * Parses a document and returns a list of block structures + * + * When encountering an invalid parse will return a best-effort + * parse. In contrast to the specification parser this does not + * return an error on invalid inputs. + * + * @since 5.0.0 + * + * @param string $document Input document being parsed. + * @return array[] + */ + public function parse( $document ) { + $this->document = $document; + $this->offset = 0; + $this->output = array(); + $this->stack = array(); + + while ( $this->proceed() ) { + continue; + } + + return $this->output; + } + + /** + * Processes the next token from the input document + * and returns whether to proceed eating more tokens + * + * This is the "next step" function that essentially + * takes a token as its input and decides what to do + * with that token before descending deeper into a + * nested block tree or continuing along the document + * or breaking out of a level of nesting. + * + * @internal + * @since 5.0.0 + * @return bool + */ + public function proceed() { + $next_token = $this->next_token(); + list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token; + $stack_depth = count( $this->stack ); + + // we may have some HTML soup before the next block. + $leading_html_start = $start_offset > $this->offset ? $this->offset : null; + + switch ( $token_type ) { + case 'no-more-tokens': + // if not in a block then flush output. + if ( 0 === $stack_depth ) { + $this->add_freeform(); + return false; + } + + /* + * Otherwise we have a problem + * This is an error + * + * we have options + * - treat it all as freeform text + * - assume an implicit closer (easiest when not nesting) + */ + + // for the easy case we'll assume an implicit closer. + if ( 1 === $stack_depth ) { + $this->add_block_from_stack(); + return false; + } + + /* + * for the nested case where it's more difficult we'll + * have to assume that multiple closers are missing + * and so we'll collapse the whole stack piecewise + */ + while ( 0 < count( $this->stack ) ) { + $this->add_block_from_stack(); + } + return false; + + case 'void-block': + /* + * easy case is if we stumbled upon a void block + * in the top-level of the document + */ + if ( 0 === $stack_depth ) { + if ( isset( $leading_html_start ) ) { + $this->output[] = (array) $this->freeform( + substr( + $this->document, + $leading_html_start, + $start_offset - $leading_html_start + ) + ); + } + + $this->output[] = (array) new WP_Block_Parser_Block( $block_name, $attrs, array(), '', array() ); + $this->offset = $start_offset + $token_length; + return true; + } + + // otherwise we found an inner block. + $this->add_inner_block( + new WP_Block_Parser_Block( $block_name, $attrs, array(), '', array() ), + $start_offset, + $token_length + ); + $this->offset = $start_offset + $token_length; + return true; + + case 'block-opener': + // track all newly-opened blocks on the stack. + array_push( + $this->stack, + new WP_Block_Parser_Frame( + new WP_Block_Parser_Block( $block_name, $attrs, array(), '', array() ), + $start_offset, + $token_length, + $start_offset + $token_length, + $leading_html_start + ) + ); + $this->offset = $start_offset + $token_length; + return true; + + case 'block-closer': + /* + * if we're missing an opener we're in trouble + * This is an error + */ + if ( 0 === $stack_depth ) { + /* + * we have options + * - assume an implicit opener + * - assume _this_ is the opener + * - give up and close out the document + */ + $this->add_freeform(); + return false; + } + + // if we're not nesting then this is easy - close the block. + if ( 1 === $stack_depth ) { + $this->add_block_from_stack( $start_offset ); + $this->offset = $start_offset + $token_length; + return true; + } + + /* + * otherwise we're nested and we have to close out the current + * block and add it as a new innerBlock to the parent + */ + $stack_top = array_pop( $this->stack ); + $html = substr( $this->document, $stack_top->prev_offset, $start_offset - $stack_top->prev_offset ); + $stack_top->block->innerHTML .= $html; + $stack_top->block->innerContent[] = $html; + $stack_top->prev_offset = $start_offset + $token_length; + + $this->add_inner_block( + $stack_top->block, + $stack_top->token_start, + $stack_top->token_length, + $start_offset + $token_length + ); + $this->offset = $start_offset + $token_length; + return true; + + default: + // This is an error. + $this->add_freeform(); + return false; + } + } + + /** + * Scans the document from where we last left off + * and finds the next valid token to parse if it exists + * + * Returns the type of the find: kind of find, block information, attributes + * + * @internal + * @since 5.0.0 + * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments + * @return array + */ + public function next_token() { + $matches = null; + + /* + * aye the magic + * we're using a single RegExp to tokenize the block comment delimiters + * we're also using a trick here because the only difference between a + * block opener and a block closer is the leading `/` before `wp:` (and + * a closer has no attributes). we can trap them both and process the + * match back in PHP to see which one it was. + */ + $has_match = preg_match( + '/).)*+)?}\s+)?(?P\/)?-->/s', + $this->document, + $matches, + PREG_OFFSET_CAPTURE, + $this->offset + ); + + // if we get here we probably have catastrophic backtracking or out-of-memory in the PCRE. + if ( false === $has_match ) { + return array( 'no-more-tokens', null, null, null, null ); + } + + // we have no more tokens. + if ( 0 === $has_match ) { + return array( 'no-more-tokens', null, null, null, null ); + } + + list( $match, $started_at ) = $matches[0]; + + $length = strlen( $match ); + $is_closer = isset( $matches['closer'] ) && -1 !== $matches['closer'][1]; + $is_void = isset( $matches['void'] ) && -1 !== $matches['void'][1]; + $namespace = $matches['namespace']; + $namespace = ( isset( $namespace ) && -1 !== $namespace[1] ) ? $namespace[0] : 'core/'; + $name = $namespace . $matches['name'][0]; + $has_attrs = isset( $matches['attrs'] ) && -1 !== $matches['attrs'][1]; + + /* + * Fun fact! It's not trivial in PHP to create "an empty associative array" since all arrays + * are associative arrays. If we use `array()` we get a JSON `[]` + */ + $attrs = $has_attrs + ? json_decode( $matches['attrs'][0], /* as-associative */ true ) + : array(); + + /* + * This state isn't allowed + * This is an error + */ + if ( $is_closer && ( $is_void || $has_attrs ) ) { + // we can ignore them since they don't hurt anything. + } + + if ( $is_void ) { + return array( 'void-block', $name, $attrs, $started_at, $length ); + } + + if ( $is_closer ) { + return array( 'block-closer', $name, null, $started_at, $length ); + } + + return array( 'block-opener', $name, $attrs, $started_at, $length ); + } + + /** + * Returns a new block object for freeform HTML + * + * @internal + * @since 5.0.0 + * + * @param string $inner_html HTML content of block. + * @return WP_Block_Parser_Block freeform block object. + */ + public function freeform( $inner_html ) { + return new WP_Block_Parser_Block( null, array(), array(), $inner_html, array( $inner_html ) ); + } + + /** + * Pushes a length of text from the input document + * to the output list as a freeform block. + * + * @internal + * @since 5.0.0 + * @param null $length how many bytes of document text to output. + */ + public function add_freeform( $length = null ) { + $length = $length ? $length : strlen( $this->document ) - $this->offset; + + if ( 0 === $length ) { + return; + } + + $this->output[] = (array) $this->freeform( substr( $this->document, $this->offset, $length ) ); + } + + /** + * Given a block structure from memory pushes + * a new block to the output list. + * + * @internal + * @since 5.0.0 + * @param WP_Block_Parser_Block $block The block to add to the output. + * @param int $token_start Byte offset into the document where the first token for the block starts. + * @param int $token_length Byte length of entire block from start of opening token to end of closing token. + * @param int|null $last_offset Last byte offset into document if continuing form earlier output. + */ + public function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) { + $parent = $this->stack[ count( $this->stack ) - 1 ]; + $parent->block->innerBlocks[] = (array) $block; + $html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset ); + + if ( ! empty( $html ) ) { + $parent->block->innerHTML .= $html; + $parent->block->innerContent[] = $html; + } + + $parent->block->innerContent[] = null; + $parent->prev_offset = $last_offset ? $last_offset : $token_start + $token_length; + } + + /** + * Pushes the top block from the parsing stack to the output list. + * + * @internal + * @since 5.0.0 + * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. + */ + public function add_block_from_stack( $end_offset = null ) { + $stack_top = array_pop( $this->stack ); + $prev_offset = $stack_top->prev_offset; + + $html = isset( $end_offset ) + ? substr( $this->document, $prev_offset, $end_offset - $prev_offset ) + : substr( $this->document, $prev_offset ); + + if ( ! empty( $html ) ) { + $stack_top->block->innerHTML .= $html; + $stack_top->block->innerContent[] = $html; + } + + if ( isset( $stack_top->leading_html_start ) ) { + $this->output[] = (array) $this->freeform( + substr( + $this->document, + $stack_top->leading_html_start, + $stack_top->token_start - $stack_top->leading_html_start + ) + ); + } + + $this->output[] = (array) $stack_top->block; + } +} + +/** + * WP_Block_Parser_Block class. + * + * Required for backward compatibility in WordPress Core. + */ +require_once __DIR__ . '/class-wp-block-parser-block.php'; + +/** + * WP_Block_Parser_Frame class. + * + * Required for backward compatibility in WordPress Core. + */ +require_once __DIR__ . '/class-wp-block-parser-frame.php'; diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index db3748c5265c8..68dccd979f2fe 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -620,7 +620,6 @@ add_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_format_library_assets' ); -add_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_script_modules' ); add_action( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); add_action( 'wp_print_scripts', 'wp_just_in_time_script_localization' ); add_filter( 'print_scripts_array', 'wp_prototype_before_jquery' ); diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 2d1f49ff95f0d..c07e4539b674a 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -218,6 +218,46 @@ function wp_get_script_polyfill( $scripts, $tests ) { return $polyfill; } +/** + * Registers development scripts that integrate with `@wordpress/scripts`. + * + * @see https://github.com/WordPress/gutenberg/tree/trunk/packages/scripts#start + * + * @since 6.0.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + */ +function wp_register_development_scripts( $scripts ) { + if ( + ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG + || empty( $scripts->registered['react'] ) + || defined( 'WP_RUN_CORE_TESTS' ) + ) { + return; + } + + $development_scripts = array( + 'react-refresh-entry', + 'react-refresh-runtime', + ); + + foreach ( $development_scripts as $script_name ) { + $assets = include ABSPATH . WPINC . '/assets/script-loader-' . $script_name . '.php'; + if ( ! is_array( $assets ) ) { + return; + } + $scripts->add( + 'wp-' . $script_name, + '/wp-includes/js/dist/development/' . $script_name . '.js', + $assets['dependencies'], + $assets['version'] + ); + } + + // See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react. + $scripts->registered['react']->deps[] = 'wp-react-refresh-entry'; +} + /** * Registers all the WordPress packages scripts that are in the standardized * `js/dist/` location. @@ -618,6 +658,7 @@ function wp_tinymce_inline_scripts() { */ function wp_default_packages( $scripts ) { wp_default_packages_vendor( $scripts ); + wp_register_development_scripts( $scripts ); wp_register_tinymce_scripts( $scripts ); wp_default_packages_scripts( $scripts ); diff --git a/src/wp-includes/script-modules.php b/src/wp-includes/script-modules.php index 85cc4accf2e52..c1e90c1c852eb 100644 --- a/src/wp-includes/script-modules.php +++ b/src/wp-includes/script-modules.php @@ -150,8 +150,8 @@ function wp_default_script_modules() { * Expects multidimensional array like: * * 'interactivity/index.min.js' => array('dependencies' => array(…), 'version' => '…'), - * 'interactivity-router/index.min.js' => array('dependencies' => array(…), 'version' => '…'), - * 'block-library/navigation/view.min.js' => … + * 'interactivity/debug.min.js' => array('dependencies' => array(…), 'version' => '…'), + * 'interactivity-router/index.min.js' => … */ $assets = include ABSPATH . WPINC . "/assets/script-modules-packages{$suffix}.php"; @@ -159,12 +159,30 @@ function wp_default_script_modules() { /* * Build the WordPress Script Module ID from the file name. * Prepend `@wordpress/` and remove extensions and `/index` if present: - * - interactivity/index.min.js => @wordpress/interactivity - * - interactivity-router/index.min.js => @wordpress/interactivity-router - * - block-library/navigation/view.js => @wordpress/block-library/navigation/view + * - interactivity/index.min.js => @wordpress/interactivity + * - interactivity/debug.min.js => @wordpress/interactivity/debug + * - block-library/query/view.js => @wordpress/block-library/query/view */ $script_module_id = '@wordpress/' . preg_replace( '~(?:/index)?(?:\.min)?\.js$~D', '', $file_name, 1 ); + switch ( $script_module_id ) { + /* + * Interactivity exposes two entrypoints, "/index" and "/debug". + * "/debug" should replace "/index" in development. + */ + case '@wordpress/interactivity/debug': + if ( ! SCRIPT_DEBUG ) { + continue 2; + } + $script_module_id = '@wordpress/interactivity'; + break; + case '@wordpress/interactivity': + if ( SCRIPT_DEBUG ) { + continue 2; + } + break; + } + /* * The Interactivity API is designed with server-side rendering as its primary goal, so all of its script modules * should be loaded with low fetchpriority and printed in the footer since they should not be needed in the @@ -189,21 +207,7 @@ function wp_default_script_modules() { wp_interactivity()->add_client_navigation_support_to_script_module( $script_module_id ); } - $path = includes_url( "js/dist/script-modules/{$file_name}" ); - $module_deps = $script_module_data['module_dependencies'] ?? array(); - wp_register_script_module( $script_module_id, $path, $module_deps, $script_module_data['version'], $args ); + $path = includes_url( "js/dist/script-modules/{$file_name}" ); + wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'], $args ); } } - -/** - * Enqueues script modules required by the block editor. - * - * @since 6.9.0 - */ -function wp_enqueue_block_editor_script_modules() { - /* - * Enqueue the LaTeX to MathML loader for the math block editor. - * The loader dynamically imports the main LaTeX to MathML module when needed. - */ - wp_enqueue_script_module( '@wordpress/latex-to-mathml/loader' ); -} diff --git a/src/wp-includes/theme-i18n.json b/src/wp-includes/theme-i18n.json index b7f46688e7f91..8ceaee85afbbe 100644 --- a/src/wp-includes/theme-i18n.json +++ b/src/wp-includes/theme-i18n.json @@ -43,11 +43,6 @@ { "name": "Aspect ratio name" } - ], - "dimensionSizes": [ - { - "name": "Dimension size name" - } ] }, "shadow": { @@ -100,11 +95,6 @@ { "name": "Aspect ratio name" } - ], - "dimensionSizes": [ - { - "name": "Dimension size name" - } ] }, "spacing": { diff --git a/src/wp-includes/theme.json b/src/wp-includes/theme.json new file mode 100644 index 0000000000000..362cfe7d3ecc0 --- /dev/null +++ b/src/wp-includes/theme.json @@ -0,0 +1,413 @@ +{ + "$schema": "https://schemas.wp.org/trunk/theme.json", + "version": 3, + "settings": { + "appearanceTools": false, + "useRootPaddingAwareAlignments": false, + "border": { + "color": false, + "radius": false, + "style": false, + "width": false + }, + "color": { + "background": true, + "button": true, + "caption": true, + "custom": true, + "customDuotone": true, + "customGradient": true, + "defaultDuotone": true, + "defaultGradients": true, + "defaultPalette": true, + "duotone": [ + { + "name": "Dark grayscale", + "colors": [ "#000000", "#7f7f7f" ], + "slug": "dark-grayscale" + }, + { + "name": "Grayscale", + "colors": [ "#000000", "#ffffff" ], + "slug": "grayscale" + }, + { + "name": "Purple and yellow", + "colors": [ "#8c00b7", "#fcff41" ], + "slug": "purple-yellow" + }, + { + "name": "Blue and red", + "colors": [ "#000097", "#ff4747" ], + "slug": "blue-red" + }, + { + "name": "Midnight", + "colors": [ "#000000", "#00a5ff" ], + "slug": "midnight" + }, + { + "name": "Magenta and yellow", + "colors": [ "#c7005a", "#fff278" ], + "slug": "magenta-yellow" + }, + { + "name": "Purple and green", + "colors": [ "#a60072", "#67ff66" ], + "slug": "purple-green" + }, + { + "name": "Blue and orange", + "colors": [ "#1900d8", "#ffa96b" ], + "slug": "blue-orange" + } + ], + "gradients": [ + { + "name": "Vivid cyan blue to vivid purple", + "gradient": "linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%)", + "slug": "vivid-cyan-blue-to-vivid-purple" + }, + { + "name": "Light green cyan to vivid green cyan", + "gradient": "linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)", + "slug": "light-green-cyan-to-vivid-green-cyan" + }, + { + "name": "Luminous vivid amber to luminous vivid orange", + "gradient": "linear-gradient(135deg,rgb(252,185,0) 0%,rgb(255,105,0) 100%)", + "slug": "luminous-vivid-amber-to-luminous-vivid-orange" + }, + { + "name": "Luminous vivid orange to vivid red", + "gradient": "linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%)", + "slug": "luminous-vivid-orange-to-vivid-red" + }, + { + "name": "Very light gray to cyan bluish gray", + "gradient": "linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%)", + "slug": "very-light-gray-to-cyan-bluish-gray" + }, + { + "name": "Cool to warm spectrum", + "gradient": "linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%)", + "slug": "cool-to-warm-spectrum" + }, + { + "name": "Blush light purple", + "gradient": "linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%)", + "slug": "blush-light-purple" + }, + { + "name": "Blush bordeaux", + "gradient": "linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)", + "slug": "blush-bordeaux" + }, + { + "name": "Luminous dusk", + "gradient": "linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%)", + "slug": "luminous-dusk" + }, + { + "name": "Pale ocean", + "gradient": "linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)", + "slug": "pale-ocean" + }, + { + "name": "Electric grass", + "gradient": "linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%)", + "slug": "electric-grass" + }, + { + "name": "Midnight", + "gradient": "linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)", + "slug": "midnight" + } + ], + "heading": true, + "link": false, + "palette": [ + { + "name": "Black", + "slug": "black", + "color": "#000000" + }, + { + "name": "Cyan bluish gray", + "slug": "cyan-bluish-gray", + "color": "#abb8c3" + }, + { + "name": "White", + "slug": "white", + "color": "#ffffff" + }, + { + "name": "Pale pink", + "slug": "pale-pink", + "color": "#f78da7" + }, + { + "name": "Vivid red", + "slug": "vivid-red", + "color": "#cf2e2e" + }, + { + "name": "Luminous vivid orange", + "slug": "luminous-vivid-orange", + "color": "#ff6900" + }, + { + "name": "Luminous vivid amber", + "slug": "luminous-vivid-amber", + "color": "#fcb900" + }, + { + "name": "Light green cyan", + "slug": "light-green-cyan", + "color": "#7bdcb5" + }, + { + "name": "Vivid green cyan", + "slug": "vivid-green-cyan", + "color": "#00d084" + }, + { + "name": "Pale cyan blue", + "slug": "pale-cyan-blue", + "color": "#8ed1fc" + }, + { + "name": "Vivid cyan blue", + "slug": "vivid-cyan-blue", + "color": "#0693e3" + }, + { + "name": "Vivid purple", + "slug": "vivid-purple", + "color": "#9b51e0" + } + ], + "text": true + }, + "dimensions": { + "defaultAspectRatios": true, + "aspectRatios": [ + { + "name": "Square - 1:1", + "slug": "square", + "ratio": "1" + }, + { + "name": "Standard - 4:3", + "slug": "4-3", + "ratio": "4/3" + }, + { + "name": "Portrait - 3:4", + "slug": "3-4", + "ratio": "3/4" + }, + { + "name": "Classic - 3:2", + "slug": "3-2", + "ratio": "3/2" + }, + { + "name": "Classic Portrait - 2:3", + "slug": "2-3", + "ratio": "2/3" + }, + { + "name": "Wide - 16:9", + "slug": "16-9", + "ratio": "16/9" + }, + { + "name": "Tall - 9:16", + "slug": "9-16", + "ratio": "9/16" + } + ] + }, + "shadow": { + "defaultPresets": true, + "presets": [ + { + "name": "Natural", + "slug": "natural", + "shadow": "6px 6px 9px rgba(0, 0, 0, 0.2)" + }, + { + "name": "Deep", + "slug": "deep", + "shadow": "12px 12px 50px rgba(0, 0, 0, 0.4)" + }, + { + "name": "Sharp", + "slug": "sharp", + "shadow": "6px 6px 0px rgba(0, 0, 0, 0.2)" + }, + { + "name": "Outlined", + "slug": "outlined", + "shadow": "6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0)" + }, + { + "name": "Crisp", + "slug": "crisp", + "shadow": "6px 6px 0px rgb(0, 0, 0)" + } + ] + }, + "spacing": { + "blockGap": null, + "margin": false, + "padding": false, + "customSpacingSize": true, + "defaultSpacingSizes": true, + "units": [ "px", "em", "rem", "vh", "vw", "%" ], + "spacingScale": { + "operator": "*", + "increment": 1.5, + "steps": 7, + "mediumStep": 1.5, + "unit": "rem" + } + }, + "typography": { + "customFontSize": true, + "defaultFontSizes": true, + "dropCap": true, + "fontSizes": [ + { + "name": "Small", + "slug": "small", + "size": "13px" + }, + { + "name": "Medium", + "slug": "medium", + "size": "20px" + }, + { + "name": "Large", + "slug": "large", + "size": "36px" + }, + { + "name": "Extra Large", + "slug": "x-large", + "size": "42px" + } + ], + "fontStyle": true, + "fontWeight": true, + "letterSpacing": true, + "lineHeight": false, + "textAlign": true, + "textDecoration": true, + "textTransform": true, + "writingMode": false + }, + "blocks": { + "core/button": { + "border": { + "radius": true + } + }, + "core/image": { + "lightbox": { + "allowEditing": true + } + }, + "core/pullquote": { + "border": { + "color": true, + "radius": true, + "style": true, + "width": true + } + } + } + }, + "styles": { + "blocks": { + "core/button": { + "variations": { + "outline": { + "border": { + "width": "2px", + "style": "solid", + "color": "currentColor" + }, + "color": { + "text": "currentColor", + "gradient": "transparent none" + }, + "spacing": { + "padding": { + "top": "0.667em", + "right": "1.33em", + "bottom": "0.667em", + "left": "1.33em" + } + } + } + } + }, + "core/site-logo": { + "variations": { + "rounded": { + "border": { + "radius": "9999px" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "text": "#fff", + "background": "#32373c" + }, + "spacing": { + "padding": { + "top": "calc(0.667em + 2px)", + "right": "calc(1.333em + 2px)", + "bottom": "calc(0.667em + 2px)", + "left": "calc(1.333em + 2px)" + } + }, + "typography": { + "fontSize": "inherit", + "fontFamily": "inherit", + "fontStyle": "inherit", + "fontWeight": "inherit", + "letterSpacing": "inherit", + "textTransform": "inherit", + "lineHeight": "inherit", + "textDecoration": "none" + }, + "border": { + "width": "0" + } + }, + "link": { + "typography": { + "textDecoration": "underline" + } + } + }, + "spacing": { + "blockGap": "24px", + "padding": { + "top": "0px", + "right": "0px", + "bottom": "0px", + "left": "0px" + } + } + } +} diff --git a/src/wp-settings.php b/src/wp-settings.php index adaa0b161c3f6..45f96ace09a1c 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -242,8 +242,6 @@ require ABSPATH . WPINC . '/cron.php'; require ABSPATH . WPINC . '/deprecated.php'; require ABSPATH . WPINC . '/script-loader.php'; -require ABSPATH . WPINC . '/build/routes.php'; -require ABSPATH . WPINC . '/build/pages.php'; require ABSPATH . WPINC . '/taxonomy.php'; require ABSPATH . WPINC . '/class-wp-taxonomy.php'; require ABSPATH . WPINC . '/class-wp-term.php'; diff --git a/tests/phpunit/data/blocks/fixtures/core__categories.server.html b/tests/phpunit/data/blocks/fixtures/core__categories.server.html index f10bd41b123bc..f073f8f5ee213 100644 --- a/tests/phpunit/data/blocks/fixtures/core__categories.server.html +++ b/tests/phpunit/data/blocks/fixtures/core__categories.server.html @@ -1 +1 @@ -
      • No categories
      +
      • No categories
      diff --git a/tests/phpunit/tests/admin/wpSiteHealth.php b/tests/phpunit/tests/admin/wpSiteHealth.php index 0c6a42f71bea3..86974db2160e3 100644 --- a/tests/phpunit/tests/admin/wpSiteHealth.php +++ b/tests/phpunit/tests/admin/wpSiteHealth.php @@ -490,7 +490,7 @@ public function data_object_cache_thresholds() { array( 'comments_count', 0 ), array( 'posts_count', 0 ), array( 'terms_count', 1 ), - array( 'options_count', 1 ), + array( 'options_count', 100 ), array( 'users_count', 0 ), array( 'alloptions_count', 100 ), array( 'alloptions_bytes', 1000 ), diff --git a/tests/phpunit/tests/script-modules/wpScriptModules.php b/tests/phpunit/tests/script-modules/wpScriptModules.php index 047176bdb2d8b..4b103953c8451 100644 --- a/tests/phpunit/tests/script-modules/wpScriptModules.php +++ b/tests/phpunit/tests/script-modules/wpScriptModules.php @@ -1823,7 +1823,7 @@ public function test_default_script_modules() { $actual_preloads = $this->normalize_markup_for_snapshot( get_echo( array( wp_script_modules(), 'print_script_module_preloads' ) ) ); $this->assertEqualHTML( ' - + ', $actual_preloads, '', @@ -1897,7 +1897,7 @@ public function test_dependent_of_default_script_modules() { $expected = ' - + '; diff --git a/tools/gutenberg/build-gutenberg.js b/tools/gutenberg/build-gutenberg.js deleted file mode 100644 index 0b989a13495ec..0000000000000 --- a/tools/gutenberg/build-gutenberg.js +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env node - -/** - * Build Gutenberg Script - * - * This script builds the Gutenberg repository using its build command - * as specified in the root package.json's "gutenberg" configuration. - * - * @package WordPress - */ - -const { spawn } = require( 'child_process' ); -const fs = require( 'fs' ); -const path = require( 'path' ); - -// Paths -const rootDir = path.resolve( __dirname, '../..' ); -const gutenbergDir = path.join( rootDir, 'gutenberg' ); - -/** - * Execute a command and return a promise. - * Captures output and only displays it on failure for cleaner logs. - * - * @param {string} command - Command to execute. - * @param {string[]} args - Command arguments. - * @param {Object} options - Spawn options. - * @return {Promise} Promise that resolves when command completes. - */ -function exec( command, args, options = {} ) { - return new Promise( ( resolve, reject ) => { - let stdout = ''; - let stderr = ''; - - const child = spawn( command, args, { - cwd: options.cwd || rootDir, - stdio: [ 'ignore', 'pipe', 'pipe' ], - shell: process.platform === 'win32', // Use shell on Windows to find .cmd files - ...options, - } ); - - // Capture output - if ( child.stdout ) { - child.stdout.on( 'data', ( data ) => { - stdout += data.toString(); - } ); - } - - if ( child.stderr ) { - child.stderr.on( 'data', ( data ) => { - stderr += data.toString(); - } ); - } - - child.on( 'close', ( code ) => { - if ( code !== 0 ) { - // Show output only on failure - if ( stdout ) { - console.error( '\nCommand output:' ); - console.error( stdout ); - } - if ( stderr ) { - console.error( '\nCommand errors:' ); - console.error( stderr ); - } - reject( - new Error( - `${ command } ${ args.join( - ' ' - ) } failed with code ${ code }` - ) - ); - } else { - resolve(); - } - } ); - - child.on( 'error', reject ); - } ); -} - -/** - * Main execution function. - */ -async function main() { - console.log( 'šŸ” Checking Gutenberg setup...' ); - - // Verify Gutenberg directory exists - if ( ! fs.existsSync( gutenbergDir ) ) { - console.error( 'āŒ Gutenberg directory not found at:', gutenbergDir ); - console.error( ' Run: node tools/gutenberg/checkout-gutenberg.js' ); - process.exit( 1 ); - } - - // Verify node_modules exists - const nodeModulesPath = path.join( gutenbergDir, 'node_modules' ); - if ( ! fs.existsSync( nodeModulesPath ) ) { - console.error( 'āŒ Gutenberg dependencies not installed' ); - console.error( ' Run: node tools/gutenberg/checkout-gutenberg.js' ); - process.exit( 1 ); - } - - console.log( 'āœ… Gutenberg directory found' ); - - // Modify Gutenberg's package.json for Core build - console.log( '\nāš™ļø Configuring build for WordPress Core...' ); - const gutenbergPackageJsonPath = path.join( gutenbergDir, 'package.json' ); - - try { - const content = fs.readFileSync( gutenbergPackageJsonPath, 'utf8' ); - const gutenbergPackageJson = JSON.parse( content ); - - // Set Core environment variables - gutenbergPackageJson.config = gutenbergPackageJson.config || {}; - gutenbergPackageJson.config.IS_GUTENBERG_PLUGIN = false; - gutenbergPackageJson.config.IS_WORDPRESS_CORE = true; - - // Set wpPlugin.name for Core naming convention - gutenbergPackageJson.wpPlugin = gutenbergPackageJson.wpPlugin || {}; - gutenbergPackageJson.wpPlugin.name = 'wp'; - - fs.writeFileSync( - gutenbergPackageJsonPath, - JSON.stringify( gutenbergPackageJson, null, '\t' ) + '\n' - ); - - console.log( ' āœ… IS_GUTENBERG_PLUGIN = false' ); - console.log( ' āœ… IS_WORDPRESS_CORE = true' ); - console.log( ' āœ… wpPlugin.name = wp' ); - } catch ( error ) { - console.error( - 'āŒ Error modifying Gutenberg package.json:', - error.message - ); - process.exit( 1 ); - } - - // Build Gutenberg - console.log( '\nšŸ”Ø Building Gutenberg for WordPress Core...' ); - console.log( ' (This may take a few minutes)' ); - - const startTime = Date.now(); - - try { - // On Windows, shell mode is used and needs the argument wrapped in quotes - // On Unix, arguments are passed directly without shell parsing - const baseUrlArg = - process.platform === 'win32' - ? '--base-url="includes_url( \'build\' )"' - : "--base-url=includes_url( 'build' )"; - - await exec( 'npm', [ 'run', 'build', '--', '--fast', baseUrlArg ], { - cwd: gutenbergDir, - } ); - - const duration = Math.round( ( Date.now() - startTime ) / 1000 ); - console.log( `āœ… Build completed in ${ duration }s` ); - } catch ( error ) { - console.error( 'āŒ Build failed:', error.message ); - process.exit( 1 ); - } -} - -// Run main function -main().catch( ( error ) => { - console.error( 'āŒ Unexpected error:', error ); - process.exit( 1 ); -} ); diff --git a/tools/gutenberg/checkout-gutenberg.js b/tools/gutenberg/checkout-gutenberg.js deleted file mode 100644 index 42e35a1967b78..0000000000000 --- a/tools/gutenberg/checkout-gutenberg.js +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env node - -/** - * Checkout Gutenberg Repository Script - * - * This script checks out the Gutenberg repository at a specific commit/branch/tag - * as specified in the root package.json's "gutenberg" configuration. - * - * It handles: - * - Initial clone if directory doesn't exist - * - Updating existing checkout to correct ref - * - Installing dependencies with npm ci - * - Idempotent operation (safe to run multiple times) - * - * @package WordPress - */ - -const { spawn } = require( 'child_process' ); -const fs = require( 'fs' ); -const path = require( 'path' ); - -// Constants -const GUTENBERG_REPO = 'https://github.com/WordPress/gutenberg.git'; - -// Paths -const rootDir = path.resolve( __dirname, '../..' ); -const gutenbergDir = path.join( rootDir, 'gutenberg' ); -const packageJsonPath = path.join( rootDir, 'package.json' ); - -/** - * Execute a command and return a promise. - * Captures output and only displays it on failure for cleaner logs. - * - * @param {string} command - Command to execute. - * @param {string[]} args - Command arguments. - * @param {Object} options - Spawn options. - * @return {Promise} Promise that resolves when command completes. - */ -function exec( command, args, options = {} ) { - return new Promise( ( resolve, reject ) => { - let stdout = ''; - let stderr = ''; - - const child = spawn( command, args, { - cwd: options.cwd || rootDir, - stdio: [ 'ignore', 'pipe', 'pipe' ], - shell: process.platform === 'win32', // Use shell on Windows to find .cmd files - ...options, - } ); - - // Capture output - if ( child.stdout ) { - child.stdout.on( 'data', ( data ) => { - stdout += data.toString(); - } ); - } - - if ( child.stderr ) { - child.stderr.on( 'data', ( data ) => { - stderr += data.toString(); - } ); - } - - child.on( 'close', ( code ) => { - if ( code !== 0 ) { - // Show output only on failure - if ( stdout ) { - console.error( '\nCommand output:' ); - console.error( stdout ); - } - if ( stderr ) { - console.error( '\nCommand errors:' ); - console.error( stderr ); - } - reject( - new Error( - `${ command } ${ args.join( - ' ' - ) } failed with code ${ code }` - ) - ); - } else { - resolve(); - } - } ); - - child.on( 'error', reject ); - } ); -} - -/** - * Execute a command and capture its output. - * - * @param {string} command - Command to execute. - * @param {string[]} args - Command arguments. - * @param {Object} options - Spawn options. - * @return {Promise} Promise that resolves with command output. - */ -function execOutput( command, args, options = {} ) { - return new Promise( ( resolve, reject ) => { - const child = spawn( command, args, { - cwd: options.cwd || rootDir, - shell: process.platform === 'win32', // Use shell on Windows to find .cmd files - ...options, - } ); - - let stdout = ''; - let stderr = ''; - - if ( child.stdout ) { - child.stdout.on( 'data', ( data ) => { - stdout += data.toString(); - } ); - } - - if ( child.stderr ) { - child.stderr.on( 'data', ( data ) => { - stderr += data.toString(); - } ); - } - - child.on( 'close', ( code ) => { - if ( code !== 0 ) { - reject( new Error( `${ command } failed: ${ stderr }` ) ); - } else { - resolve( stdout.trim() ); - } - } ); - - child.on( 'error', reject ); - } ); -} - -/** - * Main execution function. - */ -async function main() { - console.log( 'šŸ” Checking Gutenberg configuration...' ); - - // Read Gutenberg ref from package.json - let ref; - try { - const packageJson = JSON.parse( - fs.readFileSync( packageJsonPath, 'utf8' ) - ); - ref = packageJson.gutenberg?.ref; - - if ( ! ref ) { - throw new Error( 'Missing "gutenberg.ref" in package.json' ); - } - - console.log( ` Repository: ${ GUTENBERG_REPO }` ); - console.log( ` Reference: ${ ref }` ); - } catch ( error ) { - console.error( 'āŒ Error reading package.json:', error.message ); - process.exit( 1 ); - } - - // Check if Gutenberg directory exists - const gutenbergExists = fs.existsSync( gutenbergDir ); - - if ( ! gutenbergExists ) { - console.log( '\nšŸ“„ Cloning Gutenberg repository (shallow clone)...' ); - try { - // Generic shallow clone approach that works for both branches and commit hashes - // 1. Clone with no checkout and shallow depth - await exec( 'git', [ - 'clone', - '--depth', - '1', - '--no-checkout', - GUTENBERG_REPO, - 'gutenberg', - ] ); - - // 2. Fetch the specific ref with depth 1 (works for branches, tags, and commits) - await exec( 'git', [ 'fetch', '--depth', '1', 'origin', ref ], { - cwd: gutenbergDir, - } ); - - // 3. Checkout FETCH_HEAD - await exec( 'git', [ 'checkout', 'FETCH_HEAD' ], { - cwd: gutenbergDir, - } ); - - console.log( 'āœ… Cloned successfully' ); - } catch ( error ) { - console.error( 'āŒ Clone failed:', error.message ); - process.exit( 1 ); - } - } else { - console.log( '\nāœ… Gutenberg directory already exists' ); - } - - // Fetch and checkout target ref - console.log( `\nšŸ“” Fetching and checking out: ${ ref }` ); - try { - // Fetch the specific ref (works for branches, tags, and commit hashes) - await exec( 'git', [ 'fetch', '--depth', '1', 'origin', ref ], { - cwd: gutenbergDir, - } ); - - // Checkout what was just fetched - await exec( 'git', [ 'checkout', 'FETCH_HEAD' ], { - cwd: gutenbergDir, - } ); - - console.log( 'āœ… Checked out successfully' ); - } catch ( error ) { - console.error( 'āŒ Fetch/checkout failed:', error.message ); - process.exit( 1 ); - } - - // Install dependencies - console.log( '\nšŸ“¦ Installing dependencies...' ); - const nodeModulesExists = fs.existsSync( - path.join( gutenbergDir, 'node_modules' ) - ); - - if ( ! nodeModulesExists ) { - console.log( ' (This may take a few minutes on first run)' ); - } - - try { - await exec( 'npm', [ 'ci' ], { cwd: gutenbergDir } ); - console.log( 'āœ… Dependencies installed' ); - } catch ( error ) { - console.error( 'āŒ npm ci failed:', error.message ); - process.exit( 1 ); - } - - console.log( '\nāœ… Gutenberg checkout complete!' ); -} - -// Run main function -main().catch( ( error ) => { - console.error( 'āŒ Unexpected error:', error ); - process.exit( 1 ); -} ); diff --git a/tools/gutenberg/copy-gutenberg-build.js b/tools/gutenberg/copy-gutenberg-build.js deleted file mode 100644 index 7257e5f3b1d8d..0000000000000 --- a/tools/gutenberg/copy-gutenberg-build.js +++ /dev/null @@ -1,1135 +0,0 @@ -#!/usr/bin/env node - -/** - * Copy Gutenberg Build Script - * - * This script copies and transforms Gutenberg's build output to WordPress Core. - * It handles path transformations from plugin structure to Core structure. - * - * @package WordPress - */ - -const fs = require( 'fs' ); -const path = require( 'path' ); -const json2php = require( 'json2php' ); - -// Paths -const rootDir = path.resolve( __dirname, '../..' ); -const gutenbergDir = path.join( rootDir, 'gutenberg' ); -const gutenbergBuildDir = path.join( gutenbergDir, 'build' ); -const gutenbergPackagesDir = path.join( gutenbergDir, 'packages' ); - -// Determine build target from command line argument (--dev or --build-dir) -// Default to 'src' for development -const args = process.argv.slice( 2 ); -const buildDirArg = args.find( ( arg ) => arg.startsWith( '--build-dir=' ) ); -const buildTarget = buildDirArg - ? buildDirArg.split( '=' )[ 1 ] - : args.includes( '--dev' ) - ? 'src' - : 'build'; - -const wpIncludesDir = path.join( rootDir, buildTarget, 'wp-includes' ); - -/** - * Copy configuration. - * Defines what to copy from Gutenberg build and where it goes in Core. - */ -const COPY_CONFIG = { - // PHP infrastructure files (to wp-includes/build/) - phpInfrastructure: { - destination: 'build', - files: [ 'routes.php', 'pages.php' ], - directories: [ 'pages', 'routes' ], - }, - - // JavaScript packages (to wp-includes/js/dist/) - scripts: { - source: 'scripts', - destination: 'js/dist', - copyDirectories: true, // Copy subdirectories - patterns: [ '*.js', '*.js.map' ], - // Rename vendors/ to vendor/ when copying - directoryRenames: { - vendors: 'vendor', - }, - }, - - // Script modules (to wp-includes/js/dist/script-modules/) - modules: { - source: 'modules', - destination: 'js/dist/script-modules', - copyAll: true, - }, - - // Styles (to wp-includes/css/dist/) - styles: { - source: 'styles', - destination: 'css/dist', - copyAll: true, - }, - - // Blocks (to wp-includes/blocks/) - // Unified configuration for all block types - blocks: { - destination: 'blocks', - sources: [ - { - // Block library blocks - name: 'block-library', - scripts: 'scripts/block-library', - styles: 'styles/block-library', - php: 'block-library/src', - }, - { - // Widget blocks - name: 'widgets', - scripts: 'scripts/widgets/blocks', - styles: 'styles/widgets', - php: 'widgets/src/blocks', - }, - ], - }, - - // PHP source files (non-block files, copied from packages) - phpSource: { - files: [ - { - // Block parser classes - package: 'block-serialization-default-parser', - files: [ - 'class-wp-block-parser.php', - 'class-wp-block-parser-block.php', - 'class-wp-block-parser-frame.php', - ], - destination: '', // Root of wp-includes - }, - ], - }, - - // Theme JSON files (from Gutenberg lib directory) - themeJson: { - files: [ - { from: 'theme.json', to: 'theme.json' }, - { from: 'theme-i18n.json', to: 'theme-i18n.json' }, - ], - }, -}; - -/** - * Check if a block is experimental by reading its block.json. - * - * @param {string} blockJsonPath - Path to block.json file. - * @return {boolean} True if block is experimental. - */ -function isExperimentalBlock( blockJsonPath ) { - try { - if ( ! fs.existsSync( blockJsonPath ) ) { - return false; - } - const blockJson = JSON.parse( - fs.readFileSync( blockJsonPath, 'utf8' ) - ); - return !! blockJson.__experimental; - } catch ( error ) { - return false; - } -} - -/** - * Recursively copy directory. - * - * @param {string} src - Source directory. - * @param {string} dest - Destination directory. - * @param {Function} transform - Optional transform function for file contents. - * @param {Object} options - Optional configuration. - * @param {boolean} options.excludePHP - Skip PHP files. - * @param {boolean} options.excludeExperimental - Skip experimental blocks. - */ -function copyDirectory( src, dest, transform = null, options = {} ) { - if ( ! fs.existsSync( src ) ) { - return; - } - - fs.mkdirSync( dest, { recursive: true } ); - - const entries = fs.readdirSync( src, { withFileTypes: true } ); - - for ( const entry of entries ) { - const srcPath = path.join( src, entry.name ); - const destPath = path.join( dest, entry.name ); - - if ( entry.isDirectory() ) { - // Check if this directory is an experimental block - if ( options.excludeExperimental ) { - const blockJsonPath = path.join( srcPath, 'block.json' ); - if ( isExperimentalBlock( blockJsonPath ) ) { - continue; - } - } - - copyDirectory( srcPath, destPath, transform, options ); - } else { - // Skip PHP files if excludePHP is true - if ( options.excludePHP && /\.php$/.test( entry.name ) ) { - continue; - } - - let content = fs.readFileSync( srcPath ); - - // Apply transformation if provided and file is text - if ( transform && /\.(php|js|css)$/.test( entry.name ) ) { - try { - content = transform( - content.toString(), - srcPath, - destPath - ); - } catch ( error ) { - console.error( - ` āš ļø Transform error in ${ entry.name }:`, - error.message - ); - } - } - - fs.writeFileSync( destPath, content ); - } - } -} - -/** - * Copy all assets for blocks from Gutenberg to Core. - * Handles scripts, styles, PHP, and JSON for all block types in a unified way. - * - * @param {Object} config - Block configuration from COPY_CONFIG.blocks - */ -function copyBlockAssets( config ) { - const blocksDest = path.join( wpIncludesDir, config.destination ); - - for ( const source of config.sources ) { - const scriptsSrc = path.join( gutenbergBuildDir, source.scripts ); - const stylesSrc = path.join( gutenbergBuildDir, source.styles ); - const phpSrc = path.join( gutenbergPackagesDir, source.php ); - - if ( ! fs.existsSync( scriptsSrc ) ) { - continue; - } - - // Get all block directories from the scripts source - const blockDirs = fs - .readdirSync( scriptsSrc, { withFileTypes: true } ) - .filter( ( entry ) => entry.isDirectory() ) - .map( ( entry ) => entry.name ); - - for ( const blockName of blockDirs ) { - // Skip experimental blocks - const blockJsonPath = path.join( - scriptsSrc, - blockName, - 'block.json' - ); - if ( isExperimentalBlock( blockJsonPath ) ) { - continue; - } - - const blockDest = path.join( blocksDest, blockName ); - fs.mkdirSync( blockDest, { recursive: true } ); - - // 1. Copy scripts/JSON (everything except PHP) - const blockScriptsSrc = path.join( scriptsSrc, blockName ); - if ( fs.existsSync( blockScriptsSrc ) ) { - const files = fs.readdirSync( blockScriptsSrc ); - for ( const file of files ) { - if ( file.endsWith( '.php' ) ) { - continue; // Skip PHP, copied from packages - } - fs.copyFileSync( - path.join( blockScriptsSrc, file ), - path.join( blockDest, file ) - ); - } - } - - // 2. Copy styles (if they exist in per-block directory) - const blockStylesSrc = path.join( stylesSrc, blockName ); - if ( fs.existsSync( blockStylesSrc ) ) { - const cssFiles = fs - .readdirSync( blockStylesSrc ) - .filter( ( file ) => file.endsWith( '.css' ) ); - for ( const cssFile of cssFiles ) { - fs.copyFileSync( - path.join( blockStylesSrc, cssFile ), - path.join( blockDest, cssFile ) - ); - } - } - - // 3. Copy PHP from packages - const blockPhpSrc = path.join( phpSrc, blockName, 'index.php' ); - if ( fs.existsSync( blockPhpSrc ) ) { - const phpDest = path.join( - wpIncludesDir, - config.destination, - `${ blockName }.php` - ); - const content = fs.readFileSync( blockPhpSrc, 'utf8' ); - fs.writeFileSync( phpDest, content ); - } - } - - console.log( - ` āœ… ${ source.name } blocks copied (${ blockDirs.length } blocks)` - ); - } -} - -/** - * Generate script-modules-packages.min.php from individual asset files. - * Reads all view.min.asset.php files from modules/block-library and combines them - * into a single PHP file. - */ -function generateScriptModulesPackages() { - const modulesDir = path.join( gutenbergBuildDir, 'modules' ); - const assetsMin = {}; - const assetsRegular = {}; - - /** - * Recursively process directory to find .asset.php files. - * - * @param {string} dir - Directory to process. - * @param {string} baseDir - Base directory for relative paths. - */ - function processDirectory( dir, baseDir ) { - if ( ! fs.existsSync( dir ) ) { - return; - } - - const entries = fs.readdirSync( dir, { withFileTypes: true } ); - - for ( const entry of entries ) { - const fullPath = path.join( dir, entry.name ); - - if ( entry.isDirectory() ) { - processDirectory( fullPath, baseDir ); - } else if ( entry.name.endsWith( '.min.asset.php' ) ) { - const relativePath = path.relative( baseDir, fullPath ); - // Normalize path separators to forward slashes for cross-platform consistency - const normalizedPath = relativePath - .split( path.sep ) - .join( '/' ); - const jsPathMin = normalizedPath.replace( - /\.asset\.php$/, - '.js' - ); - const jsPathRegular = jsPathMin.replace( /\.min\.js$/, '.js' ); - - try { - // Read and parse the PHP asset file - const phpContent = fs.readFileSync( fullPath, 'utf8' ); - // Extract the array from PHP: `require_once ABSPATH . WPINC . '/blocks/${ name }.php';` - ) - .join( '\n' ) } -`; - - fs.writeFileSync( - path.join( wpIncludesDir, 'blocks/require-dynamic-blocks.php' ), - dynamicContent - ); - - // Generate require-static-blocks.php - const staticContent = ` `\t'${ name }',` ).join( '\n' ) } -); -`; - - fs.writeFileSync( - path.join( wpIncludesDir, 'blocks/require-static-blocks.php' ), - staticContent - ); - - console.log( - ` āœ… Generated: ${ dynamicBlocks.length } dynamic, ${ staticBlocks.length } static blocks` - ); -} - -/** - * Generate blocks-json.php from all block.json files. - * Reads all block.json files and combines them into a single PHP array. - * Uses json2php to maintain consistency with Core's formatting. - */ -function generateBlocksJson() { - const blocksDir = path.join( wpIncludesDir, 'blocks' ); - const blocks = {}; - - if ( ! fs.existsSync( blocksDir ) ) { - console.error( ' āš ļø Blocks directory not found' ); - return; - } - - const entries = fs.readdirSync( blocksDir, { withFileTypes: true } ); - - for ( const entry of entries ) { - if ( ! entry.isDirectory() ) { - continue; - } - - const blockJsonPath = path.join( blocksDir, entry.name, 'block.json' ); - - if ( fs.existsSync( blockJsonPath ) ) { - try { - const blockJson = JSON.parse( - fs.readFileSync( blockJsonPath, 'utf8' ) - ); - blocks[ entry.name ] = blockJson; - } catch ( error ) { - console.error( - ` āš ļø Error reading ${ entry.name }/block.json:`, - error.message - ); - } - } - } - - // Generate the PHP file content using json2php for consistent formatting - const phpContent = - ' 1 ) { - currentArray += 'array('; - } - i += 5; // Skip 'array(' - continue; - } - - if ( depth > 0 ) { - if ( char === '(' ) { - depth++; - currentArray += char; - } else if ( char === ')' ) { - depth--; - if ( depth === 0 ) { - // Found complete nested array - const placeholder = `__ARRAY_${ nestedArrays.length }__`; - nestedArrays.push( currentArray ); - content = - content.substring( 0, arrayStart ) + - placeholder + - content.substring( i + 1 ); - i = arrayStart + placeholder.length - 1; - currentArray = ''; - } else { - currentArray += char; - } - } else { - currentArray += char; - } - } - } else if ( depth > 0 ) { - currentArray += char; - } - } - - // Now parse the simplified content - const result = {}; - const values = []; - let isAssociative = false; - - // Split by top-level commas - const parts = []; - depth = 0; - inString = false; - let currentPart = ''; - - for ( let i = 0; i < content.length; i++ ) { - const char = content[ i ]; - - if ( - ( char === "'" || char === '"' ) && - ( i === 0 || content[ i - 1 ] !== '\\' ) - ) { - inString = ! inString; - } - - if ( ! inString && char === ',' && depth === 0 ) { - parts.push( currentPart.trim() ); - currentPart = ''; - } else { - currentPart += char; - if ( ! inString ) { - if ( char === '(' ) depth++; - if ( char === ')' ) depth--; - } - } - } - if ( currentPart.trim() ) { - parts.push( currentPart.trim() ); - } - - // Parse each part - for ( const part of parts ) { - const arrowMatch = part.match( /^(.+?)\s*=>\s*(.+)$/ ); - - if ( arrowMatch ) { - isAssociative = true; - let key = arrowMatch[ 1 ].trim().replace( /^['"]|['"]$/g, '' ); - let value = arrowMatch[ 2 ].trim(); - - // Replace placeholders - while ( value.match( /__ARRAY_(\d+)__/ ) ) { - value = value.replace( /__ARRAY_(\d+)__/, ( match, index ) => { - return 'array(' + nestedArrays[ parseInt( index ) ] + ')'; - } ); - } - - result[ key ] = parseValue( value ); - } else { - // No arrow, indexed array - let value = part; - - // Replace placeholders - while ( value.match( /__ARRAY_(\d+)__/ ) ) { - value = value.replace( /__ARRAY_(\d+)__/, ( match, index ) => { - return 'array(' + nestedArrays[ parseInt( index ) ] + ')'; - } ); - } - - values.push( parseValue( value ) ); - } - } - - return isAssociative ? result : values; - - /** - * Parse a single value. - * - * @param {string} value - The value string to parse. - * @return {*} Parsed value. - */ - function parseValue( value ) { - value = value.trim(); - - if ( value.startsWith( 'array(' ) && value.endsWith( ')' ) ) { - return parsePHPArray( value.substring( 6, value.length - 1 ) ); - } else if ( value.match( /^['"].*['"]$/ ) ) { - return value.substring( 1, value.length - 1 ); - } else if ( value === 'true' ) { - return true; - } else if ( value === 'false' ) { - return false; - } else if ( ! isNaN( value ) && value !== '' ) { - return parseInt( value, 10 ); - } - return value; - } -} - -/** - * Transform PHP file contents to work in Core. - * - * @param {string} content - File content. - * @return {string} Transformed content. - */ -function transformPHPContent( content ) { - let transformed = content; - - // Fix boot module asset file path for Core's different directory structure - // FROM: __DIR__ . '/../../modules/boot/index.min.asset.php' - // TO: ABSPATH . WPINC . '/js/dist/script-modules/boot/index.min.asset.php' - // This is needed because Core copies modules to a different location than the plugin structure - transformed = transformed.replace( - /__DIR__\s*\.\s*['"]\/\.\.\/\.\.\/modules\/boot\/index\.min\.asset\.php['"]/g, - "ABSPATH . WPINC . '/js/dist/script-modules/boot/index.min.asset.php'" - ); - - return transformed; -} - -/** - * Main execution function. - */ -async function main() { - console.log( 'šŸ” Checking Gutenberg build...' ); - console.log( ` Build target: ${ buildTarget }/` ); - - // Verify Gutenberg build exists - if ( ! fs.existsSync( gutenbergBuildDir ) ) { - console.error( 'āŒ Gutenberg build directory not found' ); - console.error( ' Run: node tools/gutenberg/build-gutenberg.js' ); - process.exit( 1 ); - } - - console.log( 'āœ… Gutenberg build found' ); - - // 1. Copy PHP infrastructure - console.log( '\nšŸ“¦ Copying PHP infrastructure...' ); - const phpConfig = COPY_CONFIG.phpInfrastructure; - const phpDest = path.join( wpIncludesDir, phpConfig.destination ); - - // Copy PHP files - for ( const file of phpConfig.files ) { - const src = path.join( gutenbergBuildDir, file ); - const dest = path.join( phpDest, file ); - - if ( fs.existsSync( src ) ) { - fs.mkdirSync( path.dirname( dest ), { recursive: true } ); - let content = fs.readFileSync( src, 'utf8' ); - content = transformPHPContent( content ); - fs.writeFileSync( dest, content ); - console.log( ` āœ… ${ file }` ); - } else { - console.log( - ` āš ļø ${ file } not found (may not exist in this Gutenberg version)` - ); - } - } - - // Copy PHP directories - for ( const dir of phpConfig.directories ) { - const src = path.join( gutenbergBuildDir, dir ); - const dest = path.join( phpDest, dir ); - - if ( fs.existsSync( src ) ) { - console.log( ` šŸ“ Copying ${ dir }/...` ); - copyDirectory( src, dest, transformPHPContent ); - console.log( ` āœ… ${ dir }/ copied` ); - } - } - - // 2. Copy JavaScript packages - console.log( '\nšŸ“¦ Copying JavaScript packages...' ); - const scriptsConfig = COPY_CONFIG.scripts; - const scriptsSrc = path.join( gutenbergBuildDir, scriptsConfig.source ); - const scriptsDest = path.join( wpIncludesDir, scriptsConfig.destination ); - - // Transform function to remove source map comments from all JS files - const removeSourceMaps = ( content ) => { - return content.replace( /\/\/# sourceMappingURL=.*$/m, '' ).trimEnd(); - }; - - if ( fs.existsSync( scriptsSrc ) ) { - const entries = fs.readdirSync( scriptsSrc, { withFileTypes: true } ); - - for ( const entry of entries ) { - const src = path.join( scriptsSrc, entry.name ); - - if ( entry.isDirectory() ) { - // Check if this should be copied as a directory (like vendors/) - if ( - scriptsConfig.copyDirectories && - scriptsConfig.directoryRenames && - scriptsConfig.directoryRenames[ entry.name ] - ) { - // Copy special directories with rename (vendors/ → vendor/) - // Only copy react-jsx-runtime from vendors (react and react-dom come from Core's node_modules) - const destName = - scriptsConfig.directoryRenames[ entry.name ]; - const dest = path.join( scriptsDest, destName ); - - if ( entry.name === 'vendors' ) { - // Only copy react-jsx-runtime files, skip react and react-dom - const vendorFiles = fs.readdirSync( src ); - let copiedCount = 0; - for ( const file of vendorFiles ) { - if ( file.startsWith( 'react-jsx-runtime' ) ) { - const srcFile = path.join( src, file ); - const destFile = path.join( dest, file ); - fs.mkdirSync( dest, { recursive: true } ); - - if ( - file.endsWith( '.js' ) && - ! file.endsWith( '.js.map' ) - ) { - let content = fs.readFileSync( - srcFile, - 'utf8' - ); - content = removeSourceMaps( content ); - fs.writeFileSync( destFile, content ); - } else { - fs.copyFileSync( srcFile, destFile ); - } - copiedCount++; - } - } - console.log( - ` āœ… ${ entry.name }/ → ${ destName }/ (react-jsx-runtime only, ${ copiedCount } files)` - ); - } else { - // Copy other special directories normally - copyDirectory( src, dest, removeSourceMaps ); - console.log( - ` āœ… ${ entry.name }/ → ${ destName }/` - ); - } - } else { - // Flatten package structure: package-name/index.js → package-name.js - // This matches Core's expected file structure - const packageFiles = fs.readdirSync( src ); - - for ( const file of packageFiles ) { - if ( - /^index\.(js|js\.map|min\.js|min\.js\.map|min\.asset\.php)$/.test( - file - ) - ) { - const srcFile = path.join( src, file ); - // Replace 'index.' with 'package-name.' - const destFile = file.replace( - /^index\./, - `${ entry.name }.` - ); - const destPath = path.join( scriptsDest, destFile ); - - fs.mkdirSync( path.dirname( destPath ), { - recursive: true, - } ); - - // Apply source map removal for .js files - if ( - file.endsWith( '.js' ) && - ! file.endsWith( '.js.map' ) - ) { - let content = fs.readFileSync( - srcFile, - 'utf8' - ); - content = removeSourceMaps( content ); - fs.writeFileSync( destPath, content ); - } else { - // Copy other files as-is - fs.copyFileSync( srcFile, destPath ); - } - } - } - } - } else if ( - entry.isFile() && - /\.(js|js\.map)$/.test( entry.name ) - ) { - // Copy root-level JS files - const dest = path.join( scriptsDest, entry.name ); - fs.mkdirSync( path.dirname( dest ), { recursive: true } ); - - if ( - entry.name.endsWith( '.js' ) && - ! entry.name.endsWith( '.js.map' ) - ) { - let content = fs.readFileSync( src, 'utf8' ); - content = removeSourceMaps( content ); - fs.writeFileSync( dest, content ); - } else { - fs.copyFileSync( src, dest ); - } - } - } - - console.log( ' āœ… JavaScript packages copied' ); - } - - // 3. Copy script modules - console.log( '\nšŸ“¦ Copying script modules...' ); - const modulesConfig = COPY_CONFIG.modules; - const modulesSrc = path.join( gutenbergBuildDir, modulesConfig.source ); - const modulesDest = path.join( wpIncludesDir, modulesConfig.destination ); - - if ( fs.existsSync( modulesSrc ) ) { - // Use the same source map removal transform - copyDirectory( modulesSrc, modulesDest, removeSourceMaps ); - console.log( ' āœ… Script modules copied' ); - } - - // 4. Copy styles - console.log( '\nšŸ“¦ Copying styles...' ); - const stylesConfig = COPY_CONFIG.styles; - const stylesSrc = path.join( gutenbergBuildDir, stylesConfig.source ); - const stylesDest = path.join( wpIncludesDir, stylesConfig.destination ); - - if ( fs.existsSync( stylesSrc ) ) { - copyDirectory( stylesSrc, stylesDest ); - console.log( ' āœ… Styles copied' ); - } - - // 5. Copy blocks (unified: scripts, styles, PHP, JSON) - console.log( '\nšŸ“¦ Copying blocks...' ); - const blocksDest = path.join( - wpIncludesDir, - COPY_CONFIG.blocks.destination - ); - copyBlockAssets( COPY_CONFIG.blocks ); - - // 6. Copy non-block PHP source files (from packages) - console.log( '\nšŸ“¦ Copying non-block PHP files...' ); - const phpSourceConfig = COPY_CONFIG.phpSource; - - for ( const fileGroup of phpSourceConfig.files ) { - const packageSrc = path.join( gutenbergPackagesDir, fileGroup.package ); - - if ( ! fs.existsSync( packageSrc ) ) { - console.log( ` āš ļø Package not found: ${ fileGroup.package }` ); - continue; - } - - for ( const file of fileGroup.files ) { - const src = path.join( packageSrc, file ); - const dest = path.join( - wpIncludesDir, - fileGroup.destination, - file - ); - - if ( fs.existsSync( src ) ) { - fs.mkdirSync( path.dirname( dest ), { recursive: true } ); - let content = fs.readFileSync( src, 'utf8' ); - fs.writeFileSync( dest, content ); - } - } - console.log( - ` āœ… ${ fileGroup.package } (${ fileGroup.files.length } files)` - ); - } - - // 7. Copy theme JSON files (from Gutenberg lib directory) - console.log( '\nšŸ“¦ Copying theme JSON files...' ); - const themeJsonConfig = COPY_CONFIG.themeJson; - const gutenbergLibDir = path.join( gutenbergDir, 'lib' ); - - for ( const fileMap of themeJsonConfig.files ) { - const src = path.join( gutenbergLibDir, fileMap.from ); - const dest = path.join( wpIncludesDir, fileMap.to ); - - if ( fs.existsSync( src ) ) { - let content = fs.readFileSync( src, 'utf8' ); - - if ( themeJsonConfig.transform && fileMap.from === 'theme.json' ) { - // Transform schema URL for Core - content = content.replace( - '"$schema": "../schemas/json/theme.json"', - '"$schema": "https://schemas.wp.org/trunk/theme.json"' - ); - } - - fs.writeFileSync( dest, content ); - console.log( ` āœ… ${ fileMap.to }` ); - } else { - console.log( ` āš ļø Not found: ${ fileMap.from }` ); - } - } - - // 9. Generate script-modules-packages.min.php from individual asset files - console.log( '\nšŸ“¦ Generating script-modules-packages.min.php...' ); - generateScriptModulesPackages(); - - // 10. Generate script-loader-packages.min.php - console.log( '\nšŸ“¦ Generating script-loader-packages.min.php...' ); - generateScriptLoaderPackages(); - - // 11. Generate require-dynamic-blocks.php and require-static-blocks.php - console.log( '\nšŸ“¦ Generating block registration files...' ); - generateBlockRegistrationFiles(); - - // 12. Generate blocks-json.php from block.json files - console.log( '\nšŸ“¦ Generating blocks-json.php...' ); - generateBlocksJson(); - - // Summary - console.log( '\nāœ… Copy complete!' ); - console.log( '\nšŸ“Š Summary:' ); - console.log( ` PHP infrastructure: ${ phpDest }` ); - console.log( ` JavaScript: ${ scriptsDest }` ); - console.log( ` Script modules: ${ modulesDest }` ); - console.log( ` Styles: ${ stylesDest }` ); - console.log( ` Blocks: ${ blocksDest }` ); -} - -// Run main function -main().catch( ( error ) => { - console.error( 'āŒ Unexpected error:', error ); - process.exit( 1 ); -} ); diff --git a/tools/vendors/copy-vendors.js b/tools/vendors/copy-vendors.js deleted file mode 100644 index 12660fc639645..0000000000000 --- a/tools/vendors/copy-vendors.js +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env node - -/** - * Copy Vendor Scripts - * - * This script copies vendor dependencies from node_modules to wp-includes/js/dist/vendor/. - * These are Core's own dependencies (moment, lodash, regenerator-runtime, polyfills, etc.) - * separate from Gutenberg packages. - * - * @package WordPress - */ - -const fs = require( 'fs' ); -const path = require( 'path' ); - -// Paths -const rootDir = path.resolve( __dirname, '../..' ); -const nodeModulesDir = path.join( rootDir, 'node_modules' ); - -// Parse command line arguments -const args = process.argv.slice( 2 ); -const buildDirArg = args.find( arg => arg.startsWith( '--build-dir=' ) ); -const buildTarget = buildDirArg - ? buildDirArg.split( '=' )[1] - : ( args.includes( '--dev' ) ? 'src' : 'build' ); - -const vendorDir = path.join( rootDir, buildTarget, 'wp-includes/js/dist/vendor' ); - -/** - * Vendor files to copy from node_modules. - */ -const VENDOR_FILES = { - // Moment.js - 'moment': { - files: [ - { from: 'moment/moment.js', to: 'moment.js' }, - { from: 'moment/min/moment.min.js', to: 'moment.min.js' }, - ], - }, - - // Lodash - 'lodash': { - files: [ - { from: 'lodash/lodash.js', to: 'lodash.js' }, - { from: 'lodash/lodash.min.js', to: 'lodash.min.js' }, - ], - }, - - // Regenerator Runtime - 'regenerator-runtime': { - files: [ - { from: 'regenerator-runtime/runtime.js', to: 'regenerator-runtime.js' }, - { from: 'regenerator-runtime/runtime.js', to: 'regenerator-runtime.min.js' }, - ], - }, - - // React (UMD builds from node_modules) - 'react': { - files: [ - { from: 'react/umd/react.development.js', to: 'react.js' }, - { from: 'react/umd/react.production.min.js', to: 'react.min.js' }, - ], - }, - - // React DOM (UMD builds from node_modules) - 'react-dom': { - files: [ - { from: 'react-dom/umd/react-dom.development.js', to: 'react-dom.js' }, - { from: 'react-dom/umd/react-dom.production.min.js', to: 'react-dom.min.js' }, - ], - }, - - // Main Polyfill bundle - 'wp-polyfill': { - files: [ - { from: '@wordpress/babel-preset-default/build/polyfill.js', to: 'wp-polyfill.js' }, - { from: '@wordpress/babel-preset-default/build/polyfill.min.js', to: 'wp-polyfill.min.js' }, - ], - }, - - // Polyfills - Fetch (same source for both - was minified by webpack) - 'wp-polyfill-fetch': { - files: [ - { from: 'whatwg-fetch/dist/fetch.umd.js', to: 'wp-polyfill-fetch.js' }, - { from: 'whatwg-fetch/dist/fetch.umd.js', to: 'wp-polyfill-fetch.min.js' }, - ], - }, - - // Polyfills - FormData - 'wp-polyfill-formdata': { - files: [ - { from: 'formdata-polyfill/FormData.js', to: 'wp-polyfill-formdata.js' }, - { from: 'formdata-polyfill/formdata.min.js', to: 'wp-polyfill-formdata.min.js' }, - ], - }, - - // Polyfills - Element Closest (same for both) - 'wp-polyfill-element-closest': { - files: [ - { from: 'element-closest/browser.js', to: 'wp-polyfill-element-closest.js' }, - { from: 'element-closest/browser.js', to: 'wp-polyfill-element-closest.min.js' }, - ], - }, - - // Polyfills - Object Fit - 'wp-polyfill-object-fit': { - files: [ - { from: 'objectFitPolyfill/src/objectFitPolyfill.js', to: 'wp-polyfill-object-fit.js' }, - { from: 'objectFitPolyfill/dist/objectFitPolyfill.min.js', to: 'wp-polyfill-object-fit.min.js' }, - ], - }, - - // Polyfills - Inert - 'wp-polyfill-inert': { - files: [ - { from: 'wicg-inert/dist/inert.js', to: 'wp-polyfill-inert.js' }, - { from: 'wicg-inert/dist/inert.min.js', to: 'wp-polyfill-inert.min.js' }, - ], - }, - - // Polyfills - URL - 'wp-polyfill-url': { - files: [ - { from: 'core-js-url-browser/url.js', to: 'wp-polyfill-url.js' }, - { from: 'core-js-url-browser/url.min.js', to: 'wp-polyfill-url.min.js' }, - ], - }, - - // Polyfills - DOMRect (same source for both - was minified by webpack) - 'wp-polyfill-dom-rect': { - files: [ - { from: 'polyfill-library/polyfills/__dist/DOMRect/raw.js', to: 'wp-polyfill-dom-rect.js' }, - { from: 'polyfill-library/polyfills/__dist/DOMRect/raw.js', to: 'wp-polyfill-dom-rect.min.js' }, - ], - }, - - // Polyfills - Node.contains (same source for both - was minified by webpack) - 'wp-polyfill-node-contains': { - files: [ - { from: 'polyfill-library/polyfills/__dist/Node.prototype.contains/raw.js', to: 'wp-polyfill-node-contains.js' }, - { from: 'polyfill-library/polyfills/__dist/Node.prototype.contains/raw.js', to: 'wp-polyfill-node-contains.min.js' }, - ], - }, -}; - -/** - * Main execution function. - */ -async function main() { - console.log( 'šŸ“¦ Copying vendor scripts from node_modules...' ); - console.log( ` Build target: ${ buildTarget }/` ); - - // Create vendor directory - fs.mkdirSync( vendorDir, { recursive: true } ); - - let copied = 0; - let skipped = 0; - - for ( const [ vendor, config ] of Object.entries( VENDOR_FILES ) ) { - for ( const file of config.files ) { - const srcPath = path.join( nodeModulesDir, file.from ); - const destPath = path.join( vendorDir, file.to ); - - if ( fs.existsSync( srcPath ) ) { - fs.copyFileSync( srcPath, destPath ); - copied++; - } else { - console.log( ` āš ļø Skipping ${ file.to }: source not found` ); - skipped++; - } - } - } - - console.log( `\nāœ… Vendor scripts copied!` ); - console.log( ` Copied: ${ copied } files` ); - if ( skipped > 0 ) { - console.log( ` Skipped: ${ skipped } files` ); - } -} - -// Run main function -main().catch( ( error ) => { - console.error( 'āŒ Unexpected error:', error ); - process.exit( 1 ); -} ); diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js new file mode 100644 index 0000000000000..f1c9d20cd8504 --- /dev/null +++ b/tools/webpack/blocks.js @@ -0,0 +1,146 @@ +/** + * External dependencies + */ +const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); + +/** + * Internal dependencies + */ +const { + baseDir, + getBaseConfig, + normalizeJoin, + stylesTransform, +} = require( './shared' ); +const { + isDynamic, + toDirectoryName, + getStableBlocksMetadata, +} = require( '../release/sync-stable-blocks' ); + +module.exports = function ( + env = { environment: 'production', watch: false, buildTarget: false } +) { + const mode = env.environment; + const suffix = mode === 'production' ? '.min' : ''; + let buildTarget = env.buildTarget + ? env.buildTarget + : mode === 'production' + ? 'build' + : 'src'; + buildTarget = buildTarget + '/wp-includes'; + + const blocks = getStableBlocksMetadata(); + const dynamicBlockFolders = blocks + .filter( isDynamic ) + .map( toDirectoryName ); + const blockFolders = blocks.map( toDirectoryName ); + const blockPHPFiles = { + 'widgets/src/blocks/legacy-widget/index.php': + 'wp-includes/blocks/legacy-widget.php', + 'widgets/src/blocks/widget-group/index.php': + 'wp-includes/blocks/widget-group.php', + ...dynamicBlockFolders.reduce( ( files, blockName ) => { + files[ + `block-library/src/${ blockName }/index.php` + ] = `wp-includes/blocks/${ blockName }.php`; + return files; + }, {} ), + }; + const blockMetadataFiles = { + 'widgets/src/blocks/legacy-widget/block.json': + 'wp-includes/blocks/legacy-widget/block.json', + 'widgets/src/blocks/widget-group/block.json': + 'wp-includes/blocks/widget-group/block.json', + ...blockFolders.reduce( ( files, blockName ) => { + files[ + `block-library/src/${ blockName }/block.json` + ] = `wp-includes/blocks/${ blockName }/block.json`; + return files; + }, {} ), + }; + + const blockPHPCopies = Object.keys( blockPHPFiles ).map( ( filename ) => ( { + from: normalizeJoin( baseDir, `node_modules/@wordpress/${ filename }` ), + to: normalizeJoin( baseDir, `src/${ blockPHPFiles[ filename ] }` ), + } ) ); + + const blockMetadataCopies = Object.keys( blockMetadataFiles ).map( + ( filename ) => ( { + from: normalizeJoin( + baseDir, + `node_modules/@wordpress/${ filename }` + ), + to: normalizeJoin( + baseDir, + `src/${ blockMetadataFiles[ filename ] }` + ), + } ) + ); + + const blockStylesheetCopies = blockFolders.map( ( blockName ) => ( { + from: normalizeJoin( + baseDir, + `node_modules/@wordpress/block-library/build-style/${ blockName }/*.css` + ), + to: normalizeJoin( + baseDir, + `${ buildTarget }/blocks/${ blockName }/[name]${ suffix }.css` + ), + transform: stylesTransform( mode ), + noErrorOnMissing: true, + } ) ); + + // Todo: This list need of entry points need to be automatically fetched from the package + // We shouldn't have to maintain it manually. + const interactiveBlocks = [ + 'navigation', + 'image', + 'query', + 'file', + 'search', + ]; + + const baseConfig = getBaseConfig( env ); + const config = { + ...baseConfig, + entry: interactiveBlocks.reduce(( memo, blockName ) => { + memo[ blockName ] = { + import: normalizeJoin( + baseDir, + `node_modules/@wordpress/block-library/build-module/${ blockName }/view` + ), + }; + return memo; + }, {}), + experiments: { + outputModule: true, + }, + output: { + devtoolNamespace: 'wp', + filename: `./blocks/[name]/view${ suffix }.js`, + path: normalizeJoin( baseDir, buildTarget ), + library: { + type: 'module', + }, + environment: { module: true }, + }, + externalsType: 'module', + externals: { + '@wordpress/interactivity': '@wordpress/interactivity', + '@wordpress/interactivity-router': 'import @wordpress/interactivity-router', + }, + plugins: [ + ...baseConfig.plugins, + new CopyWebpackPlugin( { + patterns: [ + ...blockPHPCopies, + ...blockMetadataCopies, + ...blockStylesheetCopies, + ], + } ), + ], + }; + + return config; +}; diff --git a/tools/webpack/development.js b/tools/webpack/development.js new file mode 100644 index 0000000000000..316c5bc4f72b5 --- /dev/null +++ b/tools/webpack/development.js @@ -0,0 +1,61 @@ +/** + * External dependencies + */ +const { join } = require( 'path' ); + +/** + * WordPress dependencies + */ +const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); + +const baseDir = join( __dirname, '../../' ); + +module.exports = function( env = { environment: 'production', buildTarget: false } ) { + const mode = env.environment; + const suffix = mode === 'production' ? '.min' : ''; + let buildTarget = env.buildTarget ? env.buildTarget : ( mode === 'production' ? 'build' : 'src' ); + buildTarget = buildTarget + '/wp-includes'; + + const sharedConfig = { + mode: 'development', + target: 'browserslist', + output: { + filename: `[name]${ suffix }.js`, + path: join( baseDir, `${ buildTarget }/js/dist/development` ), + }, + }; + + // See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react. + return [ + { + ...sharedConfig, + name: 'react-refresh-entry', + entry: { + 'react-refresh-entry': + '@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js', + }, + plugins: [ new DependencyExtractionWebpackPlugin( { + outputFilename: `../../../assets/script-loader-[name]${ suffix }.php`, + } ) ], + }, + { + ...sharedConfig, + name: 'react-refresh-runtime', + entry: { + 'react-refresh-runtime': { + import: 'react-refresh/runtime', + library: { + name: 'ReactRefreshRuntime', + type: 'window', + }, + }, + }, + plugins: [ + new DependencyExtractionWebpackPlugin( { + useDefaults: false, + outputFilename: `../../../assets/script-loader-[name]${ suffix }.php` + } ), + ], + }, + ]; +}; diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js new file mode 100644 index 0000000000000..f431d43b682ee --- /dev/null +++ b/tools/webpack/packages.js @@ -0,0 +1,218 @@ +/** + * External dependencies + */ +const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); +const LiveReloadPlugin = require( 'webpack-livereload-plugin' ); +const UglifyJS = require( 'uglify-js' ); + +/** + * WordPress dependencies + */ +const { + camelCaseDash, +} = require( '@wordpress/dependency-extraction-webpack-plugin/lib/util' ); +const DependencyExtractionPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); + +/** + * Internal dependencies + */ +const { + baseDir, + getBaseConfig, + normalizeJoin, + stylesTransform, + BUNDLED_PACKAGES, + MODULES, + WORDPRESS_NAMESPACE, +} = require( './shared' ); +const { dependencies } = require( '../../package' ); + +const exportDefaultPackages = [ + 'api-fetch', + 'deprecated', + 'dom-ready', + 'redux-routine', + 'token-list', + 'server-side-render', + 'shortcode', + 'warning', +]; + +/** + * Maps vendors to copy commands for the CopyWebpackPlugin. + * + * @param {Object} vendors Vendors to include in the vendor folder. + * @param {string} buildTarget The folder in which to build the packages. + * + * @return {Object[]} Copy object suitable for the CopyWebpackPlugin. + */ +function mapVendorCopies( vendors, buildTarget ) { + return Object.keys( vendors ).map( ( filename ) => ( { + from: normalizeJoin( baseDir, `node_modules/${ vendors[ filename ] }` ), + to: normalizeJoin( + baseDir, + `${ buildTarget }/js/dist/vendor/${ filename }` + ), + } ) ); +} + +module.exports = function ( + env = { environment: 'production', watch: false, buildTarget: false } +) { + const mode = env.environment; + const suffix = mode === 'production' ? '.min' : ''; + let buildTarget = env.buildTarget + ? env.buildTarget + : mode === 'production' + ? 'build' + : 'src'; + buildTarget = buildTarget + '/wp-includes'; + + const packages = Object.keys( dependencies ) + .filter( + ( packageName ) => + ! BUNDLED_PACKAGES.includes( packageName ) && + ! MODULES.includes( packageName ) && + packageName.startsWith( WORDPRESS_NAMESPACE ) + ) + .map( ( packageName ) => + packageName.replace( WORDPRESS_NAMESPACE, '' ) + ); + + const vendors = { + 'lodash.js': 'lodash/lodash.js', + 'wp-polyfill.js': '@wordpress/babel-preset-default/build/polyfill.js', + 'wp-polyfill-fetch.js': 'whatwg-fetch/dist/fetch.umd.js', + 'wp-polyfill-element-closest.js': 'element-closest/browser.js', + 'wp-polyfill-node-contains.js': + 'polyfill-library/polyfills/__dist/Node.prototype.contains/raw.js', + 'wp-polyfill-url.js': 'core-js-url-browser/url.js', + 'wp-polyfill-dom-rect.js': + 'polyfill-library/polyfills/__dist/DOMRect/raw.js', + 'wp-polyfill-formdata.js': 'formdata-polyfill/FormData.js', + 'wp-polyfill-object-fit.js': + 'objectFitPolyfill/src/objectFitPolyfill.js', + 'wp-polyfill-inert.js': 'wicg-inert/dist/inert.js', + 'moment.js': 'moment/moment.js', + 'regenerator-runtime.js': 'regenerator-runtime/runtime.js', + 'react.js': 'react/umd/react.development.js', + 'react-dom.js': 'react-dom/umd/react-dom.development.js', + }; + + const minifiedVendors = { + 'lodash.min.js': 'lodash/lodash.min.js', + 'wp-polyfill.min.js': + '@wordpress/babel-preset-default/build/polyfill.min.js', + 'wp-polyfill-element-closest.min.js': 'element-closest/browser.js', + 'wp-polyfill-formdata.min.js': 'formdata-polyfill/formdata.min.js', + 'wp-polyfill-url.min.js': 'core-js-url-browser/url.min.js', + 'wp-polyfill-object-fit.min.js': + 'objectFitPolyfill/dist/objectFitPolyfill.min.js', + 'wp-polyfill-inert.min.js': 'wicg-inert/dist/inert.min.js', + 'moment.min.js': 'moment/min/moment.min.js', + 'react.min.js': 'react/umd/react.production.min.js', + 'react-dom.min.js': 'react-dom/umd/react-dom.production.min.js', + }; + + const minifyVendors = { + 'regenerator-runtime.min.js': 'regenerator-runtime/runtime.js', + 'wp-polyfill-fetch.min.js': 'whatwg-fetch/dist/fetch.umd.js', + 'wp-polyfill-node-contains.min.js': + 'polyfill-library/polyfills/__dist/Node.prototype.contains/raw.js', + 'wp-polyfill-dom-rect.min.js': + 'polyfill-library/polyfills/__dist/DOMRect/raw.js', + }; + + const phpFiles = { + 'block-serialization-default-parser/class-wp-block-parser.php': + 'wp-includes/class-wp-block-parser.php', + 'block-serialization-default-parser/class-wp-block-parser-frame.php': + 'wp-includes/class-wp-block-parser-frame.php', + 'block-serialization-default-parser/class-wp-block-parser-block.php': + 'wp-includes/class-wp-block-parser-block.php', + }; + + const developmentCopies = mapVendorCopies( vendors, buildTarget ); + const minifiedCopies = mapVendorCopies( minifiedVendors, buildTarget ); + const minifyCopies = mapVendorCopies( minifyVendors, buildTarget ).map( + ( copyCommand ) => { + return { + ...copyCommand, + transform: ( content ) => { + return UglifyJS.minify( content.toString() ).code; + }, + }; + } + ); + + let vendorCopies = + mode === 'development' + ? developmentCopies + : [ ...minifiedCopies, ...minifyCopies ]; + + let cssCopies = packages.map( ( packageName ) => ( { + from: normalizeJoin( + baseDir, + `node_modules/@wordpress/${ packageName }/build-style/*.css` + ), + to: normalizeJoin( + baseDir, + `${ buildTarget }/css/dist/${ packageName }/[name]${ suffix }.css` + ), + transform: stylesTransform( mode ), + noErrorOnMissing: true, + } ) ); + + const phpCopies = Object.keys( phpFiles ).map( ( filename ) => ( { + from: normalizeJoin( baseDir, `node_modules/@wordpress/${ filename }` ), + to: normalizeJoin( baseDir, `src/${ phpFiles[ filename ] }` ), + } ) ); + + const baseConfig = getBaseConfig( env ); + const config = { + ...baseConfig, + entry: packages.reduce( ( memo, packageName ) => { + memo[ packageName ] = { + import: normalizeJoin( + baseDir, + `node_modules/@wordpress/${ packageName }` + ), + library: { + name: [ 'wp', camelCaseDash( packageName ) ], + type: 'window', + export: exportDefaultPackages.includes( packageName ) + ? 'default' + : undefined, + }, + }; + + return memo; + }, {} ), + output: { + devtoolNamespace: 'wp', + filename: `[name]${ suffix }.js`, + path: normalizeJoin( baseDir, `${ buildTarget }/js/dist` ), + }, + plugins: [ + ...baseConfig.plugins, + new DependencyExtractionPlugin( { + injectPolyfill: false, + combineAssets: true, + combinedOutputFile: `../../assets/script-loader-packages${ suffix }.php`, + } ), + new CopyWebpackPlugin( { + patterns: [ ...vendorCopies, ...cssCopies, ...phpCopies ], + } ), + ], + }; + + if ( config.mode === 'development' ) { + config.plugins.push( + new LiveReloadPlugin( { + port: process.env.WORDPRESS_LIVE_RELOAD_PORT || 35729, + } ) + ); + } + + return config; +}; diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js new file mode 100644 index 0000000000000..2c8ae75d01423 --- /dev/null +++ b/tools/webpack/script-modules.js @@ -0,0 +1,126 @@ +/** + * External dependencies + */ +const { createRequire } = require( 'node:module' ); +const { dirname } = require( 'node:path' ); + +/** + * WordPress dependencies + */ +const DependencyExtractionPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); + +/** + * Internal dependencies + */ +const { + baseDir, + getBaseConfig, + normalizeJoin, + MODULES, + SCRIPT_AND_MODULE_DUAL_PACKAGES, + WORDPRESS_NAMESPACE, +} = require( './shared' ); + +/** @type {Map} */ +const scriptModules = new Map(); +for ( const packageName of MODULES.concat( SCRIPT_AND_MODULE_DUAL_PACKAGES ) ) { + const packageRequire = createRequire( + `${ dirname( require.resolve( `${ packageName }/package.json` ) ) }/` + ); + + const depPackageJson = packageRequire( './package.json' ); + if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) { + continue; + } + + const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length ); + let { wpScriptModuleExports } = depPackageJson; + + // Special handling for { "wpScriptModuleExports": "./build-module/index.js" }. + if ( typeof wpScriptModuleExports === 'string' ) { + wpScriptModuleExports = { '.': wpScriptModuleExports }; + } + + if ( Object.getPrototypeOf( wpScriptModuleExports ) !== Object.prototype ) { + throw new Error( 'wpScriptModuleExports must be an object' ); + } + + for ( const [ exportName, exportPath ] of Object.entries( + wpScriptModuleExports + ) ) { + // Exclude the experimental './full-page' export from @wordpress/interactivity-router. + // This export is defined in Gutenberg's package.json but should not be bundled in Core + // as the feature is still experimental and not ready for inclusion. + if ( moduleName === 'interactivity-router' && exportName === './full-page' ) { + continue; + } + + if ( typeof exportPath !== 'string' ) { + throw new Error( 'wpScriptModuleExports paths must be strings' ); + } + + if ( ! exportPath.startsWith( './' ) ) { + throw new Error( + 'wpScriptModuleExports paths must start with "./"' + ); + } + + const name = + exportName === '.' ? 'index' : exportName.replace( /^\.\/?/, '' ); + + scriptModules.set( + `${ moduleName }/${ name }`, + packageRequire.resolve( exportPath ) + ); + } +} + +module.exports = function ( + env = { environment: 'production', watch: false, buildTarget: false } +) { + const mode = env.environment; + const suffix = mode === 'production' ? '.min' : ''; + let buildTarget = env.buildTarget + ? env.buildTarget + : mode === 'production' + ? 'build' + : 'src'; + buildTarget = buildTarget + '/wp-includes'; + + const baseConfig = getBaseConfig( env ); + const config = { + ...baseConfig, + entry: Object.fromEntries( scriptModules.entries() ), + experiments: { + outputModule: true, + }, + output: { + devtoolNamespace: 'wp', + filename: `[name]${ suffix }.js`, + path: normalizeJoin( + baseDir, + `${ buildTarget }/js/dist/script-modules` + ), + library: { + type: 'module', + }, + environment: { module: true }, + module: true, + chunkFormat: 'module', + asyncChunks: false, + }, + plugins: [ + ...baseConfig.plugins, + new DependencyExtractionPlugin( { + injectPolyfill: false, + combineAssets: true, + combinedOutputFile: normalizeJoin( + baseDir, + `${ buildTarget }/assets/script-modules-packages${ suffix }.php` + ), + } ), + ], + }; + + return config; +}; diff --git a/tools/webpack/vendors.js b/tools/webpack/vendors.js new file mode 100644 index 0000000000000..1c1f0a187a176 --- /dev/null +++ b/tools/webpack/vendors.js @@ -0,0 +1,53 @@ +/** + * External dependencies + */ +const { join } = require( 'path' ); + +const importedVendors = { + 'react-jsx-runtime': { + import: 'react/jsx-runtime', + global: 'ReactJSXRuntime', + }, +}; + +module.exports = function ( + env = { environment: 'production', watch: false, buildTarget: false } +) { + const mode = env.environment; + let buildTarget = env.buildTarget + ? env.buildTarget + : mode === 'production' + ? 'build' + : 'src'; + buildTarget = buildTarget + '/wp-includes/js/dist/vendor/'; + return [ + ...Object.entries( importedVendors ).flatMap( ( [ name, config ] ) => { + return [ 'production', 'development' ].map( ( currentMode ) => { + return { + mode: currentMode, + target: 'browserslist', + output: { + filename: + currentMode === 'development' + ? `[name].js` + : `[name].min.js`, + path: join( __dirname, '..', '..', buildTarget ), + }, + entry: { + [ name ]: { + import: config.import, + library: { + name: config.global, + type: 'window', + }, + }, + }, + + externals: { + react: 'React', + }, + }; + } ); + } ), + ]; +}; diff --git a/webpack.config.js b/webpack.config.js index 089c2d67dabec..53ef8bd9ac4d9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,20 +1,27 @@ +const blocksConfig = require( './tools/webpack/blocks' ); +const developmentConfig = require( './tools/webpack/development' ); const mediaConfig = require( './tools/webpack/media' ); +const packagesConfig = require( './tools/webpack/packages' ); +const scriptModulesConfig = require( './tools/webpack/script-modules' ); +const vendorsConfig = require( './tools/webpack/vendors' ); -module.exports = function ( - env = { environment: 'production', watch: false, buildTarget: false } -) { +module.exports = function( env = { environment: "production", watch: false, buildTarget: false } ) { if ( ! env.watch ) { env.watch = false; } if ( ! env.buildTarget ) { - env.buildTarget = env.mode === 'production' ? 'build/' : 'src/'; + env.buildTarget = ( env.mode === 'production' ? 'build/' : 'src/' ); } - // Only building Core-specific media files. - // Blocks, packages, script modules, and vendors are now sourced from - // the Gutenberg build (see tools/gutenberg/copy-gutenberg-build.js). - const config = [ mediaConfig( env ) ]; + const config = [ + blocksConfig( env ), + ...developmentConfig( env ), + mediaConfig( env ), + packagesConfig( env ), + scriptModulesConfig( env ), + ...vendorsConfig( env ), + ]; return config; };