diff --git a/.env.example b/.env.example index dddbb4be4c260..1ca8f9658dbef 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,11 @@ LOCAL_DIR=src # Valid options are 'on' and 'off'. LOCAL_NGINX_COMPRESSION=off +# How long browsers may cache static assets served by the web server, as an nginx `expires` value. +# Valid options are 'off' and a duration such as '1y'. A far-future duration matches typical +# production behavior, but edited CSS and JavaScript is then served stale until a hard reload. +LOCAL_NGINX_STATIC_EXPIRES=off + # The PHP version to use. Valid options are 'latest', and '{version}-fpm'. LOCAL_PHP=latest diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 9b3144df5c64d..0000000000000 --- a/.eslintignore +++ /dev/null @@ -1,26 +0,0 @@ -# Files and folders related to build/test tools including generated files -/build -/node_modules -/tests -/vendor -/tools -/jsdoc -/artifacts -/coverage -.cache/* -/src/wp-includes/blocks/**/*.js -/src/wp-includes/blocks/**/*.js.map -/src/wp-admin/js -/src/wp-includes/js - -# Excluded files and folders based on `jsdoc.conf.json` exclusions -/src/js/_enqueues/vendor - -# Themes -src/wp-content/themes - -# Files and folders that get created in wp-content -/src/wp-content/plugins -/src/wp-content/mu-plugins -/src/wp-content/upgrade -/src/wp-content/uploads diff --git a/.eslintrc-jsdoc.js b/.eslintrc-jsdoc.js index 6f7351ec08945..7815cb1395e80 100644 --- a/.eslintrc-jsdoc.js +++ b/.eslintrc-jsdoc.js @@ -1,29 +1,88 @@ -module.exports = { - rules: { - 'require-jsdoc': 'off', - 'valid-jsdoc': [ 'error', { - prefer: { - arg: 'param', - argument: 'param', - extends: 'augments', - returns: 'return', +/** + * ESLint v10 flat config file for JSDoc linting. + * This config is based on the original valid-jsdoc rules. + */ + +const jsdocPlugin = require( 'eslint-plugin-jsdoc' ); + +module.exports = [ + { + plugins: { + jsdoc: jsdocPlugin, + }, + settings: { + jsdoc: { + tagNamePreference: { + 'arg': 'param', + 'argument': 'param', + 'extends': 'augments', + 'returns': 'return', + }, + preferredTypes: { + 'array': 'Array', + 'bool': 'boolean', + 'Boolean': 'boolean', + 'float': 'number', + 'Float': 'number', + 'function': 'Function', + 'int': 'number', + 'integer': 'number', + 'Integer': 'number', + 'Number': 'number', + 'object': 'Object', + 'String': 'string', + 'Void': 'void', + }, }, - preferType: { - array: 'Array', - bool: 'boolean', - Boolean: 'boolean', - float: 'number', - Float: 'number', - int: 'number', - integer: 'number', - Integer: 'number', - Number: 'number', - object: 'Object', - String: 'string', - Void: 'void', - }, - requireParamDescription: false, - requireReturn: false, - } ], + }, + rules: { + 'jsdoc/check-alignment': 'error', + 'jsdoc/check-indentation': [ 'error', { + excludeTags: [ + 'deprecated', + 'example', + 'param', + 'property', + 'return', + 'since', + 'todo', + ], + } ], + 'jsdoc/check-line-alignment': [ 'error', 'always', { + tags: [ 'param', 'property' ], + } ], + 'jsdoc/check-param-names': 'error', + 'jsdoc/check-property-names': 'error', + 'jsdoc/check-syntax': 'error', + 'jsdoc/check-tag-names': [ 'error', { + definedTags: [ + 'memberOf', + 'output', + 'ticket', + 'link', + ], + } ], + 'jsdoc/check-types': 'error', + 'jsdoc/no-blank-blocks': 'error', + 'jsdoc/no-blank-block-descriptions': 'error', + 'jsdoc/require-description': 'error', + 'jsdoc/require-hyphen-before-param-description': [ 'error', 'never' ], + 'jsdoc/require-jsdoc': 'error', + 'jsdoc/require-param': [ 'error', { + enableFixer: false, + } ], + 'jsdoc/require-param-description': 'error', + 'jsdoc/require-param-name': 'error', + 'jsdoc/require-param-type': 'error', + 'jsdoc/require-property': 'error', + 'jsdoc/require-property-name': 'error', + 'jsdoc/require-property-description': 'error', + 'jsdoc/require-property-type': 'error', + 'jsdoc/require-returns': 'error', + 'jsdoc/require-returns-check': 'error', + 'jsdoc/require-returns-description': 'error', + 'jsdoc/require-returns-type': 'error', + 'jsdoc/valid-types': 'error', + }, }, -}; +]; diff --git a/.github/actions/setup-npm/action.yml b/.github/actions/setup-npm/action.yml new file mode 100644 index 0000000000000..fba5bd0257bcc --- /dev/null +++ b/.github/actions/setup-npm/action.yml @@ -0,0 +1,55 @@ +name: 'Set up npm' +description: 'Installs the npm version required by the devEngines field of package.json, so every job resolves dependencies identically. Keeps the bundled npm when the field is absent.' + +inputs: + working-directory: + description: 'Optional. The directory holding the package.json to read the required npm version from. Defaults to the workspace root.' + required: false + default: '.' + cache: + description: 'Optional. Whether to restore and save the npm cache. Defaults to true.' + required: false + default: 'true' + +runs: + using: 'composite' + steps: + - name: Install npm + id: npm + env: + WORKING_DIRECTORY: ${{ inputs.working-directory }} + run: | + NPM_VERSION="$(jq -r '.devEngines.packageManager.version // empty' package.json)" + if [ -n "$NPM_VERSION" ]; then + # Contributors need the floor; CI stays on that major's newest release. + npm install --global "npm@${NPM_VERSION/>=/^}" + echo "Required npm version: $NPM_VERSION" + else + echo "No devEngines.packageManager.version, keeping the bundled npm." + fi + echo "Installed npm version: $(npm --version)" + + # actions/setup-node cannot restore the npm cache: it locates the + # directory with `npm config get cache`, which runs before this step + # and fails the devEngines check under the bundled npm. + echo "cache-dir=$(npm config get cache | tr -d '\r')" >> "$GITHUB_OUTPUT" + + # Scopes the cache key to this package and keeps the hashFiles patterns + # workspace-relative and free of a "./" prefix, so they match the same + # files as every other cache key. + PATH_PREFIX="" + if [ "$WORKING_DIRECTORY" != '.' ] && [ -n "$WORKING_DIRECTORY" ]; then + PATH_PREFIX="${WORKING_DIRECTORY%/}/" + fi + echo "path-prefix=$PATH_PREFIX" >> "$GITHUB_OUTPUT" + working-directory: ${{ inputs.working-directory }} + shell: bash + + - name: Cache npm downloads + if: ${{ inputs.cache == 'true' }} + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ steps.npm.outputs.cache-dir }} + key: npm-cache-${{ runner.os }}-${{ runner.arch }}-${{ steps.npm.outputs.path-prefix }}lock-${{ hashFiles(format('{0}package-lock.json', steps.npm.outputs.path-prefix), format('{0}patches/**', steps.npm.outputs.path-prefix)) }} + restore-keys: | + npm-cache-${{ runner.os }}-${{ runner.arch }}-${{ steps.npm.outputs.path-prefix }}lock- diff --git a/.github/actions/smoke-check/action.yml b/.github/actions/smoke-check/action.yml new file mode 100644 index 0000000000000..4a115e0f6d754 --- /dev/null +++ b/.github/actions/smoke-check/action.yml @@ -0,0 +1,20 @@ +name: 'Smoke check a WordPress installation' +description: 'Serves an installed single site with PHP built-in web server and checks that its front end, REST API, and admin respond.' + +inputs: + admin-user: + description: 'The username of an administrator account on the site.' + required: true + admin-password: + description: 'The password of the administrator account.' + required: true + +runs: + using: 'composite' + steps: + - name: Serve the site and check it + shell: bash + run: bash "${GITHUB_ACTION_PATH}/smoke-check.sh" + env: + WP_ADMIN_USER: ${{ inputs.admin-user }} + WP_ADMIN_PASSWORD: ${{ inputs.admin-password }} diff --git a/.github/actions/smoke-check/smoke-check.sh b/.github/actions/smoke-check/smoke-check.sh new file mode 100755 index 0000000000000..d3ab33e068f9e --- /dev/null +++ b/.github/actions/smoke-check/smoke-check.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# +# Smoke checks an installed WordPress single site over HTTP. +# +# Runs from the root of the installation, with WP-CLI available. Multisite is not supported because +# a network's domain lives in wp-config.php and the database, not just an option. + +set -euo pipefail + +: "${RUNNER_TEMP:?}" "${WP_ADMIN_USER:?}" "${WP_ADMIN_PASSWORD:?}" + +site_port=8889 +site_url="http://127.0.0.1:${site_port}" +server_log="${RUNNER_TEMP}/server.log" +jar="${RUNNER_TEMP}/cookies.txt" +: > "${jar}" +response="${RUNNER_TEMP}/response.txt" +code="${RUNNER_TEMP}/http-code.txt" +http_code='' + +version="$(wp core version)" + +# Nothing undoes these, so the site is only good for this check afterwards. +wp option update home "${site_url}" +wp option update siteurl "${site_url}" +# A fresh install shows posts here already, but the front page check below needs it. +wp option update show_on_front posts +# Both make requests no check asked for, and the update checks call api.wordpress.org. +wp config set DISABLE_WP_CRON true --raw +wp config set WP_HTTP_BLOCK_EXTERNAL true --raw + +# opcache counts php -S as a web SAPI, so the runner's JIT runs here and segfaults. +php -d opcache.jit=disable -S "127.0.0.1:${site_port}" -t . > "${server_log}" 2>&1 & +server_pid=$! + +stop_server() { + local status=$? + kill "${server_pid}" 2> /dev/null || true + wait "${server_pid}" 2> /dev/null || true + [ "${status}" -eq 0 ] || cat "${server_log}" || true + exit "${status}" +} +trap stop_server EXIT + +# No connection prints 000 and exits 7, which set -e would take as fatal. +deadline=$(( SECONDS + 30 )) +while :; do + ready_code="$(curl --silent --max-time 5 --output /dev/null --write-out '%{http_code}' "${site_url}/" || true)" + [ "${ready_code}" = '000' ] || break + [ "${SECONDS}" -lt "${deadline}" ] || { echo '::error::the server never answered'; exit 1; } + sleep 1 +done + +fail() { + echo "::error::${1}" + tail -n 20 "${response}" + exit 1 +} + +# An HTTP error returns to the caller. No reply at all is fatal. +fetch() { + local path="${1}" status=0 + shift + : > "${response}" + curl --silent --show-error --max-time 30 --output "${response}" \ + --write-out '%{http_code}' --cookie "${jar}" --cookie-jar "${jar}" \ + "$@" "${site_url}${path}" > "${code}" || status=$? + http_code="$(cat "${code}")" + [ "${status}" -eq 0 ] || [ "${status}" -eq 22 ] \ + || fail "${path} got no reply and curl exited ${status}" + return "${status}" +} + +check() { + local path="${1}" marker status=0 + shift + fetch "${path}" --fail-with-body || status=$? + [ "${status}" -eq 0 ] || fail "${path} returned HTTP ${http_code}" + for marker in "$@"; do + grep -qF -e "${marker}" "${response}" || fail "${path} did not contain: ${marker}" + done + echo "ok ${path}" +} + +# A fatal mid-page still returns 200, so every check also asks for the closing tag. +check '/' "content=\"WordPress ${version}\"" 'Hello world!' '' + +fetch '/?rest_route=/' --fail-with-body || fail "/?rest_route=/ returned HTTP ${http_code}" +jq -e --arg url "${site_url}" '.url == $url and ( .namespaces | index( "wp/v2" ) )' "${response}" > /dev/null \ + || fail 'the REST index was not the expected JSON' +echo 'ok /?rest_route=/' + +# It prints this for an empty database too, which the checks above rule out. +check '/wp-admin/upgrade.php' 'No Update Required' '' + +fetch '/?p=99999999' || true +[ "${http_code}" = '404' ] || fail "a missing post returned ${http_code}, expected 404" +grep -qF '' "${response}" || fail 'the 404 page was cut short' +echo 'ok 404 handling' + +login_status=0 +fetch '/wp-login.php' --fail-with-body \ + --data-urlencode "log=${WP_ADMIN_USER}" --data-urlencode "pwd=${WP_ADMIN_PASSWORD}" || login_status=$? +[ "${login_status}" -eq 0 ] || fail "logging in returned HTTP ${http_code}" +grep -qF 'wordpress_logged_in_' "${jar}" || fail 'logging in did not set an authentication cookie' +echo 'ok login' + +# The admin bar renders only for a logged-in user. +check '/wp-admin/' 'id="wpadminbar"' '' + +# Catches a fatal during shutdown. An empty log would let the grep pass silently. +[ -s "${server_log}" ] || { echo '::error::the server wrote no log'; exit 1; } +if grep -qE 'Fatal error|Uncaught|Segmentation fault' "${server_log}"; then + echo '::error::the server logged a fatal error' + exit 1 +fi +echo 'ok server log' diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index d579368eeb079..ad099ad58460a 100644 --- a/.github/workflows/coding-standards.yml +++ b/.github/workflows/coding-standards.yml @@ -14,20 +14,61 @@ on: - '3.[89]' - '[4-9].[0-9]' paths: - # Any change to a PHP or JavaScript file should run checks. - - '**.js' - - '**.php' - # These files configure npm. Changes could affect the outcome. + - '**' + # Documentation, repository metadata, and local environment configuration. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.env.example' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!docker-compose.yml' + - '!jsdoc.conf.json' + - '!tsconfig.json' + - '!typings/**' + - '!wp-cli.yml' + # File types that PHPCS and JSHint do not inspect. + - '!**.crt' + - '!**.css' + - '!**.dat' + - '!**.dist' + - '!**.html' + - '!**.jpg' + - '!**.json' + - '!**.map' + - '!**.mo' + - '!**.neon' + - '!**.pem' + - '!**.png' + - '!**.po' + - '!**.scss' + - '!**.svg' + - '!**.txt' + - '!**.webp' + - '!**.woff2' + - '!**.xml' + - '!**.yaml' + - '!**.yml' + # JavaScript outside the JSHint targets and all tooling are not inspected. + - '!tests/e2e/**.js' + - '!tests/performance/**.js' + - '!tools/**' + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!eslint.config.js' + - '!webpack.config.js' + # Other workflows do not affect these checks. + - '!.github/**' + # Re-include configuration and workflow files that affect these checks. - 'package*.json' - '.npmrc' - '.nvmrc' - # These files configure Composer. Changes could affect the outcome. + - 'Gruntfile.js' - 'composer.*' - # This file configures JSHint. Changes could affect the outcome. - - '.jshintrc' - # This file configures PHPCS. Changes could affect the outcome. + - '**.jshintrc' - 'phpcs.xml.dist' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/coding-standards.yml' - '.github/workflows/reusable-coding-standards-*.yml' workflow_dispatch: @@ -89,7 +130,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml index f2eb5abb83ddb..e249f6e25475c 100644 --- a/.github/workflows/end-to-end-tests.yml +++ b/.github/workflows/end-to-end-tests.yml @@ -13,24 +13,37 @@ on: - '5.[3-9]' - '[6-9].[0-9]' paths: - # Any change to a PHP, CSS, or JavaScript file should run checks. - - '**.css' - - '**.js' - - '**.php' - # These files configure npm and the task runner. Changes could affect the outcome. - - 'package*.json' - - '.npmrc' - - '.nvmrc' - - 'Gruntfile.js' - - 'webpack.config.js' + - '**' + # Documentation and repository metadata. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!typings/**' + # Configuration for unrelated checks. + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!.version-support-*.json' + - '!eslint.config.js' + - '!jsdoc.conf.json' + - '!phpcompat.xml.dist' + - '!phpcs.xml.dist' + - '!phpstan.neon.dist' + - '!phpunit.xml.dist' + - '!tsconfig.json' + # Other test suites, tools, and workflows do not affect these tests. + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include the test, tool, and workflow files used here. + - 'tests/e2e/**' - 'tools/gutenberg/**' + - 'tools/local-env/**' - 'tools/vendors/**' - 'tools/webpack/**' - # These files configure Composer. Changes could affect the outcome. - - 'composer.*' - # This files affect the e2e tests. Changes could affect the outcome. - - 'tests/e2e/**' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/end-to-end-tests.yml' - '.github/workflows/reusable-end-to-end-tests*.yml' workflow_dispatch: @@ -89,7 +102,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/failed-workflow.yml b/.github/workflows/failed-workflow.yml index 288a2a9e0e930..2da0ff56989d7 100644 --- a/.github/workflows/failed-workflow.yml +++ b/.github/workflows/failed-workflow.yml @@ -43,9 +43,12 @@ jobs: // Only rerun after the first run attempt. if ( workflow_run.data.run_attempt > 1 ) { + core.info(`Skipping rerun, attempt ${workflow_run.data.run_attempt}: ${workflow_run.data.html_url}`); return; } + core.notice(`Rerunning workflow run "${workflow_run.data.name}" on ${workflow_run.data.head_branch}: ${workflow_run.data.html_url}`); + const rerun = await github.rest.actions.reRunWorkflowFailedJobs({ owner: context.repo.owner, repo: context.repo.repo, diff --git a/.github/workflows/install-testing.yml b/.github/workflows/install-testing.yml index d69dc103d2d3a..ed0446e4e083e 100644 --- a/.github/workflows/install-testing.yml +++ b/.github/workflows/install-testing.yml @@ -12,12 +12,14 @@ on: - trunk # Always test the workflow after it's updated. paths: + - '.github/actions/smoke-check/**' - '.github/workflows/install-testing.yml' - '.version-support-*.json' - '.github/workflows/reusable-support-json-reader-v1.yml' pull_request: # Always test the workflow when changes are suggested. paths: + - '.github/actions/smoke-check/**' - '.version-support-*.json' - '.github/workflows/install-testing.yml' - '.github/workflows/reusable-support-json-reader-v1.yml' @@ -60,14 +62,19 @@ jobs: # - Downloads the specified version of WordPress. # - Creates a `wp-config.php` file. # - Installs WordPress. + # - Serves the installed site and confirms it renders. install-tests-mysql: name: WP ${{ inputs.wp-version || 'nightly' }} / PHP ${{ matrix.php }} / ${{ 'mariadb' == matrix.db-type && 'MariaDB' || 'MySQL' }} ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} permissions: contents: read runs-on: ${{ matrix.os }} if: ${{ github.repository == 'WordPress/wordpress-develop' }} - timeout-minutes: 10 + timeout-minutes: 15 needs: [ build-test-matrix ] + + env: + WP_ADMIN_USER: admin + WP_ADMIN_PASSWORD: password strategy: fail-fast: false matrix: @@ -106,8 +113,10 @@ jobs: image: ${{ matrix.db-type }}:${{ matrix.db-version }} ports: - 3306 + # Ping over TCP, to wait for the TCP server rather than the Unix socket. + # MariaDB 11.0 dropped the `mysqladmin` symlink, so pick the client the image ships. options: >- - --health-cmd="mysqladmin ping" + --health-cmd="${{ matrix.db-type == 'mariadb' && ! contains( fromJSON('["5.5", "10.0", "10.1", "10.2", "10.3"]'), matrix.db-version ) && 'mariadb-admin' || 'mysqladmin' }} ping -h 127.0.0.1 --protocol=tcp" --health-interval="30s" --health-timeout="10s" --health-retries="5" @@ -135,7 +144,18 @@ jobs: DB_PORT: ${{ job.services.database.ports['3306'] }} - name: Install WordPress - run: wp core ${{ matrix.multisite && 'multisite-install' || 'install' }} --url=http://localhost/ --title="Upgrade Test" --admin_user=admin --admin_password=password --admin_email=me@example.org --skip-email + run: | + wp core ${{ matrix.multisite && 'multisite-install' || 'install' }} \ + --url=http://localhost/ --title="Install Test" --admin_user="${WP_ADMIN_USER}" \ + --admin_password="${WP_ADMIN_PASSWORD}" --admin_email=me@example.org --skip-email + + - name: Post-install smoke check + # A network's domain lives in wp-config.php and the database, not just an option. + if: ${{ ! matrix.multisite }} + uses: WordPress/wordpress-develop/.github/actions/smoke-check@trunk # zizmor: ignore[unpinned-uses] + with: + admin-user: ${{ env.WP_ADMIN_USER }} + admin-password: ${{ env.WP_ADMIN_PASSWORD }} slack-notifications: name: Slack Notifications @@ -152,7 +172,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/javascript-tests.yml b/.github/workflows/javascript-tests.yml index 08a118e4a4056..97c6f1099a43e 100644 --- a/.github/workflows/javascript-tests.yml +++ b/.github/workflows/javascript-tests.yml @@ -13,9 +13,52 @@ on: - '3.[89]' - '[4-9].[0-9]' paths: - # Any change to a JavaScript file should run tests. - - '**.js' - # These files configure npm and the task runner. Changes could affect the outcome. + - '**' + # Documentation, repository metadata, and local environment configuration. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.env.example' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!docker-compose.yml' + - '!jsdoc.conf.json' + - '!typings/**' + - '!wp-cli.yml' + # File types that the JavaScript tests do not exercise. + - '!**.crt' + - '!**.css' + - '!**.dat' + - '!**.dist' + - '!**.html' + - '!**.jpg' + - '!**.json' + - '!**.map' + - '!**.mo' + - '!**.neon' + - '!**.pem' + - '!**.php' + - '!**.png' + - '!**.po' + - '!**.scss' + - '!**.svg' + - '!**.txt' + - '!**.webp' + - '!**.woff2' + - '!**.xml' + - '!**.yaml' + - '!**.yml' + # JavaScript outside the QUnit suite and related tooling is not exercised. + - '!tests/e2e/**.js' + - '!tests/performance/**.js' + - '!tools/**' + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!eslint.config.js' + # Other workflows do not affect these tests. + - '!.github/**' + # Re-include configuration, tests, tools, and workflows used here. - 'package*.json' - '.npmrc' - '.nvmrc' @@ -24,13 +67,9 @@ on: - 'tools/gutenberg/**' - 'tools/vendors/**' - 'tools/webpack/**' - # This file configures ESLint. Changes could affect the outcome. - - '.eslintignore' - # This file configures JSHint. Changes could affect the outcome. - '.jshintrc' - # Any change to the QUnit directory should run tests. - 'tests/qunit/**' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/javascript-tests.yml' - '.github/workflows/reusable-javascript-tests.yml' workflow_dispatch: @@ -77,7 +116,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/javascript-type-checking.yml b/.github/workflows/javascript-type-checking.yml index 4983e0c619ec8..0bf9288b06e82 100644 --- a/.github/workflows/javascript-type-checking.yml +++ b/.github/workflows/javascript-type-checking.yml @@ -24,6 +24,7 @@ on: # This directory contains TypeScript definitions. Changes could affect the outcome. - 'typings/**' # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/javascript-type-checking.yml' - '.github/workflows/reusable-javascript-type-checking-v1.yml' workflow_dispatch: @@ -70,7 +71,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/local-docker-environment.yml b/.github/workflows/local-docker-environment.yml index 0f88d54ff4eb8..c636c695b6d44 100644 --- a/.github/workflows/local-docker-environment.yml +++ b/.github/workflows/local-docker-environment.yml @@ -13,6 +13,7 @@ on: - 'docker-compose.yml' # Any changes to local environment related files - 'tools/local-env/**' + - 'wp-cli.yml' # These files configure npm and the task runner. Changes could affect the outcome. - 'package*.json' - 'Gruntfile.js' @@ -27,6 +28,7 @@ on: # These files define the versions to test. - '.version-support-*.json' # Changes to this and related workflow files should always be verified. + - '.github/actions/setup-npm/**' - '.github/workflows/local-docker-environment.yml' - '.github/workflows/reusable-support-json-reader-v1.yml' - '.github/workflows/reusable-test-docker-environment-v1.yml' @@ -41,6 +43,7 @@ on: - 'docker-compose.yml' # Any changes to local environment related files - 'tools/local-env/**' + - 'wp-cli.yml' # These files configure npm and the task runner. Changes could affect the outcome. - 'package*.json' - 'Gruntfile.js' @@ -53,6 +56,7 @@ on: # These files define the versions to test. - '.version-support-*.json' # Changes to this and related workflow files should always be verified. + - '.github/actions/setup-npm/**' - '.github/workflows/local-docker-environment.yml' - '.github/workflows/reusable-support-json-reader-v1.yml' - '.github/workflows/reusable-test-docker-environment-v1.yml' @@ -135,7 +139,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 22a3a27392859..808f299208bc6 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -13,24 +13,37 @@ on: - '6.[2-9]' - '[7-9].[0-9]' paths: - # Any change to a PHP, CSS, or JavaScript file should run checks. - - '**.css' - - '**.js' - - '**.php' - # These files configure npm and the task runner. Changes could affect the outcome. - - 'package*.json' - - '.npmrc' - - '.nvmrc' - - 'Gruntfile.js' - - 'webpack.config.js' + - '**' + # Documentation and repository metadata. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!typings/**' + # Configuration for unrelated checks. + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!.version-support-*.json' + - '!eslint.config.js' + - '!jsdoc.conf.json' + - '!phpcompat.xml.dist' + - '!phpcs.xml.dist' + - '!phpstan.neon.dist' + - '!phpunit.xml.dist' + - '!tsconfig.json' + # Other test suites, tools, and workflows do not affect these tests. + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include the test, tool, and workflow files used here. + - 'tests/performance/**' - 'tools/gutenberg/**' + - 'tools/local-env/**' - 'tools/vendors/**' - 'tools/webpack/**' - # These files configure Composer. Changes could affect the outcome. - - 'composer.*' - # This files affect the performance tests. Changes could affect the outcome. - - 'tests/performance/**' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/performance.yml' - '.github/workflows/reusable-performance-*.yml' workflow_dispatch: @@ -153,7 +166,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/php-compatibility.yml b/.github/workflows/php-compatibility.yml index 37de91a73b24b..7bb6869fd5a79 100644 --- a/.github/workflows/php-compatibility.yml +++ b/.github/workflows/php-compatibility.yml @@ -13,13 +13,51 @@ on: - '5.[5-9]' - '[6-9].[0-9]' paths: - # This workflow only scans PHP files. - - '**.php' - # These files configure Composer. Changes could affect the outcome. + - '**' + # Documentation, repository metadata, and local environment configuration. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.env.example' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.jshintrc' + - '!.mailmap' + - '!docker-compose.yml' + - '!jsdoc.conf.json' + - '!typings/**' + - '!wp-cli.yml' + # File types that the PHP compatibility scan does not inspect. + - '!**.crt' + - '!**.css' + - '!**.dat' + - '!**.dist' + - '!**.html' + - '!**.jpg' + - '!**.js' + - '!**.json' + - '!**.map' + - '!**.mo' + - '!**.neon' + - '!**.pem' + - '!**.png' + - '!**.po' + - '!**.scss' + - '!**.svg' + - '!**.txt' + - '!**.webp' + - '!**.woff2' + - '!**.xml' + - '!**.yaml' + - '!**.yml' + # Only source PHP files are scanned. + - '!*.php' + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include configuration and workflow files that affect the scan. - 'composer.*' - # This file configures PHP compatibility scanning. Changes could affect the outcome. - 'phpcompat.xml.dist' - # Confirm any changes to relevant workflow files. - '.github/workflows/php-compatibility.yml' - '.github/workflows/reusable-php-compatibility.yml' workflow_dispatch: @@ -66,7 +104,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/phpstan-static-analysis.yml b/.github/workflows/phpstan-static-analysis.yml index a07ee13e16467..6a26c75b16525 100644 --- a/.github/workflows/phpstan-static-analysis.yml +++ b/.github/workflows/phpstan-static-analysis.yml @@ -66,7 +66,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/phpunit-tests-full-matrix.yml b/.github/workflows/phpunit-tests-full-matrix.yml new file mode 100644 index 0000000000000..eedbbdb087e4e --- /dev/null +++ b/.github/workflows/phpunit-tests-full-matrix.yml @@ -0,0 +1,66 @@ +name: PHPUnit Tests (label) +run-name: PHPUnit Tests${{ github.event.label.name == 'Full PHPUnit Matrix' && ' (full matrix)' || ' (ignored label)' }} + +on: + pull_request: + types: [ labeled ] + branches: + - trunk + - '3.[7-9]' + - '[4-9].[0-9]' + # Keep these paths in sync with phpunit-tests.yml. + paths: + - '**' + # Documentation and repository metadata. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!typings/**' + # Configuration for unrelated checks. + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!.version-support-*.json' + - '!eslint.config.js' + - '!jsdoc.conf.json' + - '!phpcompat.xml.dist' + - '!phpcs.xml.dist' + - '!phpstan.neon.dist' + - '!tsconfig.json' + # Other test suites, tools, and workflows do not affect these tests. + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include documentation, tests, tools, and workflows used here. + - 'SECURITY.md' + - 'src/license.txt' + - 'tests/phpunit/**' + - 'tools/gutenberg/**' + - 'tools/local-env/**' + - 'tools/vendors/**' + - 'tools/webpack/**' + - 'phpunit.xml.dist' + - '.github/actions/setup-npm/**' + - '.github/workflows/phpunit-tests.yml' + - '.github/workflows/phpunit-tests-full-matrix.yml' + - '.github/workflows/reusable-phpunit-tests-*.yml' + - '.github/workflows/reusable-prepare-gutenberg.yml' + +# Disable permissions for all available scopes by default. +permissions: {} + +# The called workflow manages concurrency. Unrelated labels never enter it. +jobs: + full-matrix: + if: github.event.label.name == 'Full PHPUnit Matrix' + permissions: + # Required by the called workflow's recovery job, which is skipped on PR events. + actions: write + contents: read + uses: ./.github/workflows/phpunit-tests.yml + secrets: + CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index 30cf72bc606ae..a212e3b6be563 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -1,4 +1,5 @@ name: PHPUnit Tests +run-name: PHPUnit Tests${{ ( github.event_name == 'schedule' || ( github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) ) ) && ' (full matrix)' || '' }} on: push: @@ -11,31 +12,62 @@ on: - trunk - '3.[7-9]' - '[4-9].[0-9]' + # Keep these paths in sync with phpunit-tests-full-matrix.yml. paths: - # Any change to a PHP, CSS, JavaScript, JSON, HTML, or otherwise tested file should run checks. - - '**.css' - - '**.html' - - '**.js' - - '**.json' - - '**.php' + - '**' + # Documentation and repository metadata. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!typings/**' + # Configuration for unrelated checks. + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!.version-support-*.json' + - '!eslint.config.js' + - '!jsdoc.conf.json' + - '!phpcompat.xml.dist' + - '!phpcs.xml.dist' + - '!phpstan.neon.dist' + - '!tsconfig.json' + # Other test suites, tools, and workflows do not affect these tests. + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include documentation, tests, tools, and workflows used here. + - 'SECURITY.md' - 'src/license.txt' - - 'src/SECURITY.md' - # These files configure npm and the task runner. Changes could affect the outcome. - - 'package*.json' - - '.npmrc' - - '.nvmrc' - - 'Gruntfile.js' - # These files configure Composer. Changes could affect the outcome. - - 'composer.*' - # These files affect the phpunit tests. Changes could affect the outcome. - 'tests/phpunit/**' - - 'tests/phpunit/multisite.xml' + - 'tools/gutenberg/**' + - 'tools/local-env/**' + - 'tools/vendors/**' + - 'tools/webpack/**' - 'phpunit.xml.dist' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/phpunit-tests.yml' + - '.github/workflows/phpunit-tests-full-matrix.yml' - '.github/workflows/reusable-phpunit-tests-*.yml' - '.github/workflows/reusable-prepare-gutenberg.yml' workflow_dispatch: + workflow_call: + secrets: + CODEVITALS_PROJECT_TOKEN: + required: false + CODECOV_TOKEN: + required: false + WPT_REPORT_API_KEY: + required: false + SLACK_GHA_SUCCESS_WEBHOOK: + required: false + SLACK_GHA_CANCELLED_WEBHOOK: + required: false + SLACK_GHA_FIXED_WEBHOOK: + required: false + SLACK_GHA_FAILURE_WEBHOOK: + required: false # Once weekly On Sundays at 00:00 UTC. schedule: - cron: '0 0 * * 0' @@ -52,6 +84,88 @@ concurrency: permissions: {} jobs: + # Reduce PR testing only for audited Core assets and unrelated companion files. + select-test-coverage: + name: Select PHPUnit coverage + runs-on: ubuntu-24.04 + timeout-minutes: 5 + permissions: + contents: read + if: | + github.repository == 'WordPress/wordpress-develop' || ( + github.event_name == 'pull_request' && ( + ! github.event.repository.private || + ! github.event.pull_request.draft || + contains( github.event.pull_request.labels.*.name, 'Draft Workflow Runs' ) + ) + ) + outputs: + assets-only: ${{ steps.select.outputs.assets-only }} + steps: + - name: Checkout the PR merge commit + if: github.event_name == 'pull_request' && ! contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 2 + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Select test coverage + id: select + env: + CHECK_ASSETS: ${{ github.event_name == 'pull_request' && ! contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) }} + run: | + assets_only=false + if [[ "$CHECK_ASSETS" == 'true' ]]; then + # Compare the tested merge result with its base parent. Include both paths of a rename. + changed_files="$RUNNER_TEMP/phpunit-changed-files" + if git diff --no-renames --name-only -z HEAD^1 HEAD > "$changed_files" && [[ -s "$changed_files" ]]; then + while IFS= read -r -d '' file; do + case "$file" in + # Preserve the workflow's explicit inclusions before ignoring Markdown files. + SECURITY.md|tests/phpunit/*|tools/gutenberg/*|tools/local-env/*|tools/vendors/*|tools/webpack/*) + ;; + src/js/*.js|src/js/*.css|src/wp-admin/css/*.css|src/wp-admin/css/colors/*.scss|src/wp-includes/css/*.css|src/wp-includes/build/*.js) + assets_only=true + continue + ;; + # These companion files are excluded by the workflow's path filters. + *.md|tests/qunit/*|typings/*|.eslintrc-jsdoc.js|.prettierrc.js|eslint.config.js|jsdoc.conf.json|tsconfig.json) + continue + ;; + esac + printf 'Running the normal PHPUnit matrix: %q is outside the audited asset paths.\n' "$file" + assets_only=false + break + done < "$changed_files" + if [[ "$assets_only" == 'false' ]]; then + echo 'Reduced coverage requires an audited asset change and no other relevant changes.' + fi + else + echo 'Running the normal PHPUnit matrix: changed paths are unavailable or empty.' + fi + else + echo 'Keeping the existing PHPUnit matrix for this event or the Full PHPUnit Matrix label.' + fi + echo "assets-only=$assets_only" >> "$GITHUB_OUTPUT" + + # One configuration keeps asset-dependent PHP tests visible on Core asset-only PRs. + # Single site only. Asset tests must not also belong to groups excluded by phpunit.xml.dist. + test-assets: + name: Core assets + uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + needs: [ select-test-coverage, prepare-gutenberg ] + permissions: + contents: read + if: needs.select-test-coverage.outputs.assets-only == 'true' + with: + php: '8.3' + db-type: 'mysql' + db-version: '8.4' + phpunit-test-groups: 'assets' + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} + gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} + # Downloads and verifies the Gutenberg build once for all PHPUnit jobs. prepare-gutenberg: name: Prepare Gutenberg Assets @@ -77,13 +191,15 @@ jobs: test-with-mysql: name: PHP ${{ matrix.php }} uses: ./.github/workflows/reusable-phpunit-tests-v3.yml - needs: prepare-gutenberg + needs: [ select-test-coverage, prepare-gutenberg ] permissions: contents: read secrets: + CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} if: | + needs.select-test-coverage.outputs.assets-only != 'true' && startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && ( @@ -97,13 +213,30 @@ jobs: fail-fast: false matrix: os: [ ubuntu-24.04 ] - # The scheduled run tests every supported PHP version. Other events test the highest and lowest of each major. - php: ${{ github.event_name == 'schedule' && fromJSON('["7.4","8.0","8.1","8.2","8.3","8.4","8.5"]') || fromJSON('["7.4","8.0","8.5"]') }} + php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.0', '8.4', '9.7' ] tests-domain: [ 'example.org' ] multisite: [ false, true ] memcached: [ false ] + # Scheduled runs and pull requests labeled with 'Full PHPUnit Matrix' test every PHP and MySQL version above. + # All other runs exclude the versions noted below to keep the number of jobs manageable. + full-matrix: + - ${{ github.event_name == 'schedule' || ( github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) ) }} + + exclude: + # Outside the full matrix, only the highest and lowest PHP version of each major are tested. + - full-matrix: false + php: '8.1' + - full-matrix: false + php: '8.2' + - full-matrix: false + php: '8.3' + - full-matrix: false + php: '8.4' + # Outside the full matrix, MySQL 5.7 compatibility and the widely used 8.x releases are tested. + - full-matrix: false + db-version: '9.7' include: # Include jobs that test with memcached. @@ -160,8 +293,8 @@ jobs: # # Creates a PHPUnit test job for each PHP/MariaDB combination. # - # All LTS versions of MariaDB supported by WordPress with greater than 1% usage according to w.org/stats should be - # tested. The exceptions to this rule are the most recent LTS and version 5.5. + # Scheduled and labeled runs test all LTS versions of MariaDB supported by WordPress with greater than 1% usage + # according to w.org/stats. The exceptions to this rule are the most recent LTS and version 5.5. # # The 5.5 release was intended as a drop-in replacement for MySQL. Because the MySQL 5.5 Docker containers do not # work, this ensures some level of MySQL 5.5 testing. @@ -169,13 +302,14 @@ jobs: test-with-mariadb: name: PHP ${{ matrix.php }} uses: ./.github/workflows/reusable-phpunit-tests-v3.yml - needs: prepare-gutenberg + needs: [ select-test-coverage, prepare-gutenberg ] permissions: contents: read secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} if: | + needs.select-test-coverage.outputs.assets-only != 'true' && startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && ( @@ -189,12 +323,31 @@ jobs: fail-fast: false matrix: os: [ ubuntu-24.04 ] - # The scheduled run tests every supported PHP version. Other events test the highest and lowest of each major. - php: ${{ github.event_name == 'schedule' && fromJSON('["7.4","8.0","8.1","8.2","8.3","8.4","8.5"]') || fromJSON('["7.4","8.0","8.5"]') }} + php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] db-type: [ 'mariadb' ] db-version: [ '5.5', '10.3', '10.5', '10.6', '10.11', '11.4', '11.8' ] multisite: [ false, true ] memcached: [ false ] + # Scheduled runs and pull requests labeled with 'Full PHPUnit Matrix' test every PHP and MariaDB version above. + # All other runs exclude the versions noted below to keep the number of jobs manageable. + full-matrix: + - ${{ github.event_name == 'schedule' || ( github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) ) }} + + exclude: + # Outside the full matrix, only the highest and lowest PHP version of each major are tested. + - full-matrix: false + php: '8.1' + - full-matrix: false + php: '8.2' + - full-matrix: false + php: '8.3' + - full-matrix: false + php: '8.4' + # Outside the full matrix, MariaDB 5.5 compatibility, 10.6, and newer LTS releases are tested. + - full-matrix: false + db-version: '10.3' + - full-matrix: false + db-version: '10.5' include: # Include jobs that test with memcached. @@ -236,13 +389,14 @@ jobs: test-innovation-releases: name: PHP ${{ matrix.php }} uses: ./.github/workflows/reusable-phpunit-tests-v3.yml - needs: prepare-gutenberg + needs: [ select-test-coverage, prepare-gutenberg ] permissions: contents: read secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} if: | + needs.select-test-coverage.outputs.assets-only != 'true' && startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && ( @@ -256,18 +410,30 @@ jobs: fail-fast: false matrix: os: [ ubuntu-24.04 ] - # The scheduled run tests every supported PHP version. Other events test the highest and lowest of each major. - php: ${{ github.event_name == 'schedule' && fromJSON('["7.4","8.0","8.1","8.2","8.3","8.4","8.5"]') || fromJSON('["7.4","8.0","8.5"]') }} + php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] db-type: [ 'mysql', 'mariadb' ] db-version: [ '12.1' ] multisite: [ false, true ] memcached: [ false ] db-innovation: [ true ] + # Scheduled runs and pull requests labeled with 'Full PHPUnit Matrix' test every version above. + # All other runs exclude the versions noted below to keep the number of jobs manageable. + full-matrix: + - ${{ github.event_name == 'schedule' || ( github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'Full PHPUnit Matrix' ) ) }} exclude: # Exclude version combinations that don't exist. - db-type: 'mysql' db-version: '12.1' + # Outside the full matrix, only the highest and lowest PHP version of each major are tested. + - full-matrix: false + php: '8.1' + - full-matrix: false + php: '8.2' + - full-matrix: false + php: '8.3' + - full-matrix: false + php: '8.4' with: os: ${{ matrix.os }} php: ${{ matrix.php }} @@ -292,13 +458,14 @@ jobs: html-api-test-groups: name: ${{ matrix.label }} uses: ./.github/workflows/reusable-phpunit-tests-v3.yml - needs: prepare-gutenberg + needs: [ select-test-coverage, prepare-gutenberg ] permissions: contents: read secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} if: | + needs.select-test-coverage.outputs.assets-only != 'true' && startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && ( @@ -335,13 +502,14 @@ jobs: limited-matrix-for-forks: name: PHP ${{ matrix.php }} uses: ./.github/workflows/reusable-phpunit-tests-v3.yml - needs: prepare-gutenberg + needs: [ select-test-coverage, prepare-gutenberg ] permissions: contents: read secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} WPT_REPORT_API_KEY: ${{ secrets.WPT_REPORT_API_KEY }} if: | + needs.select-test-coverage.outputs.assets-only != 'true' && ! startsWith( github.repository, 'WordPress/' ) && github.event_name == 'pull_request' && ( ! github.event.repository.private || @@ -396,13 +564,57 @@ jobs: gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} + # Runs the PHPUnit test suite with PHP 8.6. + # + # The number of testing combinations is intentionally limited because PHP 8.6 is still in beta/RC. + pre-release-php-8-6: + name: PHP ${{ matrix.php }} + uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + needs: [ select-test-coverage, prepare-gutenberg ] + permissions: + contents: read + if: | + needs.select-test-coverage.outputs.assets-only != 'true' && + startsWith( github.repository, 'WordPress/' ) && ( + github.repository == 'WordPress/wordpress-develop' || ( + github.event_name == 'pull_request' && ( + ! github.event.repository.private || + ! github.event.pull_request.draft || + contains( github.event.pull_request.labels.*.name, 'Draft Workflow Runs' ) + ) + ) + ) + strategy: + fail-fast: false + matrix: + php: [ '8.6' ] + db-version: [ '9.7', '11.8' ] + db-type: [ 'mysql', 'mariadb' ] + multisite: [ true, false ] + + exclude: + - db-type: 'mysql' + db-version: '11.8' + - db-type: 'mariadb' + db-version: '9.7' + + with: + php: ${{ matrix.php }} + db-version: ${{ matrix.db-version }} + db-type: ${{ matrix.db-type }} + multisite: ${{ matrix.multisite }} + phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} + allow-errors: true + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} + gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} + slack-notifications: name: Slack Notifications uses: ./.github/workflows/slack-notifications.yml permissions: actions: read contents: read - needs: [ prepare-gutenberg, test-with-mysql, test-with-mariadb, test-innovation-releases, html-api-test-groups, limited-matrix-for-forks ] + needs: [ select-test-coverage, prepare-gutenberg, test-assets, test-with-mysql, test-with-mariadb, test-innovation-releases, html-api-test-groups, limited-matrix-for-forks, pre-release-php-8-6 ] 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' }} @@ -411,7 +623,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/props-bot.yml b/.github/workflows/props-bot.yml index 38acc07113c2c..eea736f5c4ea3 100644 --- a/.github/workflows/props-bot.yml +++ b/.github/workflows/props-bot.yml @@ -70,6 +70,11 @@ jobs: ( ! github.event.pull_request.draft && github.event.pull_request.state == 'open' || ! github.event.issue.draft && github.event.issue.state == 'open' ) steps: + - name: Output PR link + env: + PR_URL: ${{ github.event.pull_request.html_url || github.event.issue.html_url }} + run: 'echo "::notice::Pull request: $PR_URL"' + - name: Gather a list of contributors uses: WordPress/props-bot-action@trunk with: diff --git a/.github/workflows/pull-request-comments.yml b/.github/workflows/pull-request-comments.yml index 8dff8e1c1fcce..6c56326774b8d 100644 --- a/.github/workflows/pull-request-comments.yml +++ b/.github/workflows/pull-request-comments.yml @@ -121,7 +121,8 @@ jobs: [Test this pull request with WordPress Playground](https://playground.wordpress.net/wordpress.html?pr=${ issue_number }). `; - github.rest.issues.createComment( commentInfo ); + await github.rest.issues.createComment( commentInfo ); + core.notice( `Created Playground comment for pull request: ${ pr.data.html_url }` ); # Manages comments reminding contributors to include a Trac ticket link when opening a pull request. trac-ticket-check: @@ -160,7 +161,8 @@ jobs: const tracTicketMatches = prBody.match( tracTicketRegex ) || prTitle.match( tracTicketRegex ); if ( ! tracTicketMatches ) { - github.rest.issues.createComment( { + core.info( `Creating missing Trac ticket comment for pull request: ${ pr.html_url }` ); + await github.rest.issues.createComment( { owner, repo, issue_number: number, diff --git a/.github/workflows/reusable-build-package.yml b/.github/workflows/reusable-build-package.yml index 5005b2149890c..4ca4b6e87dcb4 100644 --- a/.github/workflows/reusable-build-package.yml +++ b/.github/workflows/reusable-build-package.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that builds and packages WordPress. The resulting package can be used to test upgrading and installing. +# +# This workflow is used by `trunk` and branches >= 6.8. ## name: Build and package WordPress @@ -38,12 +40,18 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Install npm Dependencies run: npm ci - name: Build WordPress + timeout-minutes: 5 run: npm run build - name: Prepare the directory structure for the ZIP @@ -58,3 +66,4 @@ jobs: name: wordpress-develop path: develop.zip if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/reusable-cleanup-pull-requests.yml b/.github/workflows/reusable-cleanup-pull-requests.yml index 012f99adbec3b..c0266864b924c 100644 --- a/.github/workflows/reusable-cleanup-pull-requests.yml +++ b/.github/workflows/reusable-cleanup-pull-requests.yml @@ -3,6 +3,8 @@ # tickets that are referenced as fixed in commit messages. # # More info about using GitHub pull requests for contributing to WordPress can be found in the handbook: https://make.wordpress.org/core/handbook/contribute/git/github-pull-requests-for-code-review/. +# +# This workflow is used by `trunk` and branches >= 6.8. ## name: Run pull request cleanup @@ -56,33 +58,45 @@ jobs: const githubSha = process.env.GITHUB_SHA; let prNumbers = []; + core.notice(`Processing pull request cleanup for SVN changeset: https://core.trac.wordpress.org/changeset/${svnRevisionNumber}`); + for (const ticket of fixedList) { const tracTicketUrl = `https://core.trac.wordpress.org/ticket/${ticket}`; const corePrefix = `core-${ticket}`; + core.info(`Ticket: ${tracTicketUrl}`); + const query = ` query($searchQuery: String!) { search(query: $searchQuery, type: ISSUE_ADVANCED, first: 20) { nodes { ... on PullRequest { number - bodyText + body } } } } `; - const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open ( "${tracTicketUrl}" OR "${corePrefix}" )`; + // The PR template only asks for "a link to the WordPress Trac ticket", so some + // PRs reference it as a Markdown link with just the ticket number as the link + // text (e.g. "Trac ticket: [65864](https://core.trac.wordpress.org/ticket/65864)"). + // GitHub's search index doesn't cover Markdown link targets, only the rendered + // text, so the bare ticket number is searched for too to surface those PRs. + const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open ( "${tracTicketUrl}" OR "${corePrefix}" OR "${ticket}" )`; const result = await github.graphql(query, { searchQuery, }); - // Since search queries will match anywhere for any activity on a pull request, the body specifically needs to be manually checked. + // Since search queries will match anywhere for any activity on a pull request, the body + // specifically needs to be manually checked. The raw `body` (rather than `bodyText`) is used + // here because `bodyText` strips Markdown links down to just their visible text, which would + // drop the Trac ticket URL entirely for PRs that link the ticket via its number. const matchingPRs = result.search.nodes .filter(pr => { - const bodyLower = pr.bodyText.toLowerCase(); + const bodyLower = pr.body.toLowerCase(); return bodyLower.includes(tracTicketUrl.toLowerCase()) || bodyLower.includes(corePrefix.toLowerCase()); }).map(pr => pr.number); @@ -97,8 +111,13 @@ jobs: This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.`; + const uniquePrNumbers = [...new Set(prNumbers)]; + core.info(`Found ${uniquePrNumbers.length} pull request(s) to close.`); + // Update all matched pull requests. - for (const prNumber of prNumbers) { + for (const prNumber of uniquePrNumbers) { + core.info(`Closing pull request: https://github.com/${context.repo.owner}/${context.repo.repo}/pull/${prNumber}`); + // Comment on the pull request with details. await github.rest.issues.createComment({ owner: context.repo.owner, diff --git a/.github/workflows/reusable-coding-standards-javascript.yml b/.github/workflows/reusable-coding-standards-javascript.yml index 8c0ea06345b85..c81ef7aa2c262 100644 --- a/.github/workflows/reusable-coding-standards-javascript.yml +++ b/.github/workflows/reusable-coding-standards-javascript.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that checks the JavaScript coding standards. +# +# This workflow is used by `trunk` and branches >= 4.7. ## name: JavaScript coding standards @@ -43,7 +45,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Log debug information run: | diff --git a/.github/workflows/reusable-coding-standards-php.yml b/.github/workflows/reusable-coding-standards-php.yml index f0ee3ae0479f2..52779b0aa29b0 100644 --- a/.github/workflows/reusable-coding-standards-php.yml +++ b/.github/workflows/reusable-coding-standards-php.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that checks the PHP coding standards. +# +# This workflow is used by `trunk` and branches >= 5.1. ## name: PHP coding standards diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 9b5586973aacf..54bd6b4230fab 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -1,8 +1,7 @@ ## # A reusable workflow that runs end-to-end tests. # -# Branches 6.3 and earlier used Puppeteer instead of Playwright. -# Use https://github.com/WordPress/wordpress-develop/tree/6.3/.github/workflows/reusable-end-to-end-tests.yml instead. +# This workflow is used by `trunk` and branches >= 5.8. ## name: End-to-end Tests @@ -85,7 +84,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Log debug information run: | @@ -100,9 +104,10 @@ jobs: - name: Install Playwright browsers if: ${{ inputs.install-playwright }} - run: npm exec --no -- playwright install --with-deps chromium + run: npm exec --no -- playwright install chromium - name: Build WordPress + timeout-minutes: 5 run: npm run build - name: Start Docker environment @@ -143,6 +148,10 @@ jobs: - name: Run E2E tests run: npm run test:e2e + env: + # Chromium is installed above and is the only browser the suite runs. Without this, + # `wp-scripts test-playwright` also downloads Firefox and WebKit on every run. + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: ${{ inputs.install-playwright && '1' || '' }} - name: Archive debug artifacts (screenshots, HTML snapshots) uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -152,6 +161,7 @@ jobs: path: artifacts if-no-files-found: ignore include-hidden-files: true + retention-days: 14 - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code diff --git a/.github/workflows/reusable-javascript-tests.yml b/.github/workflows/reusable-javascript-tests.yml index c0bf656d124bb..62b237a515e66 100644 --- a/.github/workflows/reusable-javascript-tests.yml +++ b/.github/workflows/reusable-javascript-tests.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that runs JavaScript tests. +# +# This workflow is used by `trunk` and branches >= 4.7. ## name: JavaScript tests @@ -44,7 +46,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Log debug information run: | diff --git a/.github/workflows/reusable-javascript-type-checking-v1.yml b/.github/workflows/reusable-javascript-type-checking-v1.yml index 032fa67bf7be8..e0bf36ce19c9c 100644 --- a/.github/workflows/reusable-javascript-type-checking-v1.yml +++ b/.github/workflows/reusable-javascript-type-checking-v1.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that runs JavaScript Type Checking. +# +# This workflow is used by `trunk` and branches >= 7.0. ## name: JavaScript Type Checking @@ -42,7 +44,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Log debug information run: | diff --git a/.github/workflows/reusable-performance-report-v2.yml b/.github/workflows/reusable-performance-report-v2.yml index a2bce3e7c362b..56cc147491955 100644 --- a/.github/workflows/reusable-performance-report-v2.yml +++ b/.github/workflows/reusable-performance-report-v2.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that compares and publishes the performance tests. +# +# This workflow is used by `trunk` and branches >= 6.8. ## name: Compare and publish performance Tests @@ -65,7 +67,7 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false - name: Download artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/.github/workflows/reusable-performance-test-v2.yml b/.github/workflows/reusable-performance-test-v2.yml index b92893f52f7f1..6b0e43e136c37 100644 --- a/.github/workflows/reusable-performance-test-v2.yml +++ b/.github/workflows/reusable-performance-test-v2.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that runs the performance test suite. +# +# This workflow is used by `trunk` and branches >= 6.8. ## name: Run performance Tests @@ -126,7 +128,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Set up PHP if: ${{ inputs.subject == 'base' }} @@ -154,6 +161,7 @@ jobs: run: npm run env:start - name: Build WordPress + timeout-minutes: 5 run: npm run build - name: Download previous build artifact (target branch or previous commit) @@ -271,6 +279,7 @@ jobs: path: artifacts if-no-files-found: error include-hidden-files: true + retention-days: 1 - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code diff --git a/.github/workflows/reusable-php-compatibility.yml b/.github/workflows/reusable-php-compatibility.yml index 156494118fced..d22ca18a66928 100644 --- a/.github/workflows/reusable-php-compatibility.yml +++ b/.github/workflows/reusable-php-compatibility.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that runs PHP compatibility tests. +# +# This workflow is used by `trunk` and branches >= 5.5. ## name: PHP Compatibility diff --git a/.github/workflows/reusable-phpstan-static-analysis-v1.yml b/.github/workflows/reusable-phpstan-static-analysis-v1.yml index 26a14ba8d890f..57a48d0e3d503 100644 --- a/.github/workflows/reusable-phpstan-static-analysis-v1.yml +++ b/.github/workflows/reusable-phpstan-static-analysis-v1.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that runs PHP Static Analysis tests. +# +# This workflow is used by `trunk` and branches >= 7.0. ## name: PHP Static Analysis @@ -23,12 +25,10 @@ jobs: # # Performs the following steps: # - Checks out the repository. - # - Sets up Node.js. # - Sets up PHP. # - Logs debug information. # - Installs Composer dependencies. # - Make Composer packages available globally. - # - Installs npm dependencies. # - Builds WordPress. # - Configures caching for PHPStan static analysis scans. # - Runs PHPStan static analysis (with Pull Request annotations). @@ -49,12 +49,6 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: '.nvmrc' - cache: npm - - name: Set up PHP uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: @@ -64,8 +58,6 @@ jobs: - name: General debug information run: | - npm --version - node --version composer --version # Since Composer dependencies are installed using `composer update` and no lock file is in version control, @@ -78,19 +70,30 @@ jobs: - name: Make Composer packages available globally run: echo "${PWD}/vendor/bin" >> "$GITHUB_PATH" - - name: Install npm dependencies - run: npm ci --ignore-scripts - - - name: Build WordPress - run: npm run build:dev - + # The directory holds more than the analysis results. PHPStan also stores what it read out of + # each source file there, the docblocks and signatures it found, keyed by that file's contents + # and nothing else. The extensions in `tests/phpstan` change what reading a file yields without + # changing the file: a parser node visitor rewrites a docblock in the syntax tree, and the bytes + # on disk stay as they were. A cache written before one of them changed therefore answers with + # what the old code saw, and the analysis silently runs against types no longer derived. + # + # Keying on the configuration and the extensions keeps a run from restoring a cache that + # predates either. The baselines are left out of the key: they only decide which reported errors + # are ignored, PHPStan invalidates the results cache on a configuration change by itself, and + # including them would discard the whole cache every time one is regenerated. + # + # The cache is renamed rather than only prefixed, because the key this replaces restored on + # `phpstan-result-cache-`, which every key below still begins with. A branch that has not + # merged this commit yet runs the workflow it has, and that workflow would prefix-match the + # caches written here: it would analyse without the extensions against reflection derived with + # them. A name of its own leaves those runs restoring only their own caches. - name: Cache PHP Static Analysis scan cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .cache # This is defined in the base.neon file. - key: "phpstan-result-cache-${{ github.run_id }}" + key: "phpstan-analysis-cache-${{ hashFiles('phpstan.neon.dist', 'tests/phpstan/*.neon', 'tests/phpstan/*.php') }}-${{ github.run_id }}" restore-keys: | - phpstan-result-cache- + phpstan-analysis-cache-${{ hashFiles('phpstan.neon.dist', 'tests/phpstan/*.neon', 'tests/phpstan/*.php') }}- - name: Run PHP static analysis tests id: phpstan @@ -193,7 +196,7 @@ jobs: if: ${{ !cancelled() }} with: path: .cache - key: "phpstan-result-cache-${{ github.run_id }}" + key: "phpstan-analysis-cache-${{ hashFiles('phpstan.neon.dist', 'tests/phpstan/*.neon', 'tests/phpstan/*.php') }}-${{ github.run_id }}" - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code diff --git a/.github/workflows/reusable-phpunit-tests-v1.yml b/.github/workflows/reusable-phpunit-tests-v1.yml index 13c87c62671f8..dc5a0d1edd982 100644 --- a/.github/workflows/reusable-phpunit-tests-v1.yml +++ b/.github/workflows/reusable-phpunit-tests-v1.yml @@ -15,6 +15,16 @@ on: required: false type: 'string' default: 'ubuntu-24.04' + repository: + description: 'The repository to check out and test. Defaults to the repository calling this workflow.' + required: false + type: 'string' + default: '' + ref: + description: 'The branch, tag, or SHA to check out. Defaults to the ref that triggered the calling workflow.' + required: false + type: 'string' + default: '' php: description: 'The version of PHP to use, in the format of X.Y' required: true @@ -44,11 +54,21 @@ on: required: false type: 'string' default: 'phpunit.xml.dist' + phpunit-test-groups: + description: 'A list of test groups to run.' + required: false + type: 'string' + default: '' allow-errors: description: 'Whether to continue when test errors occur.' required: false type: boolean default: false + overlay-artifact: + description: 'The name of a same-workflow artifact whose contents are unpacked over the checkout. Optional: for callers whose test files are not part of the repository being tested.' + required: false + type: string + default: '' env: COMPOSER_INSTALL: false LOCAL_PHP: ${{ inputs.php }}-fpm @@ -91,6 +111,25 @@ jobs: contents: read steps: + # `ref` otherwise falls back to checkout's own default, which for another repository is + # its default branch: a "WordPress 6.2" job would test trunk and report green. + - name: Require a ref when testing another repository + if: ${{ inputs.repository != '' && inputs.ref == '' }} + run: | + echo 'Testing another repository needs an explicit ref.' >&2 + exit 1 + + # Legacy docker.js reparses arguments as shell: allow only group names. + - name: Validate test groups + if: ${{ inputs.phpunit-test-groups != '' }} + env: + TEST_GROUPS: ${{ inputs.phpunit-test-groups }} + run: | + if [[ ! "$TEST_GROUPS" =~ ^[A-Za-z0-9_.-]+(,[A-Za-z0-9_.-]+)*$ ]]; then + echo 'phpunit-test-groups must be a comma-separated list of group names.' >&2 + exit 1 + fi + - name: Configure environment variables run: | echo "PHP_FPM_UID=$(id -u)" >> "$GITHUB_ENV" @@ -99,9 +138,21 @@ jobs: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: + repository: ${{ inputs.repository || github.repository }} + ref: ${{ inputs.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false + # If the caller specifies an overlay artifact then unpack it over the checkout. + - name: Download overlay artifact + if: inputs.overlay-artifact != '' + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + # Without a run ID, this action reads only from the caller's current workflow run. + name: ${{ inputs.overlay-artifact }} + path: . + digest-mismatch: error + - name: Set up Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: @@ -173,25 +224,27 @@ jobs: run: npm run env:install - name: Run slow PHPUnit tests - if: ${{ inputs.split_slow }} + if: ${{ inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --group "${SLOW_TESTS}" - name: Run PHPUnit tests for single site excluding slow tests - if: ${{ inputs.php < '7.0' && ! inputs.split_slow && ! inputs.multisite }} + if: ${{ inputs.php < '7.0' && ! inputs.split_slow && ! inputs.multisite && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --exclude-group "${SLOW_TESTS},ajax,ms-files,ms-required" - name: Run PHPUnit tests for Multisite excluding slow tests - if: ${{ inputs.php < '7.0' && ! inputs.split_slow && inputs.multisite }} + if: ${{ inputs.php < '7.0' && ! inputs.split_slow && inputs.multisite && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --exclude-group "${SLOW_TESTS},ajax,ms-files,ms-excluded,oembed-headers" - name: Run PHPUnit tests - if: ${{ inputs.php >= '7.0' }} - run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" + if: ${{ inputs.php >= '7.0' || inputs.phpunit-test-groups }} + run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" ${{ inputs.phpunit-test-groups && '--group "${TEST_GROUPS}"' || '' }} + env: + TEST_GROUPS: ${{ inputs.phpunit-test-groups }} - name: Run AJAX tests - if: ${{ ! inputs.multisite && ! inputs.split_slow }} + if: ${{ ! inputs.multisite && ! inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --group ajax - name: Run external HTTP tests - if: ${{ ! inputs.multisite && ! inputs.split_slow }} + if: ${{ ! inputs.multisite && ! inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c phpunit.xml.dist --group external-http diff --git a/.github/workflows/reusable-phpunit-tests-v2.yml b/.github/workflows/reusable-phpunit-tests-v2.yml index 15dea5fc31efa..628b5387f0e4f 100644 --- a/.github/workflows/reusable-phpunit-tests-v2.yml +++ b/.github/workflows/reusable-phpunit-tests-v2.yml @@ -15,6 +15,16 @@ on: required: false type: 'string' default: 'ubuntu-24.04' + repository: + description: 'The repository to check out and test. Defaults to the repository calling this workflow.' + required: false + type: 'string' + default: '' + ref: + description: 'The branch, tag, or SHA to check out. Defaults to the ref that triggered the calling workflow.' + required: false + type: 'string' + default: '' php: description: 'The version of PHP to use, in the format of X.Y' required: true @@ -44,6 +54,11 @@ on: required: false type: 'string' default: 'phpunit.xml.dist' + phpunit-test-groups: + description: 'A list of test groups to run.' + required: false + type: 'string' + default: '' report: description: 'Whether to report results to WordPress.org Hosting Tests' required: false @@ -54,6 +69,11 @@ on: required: false type: boolean default: false + overlay-artifact: + description: 'The name of a same-workflow artifact whose contents are unpacked over the checkout. Optional: for callers whose test files are not part of the repository being tested.' + required: false + type: string + default: '' env: LOCAL_PHP: ${{ inputs.php }}-fpm LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }} @@ -93,6 +113,25 @@ jobs: contents: read steps: + # `ref` otherwise falls back to checkout's own default, which for another repository is + # its default branch: a "WordPress 6.2" job would test trunk and report green. + - name: Require a ref when testing another repository + if: ${{ inputs.repository != '' && inputs.ref == '' }} + run: | + echo 'Testing another repository needs an explicit ref.' >&2 + exit 1 + + # Legacy docker.js reparses arguments as shell: allow only group names. + - name: Validate test groups + if: ${{ inputs.phpunit-test-groups != '' }} + env: + TEST_GROUPS: ${{ inputs.phpunit-test-groups }} + run: | + if [[ ! "$TEST_GROUPS" =~ ^[A-Za-z0-9_.-]+(,[A-Za-z0-9_.-]+)*$ ]]; then + echo 'phpunit-test-groups must be a comma-separated list of group names.' >&2 + exit 1 + fi + - name: Configure environment variables run: | echo "PHP_FPM_UID=$(id -u)" >> "$GITHUB_ENV" @@ -101,9 +140,21 @@ jobs: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: + repository: ${{ inputs.repository || github.repository }} + ref: ${{ inputs.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false + # If the caller specifies an overlay artifact then unpack it over the checkout. + - name: Download overlay artifact + if: inputs.overlay-artifact != '' + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + # Without a run ID, this action reads only from the caller's current workflow run. + name: ${{ inputs.overlay-artifact }} + path: . + digest-mismatch: error + - name: Install Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: @@ -176,36 +227,38 @@ jobs: run: npm run env:install - name: Run slow PHPUnit tests - if: ${{ inputs.split_slow }} + if: ${{ inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --group "${SLOW_TESTS}" - name: Run PHPUnit tests for single site excluding slow tests - if: ${{ inputs.php < '7.0' && ! inputs.split_slow && ! inputs.multisite }} + if: ${{ inputs.php < '7.0' && ! inputs.split_slow && ! inputs.multisite && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --exclude-group "${SLOW_TESTS},ajax,ms-files,ms-required" - name: Run PHPUnit tests for Multisite excluding slow tests - if: ${{ inputs.php < '7.0' && ! inputs.split_slow && inputs.multisite }} + if: ${{ inputs.php < '7.0' && ! inputs.split_slow && inputs.multisite && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --exclude-group "${SLOW_TESTS},ajax,ms-files,ms-excluded,oembed-headers" - name: Run PHPUnit tests - if: ${{ inputs.php >= '7.0' }} - run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" + if: ${{ inputs.php >= '7.0' || inputs.phpunit-test-groups }} + run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" ${{ inputs.phpunit-test-groups && '--group "${TEST_GROUPS}"' || '' }} + env: + TEST_GROUPS: ${{ inputs.phpunit-test-groups }} - name: Run AJAX tests - if: ${{ ! inputs.split_slow&& inputs.test_ajax }} + if: ${{ ! inputs.split_slow&& inputs.test_ajax && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --group ajax - name: Run ms-files tests as a multisite install - if: ${{ inputs.multisite && ! inputs.split_slow }} + if: ${{ inputs.multisite && ! inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c "${PHPUNIT_CONFIG}" --group ms-files - name: Run external HTTP tests - if: ${{ ! inputs.multisite && ! inputs.split_slow }} + if: ${{ ! inputs.multisite && ! inputs.split_slow && ! inputs.phpunit-test-groups }} run: npm run "test:${PHPUNIT_SCRIPT}" -- --verbose -c phpunit.xml.dist --group external-http # __fakegroup__ is excluded to force PHPUnit to ignore the settings in phpunit.xml.dist. - name: Run (xDebug) tests - if: ${{ ! inputs.split_slow }} + if: ${{ ! inputs.split_slow && ! inputs.phpunit-test-groups }} run: LOCAL_PHP_XDEBUG=true npm run "test:${PHPUNIT_SCRIPT}" -- -v --group xdebug --exclude-group __fakegroup__ - name: Ensure version-controlled files are not modified or deleted diff --git a/.github/workflows/reusable-phpunit-tests-v3.yml b/.github/workflows/reusable-phpunit-tests-v3.yml index 4f7addcd4e60e..024a4afd7f498 100644 --- a/.github/workflows/reusable-phpunit-tests-v3.yml +++ b/.github/workflows/reusable-phpunit-tests-v3.yml @@ -13,6 +13,18 @@ on: required: false type: 'string' default: 'ubuntu-24.04' + repository: + description: 'The repository to check out and test. Defaults to the repository calling this workflow.' + required: false + type: 'string' + default: '' + # Also composes the Gutenberg build name, under the producer's constraint: a valid + # artifact name, so no slashes and none of : < > | * ? " + ref: + description: 'The branch, tag, or SHA to check out. Defaults to the ref that triggered the calling workflow.' + required: false + type: 'string' + default: '' php: description: 'The version of PHP to use, in the format of X.Y' required: true @@ -82,7 +94,15 @@ on: required: false type: string default: '' + overlay-artifact: + description: 'The name of a same-workflow artifact whose contents are unpacked over the checkout. Optional: for callers whose test files are not part of the repository being tested.' + required: false + type: string + default: '' secrets: + CODEVITALS_PROJECT_TOKEN: + description: 'The authorization token for publishing results to CodeVitals.' + required: false CODECOV_TOKEN: description: 'The Codecov token required for uploading reports.' required: false @@ -109,8 +129,10 @@ jobs: # Runs the PHPUnit tests for WordPress. # # Performs the following steps: + # - Requires a ref when the caller points at another repository. # - Sets environment variables. # - Checks out the repository. + # - Unpacks the caller-provided overlay artifact over the checkout, if any. # - Downloads the prepared Gutenberg build provided by the calling workflow. # - Sets up Node.js. # - Sets up PHP. @@ -123,6 +145,8 @@ jobs: # - Logs debug information about what's installed within the WordPress Docker containers. # - Install WordPress within the Docker container. # - Run the PHPUnit tests. + # - Flags slow PHPUnit tests with GitHub Actions annotations and a run summary. + # - Publish PHPUnit timing metrics to CodeVitals. # - Upload the code coverage report to Codecov.io. # - Ensures version-controlled files are not modified or deleted. # - Checks out the WordPress Test reporter repository. @@ -130,11 +154,32 @@ jobs: phpunit-tests: name: ${{ ( inputs.phpunit-test-groups || inputs.coverage-report ) && format( 'PHP {0} with ', inputs.php ) || '' }} ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.multisite && ' multisite' || '' }}${{ inputs.db-innovation && ' (innovation release)' || '' }}${{ inputs.memcached && ' with memcached' || '' }}${{ inputs.report && ' (test reporting enabled)' || '' }} ${{ 'example.org' != inputs.tests-domain && inputs.tests-domain || '' }} runs-on: ${{ vars.RUNNERS_NAME || inputs.os }} - timeout-minutes: ${{ inputs.coverage-report && 120 || inputs.php == '8.4' && 30 || 20 }} + timeout-minutes: ${{ inputs.coverage-report && 120 || 30 }} permissions: contents: read steps: + # `ref` otherwise falls back to checkout's own default, which for another repository is + # its default branch: a "WordPress 6.2" job would test trunk and report green. + - name: Require a ref when testing another repository + if: ${{ inputs.repository != '' && inputs.ref == '' }} + run: | + echo 'Testing another repository needs an explicit ref.' >&2 + exit 1 + + # `ref` also composes the Gutenberg artifact name, so reject what that name cannot carry + # here rather than at a download step the job only reaches minutes later. + - name: Require a ref the artifact name accepts + if: ${{ inputs.ref != '' }} + env: + REF: ${{ inputs.ref }} + run: | + invalid='[/:<>|*?"\]' + if [[ "$REF" =~ $invalid ]]; then + echo "A ref that names an artifact cannot contain / : < > | * ? \" \\ - received: $REF" >&2 + exit 1 + fi + - name: Configure environment variables run: | echo "PHP_FPM_UID=$(id -u)" >> "$GITHUB_ENV" @@ -143,15 +188,30 @@ jobs: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: + repository: ${{ inputs.repository || github.repository }} + ref: ${{ inputs.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false + # If the caller specifies an overlay artifact then unpack it over the checkout. + - name: Download overlay artifact + if: inputs.overlay-artifact != '' + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + # Without a run ID, this action reads only from the caller's current workflow run. + name: ${{ inputs.overlay-artifact }} + path: . + digest-mismatch: error + # Only WordPress 7.0+ include Gutenberg-maintained assets from a built zip file. - name: Download prepared Gutenberg build if: ${{ inputs.gutenberg-artifact }} uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: gutenberg-build + # Every branch in a run shares one artifact namespace, so the producer names each + # build after the ref it came from. Compose the same name here rather than taking + # it as an input: the two sides already agree on `ref`. + name: gutenberg-build${{ inputs.ref && format( '-{0}', inputs.ref ) || '' }} path: gutenberg digest-mismatch: error @@ -159,7 +219,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm ## # This allows Composer dependencies to be installed using a single step. @@ -185,6 +250,7 @@ jobs: run: npm ci - name: Build WordPress + timeout-minutes: 5 run: npm run build:dev env: # The producer resolved this once. Matrix jobs must not re-resolve mutable GHCR tags. @@ -256,6 +322,7 @@ jobs: continue-on-error: ${{ inputs.allow-errors }} run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c "${PHPUNIT_CONFIG}" --group external-http + # PHPUnit versions used below PHP 7.3 do not support --fail-on-empty-test-suite. - name: Run PHPUnit tests${{ inputs.phpunit-test-groups && format( ' ({0} groups)', inputs.phpunit-test-groups ) || '' }}${{ inputs.coverage-report && ' with coverage report' || '' }} continue-on-error: ${{ inputs.allow-errors }} run: | @@ -264,11 +331,69 @@ jobs: --verbose \ -c "${PHPUNIT_CONFIG}" \ ${{ inputs.phpunit-test-groups && '--group "${TEST_GROUPS}"' || '' }} \ + ${{ inputs.phpunit-test-groups && inputs.php >= '7.3' && '--fail-on-empty-test-suite' || '' }} \ ${{ inputs.coverage-report && '--coverage-clover "wp-code-coverage-${MULTISITE_FLAG}-${GITHUB_SHA}.xml"' || '' }} env: TEST_GROUPS: ${{ inputs.phpunit-test-groups }} MULTISITE_FLAG: ${{ inputs.multisite && 'multisite' || 'single' }} + - name: Flag slow PHPUnit tests + # Runs when the test step succeeds or fails, but skips cancelled jobs. + # This step never fails the job itself (continue-on-error), because the + # slow-test signal is advisory only. + if: >- + ${{ + ! cancelled() && inputs.report && inputs.php == '8.5' && + ( github.event_name == 'pull_request' || + ( github.event_name == 'push' && github.ref == 'refs/heads/trunk' ) ) + }} + continue-on-error: true + run: | + if [ -f tests/phpunit/build/logs/junit.xml ]; then + php tests/phpunit/prepare-slow-test-annotations.php \ + tests/phpunit/build/logs/junit.xml \ + 1.0 \ + 20 \ + "$RUNNER_TEMP/phpunit-timing-metrics.json" + else + echo 'PHPUnit JUnit report not found; skipping slow-test annotations.' + fi + + - name: Publish PHPUnit timing metrics + continue-on-error: true + if: | + github.event_name == 'push' && + github.ref == 'refs/heads/trunk' && + inputs.php == '8.5' && + inputs.report + env: + CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }} + shell: bash + run: | + if [ -z "$CODEVITALS_PROJECT_TOKEN" ]; then + echo "PHPUnit timing metrics could not be published. 'CODEVITALS_PROJECT_TOKEN' is not set" + exit 1 + fi + COMMITTED_AT="$(git show -s "$GITHUB_SHA" --format='%cI')" + RESPONSE="$( + php tests/phpunit/prepare-timing-results.php \ + tests/phpunit/build/logs/junit.xml \ + trunk \ + "$GITHUB_SHA" \ + "$COMMITTED_AT" \ + "$RUNNER_TEMP/phpunit-timing-metrics.json" \ + | curl --fail-with-body --silent --show-error \ + --request POST \ + --header 'Content-Type: application/json' \ + --data-binary @- \ + "https://codevitals.run/api/log?token=${CODEVITALS_PROJECT_TOKEN}" + )" + if ! php -r "\$d = json_decode(file_get_contents('php://stdin'), true); exit(is_array(\$d) && (\$d['status'] ?? null) === 'ok' && (int) (\$d['count'] ?? 0) === 6 ? 0 : 1);" <<< "$RESPONSE"; then + echo 'CodeVitals did not accept all six PHPUnit timing metrics.' + exit 1 + fi + echo 'Published six PHPUnit timing metrics to CodeVitals.' + - name: Run AJAX tests if: ${{ ! inputs.phpunit-test-groups && ! inputs.coverage-report }} continue-on-error: ${{ inputs.allow-errors }} diff --git a/.github/workflows/reusable-prepare-gutenberg.yml b/.github/workflows/reusable-prepare-gutenberg.yml index c5e1f904a9680..fd7381550f349 100644 --- a/.github/workflows/reusable-prepare-gutenberg.yml +++ b/.github/workflows/reusable-prepare-gutenberg.yml @@ -6,6 +6,19 @@ name: Prepare Gutenberg build on: workflow_call: + inputs: + repository: + description: 'The repository to check out. Defaults to the repository calling this workflow.' + required: false + type: 'string' + default: '' + # Names the uploaded build too, so it must also be a valid artifact name: no slashes, + # and none of : < > | * ? " — a `refs/heads/trunk` or `feature/x` value fails the upload. + ref: + description: 'The branch, tag, or SHA to check out. Defaults to the commit that started the calling workflow run.' + required: false + type: 'string' + default: '' outputs: gutenberg-sha: description: 'The immutable Gutenberg source SHA verified by this workflow.' @@ -19,18 +32,41 @@ jobs: prepare-gutenberg: name: Gutenberg runs-on: ubuntu-24.04 - timeout-minutes: 10 + # Two download attempts of up to six minutes each, where download.js retries internally. + timeout-minutes: 15 outputs: gutenberg-sha: ${{ steps.download.outputs.gutenberg-sha }} permissions: contents: read steps: + # `ref` otherwise falls back to this run's commit, which another repository does not have. + - name: Require a ref when preparing another repository + if: ${{ inputs.repository != '' && inputs.ref == '' }} + run: | + echo 'Preparing another repository needs an explicit ref.' >&2 + exit 1 + + # The upload names the artifact after `ref` and is this job's last step, so an unusable + # value would otherwise fail only once the whole download and verify has already run. + - name: Require a ref the artifact name accepts + if: ${{ inputs.ref != '' }} + env: + REF: ${{ inputs.ref }} + run: | + invalid='[/:<>|*?"\]' + if [[ "$REF" =~ $invalid ]]; then + echo "A ref that names an artifact cannot contain / : < > | * ? \" \\ - received: $REF" >&2 + exit 1 + fi + - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - # Resolve the Gutenberg ref from the exact commit that started this workflow run. - ref: ${{ github.sha }} + repository: ${{ inputs.repository || github.repository }} + # Resolve the Gutenberg ref from the exact commit that started this workflow run, + # unless the caller is preparing a build for a repository or branch of its own. + ref: ${{ inputs.ref || github.sha }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false @@ -38,11 +74,22 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Download and verify Gutenberg build id: download run: | - node tools/gutenberg/download.js + # Branches whose download.js predates the in-script retry stream the blob straight + # into tar in a single attempt, so an interrupted stream fails the run outright. + # One retry, not two: where download.js does retry, it already allows three tries of + # two minutes each, and a third attempt here would outrun `timeout-minutes` and have + # the job killed rather than reported. + if ! node tools/gutenberg/download.js; then + echo 'Gutenberg download failed; retrying in 5 seconds...' + sleep 5 + node tools/gutenberg/download.js + fi + gutenberg_sha="$(tr -d '\n' < gutenberg/.gutenberg-hash)" if [[ ! "$gutenberg_sha" =~ ^[a-fA-F0-9]{40}$ ]]; then echo "Expected a 40-character Gutenberg SHA, received: $gutenberg_sha" >&2 @@ -53,8 +100,11 @@ jobs: - name: Upload Gutenberg build uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: gutenberg-build + # Every branch in a run shares one artifact namespace, so name the build after the + # ref it came from. The PHPUnit consumer composes the same name from its own `ref`, + # so the name is never passed between them. + name: gutenberg-build${{ inputs.ref && format( '-{0}', inputs.ref ) || '' }} path: gutenberg/ if-no-files-found: error include-hidden-files: true - retention-days: 1 + retention-days: 7 diff --git a/.github/workflows/reusable-support-json-reader-v1.yml b/.github/workflows/reusable-support-json-reader-v1.yml index d193b4a9ea92e..a44aa103208e5 100644 --- a/.github/workflows/reusable-support-json-reader-v1.yml +++ b/.github/workflows/reusable-support-json-reader-v1.yml @@ -1,6 +1,8 @@ ## # A reusable workflow that reads the .version-support-*.json files and returns values for use in a # test matrix based on a given WordPress version. +# +# This workflow is used by `trunk` and branches >= 6.8. ## name: Determine test matrix values diff --git a/.github/workflows/reusable-test-core-build-process.yml b/.github/workflows/reusable-test-core-build-process.yml index 1a41257418dec..8b42e2b75b72e 100644 --- a/.github/workflows/reusable-test-core-build-process.yml +++ b/.github/workflows/reusable-test-core-build-process.yml @@ -1,5 +1,7 @@ ## # A reusable workflow that tests the WordPress Core build process. +# +# This workflow is used by `trunk` and branches >= 4.7. ## name: Test the WordPress Build Process @@ -94,7 +96,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm - name: Log debug information run: | @@ -121,6 +128,7 @@ jobs: run: npm run grunt copy:certificates && npm run grunt build:certificates - name: Build WordPress to run from ${{ inputs.directory }} + timeout-minutes: 5 run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }} - name: Ensure version-controlled files are not modified or deleted during building @@ -143,6 +151,7 @@ jobs: name: wordpress-build-${{ github.event_name == 'pull_request' && github.event.number || github.sha }} path: wordpress.zip if-no-files-found: error + retention-days: 14 - name: Save PR number if: ${{ inputs.prepare-playground }} diff --git a/.github/workflows/reusable-test-gutenberg-build-process.yml b/.github/workflows/reusable-test-gutenberg-build-process.yml index a538daeed6779..e9c68d232807f 100644 --- a/.github/workflows/reusable-test-gutenberg-build-process.yml +++ b/.github/workflows/reusable-test-gutenberg-build-process.yml @@ -1,5 +1,9 @@ ## +# DEPRECATED +# # A reusable workflow that tests the Gutenberg plugin build process when run within a wordpress-develop checkout. +# +# This workflow is used by branches 6.5 through 6.9. ## name: Test the Gutenberg plugin Build Process @@ -16,6 +20,11 @@ on: required: false type: 'string' default: 'src' + gutenberg-branch: + description: 'The branch in the Gutenberg repository that should be tested against.' + required: false + type: 'string' + default: 'trunk' env: GUTENBERG_DIRECTORY: ${{ inputs.directory == 'build' && 'build' || 'src' }}/wp-content/plugins/gutenberg @@ -58,6 +67,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: repository: 'WordPress/gutenberg' + ref: ${{ inputs.gutenberg-branch }} path: ${{ env.GUTENBERG_DIRECTORY }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} persist-credentials: false diff --git a/.github/workflows/reusable-test-local-docker-environment-v1.yml b/.github/workflows/reusable-test-local-docker-environment-v1.yml index 71c8a9a739f66..5d63fbc9aa4b4 100644 --- a/.github/workflows/reusable-test-local-docker-environment-v1.yml +++ b/.github/workflows/reusable-test-local-docker-environment-v1.yml @@ -95,7 +95,12 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - cache: npm + package-manager-cache: false + + - name: Set up npm + # Release branches run this workflow from trunk, but some older branches may lack the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm ## # This allows Composer dependencies to be installed using a single step. @@ -121,6 +126,7 @@ jobs: run: npm ci - name: Build WordPress + timeout-minutes: 5 run: npm run build:dev - name: General debug information diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index 169abe20006a4..95645aee79981 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -56,6 +56,7 @@ jobs: # - Updates to the version of WordPress being tested. # - Updates the database. # - Checks the version of WordPress after the upgrade. + # - Serves the upgraded site and confirms it renders. upgrade-tests: name: PHP ${{ inputs.php }} with ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.multisite && ' multisite' || '' }} permissions: @@ -63,13 +64,19 @@ jobs: runs-on: ${{ inputs.os }} timeout-minutes: 20 + env: + WP_ADMIN_USER: admin + WP_ADMIN_PASSWORD: password + services: database: image: ${{ inputs.db-type }}:${{ inputs.db-version }} ports: - 3306 + # Ping over TCP, to wait for the TCP server rather than the Unix socket. + # MariaDB 11.0 dropped the `mysqladmin` symlink, so pick the client the image ships. options: >- - --health-cmd="mysqladmin ping" + --health-cmd="${{ inputs.db-type == 'mariadb' && ! contains( fromJSON('["5.5", "10.0", "10.1", "10.2", "10.3"]'), inputs.db-version ) && 'mariadb-admin' || 'mysqladmin' }} ping -h 127.0.0.1 --protocol=tcp" --health-interval="30s" --health-timeout="10s" --health-retries="5" @@ -97,8 +104,8 @@ jobs: - name: Install WordPress run: | wp core ${{ inputs.multisite && 'multisite-install' || 'install' }} \ - --url=http://localhost/ --title="Upgrade Test" --admin_user=admin \ - --admin_password=password --admin_email=me@example.org --skip-email + --url=http://localhost/ --title="Upgrade Test" --admin_user="${WP_ADMIN_USER}" \ + --admin_password="${WP_ADMIN_PASSWORD}" --admin_email=me@example.org --skip-email - name: Pre-upgrade version check run: wp core version @@ -135,3 +142,11 @@ jobs: - name: Post-upgrade version check run: wp core version + + - name: Post-upgrade smoke check + # A network's domain lives in wp-config.php and the database, not just an option. + if: ${{ ! inputs.multisite }} + uses: WordPress/wordpress-develop/.github/actions/smoke-check@trunk # zizmor: ignore[unpinned-uses] + with: + admin-user: ${{ env.WP_ADMIN_USER }} + admin-password: ${{ env.WP_ADMIN_PASSWORD }} diff --git a/.github/workflows/reusable-workflow-lint.yml b/.github/workflows/reusable-workflow-lint.yml index 6ae6b0df10968..3c4e265458218 100644 --- a/.github/workflows/reusable-workflow-lint.yml +++ b/.github/workflows/reusable-workflow-lint.yml @@ -1,3 +1,8 @@ +## +# A reusable workflow that lints GitHub Actions workflow files. +# +# This workflow is used by `trunk` and branches >= 6.8. +## name: Lint GitHub Actions workflows on: workflow_call: @@ -29,6 +34,10 @@ jobs: with: args: "-color -verbose" + # actionlint shellchecks inline `run:` blocks, but does not read composite actions. + - name: Run shellcheck on composite action scripts + run: find .github -path '.github/actions/*' -name '*.sh' -print0 | xargs -0 -r shellcheck + # Runs the Zizmor GitHub Action workflow file linter. # # See https://github.com/zizmorcore/zizmor diff --git a/.github/workflows/slack-notifications.yml b/.github/workflows/slack-notifications.yml index 6a2f23714e291..0877405409e83 100644 --- a/.github/workflows/slack-notifications.yml +++ b/.github/workflows/slack-notifications.yml @@ -25,9 +25,6 @@ on: SLACK_GHA_FAILURE_WEBHOOK: description: 'The Slack webhook URL for a failed build.' required: true - SLACK_GHA_TIMEOUT_WEBHOOK: - description: 'The Slack webhook URL for a timed out build.' - required: false # Disable permissions for all available scopes by default. # Any needed permissions should be configured at the job level. @@ -58,7 +55,6 @@ jobs: if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event.workflow_run.event != 'pull_request' }} outputs: previous_conclusion: ${{ steps.previous-attempt-result.outputs.result }} - timed_out: ${{ steps.timeout-check.outputs.result }} payload: ${{ steps.create-payload.outputs.payload }} steps: @@ -132,25 +128,6 @@ jobs: env: CALLING_STATUS: ${{ inputs.calling_status }} - # The REST API exposes a distinct `timed_out` job conclusion that is unavailable through workflow contexts. - - name: Determine whether the workflow timed out - id: timeout-check - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - if: ${{ inputs.calling_status == 'cancelled' }} - with: - retries: 2 - retry-exempt-status-codes: 418 - result-encoding: string - script: | - const jobs = await github.paginate( github.rest.actions.listJobsForWorkflowRunAttempt, { - owner: context.repo.owner, - repo: context.repo.repo, - run_id: `${context.runId}`, - attempt_number: Number( process.env.GITHUB_RUN_ATTEMPT ), - }, ( response ) => response.data.jobs ); - - return jobs.some( ( job ) => job.conclusion === 'timed_out' ) ? 'true' : 'false'; - - name: Get the commit message id: current-commit-message uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -234,13 +211,14 @@ jobs: webhook: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} payload: ${{ needs.prepare.outputs.payload }} + # Posts notifications when a workflow is cancelled. cancelled: name: Cancelled notifications permissions: {} runs-on: ubuntu-24.04 timeout-minutes: 20 needs: [ prepare ] - if: ${{ ( inputs.calling_status == 'cancelled' && github.run_attempt == 2 && needs.prepare.outputs.timed_out != 'true' ) || cancelled() }} + if: ${{ inputs.calling_status == 'cancelled' && github.run_attempt == 2 || cancelled() }} steps: - name: Post cancelled notifications to Slack @@ -249,19 +227,3 @@ jobs: webhook-type: webhook-trigger webhook: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} payload: ${{ needs.prepare.outputs.payload }} - - timeout: - name: Timeout notifications - permissions: {} - runs-on: ubuntu-24.04 - timeout-minutes: 20 - needs: [ prepare ] - if: ${{ inputs.calling_status == 'cancelled' && github.run_attempt == 2 && needs.prepare.outputs.timed_out == 'true' }} - - steps: - - name: Post timeout notifications to Slack - uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 - with: - webhook-type: webhook-trigger - webhook: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} - payload: ${{ needs.prepare.outputs.payload }} diff --git a/.github/workflows/test-and-zip-default-themes.yml b/.github/workflows/test-and-zip-default-themes.yml index 0464a1652d36b..75de38f8f700b 100644 --- a/.github/workflows/test-and-zip-default-themes.yml +++ b/.github/workflows/test-and-zip-default-themes.yml @@ -10,6 +10,7 @@ on: # Changing the preferred version of Node.js could affect themes with build processes. - '.npmrc' - '.nvmrc' + - '.github/actions/setup-npm/**' # Changes to any themes with a build script should be confirmed. - 'src/wp-content/themes/twentynineteen/**' - 'src/wp-content/themes/twentytwenty/**' @@ -27,6 +28,7 @@ on: # Changing the preferred version of Node.js could affect themes with build processes. - '.npmrc' - '.nvmrc' + - '.github/actions/setup-npm/**' # Changes to any themes with a build script should be confirmed. - 'src/wp-content/themes/twentynineteen/**' - 'src/wp-content/themes/twentytwenty/**' @@ -160,9 +162,15 @@ jobs: - name: Set up Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version-file: '.nvmrc' - cache: npm - cache-dependency-path: src/wp-content/themes/${{ matrix.theme }}/package-lock.json + node-version-file: 'src/wp-content/themes/${{ matrix.theme }}/.nvmrc' + package-manager-cache: false + + - name: Set up npm + # A workflow_dispatch run can check out a release branch, which lacks the action. + if: ${{ hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm + with: + working-directory: src/wp-content/themes/${{ matrix.theme }} - name: Install npm dependencies run: npm ci @@ -245,9 +253,15 @@ jobs: if: matrix.theme == 'twentytwentytwo' || matrix.theme == 'twentytwentyfive' uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version-file: '.nvmrc' - cache: npm - cache-dependency-path: src/wp-content/themes/${{ matrix.theme }}/package-lock.json + node-version-file: 'src/wp-content/themes/${{ matrix.theme }}/.nvmrc' + package-manager-cache: false + + - name: Set up npm + # A workflow_dispatch run can check out a release branch, which lacks the action. + if: ${{ ( matrix.theme == 'twentytwentytwo' || matrix.theme == 'twentytwentyfive' ) && hashFiles('.github/actions/setup-npm/action.yml') != '' }} + uses: ./.github/actions/setup-npm + with: + working-directory: src/wp-content/themes/${{ matrix.theme }} - name: Install npm dependencies if: matrix.theme == 'twentytwentytwo' || matrix.theme == 'twentytwentyfive' @@ -284,7 +298,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/test-build-processes.yml b/.github/workflows/test-build-processes.yml index ab3bea392cef8..ed970276e9833 100644 --- a/.github/workflows/test-build-processes.yml +++ b/.github/workflows/test-build-processes.yml @@ -12,23 +12,38 @@ on: - '3.[7-9]' - '[4-9].[0-9]' paths: - # Any change to a PHP, CSS, JavaScript, or JSON file should run checks. - - '**.css' - - '**.js' - - '**.json' - - '**.php' - # These files configure npm and the task runner. Changes could affect the outcome. - - 'package*.json' - - '.npmrc' - - '.nvmrc' - - 'Gruntfile.js' - - 'webpack.config.js' + - '**' + # Documentation, repository metadata, and local environment configuration. + - '!**.md' + - '!.devcontainer/**' + - '!.editorconfig' + - '!.env.example' + - '!.git-blame-ignore-revs' + - '!.gitignore' + - '!.mailmap' + - '!docker-compose.yml' + - '!typings/**' + - '!wp-cli.yml' + # Configuration for unrelated checks. + - '!.eslintrc-jsdoc.js' + - '!.prettierrc.js' + - '!.version-support-*.json' + - '!eslint.config.js' + - '!jsdoc.conf.json' + - '!phpcompat.xml.dist' + - '!phpcs.xml.dist' + - '!phpstan.neon.dist' + - '!phpunit.xml.dist' + - '!tsconfig.json' + # Tests, unrelated tools, and other workflows do not affect the build. + - '!tests/**' + - '!tools/**' + - '!.github/**' + # Re-include the tools and workflows used by the build. - 'tools/gutenberg/**' - 'tools/vendors/**' - 'tools/webpack/**' - # These files configure Composer. Changes could affect the outcome. - - 'composer.*' - # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/test-build-processes.yml' - '.github/workflows/reusable-test-core-build-process.yml' workflow_dispatch: @@ -118,7 +133,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index 94f57628254c3..c29be2fb4043e 100644 --- a/.github/workflows/test-coverage.yml +++ b/.github/workflows/test-coverage.yml @@ -6,6 +6,7 @@ on: branches: - trunk paths: + - '.github/actions/setup-npm/**' - '.github/workflows/test-coverage.yml' - '.github/workflows/reusable-phpunit-tests-v3.yml' - '.github/workflows/reusable-prepare-gutenberg.yml' @@ -19,6 +20,7 @@ on: branches: - trunk paths: + - '.github/actions/setup-npm/**' - '.github/workflows/test-coverage.yml' - '.github/workflows/reusable-phpunit-tests-v3.yml' - '.github/workflows/reusable-prepare-gutenberg.yml' @@ -97,7 +99,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/test-old-branches.yml b/.github/workflows/test-old-branches.yml index 7094550485c4f..37425c8b3983c 100644 --- a/.github/workflows/test-old-branches.yml +++ b/.github/workflows/test-old-branches.yml @@ -7,7 +7,7 @@ on: - trunk paths: - '.github/workflows/test-old-branches.yml' - - '.github/workflows/reusable-phpunit-tests-v[1-3].yml' + - '.github/workflows/reusable-*.yml' # Run twice a month on the 1st and 15th at 00:00 UTC. schedule: - cron: '0 0 1 * *' @@ -158,4 +158,3 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} diff --git a/.github/workflows/upgrade-develop-testing.yml b/.github/workflows/upgrade-develop-testing.yml index a01e5239fac17..eb9046a273ed5 100644 --- a/.github/workflows/upgrade-develop-testing.yml +++ b/.github/workflows/upgrade-develop-testing.yml @@ -12,7 +12,10 @@ on: paths: # Any change to a source PHP file should run checks. - 'src/**.php' + - '*.php' # PHP files in the root, like wp-config-sample.php. # Confirm any changes to relevant workflow files. + - '.github/actions/smoke-check/**' + - '.github/actions/setup-npm/**' - '.github/workflows/upgrade-develop-testing.yml' - '.github/workflows/reusable-upgrade-testing.yml' pull_request: @@ -23,9 +26,13 @@ on: paths: # Any change to a source PHP file should run checks. - 'src/**.php' + - '*.php' # PHP files in the root, like wp-config-sample.php. # Confirm any changes to relevant workflow files. + - '.github/actions/setup-npm/**' - '.github/workflows/upgrade-develop-testing.yml' - '.github/workflows/reusable-upgrade-testing.yml' + schedule: + - cron: '0 0 * * 1' workflow_dispatch: # Cancels all previous workflow runs for pull requests that have not completed. @@ -93,13 +100,14 @@ jobs: multisite: ${{ matrix.multisite }} # Run a limited set of upgrade tests for the current branch on forks. + # + # Pull requests meeting the filtering criteria run, but `push` and `schedule` configured runs are explicitly disabled + # for forks. upgrade-tests-develop-forks: name: Upgrade from ${{ matrix.wp }} uses: ./.github/workflows/reusable-upgrade-testing.yml - # This job also runs for the push event, which has no draft state to check. if: | - github.repository != 'WordPress/wordpress-develop' && ( - github.event_name != 'pull_request' || + github.repository != 'WordPress/wordpress-develop' && github.event_name == 'pull_request' && ( ! github.event.repository.private || ! github.event.pull_request.draft || contains( github.event.pull_request.labels.*.name, 'Draft Workflow Runs' ) @@ -140,7 +148,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index ba82f96a7b779..d25bfb7271615 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -9,6 +9,7 @@ on: - trunk # Always test the workflow after it's updated. paths: + - '.github/actions/smoke-check/**' - '.github/workflows/upgrade-testing.yml' - '.github/workflows/reusable-upgrade-testing.yml' pull_request: @@ -57,11 +58,102 @@ permissions: {} # - 5.6.x Docker containers are available and work, but 5.6 only accounts for ~2.3% of installs as of 12/6/2024.defaults: # - 5.7.x accounts for ~20% of installs, so this is used below instead. jobs: + # Builds the list of starting versions for each matrix below. Drops every version that is not older than the target + # version, because upgrading from one of those is a downgrade. A job whose list ends up empty is skipped. + # + # A major target (6.4 or 6.4.0) drops its own branch, because no upgrade would occur. + # + # A minor target (6.4.4) keeps its own branch, because 6.4 to 6.4.4 is a real upgrade. The called workflow runs + # `wp core update --minor` before the final upgrade step, so the minor update performs that upgrade and the final + # upgrade step is a no-op. When the target is not the newest release on its branch, the minor update overshoots + # the target and the target is never installed. + # + # "latest" and "nightly" drop nothing. Any other unrecognized target is treated the same way, with a warning. + build-test-matrix: + name: Build Test Matrix + runs-on: ubuntu-24.04 + permissions: {} + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + timeout-minutes: 5 + outputs: + recent-releases: ${{ steps.versions.outputs.recent-releases }} + wp-6x: ${{ steps.versions.outputs.wp-6x }} + wp-5x-php-7x: ${{ steps.versions.outputs.wp-5x-php-7x }} + wp-5x-php-8x: ${{ steps.versions.outputs.wp-5x-php-8x }} + oldest-wp: ${{ steps.versions.outputs.oldest-wp }} + + steps: + - name: Drop the versions that are not older than the version being tested + id: versions + env: + NEW_VERSION: ${{ inputs.new-version && inputs.new-version || 'latest' }} + # The versions each job below starts from. See the comment on the job for why those versions are tested. + RECENT_RELEASES: '7.0 7.1' # upgrade-tests-recent-releases + WP_6X: '6.0 6.3 6.4 6.5' # upgrade-tests-wp-6x-mysql + WP_5X_PHP_7X: '5.0 5.1 5.3 5.4 5.5 5.6 5.9' # upgrade-tests-wp-5x-php-7x-mysql + WP_5X_PHP_8X: '5.3 5.4 5.5 5.6 5.9' # upgrade-tests-wp-5x-php-8x-mysql + OLDEST_WP: '4.7' # upgrade-tests-oldest-wp-mysql + run: | + # Branches are compared as a single number so that 7.0 sorts above 6.9. The spacing leaves room for a + # pre-release to sort between its own branch and the one before it. The base is forced to 10 so that a + # version number with a leading zero is not read as an invalid octal value. + if [[ "$NEW_VERSION" =~ ^v?([0-9]+)\.([0-9]+)(\.([0-9]+))?$ ]]; then + target=$(( 10#${BASH_REMATCH[1]} * 10000 + 10#${BASH_REMATCH[2]} * 100 )) + + # A version with no patch number, or a patch number of 0, is a major release: drop its own branch too. + if [[ -z "${BASH_REMATCH[4]}" || "${BASH_REMATCH[4]}" == "0" ]]; then + target=$(( target - 1 )) + fi + else + # Sorts above every version in the lists above, so nothing is dropped. + target=999999 + + if [[ "$NEW_VERSION" != 'latest' && "$NEW_VERSION" != 'nightly' ]]; then + echo "::warning::\"${NEW_VERSION}\" was not read as a version number, so every version will be tested." + fi + fi + + # Writes the versions of $2 that are older than the target to the $1 output, as a JSON array. + filter() { + local kept='' wp branch + local -a versions + + # Guards against a list being renamed in the environment above without updating the call below, which + # would otherwise skip the whole job in silence. + [[ -n "$2" ]] || { echo "::error::No versions are listed for the ${1} matrix."; exit 1; } + + read -ra versions <<< "$2" + + for wp in "${versions[@]}"; do + [[ "$wp" =~ ^([0-9]+)\.([0-9]+) ]] || continue + branch=$(( 10#${BASH_REMATCH[1]} * 10000 + 10#${BASH_REMATCH[2]} * 100 )) + + # A pre-release sorts just below its own branch, so 7.1-RC2 is tested against a target of 7.1 but + # not against 7.0.1. + if [[ "$wp" == *-* ]]; then + branch=$(( branch - 1 )) + fi + + if (( branch <= target )); then + kept+="\"${wp}\"," + fi + done + + echo "$1=[${kept%,}]" >> "$GITHUB_OUTPUT" + } + + filter recent-releases "$RECENT_RELEASES" + filter wp-6x "$WP_6X" + filter wp-5x-php-7x "$WP_5X_PHP_7X" + filter wp-5x-php-8x "$WP_5X_PHP_8X" + filter oldest-wp "$OLDEST_WP" + # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. upgrade-tests-recent-releases: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-test-matrix.outputs.recent-releases != '[]' }} + needs: [ build-test-matrix ] permissions: contents: read strategy: @@ -71,7 +163,7 @@ jobs: php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.0', '8.4', '9.7' ] - wp: [ '7.0', '7.1' ] + wp: ${{ fromJSON( needs.build-test-matrix.outputs.recent-releases ) }} multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -86,7 +178,8 @@ jobs: upgrade-tests-wp-6x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-test-matrix.outputs.wp-6x != '[]' }} + needs: [ build-test-matrix ] permissions: contents: read strategy: @@ -96,7 +189,7 @@ jobs: php: [ '7.4', '8.0', '8.4' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.4' ] - wp: [ '6.0', '6.3', '6.4', '6.5' ] + wp: ${{ fromJSON( needs.build-test-matrix.outputs.wp-6x ) }} multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -111,7 +204,8 @@ jobs: upgrade-tests-wp-5x-php-7x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-test-matrix.outputs.wp-5x-php-7x != '[]' }} + needs: [ build-test-matrix ] permissions: contents: read strategy: @@ -121,7 +215,7 @@ jobs: php: [ '7.4' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.4' ] - wp: [ '5.0', '5.1', '5.3', '5.4', '5.5', '5.6', '5.9' ] + wp: ${{ fromJSON( needs.build-test-matrix.outputs.wp-5x-php-7x ) }} multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -140,7 +234,8 @@ jobs: upgrade-tests-wp-5x-php-8x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-test-matrix.outputs.wp-5x-php-8x != '[]' }} + needs: [ build-test-matrix ] permissions: contents: read strategy: @@ -150,7 +245,7 @@ jobs: php: [ '8.0', '8.4' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.4' ] - wp: [ '5.3', '5.4', '5.5', '5.6', '5.9' ] + wp: ${{ fromJSON( needs.build-test-matrix.outputs.wp-5x-php-8x ) }} multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -170,7 +265,8 @@ jobs: upgrade-tests-oldest-wp-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-test-matrix.outputs.oldest-wp != '[]' }} + needs: [ build-test-matrix ] permissions: contents: read strategy: @@ -180,7 +276,7 @@ jobs: php: [ '7.4' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.0', '8.4', '9.7' ] - wp: [ '4.7' ] + wp: ${{ fromJSON( needs.build-test-matrix.outputs.oldest-wp ) }} multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -197,7 +293,7 @@ jobs: permissions: actions: read contents: read - needs: [ upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql ] + needs: [ build-test-matrix, upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql ] 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' }} @@ -206,7 +302,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.github/workflows/workflow-lint.yml b/.github/workflows/workflow-lint.yml index 1ef050f1b9b92..315cb833c2b18 100644 --- a/.github/workflows/workflow-lint.yml +++ b/.github/workflows/workflow-lint.yml @@ -8,6 +8,7 @@ on: - '[7-9].[0-9]' paths: # Only run when changes are made to workflow files. + - '.github/actions/**' - '.github/workflows/**' pull_request: branches: @@ -15,6 +16,7 @@ on: - '[0-9].[0-9]' paths: # Only run when changes are made to workflow files. + - '.github/actions/**' - '.github/workflows/**' workflow_dispatch: @@ -61,7 +63,6 @@ jobs: SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} - SLACK_GHA_TIMEOUT_WEBHOOK: ${{ secrets.SLACK_GHA_TIMEOUT_WEBHOOK }} failed-workflow: name: Failed workflow tasks diff --git a/.gitignore b/.gitignore index 15876fa47fee8..572b8e679f288 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ wp-tests-config.php /tests/phpunit/data/.trac-ticket-cache* /tests/qunit/compiled.html /tests/performance/**/*.test.results.json +/tests/performance/html-api/corpus/real/ /src/.wp-tests-version /node_modules /npm-debug.log diff --git a/.nvmrc b/.nvmrc index 209e3ef4b6247..82d5d714347ef 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 +24.18 diff --git a/Gruntfile.js b/Gruntfile.js index ab40643d05a80..b720379a23101 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,4 @@ /* jshint node:true */ -/* eslint-env es6 */ /* globals Set */ var webpackConfig = require( './webpack.config' ); var installChanged = require( 'install-changed' ); @@ -138,7 +137,6 @@ module.exports = function(grunt) { 'concat', 'copy', 'cssmin', - 'imagemin', 'jshint', 'uglify', 'watch' @@ -155,7 +153,11 @@ module.exports = function(grunt) { ] }; - // Load grunt-* tasks. + /** + * Loads the Grunt tasks for the given dependency. + * + * @param {string} dependency The name of the Grunt task to load. + */ function loadGruntTasks( dependency ) { var contrib = key === 'contrib' ? 'contrib-' : ''; grunt.loadNpmTasks( 'grunt-' + contrib + dependency ); @@ -368,6 +370,8 @@ module.exports = function(grunt) { [ WORKING_DIR + 'wp-includes/js/imagesloaded.min.js' ]: [ './node_modules/imagesloaded/imagesloaded.pkgd.min.js' ], [ WORKING_DIR + 'wp-includes/js/jquery/jquery.js' ]: [ './node_modules/jquery/dist/jquery.js' ], [ WORKING_DIR + 'wp-includes/js/jquery/jquery.min.js' ]: [ './node_modules/jquery/dist/jquery.min.js' ], + [ WORKING_DIR + 'wp-includes/js/jquery/jquery-migrate.js' ]: [ './node_modules/jquery-migrate/dist/jquery-migrate.js' ], + [ WORKING_DIR + 'wp-includes/js/jquery/jquery-migrate.min.js' ]: [ './node_modules/jquery-migrate/dist/jquery-migrate.min.js' ], [ WORKING_DIR + 'wp-includes/js/jquery/jquery.form.js' ]: [ './node_modules/jquery-form/src/jquery.form.js' ], [ WORKING_DIR + 'wp-includes/js/jquery/jquery.color.min.js' ]: [ './node_modules/jquery-color/dist/jquery.color.min.js' ], [ WORKING_DIR + 'wp-includes/js/masonry.min.js' ]: [ './node_modules/masonry-layout/dist/masonry.pkgd.min.js' ], @@ -807,8 +811,8 @@ module.exports = function(grunt) { // Strip the 'library/' prefix from filePath values so they // resolve correctly relative to wp-includes/images/icon-library/. .replace( - /'filePath' => 'library\//g, - '\'filePath\' => \'' + /'filePath'(\s+)=> 'library\//g, + '\'filePath\'$1=> \'' ); } }, @@ -926,6 +930,11 @@ module.exports = function(grunt) { { expr: /content/im, action: function( prop, value ) { + // Alternative text, as in `content: "\f141" / '';`, is not part of the icon. + var altText = ( value.match( /\s*\/\s*(?:'[^']*'|"[^"]*")\s*$/ ) || [ '' ] )[ 0 ]; + + value = value.slice( 0, value.length - altText.length ); + if ( value === '"\\f141"' ) { // dashicons-arrow-left value = '"\\f139"'; } else if ( value === '"\\f340"' ) { // dashicons-arrow-left-alt @@ -939,7 +948,7 @@ module.exports = function(grunt) { } else if ( value === '"\\f345"' ) { // dashicons-arrow-right-alt2 value = '"\\f341"'; } - return { prop: prop, value: value }; + return { prop: prop, value: value + altText }; } } ] @@ -1069,28 +1078,70 @@ module.exports = function(grunt) { '**/*.js', '!**/*.min.js' ], - /* - * Limit JSHint's run to a single specified plugin directory: + // Prevent traversal into these directories during glob expansion. + // This is much faster than using negation patterns alone. + ignore: [ + '**/build/**', + '**/dist/**', + '**/gutenberg/**', + '**/node_modules/**', + '**/packages/**', + '**/test/**', + '**/vendor/**' + ], + /** + * Limits JSHint's run to a single specified plugin directory: + * + * Usage example: + * grunt jshint:plugins --dir=foldername + * + * This also automatically skips minified files that may not have + * a filename ending with `.min.js`, specifically when they have + * lines longer than 500 characters. * - * grunt jshint:plugins --dir=foldername + * @param {string} dirpath Directory path. + * @return {boolean} Whether the path is skipped. */ filter: function( dirpath ) { - var index, dir = grunt.option( 'dir' ); + // Bypasses folder targets so fs.readFileSync doesn't throw errors. + if ( ! fs.lstatSync( dirpath ).isFile() ) { + return false; + } - // Don't filter when no target folder is specified. - if ( ! dir ) { - return true; + // If `--dir` is provided. + var dir = grunt.option( 'dir' ); + if ( dir ) { + var normalizedPath = dirpath.replace( /\\/g, '/' ); + var index = normalizedPath.lastIndexOf( '/' + dir ); + + // If a directory was requested but this file isn't in it, exclude it. + if ( -1 === index ) { + return false; + } } - dirpath = dirpath.replace( /\\/g, '/' ); - index = dirpath.lastIndexOf( '/' + dir ); + // Read the file and inspect line lengths to catch minified/bundled code. + var content; + try { + content = fs.readFileSync( dirpath, 'utf-8' ); + } catch ( error ) { + grunt.log.writeln( 'Could not read file: ' + dirpath + ' (Error: ' + error.message + ')' ); + return false; + } - // Match only the folder name passed from cli. - if ( -1 !== index ) { - return true; + var lines = content.split( '\n' ); + + // Cap the maximum number of iterations at 5 lines. + for ( const line of lines.slice( 0, 5 ) ) { + // Exclude files with lines longer than 500 characters. + if ( line.length > 500 ) { + grunt.log.writeln( 'Skipping minified file: ' + dirpath ); + return false; + } } - return false; + // File passed both independent checks: proceed with JSHint. + return true; } } }, @@ -1552,6 +1603,15 @@ module.exports = function(grunt) { ], dest: BUILD_DIR + 'wp-includes/js/' }, + { + expand: true, + cwd: BUILD_DIR + 'wp-includes/js/jquery', + src: [ + 'jquery-migrate.js', + 'jquery-migrate.min.js' + ], + dest: BUILD_DIR + 'wp-includes/js/jquery/' + }, { expand: true, cwd: BUILD_DIR + 'wp-includes/js/dist/', @@ -1656,13 +1716,13 @@ module.exports = function(grunt) { grunt.loadNpmTasks( 'grunt-webpack' ); // RTL task. - grunt.registerTask('rtl', ['rtlcss:core', 'rtlcss:colors']); + grunt.registerTask('rtl', 'Generates right-to-left (RTL) stylesheets for core and the admin color schemes.', ['rtlcss:core', 'rtlcss:colors']); // Color schemes task. - grunt.registerTask('colors', ['sass:colors', 'postcss:colors']); + grunt.registerTask('colors', 'Compiles and processes the admin color scheme stylesheets.', ['sass:colors', 'postcss:colors']); // JSHint task. - grunt.registerTask( 'jshint:corejs', [ + grunt.registerTask( 'jshint:corejs', 'Runs JSHint on the Gruntfile, tests, bundled themes, and core JavaScript files.', [ 'jshint:grunt', 'jshint:tests', 'jshint:themes', @@ -1670,7 +1730,7 @@ module.exports = function(grunt) { 'jshint:media' ] ); - grunt.registerTask( 'restapi-jsclient', [ + grunt.registerTask( 'restapi-jsclient', 'Runs the PHPUnit and QUnit tests for the REST API JavaScript client.', [ 'phpunit:restapi-jsclient', 'qunit:compiled' ] ); @@ -1729,7 +1789,7 @@ module.exports = function(grunt) { grunt.renameTask( 'watch', '_watch' ); - grunt.registerTask( 'watch', function() { + grunt.registerTask( 'watch', 'Watches files for changes and runs the related tasks. Use watch:phpunit or --phpunit to also run PHPUnit tests.', function() { if ( ! this.args.length || this.args.indexOf( 'webpack' ) > -1 ) { grunt.task.run( 'build' ); } @@ -1744,13 +1804,16 @@ module.exports = function(grunt) { grunt.task.run( '_' + this.nameArgs ); } ); - grunt.registerTask( 'precommit:image', [ + grunt.registerMultiTask( 'imagemin', 'Losslessly optimizes PNG, JPEG and GIF images.', require( './tools/imagemin/task.js' )( grunt ) ); + + grunt.registerTask( 'precommit:image', 'Optimizes core images in preparation for a commit.', [ 'imagemin:core' ] ); - grunt.registerTask( 'precommit:js', [ + grunt.registerTask( 'precommit:js', 'Builds, lints, type checks, and tests JavaScript files in preparation for a commit.', [ 'webpack:prod', 'jshint:corejs', + 'lint:jsdoc', 'typecheck:js', 'uglify:imgareaselect', 'uglify:jqueryform', @@ -1760,16 +1823,16 @@ module.exports = function(grunt) { 'qunit:compiled' ] ); - grunt.registerTask( 'precommit:css', [ + grunt.registerTask( 'precommit:css', 'Processes core CSS files with PostCSS in preparation for a commit.', [ 'postcss:core' ] ); - grunt.registerTask( 'precommit:php', [ + grunt.registerTask( 'precommit:php', 'Runs PHPStan and PHPUnit tests in preparation for a commit.', [ 'phpstan', 'phpunit' ] ); - grunt.registerTask( 'precommit:emoji', [ + grunt.registerTask( 'precommit:emoji', 'Updates the emoji regular expressions from the latest Twemoji file list. Requires the GitHub CLI.', [ 'replace:emoji-regex' ] ); @@ -1786,6 +1849,11 @@ module.exports = function(grunt) { path.dirname( __dirname ) + '/.svn' ] ); + /** + * Searches for the first version control directory in the given set. + * + * @param {string[]} set Array of directory paths to check. + */ function find( set ) { var dir; @@ -1798,6 +1866,9 @@ module.exports = function(grunt) { } } + /** + * Runs all tasks. + */ function runAllTasks() { grunt.log.writeln( 'Cannot determine which files are modified as SVN and GIT are not available.' ); grunt.log.writeln( 'Running all tasks and all tests.' ); @@ -1813,6 +1884,11 @@ module.exports = function(grunt) { done(); } + /** + * Determines which precommit tasks to run based on modified files detected by version control. + * + * @param {string} type The version control type: 'git' or 'svn'. + */ function run( type ) { var command = map[ type ].split( ' ' ); @@ -1822,13 +1898,23 @@ module.exports = function(grunt) { }, function( error, result, code ) { var taskList = []; - // Callback for finding modified paths. + /** + * Checks if the given path appears in the version control status output. + * + * @param {string} path The path to check. + * @return {boolean} True if the path is found, false otherwise. + */ function testPath( path ) { var regex = new RegExp( ' ' + path + '$', 'm' ); return regex.test( result.stdout ); } - // Callback for finding modified files by extension. + /** + * Checks if files with the given extension appear in the version control status output. + * + * @param {string} extension The file extension to check for. + * @return {boolean} True if the file with the given extension is found, false otherwise. + */ function testExtension( extension ) { var regex = new RegExp( '\.' + extension + '$', 'm' ); return regex.test( result.stdout ); @@ -1886,14 +1972,14 @@ module.exports = function(grunt) { } } ); - grunt.registerTask( 'copy:js', [ + grunt.registerTask( 'copy:js', 'Copies JavaScript files from npm packages, vendor libraries, wp-admin, and wp-includes.', [ 'copy:npm-packages', 'copy:vendor-js', 'copy:admin-js', 'copy:includes-js' ] ); - grunt.registerTask( 'uglify:all', [ + grunt.registerTask( 'uglify:all', 'Minifies all JavaScript files.', [ 'uglify:core', 'uglify:emoji-loader', 'uglify:jquery-ui', @@ -1904,20 +1990,20 @@ module.exports = function(grunt) { 'uglify:wp-polyfill-fetch' ] ); - grunt.registerTask( 'build:codemirror', [ + grunt.registerTask( 'build:codemirror', 'Builds the CodeMirror script and styles.', [ 'webpack:codemirror', 'cssmin:codemirror', 'usebanner:codemirror', 'copy:codemirror' ] ); - grunt.registerTask( 'build:webpack', [ + grunt.registerTask( 'build:webpack', 'Cleans the webpack assets and runs the production and development webpack builds.', [ 'clean:webpack-assets', 'webpack:prod', 'webpack:dev', ] ); - grunt.registerTask( 'build:js', [ + grunt.registerTask( 'build:js', 'Builds all JavaScript files.', [ 'clean:js', 'build:webpack', 'copy:js', @@ -1927,7 +2013,7 @@ module.exports = function(grunt) { 'concat:emoji' ] ); - grunt.registerTask( 'build:css', [ + grunt.registerTask( 'build:css', 'Builds all CSS files, including the RTL and admin color scheme stylesheets.', [ 'clean:css', 'copy:wp-admin-css-compat-rtl', 'copy:wp-admin-css-compat-min', @@ -2018,30 +2104,30 @@ module.exports = function(grunt) { } ); } ); - grunt.registerTask( 'build:certificates', [ + grunt.registerTask( 'build:certificates', 'Copies the certificate authority bundle into wp-includes.', [ 'copy:certificates' ] ); - grunt.registerTask( 'certificates:upgrade', [ + grunt.registerTask( 'certificates:upgrade', 'Upgrades the certificate authority bundle package and copies the bundle into wp-includes.', [ 'certificates:upgrade-package', 'copy:certificates' ] ); - grunt.registerTask( 'build:files', [ + grunt.registerTask( 'build:files', 'Cleans the build directory and copies the core files into it.', [ 'clean:files', 'copy:files', 'copy:version', ] ); - grunt.registerTask( 'replace:workflow-references-local-to-remote', [ + grunt.registerTask( 'replace:workflow-references-local-to-remote', 'Replaces local reusable workflow references with references to trunk.', [ 'copy:workflow-references-local-to-remote', ]); - grunt.registerTask( 'replace:workflow-references-remote-to-local', [ + grunt.registerTask( 'replace:workflow-references-remote-to-local', 'Replaces reusable workflow references to trunk with local references.', [ 'copy:workflow-references-remote-to-local', ]); - grunt.registerTask( 'post-branching', [ + grunt.registerTask( 'post-branching', 'Removes unneeded workflows and points reusable workflow references to trunk after branching.', [ 'clean:workflows', 'replace:workflow-references-local-to-remote' ]); @@ -2049,7 +2135,7 @@ module.exports = function(grunt) { /** * Build verification tasks. */ - grunt.registerTask( 'verify:build', [ + grunt.registerTask( 'verify:build', 'Runs all build verification tasks.', [ 'verify:old-files', 'verify:source-maps', ] ); @@ -2059,7 +2145,7 @@ module.exports = function(grunt) { * * @ticket 36083 */ - grunt.registerTask( 'verify:old-files', function() { + grunt.registerTask( 'verify:old-files', 'Verifies that no files listed in $_old_files exist in the build directory.', function() { const file = `${ BUILD_DIR }wp-admin/includes/update-core.php`; assert( @@ -2119,7 +2205,7 @@ module.exports = function(grunt) { * @ticket 46218 * @ticket 60348 */ - grunt.registerTask( 'verify:source-maps', function() { + grunt.registerTask( 'verify:source-maps', 'Verifies that built JavaScript files do not contain source map links.', function() { const ignoredFiles = [ 'build/wp-includes/js/dist/components.js', 'build/wp-includes/js/dist/data.js', @@ -2205,7 +2291,7 @@ module.exports = function(grunt) { } ); // Detects and copies stable routes. - grunt.registerTask( 'build:routes', [ + grunt.registerTask( 'build:routes', 'Detects and copies the stable Gutenberg routes.', [ 'routes:setup', 'copy:routes', ] ); @@ -2217,7 +2303,7 @@ module.exports = function(grunt) { * * Because all of these tasks write to src/, the outcome is identical for build and build:dev. */ - grunt.registerTask( 'build:gutenberg', [ + grunt.registerTask( 'build:gutenberg', 'Refreshes the Gutenberg-sourced content in src/.', [ 'clean:gutenberg', 'copy:gutenberg-php', 'build:routes', @@ -2230,7 +2316,7 @@ module.exports = function(grunt) { 'copy:icon-library-manifest', ] ); - grunt.registerTask( 'build', function() { + grunt.registerTask( 'build', 'Builds WordPress. Use --dev to build into src/ for development.', function() { if ( grunt.option( 'dev' ) ) { grunt.task.run( [ 'gutenberg:verify', @@ -2255,7 +2341,7 @@ module.exports = function(grunt) { } } ); - grunt.registerTask( 'prerelease', [ + grunt.registerTask( 'prerelease', 'Runs formatting checks, linting, tests, and image optimization in preparation for a release.', [ 'format:php:error', 'precommit:php', 'precommit:js', @@ -2308,6 +2394,18 @@ module.exports = function(grunt) { } ); } ); + grunt.registerTask( 'lint:jsdoc', 'Runs JSDoc linting on JavaScript files.', function() { + var done = this.async(); + + grunt.util.spawn( { + cmd: 'npm', + args: [ 'run', 'lint:jsdoc' ], + opts: { stdio: 'inherit' } + }, function( error ) { + done( ! error ); + } ); + } ); + grunt.registerTask( 'phpstan', 'Runs PHPStan on the entire codebase.', function() { var done = this.async(); @@ -2384,7 +2482,7 @@ module.exports = function(grunt) { grunt.registerTask('apply', 'patch'); // Default task. - grunt.registerTask('default', ['build']); + grunt.registerTask('default', 'Runs the build task.', ['build']); /* * Automatically updates the `:dynamic` configurations diff --git a/README.md b/README.md index eb88e407cb612..cb64a35538457 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ You will need Node and npm installed on your computer. Node is a JavaScript runt If you are not using a package manager, see the [Node.js download page](https://nodejs.org/en/download/) for installers and binaries. -**Note:** WordPress currently only officially supports Node.js `20.x` and npm `10.x`. +**Note:** WordPress currently only officially supports Node.js `24.x` and npm `11.x`. You will also need a container environment such as [Docker Desktop](https://www.docker.com/products/docker-desktop) installed and running on your computer. The container environment is the virtualization software that powers the local development environment and can be installed just like any other regular application. diff --git a/composer.json b/composer.json index 34a8d980259f1..f61b6e5e72854 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "ext-igbinary": "*", "ext-imagick": "*", "ext-intl": "*", + "ext-libxml": "*", "ext-mbstring": "*", "ext-memcached": "*", "ext-mysqli": "*", @@ -51,12 +52,17 @@ "squizlabs/php_codesniffer": "3.13.5", "wp-coding-standards/wpcs": "~3.4.1", "phpcompatibility/phpcompatibility-wp": "~2.1.3", - "phpstan/phpstan": "2.2.5", - "phpstan/phpstan-phpunit": "2.0.18", + "phpstan/phpstan": "2.3.0", + "phpstan/phpstan-phpunit": "2.1.1", "yoast/phpunit-polyfills": "^1.1.0" }, "config": { "audit": { "ignore": [ "GHSA-hmqg-cxww-wqhq", "PKSA-rdkp-vv9z-mjkg" ] }, + "policy": { + "advisories": { + "ignore-id": [ "GHSA-hmqg-cxww-wqhq", "PKSA-rdkp-vv9z-mjkg" ] + } + }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true }, diff --git a/docker-compose.yml b/docker-compose.yml index 02cd542c245db..61a123f7427c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,13 +15,14 @@ services: environment: LOCAL_DIR: ${LOCAL_DIR-src} LOCAL_NGINX_COMPRESSION: ${LOCAL_NGINX_COMPRESSION:-off} + LOCAL_NGINX_STATIC_EXPIRES: ${LOCAL_NGINX_STATIC_EXPIRES:-off} volumes: - ./tools/local-env/default.template:/etc/nginx/conf.d/default.template - ./:/var/www # Load our config file, substituting environment variables into the config. - command: /bin/sh -c "envsubst '$$LOCAL_DIR $$LOCAL_NGINX_COMPRESSION' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'" + command: /bin/sh -c "envsubst '$$LOCAL_DIR $$LOCAL_NGINX_COMPRESSION $$LOCAL_NGINX_STATIC_EXPIRES' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'" depends_on: php: @@ -52,14 +53,27 @@ services: - ./tools/local-env/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini - ./:/var/www - # Copy or delete the Memcached dropin plugin file as appropriate. - command: /bin/sh -c "if [ $LOCAL_PHP_MEMCACHED = true ]; then cp -n /var/www/tests/phpunit/includes/object-cache.php /var/www/src/wp-content/object-cache.php; else rm -f /var/www/src/wp-content/object-cache.php; fi && exec php-fpm" + # Install the loopback-request shim (see tools/local-env/mu-plugins/fix-docker-loopback.php), then + # copy or delete the Memcached dropin plugin file as appropriate. The shim is only installed when wp-content already + # exists, so that a not-yet-built LOCAL_DIR (e.g. build) is not created here as root, which would block the build. + command: >- + /bin/sh -c " + if [ -d /var/www/${LOCAL_DIR-src}/wp-content ]; then + mkdir -m 777 -p /var/www/${LOCAL_DIR-src}/wp-content/mu-plugins && sed -e '2a\\ * ⚠️ DO NOT EDIT THIS FILE. It is overwritten whenever the environment starts. Edit tools/local-env/mu-plugins/fix-docker-loopback.php instead.' -e '2a\\ *' /var/www/tools/local-env/mu-plugins/fix-docker-loopback.php > /var/www/${LOCAL_DIR-src}/wp-content/mu-plugins/fix-docker-loopback.php; + fi; + if [ $LOCAL_PHP_MEMCACHED = true ]; then + cp -n /var/www/tests/phpunit/includes/object-cache.php /var/www/src/wp-content/object-cache.php; + else + rm -f /var/www/src/wp-content/object-cache.php; + fi && exec php-fpm + " # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly. init: true extra_hosts: - localhost:host-gateway + - host.docker.internal:host-gateway ## # The MySQL container. @@ -80,10 +94,13 @@ services: - ./tools/local-env/mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql - mysql:/var/lib/mysql + # Ping over TCP: the client resolves the literal `localhost` to the Unix socket, which the + # temporary `--skip-networking` server used to initialise a cold volume answers long before + # the real server listens on port 3306. healthcheck: test: [ 'CMD-SHELL', - 'if [ "$LOCAL_DB_TYPE" = "mariadb" ]; then case "$LOCAL_DB_VERSION" in 5.5|10.0|10.1|10.2|10.3) mysqladmin ping -h localhost || exit $$?;; *) mariadb-admin ping -h localhost || exit $$?;; esac; else mysqladmin ping -h localhost || exit $$?; fi' + 'if [ "$LOCAL_DB_TYPE" = "mariadb" ]; then case "$LOCAL_DB_VERSION" in 5.5|10.0|10.1|10.2|10.3) mysqladmin ping -h 127.0.0.1 --protocol=tcp || exit $$?;; *) mariadb-admin ping -h 127.0.0.1 --protocol=tcp || exit $$?;; esac; else mysqladmin ping -h 127.0.0.1 --protocol=tcp || exit $$?; fi' ] timeout: 5s interval: 5s @@ -118,6 +135,7 @@ services: extra_hosts: - localhost:host-gateway + - host.docker.internal:host-gateway depends_on: php: diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000000..a3f2f384d7d7b --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,38 @@ +/** + * ESLint v10 flat config entry point. + * + * This minimal config focuses only on JSDoc linting by importing + * the configuration from .eslintrc-jsdoc.js. + * + * General JavaScript linting is not performed here. + */ + +const jsdocConfig = require( './.eslintrc-jsdoc.js' ); + +module.exports = [ + ...jsdocConfig, + { + ignores: [ + 'build/**', + '**/build/**', + 'node_modules/**', + 'tests/**', + 'vendor/**', + 'tools/**', + 'jsdoc/**', + 'artifacts/**', + 'coverage/**', + '.cache/**', + 'src/wp-includes/blocks/**/*.js', + 'src/wp-includes/blocks/**/*.js.map', + 'src/wp-content/themes/**', + 'src/wp-content/plugins/**', + 'src/wp-content/mu-plugins/**', + 'src/wp-content/upgrade/**', + 'src/wp-content/uploads/**', + 'src/js/_enqueues/vendor/**', + 'src/wp-admin/js/**', + 'src/wp-includes/js/**', + ], + }, +]; diff --git a/package-lock.json b/package-lock.json index f1d7ebd89b2c4..66c8e2ff74616 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "jquery-color": "3.0.0", "jquery-form": "4.3.0", "jquery-hoverintent": "1.10.2", + "jquery-migrate": "3.6.0", "jsonlint": "1.6.3", "lodash": "4.18.1", "masonry-layout": "4.2.2", @@ -40,7 +41,9 @@ "wicg-inert": "3.1.3" }, "devDependencies": { + "@343dev/gifsicle": "1.2.0", "@lodder/grunt-postcss": "^3.1.1", + "@napi-rs/image": "1.14.0", "@playwright/test": "1.61.1", "@pmmmwh/react-refresh-webpack-plugin": "0.6.2", "@types/codemirror": "5.60.17", @@ -54,7 +57,6 @@ "@wordpress/scripts": "33.0.0", "autoprefixer": "10.5.3", "chalk": "5.6.2", - "check-node-version": "4.2.1", "cssnano": "7.1.9", "dotenv": "17.4.2", "dotenv-expand": "13.0.0", @@ -64,7 +66,6 @@ "grunt-contrib-concat": "2.1.0", "grunt-contrib-copy": "~1.0.0", "grunt-contrib-cssmin": "~5.0.0", - "grunt-contrib-imagemin": "~4.0.0", "grunt-contrib-jshint": "3.2.0", "grunt-contrib-uglify": "~5.2.2", "grunt-contrib-watch": "~1.1.0", @@ -95,8 +96,21 @@ "webpack": "5.108.4" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=24.18.0", + "npm": ">=11.16.0" + } + }, + "node_modules/@343dev/gifsicle": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@343dev/gifsicle/-/gifsicle-1.2.0.tgz", + "integrity": "sha512-sJMxT5SCdnAgf3j7GIXTYecRLPG/NYsCdPpjYhoXesVr2NqdH4HZsl6+j5M9Q5HtA/Ee4AOkTQRd98hlYHFW6A==", + "dev": true, + "license": "GPL-2.0-only", + "bin": { + "gifsicle": "cli.js" + }, + "engines": { + "node": ">=18.17" } }, "node_modules/@asamuzakjp/css-color": { @@ -4112,17 +4126,302 @@ "postcss": "^8.0.0" } }, - "node_modules/@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "node_modules/@napi-rs/image": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image/-/image-1.14.0.tgz", + "integrity": "sha512-pmwJPWY6R063luNBEP9msq9lFu+kYVMiQTJRSpyGnzYnnerYpT3U4vCgFhhVR3jypCgCVWi9viDLoEJoZoIA1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/image-android-arm64": "1.14.0", + "@napi-rs/image-darwin-arm64": "1.14.0", + "@napi-rs/image-darwin-x64": "1.14.0", + "@napi-rs/image-freebsd-x64": "1.14.0", + "@napi-rs/image-linux-arm-gnueabihf": "1.14.0", + "@napi-rs/image-linux-arm64-gnu": "1.14.0", + "@napi-rs/image-linux-arm64-musl": "1.14.0", + "@napi-rs/image-linux-x64-gnu": "1.14.0", + "@napi-rs/image-linux-x64-musl": "1.14.0", + "@napi-rs/image-wasm32-wasi": "1.14.0", + "@napi-rs/image-win32-arm64-msvc": "1.14.0", + "@napi-rs/image-win32-ia32-msvc": "1.14.0", + "@napi-rs/image-win32-x64-msvc": "1.14.0" + } + }, + "node_modules/@napi-rs/image-android-arm64": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-android-arm64/-/image-android-arm64-1.14.0.tgz", + "integrity": "sha512-LBWu1fNR7uC6kNQy+axDqXKU7Kj1x3UdD3xGKw/bks6YAUG15m92qwSwINDEB4Jqgl29vCeSNFItJZRm3byfJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-darwin-arm64": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-darwin-arm64/-/image-darwin-arm64-1.14.0.tgz", + "integrity": "sha512-0f7SqjtXHelxbwkqdpUb/5yhVK7ciVoe902hqCeffhAFsJA7HQbEbzfM8W1MDawI6Ghenr5zHYQimWf1W1vaow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-darwin-x64": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-darwin-x64/-/image-darwin-x64-1.14.0.tgz", + "integrity": "sha512-wi6w06N516QzSd/QMre/Ye92mA4b5E2yQfr1+Hhml3tWrIM2Po2QvxBO9ns0AaG8u6y8b545bDzQCGLTfBykyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-freebsd-x64": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-freebsd-x64/-/image-freebsd-x64-1.14.0.tgz", + "integrity": "sha512-Sz1XSGF6/Xmjb33CbWLOb7h6+ekmoJRGsN0bdnzn8W86OHPTSsIbTOMtqp9ZXTLQNJgeXQhprQhhmRFNRqq0Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-linux-arm-gnueabihf": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-linux-arm-gnueabihf/-/image-linux-arm-gnueabihf-1.14.0.tgz", + "integrity": "sha512-ZsJ+0Rl3Ke1DN+W4lQMSzsfrwskjP4CkUsqOT7Y/HpziwirQn9R2fl2QU2Kb2eDSQvwSvGbRCkMLqH+4V4rzHg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-linux-arm64-gnu": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-linux-arm64-gnu/-/image-linux-arm64-gnu-1.14.0.tgz", + "integrity": "sha512-J06fGFXt76fAGEaCb3uyPQgZrwvGbpYZycA4Xz6F5dauVgcLPw75syXmggode5G+a0cSg40fjddXMvSWhPwHGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-linux-arm64-musl": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-linux-arm64-musl/-/image-linux-arm64-musl-1.14.0.tgz", + "integrity": "sha512-AH8WvQb58ix9/RHB+9XNF2rOB8aAnFHzj0hDCCZCplRGHmv9BzOtA+IWdf5l4f7KmEJUohY+MxVWJ1jfpgn+JQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-linux-x64-gnu": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-linux-x64-gnu/-/image-linux-x64-gnu-1.14.0.tgz", + "integrity": "sha512-oU3wnQcDeZf+t8vyKMP4A6okY7JNjRbiiC7j8UsJ2lDf0no3GDQEJCCFDrQ7gCKQZAI7cr0rFbI75l2KlTM0PQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-linux-x64-musl": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-linux-x64-musl/-/image-linux-x64-musl-1.14.0.tgz", + "integrity": "sha512-iuDTfVmFm9W6S4gzLNdSFt+Wr86LtciJJ+u2i0KBixpFYoHzeIkUr6LHBIkYg3eNdi7xHBb9qFBvxxhFQg4tUQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-wasm32-wasi": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-wasm32-wasi/-/image-wasm32-wasi-1.14.0.tgz", + "integrity": "sha512-XRAbAQVWSm4wQzYwnTtOHD+ev6dRHUxLxmFQe5Nbev12dspqkB40zsDJ/yr4VwnV80gIfEfg7BvRLw9FFvLRlg==", + "cpu": [ + "wasm32" + ], "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" }, "engines": { - "node": ">=4" + "node": ">=14.0.0" + } + }, + "node_modules/@napi-rs/image-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/image-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/image-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/image-win32-arm64-msvc": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-win32-arm64-msvc/-/image-win32-arm64-msvc-1.14.0.tgz", + "integrity": "sha512-Wuq0AfN5rjrv2SkJTubIIYW//B5aBloPxND9GxRHKgGkLhyiSxBD6iOCQA1M/n12rvF9BWeadDDO8JLoO3iRHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-win32-ia32-msvc": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-win32-ia32-msvc/-/image-win32-ia32-msvc-1.14.0.tgz", + "integrity": "sha512-Idb+OyISq24YRdO8iU+BC6QaN4pU6HpC+SRrxFOftWJg0xXPzfPfpwpwdviduJK/SjJcHe02nhUq3HKHtUEnWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/image-win32-x64-msvc": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@napi-rs/image-win32-x64-msvc/-/image-win32-x64-msvc-1.14.0.tgz", + "integrity": "sha512-Hq5BY3+FeNehRe1VPhVQ28dGTSWlxnGAHeoF7/GpgeWBfltLT5+DpkV+FPyq6ju49kG1aFofE+IlSGi5sMJ0Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -4819,16 +5118,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -5868,13 +6157,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/q": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", - "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", - "dev": true, - "optional": true - }, "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", @@ -8758,51 +9040,6 @@ "node": ">= 8" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true - }, - "node_modules/archive-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", - "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", - "dev": true, - "optional": true, - "dependencies": { - "file-type": "^4.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/archive-type/node_modules/file-type": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/are-docs-informative": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", @@ -8839,33 +9076,6 @@ "node": ">= 0.4" } }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -8891,16 +9101,6 @@ "node": ">=0.10.0" } }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -8939,37 +9139,6 @@ "node": ">=0.10.0" } }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -9116,15 +9285,6 @@ "node": ">=0.8" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -9178,18 +9338,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/autoprefixer": { "version": "10.5.3", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.3.tgz", @@ -9740,51 +9888,6 @@ "bare-path": "^3.0.0" } }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -9852,546 +9955,171 @@ "node": "*" } }, - "node_modules/bin-build": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-3.0.0.tgz", - "integrity": "sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==", + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true, - "optional": true, - "dependencies": { - "decompress": "^4.0.0", - "download": "^6.2.2", - "execa": "^0.7.0", - "p-map-series": "^1.0.0", - "tempfile": "^2.0.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/bin-build/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true, + "dependencies": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/bin-build/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/bin-check": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-4.1.0.tgz", - "integrity": "sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==", + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "execa": "^0.7.0", - "executable": "^4.1.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/bin-check/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/bin-check/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/bin-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-3.1.0.tgz", - "integrity": "sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==", + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, - "optional": true, - "dependencies": { - "execa": "^1.0.0", - "find-versions": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/bin-version-check": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-4.0.0.tgz", - "integrity": "sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==", + "node_modules/body/node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", + "dev": true + }, + "node_modules/body/node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "bin-version": "^3.0.0", - "semver": "^5.6.0", - "semver-truncate": "^1.1.2" + "bytes": "1", + "string_decoder": "0.10" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/bin-version-check/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/body/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } + "license": "MIT" }, - "node_modules/bin-wrapper": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-4.1.0.tgz", - "integrity": "sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==", + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", "dev": true, - "optional": true, "dependencies": { - "bin-check": "^4.1.0", - "bin-version-check": "^4.0.0", - "download": "^7.1.0", - "import-lazy": "^3.1.0", - "os-filter-obj": "^2.0.0", - "pify": "^4.0.1" - }, - "engines": { - "node": ">=6" + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" } }, - "node_modules/bin-wrapper/node_modules/download": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", - "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", - "dev": true, - "optional": true, - "dependencies": { - "archive-type": "^4.0.0", - "caw": "^2.0.1", - "content-disposition": "^0.5.2", - "decompress": "^4.2.0", - "ext-name": "^5.0.0", - "file-type": "^8.1.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^8.3.1", - "make-dir": "^1.2.0", - "p-event": "^2.1.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true }, - "node_modules/bin-wrapper/node_modules/download/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/file-type": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", - "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/bin-wrapper/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/got": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", - "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "dev": true, - "optional": true, - "dependencies": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/got/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/import-lazy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", - "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/bin-wrapper/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/p-cancelable": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", - "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/p-event": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", - "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", - "dev": true, - "optional": true, - "dependencies": { - "p-timeout": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/bin-wrapper/node_modules/p-timeout": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "optional": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-wrapper/node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "dependencies": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "node_modules/body-parser": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", - "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.15.1", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body/node_modules/bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", - "dev": true - }, - "node_modules/body/node_modules/raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "1", - "string_decoder": "0.10" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/body/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", - "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/browserslist": { @@ -10461,24 +10189,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "optional": true, - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true, - "optional": true - }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -10488,13 +10198,6 @@ "node": "*" } }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true, - "optional": true - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -10520,26 +10223,6 @@ "node": ">= 0.8" } }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cacheable": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", @@ -10554,88 +10237,6 @@ "qified": "^0.10.1" } }, - "node_modules/cacheable-request": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==", - "dev": true, - "optional": true, - "dependencies": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "optional": true, - "dependencies": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cacheable-request/node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cacheable-request/node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "optional": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-request/node_modules/sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/cacheable/node_modules/keyv": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", @@ -10696,12 +10297,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -10730,32 +10325,6 @@ "node": ">=6" } }, - "node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -10818,22 +10387,6 @@ "node": ">= 10" } }, - "node_modules/caw": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", - "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", - "dev": true, - "optional": true, - "dependencies": { - "get-proxy": "^2.0.0", - "isurl": "^1.0.0-alpha5", - "tunnel-agent": "^0.6.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", @@ -11109,34 +10662,6 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -11268,16 +10793,6 @@ "node": ">=0.8" } }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "optional": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -11288,36 +10803,6 @@ "node": ">= 0.12.0" } }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/coa/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/codemirror": { "version": "5.65.20", "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.20.tgz", @@ -11344,19 +10829,6 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -11439,12 +10911,6 @@ "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", "dev": true }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -11507,17 +10973,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "node_modules/config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "optional": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -11556,13 +11011,6 @@ "node": ">=0.8" } }, - "node_modules/console-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", - "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", - "dev": true, - "optional": true - }, "node_modules/constant-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", @@ -11624,15 +11072,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/copy-webpack-plugin": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", @@ -11929,51 +11368,6 @@ "node": ">=8" } }, - "node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/cross-spawn/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "optional": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/cross-spawn/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true, - "license": "ISC", - "optional": true - }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -12010,97 +11404,40 @@ "postcss": "^8.0.9" } }, - "node_modules/css-functions-list": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", - "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dev": true, - "optional": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", - "dev": true, - "optional": true - }, - "node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "dev": true, - "optional": true, - "dependencies": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/css-functions-list": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", "dev": true, - "optional": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "node_modules/css-loader": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", + "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", "dev": true, - "optional": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.19", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, "engines": { - "node": ">= 6" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, "node_modules/cssesc": { @@ -12210,51 +11547,6 @@ "postcss": "^8.5.13" } }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "optional": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true, - "optional": true - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cssstyle": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", @@ -12276,19 +11568,6 @@ "dev": true, "license": "MIT" }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "optional": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -12361,336 +11640,97 @@ "engines": { "node": ">= 0.4" }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "node_modules/debug": { - "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" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "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" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, - "license": "MIT" - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "optional": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar/node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/decompress-tar/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar/node_modules/tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "optional": true, - "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tarbz2/node_modules/file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, - "optional": true, "dependencies": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/decompress-unzip/node_modules/file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "dev": true, - "license": "MIT", - "optional": true, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/decompress-unzip/node_modules/get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" + "ms": "^2.1.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/decompress-unzip/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true, - "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/decompress/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, - "optional": true, "dependencies": { - "pify": "^3.0.0" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/decompress/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decompress/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/dedent": { "version": "1.5.1", @@ -12899,33 +11939,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", @@ -13136,17 +12149,6 @@ } ] }, - "node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "optional": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -13198,75 +12200,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/download": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", - "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", - "dev": true, - "optional": true, - "dependencies": { - "caw": "^2.0.0", - "content-disposition": "^0.5.2", - "decompress": "^4.0.0", - "ext-name": "^5.0.0", - "file-type": "5.2.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^7.0.0", - "make-dir": "^1.0.0", - "p-event": "^1.0.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/download/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/download/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/download/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/download/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -13287,13 +12220,6 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true, - "optional": true - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -14623,152 +13549,9 @@ "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.7.0" - } - }, - "node_modules/exec-buffer": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", - "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", - "dev": true, - "optional": true, - "dependencies": { - "execa": "^0.7.0", - "p-finally": "^1.0.0", - "pify": "^3.0.0", - "rimraf": "^2.5.4", - "tempfile": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/exec-buffer/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/exec-buffer/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/exec-buffer/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "optional": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/executable/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" } }, "node_modules/exit": { @@ -14790,66 +13573,6 @@ "node": ">= 0.8.0" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, "node_modules/expect": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", @@ -14935,77 +13658,12 @@ "dev": true, "license": "MIT" }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, - "optional": true, - "dependencies": { - "mime-db": "^1.28.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, - "optional": true, - "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", @@ -15032,65 +13690,6 @@ "node": ">=0.10.0" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -15259,26 +13858,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fast-xml-parser": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.7.tgz", - "integrity": "sha512-a6Qh1RMCNbSrU1+sAyAAZH3rTe+OaWJbNZIq0S+ifZciUUOQtlVxBJwoTUE2bYhysmG/RYyI5WJFIKdBahJdrQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "optional": true, - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -15368,21 +13947,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -15402,69 +13966,6 @@ "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", "dev": true }, - "node_modules/file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", - "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", - "dev": true, - "optional": true, - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -15639,19 +14140,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", - "dev": true, - "optional": true, - "dependencies": { - "semver-regex": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/findup-sync": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", @@ -16002,18 +14490,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -16041,13 +14517,6 @@ "from2": "^2.0.3" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "optional": true - }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -16215,48 +14684,11 @@ "node": ">= 0.4" } }, - "node_modules/get-proxy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", - "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", - "dev": true, - "optional": true, - "dependencies": { - "npm-conf": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/get-size": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/get-size/-/get-size-2.0.3.tgz", "integrity": "sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==" }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -16302,15 +14734,6 @@ "node": ">= 14" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/getobject": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.0.tgz", @@ -16340,26 +14763,6 @@ "safe-buffer": "^5.1.1" } }, - "node_modules/gifsicle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-4.0.1.tgz", - "integrity": "sha512-A/kiCLfDdV+ERV/UB+2O41mifd+RxH8jlRG8DMxZO84Bma/Fw0htqZ+hY2iaalLRNyUu7tYZQslqUBJxBggxbg==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "execa": "^1.0.0", - "logalot": "^2.0.0" - }, - "bin": { - "gifsicle": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -16394,13 +14797,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", - "dev": true, - "license": "BSD" - }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -16572,43 +14968,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, - "optional": true, - "dependencies": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -16983,72 +15342,6 @@ "node": ">=8" } }, - "node_modules/grunt-contrib-imagemin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-imagemin/-/grunt-contrib-imagemin-4.0.0.tgz", - "integrity": "sha512-2GYQBQFfJLjeTThJ8E7+vLgvgfOh78u0bgieIK85c2Rv9V6ssd2AvBvuF7T26mK261EN/SlNefpW5+zGWzfrVw==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "imagemin": "^6.0.0", - "p-map": "^1.2.0", - "plur": "^3.0.1", - "pretty-bytes": "^5.1.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "imagemin-gifsicle": "^6.0.1", - "imagemin-jpegtran": "^6.0.0", - "imagemin-optipng": "^6.0.0", - "imagemin-svgo": "^7.0.0" - } - }, - "node_modules/grunt-contrib-imagemin/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-imagemin/node_modules/irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/grunt-contrib-imagemin/node_modules/p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-imagemin/node_modules/plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", - "dev": true, - "dependencies": { - "irregular-plurals": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/grunt-contrib-jshint": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-3.2.0.tgz", @@ -17884,16 +16177,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -17906,19 +16189,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "optional": true, - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", @@ -17934,48 +16204,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hashery": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", @@ -18349,13 +16577,6 @@ "dev": true, "license": "MIT" }, - "node_modules/http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true, - "optional": true - }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", @@ -18616,246 +16837,17 @@ "dev": true, "dependencies": { "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/image-ssim": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", - "dev": true - }, - "node_modules/imagemin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-6.1.0.tgz", - "integrity": "sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A==", - "dev": true, - "dependencies": { - "file-type": "^10.7.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^4.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin-gifsicle": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-6.0.1.tgz", - "integrity": "sha512-kuu47c6iKDQ6R9J10xCwL0lgs0+sMz3LRHqRcJ2CRBWdcNmo3T5hUaM8hSZfksptZXJLGKk8heSAvwtSdB1Fng==", - "dev": true, - "optional": true, - "dependencies": { - "exec-buffer": "^3.0.0", - "gifsicle": "^4.0.0", - "is-gif": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin-jpegtran": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz", - "integrity": "sha512-Ih+NgThzqYfEWv9t58EItncaaXIHR0u9RuhKa8CtVBlMBvY0dCIxgQJQCfwImA4AV1PMfmUKlkyIHJjb7V4z1g==", - "dev": true, - "optional": true, - "dependencies": { - "exec-buffer": "^3.0.0", - "is-jpg": "^2.0.0", - "jpegtran-bin": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin-optipng": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-6.0.0.tgz", - "integrity": "sha512-FoD2sMXvmoNm/zKPOWdhKpWdFdF9qiJmKC17MxZJPH42VMAp17/QENI/lIuP7LCUnLVAloO3AUoTSNzfhpyd8A==", - "dev": true, - "optional": true, - "dependencies": { - "exec-buffer": "^3.0.0", - "is-png": "^1.0.0", - "optipng-bin": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin-svgo": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-7.1.0.tgz", - "integrity": "sha512-0JlIZNWP0Luasn1HT82uB9nU9aa+vUj6kpT+MjPW11LbprXC+iC4HDwn1r4Q2/91qj4iy9tRZNsFySMlEpLdpg==", - "dev": true, - "optional": true, - "dependencies": { - "is-svg": "^4.2.1", - "svgo": "^1.3.2" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sindresorhus/imagemin-svgo?sponsor=1" - } - }, - "node_modules/imagemin/node_modules/@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/imagemin/node_modules/dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "dependencies": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/imagemin/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/imagemin/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/imagemin/node_modules/globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/globby/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "node_modules/imagemin/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", - "dev": true, - "license": "MIT", + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, + "node_modules/image-ssim": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", + "dev": true + }, "node_modules/imagesloaded": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/imagesloaded/-/imagesloaded-5.0.0.tgz", @@ -18926,20 +16918,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -19087,20 +17065,6 @@ "tslib": "2" } }, - "node_modules/into-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "optional": true, - "dependencies": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/ip-address": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", @@ -19143,19 +17107,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", - "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -19241,12 +17192,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, "node_modules/is-bun-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", @@ -19285,19 +17230,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", - "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/is-data-view": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", @@ -19331,20 +17263,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -19360,16 +17278,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -19393,19 +17301,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -19443,19 +17338,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-gif": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-3.0.0.tgz", - "integrity": "sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw==", - "dev": true, - "optional": true, - "dependencies": { - "file-type": "^10.4.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -19467,16 +17349,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-jpg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-2.0.0.tgz", - "integrity": "sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -19489,13 +17361,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true, - "optional": true - }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -19509,19 +17374,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", @@ -19547,16 +17399,6 @@ "node": ">=8" } }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "optional": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -19576,16 +17418,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-png": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", - "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -19623,16 +17455,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", @@ -19660,17 +17482,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -19687,22 +17498,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-svg": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.4.0.tgz", - "integrity": "sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug==", - "dev": true, - "optional": true, - "dependencies": { - "fast-xml-parser": "^4.1.3" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-symbol": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", @@ -19765,13 +17560,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true, - "optional": true - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -19985,20 +17773,6 @@ "node": ">=8" } }, - "node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "optional": true, - "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - }, - "engines": { - "node": ">= 4" - } - }, "node_modules/iterator.prototype": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", @@ -22273,25 +20047,6 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, - "node_modules/jpegtran-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-4.0.0.tgz", - "integrity": "sha512-2cRl1ism+wJUoYAYFt6O/rLBfpXNWG2dUWbgcEkTt5WGMnqI46eEro8T4C5zGROxKRqyKpCBSdHPvt5UYCtxaQ==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" - }, - "bin": { - "jpegtran": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jquery": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", @@ -22324,6 +20079,15 @@ "jquery": ">=1.7.0" } }, + "node_modules/jquery-migrate": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-3.6.0.tgz", + "integrity": "sha512-2k3GMQXXEellCOkj8tczgCd/Y0KMm7LErz4rE6CkHIZV1JTUDlgs7XFN+GpwGKXDQtw/HsjtJuE+CS8IfEOnPg==", + "license": "MIT", + "peerDependencies": { + "jquery": ">=3 <4" + } + }, "node_modules/js-library-detector": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", @@ -22591,14 +20355,6 @@ "node": ">=0.8.0" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "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", @@ -22724,29 +20480,6 @@ "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, - "node_modules/keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "optional": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -23137,62 +20870,6 @@ "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", "dev": true }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/loader-runner": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", @@ -23367,43 +21044,19 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/logalot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", - "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", - "dev": true, - "optional": true, - "dependencies": { - "figures": "^1.3.5", - "squeak": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "optional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/lookup-closest-locale": { @@ -23423,20 +21076,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "optional": true, - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -23446,36 +21085,6 @@ "tslib": "^2.0.3" } }, - "node_modules/lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lpad-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", - "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", - "dev": true, - "optional": true, - "dependencies": { - "get-stdin": "^4.0.1", - "indent-string": "^2.1.0", - "longest": "^1.0.0", - "meow": "^3.3.0" - }, - "bin": { - "lpad-align": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -23567,18 +21176,6 @@ "integrity": "sha1-douOecAJvytk/ugG4ip7HEGQyZA=", "dev": true }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -23889,13 +21486,6 @@ "node": ">=8" } }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", - "dev": true, - "optional": true - }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -23931,29 +21521,6 @@ "dev": true, "license": "MIT" }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -23993,39 +21560,6 @@ "node": ">= 0.6" } }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -24069,16 +21603,6 @@ "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -24347,43 +21871,6 @@ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "dev": true }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -24473,37 +21960,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/napi-postinstall": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", @@ -24564,13 +22020,6 @@ "node": ">= 0.10.0" } }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "optional": true - }, "node_modules/nise": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", @@ -24835,31 +22284,6 @@ "npm-normalize-package-bin": "^1.0.1" } }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "optional": true, - "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-conf/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", @@ -25281,30 +22705,6 @@ "node": ">=10" } }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "optional": true, - "dependencies": { - "boolbase": "~1.0.0" - } - }, "node_modules/nwsapi": { "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", @@ -25330,33 +22730,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-filter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", @@ -25385,18 +22758,6 @@ "node": ">= 0.4" } }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.assign": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", @@ -25480,24 +22841,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", - "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", - "dev": true, - "optional": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.groupby": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", @@ -25676,38 +23019,6 @@ "node": ">= 0.8.0" } }, - "node_modules/optipng-bin": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-5.1.0.tgz", - "integrity": "sha512-9baoqZTNNmXQjq/PQTWEXbVV3AMO2sI/GaaqZJZ8SExfAzjijeAP7FEeT+TtyumSw7gr0PZtSUYB/Ke7iHQVKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" - }, - "bin": { - "optipng": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/os-filter-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz", - "integrity": "sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==", - "dev": true, - "optional": true, - "dependencies": { - "arch": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -25760,51 +23071,7 @@ "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-event": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", - "integrity": "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "p-timeout": "^1.1.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/p-limit": { @@ -25854,38 +23121,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", - "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", - "dev": true, - "optional": true, - "dependencies": { - "p-reduce": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", @@ -25899,20 +23134,6 @@ "node": ">=8" } }, - "node_modules/p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -26091,15 +23312,6 @@ "tslib": "^2.0.3" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", @@ -26110,12 +23322,6 @@ "tslib": "^2.0.3" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -26135,17 +23341,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -26272,29 +23467,6 @@ "node": ">=6" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "optional": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -26418,15 +23590,6 @@ "node": ">=12" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -27373,17 +24536,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/prettier": { "name": "wp-prettier", "version": "3.0.3", @@ -27503,13 +24655,6 @@ "dev": true, "license": "MIT" }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true, - "optional": true - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -27568,13 +24713,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true, - "optional": true - }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -27697,17 +24835,6 @@ } ] }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, "node_modules/qified": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", @@ -27931,93 +25058,6 @@ "node": ">=8" } }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -28072,21 +25112,6 @@ "node": ">= 0.10" } }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -28141,19 +25166,6 @@ "@babel/runtime": "^7.8.4" } }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -28209,46 +25221,6 @@ "regjsparser": "bin/parser" } }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "optional": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -28435,13 +25407,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -28451,16 +25416,6 @@ "node": ">=10" } }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "optional": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, "node_modules/restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -28496,15 +25451,6 @@ "node": ">=4" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -28762,15 +25708,6 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -28930,20 +25867,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/seek-bzip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", - "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", - "dev": true, - "optional": true, - "dependencies": { - "commander": "^2.8.1" - }, - "bin": { - "seek-bunzip": "bin/seek-bunzip", - "seek-table": "bin/seek-bzip-table" - } - }, "node_modules/select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", @@ -28972,45 +25895,12 @@ "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/semver-truncate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", - "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", - "dev": true, - "optional": true, - "dependencies": { - "semver": "^5.3.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/semver-truncate/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, + "license": "ISC", "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -29225,46 +26115,6 @@ "node": ">= 0.4" } }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -29272,31 +26122,6 @@ "dev": true, "license": "ISC" }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/shell-quote": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", @@ -29551,120 +26376,6 @@ "tslib": "^2.0.3" } }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -29726,33 +26437,6 @@ "node": ">= 14" } }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", - "dev": true, - "optional": true, - "dependencies": { - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -29792,20 +26476,6 @@ "webpack": "^5.72.1" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -29825,13 +26495,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -29922,104 +26585,12 @@ "node": ">=8.0" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, - "node_modules/squeak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", - "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "^1.0.0", - "console-stream": "^0.1.1", - "lpad-align": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -30045,14 +26616,6 @@ "node": ">=0.10.0" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true, - "optional": true - }, "node_modules/stable-hash-x": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", @@ -30075,47 +26638,21 @@ "node": ">=10" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/stackframe": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", - "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==", - "dev": true - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, + "node_modules/stackframe": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", + "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==", + "dev": true + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -30168,16 +26705,6 @@ "text-decoder": "^1.1.0" } }, - "node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -30390,26 +26917,6 @@ "node": ">=8" } }, - "node_modules/strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "dev": true, - "optional": true, - "dependencies": { - "is-natural-number": "^4.0.1" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -30419,23 +26926,6 @@ "node": ">=6" } }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -30447,26 +26937,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "dev": true, - "optional": true - }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -31063,50 +27533,6 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, - "node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/svgo/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -31284,42 +27710,6 @@ "streamx": "^2.12.5" } }, - "node_modules/temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tempfile/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/terser": { "version": "5.37.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", @@ -31519,16 +27909,6 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", @@ -31644,54 +28024,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true, - "optional": true - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -31742,29 +28074,6 @@ "node": ">=18" } }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -32123,21 +28432,6 @@ "node": ">=4" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -32170,13 +28464,6 @@ "node": ">= 0.8" } }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true, - "optional": true - }, "node_modules/unrs-resolver": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", @@ -32215,57 +28502,6 @@ "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", @@ -32333,13 +28569,6 @@ "node": ">= 0.10" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -32367,39 +28596,6 @@ } } }, - "node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/use-memo-one": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", @@ -32415,22 +28611,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "optional": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -33586,16 +29766,6 @@ "npm": ">=1.0.0" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 9bb1fd5d0af5b..02255a40b245e 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,23 @@ "url": "https://develop.svn.wordpress.org/trunk" }, "gutenberg": { - "sha": "ea285b45692aed6c4f95353671393402f97f0aa7", + "sha": "954fe7f9e04631c41aec4552acd627a7203a2aad", "ghcrRepo": "WordPress/gutenberg/gutenberg-wp-develop-build" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=24.18.0", + "npm": ">=11.16.0" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": ">=24.18.0" + }, + "packageManager": { + "name": "npm", + "version": ">=11.16.0", + "onFail": "error" + } }, "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", @@ -28,7 +39,9 @@ "last 2 Opera versions" ], "devDependencies": { + "@343dev/gifsicle": "1.2.0", "@lodder/grunt-postcss": "^3.1.1", + "@napi-rs/image": "1.14.0", "@playwright/test": "1.61.1", "@pmmmwh/react-refresh-webpack-plugin": "0.6.2", "@types/codemirror": "5.60.17", @@ -42,7 +55,6 @@ "@wordpress/scripts": "33.0.0", "autoprefixer": "10.5.3", "chalk": "5.6.2", - "check-node-version": "4.2.1", "cssnano": "7.1.9", "dotenv": "17.4.2", "dotenv-expand": "13.0.0", @@ -52,7 +64,6 @@ "grunt-contrib-concat": "2.1.0", "grunt-contrib-copy": "~1.0.0", "grunt-contrib-cssmin": "~5.0.0", - "grunt-contrib-imagemin": "~4.0.0", "grunt-contrib-jshint": "3.2.0", "grunt-contrib-uglify": "~5.2.2", "grunt-contrib-watch": "~1.1.0", @@ -99,6 +110,7 @@ "jquery-color": "3.0.0", "jquery-form": "4.3.0", "jquery-hoverintent": "1.10.2", + "jquery-migrate": "3.6.0", "jsonlint": "1.6.3", "lodash": "4.18.1", "masonry-layout": "4.2.2", @@ -117,13 +129,13 @@ "zod": "3.25.1" }, "scripts": { - "build": "grunt build", - "build:dev": "grunt build --dev", - "build:gutenberg": "grunt build:gutenberg", - "dev": "grunt watch --dev", - "test": "grunt test", - "watch": "grunt watch", - "grunt": "grunt", + "build": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt build", + "build:dev": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt build --dev", + "build:gutenberg": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt build:gutenberg", + "dev": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt watch --dev", + "test": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt test", + "watch": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt watch", + "grunt": "node --no-maglev --no-concurrent-sparkplug node_modules/grunt/bin/grunt", "lint:jsdoc": "wp-scripts lint-js", "lint:jsdoc:fix": "wp-scripts lint-js --fix", "typecheck:js": "tsc --build", @@ -146,6 +158,6 @@ "typecheck:php:baselines": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan:baselines --", "gutenberg:copy": "node tools/gutenberg/copy.js", "gutenberg:verify": "node tools/gutenberg/utils.js", - "gutenberg:download": "node tools/gutenberg/download.js && grunt build:gutenberg" + "gutenberg:download": "node tools/gutenberg/download.js && npm run build:gutenberg" } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bb806bc4a4b95..c4fda7711f053 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -24,8 +24,6 @@ includes: # phpstan:baselines start - tests/phpstan/baselines/argument.type.neon - tests/phpstan/baselines/argument.unresolvableType.neon - - tests/phpstan/baselines/arguments.count.neon - - tests/phpstan/baselines/arrayValues.list.neon - tests/phpstan/baselines/assign.propertyType.neon - tests/phpstan/baselines/binaryOp.invalid.neon - tests/phpstan/baselines/booleanAnd.alwaysFalse.neon @@ -35,15 +33,11 @@ includes: - tests/phpstan/baselines/booleanNot.alwaysTrue.neon - tests/phpstan/baselines/booleanOr.alwaysFalse.neon - tests/phpstan/baselines/booleanOr.alwaysTrue.neon - - tests/phpstan/baselines/booleanOr.rightAlwaysTrue.neon - - tests/phpstan/baselines/catch.neverThrown.neon - tests/phpstan/baselines/class.notFound.neon - tests/phpstan/baselines/deadCode.unreachable.neon - tests/phpstan/baselines/empty.offset.neon - tests/phpstan/baselines/empty.property.neon - tests/phpstan/baselines/empty.variable.neon - - tests/phpstan/baselines/encapsedStringPart.nonString.neon - - tests/phpstan/baselines/foreach.nonIterable.neon - tests/phpstan/baselines/function.alreadyNarrowedType.neon - tests/phpstan/baselines/function.impossibleType.neon - tests/phpstan/baselines/function.resultUnused.neon @@ -52,42 +46,29 @@ includes: - tests/phpstan/baselines/identical.alwaysTrue.neon - tests/phpstan/baselines/if.alwaysFalse.neon - tests/phpstan/baselines/if.alwaysTrue.neon - - tests/phpstan/baselines/instanceof.alwaysTrue.neon - tests/phpstan/baselines/isset.offset.neon - tests/phpstan/baselines/isset.property.neon - - tests/phpstan/baselines/isset.variable.neon - tests/phpstan/baselines/method.childParameterType.neon - - tests/phpstan/baselines/method.nonObject.neon - - tests/phpstan/baselines/method.notFound.neon - tests/phpstan/baselines/method.unused.neon - tests/phpstan/baselines/notIdentical.alwaysTrue.neon - - tests/phpstan/baselines/nullCoalesce.offset.neon - tests/phpstan/baselines/nullCoalesce.property.neon - tests/phpstan/baselines/offsetAccess.nonOffsetAccessible.neon - tests/phpstan/baselines/offsetAccess.notFound.neon - tests/phpstan/baselines/offsetAssign.valueType.neon - tests/phpstan/baselines/parameter.defaultValue.neon - tests/phpstan/baselines/parameter.notFound.neon - - tests/phpstan/baselines/parameter.phpDocType.neon - tests/phpstan/baselines/parameterByRef.type.neon - tests/phpstan/baselines/parameterByRef.unusedType.neon - tests/phpstan/baselines/property.defaultValue.neon - tests/phpstan/baselines/property.nonObject.neon - tests/phpstan/baselines/property.notFound.neon - - tests/phpstan/baselines/property.onlyWritten.neon - - tests/phpstan/baselines/property.phpDocType.neon - tests/phpstan/baselines/property.private.neon - tests/phpstan/baselines/property.protected.neon - - tests/phpstan/baselines/return.missing.neon - tests/phpstan/baselines/return.type.neon - tests/phpstan/baselines/return.unusedType.neon - - tests/phpstan/baselines/smallerOrEqual.alwaysTrue.neon - - tests/phpstan/baselines/staticClassAccess.privateMethod.neon - tests/phpstan/baselines/ternary.alwaysTrue.neon - tests/phpstan/baselines/varTag.noVariable.neon - tests/phpstan/baselines/variable.undefined.neon - - tests/phpstan/baselines/while.alwaysFalse.neon - - tests/phpstan/baselines/while.alwaysTrue.neon # phpstan:baselines end parameters: @@ -124,6 +105,22 @@ parameters: path: src/wp-includes/canonical.php count: 1 + # In core, @internal is advisory for extenders: it marks a symbol that plugins should not rely on. Core itself is + # one codebase and its own uses of these symbols are intended. PHPStan scopes @internal by root namespace, and + # since core symbols live in the global namespace, it reports every use outside the declaring class or file. + # + # The identifier depends on where the symbol is used (e.g. new.internalClass, parameter.internalInterface, + # varTag.internalTrait), so the entry matches on the message instead, which always names the symbol right after + # "internal ". The name must not contain a backslash, so uses of @internal symbols from namespaced + # third-party libraries like SimplePie and Requests are still reported. A bundled library in the global + # namespace cannot be told apart from core that way, so it must be excluded by its prefix instead. Currently + # that is only sodium_compat (ParagonIE_), which marks much of its API as @internal. These checks are only + # enabled by bleedingEdge; functions, class constants, instantiations, and static calls are checked from level 0, + # and methods, properties, and type references from level 2. + - + message: '#\binternal (?:static )?(?:class|interface|trait|enum|function|method|constant|property) (?!ParagonIE_)\w++(?!\\)#' + reportUnmatched: false + # Level 2: # ValueError is PHP 8.0+; core throws it conditionally so the docblocks are correct for WP's 7.4+ range, # but bleedingEdge's version-aware check treats the class as non-existent against the PHP 7.4 floor. @@ -131,3 +128,64 @@ parameters: message: '#^PHPDoc tag @throws with type InvalidArgumentException\|ValueError is not subtype of Throwable$#' path: src/wp-includes/compat.php reportUnmatched: false + + # Level 5: + # substr_compare()'s $length has always accepted null, meaning "compare the full length". PHP 7.4 spelled + # that `int $length = null`, where the null default makes the parameter implicitly nullable, and PHP 8.0 + # only made it explicit as `?int $length = null`. The behavior never differed: verified on PHP 7.4 that + # passing null compares the whole string rather than coercing to a length of 0. + # + # PHPStan reads the two spellings from two sources and only one is right. Its PHP 8 stub carries `?int`, + # but the pre-8.0 `resources/functionMap.php` records the type as plain `int`, having dropped the implicit + # nullability when it was transcribed from the old manual. Because `phpVersion.min` is 70400, the legacy + # map wins and null is reported as invalid. + # + # This lives here rather than in a baseline because a baseline entry records work still to be done, and + # there is none: the call is correct on every version WordPress supports, and the fault is in PHPStan's + # data. Passing an explicit length purely to satisfy it would change working code to suit a tooling bug. + # `reportUnmatched: false` so this entry lapses quietly if PHPStan corrects the map. + - + message: '#^Parameter \#4 \$length of function substr_compare expects int, null given\.$#' + path: src/wp-includes/html-api/class-wp-html-tag-processor.php + reportUnmatched: false + + # HTML API: + # These errors are ignored for the sake of making it easier to keep the HTML Processor in sync with the HTML spec. + - + message: '#^Comparison operation "\>" between 999\|1000 and 0 is always true\.$#' + identifier: greater.alwaysTrue + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^Comparison operation "\>\=" between 0 and 8 is always false\.$#' + identifier: greaterOrEqual.alwaysFalse + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^Left side of && is always true\.$#' + identifier: booleanAnd.leftAlwaysTrue + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 15 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^If condition is always true\.$#' + identifier: if.alwaysTrue + count: 2 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^Dead catch \- Exception is never thrown in the try block\.$#' + identifier: catch.neverThrown + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + # The early return at the start of step() narrows $last_error to null, and PHPStan does not see that + # bookmark_token() sets it to ERROR_EXCEEDED_MAX_BOOKMARKS before throwing. So it reports that the + # check in the catch block can never match, when in fact it always does. + message: '#^Strict comparison using \=\=\= between ''exceeded\-max…'' and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php diff --git a/src/js/_enqueues/admin/application-passwords.js b/src/js/_enqueues/admin/application-passwords.js index c79cdb8b4037f..21fbeb65820af 100644 --- a/src/js/_enqueues/admin/application-passwords.js +++ b/src/js/_enqueues/admin/application-passwords.js @@ -2,6 +2,11 @@ * @output wp-admin/js/application-passwords.js */ +/** + * Handles the Application Passwords functionality in the user profile screen. + * + * @param {JQueryStatic} $ The jQuery object. + */ ( function( $ ) { var $appPassSection = $( '#application-passwords-section' ), $newAppPassForm = $appPassSection.find( '.create-application-password' ), @@ -167,8 +172,8 @@ * * @since 5.6.0 * - * @param {jqXHR} xhr The XHR object from the ajax call. - * @param {string} textStatus The string categorizing the ajax request's status. + * @param {jqXHR} xhr The XHR object from the ajax call. + * @param {string} textStatus The string categorizing the ajax request's status. * @param {string} errorThrown The HTTP status error text. */ function handleErrorResponse( xhr, textStatus, errorThrown ) { @@ -188,7 +193,7 @@ * * @param {string} message The message to display. * @param {string} type The notice type. Either 'success' or 'error'. - * @returns {jQuery} The notice element. + * @return {jQuery} The notice element. */ function addNotice( message, type ) { var $notice = $( '
' ) diff --git a/src/js/_enqueues/admin/comment.js b/src/js/_enqueues/admin/comment.js index b31f174bab5fe..5ed06b0fa41f7 100644 --- a/src/js/_enqueues/admin/comment.js +++ b/src/js/_enqueues/admin/comment.js @@ -9,7 +9,7 @@ * * @since 2.5.0 * - * @param {jQuery} $ The jQuery object. + * @param {JQueryStatic} $ The jQuery object. */ jQuery( function($) { @@ -24,8 +24,6 @@ jQuery( function($) { /** * Adds event that opens the time stamp form if the form is hidden. * - * @listens $edittimestamp:click - * * @param {Event} event The event object. * @return {void} */ @@ -43,8 +41,6 @@ jQuery( function($) { /** * Resets the time stamp values when the cancel button is clicked. * - * @listens .cancel-timestamp:click - * * @param {Event} event The event object. * @return {void} */ @@ -65,8 +61,6 @@ jQuery( function($) { /** * Sets the time stamp values when the ok button is clicked. * - * @listens .save-timestamp:click - * * @param {Event} event The event object. * @return {void} */ @@ -110,8 +104,6 @@ jQuery( function($) { * * @since 7.1.0 * - * @listens $editcommentparent:click - * * @param {Event} event The event object. * @return {void} */ @@ -131,8 +123,6 @@ jQuery( function($) { * * @since 7.1.0 * - * @listens .cancel-comment-parent:click - * * @param {Event} event The event object. * @return {void} */ @@ -150,8 +140,6 @@ jQuery( function($) { * * @since 7.1.0 * - * @listens .save-comment-parent:click - * * @param {Event} event The event object. * @return {void} */ diff --git a/src/js/_enqueues/admin/common.js b/src/js/_enqueues/admin/common.js index c3d49310e8897..757df6b28b513 100644 --- a/src/js/_enqueues/admin/common.js +++ b/src/js/_enqueues/admin/common.js @@ -2,15 +2,14 @@ * @output wp-admin/js/common.js */ -/* global setUserSetting, ajaxurl, alert, confirm, pagenow */ -/* global columns, screenMeta */ +/* global setUserSetting, ajaxurl, alert, confirm, pagenow, columns, screenMeta */ /** - * Adds common WordPress functionality to the window. + * Adds common WordPress functionality to the window. * - * @param {jQuery} $ jQuery object. - * @param {Object} window The window object. - * @param {mixed} undefined Unused. + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} window The window object. + * @param {*} undefined Unused. */ ( function( $, window, undefined ) { var $document = $( document ), @@ -58,10 +57,10 @@ function deprecatedProperty( propName, version, replacement ) { * @since 5.6.0 Added the `version` parameter. * * @param {string} name The name of the object, i.e. commonL10n. - * @param {object} l10nObject The object to deprecate the properties on. + * @param {Object} l10nObject The object to deprecate the properties on. * @param {string} version The version of WordPress that deprecated the property. * - * @return {object} The object with all its properties deprecated. + * @return {Object} The object with all its properties deprecated. */ function deprecateL10nObject( name, l10nObject, version ) { var deprecatedObject = {}; @@ -476,8 +475,6 @@ window.columns = { * Gets the checked column toggles from the screen options. * * @since 3.0.0 - * - * @return {string} String containing the checked column names. */ useCheckboxesForHidden : function() { this.hidden = function(){ @@ -557,7 +554,7 @@ window.showNotice = { * * @since 2.7.0 * - * @param text The text to display in the message. + * @param {string} text The text to display in the message. */ note : function(text) { alert(text); @@ -570,8 +567,8 @@ window.showNotice = { * @since 3.2.0 * * @type {{element: null, toggles: null, page: null, init: screenMeta.init, - * toggleEvent: screenMeta.toggleEvent, open: screenMeta.open, - * close: screenMeta.close}} + * toggleEvent: screenMeta.toggleEvent, open: screenMeta.open, + * close: screenMeta.close}} * * @return {void} */ @@ -695,7 +692,7 @@ $('.contextual-help-tabs').on( 'click', 'a', function(e) { $('.contextual-help-tabs .active').removeClass('active'); link.parent('li').addClass('active'); - panel = $( link.attr('href') ); + panel = $( document ).find( link.attr('href') ); // Panels. $('.help-tab-content').not( panel ).removeClass('active').hide(); @@ -982,8 +979,8 @@ $( function() { /* * Show the sub instead of following the link if: - * - the submenu is not open. - * - the submenu is not shown inline or the menu is not folded. + * - the submenu is not open. + * - the submenu is not shown inline or the menu is not folded. */ if ( ! $menuItem.hasClass( 'opensub' ) && ( ! $menuItem.hasClass( 'wp-menu-open' ) || $menuItem.width() < 40 ) ) { event.preventDefault(); @@ -1078,17 +1075,6 @@ $( function() { }); } - /* - * The `.below-h2` class is here just for backward compatibility with plugins - * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570. - * If '.wp-header-end' is found, append the notices after it otherwise - * after the first h1 or h2 heading found within the main content. - */ - if ( ! $headerEnd.length ) { - $headerEnd = $( '.wrap h1, .wrap h2' ).first(); - } - $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $headerEnd ); - /** * Makes notices dismissible. * @@ -1263,6 +1249,7 @@ $( function() { /** * Triggers the primary submit when then secondary submit is clicked. * + * @param {SubmitEvent} e The event object. * @since 5.7.0 * * @return {void} @@ -1486,7 +1473,7 @@ $( function() { * @param {Event} e The event object. * * @return {void} - */ + */ $('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){ if ( e.target.scrollIntoViewIfNeeded ) e.target.scrollIntoViewIfNeeded(false); @@ -1527,6 +1514,32 @@ $( function() { input.on('change', toggleUploadButton); })(); + /** + * Moves the admin notices into an `aside` element after the first `h1`. + * Prior to 7.2.0, admin notices were only moved after the first `h1`; + * The `aside` wrapper was added in 7.2.0. + * + * @since 7.2.0 + * + * @return {void} + */ + function moveAdminNotices() { + /* + * The `.below-h2` class is here just for backward compatibility with plugins + * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570. + * If '.wp-header-end' is found, append the notices after it otherwise + * after the first h1 or h2 heading found within the main content. + */ + if ( ! $headerEnd.length ) { + $headerEnd = $( '.wrap h1, .wrap h2' ).first(); + } + const $notices = $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ); + if ( $notices.length ) { + const $wpAdminNotices = $( '' ).attr( 'aria-label', __( 'Admin Notices' ) ).insertAfter( $headerEnd ); + $notices.appendTo( $wpAdminNotices ); + } + } + /** * Pins the menu while distraction-free writing is enabled. * @@ -1845,7 +1858,7 @@ $( function() { $document.on( 'postbox-toggled', this.maybeDisableSortables ); // When the screen columns are changed, potentially disable sortables. - $( '#screen-options-wrap input' ).on( 'click', this.maybeDisableSortables ); + $( '#screen-options-wrap input:not(.meta-box-reordering-toggle)' ).on( 'click', this.maybeDisableSortables ); }, /** @@ -1859,6 +1872,7 @@ $( function() { var width = navigator.userAgent.indexOf('AppleWebKit/') > -1 ? $window.width() : window.innerWidth; if ( + $body.hasClass( 'meta-box-reordering-disabled' ) || ( width <= 782 ) || ( 1 >= $sortables.find( '.ui-sortable-handle:visible' ).length && jQuery( '.columns-prefs-1 input' ).prop( 'checked' ) ) ) { @@ -2129,6 +2143,7 @@ $( function() { }); window.wpResponsive.init(); + moveAdminNotices(); setPinMenu(); setMenuState(); makeNoticesDismissible(); @@ -2245,6 +2260,8 @@ $( function( $ ) { * plugin icon images in the update plugins table. * * @since 6.4.0 + * + * @return {Object} Public methods. */ (function() { // Private variables and methods. diff --git a/src/js/_enqueues/admin/custom-background.js b/src/js/_enqueues/admin/custom-background.js index f83db00af03b4..b10a72296d2c6 100644 --- a/src/js/_enqueues/admin/custom-background.js +++ b/src/js/_enqueues/admin/custom-background.js @@ -10,6 +10,8 @@ * @since 3.0.0 * * @requires jQuery + * + * @param {JQueryStatic} $ The jQuery object. */ (function($) { $( function() { @@ -122,7 +124,7 @@ * @since 3.5.0 * * @return {void} - */ + */ frame.on( 'select', function() { // Grab the selected attachment. var attachment = frame.state().get('selection').first(); diff --git a/src/js/_enqueues/admin/custom-header.js b/src/js/_enqueues/admin/custom-header.js index 367756ef8758b..40f9be4f35962 100644 --- a/src/js/_enqueues/admin/custom-header.js +++ b/src/js/_enqueues/admin/custom-header.js @@ -11,6 +11,8 @@ * * @deprecated 4.1.0 The page this is used on is never linked to from the UI. * Setting a custom header is completely handled by the Customizer. + * + * @param {JQueryStatic} $ The jQuery object. */ (function($) { var frame; diff --git a/src/js/_enqueues/admin/edit-comments.js b/src/js/_enqueues/admin/edit-comments.js index 78ee78de759ff..7e89f1c0dd7cb 100644 --- a/src/js/_enqueues/admin/edit-comments.js +++ b/src/js/_enqueues/admin/edit-comments.js @@ -1,14 +1,15 @@ +/* global adminCommentsSettings, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */ +/* global commentReply, theExtraList, theList, setCommentsList */ + /** - * Handles updating and editing comments. - * - * @file This file contains functionality for the admin comments page. - * @since 2.1.0 * @output wp-admin/js/edit-comments.js */ -/* global adminCommentsSettings, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */ -/* global commentReply, theExtraList, theList, setCommentsList */ - +/** + * Handles updating and editing comments. + * + * @param {JQueryStatic} $ The jQuery object. + */ (function($) { var getCount, updateCount, updateCountText, updatePending, updateApproved, updateHtmlTitle, updateDashboardText, updateInModerationText, adminTitle = document.title, @@ -41,7 +42,7 @@ var getCount, updateCount, updateCountText, updatePending, updateApproved, * @access private * * @param {jQuery} el The jQuery element to update. - * @param {number} n Number to be put in the element. + * @param {number} n Number to be put in the element. * * @return {void} */ @@ -67,7 +68,7 @@ var getCount, updateCount, updateCountText, updatePending, updateApproved, * @since 4.4.0 * @access private * - * @param {number} diff The amount to lower or raise the approved count with. + * @param {number} diff The amount to lower or raise the approved count with. * @param {number} commentPostId The ID of the post to be updated. * * @return {void} @@ -121,7 +122,7 @@ var getCount, updateCount, updateCountText, updatePending, updateApproved, * * @param {string} selector The jQuery selector for elements to update a count * for. - * @param {number} diff The amount to lower or raise the count with. + * @param {number} diff The amount to lower or raise the count with. * * @return {void} */ @@ -230,7 +231,7 @@ var getCount, updateCount, updateCountText, updatePending, updateApproved, * @since 3.2.0 * @access private * - * @param {number} diff The amount to lower or raise the pending count with. + * @param {number} diff The amount to lower or raise the pending count with. * @param {number} commentPostId The ID of the post to be updated. * * @return {void} @@ -321,9 +322,9 @@ window.setCommentsList = function() { * @since 2.8.0 * @access private * - * @param {number} total Total number of comments. - * @param {number} time Unix timestamp of response. - * @param {boolean} setConfidentTime Whether to update the last confident time + * @param {number} total Total number of comments. + * @param {number} time Unix timestamp of response. + * @param {boolean} setConfidentTime Whether to update the last confident time * with the given time. * * @return {void} @@ -344,7 +345,7 @@ window.setCommentsList = function() { * @since 2.5.0 * @access private * - * @param {Object} r Ajax response object. + * @param {Object} r Ajax response object. * @param {Object} settings Settings for the wpList object. * * @return {void} @@ -397,8 +398,8 @@ window.setCommentsList = function() { * @since 2.8.0 * @access private * - * @param {Object} settings Settings for the wpList object. - * @param {HTMLElement} list Comments table element. + * @param {Object} settings Settings for the wpList object. + * @param {HTMLElement} list Comments table element. * * @return {Object} The settings object. */ @@ -470,7 +471,7 @@ window.setCommentsList = function() { * @since 2.5.0 * @access private * - * @param {Object} r Ajax response object. + * @param {Object} r Ajax response object. * @param {Object} settings Settings for the wpList object. * * @return {void} @@ -944,8 +945,8 @@ window.commentReply = { * @memberof commentReply * * @param {number} comment_id The comment ID to open an editor for. - * @param {number} post_id The post ID to open an editor for. - * @param {string} action The action to perform. Either 'edit' or 'replyto'. + * @param {number} post_id The post ID to open an editor for. + * @param {string} action The action to perform. Either 'edit' or 'replyto'. * * @return {boolean} Always false. */ diff --git a/src/js/_enqueues/admin/inline-edit-post.js b/src/js/_enqueues/admin/inline-edit-post.js index 6e6e3bef606ed..aaf4bcc5bc3ec 100644 --- a/src/js/_enqueues/admin/inline-edit-post.js +++ b/src/js/_enqueues/admin/inline-edit-post.js @@ -18,8 +18,11 @@ window.wp = window.wp || {}; * * @type {Object} * - * @property {string} type The type of inline editor. - * @property {string} what The prefix before the post ID. + * @property {string} type The type of inline editor. + * @property {string} what The prefix before the post ID. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {wp} wp The WordPress global object. * */ ( function( $, wp ) { @@ -188,6 +191,8 @@ window.wp = window.wp || {}; * @since 2.7.0 * * @memberof inlineEditPost + * + * @return {void|false} Returns false if no checkboxes are checked, otherwise does not return anything. */ setBulk : function(){ var te = '', type = this.type, c = true; diff --git a/src/js/_enqueues/admin/inline-edit-tax.js b/src/js/_enqueues/admin/inline-edit-tax.js index 86e3498cd1eac..f22633651a70c 100644 --- a/src/js/_enqueues/admin/inline-edit-tax.js +++ b/src/js/_enqueues/admin/inline-edit-tax.js @@ -13,9 +13,11 @@ window.wp = window.wp || {}; * * @namespace inlineEditTax * - * @property {string} type The type of inline edit we are currently on. - * @property {string} what The type property with a hash prefixed and a dash - * suffixed. + * @property {string} type The type of inline edit we are currently on. + * @property {string} what The type property with a hash prefixed and a dash suffixed. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wp The WordPress object. */ ( function( $, wp ) { @@ -27,7 +29,7 @@ window.inlineEditTax = { * * @since 2.7.0 * - * @this inlineEditTax + * @this {inlineEditTax} * @memberof inlineEditTax * @return {void} */ @@ -91,7 +93,7 @@ window.inlineEditTax = { * * @since 2.7.0 * - * @this inlineEditTax + * @this {inlineEditTax} * @memberof inlineEditTax * * @param {HTMLElement} el An element within the table row or the table row @@ -109,12 +111,12 @@ window.inlineEditTax = { * * @since 2.7.0 * - * @this inlineEditTax + * @this {inlineEditTax} * @memberof inlineEditTax * * @param {string|HTMLElement} id The ID of the term we want to quick edit or an * element within the table row or the - * table row itself. + * table row itself. * @return {boolean} Always returns false. */ edit : function(id) { @@ -156,12 +158,12 @@ window.inlineEditTax = { * * @since 2.7.0 * - * @this inlineEditTax + * @this {inlineEditTax} * @memberof inlineEditTax * * @param {string|HTMLElement} id The ID of the term we want to quick edit or an * element within the table row or the - * table row itself. + * table row itself. * @return {boolean} Always returns false. */ save : function(id) { @@ -253,7 +255,7 @@ window.inlineEditTax = { * * @since 2.7.0 * - * @this inlineEditTax + * @this {inlineEditTax} * @memberof inlineEditTax * @return {void} */ diff --git a/src/js/_enqueues/admin/media.js b/src/js/_enqueues/admin/media.js index db61220b50e5f..f464fe960b03f 100644 --- a/src/js/_enqueues/admin/media.js +++ b/src/js/_enqueues/admin/media.js @@ -24,7 +24,7 @@ * @memberOf findPosts * * @param {string} af_name The name of the affected element. - * @param {string} af_val The value of the affected post element. + * @param {string} af_val The value of the affected post element. * * @return {boolean} Always returns false. */ diff --git a/src/js/_enqueues/admin/password-toggle.js b/src/js/_enqueues/admin/password-toggle.js index 5bfaa3b122c01..bdd98f8bb7359 100644 --- a/src/js/_enqueues/admin/password-toggle.js +++ b/src/js/_enqueues/admin/password-toggle.js @@ -1,10 +1,12 @@ +/** + * @output wp-admin/js/password-toggle.js + */ + /** * Adds functionality for password visibility buttons to toggle between text and password input types. * * @since 6.3.0 - * @output wp-admin/js/password-toggle.js */ - ( function () { var toggleElements, status, input, icon, label, __ = wp.i18n.__; @@ -15,6 +17,9 @@ toggle.addEventListener( 'click', togglePassword ); } ); + /** + * Toggles the password input field visibility. + */ function togglePassword() { status = this.getAttribute( 'data-toggle' ); input = this.parentElement.children.namedItem( 'pwd' ); diff --git a/src/js/_enqueues/admin/plugin-install.js b/src/js/_enqueues/admin/plugin-install.js index 1e994763e1fda..b79931a7e7791 100644 --- a/src/js/_enqueues/admin/plugin-install.js +++ b/src/js/_enqueues/admin/plugin-install.js @@ -6,6 +6,11 @@ /* global tb_click, tb_remove, tb_position */ +/** + * Initializes the plugin install screens. + * + * @param {JQueryStatic} $ The jQuery object. + */ jQuery( function( $ ) { var tbWindow, @@ -78,6 +83,9 @@ jQuery( function( $ ) { $focusedBefore.trigger( 'focus' ); }); + /** + * Initializes the plugin details modal dialog after the iframe has fully loaded. + */ function iframeLoaded() { var $iframe = tbWindow.find( '#TB_iframeContent' ); @@ -109,8 +117,9 @@ jQuery( function( $ ) { }); } - /* - * Get the tabbable elements and detach/attach the keydown event. + /** + * Gets the tabbable elements and detaches/attaches the keydown event. + * * Called after the iframe has fully loaded so we have all the elements we need. * Called again each time a Tab gets clicked. * @todo Consider to implement a WordPress general utility for this and don't use jQuery UI. @@ -133,7 +142,11 @@ jQuery( function( $ ) { }); } - // Constrain tabbing within the plugin modal dialog. + /** + * Constrains tabbing within the plugin modal dialog. + * + * @param {JQuery.Event} event The keydown event. + */ function constrainTabbing( event ) { if ( 9 !== event.which ) { return; @@ -148,11 +161,13 @@ jQuery( function( $ ) { } } - /* - * Open the Plugin details modal. The event is delegated to get also the links - * in the plugins search tab, after the Ajax search rebuilds the HTML. It's - * delegated on the closest ancestor and not on the body to avoid conflicts - * with other handlers, see Trac ticket #43082. + /** + * Opens the Plugin details modal. + * + * The event is delegated to get also the links in the plugins search tab, + * after the Ajax search rebuilds the HTML. It's delegated on the closest + * ancestor and not on the body to avoid conflicts with other handlers, see + * Trac ticket #43082. */ $( '.wrap' ).on( 'click', '.thickbox.open-plugin-details-modal', function( e ) { // The `data-title` attribute is used only in the Plugin screens. diff --git a/src/js/_enqueues/admin/post.js b/src/js/_enqueues/admin/post.js index 445e79d8a6f05..462523636c9ab 100644 --- a/src/js/_enqueues/admin/post.js +++ b/src/js/_enqueues/admin/post.js @@ -14,6 +14,11 @@ window.makeSlugeditClickable = window.editPermalink = function(){}; // Make sure the wp object exists. window.wp = window.wp || {}; +/** + * Handles the dynamic functionality needed on post and term pages. + * + * @param {JQueryStatic} $ The jQuery object. + */ ( function( $ ) { var titleHasFocus = false, __ = wp.i18n.__; @@ -253,7 +258,9 @@ window.wp = window.wp || {}; }(jQuery)); /** - * Heartbeat refresh nonces. + * Handles the Heartbeat refresh nonces. + * + * @param {JQueryStatic} $ The jQuery object. */ (function($) { var check, timeout; @@ -299,7 +306,9 @@ window.wp = window.wp || {}; }(jQuery)); /** - * All post and postbox controls and functionality. + * Handles all post and postbox controls and functionality. + * + * @param {JQueryStatic} $ The jQuery object. */ jQuery( function($) { var stamp, visibility, $submitButtons, updateVisibility, updateText, @@ -620,11 +629,11 @@ jQuery( function($) { }); /** - * Before adding a new taxonomy, disable submit button. + * Disables the submit button before adding a new taxonomy. * * @param {Object} s Taxonomy object which will be added. * - * @return {Object} + * @return {Object} Taxonomy object with additional data to be sent to the server. */ catAddBefore = function( s ) { if ( !$('#new'+taxonomy).val() ) { @@ -1321,7 +1330,10 @@ jQuery( function($) { } ); /** - * TinyMCE word count display + * Handles the TinyMCE word count display. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {wp.utils.WordCounter} counter The WordCounter object. */ ( function( $, counter ) { $( function() { diff --git a/src/js/_enqueues/admin/postbox.js b/src/js/_enqueues/admin/postbox.js index b6d1b6569dc84..fec46d3f6d909 100644 --- a/src/js/_enqueues/admin/postbox.js +++ b/src/js/_enqueues/admin/postbox.js @@ -104,6 +104,10 @@ postboxWithinSortablesIndex = postboxesWithinSortables.index( postbox ), firstOrLastPositionMessage; + if ( ! postboxes.metaBoxReorderingEnabled ) { + return; + } + if ( 'dashboard_browser_nag' === postboxId ) { return; } @@ -246,10 +250,10 @@ * * @memberof postboxes * - * @param {string} page The page we are currently on. - * @param {Object} [args] - * @param {Function} args.pbshow A callback that is called when a postbox opens. - * @param {Function} args.pbhide A callback that is called when a postbox closes. + * @param {string} page The page we are currently on. + * @param {Object} [args] Optional arguments for the postbox toggles. + * @param {Function} [args.pbshow] A callback that is called when a postbox opens. + * @param {Function} [args.pbhide] A callback that is called when a postbox closes. * @return {void} */ add_postbox_toggles : function (page, args) { @@ -344,6 +348,13 @@ postboxes.save_order( page ); } }); + + $( '.meta-box-reordering-toggle' ).on( 'click.postboxes', function() { + var enabled = $( this ).prop( 'checked' ); + + postboxes.setMetaBoxReordering( enabled ); + postboxes.save_meta_box_reordering_state( enabled ); + } ); }, /** @@ -353,8 +364,8 @@ * * @memberof postboxes * - * @param {string} page The page we are currently on. - * @param {Object} [args={}] The arguments for the postbox initializer. + * @param {string} page The page we are currently on. + * @param {Object} [args={}] The arguments for the postbox initializer. * @param {Function} args.pbshow A callback that is called when a postbox opens. * @param {Function} args.pbhide A callback that is called when a postbox * closes. @@ -419,6 +430,8 @@ } }); + this.setMetaBoxReordering( this.isMetaBoxReorderingEnabled() ); + if ( isMobile ) { $(document.body).on('orientationchange.postboxes', function(){ postboxes._pb_change(); }); this._pb_change(); @@ -437,6 +450,51 @@ }); }, + /** + * Checks whether meta box reordering is enabled. + * + * @since 7.2.0 + * + * @return {boolean} Whether meta box reordering is enabled. + */ + isMetaBoxReorderingEnabled: function() { + var $toggle = $( '#meta-box-reordering' ); + + if ( $toggle.length ) { + return $toggle.prop( 'checked' ); + } + + return ! $( document.body ).hasClass( 'meta-box-reordering-disabled' ); + }, + + /** + * Enables or disables the meta box reordering UI. + * + * @since 7.2.0 + * + * @param {boolean} enabled Whether reordering should be enabled. + * @return {void} + */ + setMetaBoxReordering: function( enabled ) { + var $sortables = $( '.meta-box-sortables' ); + + this.metaBoxReorderingEnabled = enabled; + + $( document.body ).toggleClass( 'meta-box-reordering-disabled', ! this.metaBoxReorderingEnabled ); + + if ( window.wpResponsive && window.wpResponsive.maybeDisableSortables ) { + window.wpResponsive.maybeDisableSortables(); + return; + } + + if ( $sortables.hasClass( 'ui-sortable' ) ) { + $sortables + .sortable( this.metaBoxReorderingEnabled ? 'enable' : 'disable' ) + .find( '.ui-sortable-handle' ) + .toggleClass( 'is-non-sortable', ! this.metaBoxReorderingEnabled ); + } + }, + /** * Saves the state of the postboxes to the server. * @@ -476,6 +534,32 @@ ); }, + /** + * Saves the meta box reordering setting to the server. + * + * @since 7.2.0 + * + * @param {boolean} enabled Whether meta box reordering is enabled. + * @return {void} + */ + save_meta_box_reordering_state: function( enabled ) { + $.post( + ajaxurl, + { + action: 'meta-box-reordering', + enabled: enabled ? 1 : 0, + screenoptionnonce: $( '#screenoptionnonce' ).val() + }, + function() { + wp.a11y.speak( + enabled ? + __( 'Rearranging screen elements enabled.' ) : + __( 'Rearranging screen elements disabled.' ) + ); + } + ); + }, + /** * Saves the order of the postboxes to the server. * diff --git a/src/js/_enqueues/admin/privacy-tools.js b/src/js/_enqueues/admin/privacy-tools.js index 480766ad051d7..1a48c0759329a 100644 --- a/src/js/_enqueues/admin/privacy-tools.js +++ b/src/js/_enqueues/admin/privacy-tools.js @@ -1,27 +1,55 @@ /** - * Interactions used by the User Privacy tools in WordPress. - * * @output wp-admin/js/privacy-tools.js */ -// Privacy request action handling. +/** + * Sets the interactions used by the User Privacy tools in WordPress. + * + * @param {jQueryStatic} $ The jQuery object. + */ jQuery( function( $ ) { var __ = wp.i18n.__, copiedNoticeTimeout; + /** + * Sets the state of the action. + * + * @since 4.9.6 + * + * @param {jQuery} $action The action to set the state for. + * @param {string} state The state to set the action to. + * @return {void} + */ function setActionState( $action, state ) { $action.children().addClass( 'hidden' ); $action.children( '.' + state ).removeClass( 'hidden' ); } + /** + * Clears any results row after the request row. + * + * @since 4.9.6 + * + * @param {jQuery} $requestRow The request row to clear results for. + * @return {void} + */ function clearResultsAfterRow( $requestRow ) { - $requestRow.removeClass( 'has-request-results' ); - if ( $requestRow.next().hasClass( 'request-results' ) ) { $requestRow.next().remove(); } } + /** + * Appends a results row after the request row. + * + * @since 4.9.6 + * + * @param {jQuery} $requestRow The request row to append the results after. + * @param {string} classes The classes to add to the results row. + * @param {string} summaryMessage The summary message to display in the results row. + * @param {string[]} additionalMessages Additional messages to display in the results row. + * @return {void} + */ function appendResultsAfterRow( $requestRow, classes, summaryMessage, additionalMessages ) { var itemList = '', resultRowClasses = 'request-results'; @@ -35,8 +63,6 @@ jQuery( function( $ ) { itemList = ''; } - $requestRow.addClass( 'has-request-results' ); - if ( $requestRow.hasClass( 'status-request-confirmed' ) ) { resultRowClasses = resultRowClasses + ' status-request-confirmed'; } @@ -51,7 +77,7 @@ jQuery( function( $ ) { '

' + summaryMessage + '

' + itemList + '' + - '' + + '' + ''; }); } @@ -76,6 +102,15 @@ jQuery( function( $ ) { clearResultsAfterRow( $requestRow ); setExportProgress( 0 ); + /** + * Handles a successful export. + * + * @since 4.9.6 + * + * @param {string} [zipUrl] Optional. The URL of the generated ZIP file. Undefined when + * the export link is sent by email instead. + * @return {void} + */ function onExportDoneSuccess( zipUrl ) { var summaryMessage = __( 'This user’s personal data export link was sent.' ); @@ -96,6 +131,15 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Handles an export failure. + * + * @since 4.9.6 + * + * @param {string} [errorMessage] Optional. The error message to display. The results + * row is only added when a message is passed. + * @return {void} + */ function onExportFailure( errorMessage ) { var summaryMessage = __( 'An error occurred while attempting to export personal data.' ); @@ -108,6 +152,15 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Updates the export progress indicator based on the number of completed exporters. + * + * @since 5.4.0 + * + * @param {number} exporterIndex The number of exporters that have finished. Should be + * between 0 and exportersCount. + * @return {void} + */ function setExportProgress( exporterIndex ) { var progress = ( exportersCount > 0 ? exporterIndex / exportersCount : 0 ), progressString = Math.round( progress * 100 ).toString() + '%'; @@ -115,6 +168,16 @@ jQuery( function( $ ) { $progress.html( progressString ); } + /** + * Performs the next export request. + * + * @since 4.9.6 + * + * @param {number} exporterIndex The 1-based index of the exporter to process, between 1 + * and exportersCount. + * @param {number} pageIndex The 1-based index of the page to process for the current exporter. + * @return {void} + */ function doNextExport( exporterIndex, pageIndex ) { $.ajax( { @@ -181,6 +244,13 @@ jQuery( function( $ ) { clearResultsAfterRow( $requestRow ); setErasureProgress( 0 ); + /** + * Handles a successful erasure. + * + * @since 4.9.6 + * + * @return {void} + */ function onErasureDoneSuccess() { var summaryMessage = __( 'No personal data was found for this user.' ), classes = 'notice-success'; @@ -207,6 +277,13 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Handles an erasure failure. + * + * @since 4.9.6 + * + * @return {void} + */ function onErasureFailure() { var summaryMessage = __( 'An error occurred while attempting to find and erase personal data.' ); @@ -217,6 +294,15 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Updates the erasure progress indicator based on the number of completed erasers. + * + * @since 5.4.0 + * + * @param {number} eraserIndex The number of erasers that have finished. Should be + * between 0 and erasersCount. + * @return {void} + */ function setErasureProgress( eraserIndex ) { var progress = ( erasersCount > 0 ? eraserIndex / erasersCount : 0 ), progressString = Math.round( progress * 100 ).toString() + '%'; @@ -224,6 +310,16 @@ jQuery( function( $ ) { $progress.html( progressString ); } + /** + * Performs the next erasure request. + * + * @since 4.9.6 + * + * @param {number} eraserIndex The 1-based index of the eraser to process, between 1 + * and erasersCount. + * @param {number} pageIndex The 1-based index of the page to process for the current eraser. + * @return {void} + */ function doNextErasure( eraserIndex, pageIndex ) { $.ajax({ url: window.ajaxurl, diff --git a/src/js/_enqueues/admin/site-health.js b/src/js/_enqueues/admin/site-health.js index 57d5c9cbcf289..0a1b052e56f3b 100644 --- a/src/js/_enqueues/admin/site-health.js +++ b/src/js/_enqueues/admin/site-health.js @@ -1,11 +1,14 @@ /** - * Interactions used by the Site Health modules in WordPress. - * * @output wp-admin/js/site-health.js */ /* global ajaxurl, ClipboardJS, SiteHealth, wp */ +/** + * Handles the interactions used by the Site Health modules in WordPress. + * + * @param {JQueryStatic} $ The jQuery object. + */ jQuery( function( $ ) { var __ = wp.i18n.__, @@ -85,9 +88,9 @@ jQuery( function( $ ) { * * @since 5.6.0 * - * @param {Object} issue + * @param {Object} issue The issue data to validate. * - * @return {boolean} + * @return {boolean} True if the issue data is valid, false otherwise. */ function validateIssueData( issue ) { // Expected minimum format of a valid SiteHealth test response. @@ -137,6 +140,7 @@ jQuery( function( $ ) { * @since 5.2.0 * * @param {Object} issue The issue data. + * @return {void|boolean} True if the issue was appended, false otherwise. */ function appendIssue( issue ) { var template = wp.template( 'health-check-issue' ), @@ -346,6 +350,8 @@ jQuery( function( $ ) { /** * Add the details of a failed asynchronous test to the list of test results. * + * @param {string} url The URL of the failed test. + * @param {string} description The description of the failed test. * @since 5.6.0 */ function addFailedSiteHealthCheckNotice( url, description ) { @@ -390,6 +396,9 @@ jQuery( function( $ ) { } } + /** + * Get the sizes of the directories in the Site Health Info section. + */ function getDirectorySizes() { var timestamp = ( new Date().getTime() ); @@ -431,6 +440,11 @@ jQuery( function( $ ) { } ); } + /** + * Updates the directory sizes in the Site Health Info section. + * + * @param {Object} data The directory sizes data. + */ function updateDirSizes( data ) { var copyButton = $( 'button.button.copy-button' ); var clipboardText = copyButton.attr( 'data-clipboard-text' ); diff --git a/src/js/_enqueues/admin/site-icon.js b/src/js/_enqueues/admin/site-icon.js index a4f94797a5a48..59a098dc08aac 100644 --- a/src/js/_enqueues/admin/site-icon.js +++ b/src/js/_enqueues/admin/site-icon.js @@ -141,7 +141,7 @@ * * @since 6.5.0 * - * @param {array} attributes The attributes for the attachment. + * @param {Object} attributes The attributes for the attachment. */ function switchToUpdate( attributes ) { var i18nAppAlternativeString, i18nBrowserAlternativeString; diff --git a/src/js/_enqueues/admin/tags-box.js b/src/js/_enqueues/admin/tags-box.js index 99d664691c9c8..a3e1e901be22c 100644 --- a/src/js/_enqueues/admin/tags-box.js +++ b/src/js/_enqueues/admin/tags-box.js @@ -219,11 +219,11 @@ * * @memberOf tagBox * - * @param {Object} el The container HTML element. - * @param {Object|boolean} a When this is an HTML element the text of that - * element will be used for the new tag. - * @param {number|boolean} f If this value is not passed then the tag input - * field is focused. + * @param {Object} el The container HTML element. + * @param {Object|boolean} a When this is an HTML element the text of that + * element will be used for the new tag. + * @param {number|boolean} f If this value is not passed then the tag input + * field is focused. * * @return {boolean} Always returns false. */ @@ -287,8 +287,8 @@ * * @since 2.9.0 * - * @param {number|string} r The response message from the Ajax call. - * @param {string} stat The status of the Ajax request. + * @param {number|string} r The response message from the Ajax call. + * @param {string} stat The status of the Ajax request. * * @return {void} */ diff --git a/src/js/_enqueues/admin/tags-suggest.js b/src/js/_enqueues/admin/tags-suggest.js index d439f06ef0de8..e7469cfea2286 100644 --- a/src/js/_enqueues/admin/tags-suggest.js +++ b/src/js/_enqueues/admin/tags-suggest.js @@ -1,7 +1,11 @@ +/** + * @output wp-admin/js/tags-suggest.js + */ + /** * Default settings for jQuery UI Autocomplete for use with non-hierarchical taxonomies. * - * @output wp-admin/js/tags-suggest.js + * @param {JQueryStatic} $ The jQuery object. */ ( function( $ ) { var tempID = 0; @@ -10,16 +14,28 @@ _n = wp.i18n._n, sprintf = wp.i18n.sprintf; + /** + * Splits a string into an array of terms based on the separator. + * + * @param {string} val The string to split. + * @return {string[]} An array of terms. + */ function split( val ) { return val.split( new RegExp( separator + '\\s*' ) ); } + /** + * Gets the last term from a string based on the separator. + * + * @param {string} term The string to get the last term from. + * @return {string} The last term. + */ function getLast( term ) { return split( term ).pop(); } /** - * Add UI Autocomplete to an input or textarea element with presets for use + * Adds UI Autocomplete to an input or textarea element with presets for use * with non-hierarchical taxonomies. * * Example: `$( element ).wpTagsSuggest( options )`. diff --git a/src/js/_enqueues/admin/tags.js b/src/js/_enqueues/admin/tags.js index 88e38b6926309..8d449ca986863 100644 --- a/src/js/_enqueues/admin/tags.js +++ b/src/js/_enqueues/admin/tags.js @@ -9,6 +9,9 @@ /* global ajaxurl, wpAjax, showNotice, validateForm */ + /** + * @param {JQueryStatic} $ The jQuery object. + */ jQuery( function($) { var addingTerm = false; diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 6a6be6745e357..3507b53287b0a 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -1,8 +1,14 @@ +/* global ajaxurl, pwsL10n, userProfileL10n, ClipboardJS */ + /** * @output wp-admin/js/user-profile.js */ -/* global ajaxurl, pwsL10n, userProfileL10n, ClipboardJS */ +/** + * Handles the user profile functionality. + * + * @param {JQueryStatic} $ The jQuery object. + */ (function($) { var updateLock = false, isSubmitting = false, @@ -26,6 +32,17 @@ isSafari = window.safari !== 'undefined' && typeof window.safari === 'object', isFirefox = ua.indexOf( 'firefox' ) !== -1; + /** + * Generates a password and updates the password input field. + * + * If zxcvbn is not yet loaded, it will wait and try again. If the password + * input field is empty or the password wrapper is open, it will set the + * password to the generated value. If the user has already entered a + * password, it will check the strength of that password. It also binds + * the toggle button to show or hide the password and sets the initial state + * of the toggle button based on whether the password should be masked or + * not. Finally, it updates the label for confirming weak passwords. + */ function generatePassword() { if ( typeof zxcvbn !== 'function' ) { setTimeout( generatePassword, 50 ); @@ -61,6 +78,9 @@ $( '#pw-weak-text-label' ).text( __( 'Confirm use of weak password' ) ); } + /** + * Binds the password input field to update the current password and refresh the password strength area when the user types in the field. + */ function bindPass1() { currentPass = $pass1.val(); @@ -83,6 +103,11 @@ bindCapsLockWarning( $pass1 ); } + /** + * Resets the toggle button to show or hide the password. + * + * @param {boolean} show Whether to show the password or not. + */ function resetToggle( show ) { $toggleButton .attr({ @@ -96,6 +121,9 @@ .addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' ); } + /** + * Binds the toggle button to show or hide the password. Also ensures that the password input type is set to password when the form is submitted. + */ function bindToggleButton() { if ( !! $toggleButton ) { // Do not rebind. @@ -158,10 +186,10 @@ /** * Helper function to insert an inline notice of success or failure. * - * @param {jQuery Object} $this The button element: the message will be inserted - * above this button - * @param {bool} success Whether the message is a success message. - * @param {string} message The message to insert. + * @param {jQuery} $this The button element: the message will be inserted + * above this button + * @param {boolean} success Whether the message is a success message. + * @param {string} message The message to insert. */ function addInlineNotice( $this, success, message ) { var resultDiv = $( '
', { @@ -187,6 +215,9 @@ $this.before( resultDiv ); } + /** + * Initializes the password form, including the password strength meter, weak password checkbox, and show/hide password toggle button. + */ function bindPasswordForm() { var $generateButton, $cancelButton; @@ -303,6 +334,9 @@ }); } + /** + * Sets CSS classes to the password strength results based on the password strength. + */ function check_pass_strength() { var pass1 = $('#pass1').val(), strength; @@ -400,7 +434,7 @@ * On macOS Safari and Firefox, the native warning is preferred, * so this function returns false to suppress custom warnings. * - * @param {KeyboardEvent} e The keydown event object. + * @param {KeyboardEvent} event The keydown event object. * * @return {boolean} True if Caps Lock is on, false otherwise. */ @@ -408,6 +442,9 @@ return event.getModifierState( 'CapsLock' ); } + /** + * Toggles the visibility of the weak password checkbox. + */ function showOrHideWeakPasswordCheckbox() { var passStrengthResult = $('#pass-strength-result'); @@ -457,9 +494,9 @@ $( function() { var $colorpicker, $stylesheet, user_id, current_user_id, - select = $( '#display_name' ), - current_name = select.val(), - greeting = $( '#wp-admin-bar-my-account' ).find( '.display-name' ); + select = $( '#display_name' ), + username = $( '#user_login' ).val(), + greeting = $( '#wp-admin-bar-my-account' ).find( '.display-name' ); $( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength ); $('#pass-strength-result').show(); @@ -503,14 +540,14 @@ }); /** - * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile. + * Updates the display name in the admin toolbar whenever the display name dropdown is updated for one's own profile. */ select.on( 'change', function() { if ( user_id !== current_user_id ) { return; } - var display_name = this.value.trim() || current_name; + var display_name = this.value.trim() || username; greeting.text( display_name ); } ); diff --git a/src/js/_enqueues/admin/widgets.js b/src/js/_enqueues/admin/widgets.js index e8fc42507d382..f63f0182853ef 100644 --- a/src/js/_enqueues/admin/widgets.js +++ b/src/js/_enqueues/admin/widgets.js @@ -11,14 +11,14 @@ window.wpWidgets = { /** * A closed Sidebar that gets a Widget dragged over it. * - * @var {element|null} + * @member {jQuery|null} */ hoveredSidebar: null, /** * Lookup of which widgets have had change events triggered. * - * @var {object} + * @member {Object} */ dirtyWidgets: {}, @@ -751,8 +751,8 @@ $( function(){ wpWidgets.init(); } ); * @since 4.9.0 * @deprecated 5.5.0 * - * @type {object} -*/ + * @type {Object} + */ wpWidgets.l10n = wpWidgets.l10n || { save: '', saved: '', diff --git a/src/js/_enqueues/lib/accordion.js b/src/js/_enqueues/lib/accordion.js index 9b52b179b22a6..2670b67d51e5f 100644 --- a/src/js/_enqueues/lib/accordion.js +++ b/src/js/_enqueues/lib/accordion.js @@ -5,6 +5,8 @@ * with one section opening at a time when its title is clicked. * Use the following markup structure for accordion behavior: * + * @example + * ```html *
*
*

@@ -22,6 +24,7 @@ *
*
*
+ * ``` * * Note that any appropriate tags may be used, as long as the above classes are present. * @@ -29,6 +32,11 @@ * @output wp-admin/js/accordion.js */ +/** + * Handles the accordion functionality. + * + * @param {JQueryStatic} $ The jQuery object. + */ ( function( $ ){ $( function () { @@ -43,7 +51,7 @@ /** * Close the current accordion section and open a new one. * - * @param {Object} el Title element of the accordion section to toggle. + * @param {JQuery} el Title element of the accordion section to toggle. * @since 3.6.0 */ function accordionSwitch ( el ) { diff --git a/src/js/_enqueues/lib/admin-bar.js b/src/js/_enqueues/lib/admin-bar.js index 619694db37f5c..4430ccc7ecb77 100644 --- a/src/js/_enqueues/lib/admin-bar.js +++ b/src/js/_enqueues/lib/admin-bar.js @@ -174,7 +174,7 @@ * @since 5.3.1 * * @param {NodeList} topMenuItems All menu items. - * @param {Event} event The click event. + * @param {Event} event The click event. */ function mobileHover( topMenuItems, event ) { var wrapper; @@ -206,7 +206,7 @@ * @since 5.3.1 Use querySelector to clean up the function. * * @param {Event} event The click event. - * @return {boolean} Returns false to prevent default click behavior. + * @return {boolean|void} False to prevent default action. */ function clickShortlink( event ) { var wrapper = event.target.parentNode, @@ -260,7 +260,7 @@ * * @since 5.3.1 * - * @param {HTMLElement} element The HTML element. + * @param {HTMLElement} element The HTML element. * @param {string} className The class name. * @return {boolean} Whether the element has the className. */ @@ -286,7 +286,7 @@ * * @since 5.3.1 * - * @param {HTMLElement} element The HTML element. + * @param {HTMLElement} element The HTML element. * @param {string} className The class name. */ function addClass( element, className ) { @@ -315,7 +315,7 @@ * * @since 5.3.1 * - * @param {HTMLElement} element The HTML element. + * @param {HTMLElement} element The HTML element. * @param {string} className The class name. */ function removeClass( element, className ) { @@ -395,8 +395,10 @@ * * @since 5.3.1 * - * @param {HTMLElement} el Element to get parent. - * @param {string} selector CSS selector to match. + * @param {HTMLElement} el Element to get parent. + * @param {string} selector CSS selector to match. + * + * @return {HTMLElement|null} The closest matching element or null if not found. */ function getClosest( el, selector ) { if ( ! window.Element.prototype.matches ) { diff --git a/src/js/_enqueues/lib/auth-check.js b/src/js/_enqueues/lib/auth-check.js index ff64573639a25..f05d6643bf776 100644 --- a/src/js/_enqueues/lib/auth-check.js +++ b/src/js/_enqueues/lib/auth-check.js @@ -1,9 +1,12 @@ /** - * Interim login dialog. - * * @output wp-includes/js/wp-auth-check.js */ +/** + * Handles the interim login dialog. + * + * @param {JQueryStatic} $ The jQuery object. + */ ( function( $ ) { var wrap, tempHidden, @@ -134,14 +137,13 @@ * Binds to the Heartbeat Tick event. * * - Shows the authentication form popup if user is not logged in. - * - Hides the authentication form popup if it is already visible and user is - * logged in. + * - Hides the authentication form popup if it is already visible and user is logged in. * * @ignore * * @since 3.6.0 * - * @param {Object} e The heartbeat-tick event that has been triggered. + * @param {Object} e The heartbeat-tick event that has been triggered. * @param {Object} data Response data. */ $( function() { diff --git a/src/js/_enqueues/lib/codemirror/htmlhint-kses.js b/src/js/_enqueues/lib/codemirror/htmlhint-kses.js index e08c4c0f5b756..e40a8ca8f3631 100644 --- a/src/js/_enqueues/lib/codemirror/htmlhint-kses.js +++ b/src/js/_enqueues/lib/codemirror/htmlhint-kses.js @@ -8,9 +8,9 @@ HTMLHint.addRule( { * Initialize. * * @this {import('htmlhint/types').Rule} - * @param {import('htmlhint').HTMLParser} parser - Parser. - * @param {import('htmlhint').Reporter} reporter - Reporter. - * @param {Record>} options - KSES options. + * @param {import('htmlhint').HTMLParser} parser Parser. + * @param {import('htmlhint').Reporter} reporter Reporter. + * @param {Record>} options KSES options. * @return {void} */ init: function ( parser, reporter, options ) { diff --git a/src/js/_enqueues/lib/codemirror/javascript-lint.js b/src/js/_enqueues/lib/codemirror/javascript-lint.js index 2c96798a20ae3..15fefe832805c 100644 --- a/src/js/_enqueues/lib/codemirror/javascript-lint.js +++ b/src/js/_enqueues/lib/codemirror/javascript-lint.js @@ -12,10 +12,10 @@ import CodeMirror from 'codemirror'; * @see https://codemirror.net/5/doc/manual.html#addon_lint * * @typedef {Object} CodeMirrorLintError - * @property {string} message - Error message. - * @property {'error'} severity - Severity. - * @property {CodeMirror.Position} from - From position. - * @property {CodeMirror.Position} to - To position. + * @property {string} message Error message. + * @property {'error'} severity Severity. + * @property {CodeMirror.Position} from From position. + * @property {CodeMirror.Position} to To position. */ /** @@ -25,12 +25,12 @@ import CodeMirror from 'codemirror'; * @see https://www.npmjs.com/package/espree#options * * @typedef {Object} SupportedJSHintOptions - * @property {import('espree').Options['ecmaVersion']} [esversion] - "This option is used to specify the ECMAScript version to which the code must adhere." - * @property {boolean} [es5] - "This option enables syntax first defined in the ECMAScript 5.1 specification. This includes allowing reserved keywords as object properties." - * @property {boolean} [es3] - "This option tells JSHint that your code needs to adhere to ECMAScript 3 specification. Use this option if you need your program to be executable in older browsers—such as Internet Explorer 6/7/8/9—and other legacy JavaScript environments." - * @property {boolean} [module] - "This option informs JSHint that the input code describes an ECMAScript 6 module. All module code is interpreted as strict mode code." - * @property {'implied'} [strict] - "This option requires the code to run in ECMAScript 5's strict mode." - * @property {string} [espreeModuleUrl] - The URL to the espree script module. + * @property {import('espree').Options['ecmaVersion']} [esversion] "This option is used to specify the ECMAScript version to which the code must adhere." + * @property {boolean} [es5] "This option enables syntax first defined in the ECMAScript 5.1 specification. This includes allowing reserved keywords as object properties." + * @property {boolean} [es3] "This option tells JSHint that your code needs to adhere to ECMAScript 3 specification. Use this option if you need your program to be executable in older browsers—such as Internet Explorer 6/7/8/9—and other legacy JavaScript environments." + * @property {boolean} [module] "This option informs JSHint that the input code describes an ECMAScript 6 module. All module code is interpreted as strict mode code." + * @property {'implied'} [strict] "This option requires the code to run in ECMAScript 5's strict mode." + * @property {string} [espreeModuleUrl] The URL to the espree script module. */ /** @@ -38,9 +38,9 @@ import CodeMirror from 'codemirror'; * * @since 7.0.0 * - * @param {string} text - Source. - * @param {SupportedJSHintOptions} options - Linting options. - * @returns {Promise} + * @param {string} text Source. + * @param {SupportedJSHintOptions} options Linting options. + * @return {Promise} Linting errors. */ async function validator( text, options ) { if ( ! options.espreeModuleUrl ) { @@ -84,14 +84,8 @@ CodeMirror.registerHelper( 'lint', 'javascript', validator ); * * @since 7.0.0 * - * @param {SupportedJSHintOptions} options - Linting options for JSHint. - * @return {{ - * ecmaVersion?: import('espree').Options['ecmaVersion'], - * sourceType?: 'module'|'script', - * ecmaFeatures?: { - * impliedStrict?: true - * } - * }} + * @param {SupportedJSHintOptions} options Linting options for JSHint. + * @return {import('espree').Options} Options for Espree. */ function getEspreeOptions( options ) { /** @type {{ impliedStrict?: true }} */ @@ -112,7 +106,7 @@ function getEspreeOptions( options ) { * * @since 7.0.0 * - * @param {SupportedJSHintOptions} options - Options. + * @param {SupportedJSHintOptions} options Options. * @return {import('espree').Options['ecmaVersion']} ECMAScript version. */ function getEcmaVersion( options ) { diff --git a/src/js/_enqueues/lib/color-picker.js b/src/js/_enqueues/lib/color-picker.js index 600e0235b3bdb..d8258c53de22c 100644 --- a/src/js/_enqueues/lib/color-picker.js +++ b/src/js/_enqueues/lib/color-picker.js @@ -1,7 +1,15 @@ /** * @output wp-admin/js/color-picker.js + * + * @since 3.5.0 */ +/** + * Handles the color picker functionality. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {undefined} undef The undefined value. + */ ( function( $, undef ) { var ColorPicker, @@ -61,8 +69,8 @@ * * @ignore * - * @param {Event} event The event that's being called. - * @param {HTMLElement} ui The HTMLElement containing the color picker. + * @param {Event} event The event that's being called. + * @param {HTMLElement} ui The HTMLElement containing the color picker. * * @return {void} */ @@ -181,8 +189,8 @@ * * @ignore * - * @param {Event} event The event that's being called. - * @param {HTMLElement} ui The HTMLElement containing the color picker. + * @param {Event} event The event that's being called. + * @param {HTMLElement} ui The HTMLElement containing the color picker. * * @return {void} */ @@ -320,11 +328,11 @@ /** * Returns the iris object if no new color is provided. If a new color is provided, it sets the new color. * - * @param newColor {string|*} The new color to use. Can be undefined. + * @param {string|*} newColor The new color to use. Can be undefined. * * @since 3.5.0 * - * @return {string} The element's color. + * @return {string|void} The element's color. */ color: function( newColor ) { if ( newColor === undef ) { @@ -332,15 +340,16 @@ } this.element.iris( 'option', 'color', newColor ); }, + /** * Returns the iris object if no new default color is provided. * If a new default color is provided, it sets the new default color. * - * @param newDefaultColor {string|*} The new default color to use. Can be undefined. + * @param {string|*} newDefaultColor The new default color to use. Can be undefined. * * @since 3.5.0 * - * @return {boolean|string} The element's color. + * @return {string|void} The element's default color. */ defaultColor: function( newDefaultColor ) { if ( newDefaultColor === undef ) { diff --git a/src/js/_enqueues/lib/comment-reply.js b/src/js/_enqueues/lib/comment-reply.js index fabd579f5afc2..6ebc181551f79 100644 --- a/src/js/_enqueues/lib/comment-reply.js +++ b/src/js/_enqueues/lib/comment-reply.js @@ -127,7 +127,7 @@ window.addComment = ( function( window ) { * * @param {HTMLElement} context The parent DOM element to search for links. * - * @return {HTMLCollection|NodeList|Array} + * @return {HTMLCollection|NodeList} The collection of links. */ function replyLinks( context ) { var selectorClass = config.commentReplyClass; @@ -270,10 +270,10 @@ window.addComment = ( function( window ) { * * @since 5.1.0 * - * @param {HTMLElement} Element DOM element with the attribute. - * @param {string} Attribute the attribute to get. + * @param {HTMLElement} element DOM element with the attribute. + * @param {string} attribute The attribute to get. * - * @return {string} + * @return {string} The value of the attribute. */ function getDataAttribute( element, attribute ) { if ( supportsDataset ) { @@ -291,7 +291,9 @@ window.addComment = ( function( window ) { * * @since 5.1.0 * - * @param {HTMLElement} The requested element. + * @param {string} elementId The requested element. + * + * @return {HTMLElement} The element with the given ID. */ function getElementById( elementId ) { return document.getElementById( elementId ); @@ -309,6 +311,8 @@ window.addComment = ( function( window ) { * @param {string} respondId HTML ID of 'respond' element. * @param {string} postId Database ID of the post. * @param {string} replyTo Form heading content. + * + * @return {void|boolean} Returns false for backward compatibility with third party commenting systems hooking into this function. */ function moveForm( addBelowId, commentId, respondId, postId, replyTo ) { // Get elements based on their IDs. diff --git a/src/js/_enqueues/lib/cookies.js b/src/js/_enqueues/lib/cookies.js index 66d920affaa85..bb398fe8ce487 100644 --- a/src/js/_enqueues/lib/cookies.js +++ b/src/js/_enqueues/lib/cookies.js @@ -40,6 +40,9 @@ window.wpCookies = { /** * Get a multi-values cookie. * Returns a JS object with the name: 'value' pairs. + * + * @param {string} name The name of the cookie. + * @return {Object} The cookie values as a JS object. */ getHash: function( name ) { var cookie = this.get( name ), values; @@ -59,6 +62,13 @@ window.wpCookies = { * Set a multi-values cookie. * * 'values_obj' is the JS object that is stored. It is encoded as URI in wpCookies.set(). + * + * @param {string} name The name of the cookie. + * @param {Object} values_obj The values to store in the cookie. + * @param {number|Date} [expires] Optional. Expiration time in seconds or a Date object. + * @param {string} [path] Optional. The path on the server in which the cookie will be available on. + * @param {string} [domain] Optional. The domain that the cookie is available to. + * @param {boolean} [secure] Optional. Whether the cookie should only be transmitted over a secure HTTPS connection. */ setHash: function( name, values_obj, expires, path, domain, secure ) { var str = ''; @@ -72,6 +82,8 @@ window.wpCookies = { /** * Get a cookie. + * @param {string} name The name of the cookie. + * @return {void|string} The cookie value. */ get: function( name ) { var e, b, @@ -107,7 +119,14 @@ window.wpCookies = { * Set a cookie. * * The 'expires' arg can be either a JS Date() object set to the expiration date (back-compat) - * or the number of seconds until expiration + * or the number of seconds until expiration. + * + * @param {string} name The name of the cookie. + * @param {string} value The value of the cookie. + * @param {number|Date} [expires] Optional. Expiration time in seconds or a Date object. + * @param {string} [path] Optional. The path on the server in which the cookie will be available on. + * @param {string} [domain] Optional. The domain that the cookie is available to. + * @param {boolean} [secure] Optional. Whether the cookie should only be transmitted over a secure HTTPS connection. */ set: function( name, value, expires, path, domain, secure ) { var d = new Date(); @@ -132,6 +151,11 @@ window.wpCookies = { * Remove a cookie. * * This is done by setting it to an empty value and setting the expiration time in the past. + * + * @param {string} name The name of the cookie. + * @param {string} [path] Optional. The path on the server in which the cookie will be available on. + * @param {string} [domain] Optional. The domain that the cookie is available to. + * @param {boolean} [secure] Optional. Whether the cookie should only be transmitted over a secure HTTPS connection. */ remove: function( name, path, domain, secure ) { this.set( name, '', -1000, path, domain, secure ); diff --git a/src/js/_enqueues/lib/embed-template.js b/src/js/_enqueues/lib/embed-template.js index ae58e4e967d7a..85c1369322b98 100644 --- a/src/js/_enqueues/lib/embed-template.js +++ b/src/js/_enqueues/lib/embed-template.js @@ -1,6 +1,13 @@ /** * @output wp-includes/js/wp-embed-template.js */ + +/** + * IIFE setup function. + * + * @param {Window} window The global window object. + * @param {Document} document The global document object. + */ (function ( window, document ) { 'use strict'; @@ -10,6 +17,12 @@ secretTimeout, resizing; + /** + * Sends a message to the parent window. + * + * @param {string} message The message type (e.g., 'height', 'link'). + * @param {*} value The message value. Type depends on message (number for height, string for link). + */ function sendEmbedMessage( message, value ) { window.parent.postMessage( { message: message, @@ -25,6 +38,12 @@ sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); } + /** + * Runs on DomContentLoaded and load event. + * + * Exits early on the load event if the earlier event has + * successfully fired. + */ function onLoad() { if ( loaded ) { return; @@ -41,18 +60,24 @@ if ( share_input ) { for ( i = 0; i < share_input.length; i++ ) { - share_input[ i ].addEventListener( 'click', function ( e ) { - e.target.select(); + share_input[ i ].addEventListener( 'click', function ( event ) { + event.target.select(); } ); } } + /** + * Open share dialog within embed iframe. + */ function openSharingDialog() { share_dialog.className = share_dialog.className.replace( 'hidden', '' ); // Initial focus should go on the currently selected tab in the dialog. document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ).focus(); } + /** + * Close share dialog within embed iframe. + */ function closeSharingDialog() { share_dialog.className += ' hidden'; document.querySelector( '.wp-embed-share-dialog-open' ).focus(); @@ -70,24 +95,35 @@ } ); } - function shareClickHandler( e ) { + /** + * Click event handler for share button. + * + * @param {MouseEvent} event Event handler. + */ + function shareClickHandler( event ) { var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); currentTab.setAttribute( 'aria-selected', 'false' ); document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); - e.target.setAttribute( 'aria-selected', 'true' ); - document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); + event.target.setAttribute( 'aria-selected', 'true' ); + document.querySelector( '#' + event.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); } - function shareKeyHandler( e ) { - var target = e.target, + /** + * Keyboard event handler for share button. + * + * @param {KeyboardEvent} event Event handler. + * @return {boolean|void} Returns false if default action is to be prevented. + */ + function shareKeyHandler( event ) { + var target = event.target, previousSibling = target.parentElement.previousElementSibling, nextSibling = target.parentElement.nextElementSibling, newTab, newTabChild; - if ( 37 === e.keyCode ) { + if ( 37 === event.keyCode ) { newTab = previousSibling; - } else if ( 39 === e.keyCode ) { + } else if ( 39 === event.keyCode ) { newTab = nextSibling; } else { return false; @@ -119,24 +155,29 @@ } } - document.addEventListener( 'keydown', function ( e ) { - if ( 27 === e.keyCode && -1 === share_dialog.className.indexOf( 'hidden' ) ) { + document.addEventListener( 'keydown', function ( event ) { + if ( 27 === event.keyCode && -1 === share_dialog.className.indexOf( 'hidden' ) ) { closeSharingDialog(); - } else if ( 9 === e.keyCode ) { - constrainTabbing( e ); + } else if ( 9 === event.keyCode ) { + constrainTabbing( event ); } }, false ); - function constrainTabbing( e ) { + /** + * Constrain tabbing to share dialog when open. + * + * @param {KeyboardEvent} event Event object. + */ + function constrainTabbing( event ) { // Need to re-get the selected tab each time. var firstFocusable = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); - if ( share_dialog_close === e.target && ! e.shiftKey ) { + if ( share_dialog_close === event.target && ! event.shiftKey ) { firstFocusable.focus(); - e.preventDefault(); - } else if ( firstFocusable === e.target && e.shiftKey ) { + event.preventDefault(); + } else if ( firstFocusable === event.target && event.shiftKey ) { share_dialog_close.focus(); - e.preventDefault(); + event.preventDefault(); } } @@ -154,15 +195,16 @@ /** * Detect clicks to external (_top) links. + * + * @param {MouseEvent} event The click event object. */ - function linkClickHandler( e ) { - var target = e.target, - href; - if ( target.hasAttribute( 'href' ) ) { - href = target.getAttribute( 'href' ); - } else { - href = target.parentElement.getAttribute( 'href' ); - } + function linkClickHandler( event ) { + /* + * The href property resolves to an absolute URL, which the parent window requires. + * Elements whose href is not a string, such as SVG anchors, are skipped. + */ + var link = event.target.closest( '[href]' ), + href = 'string' === typeof link?.href ? link.href : null; // Only catch clicks from the primary mouse button, without any modifiers. if ( event.altKey || event.ctrlKey || event.metaKey || event.shiftKey ) { @@ -172,7 +214,7 @@ // Send link target to the parent (embedding) site. if ( href ) { sendEmbedMessage( 'link', href ); - e.preventDefault(); + event.preventDefault(); } } @@ -195,7 +237,7 @@ /** * Message handler. * - * @param {MessageEvent} event + * @param {MessageEvent} event The message event object. */ function onMessage( event ) { var data = event.data; diff --git a/src/js/_enqueues/lib/emoji-loader.js b/src/js/_enqueues/lib/emoji-loader.js index 4882107670174..bbb46e80d0337 100644 --- a/src/js/_enqueues/lib/emoji-loader.js +++ b/src/js/_enqueues/lib/emoji-loader.js @@ -2,24 +2,14 @@ * @output wp-includes/js/wp-emoji-loader.js */ -/* eslint-env es6 */ - // Note: This is loaded as a script module, so there is no need for an IIFE to prevent pollution of the global scope. -/** - * Emoji Settings as exported in PHP via _print_emoji_detection_script(). - * @typedef WPEmojiSettings - * @type {object} - * @property {?object} source - * @property {?string} source.concatemoji - * @property {?string} source.twemoji - * @property {?string} source.wpemoji - */ +// Note: The WPEmojiSettings and EmojiSupports types are declared in typings/wp-emoji, since wp-emoji.js reads them back. const selector = 'script#wp-emoji-settings'; const script = document.querySelector( selector ); if ( ! ( script instanceof HTMLScriptElement ) ) { - throw new Error( `Element missing: ${ selector }`); + throw new Error( `Element missing: ${ selector }` ); } const settings = /** @type {WPEmojiSettings} */ ( JSON.parse( script.text ) ); @@ -27,14 +17,17 @@ const settings = /** @type {WPEmojiSettings} */ ( JSON.parse( script.text ) ); window._wpemojiSettings = settings; /** - * Support tests. + * Results of the emoji support tests. + * * @typedef SupportTests - * @type {object} - * @property {?boolean} flag - * @property {?boolean} emoji + * @type {Object} + * @property {boolean} flag Whether the browser renders flag emoji. + * @property {boolean} emoji Whether the browser renders emoji. */ const sessionStorageKey = 'wpEmojiSettingsSupports'; + +/** @type {Array} */ const tests = [ 'flag', 'emoji' ]; /** @@ -44,23 +37,25 @@ const tests = [ 'flag', 'emoji' ]; * * @private * - * @returns {boolean} + * @return {boolean} True if the browser supports offloading to a Worker. */ function supportsWorkerOffloading() { return ( typeof Worker !== 'undefined' && typeof OffscreenCanvas !== 'undefined' && typeof URL !== 'undefined' && - URL.createObjectURL && + typeof URL.createObjectURL === 'function' && typeof Blob !== 'undefined' ); } /** + * Support tests as they are stored in session storage. + * * @typedef SessionSupportTests - * @type {object} - * @property {number} timestamp - * @property {SupportTests} supportTests + * @type {Object} + * @property {number} timestamp When the tests were run, in milliseconds since the epoch. + * @property {SupportTests} supportTests What the tests found. */ /** @@ -70,14 +65,17 @@ function supportsWorkerOffloading() { * * @private * - * @returns {?SupportTests} Support tests, or null if not set or older than 1 week. + * @return {?SupportTests} Support tests, or null if not set or older than 1 week. */ function getSessionSupportTests() { try { + const itemJson = sessionStorage.getItem( sessionStorageKey ); + if ( null === itemJson ) { + return null; + } + /** @type {SessionSupportTests} */ - const item = JSON.parse( - sessionStorage.getItem( sessionStorageKey ) - ); + const item = JSON.parse( itemJson ); if ( typeof item === 'object' && typeof item.timestamp === 'number' && @@ -97,7 +95,7 @@ function getSessionSupportTests() { * * @private * - * @param {SupportTests} supportTests Support tests. + * @param {SupportTests} supportTests What the tests found. */ function setSessionSupportTests( supportTests ) { try { @@ -114,6 +112,51 @@ function setSessionSupportTests( supportTests ) { } catch ( e ) {} } +/** + * A 2D context for the support tests. + * + * Which of the two it is depends on the kind of canvas it came from, and the tests use only what + * both provide. + * + * @typedef {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} EmojiTestContext + */ + +/** + * Checks if two sets of Emoji characters render the same visually. + * + * @callback EmojiSetsRenderIdentically + * + * @param {EmojiTestContext} context 2D Context. + * @param {string} set1 Set of Emoji to test. + * @param {string} set2 Set of Emoji to test. + * + * @return {boolean} True if the two sets render the same. + */ + +/** + * Checks if the center point of a single emoji is empty. + * + * @callback EmojiRendersEmptyCenterPoint + * + * @param {EmojiTestContext} context 2D Context. + * @param {string} emoji Emoji to test. + * + * @return {boolean} True if the center point is empty. + */ + +/** + * Determines if the browser properly renders Emoji that Twemoji can supplement. + * + * @callback BrowserSupportsEmoji + * + * @param {EmojiTestContext} context 2D Context. + * @param {keyof SupportTests} type Which support test to run. + * @param {EmojiSetsRenderIdentically} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. + * @param {EmojiRendersEmptyCenterPoint} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. + * + * @return {boolean} True if the browser can render emoji, false if it cannot. + */ + /** * Checks if two sets of Emoji characters render the same visually. * @@ -129,9 +172,9 @@ function setSessionSupportTests( supportTests ) { * * @private * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} set1 Set of Emoji to test. - * @param {string} set2 Set of Emoji to test. + * @param {EmojiTestContext} context 2D Context. + * @param {string} set1 Set of Emoji to test. + * @param {string} set2 Set of Emoji to test. * * @return {boolean} True if the two sets render the same. */ @@ -179,8 +222,8 @@ function emojiSetsRenderIdentically( context, set1, set2 ) { * * @private * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} emoji Emoji to test. + * @param {EmojiTestContext} context 2D Context. + * @param {string} emoji Emoji to test. * * @return {boolean} True if the center point is empty. */ @@ -190,7 +233,7 @@ function emojiRendersEmptyCenterPoint( context, emoji ) { context.fillText( emoji, 0, 0 ); // Test if the center point (16, 16) is empty (0,0,0,0). - const centerPoint = context.getImageData(16, 16, 1, 1); + const centerPoint = context.getImageData( 16, 16, 1, 1 ); for ( let i = 0; i < centerPoint.data.length; i++ ) { if ( centerPoint.data[ i ] !== 0 ) { // Stop checking the moment it's known not to be empty. @@ -211,14 +254,15 @@ function emojiRendersEmptyCenterPoint( context, emoji ) { * * @private * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} type Whether to test for support of "flag" or "emoji". - * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. - * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. + * @param {EmojiTestContext} context 2D Context. + * @param {keyof SupportTests} type Which support test to run. + * @param {EmojiSetsRenderIdentically} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. + * @param {EmojiRendersEmptyCenterPoint} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. * * @return {boolean} True if the browser can render emoji, false if it cannot. */ function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { + /** @type {boolean} */ let isIdentical; switch ( type ) { @@ -258,7 +302,7 @@ function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiR /* * Test for English flag compatibility. England is a country in the United Kingdom, it - * does not have a two letter locale code but rather a five letter sub-division code. + * does not have a two letter locale code but rather a five letter subdivision code. * * To test for support, we try to render it, and compare the rendering to how it would look if * the browser doesn't render it correctly (black flag emoji + [G] + [B] + [E] + [N] + [G]). @@ -281,17 +325,15 @@ function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiR * The hairy creature emoji is a single code point emoji. Testing for browser * support required testing the center point of the emoji to see if it is empty. * - * 0xD83E 0x1FAC8 (\uD83E\u1FAC8) == 🫈 Hairy creature. + * U+1FAC8 (\uD83E\uDEC8) == 🫈 Hairy creature. * * When updating this test, please ensure that the emoji is either a single code point * or switch to using the emojiSetsRenderIdentically function and testing with a zero-width * joiner vs a zero-width space. */ - const notSupported = emojiRendersEmptyCenterPoint( context, '\uD83E\u1FAC8' ); + const notSupported = emojiRendersEmptyCenterPoint( context, '\uD83E\uDEC8' ); return ! notSupported; } - - return false; } /** @@ -304,25 +346,30 @@ function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiR * * @private * - * @param {string[]} tests Tests. - * @param {Function} browserSupportsEmoji Reference to browserSupportsEmoji function, needed due to minification. - * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. - * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. + * @param {Array} tests Which support tests to run. + * @param {BrowserSupportsEmoji} browserSupportsEmoji Reference to browserSupportsEmoji function, needed due to minification. + * @param {EmojiSetsRenderIdentically} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. + * @param {EmojiRendersEmptyCenterPoint} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. * * @return {SupportTests} Support tests. */ function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { - let canvas; + /** @type {?EmojiTestContext} */ + let context; + if ( typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope ) { - canvas = new OffscreenCanvas( 300, 150 ); // Dimensions are default for HTMLCanvasElement. + // Dimensions are default for HTMLCanvasElement. + context = new OffscreenCanvas( 300, 150 ).getContext( '2d', { willReadFrequently: true } ); } else { - canvas = document.createElement( 'canvas' ); + context = document.createElement( 'canvas' ).getContext( '2d', { willReadFrequently: true } ); } - const context = canvas.getContext( '2d', { willReadFrequently: true } ); + if ( ! context ) { + throw new Error( 'Unable to obtain a 2D context for the emoji support tests.' ); + } /* * Chrome on OS X added native emoji rendering in M41. Unfortunately, @@ -332,7 +379,7 @@ function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentica context.textBaseline = 'top'; context.font = '600 32px Arial'; - const supports = {}; + const supports = /** @type {SupportTests} */ ( {} ); tests.forEach( ( test ) => { supports[ test ] = browserSupportsEmoji( context, test, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); } ); @@ -363,10 +410,11 @@ settings.supports = { }; // Obtain the emoji support from the browser, asynchronously when possible. -new Promise( ( resolve ) => { - let supportTests = getSessionSupportTests(); - if ( supportTests ) { - resolve( supportTests ); +/** @type {Promise} */ +const supportTestsPromise = new Promise( ( resolve ) => { + const sessionSupportTests = getSessionSupportTests(); + if ( sessionSupportTests ) { + resolve( sessionSupportTests ); return; } @@ -388,20 +436,21 @@ new Promise( ( resolve ) => { type: 'text/javascript' } ); const worker = new Worker( URL.createObjectURL( blob ), { name: 'wpTestEmojiSupports' } ); - worker.onmessage = ( event ) => { - supportTests = event.data; - setSessionSupportTests( supportTests ); + worker.onmessage = ( /** @type {MessageEvent} */ event ) => { + setSessionSupportTests( event.data ); worker.terminate(); - resolve( supportTests ); + resolve( event.data ); }; return; } catch ( e ) {} } - supportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); - setSessionSupportTests( supportTests ); - resolve( supportTests ); -} ) + const testedSupportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); + setSessionSupportTests( testedSupportTests ); + resolve( testedSupportTests ); +} ); + +supportTestsPromise // Once the browser emoji support has been obtained from the session, finalize the settings. .then( ( supportTests ) => { /* @@ -409,15 +458,17 @@ new Promise( ( resolve ) => { * support settings accordingly. */ for ( const test in supportTests ) { - settings.supports[ test ] = supportTests[ test ]; + const key = /** @type {keyof SupportTests} */ ( test ); + const supported = supportTests[ key ]; + + settings.supports[ key ] = supported; settings.supports.everything = - settings.supports.everything && settings.supports[ test ]; + settings.supports.everything && supported; - if ( 'flag' !== test ) { + if ( 'flag' !== key ) { settings.supports.everythingExceptFlag = - settings.supports.everythingExceptFlag && - settings.supports[ test ]; + settings.supports.everythingExceptFlag && supported; } } diff --git a/src/js/_enqueues/lib/image-edit.js b/src/js/_enqueues/lib/image-edit.js index d1603051d7078..d076b41b1534c 100644 --- a/src/js/_enqueues/lib/image-edit.js +++ b/src/js/_enqueues/lib/image-edit.js @@ -1,12 +1,13 @@ + /* global ajaxurl, confirm */ + /** * The functions necessary for editing images. * * @since 2.9.0 * @output wp-admin/js/image-edit.js + * + * @param {JQueryStatic} $ The jQuery object. */ - - /* global ajaxurl, confirm */ - (function($) { var __ = wp.i18n.__; @@ -23,6 +24,10 @@ /** * Enable crop tool. + * + * @param {number} postid The post ID. + * @param {string} nonce The nonce to verify the request. + * @param {HTMLElement} cropButton The crop button element. */ toggleCropTool: function( postid, nonce, cropButton ) { var img = $( '#image-preview-' + postid ), @@ -64,6 +69,10 @@ /** * Handle crop tool clicks. + * + * @param {number} postid The post ID. + * @param {string} nonce The nonce to verify the request. + * @param {HTMLElement} cropButton The crop button element. */ handleCropToolClick: function( postid, nonce, cropButton ) { @@ -269,8 +278,6 @@ * * @memberof imageEdit * - * @param {HTMLElement} el The activated control element. - * * @return {boolean} Always returns false. */ monitorPopup : function() { @@ -300,8 +307,8 @@ * * @memberof imageEdit * - * @param {Event} event The key or click event. - * @param {HTMLElement} el The current element. + * @param {Event} event The key or click event. + * @param {HTMLElement} el The current element. * * @return {boolean} Always returns false. */ @@ -431,10 +438,10 @@ * * @memberof imageEdit * - * @param {number} postid The current post ID. - * @param {number} x Is 0 when it applies the y-axis - * and 1 when applicable for the x-axis. - * @param {jQuery} el Element. + * @param {number} postid The current post ID. + * @param {number} x Is 0 when it applies the y-axis + * and 1 when applicable for the x-axis. + * @param {jQuery} el Element. * * @return {void} */ @@ -567,7 +574,7 @@ * * @param {number} postid The post ID. * @param {string} nonce The nonce to verify the request. - * @param {function} callback Function to execute when the image is loaded. + * @param {Function} callback Function to execute when the image is loaded. * * @return {void} */ @@ -725,8 +732,8 @@ * * @memberof imageEdit * - * @param {number} postid The post ID to get the image from the database. - * @param {string} nonce The nonce to verify the request. + * @param {number} postid The post ID to get the image from the database. + * @param {string} nonce The nonce to verify the request. * * @return {boolean|void} If the actions are successfully saved a response message is shown. * Returns false if there is no image editing history, @@ -794,9 +801,9 @@ * * @memberof imageEdit * - * @param {number} postid The post ID for the image. - * @param {string} nonce The nonce to verify the request. - * @param {Object} view The image editor view to be used for the editing. + * @param {number} postid The post ID for the image. + * @param {string} nonce The nonce to verify the request. + * @param {Object} view The image editor view to be used for the editing. * * @return {void|promise} Either returns void if the button was already activated * or returns an instance of the image editor, wrapped in a promise. @@ -905,11 +912,11 @@ setTimeout( function() { var elementToSetFocusTo = $( '.notice[role="alert"]' ); - if ( ! elementToSetFocusTo.length ) { - elementToSetFocusTo = $( '.imgedit-wrap' ).find( ':tabbable:first' ); + if ( elementToSetFocusTo.length ) { + elementToSetFocusTo.attr( 'tabindex', '-1' ).trigger( 'focus' ); + } else { + $( '.imgedit-wrap' ).find( ':tabbable:first' ).trigger( 'focus' ); } - - elementToSetFocusTo.attr( 'tabindex', '-1' ).trigger( 'focus' ); }, 100 ); }, @@ -1002,7 +1009,7 @@ * @param {Object} img jQuery object representing the image. * @param {Object} c The selection. * - * @return {Object} + * @return {void} */ onSelectEnd: function(img, c) { imageEdit.setCropSelection(postid, c); @@ -1047,7 +1054,7 @@ * @param {number} postid The post ID. * @param {Object} c The selection. * - * @return {boolean} + * @return {boolean|void} Returns false if the selection is invalid. */ setCropSelection : function(postid, c) { var sel, @@ -1197,7 +1204,7 @@ * @param {string} nonce The nonce. * @param {Object} t The target element. * - * @return {boolean} + * @return {boolean|void} Returns false if the rotate button is disabled. */ rotate : function(angle, postid, nonce, t) { if ( $(t).hasClass('disabled') ) { @@ -1224,7 +1231,7 @@ * @param {string} nonce The nonce. * @param {Object} t The target element. * - * @return {boolean} + * @return {boolean|void} Returns false if the flip button is disabled. */ flip : function (axis, postid, nonce, t) { if ( $(t).hasClass('disabled') ) { @@ -1283,8 +1290,8 @@ * * @memberof imageEdit * - * @param {number} postid The post ID. - * @param {string} nonce The nonce. + * @param {number} postid The post ID. + * @param {string} nonce The nonce. * * @return {void|false} Returns false if the undo button is disabled. */ @@ -1441,9 +1448,9 @@ * * @memberof imageEdit * - * @param {number} postid The post ID. - * @param {number} n The ratio to set. - * @param {jQuery} el The element containing the values. + * @param {number} postid The post ID. + * @param {number} n The ratio to set. + * @param {jQuery} el The element containing the values. * * @return {void} */ diff --git a/src/js/_enqueues/lib/link.js b/src/js/_enqueues/lib/link.js index a2500a9069648..0d1a5a923e978 100644 --- a/src/js/_enqueues/lib/link.js +++ b/src/js/_enqueues/lib/link.js @@ -2,8 +2,15 @@ * @output wp-includes/js/wplink.js */ - /* global wpLink */ +/* global wpLink */ +/** + * The WordPress Link Modal dialog. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wpLinkL10n The WordPress Link localization object. + * @param {Object} wp The WordPress global object. + */ ( function( $, wpLinkL10n, wp ) { var editor, searchTimer, River, Query, correctedURL, emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$/i, @@ -12,6 +19,11 @@ rivers = {}, isTouch = ( 'ontouchend' in document ); + /** + * Gets the currently selected link in the editor. + * + * @return {JQuery} The currently selected link element. + */ function getLink() { if ( editor ) { return editor.$( 'a[data-wplink-edit="true"]' ); diff --git a/src/js/_enqueues/lib/list-revisions.js b/src/js/_enqueues/lib/list-revisions.js index db0485ef97a08..ae5ad321ef961 100644 --- a/src/js/_enqueues/lib/list-revisions.js +++ b/src/js/_enqueues/lib/list-revisions.js @@ -2,6 +2,12 @@ * @output wp-includes/js/wp-list-revisions.js */ +/** + * Hides the revisions radio buttons to stop selecting reverse comparisons + * + * @param {Window} w The global window object. + */ + (function(w) { var init = function() { var pr = document.getElementById('post-revisions'), diff --git a/src/js/_enqueues/lib/lists.js b/src/js/_enqueues/lib/lists.js index d7e888c85b9ab..43672c9a5aaf5 100644 --- a/src/js/_enqueues/lib/lists.js +++ b/src/js/_enqueues/lib/lists.js @@ -5,7 +5,9 @@ /* global ajaxurl, wpAjax */ /** - * @param {jQuery} $ jQuery object. + * Handles the dynamic functionality needed for lists. + * + * @param {JQueryStatic} $ The jQuery object. */ ( function( $ ) { var functions = { @@ -22,7 +24,7 @@ var functions = { wpList = { /** - * @member {object} + * @member {Object} */ settings: { @@ -108,9 +110,9 @@ wpList = { * Callback that's run before a request is made. * * @callback wpList~confirm - * @param {object} this + * @param {Object} this * @param {HTMLElement} list The list DOM element. - * @param {object} settings Settings for the current list. + * @param {Object} settings Settings for the current list. * @param {string} action The type of action to perform: 'add', 'delete', or 'dim'. * @param {string} backgroundColor Background color of the list's DOM element. * @return {boolean} Whether to proceed with the action or not. @@ -123,7 +125,7 @@ wpList = { * Allows to cancel the request. * * @callback wpList~addBefore - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @return {object|boolean} Settings for the Ajax request or false to abort. */ addBefore: null, @@ -133,11 +135,11 @@ wpList = { * * @callback wpList~addAfter * @param {XML} returnedResponse Raw response returned from the server. - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @param {jqXHR} settings.xml jQuery XMLHttpRequest object. * @param {string} settings.status Status of the request: 'success', 'notmodified', 'nocontent', 'error', * 'timeout', 'abort', or 'parsererror'. - * @param {object} settings.parsed Parsed response object. + * @param {Object} settings.parsed Parsed response object. */ addAfter: null, @@ -147,7 +149,7 @@ wpList = { * Allows to cancel the request. * * @callback wpList~delBefore - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @param {HTMLElement} list The list DOM element. * @return {object|boolean} Settings for the Ajax request or false to abort. */ @@ -158,11 +160,11 @@ wpList = { * * @callback wpList~delAfter * @param {XML} returnedResponse Raw response returned from the server. - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @param {jqXHR} settings.xml jQuery XMLHttpRequest object. * @param {string} settings.status Status of the request: 'success', 'notmodified', 'nocontent', 'error', * 'timeout', 'abort', or 'parsererror'. - * @param {object} settings.parsed Parsed response object. + * @param {Object} settings.parsed Parsed response object. */ delAfter: null, @@ -172,7 +174,7 @@ wpList = { * Allows to cancel the request. * * @callback wpList~dimBefore - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @return {object|boolean} Settings for the Ajax request or false to abort. */ dimBefore: null, @@ -182,11 +184,11 @@ wpList = { * * @callback wpList~dimAfter * @param {XML} returnedResponse Raw response returned from the server. - * @param {object} settings Settings for the Ajax request. + * @param {Object} settings Settings for the Ajax request. * @param {jqXHR} settings.xml jQuery XMLHttpRequest object. * @param {string} settings.status Status of the request: 'success', 'notmodified', 'nocontent', 'error', * 'timeout', 'abort', or 'parsererror'. - * @param {object} settings.parsed Parsed response object. + * @param {Object} settings.parsed Parsed response object. */ dimAfter: null }, @@ -224,7 +226,7 @@ wpList = { * data[2] - ID of the parent element of all inputs necessary for the request. * data[3] - Hex color to be used in this request. If data[0] is 'dim', dim class. * data[4] - Additional arguments in query syntax that are added to the request. Example: 'post_id=1234'. - * If data[0] is 'dim', dim add color. + * If data[0] is 'dim', dim add color. * data[5] - Only available if data[0] is 'dim', dim delete color. * data[6] - Only available if data[0] is 'dim', additional arguments in query syntax that are added to the request. * @@ -737,7 +739,7 @@ wpList = { /** * Registers event handlers to add, delete, and dim items. * - * @param {string} elementId + * @param {string} elementId ID of the element to process, including leading #. */ process: function( elementId ) { var list = this, @@ -810,31 +812,31 @@ wpList = { /** * Initializes wpList object. * - * @param {Object} settings - * @param {string} settings.url URL for ajax calls. Default: ajaxurl. - * @param {string} settings.type The HTTP method to use for Ajax requests. Default: 'POST'. - * @param {string} settings.response ID of the element the parsed ajax response will be stored in. - * Default: 'ajax-response'. + * @param {Object} settings The settings for the wpList instance. + * @param {string} settings.url URL for ajax calls. Default: ajaxurl. + * @param {string} settings.type The HTTP method to use for Ajax requests. Default: 'POST'. + * @param {string} settings.response ID of the element the parsed ajax response will be stored in. + * Default: 'ajax-response'. * - * @param {string} settings.what Default: ''. - * @param {string} settings.alt CSS class name for alternate styling. Default: 'alternate'. - * @param {number} settings.altOffset Offset to start alternate styling from. Default: 0. - * @param {string} settings.addColor Hex code or 'none' to disable animation. Default: '#ffff33'. - * @param {string} settings.delColor Hex code or 'none' to disable animation. Default: '#faafaa'. - * @param {string} settings.dimAddColor Hex code or 'none' to disable animation. Default: '#ffff33'. - * @param {string} settings.dimDelColor Hex code or 'none' to disable animation. Default: '#ff3333'. + * @param {string} settings.what Default: ''. + * @param {string} settings.alt CSS class name for alternate styling. Default: 'alternate'. + * @param {number} settings.altOffset Offset to start alternate styling from. Default: 0. + * @param {string} settings.addColor Hex code or 'none' to disable animation. Default: '#ffff33'. + * @param {string} settings.delColor Hex code or 'none' to disable animation. Default: '#faafaa'. + * @param {string} settings.dimAddColor Hex code or 'none' to disable animation. Default: '#ffff33'. + * @param {string} settings.dimDelColor Hex code or 'none' to disable animation. Default: '#ff3333'. * - * @param {wpList~confirm} settings.confirm Callback that's run before a request is made. Default: null. - * @param {wpList~addBefore} settings.addBefore Callback that's run before an item gets added to the list. - * Default: null. - * @param {wpList~addAfter} settings.addAfter Callback that's run after an item got added to the list. - * Default: null. - * @param {wpList~delBefore} settings.delBefore Callback that's run before an item gets deleted from the list. - * Default: null. - * @param {wpList~delAfter} settings.delAfter Callback that's run after an item got deleted from the list. - * Default: null. - * @param {wpList~dimBefore} settings.dimBefore Callback that's run before an item gets dim'd. Default: null. - * @param {wpList~dimAfter} settings.dimAfter Callback that's run after an item got dim'd. Default: null. + * @param {Function} settings.confirm Callback that's run before a request is made. Default: null. + * @param {Function} settings.addBefore Callback that's run before an item gets added to the list. + * Default: null. + * @param {Function} settings.addAfter Callback that's run after an item got added to the list. + * Default: null. + * @param {Function} settings.delBefore Callback that's run before an item gets deleted from the list. + * Default: null. + * @param {Function} settings.delAfter Callback that's run after an item got deleted from the list. + * Default: null. + * @param {Function} settings.dimBefore Callback that's run before an item gets dim'd. Default: null. + * @param {Function} settings.dimAfter Callback that's run after an item got dim'd. Default: null. * @return {$.fn} wpList API function. */ $.fn.wpList = function( settings ) { diff --git a/src/js/_enqueues/lib/nav-menu.js b/src/js/_enqueues/lib/nav-menu.js index 79917c8447f1a..5e94a2b34f3c9 100644 --- a/src/js/_enqueues/lib/nav-menu.js +++ b/src/js/_enqueues/lib/nav-menu.js @@ -1,16 +1,17 @@ /** - * WordPress Administration Navigation Menu - * Interface JS functions - * - * @version 2.0.0 - * - * @package WordPress - * @subpackage Administration * @output wp-admin/js/nav-menu.js */ /* global menus, postboxes, columns, isRtl, ajaxurl, wpNavMenu */ +/** + * Handles the WordPress Administration Navigation Menu Interface functionality. + * + * @version 2.0.0 + * @package WordPress + * + * @param {JQueryStatic} $ The jQuery object. + */ (function($) { var api; @@ -178,7 +179,7 @@ * * @ignore * - * @param jQuery metabox The metabox jQuery object. + * @param {Function} processMethod The method to use for adding the menu items. Defaults to api.addMenuItemToBottom. */ addSelectedToMenu : function(processMethod) { if ( 0 === $('#menu-to-edit').length ) { @@ -339,7 +340,7 @@ } }); }); - + }); }, updateOrderDropdown : function() { @@ -403,7 +404,7 @@ } }); - + }); } }); @@ -560,7 +561,7 @@ menu.on( 'change', '.edit-menu-item-parent', function() { api.changeMenuParent( $( this ) ); }); - + // Update menu item order when value is changed. menu.on( 'change', '.edit-menu-item-order', function() { api.changeMenuOrder( $( this ) ); @@ -569,10 +570,10 @@ /** * changeMenuParent( [parentDropdown] ) - * + * * @since 6.7.0 * - * @param {object} parentDropdown select field + * @param {Object} parentDropdown select field */ changeMenuParent : function( parentDropdown ) { var menuItemNewPosition, @@ -625,10 +626,10 @@ /** * changeMenuOrder( [OrderDropdown] ) - * + * * @since 6.7.0 * - * @param {object} orderDropdown select field + * @param {Object} orderDropdown select field */ changeMenuOrder : function( orderDropdown ) { var menuItems = $( '#menu-to-edit li' ), @@ -1012,6 +1013,11 @@ } }); + /** + * Updates the shared variables used to determine the depth of the menu item being moved. + * + * @param {Object} ui The jQuery UI object for the menu item being moved. + */ function updateSharedVars(ui) { var depth; @@ -1032,17 +1038,35 @@ maxDepth = 0; } + /** + * Updates the current depth of the menu item being moved. + * + * @param {Object} ui The jQuery UI object for the menu item being moved. + * @param {number} depth The new depth of the menu item being moved. + * @return {void} + */ function updateCurrentDepth(ui, depth) { ui.placeholder.updateDepthClass( depth, currentDepth ); currentDepth = depth; } + /** + * Determines the initial menu max depth class on the body element. + * + * @return {number} The initial menu max depth. + */ function initialMenuMaxDepth() { if( ! body[0].className ) return 0; var match = body[0].className.match(/menu-max-depth-(\d+)/); return match && match[1] ? parseInt( match[1], 10 ) : 0; } + /** + * Updates the menu max depth class on the body element. + * + * @param {number} depthChange The change in depth of the menu item being moved. + * @return {void} + */ function updateMenuMaxDepth( depthChange ) { var depth, newDepth = menuMaxDepth; if ( depthChange === 0 ) { @@ -1159,7 +1183,7 @@ * Handle toggling bulk selection checkboxes for menu items. * * @since 5.8.0 - */ + */ attachBulkSelectButtonListeners : function() { var that = this; @@ -1178,7 +1202,7 @@ * Enable bulk selection checkboxes for menu items. * * @since 5.8.0 - */ + */ enableBulkSelection : function() { var checkbox = $( '#menu-to-edit .menu-item-checkbox' ); @@ -1195,7 +1219,7 @@ * Disable bulk selection checkboxes for menu items. * * @since 5.8.0 - */ + */ disableBulkSelection : function() { var checkbox = $( '#menu-to-edit .menu-item-checkbox' ); @@ -1219,7 +1243,7 @@ * Listen for state changes on bulk action checkboxes. * * @since 5.8.0 - */ + */ attachMenuCheckBoxListeners : function() { var that = this; @@ -1232,7 +1256,7 @@ * Create delete button to remove menu items from collection. * * @since 5.8.0 - */ + */ attachMenuItemDeleteButton : function() { var that = this; @@ -1275,7 +1299,7 @@ * List menu items awaiting deletion. * * @since 5.8.0 - */ + */ attachPendingMenuItemsListForDeletion : function() { $( '#post-body-content' ).on( 'change', '.menu-item-checkbox', function() { var menuItemName, menuItemType, menuItemID, listedMenuItem; @@ -1317,7 +1341,7 @@ * Set status of bulk delete checkbox. * * @since 5.8.0 - */ + */ setBulkDeleteCheckboxStatus : function() { var that = this; var checkbox = $( '#menu-to-edit .menu-item-checkbox' ); @@ -1341,7 +1365,7 @@ * Set status of menu items removal button. * * @since 5.8.0 - */ + */ setRemoveSelectedButtonStatus : function() { var button = $( '.menu-items-delete' ); @@ -1419,7 +1443,7 @@ } /* - * Reset results when search is less than or equal to + * Reset results when search is less than or equal to * minimum characters for searched term. */ if ( q.length <= minSearchLength ) { @@ -1766,9 +1790,9 @@ /** * Process the quick search response into a search result * - * @param string resp The server response to the query. - * @param object req The request arguments. - * @param jQuery panel The tabs panel we're searching in. + * @param {string} resp The server response to the query. + * @param {Object} req The request arguments. + * @param {jQuery} panel The tabs panel we're searching in. */ processQuickSearchQueryResponse : function(resp, req, panel) { var matched, newID, diff --git a/src/js/_enqueues/lib/pointer.js b/src/js/_enqueues/lib/pointer.js index 9d043f6dee141..7e63d0e009b53 100644 --- a/src/js/_enqueues/lib/pointer.js +++ b/src/js/_enqueues/lib/pointer.js @@ -4,6 +4,8 @@ /** * Initializes the wp-pointer widget using jQuery UI Widget Factory. + * + * @param {JQueryStatic} $ The jQuery object. */ (function($){ var identifier = 0, @@ -72,7 +74,7 @@ * There are 4 special values that do something extra: * * - `document` will transfer the pointer to the body of the new document - * specified by the value. + * specified by the value. * - `pointerClass` will change the class of the pointer element. * - `position` will reposition the pointer. * - `content` will update the content of the pointer. @@ -146,7 +148,7 @@ * * @param {Object} event The event that caused the update. * - * @return {Promise} Resolves when the update has been executed. + * @return {Promise|void} Resolves when the update has been executed. */ update: function( event ) { var self = this, diff --git a/src/js/_enqueues/lib/quicktags.js b/src/js/_enqueues/lib/quicktags.js index 4b1a80fa28c94..ffdbfaeef7349 100644 --- a/src/js/_enqueues/lib/quicktags.js +++ b/src/js/_enqueues/lib/quicktags.js @@ -1,4 +1,3 @@ - /* * Quicktags * @@ -234,6 +233,12 @@ window.edToolbar = function(){}; t.init(); }; + /** + * Escapes HTML special characters in a string. + * + * @param {string} text The string to escape. + * @return {string} The escaped string. + */ function _escape( text ) { text = text || ''; text = text.replace( /&([^#])(?![a-z1-4]{1,8};)/gi, '&$1' ); @@ -249,6 +254,11 @@ window.edToolbar = function(){}; qt._buttonsInit = function( id ) { var t = this; + /** + * Initializes the Quicktags buttons for a specific instance. + * + * @param {string} instanceId The ID of the Quicktags instance to initialize buttons for. + */ function _init( instanceId ) { var canvas, name, settings, theButtons, html, ed, id, i, use, defaults = ',strong,em,link,block,del,ins,img,ul,ol,li,code,more,close,'; @@ -323,23 +333,23 @@ window.edToolbar = function(){}; * use add_action( 'admin_print_footer_scripts', 'output_my_js', 100 ) or add_action( 'wp_footer', 'output_my_js', 100 ) * * Minimum required to add a button that calls an external function: - * QTags.addButton( 'my_id', 'my button', my_callback ); - * function my_callback() { alert('yeah!'); } + * QTags.addButton( 'my_id', 'my button', my_callback ); + * function my_callback() { alert('yeah!'); } * * Minimum required to add a button that inserts a tag: - * QTags.addButton( 'my_id', 'my button', '', '' ); - * QTags.addButton( 'my_id2', 'my button', '
' ); + * QTags.addButton( 'my_id', 'my button', '', '' ); + * QTags.addButton( 'my_id2', 'my button', '
' ); * - * @param string id Required. Button HTML ID - * @param string display Required. Button's value="..." - * @param string|function arg1 Required. Either a starting tag to be inserted like "" or a callback that is executed when the button is clicked. - * @param string arg2 Optional. Ending tag like "" - * @param string access_key Deprecated Not used - * @param string title Optional. Button's title="..." - * @param int priority Optional. Number representing the desired position of the button in the toolbar. 1 - 9 = first, 11 - 19 = second, 21 - 29 = third, etc. - * @param string instance Optional. Limit the button to a specific instance of Quicktags, add to all instances if not present. - * @param attr object Optional. Used to pass additional attributes. Currently supports `ariaLabel` and `ariaLabelClose` (for "close tag" state) - * @return mixed null or the button object that is needed for back-compat. + * @param {string} id Required. Button HTML ID + * @param {string} display Required. Button's value="..." + * @param {string|Function} arg1 Required. Either a starting tag to be inserted like "" or a callback that is executed when the button is clicked. + * @param {string} arg2 Optional. Ending tag like "" + * @param {string} [access_key] Deprecated Not used + * @param {string} [title] Optional. Button's title="..." + * @param {number} [priority] Optional. Number representing the desired position of the button in the toolbar. 1 - 9 = first, 11 - 19 = second, 21 - 29 = third, etc. + * @param {string} [instance] Optional. Limit the button to a specific instance of Quicktags, add to all instances if not present. + * @param {Object} [attr] Optional. Used to pass additional attributes. Currently supports `ariaLabel` and `ariaLabelClose` (for "close tag" state) + * @return {void|Object} Returns the button object if priority is -1, otherwise returns void. */ qt.addButton = function( id, display, arg1, arg2, access_key, title, priority, instance, attr ) { var btn; @@ -723,26 +733,38 @@ window.edToolbar = function(){}; /** * Initialize new instance of the Quicktags editor + * + * @param {Object} settings The settings for the Quicktags editor. + * @return {Object} The Quicktags editor instance. */ window.quicktags = function(settings) { return new window.QTags(settings); }; /** - * Inserts content at the caret in the active editor (textarea) + * Inserts content at the caret in the active editor (textarea). * * Added for back compatibility + * @param {string} bah The ID of the textarea. + * @param {string} txt The content to insert. * @see QTags.insertContent() + * @return {boolean} True if the content was inserted, false otherwise. */ window.edInsertContent = function(bah, txt) { return window.QTags.insertContent(txt); }; /** - * Adds a button to all instances of the editor + * Adds a button to all instances of the editor. * * Added for back compatibility, use QTags.addButton() as it gives more flexibility like type of button, button placement, etc. + * @param {string} id The ID of the button. + * @param {string} display The display text of the button. + * @param {string} tagStart The starting tag. + * @param {string} tagEnd The ending tag. + * @param {string} access The access key for the button. * @see QTags.addButton() + * @return {void|Object} Returns the button object if priority is -1, otherwise returns void. */ window.edButton = function(id, display, tagStart, tagEnd, access) { return window.QTags.addButton( id, display, tagStart, tagEnd, access, '', -1 ); diff --git a/src/js/_enqueues/lib/user-suggest.js b/src/js/_enqueues/lib/user-suggest.js index f05b7ffa8892f..fc58ac4ef0044 100644 --- a/src/js/_enqueues/lib/user-suggest.js +++ b/src/js/_enqueues/lib/user-suggest.js @@ -34,11 +34,11 @@ * * Optional data-attributes: * - data-autocomplete-type (add, search) - * The action that is going to be performed: search for existing users - * or add a new one. Default: add + * The action that is going to be performed: search for existing users + * or add a new one. Default: add * - data-autocomplete-field (user_login, user_email) - * The field that is returned as the value for the suggestion. - * Default: user_login + * The field that is returned as the value for the suggestion. + * Default: user_login * * @see wp-admin/includes/admin-actions.php:wp_ajax_autocomplete_user() */ diff --git a/src/js/_enqueues/vendor/jquery/jquery-migrate.js b/src/js/_enqueues/vendor/jquery/jquery-migrate.js deleted file mode 100644 index 5ef505ed920f9..0000000000000 --- a/src/js/_enqueues/vendor/jquery/jquery-migrate.js +++ /dev/null @@ -1,1018 +0,0 @@ -/*! - * jQuery Migrate - v3.4.1 - 2023-02-23T15:31Z - * Copyright OpenJS Foundation and other contributors - */ -( function( factory ) { - "use strict"; - - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( [ "jquery" ], function( jQuery ) { - return factory( jQuery, window ); - } ); - } else if ( typeof module === "object" && module.exports ) { - - // Node/CommonJS - // eslint-disable-next-line no-undef - module.exports = factory( require( "jquery" ), window ); - } else { - - // Browser globals - factory( jQuery, window ); - } -} )( function( jQuery, window ) { -"use strict"; - -jQuery.migrateVersion = "3.4.1"; - -// Returns 0 if v1 == v2, -1 if v1 < v2, 1 if v1 > v2 -function compareVersions( v1, v2 ) { - var i, - rVersionParts = /^(\d+)\.(\d+)\.(\d+)/, - v1p = rVersionParts.exec( v1 ) || [ ], - v2p = rVersionParts.exec( v2 ) || [ ]; - - for ( i = 1; i <= 3; i++ ) { - if ( +v1p[ i ] > +v2p[ i ] ) { - return 1; - } - if ( +v1p[ i ] < +v2p[ i ] ) { - return -1; - } - } - return 0; -} - -function jQueryVersionSince( version ) { - return compareVersions( jQuery.fn.jquery, version ) >= 0; -} - -// A map from disabled patch codes to `true`. This should really -// be a `Set` but those are unsupported in IE. -var disabledPatches = Object.create( null ); - -// Don't apply patches for specified codes. Helpful for code bases -// where some Migrate warnings have been addressed and it's desirable -// to avoid needless patches or false positives. -jQuery.migrateDisablePatches = function() { - var i; - for ( i = 0; i < arguments.length; i++ ) { - disabledPatches[ arguments[ i ] ] = true; - } -}; - -// Allow enabling patches disabled via `jQuery.migrateDisablePatches`. -// Helpful if you want to disable a patch only for some code that won't -// be updated soon to be able to focus on other warnings - and enable it -// immediately after such a call: -// ```js -// jQuery.migrateDisablePatches( "workaroundA" ); -// elem.pluginViolatingWarningA( "pluginMethod" ); -// jQuery.migrateEnablePatches( "workaroundA" ); -// ``` -jQuery.migrateEnablePatches = function() { - var i; - for ( i = 0; i < arguments.length; i++ ) { - delete disabledPatches[ arguments[ i ] ]; - } -}; - -jQuery.migrateIsPatchEnabled = function( patchCode ) { - return !disabledPatches[ patchCode ]; -}; - -( function() { - - // Support: IE9 only - // IE9 only creates console object when dev tools are first opened - // IE9 console is a host object, callable but doesn't have .apply() - if ( !window.console || !window.console.log ) { - return; - } - - // Need jQuery 3.x-4.x and no older Migrate loaded - if ( !jQuery || !jQueryVersionSince( "3.0.0" ) || - jQueryVersionSince( "5.0.0" ) ) { - window.console.log( "JQMIGRATE: jQuery 3.x-4.x REQUIRED" ); - } - if ( jQuery.migrateWarnings ) { - window.console.log( "JQMIGRATE: Migrate plugin loaded multiple times" ); - } - - // Show a message on the console so devs know we're active - window.console.log( "JQMIGRATE: Migrate is installed" + - ( jQuery.migrateMute ? "" : " with logging active" ) + - ", version " + jQuery.migrateVersion ); - -} )(); - -var warnedAbout = {}; - -// By default each warning is only reported once. -jQuery.migrateDeduplicateWarnings = true; - -// List of warnings already given; public read only -jQuery.migrateWarnings = []; - -// Set to false to disable traces that appear with warnings -if ( jQuery.migrateTrace === undefined ) { - jQuery.migrateTrace = true; -} - -// Forget any warnings we've already given; public -jQuery.migrateReset = function() { - warnedAbout = {}; - jQuery.migrateWarnings.length = 0; -}; - -function migrateWarn( code, msg ) { - var console = window.console; - if ( jQuery.migrateIsPatchEnabled( code ) && - ( !jQuery.migrateDeduplicateWarnings || !warnedAbout[ msg ] ) ) { - warnedAbout[ msg ] = true; - jQuery.migrateWarnings.push( msg + " [" + code + "]" ); - if ( console && console.warn && !jQuery.migrateMute ) { - console.warn( "JQMIGRATE: " + msg ); - if ( jQuery.migrateTrace && console.trace ) { - console.trace(); - } - } - } -} - -function migrateWarnProp( obj, prop, value, code, msg ) { - Object.defineProperty( obj, prop, { - configurable: true, - enumerable: true, - get: function() { - migrateWarn( code, msg ); - return value; - }, - set: function( newValue ) { - migrateWarn( code, msg ); - value = newValue; - } - } ); -} - -function migrateWarnFuncInternal( obj, prop, newFunc, code, msg ) { - var finalFunc, - origFunc = obj[ prop ]; - - obj[ prop ] = function() { - - // If `msg` not provided, do not warn; more sophisticated warnings - // logic is most likely embedded in `newFunc`, in that case here - // we just care about the logic choosing the proper implementation - // based on whether the patch is disabled or not. - if ( msg ) { - migrateWarn( code, msg ); - } - - // Since patches can be disabled & enabled dynamically, we - // need to decide which implementation to run on each invocation. - finalFunc = jQuery.migrateIsPatchEnabled( code ) ? - newFunc : - - // The function may not have existed originally so we need a fallback. - ( origFunc || jQuery.noop ); - - return finalFunc.apply( this, arguments ); - }; -} - -function migratePatchAndWarnFunc( obj, prop, newFunc, code, msg ) { - if ( !msg ) { - throw new Error( "No warning message provided" ); - } - return migrateWarnFuncInternal( obj, prop, newFunc, code, msg ); -} - -function migratePatchFunc( obj, prop, newFunc, code ) { - return migrateWarnFuncInternal( obj, prop, newFunc, code ); -} - -if ( window.document.compatMode === "BackCompat" ) { - - // jQuery has never supported or tested Quirks Mode - migrateWarn( "quirks", "jQuery is not compatible with Quirks Mode" ); -} - -var findProp, - class2type = {}, - oldInit = jQuery.fn.init, - oldFind = jQuery.find, - - rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, - rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g, - - // Require that the "whitespace run" starts from a non-whitespace - // to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position. - rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g; - -migratePatchFunc( jQuery.fn, "init", function( arg1 ) { - var args = Array.prototype.slice.call( arguments ); - - if ( jQuery.migrateIsPatchEnabled( "selector-empty-id" ) && - typeof arg1 === "string" && arg1 === "#" ) { - - // JQuery( "#" ) is a bogus ID selector, but it returned an empty set - // before jQuery 3.0 - migrateWarn( "selector-empty-id", "jQuery( '#' ) is not a valid selector" ); - args[ 0 ] = []; - } - - return oldInit.apply( this, args ); -}, "selector-empty-id" ); - -// This is already done in Core but the above patch will lose this assignment -// so we need to redo it. It doesn't matter whether the patch is enabled or not -// as the method is always going to be a Migrate-created wrapper. -jQuery.fn.init.prototype = jQuery.fn; - -migratePatchFunc( jQuery, "find", function( selector ) { - var args = Array.prototype.slice.call( arguments ); - - // Support: PhantomJS 1.x - // String#match fails to match when used with a //g RegExp, only on some strings - if ( typeof selector === "string" && rattrHashTest.test( selector ) ) { - - // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0 - // First see if qS thinks it's a valid selector, if so avoid a false positive - try { - window.document.querySelector( selector ); - } catch ( err1 ) { - - // Didn't *look* valid to qSA, warn and try quoting what we think is the value - selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) { - return "[" + attr + op + "\"" + value + "\"]"; - } ); - - // If the regexp *may* have created an invalid selector, don't update it - // Note that there may be false alarms if selector uses jQuery extensions - try { - window.document.querySelector( selector ); - migrateWarn( "selector-hash", - "Attribute selector with '#' must be quoted: " + args[ 0 ] ); - args[ 0 ] = selector; - } catch ( err2 ) { - migrateWarn( "selector-hash", - "Attribute selector with '#' was not fixed: " + args[ 0 ] ); - } - } - } - - return oldFind.apply( this, args ); -}, "selector-hash" ); - -// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML) -for ( findProp in oldFind ) { - if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) { - jQuery.find[ findProp ] = oldFind[ findProp ]; - } -} - -// The number of elements contained in the matched element set -migratePatchAndWarnFunc( jQuery.fn, "size", function() { - return this.length; -}, "size", -"jQuery.fn.size() is deprecated and removed; use the .length property" ); - -migratePatchAndWarnFunc( jQuery, "parseJSON", function() { - return JSON.parse.apply( null, arguments ); -}, "parseJSON", -"jQuery.parseJSON is deprecated; use JSON.parse" ); - -migratePatchAndWarnFunc( jQuery, "holdReady", jQuery.holdReady, - "holdReady", "jQuery.holdReady is deprecated" ); - -migratePatchAndWarnFunc( jQuery, "unique", jQuery.uniqueSort, - "unique", "jQuery.unique is deprecated; use jQuery.uniqueSort" ); - -// Now jQuery.expr.pseudos is the standard incantation -migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos, "expr-pre-pseudos", - "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" ); -migrateWarnProp( jQuery.expr, ":", jQuery.expr.pseudos, "expr-pre-pseudos", - "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos" ); - -// Prior to jQuery 3.1.1 there were internal refs so we don't warn there -if ( jQueryVersionSince( "3.1.1" ) ) { - migratePatchAndWarnFunc( jQuery, "trim", function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "$1" ); - }, "trim", - "jQuery.trim is deprecated; use String.prototype.trim" ); -} - -// Prior to jQuery 3.2 there were internal refs so we don't warn there -if ( jQueryVersionSince( "3.2.0" ) ) { - migratePatchAndWarnFunc( jQuery, "nodeName", function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, "nodeName", - "jQuery.nodeName is deprecated" ); - - migratePatchAndWarnFunc( jQuery, "isArray", Array.isArray, "isArray", - "jQuery.isArray is deprecated; use Array.isArray" - ); -} - -if ( jQueryVersionSince( "3.3.0" ) ) { - - migratePatchAndWarnFunc( jQuery, "isNumeric", function( obj ) { - - // As of jQuery 3.0, isNumeric is limited to - // strings and numbers (primitives or objects) - // that can be coerced to finite numbers (gh-2662) - var type = typeof obj; - return ( type === "number" || type === "string" ) && - - // parseFloat NaNs numeric-cast false positives ("") - // ...but misinterprets leading-number strings, e.g. hex literals ("0x...") - // subtraction forces infinities to NaN - !isNaN( obj - parseFloat( obj ) ); - }, "isNumeric", - "jQuery.isNumeric() is deprecated" - ); - - // Populate the class2type map - jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol". - split( " " ), - function( _, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); - } ); - - migratePatchAndWarnFunc( jQuery, "type", function( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ Object.prototype.toString.call( obj ) ] || "object" : - typeof obj; - }, "type", - "jQuery.type is deprecated" ); - - migratePatchAndWarnFunc( jQuery, "isFunction", - function( obj ) { - return typeof obj === "function"; - }, "isFunction", - "jQuery.isFunction() is deprecated" ); - - migratePatchAndWarnFunc( jQuery, "isWindow", - function( obj ) { - return obj != null && obj === obj.window; - }, "isWindow", - "jQuery.isWindow() is deprecated" - ); -} - -// Support jQuery slim which excludes the ajax module -if ( jQuery.ajax ) { - -var oldAjax = jQuery.ajax, - rjsonp = /(=)\?(?=&|$)|\?\?/; - -migratePatchFunc( jQuery, "ajax", function() { - var jQXHR = oldAjax.apply( this, arguments ); - - // Be sure we got a jQXHR (e.g., not sync) - if ( jQXHR.promise ) { - migratePatchAndWarnFunc( jQXHR, "success", jQXHR.done, "jqXHR-methods", - "jQXHR.success is deprecated and removed" ); - migratePatchAndWarnFunc( jQXHR, "error", jQXHR.fail, "jqXHR-methods", - "jQXHR.error is deprecated and removed" ); - migratePatchAndWarnFunc( jQXHR, "complete", jQXHR.always, "jqXHR-methods", - "jQXHR.complete is deprecated and removed" ); - } - - return jQXHR; -}, "jqXHR-methods" ); - -// Only trigger the logic in jQuery <4 as the JSON-to-JSONP auto-promotion -// behavior is gone in jQuery 4.0 and as it has security implications, we don't -// want to restore the legacy behavior. -if ( !jQueryVersionSince( "4.0.0" ) ) { - - // Register this prefilter before the jQuery one. Otherwise, a promoted - // request is transformed into one with the script dataType and we can't - // catch it anymore. - jQuery.ajaxPrefilter( "+json", function( s ) { - - // Warn if JSON-to-JSONP auto-promotion happens. - if ( s.jsonp !== false && ( rjsonp.test( s.url ) || - typeof s.data === "string" && - ( s.contentType || "" ) - .indexOf( "application/x-www-form-urlencoded" ) === 0 && - rjsonp.test( s.data ) - ) ) { - migrateWarn( "jsonp-promotion", "JSON-to-JSONP auto-promotion is deprecated" ); - } - } ); -} - -} - -var oldRemoveAttr = jQuery.fn.removeAttr, - oldToggleClass = jQuery.fn.toggleClass, - rmatchNonSpace = /\S+/g; - -migratePatchFunc( jQuery.fn, "removeAttr", function( name ) { - var self = this, - patchNeeded = false; - - jQuery.each( name.match( rmatchNonSpace ), function( _i, attr ) { - if ( jQuery.expr.match.bool.test( attr ) ) { - - // Only warn if at least a single node had the property set to - // something else than `false`. Otherwise, this Migrate patch - // doesn't influence the behavior and there's no need to set or warn. - self.each( function() { - if ( jQuery( this ).prop( attr ) !== false ) { - patchNeeded = true; - return false; - } - } ); - } - - if ( patchNeeded ) { - migrateWarn( "removeAttr-bool", - "jQuery.fn.removeAttr no longer sets boolean properties: " + attr ); - self.prop( attr, false ); - } - } ); - - return oldRemoveAttr.apply( this, arguments ); -}, "removeAttr-bool" ); - -migratePatchFunc( jQuery.fn, "toggleClass", function( state ) { - - // Only deprecating no-args or single boolean arg - if ( state !== undefined && typeof state !== "boolean" ) { - - return oldToggleClass.apply( this, arguments ); - } - - migrateWarn( "toggleClass-bool", "jQuery.fn.toggleClass( boolean ) is deprecated" ); - - // Toggle entire class name of each element - return this.each( function() { - var className = this.getAttribute && this.getAttribute( "class" ) || ""; - - if ( className ) { - jQuery.data( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || state === false ? - "" : - jQuery.data( this, "__className__" ) || "" - ); - } - } ); -}, "toggleClass-bool" ); - -function camelCase( string ) { - return string.replace( /-([a-z])/g, function( _, letter ) { - return letter.toUpperCase(); - } ); -} - -var origFnCss, internalCssNumber, - internalSwapCall = false, - ralphaStart = /^[a-z]/, - - // The regex visualized: - // - // /----------\ - // | | /-------\ - // | / Top \ | | | - // /--- Border ---+-| Right |-+---+- Width -+---\ - // | | Bottom | | - // | \ Left / | - // | | - // | /----------\ | - // | /-------------\ | | |- END - // | | | | / Top \ | | - // | | / Margin \ | | | Right | | | - // |---------+-| |-+---+-| Bottom |-+----| - // | \ Padding / \ Left / | - // BEGIN -| | - // | /---------\ | - // | | | | - // | | / Min \ | / Width \ | - // \--------------+-| |-+---| |---/ - // \ Max / \ Height / - rautoPx = /^(?:Border(?:Top|Right|Bottom|Left)?(?:Width|)|(?:Margin|Padding)?(?:Top|Right|Bottom|Left)?|(?:Min|Max)?(?:Width|Height))$/; - -// If this version of jQuery has .swap(), don't false-alarm on internal uses -if ( jQuery.swap ) { - jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) { - var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get; - - if ( oldHook ) { - jQuery.cssHooks[ name ].get = function() { - var ret; - - internalSwapCall = true; - ret = oldHook.apply( this, arguments ); - internalSwapCall = false; - return ret; - }; - } - } ); -} - -migratePatchFunc( jQuery, "swap", function( elem, options, callback, args ) { - var ret, name, - old = {}; - - if ( !internalSwapCall ) { - migrateWarn( "swap", "jQuery.swap() is undocumented and deprecated" ); - } - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}, "swap" ); - -if ( jQueryVersionSince( "3.4.0" ) && typeof Proxy !== "undefined" ) { - jQuery.cssProps = new Proxy( jQuery.cssProps || {}, { - set: function() { - migrateWarn( "cssProps", "jQuery.cssProps is deprecated" ); - return Reflect.set.apply( this, arguments ); - } - } ); -} - -// In jQuery >=4 where jQuery.cssNumber is missing fill it with the latest 3.x version: -// https://github.com/jquery/jquery/blob/3.6.0/src/css.js#L212-L233 -// This way, number values for the CSS properties below won't start triggering -// Migrate warnings when jQuery gets updated to >=4.0.0 (gh-438). -if ( jQueryVersionSince( "4.0.0" ) ) { - - // We need to keep this as a local variable as we need it internally - // in a `jQuery.fn.css` patch and this usage shouldn't warn. - internalCssNumber = { - animationIterationCount: true, - columnCount: true, - fillOpacity: true, - flexGrow: true, - flexShrink: true, - fontWeight: true, - gridArea: true, - gridColumn: true, - gridColumnEnd: true, - gridColumnStart: true, - gridRow: true, - gridRowEnd: true, - gridRowStart: true, - lineHeight: true, - opacity: true, - order: true, - orphans: true, - widows: true, - zIndex: true, - zoom: true - }; - - if ( typeof Proxy !== "undefined" ) { - jQuery.cssNumber = new Proxy( internalCssNumber, { - get: function() { - migrateWarn( "css-number", "jQuery.cssNumber is deprecated" ); - return Reflect.get.apply( this, arguments ); - }, - set: function() { - migrateWarn( "css-number", "jQuery.cssNumber is deprecated" ); - return Reflect.set.apply( this, arguments ); - } - } ); - } else { - - // Support: IE 9-11+ - // IE doesn't support proxies, but we still want to restore the legacy - // jQuery.cssNumber there. - jQuery.cssNumber = internalCssNumber; - } -} else { - - // Make `internalCssNumber` defined for jQuery <4 as well as it's needed - // in the `jQuery.fn.css` patch below. - internalCssNumber = jQuery.cssNumber; -} - -function isAutoPx( prop ) { - - // The first test is used to ensure that: - // 1. The prop starts with a lowercase letter (as we uppercase it for the second regex). - // 2. The prop is not empty. - return ralphaStart.test( prop ) && - rautoPx.test( prop[ 0 ].toUpperCase() + prop.slice( 1 ) ); -} - -origFnCss = jQuery.fn.css; - -migratePatchFunc( jQuery.fn, "css", function( name, value ) { - var camelName, - origThis = this; - - if ( name && typeof name === "object" && !Array.isArray( name ) ) { - jQuery.each( name, function( n, v ) { - jQuery.fn.css.call( origThis, n, v ); - } ); - return this; - } - - if ( typeof value === "number" ) { - camelName = camelCase( name ); - - // Use `internalCssNumber` to avoid triggering our warnings in this - // internal check. - if ( !isAutoPx( camelName ) && !internalCssNumber[ camelName ] ) { - migrateWarn( "css-number", - "Number-typed values are deprecated for jQuery.fn.css( \"" + - name + "\", value )" ); - } - } - - return origFnCss.apply( this, arguments ); -}, "css-number" ); - -var origData = jQuery.data; - -migratePatchFunc( jQuery, "data", function( elem, name, value ) { - var curData, sameKeys, key; - - // Name can be an object, and each entry in the object is meant to be set as data - if ( name && typeof name === "object" && arguments.length === 2 ) { - - curData = jQuery.hasData( elem ) && origData.call( this, elem ); - sameKeys = {}; - for ( key in name ) { - if ( key !== camelCase( key ) ) { - migrateWarn( "data-camelCase", - "jQuery.data() always sets/gets camelCased names: " + key ); - curData[ key ] = name[ key ]; - } else { - sameKeys[ key ] = name[ key ]; - } - } - - origData.call( this, elem, sameKeys ); - - return name; - } - - // If the name is transformed, look for the un-transformed name in the data object - if ( name && typeof name === "string" && name !== camelCase( name ) ) { - - curData = jQuery.hasData( elem ) && origData.call( this, elem ); - if ( curData && name in curData ) { - migrateWarn( "data-camelCase", - "jQuery.data() always sets/gets camelCased names: " + name ); - if ( arguments.length > 2 ) { - curData[ name ] = value; - } - return curData[ name ]; - } - } - - return origData.apply( this, arguments ); -}, "data-camelCase" ); - -// Support jQuery slim which excludes the effects module -if ( jQuery.fx ) { - -var intervalValue, intervalMsg, - oldTweenRun = jQuery.Tween.prototype.run, - linearEasing = function( pct ) { - return pct; - }; - -migratePatchFunc( jQuery.Tween.prototype, "run", function( ) { - if ( jQuery.easing[ this.easing ].length > 1 ) { - migrateWarn( - "easing-one-arg", - "'jQuery.easing." + this.easing.toString() + "' should use only one argument" - ); - - jQuery.easing[ this.easing ] = linearEasing; - } - - oldTweenRun.apply( this, arguments ); -}, "easing-one-arg" ); - -intervalValue = jQuery.fx.interval; -intervalMsg = "jQuery.fx.interval is deprecated"; - -// Support: IE9, Android <=4.4 -// Avoid false positives on browsers that lack rAF -// Don't warn if document is hidden, jQuery uses setTimeout (#292) -if ( window.requestAnimationFrame ) { - Object.defineProperty( jQuery.fx, "interval", { - configurable: true, - enumerable: true, - get: function() { - if ( !window.document.hidden ) { - migrateWarn( "fx-interval", intervalMsg ); - } - - // Only fallback to the default if patch is enabled - if ( !jQuery.migrateIsPatchEnabled( "fx-interval" ) ) { - return intervalValue; - } - return intervalValue === undefined ? 13 : intervalValue; - }, - set: function( newValue ) { - migrateWarn( "fx-interval", intervalMsg ); - intervalValue = newValue; - } - } ); -} - -} - -var oldLoad = jQuery.fn.load, - oldEventAdd = jQuery.event.add, - originalFix = jQuery.event.fix; - -jQuery.event.props = []; -jQuery.event.fixHooks = {}; - -migrateWarnProp( jQuery.event.props, "concat", jQuery.event.props.concat, - "event-old-patch", - "jQuery.event.props.concat() is deprecated and removed" ); - -migratePatchFunc( jQuery.event, "fix", function( originalEvent ) { - var event, - type = originalEvent.type, - fixHook = this.fixHooks[ type ], - props = jQuery.event.props; - - if ( props.length ) { - migrateWarn( "event-old-patch", - "jQuery.event.props are deprecated and removed: " + props.join() ); - while ( props.length ) { - jQuery.event.addProp( props.pop() ); - } - } - - if ( fixHook && !fixHook._migrated_ ) { - fixHook._migrated_ = true; - migrateWarn( "event-old-patch", - "jQuery.event.fixHooks are deprecated and removed: " + type ); - if ( ( props = fixHook.props ) && props.length ) { - while ( props.length ) { - jQuery.event.addProp( props.pop() ); - } - } - } - - event = originalFix.call( this, originalEvent ); - - return fixHook && fixHook.filter ? - fixHook.filter( event, originalEvent ) : - event; -}, "event-old-patch" ); - -migratePatchFunc( jQuery.event, "add", function( elem, types ) { - - // This misses the multiple-types case but that seems awfully rare - if ( elem === window && types === "load" && window.document.readyState === "complete" ) { - migrateWarn( "load-after-event", - "jQuery(window).on('load'...) called after load event occurred" ); - } - return oldEventAdd.apply( this, arguments ); -}, "load-after-event" ); - -jQuery.each( [ "load", "unload", "error" ], function( _, name ) { - - migratePatchFunc( jQuery.fn, name, function() { - var args = Array.prototype.slice.call( arguments, 0 ); - - // If this is an ajax load() the first arg should be the string URL; - // technically this could also be the "Anything" arg of the event .load() - // which just goes to show why this dumb signature has been deprecated! - // jQuery custom builds that exclude the Ajax module justifiably die here. - if ( name === "load" && typeof args[ 0 ] === "string" ) { - return oldLoad.apply( this, args ); - } - - migrateWarn( "shorthand-removed-v3", - "jQuery.fn." + name + "() is deprecated" ); - - args.splice( 0, 0, name ); - if ( arguments.length ) { - return this.on.apply( this, args ); - } - - // Use .triggerHandler here because: - // - load and unload events don't need to bubble, only applied to window or image - // - error event should not bubble to window, although it does pre-1.7 - // See http://bugs.jquery.com/ticket/11820 - this.triggerHandler.apply( this, args ); - return this; - }, "shorthand-removed-v3" ); - -} ); - -jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup contextmenu" ).split( " " ), - function( _i, name ) { - - // Handle event binding - migratePatchAndWarnFunc( jQuery.fn, name, function( data, fn ) { - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }, - "shorthand-deprecated-v3", - "jQuery.fn." + name + "() event shorthand is deprecated" ); -} ); - -// Trigger "ready" event only once, on document ready -jQuery( function() { - jQuery( window.document ).triggerHandler( "ready" ); -} ); - -jQuery.event.special.ready = { - setup: function() { - if ( this === window.document ) { - migrateWarn( "ready-event", "'ready' event is deprecated" ); - } - } -}; - -migratePatchAndWarnFunc( jQuery.fn, "bind", function( types, data, fn ) { - return this.on( types, null, data, fn ); -}, "pre-on-methods", "jQuery.fn.bind() is deprecated" ); -migratePatchAndWarnFunc( jQuery.fn, "unbind", function( types, fn ) { - return this.off( types, null, fn ); -}, "pre-on-methods", "jQuery.fn.unbind() is deprecated" ); -migratePatchAndWarnFunc( jQuery.fn, "delegate", function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); -}, "pre-on-methods", "jQuery.fn.delegate() is deprecated" ); -migratePatchAndWarnFunc( jQuery.fn, "undelegate", function( selector, types, fn ) { - return arguments.length === 1 ? - this.off( selector, "**" ) : - this.off( types, selector || "**", fn ); -}, "pre-on-methods", "jQuery.fn.undelegate() is deprecated" ); -migratePatchAndWarnFunc( jQuery.fn, "hover", function( fnOver, fnOut ) { - return this.on( "mouseenter", fnOver ).on( "mouseleave", fnOut || fnOver ); -}, "pre-on-methods", "jQuery.fn.hover() is deprecated" ); - -var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - makeMarkup = function( html ) { - var doc = window.document.implementation.createHTMLDocument( "" ); - doc.body.innerHTML = html; - return doc.body && doc.body.innerHTML; - }, - warnIfChanged = function( html ) { - var changed = html.replace( rxhtmlTag, "<$1>" ); - if ( changed !== html && makeMarkup( html ) !== makeMarkup( changed ) ) { - migrateWarn( "self-closed-tags", - "HTML tags must be properly nested and closed: " + html ); - } - }; - -/** - * Deprecated, please use `jQuery.migrateDisablePatches( "self-closed-tags" )` instead. - * @deprecated - */ -jQuery.UNSAFE_restoreLegacyHtmlPrefilter = function() { - jQuery.migrateEnablePatches( "self-closed-tags" ); -}; - -migratePatchFunc( jQuery, "htmlPrefilter", function( html ) { - warnIfChanged( html ); - return html.replace( rxhtmlTag, "<$1>" ); -}, "self-closed-tags" ); - -// This patch needs to be disabled by default as it re-introduces -// security issues (CVE-2020-11022, CVE-2020-11023). -jQuery.migrateDisablePatches( "self-closed-tags" ); - -var origOffset = jQuery.fn.offset; - -migratePatchFunc( jQuery.fn, "offset", function() { - var elem = this[ 0 ]; - - if ( elem && ( !elem.nodeType || !elem.getBoundingClientRect ) ) { - migrateWarn( "offset-valid-elem", "jQuery.fn.offset() requires a valid DOM element" ); - return arguments.length ? this : undefined; - } - - return origOffset.apply( this, arguments ); -}, "offset-valid-elem" ); - -// Support jQuery slim which excludes the ajax module -// The jQuery.param patch is about respecting `jQuery.ajaxSettings.traditional` -// so it doesn't make sense for the slim build. -if ( jQuery.ajax ) { - -var origParam = jQuery.param; - -migratePatchFunc( jQuery, "param", function( data, traditional ) { - var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - - if ( traditional === undefined && ajaxTraditional ) { - - migrateWarn( "param-ajax-traditional", - "jQuery.param() no longer uses jQuery.ajaxSettings.traditional" ); - traditional = ajaxTraditional; - } - - return origParam.call( this, data, traditional ); -}, "param-ajax-traditional" ); - -} - -migratePatchAndWarnFunc( jQuery.fn, "andSelf", jQuery.fn.addBack, "andSelf", - "jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()" ); - -// Support jQuery slim which excludes the deferred module in jQuery 4.0+ -if ( jQuery.Deferred ) { - -var oldDeferred = jQuery.Deferred, - tuples = [ - - // Action, add listener, callbacks, .then handlers, final state - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), "rejected" ], - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ) ] - ]; - -migratePatchFunc( jQuery, "Deferred", function( func ) { - var deferred = oldDeferred(), - promise = deferred.promise(); - - function newDeferredPipe( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = typeof fns[ i ] === "function" && fns[ i ]; - - // Deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && typeof returned.promise === "function" ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this === promise ? newDefer.promise() : this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - } - - migratePatchAndWarnFunc( deferred, "pipe", newDeferredPipe, "deferred-pipe", - "deferred.pipe() is deprecated" ); - migratePatchAndWarnFunc( promise, "pipe", newDeferredPipe, "deferred-pipe", - "deferred.pipe() is deprecated" ); - - if ( func ) { - func.call( deferred, deferred ); - } - - return deferred; -}, "deferred-pipe" ); - -// Preserve handler of uncaught exceptions in promise chains -jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook; - -} - -return jQuery; -} ); diff --git a/src/js/_enqueues/vendor/jquery/jquery-migrate.min.js b/src/js/_enqueues/vendor/jquery/jquery-migrate.min.js deleted file mode 100644 index 29a4939df3349..0000000000000 --- a/src/js/_enqueues/vendor/jquery/jquery-migrate.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery Migrate v3.4.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e,window)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery"),window):t(jQuery,window)}(function(s,n){"use strict";function e(e){return 0<=function(e,t){for(var r=/^(\d+)\.(\d+)\.(\d+)/,n=r.exec(e)||[],o=r.exec(t)||[],a=1;a<=3;a++){if(+o[a]<+n[a])return 1;if(+n[a]<+o[a])return-1}return 0}(s.fn.jquery,e)}s.migrateVersion="3.4.1";var t=Object.create(null);s.migrateDisablePatches=function(){for(var e=0;e\x20\t\r\n\f]*)[^>]*)\/>/gi;s.UNSAFE_restoreLegacyHtmlPrefilter=function(){s.migrateEnablePatches("self-closed-tags")},i(s,"htmlPrefilter",function(e){var t,r;return(r=(t=e).replace(F,"<$1>"))!==t&&T(t)!==T(r)&&u("self-closed-tags","HTML tags must be properly nested and closed: "+t),e.replace(F,"<$1>")},"self-closed-tags"),s.migrateDisablePatches("self-closed-tags");var D,W,_,I=s.fn.offset;return i(s.fn,"offset",function(){var e=this[0];return!e||e.nodeType&&e.getBoundingClientRect?I.apply(this,arguments):(u("offset-valid-elem","jQuery.fn.offset() requires a valid DOM element"),arguments.length?this:void 0)},"offset-valid-elem"),s.ajax&&(D=s.param,i(s,"param",function(e,t){var r=s.ajaxSettings&&s.ajaxSettings.traditional;return void 0===t&&r&&(u("param-ajax-traditional","jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),t=r),D.call(this,e,t)},"param-ajax-traditional")),c(s.fn,"andSelf",s.fn.addBack,"andSelf","jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),s.Deferred&&(W=s.Deferred,_=[["resolve","done",s.Callbacks("once memory"),s.Callbacks("once memory"),"resolved"],["reject","fail",s.Callbacks("once memory"),s.Callbacks("once memory"),"rejected"],["notify","progress",s.Callbacks("memory"),s.Callbacks("memory")]],i(s,"Deferred",function(e){var a=W(),i=a.promise();function t(){var o=arguments;return s.Deferred(function(n){s.each(_,function(e,t){var r="function"==typeof o[e]&&o[e];a[t[1]](function(){var e=r&&r.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[t[0]+"With"](this===i?n.promise():this,r?[e]:arguments)})}),o=null}).promise()}return c(a,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),c(i,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),e&&e.call(a,a),a},"deferred-pipe"),s.Deferred.exceptionHook=W.exceptionHook),s}); diff --git a/src/js/_enqueues/wp/api-request.js b/src/js/_enqueues/wp/api-request.js index 58ef53117903e..4762a37f658e2 100644 --- a/src/js/_enqueues/wp/api-request.js +++ b/src/js/_enqueues/wp/api-request.js @@ -1,3 +1,7 @@ +/** + * @output wp-includes/js/api-request.js + */ + /** * Thin jQuery.ajax wrapper for WP REST API requests. * @@ -11,17 +15,44 @@ * @since 4.9.0 * @since 5.6.0 Added overriding of the "PUT" and "DELETE" methods with "POST". * Added an "application/json" Accept header to all requests. - * @output wp-includes/js/api-request.js + * + * @param {JQueryStatic} $ The jQuery object. */ - ( function( $ ) { var wpApiSettings = window.wpApiSettings; + /** + * Makes an API request. + * + * @param {Object} options The options for the API request. + * @param {string} [options.url] The full URL for the request. + * @param {string} [options.path] The API path (e.g., 'wp/v2/posts'). Used if url is not provided. + * @param {string} [options.namespace] The API namespace (e.g., 'wp/v2'). Used with endpoint to build path. + * @param {string} [options.endpoint] The API endpoint (e.g., 'posts'). Used with namespace to build path. + * @param {string} [options.method] The HTTP method (GET, POST, PUT, DELETE, etc.). + * @param {Object} [options.data] The request data to send. + * @param {string} [options.data._wpnonce] Nonce for security. + * @param {Object} [options.headers] Custom headers to include in the request. + * @return {JQueryXHR} The jQuery XHR object. + */ function apiRequest( options ) { options = apiRequest.buildAjaxOptions( options ); return apiRequest.transport( options ); } + /** + * Builds the options for the jQuery.ajax request. + * + * @param {Object} options The options for the API request. + * @param {string} [options.url] The full URL for the request. + * @param {string} [options.path] The API path (e.g., 'wp/v2/posts'). Used if url is not provided. + * @param {string} [options.namespace] The API namespace (e.g., 'wp/v2'). Used with endpoint to build path. + * @param {string} [options.endpoint] The API endpoint (e.g., 'posts'). Used with namespace to build path. + * @param {string} [options.method] The HTTP method (GET, POST, PUT, DELETE, etc.). + * @param {Object} [options.data] The request data to send. + * @param {Object} [options.headers] Custom headers to include in the request. + * @return {Object} The options for the jQuery.ajax request. + */ apiRequest.buildAjaxOptions = function( options ) { var url = options.url; var path = options.path; diff --git a/src/js/_enqueues/wp/api.js b/src/js/_enqueues/wp/api.js index 9e68d77553c56..7f89de8830d1a 100644 --- a/src/js/_enqueues/wp/api.js +++ b/src/js/_enqueues/wp/api.js @@ -2,6 +2,12 @@ * @output wp-includes/js/wp-api.js */ +/** + * Initialize the WordPress REST API client. + * + * @param {Window} window The global window object. + * @param {undefined} undefined The undefined value. + */ (function( window, undefined ) { 'use strict'; @@ -31,6 +37,12 @@ })( window ); +/** + * Sets up the WordPress REST API client with utilities and Backbone model mixins for managing API resources. + * + * @param {Window} window The global window object. + * @param {undefined} undefined The undefined value. + */ (function( window, undefined ) { 'use strict'; @@ -47,9 +59,8 @@ /** * Determine model based on API route. * - * @param {string} route The API route. - * - * @return {Backbone Model} The model found at given route. Undefined if not found. + * @param {string} route The API route. + * @return {Backbone.Model|undefined} The model found at given route. Undefined if not found. */ wp.api.getModelByRoute = function( route ) { return _.find( wp.api.models, function( model ) { @@ -60,9 +71,8 @@ /** * Determine collection based on API route. * - * @param {string} route The API route. - * - * @return {Backbone Model} The collection found at given route. Undefined if not found. + * @param {string} route The API route. + * @return {Backbone.Collection|undefined} The collection found at given route. Undefined if not found. */ wp.api.getCollectionByRoute = function( route ) { return _.find( wp.api.collections, function( collection ) { @@ -100,7 +110,9 @@ /** * Parse date into ISO 8601 format. * - * @param {Date} date. + * @param {Date} date A date object to parse. + * + * @return {number} The timestamp of the date. */ wp.api.utils.parseISO8601 = function( date ) { var timestamp, struct, i, k, @@ -152,6 +164,9 @@ /** * Helper for capitalizing strings. + * + * @param {string} str The string to capitalize. + * @return {string} The capitalized string. */ wp.api.utils.capitalize = function( str ) { if ( _.isUndefined( str ) ) { @@ -163,6 +178,9 @@ /** * Helper function that capitalizes the first word and camel cases any words starting * after dashes, removing the dashes. + * + * @param {string} str The string to capitalize and camel case. + * @return {string} The capitalized and camel cased string. */ wp.api.utils.capitalizeAndCamelCaseDashes = function( str ) { if ( _.isUndefined( str ) ) { @@ -175,6 +193,9 @@ /** * Helper function to camel case the letter after dashes, removing the dashes. + * + * @param {string} str The string to camel case. + * @return {string} The camel cased string. */ wp.api.utils.camelCaseDashes = function( str ) { return str.replace( /-([a-z])/g, function( g ) { @@ -185,11 +206,12 @@ /** * Extract a route part based on negative index. * - * @param {string} route The endpoint route. - * @param {number} part The number of parts from the end of the route to retrieve. Default 1. + * @param {string} route The endpoint route. + * @param {number} part The number of parts from the end of the route to retrieve. Default 1. * Example route `/a/b/c`: part 1 is `c`, part 2 is `b`, part 3 is `a`. * @param {string} [versionString] Version string, defaults to `wp.api.versionString`. * @param {boolean} [reverse] Whether to reverse the order when extracting the route part. Optional, default false. + * @return {string} The route part. */ wp.api.utils.extractRoutePart = function( route, part, versionString, reverse ) { var routeParts; @@ -216,6 +238,7 @@ * Extract a parent name from a passed route. * * @param {string} route The route to extract a name from. + * @return {string} The parent name. */ wp.api.utils.extractParentName = function( route ) { var name, @@ -288,9 +311,10 @@ /** * Add mixins and helpers to models depending on their defaults. * - * @param {Backbone Model} model The model to attach helpers and mixins to. + * @param {Backbone.Model} model The model to attach helpers and mixins to. * @param {string} modelClassName The classname of the constructed model. - * @param {Object} loadingObjects An object containing the models and collections we are building. + * @param {Object} loadingObjects An object containing the models and collections we are building. + * @return {undefined} No return value. */ wp.api.utils.addMixinsAndHelpers = function( model, modelClassName, loadingObjects ) { @@ -320,9 +344,10 @@ * This helper function accepts a field and Date object. It converts the passed Date * to an ISO string and sets that on the model field. * - * @param {Date} date A JavaScript date object. WordPress expects dates in UTC. - * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified' - * or 'date_modified_gmt'. Optional, defaults to 'date'. + * @param {Date} date A JavaScript date object. WordPress expects dates in UTC. + * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified' + * or 'date_modified_gmt'. Optional, defaults to 'date'. + * @return {void|boolean} False if the field is not a parseable date field, true otherwise. */ setDate: function( date, field ) { var theField = field || 'date'; @@ -341,8 +366,9 @@ * WordPress returns 'date' and 'date_modified' in the timezone of the server as well as * UTC dates as 'date_gmt' and 'date_modified_gmt'. Draft posts do not include UTC dates. * - * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified' - * or 'date_modified_gmt'. Optional, defaults to 'date'. + * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified' + * or 'date_modified_gmt'. Optional, defaults to 'date'. + * @return {Date|boolean} A JavaScript Date object, or false if the field is not a parseable date field. */ getDate: function( field ) { var theField = field || 'date', @@ -494,6 +520,9 @@ /** * Set the model post parent. + * + * @param {wp.api.collections} collection The collection to set the parent post for. + * @param {number} postId The ID of the parent post. */ setHelperParentPost = function( collection, postId ) { @@ -590,6 +619,7 @@ * Accepts an array of tag slugs, or a Tags collection. * * @param {Array|Backbone.Collection} tags The tags to set on the post. + * @return {void|boolean} False if the tags parameter is a string, otherwise void. * */ setTags: function( tags ) { @@ -636,6 +666,7 @@ * Accepts a Tags collection. * * @param {Array|Backbone.Collection} tags The tags to set on the post. + * @return {void} No return value. * */ setTagsWithCollection: function( tags ) { @@ -674,7 +705,7 @@ * Accepts an array of category slugs, or a Categories collection. * * @param {Array|Backbone.Collection} categories The categories to set on the post. - * + * @return {void|boolean} False if the categories parameter is a string, otherwise void. */ setCategories: function( categories ) { var allCategories, newCategory, @@ -721,7 +752,7 @@ * Accepts Categories collection. * * @param {Array|Backbone.Collection} categories The categories to set on the post. - * + * @return {void} No return value. */ setCategoriesWithCollection: function( categories ) { @@ -805,6 +836,10 @@ // Suppress warning about parse function's unused "options" argument: /* jshint unused:false */ + +/** + * Creates the base Backbone model for WordPress REST API. + */ (function() { 'use strict'; @@ -823,21 +858,22 @@ initialize: function() { /** - * Types that don't support trashing require passing ?force=true to delete. - * - */ + * Types that don't support trashing require passing ?force=true to delete. + */ if ( -1 === _.indexOf( trashableTypes, this.name ) ) { this.requireForceForDelete = true; } }, /** - * Set nonce header before every Backbone sync. + * Sets a nonce header before every Backbone sync. * - * @param {string} method. - * @param {Backbone.Model} model. - * @param {{beforeSend}, *} options. - * @return {*}. + * @param {string} method The CRUD method ("create", "read", "update", or "delete") to be performed. + * @param {Backbone.Model} model The model to be synced. + * @param {Object} options Additional options for the sync. + * @param {Function} [options.beforeSend] A function to be called before sending the request. + * @param {Function} [options.complete] A function to be called when the request completes. + * @return {JQuery.Promise} A promise that resolves when the sync operation completes. */ sync: function( method, model, options ) { var beforeSend; @@ -888,6 +924,9 @@ /** * Save is only allowed when the PUT OR POST methods are available for the endpoint. + * @param {Object} attrs The attributes to save. + * @param {Object} options The options for the save operation. + * @return {boolean} True if the save was executed, false if not allowed. */ save: function( attrs, options ) { @@ -905,6 +944,8 @@ /** * Delete is only allowed when the DELETE method is available for the endpoint. + * @param {Object} [options] The options for the delete operation. + * @return {boolean} True if the delete was executed, false if not allowed. */ destroy: function( options ) { @@ -952,6 +993,9 @@ ); })(); +/** + * Creates the base Backbone collection for WordPress REST API. + */ ( function() { 'use strict'; @@ -967,6 +1011,8 @@ /** * Setup default state. + * @param {Backbone.Model[]} models The initial array of models. + * @param {Object} [options] The options for the collection. */ initialize: function( models, options ) { this.state = { @@ -983,14 +1029,18 @@ }, /** - * Extend Backbone.Collection.sync to add nonce and pagination support. + * Extends Backbone.Collection.sync to add nonce and pagination support. * - * Set nonce header before every Backbone sync. + * Sets a nonce header before every Backbone sync. * - * @param {string} method. - * @param {Backbone.Model} model. - * @param {{success}, *} options. - * @return {*}. + * @param {string} method The CRUD method ("create", "read", "update", or "delete") to be performed. + * @param {Backbone.Model} model The model to be synced. + * @param {Object} options Additional options for the sync. + * @param {Function} [options.beforeSend] A function to be called before sending the request. + * @param {Function} [options.success] A function to be called when the request succeeds. + * @param {Function} [options.complete] A function to be called when the request completes, regardless of success or failure. + * @param {Object} [options.data] Data to be sent with the request. + * @return {JQuery.Promise} A promise that resolves when the sync operation completes. */ sync: function( method, model, options ) { var beforeSend, success, @@ -1064,8 +1114,9 @@ /** * Fetches the next page of objects if a new page exists. * - * @param {data: {page}} options. - * @return {*}. + * @param {Object} [options] An object containing the page number to fetch. If not provided, the next page will be fetched. + * @param {number} [options.data.page] The page number to fetch. + * @return {JQuery.Promise} A promise that resolves when the fetch operation completes. */ more: function( options ) { options = options || {}; @@ -1091,7 +1142,7 @@ /** * Returns true if there are more pages of objects available. * - * @return {null|boolean} + * @return {null|boolean} Returns null if the current page, total pages, or total objects are unknown. Otherwise returns true if there are more pages available. */ hasMore: function() { if ( null === this.state.totalPages || @@ -1107,6 +1158,9 @@ } )(); +/** + * Constructs Backbone models and collections from the WordPress REST API schema. + */ ( function() { 'use strict'; @@ -1498,11 +1552,12 @@ /** * Initialize the wp-api, optionally passing the API root. * - * @param {Object} [args] - * @param {string} [args.nonce] The nonce. Optional, defaults to wpApiSettings.nonce. - * @param {string} [args.apiRoot] The api root. Optional, defaults to wpApiSettings.root. + * @param {Object} [args] The arguments for initializing the wp-api. + * @param {string} [args.nonce] The nonce. Optional, defaults to wpApiSettings.nonce. + * @param {string} [args.apiRoot] The api root. Optional, defaults to wpApiSettings.root. * @param {string} [args.versionString] The version string. Optional, defaults to wpApiSettings.root. - * @param {Object} [args.schema] The schema. Optional, will be fetched from API if not provided. + * @param {Object} [args.schema] The schema. Optional, will be fetched from API if not provided. + * @return {Promise} A promise that resolves with the endpoint once it is ready. */ wp.api.init = function( args ) { var endpoint, attributes = {}, deferred, promise; diff --git a/src/js/_enqueues/wp/autosave.js b/src/js/_enqueues/wp/autosave.js index 9f46c3161483e..4ad4e7fe56133 100644 --- a/src/js/_enqueues/wp/autosave.js +++ b/src/js/_enqueues/wp/autosave.js @@ -13,8 +13,8 @@ window.autosave = function() { * * @since 3.9.0 * - * @param {jQuery} $ jQuery object. - * @param {window} The window object. + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} window The window object. * */ ( function( $, window ) { @@ -243,6 +243,7 @@ window.autosave = function() { * Sets the storage for this blog. Confirms that the data was saved * successfully. * + * @param {Object} stored_obj The storage object to set. * @since 3.9.0 * * @return {boolean} True if the data was saved successfully, false if it wasn't saved. @@ -448,6 +449,12 @@ window.autosave = function() { * @return {boolean} True if the strings are the same. */ function compare( str1, str2 ) { + /** + * Removes all whitespace characters from a string. + * + * @param {string} string The string to remove whitespace from. + * @return {string} The string without whitespace characters. + */ function removeSpaces( string ) { return string.toString().replace(/[\x20\t\r\n\f]+/g, ''); } diff --git a/src/js/_enqueues/wp/backbone.js b/src/js/_enqueues/wp/backbone.js index 4fd194f5737d5..2c8e62d23cca3 100644 --- a/src/js/_enqueues/wp/backbone.js +++ b/src/js/_enqueues/wp/backbone.js @@ -284,7 +284,7 @@ window.wp = window.wp || {}; * @since 3.5.0 * * @return {wp.Backbone.Subviews} The current Subviews instance. - */ + */ render: function() { var options = { ready: this._isReady() @@ -314,7 +314,7 @@ window.wp = window.wp || {}; * the master views' parent. * * @return {wp.Backbone.Subviews} The current Subviews instance. - */ + */ remove: function( options ) { if ( ! options || ! options.silent ) { if ( this.parent && this.parent.views ) @@ -338,7 +338,7 @@ window.wp = window.wp || {}; * @since 3.5.0 * * @param {string} $target Selector where to put the elements. - * @param {*} els HTML or elements to put into the selector's HTML. + * @param {*} els HTML or elements to put into the selector's HTML. * * @return {wp.Backbone.Subviews} The current Subviews instance. */ diff --git a/src/js/_enqueues/wp/code-editor.js b/src/js/_enqueues/wp/code-editor.js index ed8be9d6a5580..18451a0a7881e 100644 --- a/src/js/_enqueues/wp/code-editor.js +++ b/src/js/_enqueues/wp/code-editor.js @@ -4,8 +4,6 @@ /* global console */ -/* eslint-env es2020 */ - if ( 'undefined' === typeof window.wp ) { /** * @namespace wp @@ -20,106 +18,106 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { } /** - * @typedef {object} CodeMirrorState - * @property {boolean} [completionActive] - Whether completion is active. - * @property {boolean} [focused] - Whether the editor is focused. + * @typedef {Object} CodeMirrorState + * @property {boolean} [completionActive] Whether completion is active. + * @property {boolean} [focused] Whether the editor is focused. */ /** * @typedef {import('codemirror').EditorFromTextArea & { - * options: import('codemirror').EditorConfiguration, - * performLint?: () => void, - * showHint?: (options: import('codemirror').ShowHintOptions) => void, - * state: CodeMirrorState + * options: import('codemirror').EditorConfiguration, + * performLint?: () => void, + * showHint?: (options: import('codemirror').ShowHintOptions) => void, + * state: CodeMirrorState * }} CodeMirrorEditor */ /** - * @typedef {object} LintAnnotation - * @property {string} message - Message. - * @property {'error'|'warning'} severity - Severity. - * @property {import('codemirror').Position} from - From position. - * @property {import('codemirror').Position} to - To position. + * @typedef {Object} LintAnnotation + * @property {string} message Message. + * @property {'error'|'warning'} severity Severity. + * @property {import('codemirror').Position} from From position. + * @property {import('codemirror').Position} to To position. */ /** - * @typedef {object} CodeMirrorTokenState - * @property {object} [htmlState] - HTML state. - * @property {string} [htmlState.tagName] - Tag name. - * @property {CodeMirrorTokenState} [curState] - Current state. + * @typedef {Object} CodeMirrorTokenState + * @property {Object} [htmlState] HTML state. + * @property {string} [htmlState.tagName] Tag name. + * @property {CodeMirrorTokenState} [curState] Current state. */ /** * @typedef {import('codemirror').EditorConfiguration & { - * lint?: boolean | CombinedLintOptions, - * autoCloseBrackets?: boolean, - * matchBrackets?: boolean, - * continueComments?: boolean, - * styleActiveLine?: boolean + * lint?: boolean | CombinedLintOptions, + * autoCloseBrackets?: boolean, + * matchBrackets?: boolean, + * continueComments?: boolean, + * styleActiveLine?: boolean * }} CodeMirrorSettings */ /** - * @typedef {object} CSSLintRules - * @property {boolean} [errors] - Errors. - * @property {boolean} [box-model] - Box model rules. - * @property {boolean} [display-property-grouping] - Display property grouping rules. - * @property {boolean} [duplicate-properties] - Duplicate properties rules. - * @property {boolean} [known-properties] - Known properties rules. - * @property {boolean} [outline-none] - Outline none rules. + * @typedef {Object} CSSLintRules + * @property {boolean} [errors] Errors. + * @property {boolean} [box-model] Box model rules. + * @property {boolean} [display-property-grouping] Display property grouping rules. + * @property {boolean} [duplicate-properties] Duplicate properties rules. + * @property {boolean} [known-properties] Known properties rules. + * @property {boolean} [outline-none] Outline none rules. */ /** - * @typedef {object} JSHintRules - * @property {number} [esversion] - ECMAScript version. - * @property {boolean} [module] - Whether to use modules. - * @property {boolean} [boss] - Whether to allow assignments in control expressions. - * @property {boolean} [curly] - Whether to require curly braces. - * @property {boolean} [eqeqeq] - Whether to require === and !==. - * @property {boolean} [eqnull] - Whether to allow == null. - * @property {boolean} [expr] - Whether to allow expressions. - * @property {boolean} [immed] - Whether to require immediate function invocation. - * @property {boolean} [noarg] - Whether to prohibit arguments.caller/callee. - * @property {boolean} [nonbsp] - Whether to prohibit non-breaking spaces. - * @property {string} [quotmark] - Quote mark preference. - * @property {boolean} [undef] - Whether to prohibit undefined variables. - * @property {boolean} [unused] - Whether to prohibit unused variables. - * @property {boolean} [browser] - Whether to enable browser globals. - * @property {Record} [globals] - Global variables. + * @typedef {Object} JSHintRules + * @property {number} [esversion] ECMAScript version. + * @property {boolean} [module] Whether to use modules. + * @property {boolean} [boss] Whether to allow assignments in control expressions. + * @property {boolean} [curly] Whether to require curly braces. + * @property {boolean} [eqeqeq] Whether to require === and !==. + * @property {boolean} [eqnull] Whether to allow == null. + * @property {boolean} [expr] Whether to allow expressions. + * @property {boolean} [immed] Whether to require immediate function invocation. + * @property {boolean} [noarg] Whether to prohibit arguments.caller/callee. + * @property {boolean} [nonbsp] Whether to prohibit non-breaking spaces. + * @property {string} [quotmark] Quote mark preference. + * @property {boolean} [undef] Whether to prohibit undefined variables. + * @property {boolean} [unused] Whether to prohibit unused variables. + * @property {boolean} [browser] Whether to enable browser globals. + * @property {Record} [globals] Global variables. */ /** - * @typedef {object} HTMLHintRules - * @property {boolean} [tagname-lowercase] - Tag name lowercase rules. - * @property {boolean} [attr-lowercase] - Attribute lowercase rules. - * @property {boolean} [attr-value-double-quotes] - Attribute value double quotes rules. - * @property {boolean} [doctype-first] - Doctype first rules. - * @property {boolean} [tag-pair] - Tag pair rules. - * @property {boolean} [spec-char-escape] - Spec char escape rules. - * @property {boolean} [id-unique] - ID unique rules. - * @property {boolean} [src-not-empty] - Src not empty rules. - * @property {boolean} [attr-no-duplication] - Attribute no duplication rules. - * @property {boolean} [alt-require] - Alt require rules. - * @property {string} [space-tab-mixed-disabled] - Space tab mixed disabled rules. - * @property {boolean} [attr-unsafe-chars] - Attribute unsafe chars rules. - * @property {JSHintRules} [jshint] - JSHint rules. - * @property {CSSLintRules} [csslint] - CSSLint rules. + * @typedef {Object} HTMLHintRules + * @property {boolean} [tagname-lowercase] Tag name lowercase rules. + * @property {boolean} [attr-lowercase] Attribute lowercase rules. + * @property {boolean} [attr-value-double-quotes] Attribute value double quotes rules. + * @property {boolean} [doctype-first] Doctype first rules. + * @property {boolean} [tag-pair] Tag pair rules. + * @property {boolean} [spec-char-escape] Spec char escape rules. + * @property {boolean} [id-unique] ID unique rules. + * @property {boolean} [src-not-empty] Src not empty rules. + * @property {boolean} [attr-no-duplication] Attribute no duplication rules. + * @property {boolean} [alt-require] Alt require rules. + * @property {string} [space-tab-mixed-disabled] Space tab mixed disabled rules. + * @property {boolean} [attr-unsafe-chars] Attribute unsafe chars rules. + * @property {JSHintRules} [jshint] JSHint rules. + * @property {CSSLintRules} [csslint] CSSLint rules. */ /** * Settings for the code editor. * - * @typedef {object} CodeEditorSettings + * @typedef {Object} CodeEditorSettings * - * @property {CodeMirrorSettings} [codemirror] - CodeMirror settings. - * @property {CSSLintRules} [csslint] - CSSLint rules. - * @property {JSHintRules} [jshint] - JSHint rules. - * @property {HTMLHintRules} [htmlhint] - HTMLHint rules. + * @property {CodeMirrorSettings} [codemirror] CodeMirror settings. + * @property {CSSLintRules} [csslint] CSSLint rules. + * @property {JSHintRules} [jshint] JSHint rules. + * @property {HTMLHintRules} [htmlhint] HTMLHint rules. * - * @property {(codemirror: CodeMirrorEditor, event: KeyboardEvent|JQuery.KeyDownEvent) => void} [onTabNext] - Callback to handle tabbing to the next tabbable element. - * @property {(codemirror: CodeMirrorEditor, event: KeyboardEvent|JQuery.KeyDownEvent) => void} [onTabPrevious] - Callback to handle tabbing to the previous tabbable element. - * @property {(errorAnnotations: LintAnnotation[], annotations: LintAnnotation[], annotationsSorted: LintAnnotation[], cm: CodeMirrorEditor) => void} [onChangeLintingErrors] - Callback for when the linting errors have changed. - * @property {(errorAnnotations: LintAnnotation[], editor: CodeMirrorEditor) => void} [onUpdateErrorNotice] - Callback for when error notice should be displayed. + * @property {(codemirror: CodeMirrorEditor, event: KeyboardEvent|JQuery.KeyDownEvent) => void} [onTabNext] Callback to handle tabbing to the next tabbable element. + * @property {(codemirror: CodeMirrorEditor, event: KeyboardEvent|JQuery.KeyDownEvent) => void} [onTabPrevious] Callback to handle tabbing to the previous tabbable element. + * @property {(errorAnnotations: LintAnnotation[], annotations: LintAnnotation[], annotationsSorted: LintAnnotation[], cm: CodeMirrorEditor) => void} [onChangeLintingErrors] Callback for when the linting errors have changed. + * @property {(errorAnnotations: LintAnnotation[], editor: CodeMirrorEditor) => void} [onUpdateErrorNotice] Callback for when error notice should be displayed. */ /** @@ -127,24 +125,23 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { */ /** - * @typedef {object} CodeEditorInstance - * @property {CodeEditorSettings} settings - The code editor settings. - * @property {CodeMirrorEditor} codemirror - The CodeMirror instance. - * @property {() => void} updateErrorNotice - Force update the error notice. + * @typedef {Object} CodeEditorInstance + * @property {CodeEditorSettings} settings The code editor settings. + * @property {CodeMirrorEditor} codemirror The CodeMirror instance. + * @property {() => void} updateErrorNotice Force update the error notice. */ /** - * @typedef {object} WpCodeEditor - * @property {CodeEditorSettings} defaultSettings - Default settings. - * @property {(textarea: string|JQuery|Element, settings?: CodeEditorSettings) => CodeEditorInstance} initialize - Initialize. + * @typedef {Object} WpCodeEditor + * @property {CodeEditorSettings} defaultSettings Default settings. + * @property {(textarea: string|JQuery|Element, settings?: CodeEditorSettings) => CodeEditorInstance} initialize Initialize. */ /** - * @param {JQueryStatic} $ - jQuery. - * @param {Object & { - * codeEditor: WpCodeEditor, - * CodeMirror: typeof import('codemirror'), - * }} wp - WordPress namespace. + * Handles the Code Editor (CodeMirror) functionality. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {wp} wp The WordPress global object. */ ( function( $, wp ) { 'use strict'; @@ -167,13 +164,13 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { }; /** - * Configure linting. + * Configures linting. * - * @param {CodeEditorSettings} settings - Code editor settings. + * @param {CodeEditorSettings} settings Code editor settings. * * @return {LintingController} Linting controller. */ - function configureLinting( settings ) { // eslint-disable-line complexity + function configureLinting( settings ) { /** @type {LintAnnotation[]} */ let currentErrorAnnotations = []; @@ -183,7 +180,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { /** * Call the onUpdateErrorNotice if there are new errors to show. * - * @param {import('codemirror').Editor} editor - Editor. + * @param {import('codemirror').Editor} editor Editor. * @return {void} */ function updateErrorNotice( editor ) { @@ -194,11 +191,11 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { } /** - * Get lint options. + * Gets the lint options. * * @return {CombinedLintOptions|false} Lint options. */ - function getLintOptions() { // eslint-disable-line complexity + function getLintOptions() { /** @type {CombinedLintOptions | boolean} */ let options = settings.codemirror?.lint ?? false; @@ -238,9 +235,11 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { // Wrap the onUpdateLinting CodeMirror event to route to onChangeLintingErrors and onUpdateErrorNotice. linterOptions.onUpdateLinting = (function( onUpdateLintingOverridden ) { /** - * @param {LintAnnotation[]} annotations - Annotations. - * @param {LintAnnotation[]} annotationsSorted - Sorted annotations. - * @param {CodeMirrorEditor} cm - Editor. + * Wraps the onUpdateLinting event to filter errors, detect state changes, and manage error notice visibility. + * + * @param {LintAnnotation[]} annotations Annotations. + * @param {LintAnnotation[]} annotationsSorted Sorted annotations. + * @param {CodeMirrorEditor} cm Editor. */ return function( annotations, annotationsSorted, cm ) { const errorAnnotations = annotations.filter( function( annotation ) { @@ -280,7 +279,9 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { return { getLintOptions, /** - * @param {CodeMirrorEditor} editor - Editor instance. + * Initializes the CodeMirror editor. + * + * @param {CodeMirrorEditor} editor Editor instance. * @return {void} */ init: function( editor ) { @@ -348,7 +349,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { } ); }, /** - * @param {CodeMirrorEditor} editor - Editor instance. + * @param {CodeMirrorEditor} editor Editor instance. * @return {void} */ updateErrorNotice, @@ -358,8 +359,8 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { /** * Configure tabbing. * - * @param {CodeMirrorEditor} codemirror - Editor. - * @param {CodeEditorSettings} settings - Code editor settings. + * @param {CodeMirrorEditor} codemirror Editor. + * @param {CodeEditorSettings} settings Code editor settings. * * @return {void} */ @@ -397,10 +398,10 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { } /** - * @typedef {object} LintingController - * @property {() => CombinedLintOptions|false} getLintOptions - Get lint options. - * @property {(editor: CodeMirrorEditor) => void} init - Initialize. - * @property {(editor: import('codemirror').Editor) => void} updateErrorNotice - Update error notice. + * @typedef {Object} LintingController + * @property {() => CombinedLintOptions|false} getLintOptions Get lint options. + * @property {(editor: CodeMirrorEditor) => void} init Initialize. + * @property {(editor: import('codemirror').Editor) => void} updateErrorNotice Update error notice. */ /** @@ -408,8 +409,8 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { * * @since 4.9.0 * - * @param {string|JQuery|HTMLElement} textarea - The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. - * @param {CodeEditorSettings} [settings] - Settings to override defaults. + * @param {string|JQuery|HTMLElement} textarea The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. + * @param {CodeEditorSettings} [settings] Settings to override defaults. * * @return {CodeEditorInstance} Instance. */ diff --git a/src/js/_enqueues/wp/custom-header.js b/src/js/_enqueues/wp/custom-header.js index ae43f56174f23..fccab2565b164 100644 --- a/src/js/_enqueues/wp/custom-header.js +++ b/src/js/_enqueues/wp/custom-header.js @@ -19,7 +19,7 @@ * Trigger an event. * * @param {Element} target HTML element to dispatch the event on. - * @param {string} name Event name. + * @param {string} name Event name. */ function trigger( target, name ) { var evt; @@ -76,7 +76,7 @@ * * Themes and plugins can override this method to change the criteria. * - * @return {boolean} + * @return {boolean} True if the environment supports video, false otherwise. */ supportsVideo: function() { // Don't load video on small screens. @todo Consider bandwidth and other factors. @@ -163,7 +163,7 @@ * Whether the video is paused. * * @abstract - * @return {boolean} + * @return {boolean} True if the video is paused, false otherwise. */ isPaused: function() {}, @@ -217,8 +217,7 @@ * Whether the handler can process a video. * * @abstract - * @param {Object} settings Video settings. - * @return {boolean} + * @return {boolean} True if the handler can process a video, false otherwise. Default is false. */ test: function() { return false; @@ -240,11 +239,16 @@ * @memberOf wp * * @param {Object} protoProps Properties to apply to the prototype. - * @return CustomHandler The subclass. + * @return {Function} Custom handler constructor. */ BaseHandler.extend = function( protoProps ) { var prop; + /** + * Creates a custom handler instance. + * + * @return {CustomHandler} A custom handler instance, when called with new. + */ function CustomHandler() { var result = BaseHandler.apply( this, arguments ); return result; @@ -272,7 +276,7 @@ * Whether the native handler supports a video. * * @param {Object} settings Video settings. - * @return {boolean} + * @return {boolean} True if the native handler supports a video, false otherwise. */ test: function( settings ) { var video = document.createElement( 'video' ); @@ -314,7 +318,7 @@ /** * Whether the video is paused. * - * @return {boolean} + * @return {boolean} True if the video is paused, false otherwise. */ isPaused: function() { return this.video.paused; @@ -347,7 +351,7 @@ * Whether the handler supports a video. * * @param {Object} settings Video settings. - * @return {boolean} + * @return {boolean} True if the handler supports a video, false otherwise. */ test: function( settings ) { return 'video/x-youtube' === settings.mimeType; @@ -423,7 +427,7 @@ /** * Whether the video is paused. * - * @return {boolean} + * @return {boolean} True if the video is paused, false otherwise. */ isPaused: function() { return YT.PlayerState.PAUSED === this.player.getPlayerState(); diff --git a/src/js/_enqueues/wp/customize/base.js b/src/js/_enqueues/wp/customize/base.js index 4afaa945571f0..44e23ae35740d 100644 --- a/src/js/_enqueues/wp/customize/base.js +++ b/src/js/_enqueues/wp/customize/base.js @@ -5,9 +5,14 @@ /** @namespace wp */ window.wp = window.wp || {}; -(function( exports, $ ){ - var api = {}, ctor, inherits, - slice = Array.prototype.slice; +/** + * The WordPress Customizer API. + * + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. + */ +(function( wp, $ ){ + var api = {}, ctor, inherits; // Shared empty constructor function to aid in prototype-chain creation. ctor = function() {}; @@ -17,10 +22,10 @@ window.wp = window.wp || {}; * Similar to `goog.inherits`, but uses a hash of prototype properties and * class properties to be extended. * - * @param object parent Parent class constructor to inherit from. - * @param object protoProps Properties to apply to the prototype for use as class instance properties. - * @param object staticProps Properties to apply directly to the class constructor. - * @return child The subclassed constructor. + * @param {Object} parent Parent class constructor to inherit from. + * @param {Object} [protoProps] Properties to apply to the prototype for use as class instance properties. + * @param {Object} [staticProps] Properties to apply directly to the class constructor. + * @return {Function} The subclassed constructor. */ inherits = function( parent, protoProps, staticProps ) { var child; @@ -33,14 +38,14 @@ window.wp = window.wp || {}; if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) { child = protoProps.constructor; } else { - child = function() { + child = function( ...args ) { /* * Storing the result `super()` before returning the value * prevents a bug in Opera where, if the constructor returns * a function, Opera will reject the return value in favor of * the original object. This causes all sorts of trouble. */ - var result = parent.apply( this, arguments ); + var result = parent.apply( this, args ); return result; }; } @@ -75,13 +80,28 @@ window.wp = window.wp || {}; /** * Base class for object inheritance. + * + * The arguments are normally passed straight through to the class's + * initialize method. As a special case, when the first argument is + * api.Class.applicator, the second argument is used as the array of + * arguments for initialize and the third is used to extend the instance. + * This allows a class to be constructed from an argument list that is only + * known at runtime. See {@link wp.customize.Values#create}. + * + * @param {...*} args Arguments for the class's initialize method. Or + * api.Class.applicator, followed by the array of + * arguments for the initialize method, followed by an + * optional object of properties to extend the instance + * with. + * @return {Object|Function} The instance of the class, which is a function when the class + * defines an instance method, so that the instance is callable. */ - api.Class = function( applicator, argsArray, options ) { - var magic, args = arguments; + api.Class = function( ...args ) { + var magic; - if ( applicator && argsArray && api.Class.applicator === applicator ) { - args = argsArray; - $.extend( this, options || {} ); + if ( args[0] && args[1] && api.Class.applicator === args[0] ) { + $.extend( this, args[2] || {} ); + args = args[1]; } magic = this; @@ -94,8 +114,8 @@ window.wp = window.wp || {}; * It is also an object that has properties and methods inside it. */ if ( this.instance ) { - magic = function() { - return magic.instance.apply( magic, arguments ); + magic = function( ...instanceArgs ) { + return magic.instance.apply( magic, instanceArgs ); }; $.extend( magic, this ); @@ -108,9 +128,9 @@ window.wp = window.wp || {}; /** * Creates a subclass of the class. * - * @param object protoProps Properties to apply to the prototype. - * @param object staticProps Properties to apply directly to the class. - * @return child The subclass. + * @param {Object} [protoProps] Properties to apply to the prototype. + * @param {Object} [staticProps] Properties to apply directly to the class. + * @return {Function} The subclass. */ api.Class.extend = function( protoProps, staticProps ) { var child = inherits( this, protoProps, staticProps ); @@ -155,23 +175,44 @@ window.wp = window.wp || {}; * Used as a mixin. */ api.Events = { - trigger: function( id ) { + /** + * Trigger an event, invoking all of the callbacks bound to it. + * + * @param {string} id ID of the event to trigger. + * @param {...*} [args] Zero or more arguments to pass to the bound callbacks. + * @return {Object} The instance the mixin is applied to. + */ + trigger: function( id, ...args ) { if ( this.topics && this.topics[ id ] ) { - this.topics[ id ].fireWith( this, slice.call( arguments, 1 ) ); + this.topics[ id ].fireWith( this, args ); } return this; }, - bind: function( id ) { + /** + * Bind one or more callbacks to an event. + * + * @param {string} id ID of the event to bind to. + * @param {...Function} callbacks A function, or multiple functions, to add to the callback stack. + * @return {Object} The instance the mixin is applied to. + */ + bind: function( id, ...callbacks ) { this.topics = this.topics || {}; this.topics[ id ] = this.topics[ id ] || $.Callbacks(); - this.topics[ id ].add.apply( this.topics[ id ], slice.call( arguments, 1 ) ); + this.topics[ id ].add.apply( this.topics[ id ], callbacks ); return this; }, - unbind: function( id ) { + /** + * Unbind one or more previously bound callbacks from an event. + * + * @param {string} id ID of the event to unbind from. + * @param {...Function} callbacks A function, or multiple functions, to remove from the callback stack. + * @return {Object} The instance the mixin is applied to. + */ + unbind: function( id, ...callbacks ) { if ( this.topics && this.topics[ id ] ) { - this.topics[ id ].remove.apply( this.topics[ id ], slice.call( arguments, 1 ) ); + this.topics[ id ].remove.apply( this.topics[ id ], callbacks ); } return this; } @@ -183,12 +224,15 @@ window.wp = window.wp || {}; * @memberOf wp.customize * @alias wp.customize.Value * - * @constructor + * @class + * @augments wp.customize.Class */ api.Value = api.Class.extend(/** @lends wp.customize.Value.prototype */{ /** - * @param {mixed} initial The initial value. - * @param {Object} options + * Initializes the Value instance and configures callbacks and options. + * + * @param {*} initial The initial value. + * @param {Object} [options] Options to extend the instance with. */ initialize: function( initial, options ) { this._value = initial; // @todo Potentially change this to a this.set() call. @@ -204,14 +248,14 @@ window.wp = window.wp || {}; * Magic. Returns a function that will become the instance. * Set to null to prevent the instance from extending a function. */ - instance: function() { - return arguments.length ? this.set.apply( this, arguments ) : this.get(); + instance: function( ...args ) { + return args.length ? this.set.apply( this, args ) : this.get(); }, /** * Get the value. * - * @return {mixed} + * @return {*} The value. */ get: function() { return this._value; @@ -220,12 +264,14 @@ window.wp = window.wp || {}; /** * Set the value and trigger all bound callbacks. * - * @param {Object} to New value. + * @param {*} to New value. + * @param {...*} [args] Zero or more additional arguments to pass to the setter. + * @return {wp.customize.Value} The instance of the Value. */ - set: function( to ) { + set: function( to, ...args ) { var from = this._value; - to = this._setter.apply( this, arguments ); + to = this._setter( to, ...args ); to = this.validate( to ); // Bail if the sanitized value is null or unchanged. @@ -267,51 +313,81 @@ window.wp = window.wp || {}; /** * Bind a function to be invoked whenever the value changes. * - * @param {...Function} A function, or multiple functions, to add to the callback stack. + * @param {...Function} callbacks A function, or multiple functions, to add to the callback stack. + * @return {wp.customize.Value} The instance of the Value. */ - bind: function() { - this.callbacks.add.apply( this.callbacks, arguments ); + bind: function( ...callbacks ) { + this.callbacks.add.apply( this.callbacks, callbacks ); return this; }, /** * Unbind a previously bound function. * - * @param {...Function} A function, or multiple functions, to remove from the callback stack. + * @param {...Function} callbacks A function, or multiple functions, to remove from the callback stack. + * @return {wp.customize.Value} The instance of the Value. */ - unbind: function() { - this.callbacks.remove.apply( this.callbacks, arguments ); + unbind: function( ...callbacks ) { + this.callbacks.remove.apply( this.callbacks, callbacks ); return this; }, - link: function() { // values* + /** + * Update this value whenever one or more other values change. + * + * Note that this is one-directional: this value follows the supplied + * values, not the other way around. Use sync() to link in both + * directions. + * + * @param {...wp.customize.Value} values A value, or multiple values, for this value to follow. + * @return {wp.customize.Value} The instance of the Value. + */ + link: function( ...values ) { var set = this.set; - $.each( arguments, function() { + $.each( values, function() { this.bind( set ); }); return this; }, - unlink: function() { // values* + /** + * Stop updating this value when one or more other values change. + * + * @param {...wp.customize.Value} values A value, or multiple values, for this value to stop following. + * @return {wp.customize.Value} The instance of the Value. + */ + unlink: function( ...values ) { var set = this.set; - $.each( arguments, function() { + $.each( values, function() { this.unbind( set ); }); return this; }, - sync: function() { // values* + /** + * Link this value with one or more other values in both directions. + * + * @param {...wp.customize.Value} values A value, or multiple values, to keep in sync with this value. + * @return {wp.customize.Value} The instance of the Value. + */ + sync: function( ...values ) { var that = this; - $.each( arguments, function() { + $.each( values, function() { that.link( this ); this.link( that ); }); return this; }, - unsync: function() { // values* + /** + * Stop keeping this value in sync with one or more other values. + * + * @param {...wp.customize.Value} values A value, or multiple values, to stop keeping in sync with this value. + * @return {wp.customize.Value} The instance of the Value. + */ + unsync: function( ...values ) { var that = this; - $.each( arguments, function() { + $.each( values, function() { that.unlink( this ); this.unlink( that ); }); @@ -325,7 +401,7 @@ window.wp = window.wp || {}; * @memberOf wp.customize * @alias wp.customize.Values * - * @constructor + * @class * @augments wp.customize.Class * @mixes wp.customize.Events */ @@ -334,7 +410,7 @@ window.wp = window.wp || {}; /** * The default constructor for items of the collection. * - * @type {object} + * @type {Function} */ defaultConstructor: api.Value, @@ -352,27 +428,27 @@ window.wp = window.wp || {}; * the last to be a function callback that will be invoked when the requested * items are available. * - * @see {api.Values.when} + * @see {@link wp.customize.Values#when} * - * @param {string} id ID of the item. - * @param {...} Zero or more IDs of items to wait for and a callback - * function to invoke when they're available. Optional. - * @return {mixed} The item instance if only one ID was supplied. - * A Deferred Promise object if a callback function is supplied. + * @param {string} id ID of the item. + * @param {...(string|Function)} [args] Zero or more IDs of items to wait for and a callback + * function to invoke when they're available. Optional. + * @return {*} The item instance if only one ID was supplied. + * A Deferred Promise object if a callback function is supplied. */ - instance: function( id ) { - if ( arguments.length === 1 ) { + instance: function( id, ...args ) { + if ( 0 === args.length ) { return this.value( id ); } - return this.when.apply( this, arguments ); + return this.when( id, ...args ); }, /** * Get the instance of an item. * * @param {string} id The ID of the item. - * @return {[type]} [description] + * @return {*} The item instance. */ value: function( id ) { return this._value[ id ]; @@ -382,7 +458,7 @@ window.wp = window.wp || {}; * Whether the collection has an item with the given ID. * * @param {string} id The ID of the item to look for. - * @return {boolean} + * @return {boolean} True if the collection has an item with the given ID, false otherwise. */ has: function( id ) { return typeof this._value[ id ] !== 'undefined'; @@ -391,9 +467,9 @@ window.wp = window.wp || {}; /** * Add an item to the collection. * - * @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add. - * When an ID string is supplied, then itemObject must be provided. - * @param {wp.customize.Class} [itemObject] - The item instance when the first argument is an ID string. + * @param {string|wp.customize.Class} item The item instance to add, or the ID for the instance to add. + * When an ID string is supplied, then itemObject must be provided. + * @param {wp.customize.Class} [itemObject] The item instance when the first argument is an ID string. * @return {wp.customize.Class} The new item's instance, or an existing instance if already added. */ add: function( item, itemObject ) { @@ -436,19 +512,19 @@ window.wp = window.wp || {}; * Create a new item of the collection using the collection's default constructor * and store it in the collection. * - * @param {string} id The ID of the item. - * @param {mixed} value Any extra arguments are passed into the item's initialize method. - * @return {mixed} The new item's instance. + * @param {string} id The ID of the item. + * @param {...*} [args] Zero or more extra arguments to pass into the item's initialize method. + * @return {wp.customize.Class} The new item's instance. */ - create: function( id ) { - return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) ); + create: function( id, ...args ) { + return this.add( id, new this.defaultConstructor( api.Class.applicator, args ) ); }, /** * Iterate over all items in the collection invoking the provided callback. * - * @param {Function} callback Function to invoke. - * @param {Object} context Object context to invoke the function with. Optional. + * @param {Function} callback Function to invoke. + * @param {Object} [context] Object context to invoke the function with. */ each: function( callback, context ) { context = typeof context === 'undefined' ? this : context; @@ -492,13 +568,14 @@ window.wp = window.wp || {}; * when( ids*, [callback] ); * * For example: - * when( id1, id2, id3, function( value1, value2, value3 ) {} ); + * when( id1, id2, id3, function( value1, value2, value3 ) {} ); * - * @return $.Deferred.promise(); + * @param {...(string|Function)} ids Zero or more IDs of items to wait for, optionally followed by + * a callback function to invoke once they are all available. + * @return {JQuery.Promise<*>} A promise that is resolved when all of the requested values exist. */ - when: function() { + when: function( ...ids ) { var self = this, - ids = slice.call( arguments ), dfd = $.Deferred(); // If the last argument is a callback, bind it to .done(). @@ -555,9 +632,10 @@ window.wp = window.wp || {}; /** - * Cast a string to a jQuery collection if it isn't already. + * Cast a string to a jQuery object if it isn't already. * - * @param {string|jQuery collection} element + * @param {string|JQuery} element A selector or an existing jQuery collection. + * @return {JQuery} The jQuery collection. */ api.ensure = function( element ) { return typeof element === 'string' ? $( element ) : element; @@ -571,7 +649,7 @@ window.wp = window.wp || {}; * @memberOf wp.customize * @alias wp.customize.Element * - * @constructor + * @class * @augments wp.customize.Value * @augments wp.customize.Class */ @@ -600,9 +678,9 @@ window.wp = window.wp || {}; update = this.update; refresh = this.refresh; - this.update = function( to ) { + this.update = function( to, ...args ) { if ( to !== refresh.call( self ) ) { - update.apply( this, arguments ); + update.call( this, to, ...args ); } }; this.refresh = function() { @@ -663,7 +741,7 @@ window.wp = window.wp || {}; * @memberOf wp.customize * @alias wp.customize.Messenger * - * @constructor + * @class * @augments wp.customize.Class * @mixes wp.customize.Events */ @@ -671,10 +749,10 @@ window.wp = window.wp || {}; /** * Create a new Value. * - * @param {string} key Unique identifier. - * @param {mixed} initial Initial value. - * @param {mixed} options Options hash. Optional. - * @return {Value} Class instance of the Value. + * @param {string} key Unique identifier. + * @param {*} initial Initial value. + * @param {*} [options] Options hash. + * @return {wp.customize.Value} Class instance of the Value. */ add: function( key, initial, options ) { return this[ key ] = new api.Value( initial, options ); @@ -683,11 +761,11 @@ window.wp = window.wp || {}; /** * Initialize Messenger. * - * @param {Object} params - Parameters to configure the messenger. - * {string} params.url - The URL to communicate with. - * {window} params.targetWindow - The window instance to communicate with. Default window.parent. - * {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel. - * @param {Object} options - Extend any instance parameter or method with this object. + * @param {Object} params Parameters to configure the messenger. + * @param {string} params.url The URL to communicate with. + * @param {Window} params.targetWindow The window instance to communicate with. Default window.parent. + * @param {string} [params.channel] If provided, will send the channel with each message and only accept messages a matching channel. + * @param {Object} [options] Extend any instance parameter or method with this object. */ initialize: function( params, options ) { // Target the parent frame by default, but only if a parent frame exists. @@ -707,10 +785,10 @@ window.wp = window.wp || {}; // First add with no value. this.add( 'targetWindow', null ); // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios. - this.targetWindow.set = function( to ) { + this.targetWindow.set = function( to, ...args ) { var from = this._value; - to = this._setter.apply( this, arguments ); + to = this._setter( to, ...args ); to = this.validate( to ); if ( null === to || from === to ) { @@ -748,7 +826,7 @@ window.wp = window.wp || {}; /** * Receive data from the other window. * - * @param {jQuery.Event} event Event with embedded data. + * @param {JQuery.Event} event Event with embedded data. */ receive: function( event ) { var message; @@ -787,8 +865,8 @@ window.wp = window.wp || {}; /** * Send data to the other window. * - * @param {string} id The event name. - * @param {Object} data Data. + * @param {string} id The event name. + * @param {*} [data] Data. */ send: function( id, data ) { var message; @@ -821,13 +899,13 @@ window.wp = window.wp || {}; * @memberOf wp.customize * @alias wp.customize.Notification * - * @param {string} code - The error code. - * @param {object} params - Params. - * @param {string} params.message=null - The error message. - * @param {string} [params.type=error] - The notification type. - * @param {boolean} [params.fromServer=false] - Whether the notification was server-sent. - * @param {string} [params.setting=null] - The setting ID that the notification is related to. - * @param {*} [params.data=null] - Any additional data. + * @param {string} code The error code. + * @param {Object} params Params. + * @param {string} [params.message=null] The error message. + * @param {string} [params.type=error] The notification type. + * @param {boolean} [params.fromServer=false] Whether the notification was server-sent. + * @param {string} [params.setting=null] The setting ID that the notification is related to. + * @param {*} [params.data=null] Any additional data. */ api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{ @@ -837,7 +915,7 @@ window.wp = window.wp || {}; * This will be populated with template option or else it will be populated with template from the ID. * * @since 4.9.0 - * @var {Function} + * @member {Function} */ template: null, @@ -845,7 +923,7 @@ window.wp = window.wp || {}; * ID for the template to render the notification. * * @since 4.9.0 - * @var {string} + * @member {string} */ templateId: 'customize-notification', @@ -853,7 +931,7 @@ window.wp = window.wp || {}; * Additional class names to add to the notification container. * * @since 4.9.0 - * @var {string} + * @member {string} */ containerClasses: '', @@ -862,15 +940,15 @@ window.wp = window.wp || {}; * * @since 4.9.0 * - * @param {string} code - Notification code. - * @param {Object} params - Notification parameters. - * @param {string} params.message - Message. - * @param {string} [params.type=error] - Type. - * @param {string} [params.setting] - Related setting ID. - * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId. - * @param {string} [params.templateId] - ID for template to render the notification. - * @param {string} [params.containerClasses] - Additional class names to add to the notification container. - * @param {boolean} [params.dismissible] - Whether the notification can be dismissed. + * @param {string} code Notification code. + * @param {Object} params Notification parameters. + * @param {string} params.message Message. + * @param {string} [params.type=error] Type. + * @param {string} [params.setting] Related setting ID. + * @param {Function} [params.template] Function for rendering template. If not provided, this will come from templateId. + * @param {string} [params.templateId] ID for template to render the notification. + * @param {string} [params.containerClasses] Additional class names to add to the notification container. + * @param {boolean} [params.dismissible] Whether the notification can be dismissed. */ initialize: function( code, params ) { var _params; @@ -897,7 +975,7 @@ window.wp = window.wp || {}; * * @since 4.9.0 * - * @return {jQuery} Notification container element. + * @return {JQuery} Notification container element. */ render: function() { var notification = this, container, data; @@ -935,7 +1013,7 @@ window.wp = window.wp || {}; * * @alias wp.customize.get * - * @return {Object} + * @return {Object} All customize settings. */ api.get = function() { var result = {}; @@ -990,5 +1068,5 @@ window.wp = window.wp || {}; * * @namespace wp.customize */ - exports.customize = api; + wp.customize = api; })( wp, jQuery ); diff --git a/src/js/_enqueues/wp/customize/controls.js b/src/js/_enqueues/wp/customize/controls.js index 00123f9141c30..83d5a0c2f9897 100644 --- a/src/js/_enqueues/wp/customize/controls.js +++ b/src/js/_enqueues/wp/customize/controls.js @@ -3,7 +3,14 @@ */ /* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer, console, confirm */ -(function( exports, $ ){ + +/** + * The WordPress Customizer controls API. + * + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. + */ +(function( wp, $ ){ var Container, focus, normalizedTransitionendEventName, api = wp.customize; var reducedMotionMediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' ); @@ -18,7 +25,7 @@ * Whether the notification should show a loading spinner. * * @since 4.9.0 - * @var {boolean} + * @member {boolean} */ loading: false, @@ -30,8 +37,8 @@ * * @since 4.9.0 * - * @param {string} code - Code. - * @param {Object} params - Params. + * @param {string} code Notification code. + * @param {Object} params Notification params. */ initialize: function( code, params ) { var notification = this; @@ -47,7 +54,7 @@ * * @since 4.9.0 * - * @return {jQuery} Notification container. + * @return {JQuery} Notification container. */ render: function() { var li = api.Notification.prototype.render.call( this ); @@ -60,7 +67,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ handleEscape: function( event ) { @@ -88,7 +95,7 @@ * The default constructor for items of the collection. * * @since 4.9.0 - * @type {object} + * @type {Function} */ defaultConstructor: api.Notification, @@ -100,9 +107,9 @@ * @constructs wp.customize.Notifications * @augments wp.customize.Values * - * @param {Object} options - Options. - * @param {jQuery} [options.container] - Container element for notifications. This can be injected later. - * @param {boolean} [options.alt] - Whether alternative style should be used when rendering notifications. + * @param {Object} options Options. + * @param {JQuery} [options.container] Container element for notifications. This can be injected later. + * @param {boolean} [options.alt] Whether alternative style should be used when rendering notifications. * * @return {void} */ @@ -141,8 +148,8 @@ * * @since 4.9.0 * - * @param {string|wp.customize.Notification} notification - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied. - * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string. + * @param {string|wp.customize.Notification} notification Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied. + * @param {wp.customize.Notification} [notificationObject] Notification to add when first argument is the code string. * @return {wp.customize.Notification} Added notification (or existing instance if it was already added). */ add: function( notification, notificationObject ) { @@ -165,8 +172,8 @@ * Add notification to the collection. * * @since 4.9.0 - * @param {string} code - Notification code to remove. - * @return {api.Notification} Added instance (or existing instance if it was already added). + * @param {string} code Notification code to remove. + * @return {wp.customize.Notification} Added instance (or existing instance if it was already added). */ remove: function( code ) { var collection = this; @@ -180,9 +187,9 @@ * Notifications may be sorted by type followed by added time. * * @since 4.9.0 - * @param {Object} args - Args. - * @param {boolean} [args.sort=false] - Whether to return the notifications sorted. - * @return {Array.} Notifications. + * @param {Object} args Args. + * @param {boolean} [args.sort=false] Whether to return the notifications sorted. + * @return {wp.customize.Notification[]} Notifications. */ get: function( args ) { var collection = this, notifications, errorTypePriorities, params; @@ -309,7 +316,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ constrainFocus: function constrainFocus( event ) { @@ -346,7 +353,7 @@ * Default params. * * @since 4.9.0 - * @var {object} + * @member {Object} */ defaults: { transport: 'refresh', @@ -366,12 +373,12 @@ * * @since 3.4.0 * - * @param {string} id - The setting ID. - * @param {*} value - The initial value of the setting. - * @param {Object} [options={}] - Options. - * @param {string} [options.transport=refresh] - The transport to use for previewing. Supports 'refresh' and 'postMessage'. - * @param {boolean} [options.dirty=false] - Whether the setting should be considered initially dirty. - * @param {Object} [options.previewer] - The Previewer instance to sync with. Defaults to wp.customize.previewer. + * @param {string} id The setting ID. + * @param {*} value The initial value of the setting. + * @param {Object} [options={}] Options. + * @param {string} [options.transport=refresh] The transport to use for previewing. Supports 'refresh' and 'postMessage'. + * @param {boolean} [options.dirty=false] Whether the setting should be considered initially dirty. + * @param {Object} [options.previewer] The Previewer instance to sync with. Defaults to wp.customize.previewer. */ initialize: function( id, value, options ) { var setting = this, params; @@ -468,7 +475,7 @@ * @alias wp.customize._latestSettingRevisions * * @since 4.7.0 - * @type {object} + * @type {Object} * @protected */ api._latestSettingRevisions = {}; @@ -501,7 +508,7 @@ * @since 4.7.0 * @access public * - * @param {Object} [options] Options. + * @param {Object} [options] Options. * @param {boolean} [options.unsaved=false] Whether only values not saved yet into a changeset will be returned (differential changes). * @return {Object} Dirty setting values. */ @@ -534,14 +541,14 @@ * @since 4.7.0 * @access public * - * @param {Object} [changes] - Mapping of setting IDs to setting params each normally including a value property, or mapping to null. - * If not provided, then the changes will still be obtained from unsaved dirty settings. - * @param {Object} [args] - Additional options for the save request. - * @param {boolean} [args.autosave=false] - Whether changes will be stored in autosave revision if the changeset has been promoted from an auto-draft. - * @param {boolean} [args.force=false] - Send request to update even when there are no changes to submit. This can be used to request the latest status of the changeset on the server. - * @param {string} [args.title] - Title to update in the changeset. Optional. - * @param {string} [args.date] - Date to update in the changeset. Optional. - * @return {jQuery.Promise} Promise resolving with the response data. + * @param {Object} [changes] Mapping of setting IDs to setting params each normally including a value property, or mapping to null. + * If not provided, then the changes will still be obtained from unsaved dirty settings. + * @param {Object} [args] Additional options for the save request. + * @param {boolean} [args.autosave=false] Whether changes will be stored in autosave revision if the changeset has been promoted from an auto-draft. + * @param {boolean} [args.force=false] Send request to update even when there are no changes to submit. This can be used to request the latest status of the changeset on the server. + * @param {string} [args.title] Title to update in the changeset. Optional. + * @param {string} [args.date] Date to update in the changeset. Optional. + * @return {JQuery.Promise<*>} Promise resolving with the response data. */ api.requestChangesetUpdate = function requestChangesetUpdate( changes, args ) { var deferred, request, submittedChanges = {}, data, submittedArgs; @@ -671,8 +678,8 @@ * * @since 4.1.0 * - * @param {wp.customize.Class} instance - * @param {Array} properties The names of the Value instances to watch. + * @param {wp.customize.Class} instance The instance whose Value properties are watched. + * @param {string[]} properties The names of the Value instances to watch. */ api.utils.bubbleChildValueChanges = function ( instance, properties ) { $.each( properties, function ( i, key ) { @@ -691,8 +698,8 @@ * * @since 4.1.0 * - * @param {Object} [params] - * @param {Function} [params.completeCallback] + * @param {Object} [params] Object containing options for the focus. + * @param {Function} [params.completeCallback] Function to call once the construct is expanded and focused. */ focus = function ( params ) { var construct, completeCallback, focus, focusElement, sections; @@ -752,9 +759,9 @@ * * @since 4.1.0 * - * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a - * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b - * @return {number} + * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a The first construct to compare. + * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b The second construct to compare. + * @return {number} A negative number if a has lower priority than b, a positive number if a has higher priority than b, or zero if they have the same priority. */ api.utils.prioritySort = function ( a, b ) { if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) { @@ -771,8 +778,8 @@ * * @since 4.1.0 * - * @param {jQuery.Event} event - * @return {boolean} + * @param {JQuery.Event} event Event object. + * @return {boolean} True if the event is a keydown event but not the Enter key, false otherwise. */ api.utils.isKeydownButNotEnterEvent = function ( event ) { return ( 'keydown' === event.type && 13 !== event.which ); @@ -785,9 +792,9 @@ * * @since 4.1.0 * - * @param {Array|jQuery} listA - * @param {Array|jQuery} listB - * @return {boolean} + * @param {JQuery[]|JQuery} listA First list of elements. + * @param {JQuery[]|JQuery} listB Second list of elements. + * @return {boolean} True if the two lists are equal, false otherwise. */ api.utils.areElementListsEqual = function ( listA, listB ) { var equal = ( @@ -813,14 +820,14 @@ * * @since 4.9.0 * - * @param {jQuery} button - The element to highlight. - * @param {Object} [options] - Options. - * @param {number} [options.delay=0] - Delay in milliseconds. - * @param {jQuery} [options.focusTarget] - A target for user focus that defaults to the highlighted element. - * If the user focuses the target before the delay passes, the reminder - * is canceled. This option exists to accommodate compound buttons - * containing auxiliary UI, such as the Publish button augmented with a - * Settings button. + * @param {JQuery} button The element to highlight. + * @param {Object} [options] Options. + * @param {number} [options.delay=0] Delay in milliseconds. + * @param {JQuery} [options.focusTarget] A target for user focus that defaults to the highlighted element. + * If the user focuses the target before the delay passes, the reminder + * is canceled. This option exists to accommodate compound buttons + * containing auxiliary UI, such as the Publish button augmented with a + * Settings button. * @return {Function} An idempotent function that cancels the reminder. */ api.utils.highlightButton = function highlightButton( button, options ) { @@ -836,6 +843,9 @@ options ); + /** + * Cancels the reminder, preventing the button from being highlighted. + */ function cancelReminder() { canceled = true; } @@ -887,8 +897,8 @@ * * @since 4.9.0 * - * @param {string|number|Date} datetime - Date time or timestamp of the future date. - * @return {number} remainingTime - Remaining time in milliseconds. + * @param {string|number|Date} datetime Date time or timestamp of the future date. + * @return {number} Remaining time in milliseconds. */ api.utils.getRemainingTime = function getRemainingTime( datetime ) { var millisecondsDivider = 1000, remainingTime, timestamp; @@ -957,16 +967,16 @@ * * @borrows wp.customize~focus as focus * - * @param {string} id - The ID for the container. - * @param {Object} options - Object containing one property: params. - * @param {string} options.title - Title shown when panel is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the panel. - * @param {number} [options.priority=100] - The sort priority for the panel. - * @param {string} [options.templateId] - Template selector for container. - * @param {string} [options.type=default] - The type of the panel. See wp.customize.panelConstructor. - * @param {string} [options.content] - The markup to be used for the panel container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the panel is active or not. - * @param {Object} [options.params] - Deprecated wrapper for the above properties. + * @param {string} id The ID for the container. + * @param {Object} options Object containing one property: params. + * @param {string} options.title Title shown when panel is collapsed and expanded. + * @param {string} [options.description] Description shown at the top of the panel. + * @param {number} [options.priority=100] The sort priority for the panel. + * @param {string} [options.templateId] Template selector for container. + * @param {string} [options.type=default] The type of the panel. See wp.customize.panelConstructor. + * @param {string} [options.content] The markup to be used for the panel container. If empty, a JS template is used. + * @param {boolean} [options.active=true] Whether the panel is active or not. + * @param {Object} [options.params] Deprecated wrapper for the above properties. */ initialize: function ( id, options ) { var container = this; @@ -1033,7 +1043,7 @@ * Get the element that will contain the notifications. * * @since 4.9.0 - * @return {jQuery} Notification container element. + * @return {JQuery} Notification container element. */ getNotificationsContainerElement: function() { var container = this; @@ -1062,6 +1072,8 @@ }, /** + * Handles the ready state (when overridden). + * * @since 4.1.0 * * @abstract @@ -1073,9 +1085,9 @@ * * @since 4.1.0 * - * @param {string} parentType - * @param {string} childType - * @return {Array} + * @param {string} parentType The parent's type, which is also the name of the Value on each child that holds its parent's ID. + * @param {string} childType The children's type, which is also the name of the collection on wp.customize to iterate over. + * @return {wp.customize.Class[]} Array of child models sorted by priority. */ _children: function ( parentType, childType ) { var parent = this, @@ -1109,11 +1121,11 @@ * * @since 4.1.0 * - * @param {boolean} active - The active state to transiution to. - * @param {Object} [args] - Args. - * @param {Object} [args.duration] - The duration for the slideUp/slideDown animation. - * @param {boolean} [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. - * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed. + * @param {boolean} active The active state to transition to. + * @param {Object} [args] Args. + * @param {Object} [args.duration] The duration for the slideUp/slideDown animation. + * @param {boolean} [args.unchanged] Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. + * @param {Function} [args.completeCallback] Function to call when the slideUp/slideDown has completed. */ onChangeActive: function( active, args ) { var construct = this, @@ -1170,10 +1182,12 @@ }, /** + * Handles the toggle logic to transition the active state. + * * @since 4.1.0 * - * @param {boolean} active - * @param {Object} [params] + * @param {boolean} active The active state to transition to. + * @param {Object} [params] Params. * @return {boolean} False if state already applied. */ _toggleActive: function ( active, params ) { @@ -1192,7 +1206,9 @@ }, /** - * @param {Object} [params] + * Activate the control. + * + * @param {Object} [params] Params. * @return {boolean} False if already active. */ activate: function ( params ) { @@ -1200,7 +1216,9 @@ }, /** - * @param {Object} [params] + * Deactivate the control. + * + * @param {Object} [params] Params. * @return {boolean} False if already inactive. */ deactivate: function ( params ) { @@ -1218,9 +1236,9 @@ /** * Handle the toggle logic for expand/collapse. * - * @param {boolean} expanded - The new state to apply. - * @param {Object} [params] - Object containing options for expand/collapse. - * @param {Function} [params.completeCallback] - Function to call when expansion/collapse is complete. + * @param {boolean} expanded The new state to apply. + * @param {Object} [params] Object containing options for expand/collapse. + * @param {Function} [params.completeCallback] Function to call when expansion/collapse is complete. * @return {boolean} False if state already applied or active state is false. */ _toggleExpanded: function( expanded, params ) { @@ -1234,9 +1252,9 @@ } api.state( 'paneVisible' ).set( true ); - params.completeCallback = function() { + params.completeCallback = function( ...args ) { if ( previousCompleteCallback ) { - previousCompleteCallback.apply( instance, arguments ); + previousCompleteCallback.apply( instance, args ); } if ( expanded ) { instance.container.trigger( 'expanded' ); @@ -1257,7 +1275,9 @@ }, /** - * @param {Object} [params] + * Expand the container. + * + * @param {Object} [params] Object containing options for expansion. * @return {boolean} False if already expanded or if inactive. */ expand: function ( params ) { @@ -1265,7 +1285,9 @@ }, /** - * @param {Object} [params] + * Collapse the container. + * + * @param {Object} [params] Object containing options for collapse. * @return {boolean} False if already collapsed. */ collapse: function ( params ) { @@ -1278,7 +1300,7 @@ * @since 4.7.0 * @private * - * @param {function} completeCallback Function to be called after transition is completed. + * @param {Function} completeCallback Function to be called after transition is completed. * @return {void} */ _animateChangeExpanded: function( completeCallback ) { @@ -1352,6 +1374,7 @@ * Return the container html, generated from its JS template, if it exists. * * @since 4.3.0 + * @return {string} Container html. */ getContainer: function () { var template, @@ -1385,7 +1408,7 @@ * @since 4.7.0 * @access public * - * @return {jQuery} Detached content element. + * @return {JQuery} Detached content element. */ getContent: function() { var construct = this, @@ -1424,22 +1447,24 @@ }, /** + * Initializes a section. + * * @constructs wp.customize.Section * @augments wp.customize~Container * * @since 4.1.0 * - * @param {string} id - The ID for the section. - * @param {Object} options - Options. - * @param {string} options.title - Title shown when section is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the section. - * @param {number} [options.priority=100] - The sort priority for the section. - * @param {string} [options.type=default] - The type of the section. See wp.customize.sectionConstructor. - * @param {string} [options.content] - The markup to be used for the section container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the section is active or not. - * @param {string} options.panel - The ID for the panel this section is associated with. - * @param {string} [options.customizeAction] - Additional context information shown before the section title when expanded. - * @param {Object} [options.params] - Deprecated wrapper for the above properties. + * @param {string} id The ID for the section. + * @param {Object} options Options. + * @param {string} options.title Title shown when section is collapsed and expanded. + * @param {string} [options.description] Description shown at the top of the section. + * @param {number} [options.priority=100] The sort priority for the section. + * @param {string} [options.type=default] The type of the section. See wp.customize.sectionConstructor. + * @param {string} [options.content] The markup to be used for the section container. If empty, a JS template is used. + * @param {boolean} [options.active=true] Whether the section is active or not. + * @param {string} options.panel The ID for the panel this section is associated with. + * @param {string} [options.customizeAction] Additional context information shown before the section title when expanded. + * @param {Object} [options.params] Deprecated wrapper for the above properties. */ initialize: function ( id, options ) { var section = this, params; @@ -1566,7 +1591,7 @@ * * @since 4.1.0 * - * @return {boolean} + * @return {boolean} True if the section has any active controls, false otherwise. */ isContextuallyActive: function () { var section = this, @@ -1585,7 +1610,7 @@ * * @since 4.1.0 * - * @return {Array} + * @return {wp.customize.Control[]} Array of control models sorted by priority. */ controls: function () { return this._children( 'section', 'control' ); @@ -1596,8 +1621,8 @@ * * @since 4.1.0 * - * @param {boolean} expanded - * @param {Object} args + * @param {boolean} expanded The expanded state to transition to. + * @param {Object} args Object containing options for expand/collapse. */ onChangeExpanded: function ( expanded, args ) { var section = this, @@ -1714,8 +1739,8 @@ * * @since 4.9.0 * - * @param {string} id - ID. - * @param {Object} options - Options. + * @param {string} id ID. + * @param {Object} options Options. * @return {void} */ initialize: function( id, options ) { @@ -1831,7 +1856,7 @@ * * @since 4.2.0 * - * @return {boolean} + * @return {boolean} True if the section is active, false otherwise. */ isContextuallyActive: function () { return this.active(); @@ -1959,6 +1984,9 @@ api.section( 'wporg_themes' ).focus(); }); + /** + * Updates the section header to reflect the expanded state. + */ function updateSelectedState() { var el = section.headerContainer.find( '.customize-themes-section-title' ); el.toggleClass( 'selected', section.expanded() ); @@ -1983,10 +2011,10 @@ * * @since 4.2.0 * - * @param {boolean} expanded - * @param {Object} args - * @param {boolean} args.unchanged - * @param {Function} args.completeCallback + * @param {boolean} expanded The expanded state to transition to. + * @param {Object} args Object containing options for expand/collapse. + * @param {boolean} args.unchanged Whether the expanded state is unchanged. + * @param {Function} args.completeCallback Callback to be executed once the expand/collapse action is complete. * @return {void} */ onChangeExpanded: function ( expanded, args ) { @@ -2003,6 +2031,9 @@ return; } + /** + * Expands the section. + */ function expand() { // Try to load controls if none are loaded yet. @@ -2077,7 +2108,7 @@ * * @since 4.9.0 * - * @return {jQuery} + * @return {JQuery} The section's content element. */ getContent: function() { return this.container.find( '.control-section-content' ); @@ -2198,8 +2229,8 @@ * Loads controls into the section from data received from loadThemes(). * * @since 4.9.0 - * @param {Array} themes - Array of theme data to create controls with. - * @param {number} page - Page of results being loaded. + * @param {Object[]} themes Array of theme data to create controls with. + * @param {number} page Page of results being loaded. * @return {void} */ loadControls: function( themes, page ) { @@ -2252,7 +2283,7 @@ * * @since 4.9.0 * - * @param {string} term - The raw search input value. + * @param {string} term The raw search input value. * @return {void} */ filterSearch: function( term ) { @@ -2296,7 +2327,7 @@ * * @since 4.9.0 * - * @param {wp.customize.ThemesSection} section - The current theme section, passed through the debouncer. + * @param {wp.customize.ThemesSection} section The current theme section, passed through the debouncer. * @return {void} */ checkTerm: function( section ) { @@ -2355,8 +2386,8 @@ * * @since 4.9.0 * - * @param {string} newTerm - New term. - * @param {Array} newTags - New tags. + * @param {string} newTerm New term. + * @param {string[]} newTags New tags. * @return {void} */ initializeNewQuery: function( newTerm, newTags ) { @@ -2455,6 +2486,7 @@ * * @since 4.9.0 * + * @param {number} [count] The number of themes. Defaults to the number of visible theme controls. * @return {void} */ updateCount: function( count ) { @@ -2565,10 +2597,14 @@ */ updateLimits: function () { if ( ! this.getNextTheme() ) { - this.overlay.find( '.right' ).addClass( 'disabled' ); + this.overlay.find( '.right' ) + .addClass( 'disabled' ) + .attr( 'aria-disabled', true ); } if ( ! this.getPreviousTheme() ) { - this.overlay.find( '.left' ).addClass( 'disabled' ); + this.overlay.find( '.left' ) + .addClass( 'disabled' ) + .attr( 'aria-disabled', true ); } }, @@ -2580,7 +2616,7 @@ * * @deprecated * @param {string} themeId Theme ID. - * @return {jQuery.promise} Promise. + * @return {JQuery.Promise<*>} Promise. */ loadThemePreview: function( themeId ) { return api.ThemesPanel.prototype.loadThemePreview.call( this, themeId ); @@ -2591,8 +2627,8 @@ * * @since 4.2.0 * - * @param {Object} theme - Theme. - * @param {Function} [callback] - Callback once the details have been shown. + * @param {Object} theme Theme. + * @param {Function} [callback] Callback once the details have been shown. * @return {void} */ showDetails: function ( theme, callback ) { @@ -2602,11 +2638,21 @@ .fadeIn( 'fast' ) .focus(); + /** + * Disables the switch buttons if the theme cannot be switched to. + * + * @return {boolean} True if the switch buttons should be disabled, false otherwise. + */ function disableSwitchButtons() { return ! panel.canSwitchTheme( theme.id ); } // Temporary special function since supplying SFTP credentials does not work yet. See #42184. + /** + * Disables the install buttons if the theme cannot be installed or if filesystem credentials are needed. + * + * @return {boolean} True if the install buttons should be disabled, false otherwise. + */ function disableInstallButtons() { return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded; } @@ -2645,7 +2691,7 @@ * * @since 4.2.0 * - * @param {jQuery} el - Element to contain focus. + * @param {JQuery} el Element to contain focus. * @return {void} */ containFocus: function( el ) { @@ -2687,13 +2733,15 @@ * * @since 4.9.0 * + * @param {string} id The ID for the section. + * @param {Object} options Options, as accepted by wp.customize.Section. * @return {void} */ - initialize: function() { + initialize: function( id, options ) { var section = this; section.containerParent = '#customize-outer-theme-controls'; section.containerPaneParent = '.customize-outer-pane-parent'; - api.Section.prototype.initialize.apply( section, arguments ); + api.Section.prototype.initialize.call( section, id, options ); }, /** @@ -2702,11 +2750,11 @@ * * @since 4.9.0 * - * @param {boolean} expanded - The expanded state to transition to. - * @param {Object} [args] - Args. - * @param {boolean} [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. - * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed. - * @param {Object} [args.duration] - The duration for the animation. + * @param {boolean} expanded The expanded state to transition to. + * @param {Object} [args] Args. + * @param {boolean} [args.unchanged] Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. + * @param {Function} [args.completeCallback] Function to call when the slideUp/slideDown has completed. + * @param {Object} [args.duration] The duration for the animation. */ onChangeExpanded: function( expanded, args ) { var section = this, @@ -2787,20 +2835,22 @@ containerType: 'panel', /** + * Initializes a panel. + * * @constructs wp.customize.Panel * @augments wp.customize~Container * * @since 4.1.0 * - * @param {string} id - The ID for the panel. - * @param {Object} options - Object containing one property: params. - * @param {string} options.title - Title shown when panel is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the panel. - * @param {number} [options.priority=100] - The sort priority for the panel. - * @param {string} [options.type=default] - The type of the panel. See wp.customize.panelConstructor. - * @param {string} [options.content] - The markup to be used for the panel container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the panel is active or not. - * @param {Object} [options.params] - Deprecated wrapper for the above properties. + * @param {string} id The ID for the panel. + * @param {Object} options Object containing one property: params. + * @param {string} options.title Title shown when panel is collapsed and expanded. + * @param {string} [options.description] Description shown at the top of the panel. + * @param {number} [options.priority=100] The sort priority for the panel. + * @param {string} [options.type=default] The type of the panel. See wp.customize.panelConstructor. + * @param {string} [options.content] The markup to be used for the panel container. If empty, a JS template is used. + * @param {boolean} [options.active=true] Whether the panel is active or not. + * @param {Object} [options.params] Deprecated wrapper for the above properties. */ initialize: function ( id, options ) { var panel = this, params; @@ -2847,6 +2897,8 @@ }, /** + * Attaches events to the panel. + * * @since 4.1.0 */ attachEvents: function () { @@ -2906,7 +2958,7 @@ * * @since 4.1.0 * - * @return {Array} + * @return {wp.customize.Section[]} Array of sections. */ sections: function () { return this._children( 'panel', 'section' ); @@ -2936,10 +2988,10 @@ * * @since 4.1.0 * - * @param {boolean} expanded - * @param {Object} args - * @param {boolean} args.unchanged - * @param {Function} args.completeCallback + * @param {boolean} expanded The expanded state to transition to. + * @param {Object} args Object containing options for expand/collapse. + * @param {boolean} args.unchanged Whether the expanded state is unchanged. + * @param {Function} args.completeCallback Callback to be executed once the expand/collapse action is complete. * @return {void} */ onChangeExpanded: function ( expanded, args ) { @@ -3050,10 +3102,10 @@ } }); - api.ThemesPanel = api.Panel.extend(/** @lends wp.customize.ThemsPanel.prototype */{ + api.ThemesPanel = api.Panel.extend(/** @lends wp.customize.ThemesPanel.prototype */{ /** - * Class wp.customize.ThemesPanel. + * Class wp.customize.ThemesPanel. * * Custom section for themes that displays without the customize preview. * @@ -3062,8 +3114,8 @@ * * @since 4.9.0 * - * @param {string} id - The ID for the panel. - * @param {Object} options - Options. + * @param {string} id The ID for the panel. + * @param {Object} options Options. * @return {void} */ initialize: function( id, options ) { @@ -3077,7 +3129,7 @@ * * @since 4.9.0 * - * @param {string} [slug] - Theme slug. + * @param {string} [slug] Theme slug. When omitted, whether switching is possible at all. * @return {boolean} Whether the theme can be switched to. */ canSwitchTheme: function canSwitchTheme( slug ) { @@ -3108,6 +3160,9 @@ } ) ); } + /** + * Toggles the theme switch unavailable notification based on whether switching is possible. + */ function toggleDisabledNotifications() { if ( panel.canSwitchTheme() ) { panel.notifications.remove( 'theme_switch_unavailable' ); @@ -3160,10 +3215,10 @@ * * @since 4.9.0 * - * @param {boolean} expanded - Expanded state. - * @param {Object} args - Args. - * @param {boolean} args.unchanged - Whether or not the state changed. - * @param {Function} args.completeCallback - Callback to execute when the animation completes. + * @param {boolean} expanded Expanded state. + * @param {Object} args Args. + * @param {boolean} args.unchanged Whether or not the state changed. + * @param {Function} args.completeCallback Callback to execute when the animation completes. * @return {void} */ onChangeExpanded: function( expanded, args ) { @@ -3215,8 +3270,8 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. - * @return {jQuery.promise} Promise. + * @param {JQuery.Event} event Event. + * @return {JQuery.Promise<*>} Promise. */ installTheme: function( event ) { var panel = this, preview, onInstallSuccess, slug = $( event.target ).data( 'slug' ), deferred = $.Deferred(), request; @@ -3321,7 +3376,7 @@ * @since 4.9.0 * * @param {string} themeId Theme ID. - * @return {jQuery.promise} Promise. + * @return {JQuery.Promise<*>} Promise. */ loadThemePreview: function( themeId ) { var panel = this, deferred = $.Deferred(), onceProcessingComplete, urlParser, queryParams; @@ -3396,7 +3451,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ updateTheme: function( event ) { @@ -3426,7 +3481,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ deleteTheme: function( event ) { @@ -3484,7 +3539,7 @@ * Default params. * * @since 4.9.0 - * @var {object} + * @member {Object} */ defaults: { label: '', @@ -3508,22 +3563,22 @@ * @borrows wp.customize~Container#deactivate as this#deactivate * @borrows wp.customize~Container#_toggleActive as this#_toggleActive * - * @param {string} id - Unique identifier for the control instance. - * @param {Object} options - Options hash for the control instance. - * @param {Object} options.type - Type of control (e.g. text, radio, dropdown-pages, etc.) - * @param {string} [options.content] - The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId. - * @param {string} [options.templateId] - Template ID for control's content. - * @param {string} [options.priority=10] - Order of priority to show the control within the section. - * @param {string} [options.active=true] - Whether the control is active. - * @param {string} options.section - The ID of the section the control belongs to. - * @param {mixed} [options.setting] - The ID of the main setting or an instance of this setting. - * @param {mixed} options.settings - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects. - * @param {mixed} options.settings.default - The ID of the setting the control relates to. - * @param {string} options.settings.data - @todo Is this used? - * @param {string} options.label - Label. - * @param {string} options.description - Description. - * @param {number} [options.instanceNumber] - Order in which this instance was created in relation to other instances. - * @param {Object} [options.params] - Deprecated wrapper for the above properties. + * @param {string} id Unique identifier for the control instance. + * @param {Object} options Options hash for the control instance. + * @param {Object} options.type Type of control (e.g. text, radio, dropdown-pages, etc.). + * @param {string} [options.content] The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId. + * @param {string} [options.templateId] Template ID for control's content. + * @param {string} [options.priority=10] Order of priority to show the control within the section. + * @param {string} [options.active=true] Whether the control is active. + * @param {string} options.section The ID of the section the control belongs to. + * @param {*} [options.setting] The ID of the main setting or an instance of this setting. + * @param {*} options.settings An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects. + * @param {*} options.settings.default The ID of the setting the control relates to. + * @param {string} options.settings.data @todo Is this used? + * @param {string} options.label Label. + * @param {string} options.description Description. + * @param {number} [options.instanceNumber] Order in which this instance was created in relation to other instances. + * @param {Object} [options.params] Deprecated wrapper for the above properties. * @return {void} */ initialize: function( id, options ) { @@ -3771,7 +3826,7 @@ * including special handling for nav menu items and widgets. * * @since 4.6.0 - * @return {jQuery} Setting validation message element. + * @return {JQuery} Setting validation message element. */ getNotificationsContainerElement: function() { var control = this, controlTitle, notificationsContainer; @@ -3909,7 +3964,7 @@ /** * Normal controls do not expand, so just expand its parent * - * @param {Object} [params] + * @param {Object} [params] Parameters to pass to the section's expand method. */ expand: function ( params ) { api.section( this.section() ).expand( params ); @@ -3927,10 +3982,11 @@ * * @since 4.1.0 * - * @param {boolean} active - * @param {Object} args - * @param {number} args.duration - * @param {Function} args.completeCallback + * @param {boolean} active The active state to transition to. + * @param {Object} [args] Object containing options for showing or hiding the control. + * @param {number} [args.duration] The duration for the slideUp/slideDown animation. + * @param {boolean} [args.unchanged] Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. + * @param {Function} [args.completeCallback] Function to call when the slideUp/slideDown has completed. */ onChangeActive: function ( active, args ) { if ( args.unchanged ) { @@ -3954,7 +4010,11 @@ }, /** + * Toggle the control's active state. + * + * @param {boolean} active The active state to toggle. * @deprecated 4.1.0 Use this.onChangeActive() instead. + * @return {void} */ toggle: function ( active ) { return this.onChangeActive( active, this.defaultActiveArguments ); @@ -4263,7 +4323,7 @@ * and it is the responsibility of the UploadControl to set the control's * attachmentData before calling the renderContent method. * - * @param {number|string} value Attachment + * @param {number|string} value Attachment. */ function setAttachmentDataAndRenderContent( value ) { var hasAttachmentData = $.Deferred(); @@ -4313,6 +4373,8 @@ /** * Open the media modal. + * + * @param {JQuery.Event} event Event. */ openFrame: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4376,6 +4438,8 @@ /** * Reset the setting to the default value. + * + * @param {JQuery.Event} event Event. */ restoreDefault: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4390,7 +4454,7 @@ /** * Called when the "Remove" link is clicked. Empties the setting. * - * @param {Object} event jQuery Event object + * @param {JQuery.Event} event Event. */ removeFile: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4470,7 +4534,7 @@ * set up internal event bindings. */ ready: function() { - api.UploadControl.prototype.ready.apply( this, arguments ); + api.UploadControl.prototype.ready.call( this ); }, /** @@ -4478,7 +4542,7 @@ * Does an additional Ajax request for setting the background context. */ select: function() { - api.UploadControl.prototype.select.apply( this, arguments ); + api.UploadControl.prototype.select.call( this ); wp.ajax.post( 'custom-background-add', { nonce: _wpCustomizeBackground.nonces.add, @@ -4539,6 +4603,8 @@ /** * Open the media modal to the library state. + * + * @param {JQuery.Event} event Event. */ openFrame: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4611,9 +4677,9 @@ * control-specific data, to be fed to the imgAreaSelect plugin in * wp.media.view.Cropper. * - * @param {wp.media.model.Attachment} attachment - * @param {wp.media.controller.Cropper} controller - * @return {Object} Options + * @param {wp.media.model.Attachment} attachment The attachment to be cropped. + * @param {wp.media.controller.Cropper} controller The cropper controller. + * @return {Object} Options for the imgAreaSelect plugin. */ calculateImageSelectOptions: function( attachment, controller ) { var control = controller.get( 'control' ), @@ -4741,7 +4807,7 @@ /** * Updates the setting and re-renders the control UI. * - * @param {Object} attachment + * @param {Object} attachment Attachment object for the selected image. */ setImageFromAttachment: function( attachment ) { var control = this; @@ -4836,7 +4902,7 @@ /** * Updates the setting and re-renders the control UI. * - * @param {Object} attachment + * @param {Object} attachment Attachment object for the selected image. */ setImageFromAttachment: function( attachment ) { var control = this, @@ -4874,7 +4940,7 @@ /** * Called when the "Remove" link is clicked. Empties the setting. * - * @param {Object} event jQuery Event object + * @param {JQuery.Event} event Event. */ removeFile: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4936,7 +5002,7 @@ * * @since 4.2.0 * - * @return {Object} Options + * @return {wp.customize.HeaderTool.ImageModel} Model for the currently saved header image, or an empty model when none is set. */ getInitialHeaderImage: function() { if ( ! api.get().header_image || ! api.get().header_image_data || _.contains( [ 'remove-header', 'random-default-image', 'random-uploaded-image' ], api.get().header_image ) ) { @@ -4967,9 +5033,9 @@ * theme-specific data, to be fed to the imgAreaSelect plugin in * wp.media.view.Cropper. * - * @param {wp.media.model.Attachment} attachment - * @param {wp.media.controller.Cropper} controller - * @return {Object} Options + * @param {wp.media.model.Attachment} attachment The attachment to be cropped. + * @param {wp.media.controller.Cropper} controller The cropper controller. + * @return {Object} Options for the imgAreaSelect plugin. */ calculateImageSelectOptions: function(attachment, controller) { var xInit = parseInt(_wpCustomizeHeader.data.width, 10), @@ -5038,7 +5104,7 @@ * current theme, a cropping step after selection may be required or * skippable. * - * @param {event} event + * @param {JQuery.Event} event Event. */ openMedia: function(event) { var l10n = _wpMediaViewsL10n; @@ -5097,7 +5163,7 @@ /** * If cropping was skipped, apply the image data directly to the setting. * - * @param {Object} selection + * @param {Object} selection The image selected in the media modal. */ onSkippedCrop: function(selection) { var url = selection.get('url'), @@ -5111,10 +5177,10 @@ * header image data and inserts it into the user-uploaded headers * collection. * - * @param {string} url - * @param {number} attachmentId - * @param {number} width - * @param {number} height + * @param {string} url URL of the header image. + * @param {number} [attachmentId] ID of the image attachment, when the image has one. + * @param {number} [width] Width of the image in pixels. + * @param {number} [height] Height of the image in pixels. */ setImageFromURL: function(url, attachmentId, width, height) { var choice, data = {}; @@ -5168,19 +5234,35 @@ screenshotRendered: false, /** + * Handles the control's ready state. + * * @since 4.2.0 */ ready: function() { var control = this, panel = api.panel( 'themes' ); + /** + * Disables the preview buttons if the theme cannot be switched to. + * + * @return {boolean} True if the preview buttons should be disabled, false otherwise. + */ function disableSwitchButtons() { return ! panel.canSwitchTheme( control.params.theme.id ); } // Temporary special function since supplying SFTP credentials does not work yet. See #42184. + /** + * Disables the install buttons if the theme cannot be installed or if filesystem credentials are needed. + * + * @return {boolean} True if the install buttons should be disabled, false otherwise. + */ function disableInstallButtons() { return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded; } + + /** + * Updates the state of the preview and install buttons based on whether the theme can be switched to or installed. + */ function updateButtons() { control.container.find( 'button.preview, button.preview-theme' ).toggleClass( 'disabled', disableSwitchButtons() ); control.container.find( 'button.theme-install' ).toggleClass( 'disabled', disableInstallButtons() ); @@ -5237,7 +5319,7 @@ * Show or hide the theme based on the presence of the term in the title, description, tags, and author. * * @since 4.2.0 - * @param {Array} terms - An array of terms to search for. + * @param {string[]} terms An array of terms to search for. * @return {boolean} Whether a theme control was activated or not. */ filter: function( terms ) { @@ -5288,6 +5370,7 @@ /** * Rerender the theme from its JS template with the installed type. * + * @param {boolean} installed Whether the theme is installed. * @since 4.9.0 * * @return {void} @@ -5319,8 +5402,8 @@ * Initialize. * * @since 4.9.0 - * @param {string} id - Unique identifier for the control instance. - * @param {Object} options - Options hash for the control instance. + * @param {string} id Unique identifier for the control instance. + * @param {Object} options Options hash for the control instance. * @return {void} */ initialize: function( id, options ) { @@ -5437,8 +5520,8 @@ * Make sure editor gets focused when control is focused. * * @since 4.9.0 - * @param {Object} [params] - Focus params. - * @param {Function} [params.completeCallback] - Function to call when expansion is complete. + * @param {Object} [params] Focus params. + * @param {Function} [params.completeCallback] Function to call when expansion is complete. * @return {void} */ focus: function( params ) { @@ -5459,7 +5542,7 @@ * Initialize syntax-highlighting editor. * * @since 4.9.0 - * @param {Object} codeEditorSettings - Code editor settings. + * @param {Object} codeEditorSettings Code editor settings. * @return {void} */ initSyntaxHighlightingEditor: function( codeEditorSettings ) { @@ -5555,7 +5638,7 @@ * Update error notice. * * @since 4.9.0 - * @param {Array} errorAnnotations - Error annotations. + * @param {Object[]} errorAnnotations Error annotations. * @return {void} */ onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { @@ -5700,7 +5783,7 @@ * * @since 4.9.0 * - * @param {string} datetime - Date/Time string. Accepts Y-m-d[ H:i[:s]] format. + * @param {string} datetime Date/Time string. Accepts Y-m-d[ H:i[:s]] format. * @return {Object|null} Returns object containing date components or null if parse error. */ parseDateTime: function parseDateTime( datetime ) { @@ -5888,8 +5971,8 @@ * Convert hour in twelve hour format to twenty four hour format. * * @since 4.9.0 - * @param {string} hourInTwelveHourFormat - Hour in twelve hour format. - * @param {string} meridian - Either 'am' or 'pm'. + * @param {string} hourInTwelveHourFormat Hour in twelve hour format. + * @param {string} meridian Either 'am' or 'pm'. * @return {string} Hour in twenty four hour format. */ convertHourToTwentyFourHourFormat: function convertHour( hourInTwelveHourFormat, meridian ) { @@ -5959,7 +6042,7 @@ * * @since 4.9.0 * @param {boolean} notify Add or remove the notification. - * @return {wp.customize.DateTimeControl} + * @return {wp.customize.DateTimeControl} The date control instance. */ toggleFutureDateNotification: function toggleFutureDateNotification( notify ) { var control = this, notificationCode, notification; @@ -6123,10 +6206,10 @@ * @since 3.4.0 * * @type {Function} - * @param {...string} ids - One or more ids for controls to obtain. - * @param {deferredControlsCallback} [callback] - Function called when all supplied controls exist. - * @return {wp.customize.Control|undefined|jQuery.promise} Control instance or undefined (if function called with one id param), - * or promise resolving to requested controls. + * @param {...string} ids One or more ids for controls to obtain. + * @param {wp.customize.deferredControlsCallback} [callback] Function called when all supplied controls exist. + * @return {wp.customize.Control|undefined|JQuery.Promise<*>} Control instance or undefined (if function called with one id param), + * or promise resolving to requested controls. * * @example Loop over all registered controls. * wp.customize.control.each( function( control ) { ... } ); @@ -6185,10 +6268,10 @@ * @since 3.4.0 * * @type {Function} - * @param {...string} ids - One or more ids for sections to obtain. - * @param {deferredSectionsCallback} [callback] - Function called when all supplied sections exist. - * @return {wp.customize.Section|undefined|jQuery.promise} Section instance or undefined (if function called with one id param), - * or promise resolving to requested sections. + * @param {...string} ids One or more ids for sections to obtain. + * @param {wp.customize.deferredSectionsCallback} [callback] Function called when all supplied sections exist. + * @return {wp.customize.Section|undefined|JQuery.Promise<*>} Section instance or undefined (if function called with one id param), + * or promise resolving to requested sections. * * @example Loop over all registered sections. * wp.customize.section.each( function( section ) { ... } ) @@ -6220,10 +6303,10 @@ * @since 4.0.0 * * @type {Function} - * @param {...string} ids - One or more ids for panels to obtain. - * @param {deferredPanelsCallback} [callback] - Function called when all supplied panels exist. - * @return {wp.customize.Panel|undefined|jQuery.promise} Panel instance or undefined (if function called with one id param), - * or promise resolving to requested panels. + * @param {...string} ids One or more ids for panels to obtain. + * @param {wp.customize.deferredPanelsCallback} [callback] Function called when all supplied panels exist. + * @return {wp.customize.Panel|undefined|JQuery.Promise<*>} Panel instance or undefined (if function called with one id param), + * or promise resolving to requested panels. * * @example Loop over all registered panels. * wp.customize.panel.each( function( panel ) { ... } ) @@ -6255,10 +6338,10 @@ * @since 4.9.0 * * @type {Function} - * @param {...string} codes - One or more codes for notifications to obtain. - * @param {deferredNotificationsCallback} [callback] - Function called when all supplied notifications exist. - * @return {wp.customize.Notification|undefined|jQuery.promise} Notification instance or undefined (if function called with one code param), - * or promise resolving to requested notifications. + * @param {...string} codes One or more codes for notifications to obtain. + * @param {wp.customize.deferredNotificationsCallback} [callback] Function called when all supplied notifications exist. + * @return {wp.customize.Notification|undefined|JQuery.Promise<*>} Notification instance or undefined (if function called with one code param), + * or promise resolving to requested notifications. * * @example Check if existing notification * exists = wp.customize.notifications.has( 'a_new_day_arrived' ); @@ -6293,10 +6376,11 @@ * @constructs wp.customize.PreviewFrame * @augments wp.customize.Messenger * - * @param {Object} params.container - * @param {Object} params.previewUrl - * @param {Object} params.query - * @param {Object} options + * @param {Object} params The parameters object. + * @param {Object} params.container The container element for the preview frame. + * @param {string} params.previewUrl The URL of the preview. + * @param {Object} params.query The query parameters for the preview URL. + * @param {Object} options The options object. */ initialize: function( params, options ) { var deferred = $.Deferred(); @@ -6500,7 +6584,7 @@ * misnomer as it is not an actual UUID, and it is not universally unique. * This is not to be confused with `api.settings.changeset.uuid`. * - * @return {string} + * @return {string} A unique ID for a preview messenger channel. */ api.PreviewFrame.uuid = function() { return 'preview-' + String( id++ ); @@ -6514,7 +6598,7 @@ * * @since 4.1.0 * - * @param {string} documentTitle + * @param {string} documentTitle The title to insert into the document title template. */ api.setDocumentTitle = function ( documentTitle ) { var tmpl, title; @@ -6528,15 +6612,18 @@ refreshBuffer: null, // Will get set to api.settings.timeouts.windowRefresh. /** + * Initializes the previewer. + * * @constructs wp.customize.Previewer * @augments wp.customize.Messenger * - * @param {Array} params.allowedUrls - * @param {string} params.container A selector or jQuery element for the preview - * frame to be placed. - * @param {string} params.form - * @param {string} params.previewUrl The URL to preview. - * @param {Object} options + * @param {Object} params The parameters object. + * @param {string[]} params.allowedUrls An array of allowed URLs for the preview. + * @param {string} params.container A selector or jQuery element for the preview + * frame to be placed. + * @param {string} params.form A selector or jQuery element for the form to be used for POSTing data to the preview frame. + * @param {string} params.previewUrl The URL to preview. + * @param {Object} [options] The options object. */ initialize: function( params, options ) { var previewer = this, @@ -6684,9 +6771,9 @@ * @since 4.7.0 * @access public * - * @param {Object} data - Data from preview. - * @param {string} data.currentUrl - Current URL. - * @param {Object} data.activePanels - Active panels. + * @param {Object} data Data from preview. + * @param {string} data.currentUrl Current URL. + * @param {Object} data.activePanels Active panels. * @param {Object} data.activeSections Active sections. * @param {Object} data.activeControls Active controls. * @return {void} @@ -6992,9 +7079,9 @@ * @since 4.6.0 * @private * - * @param {Object} args - * @param {Object} args.settingValidities - * @param {boolean} [args.focusInvalidControl=false] + * @param {Object} args Arguments. + * @param {Object} args.settingValidities Mapping of setting IDs to true, or to a mapping of error codes to notification params. + * @param {boolean} [args.focusInvalidControl=false] Whether to focus the first control that has an invalid setting. * @return {void} */ api._handleSettingValidities = function handleSettingValidities( args ) { @@ -7068,7 +7155,7 @@ * * @since 4.6.0 * @param {string[]} settingIds Setting IDs. - * @return {Object} Mapping setting ids to arrays of controls. + * @return {Object.} Mapping setting ids to arrays of controls. */ api.findControlsForSettings = function findControlsForSettings( settingIds ) { var controls = {}, settingControls; @@ -7289,6 +7376,9 @@ updateButtonsState(); section.active.bind( updateButtonsState ); + /** + * Highlights the schedule button to remind the user to schedule the changes. + */ function highlightScheduleButton() { if ( ! cancelScheduleButtonReminder ) { cancelScheduleButtonReminder = api.utils.highlightButton( btnWrapper, { @@ -7303,6 +7393,10 @@ } ); } } + + /** + * Cancels the highlight reminder for the schedule button. + */ function cancelHighlightScheduleButton() { if ( cancelScheduleButtonReminder ) { cancelScheduleButtonReminder(); @@ -7476,7 +7570,7 @@ * @since 4.7.0 Added options param. * @access public * - * @param {Object} [options] Options. + * @param {Object} [options] Options. * @param {boolean} [options.excludeCustomizedSaved=false] Exclude saved settings in customized response (values pending writing to changeset). * @return {Object} Query vars. */ @@ -7514,11 +7608,11 @@ * @since 3.4.0 * @since 4.7.0 Added args param and return value. * - * @param {Object} [args] Args. + * @param {Object} [args] Args. * @param {string} [args.status=publish] Status. - * @param {string} [args.date] Date, in local time in MySQL format. - * @param {string} [args.title] Title - * @return {jQuery.promise} Promise. + * @param {string} [args.date] Date, in local time in MySQL format. + * @param {string} [args.title] Title. + * @return {JQuery.Promise<*>} Promise. */ save: function( args ) { var previewer = this, @@ -7544,6 +7638,11 @@ api.state( 'saving' ).set( true ); + /** + * Captures a setting as modified during the save process. + * + * @param {wp.customize.Setting} setting The setting that was modified. + */ function captureSettingModifiedDuringSave( setting ) { modifiedWhileSaving[ setting.id ] = true; } @@ -7790,8 +7889,6 @@ * Revert the Customizer to its previously-published state. * * @since 4.9.0 - * - * @return {jQuery.promise} Promise. */ trash: function trash() { var request, success, fail; @@ -8183,7 +8280,7 @@ /** * Lock user. * - * @type {object} + * @type {Object} */ lockUser: null, @@ -8195,8 +8292,8 @@ * * @since 4.9.0 * - * @param {string} [code] - Code. - * @param {Object} [params] - Params. + * @param {string} [code] Code. + * @param {Object} [params] Params. */ initialize: function( code, params ) { var notification = this, _code, _params; @@ -8219,7 +8316,7 @@ * * @since 4.9.0 * - * @return {jQuery} Notification container. + * @return {JQuery} Notification container. */ render: function() { var notification = this, li, data, takeOverButton, request; @@ -8285,9 +8382,9 @@ * * @since 4.9.0 * - * @param {Object} [args] - Args. - * @param {Object} [args.lockUser] - Lock user data. - * @param {boolean} [args.allowOverride=false] - Whether override is allowed. + * @param {Object} [args] Args. + * @param {Object} [args.lockUser] Lock user data. + * @param {boolean} [args.allowOverride=false] Whether override is allowed. * @return {void} */ function startLock( args ) { @@ -8367,7 +8464,7 @@ /** * Remove parameter from the URL. * - * @param {Array} params - Parameter names to remove. + * @param {string[]} params Parameter names to remove. * @return {void} */ function stripParamsFromLocation( params ) { @@ -8393,7 +8490,7 @@ * * @since 4.9.0 * - * @param {string} [notification] - A notification to display. + * @param {string} [notification] A notification to display. * @return {void} */ function addSiteEditorNotification( notification ) { @@ -8750,9 +8847,9 @@ * @since 4.7.0 * @access private * - * @param {Object} header - Header. - * @param {number} scrollTop - Scroll top. - * @param {number} scrollDirection - Scroll direction, negative number being up and positive being down. + * @param {Object} header Header. + * @param {number} scrollTop Scroll top. + * @param {number} scrollDirection Scroll direction, negative number being up and positive being down. * @return {void} */ positionStickyHeader = function( header, scrollTop, scrollDirection ) { @@ -8888,6 +8985,11 @@ (function() { var isInsideIframe = false; + /** + * Determine whether the Customizer is in a clean state. + * + * @return {boolean} True if the Customizer is in a clean state, false otherwise. + */ function isCleanState() { var defaultChangesetStatus; @@ -8924,6 +9026,9 @@ isInsideIframe = true; }); + /** + * Starts prompting the user before unloading the Customizer if there are unsaved changes. + */ function startPromptingBeforeUnload() { api.unbind( 'change', startPromptingBeforeUnload ); api.state( 'selectedChangesetStatus' ).unbind( startPromptingBeforeUnload ); @@ -8943,6 +9048,11 @@ api.state( 'selectedChangesetStatus' ).bind( startPromptingBeforeUnload ); api.state( 'selectedChangesetDate' ).bind( startPromptingBeforeUnload ); + /** + * Requests to close the Customizer, prompting the user to save changes if necessary. + * + * @return {JQuery.Promise} A promise that resolves if the user is cleared to close the Customizer, or rejects if the user cancels the close. + */ function requestClose() { var clearedToClose = $.Deferred(), dismissAutoSave = false, dismissLock = false; @@ -9332,12 +9442,19 @@ api.previewer.send( 'edit-shortcut-visibility', visibility ); } ); - // Autosave changeset. + /** + * Starts autosaving changeset when a change is made. + */ function startAutosaving() { var timeoutId, updateChangesetWithReschedule, scheduleChangesetUpdate, updatePending = false; api.unbind( 'change', startAutosaving ); // Ensure startAutosaving only fires once. + /** + * Handles changes to the saved state of the changeset. + * + * @param {boolean} isSaved Whether the changeset is saved or not. + */ function onChangeSaved( isSaved ) { if ( ! isSaved && ! api.settings.changeset.autosaved ) { api.settings.changeset.autosaved = true; // Once a change is made then autosaving kicks in. diff --git a/src/js/_enqueues/wp/customize/loader.js b/src/js/_enqueues/wp/customize/loader.js index 2326f1f7dfccc..0f053f4c69505 100644 --- a/src/js/_enqueues/wp/customize/loader.js +++ b/src/js/_enqueues/wp/customize/loader.js @@ -12,7 +12,13 @@ */ window.wp = window.wp || {}; -(function( exports, $ ){ +/** + * The WordPress Customizer loader API. + * + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. + */ +(function( wp, $ ){ var api = wp.customize, Loader; @@ -27,7 +33,7 @@ window.wp = window.wp || {}; * By default, any element in the body with the load-customize class will open * an iframe overlay with the URL specified. * - * e.g. Open Customizer + * e.g. Open Customizer * * @memberOf wp.customize * @@ -76,6 +82,12 @@ window.wp = window.wp || {}; } }, + /** + * Handle popstate event. + * + * @param {JQuery.Event} e The popstate event. + * @return {void} + */ popstate: function( e ) { var state = e.originalEvent.state; if ( state && state.customize ) { @@ -85,6 +97,9 @@ window.wp = window.wp || {}; } }, + /** + * Handle hashchange event. + */ hashchange: function() { var hash = window.location.toString().split('#')[1]; @@ -97,6 +112,11 @@ window.wp = window.wp || {}; } }, + /** + * Handle beforeunload event. + * + * @return {string|void} Confirmation message if there are unsaved changes. + */ beforeunload: function () { if ( ! Loader.saved() ) { return Loader.settings.l10n.saveAlert; @@ -106,7 +126,8 @@ window.wp = window.wp || {}; /** * Open the Customizer overlay for a specific URL. * - * @param string src URL to load in the Customizer. + * @param {string} src URL to load in the Customizer. + * @return {string|void} The URL, when navigating to it directly on mobile. */ open: function( src ) { @@ -189,6 +210,11 @@ window.wp = window.wp || {}; this.trigger( 'open' ); }, + /** + * Push the state of the Customizer onto the history stack. + * + * @param {string} src URL to push. + */ pushState: function ( src ) { var hash = src.split( '?' )[1]; @@ -270,10 +296,16 @@ window.wp = window.wp || {}; * Overlay hide/show utility methods. */ overlay: { + /** + * Show the overlay. + */ show: function() { this.element.fadeIn( 200, Loader.opened ); }, + /** + * Hide the overlay. + */ hide: function() { this.element.fadeOut( 200, Loader.closed ); } diff --git a/src/js/_enqueues/wp/customize/models.js b/src/js/_enqueues/wp/customize/models.js index e72266327a333..a56f035728464 100644 --- a/src/js/_enqueues/wp/customize/models.js +++ b/src/js/_enqueues/wp/customize/models.js @@ -3,6 +3,13 @@ */ /* global _wpCustomizeHeader */ + +/** + * The WordPress Customizer models API. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wp The WordPress global object. + */ (function( $, wp ) { var api = wp.customize; /** @namespace wp.customize.HeaderTool */ @@ -21,10 +28,15 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.ImageModel * - * @constructor + * @class * @augments Backbone.Model */ api.HeaderTool.ImageModel = Backbone.Model.extend(/** @lends wp.customize.HeaderTool.ImageModel.prototype */{ + /** + * Returns the default attributes for a header image. + * + * @return {Object} Default attributes. + */ defaults: function() { return { header: { @@ -39,16 +51,25 @@ }; }, + /** + * Initializes the model, hiding the header when asked to. + */ initialize: function() { this.on('hide', this.hide, this); }, + /** + * Hides the header image, removing it from the site. + */ hide: function() { this.set('choice', ''); api('header_image').set('remove-header'); api('header_image_data').set('remove-header'); }, + /** + * Removes the image, hiding the header first if it is the current one. + */ destroy: function() { var data = this.get('header'), curr = api.HeaderTool.currentHeader.get('header').attachment_id; @@ -69,6 +90,9 @@ this.trigger('destroy', this, this.collection); }, + /** + * Makes this image the current header image. + */ save: function() { if (this.get('random')) { api('header_image').set(this.get('header').random); @@ -86,6 +110,9 @@ api.HeaderTool.combinedList.trigger('control:setImage', this); }, + /** + * Adds the image to the theme's uploaded headers. + */ importImage: function() { var data = this.get('header'); if (data.attachment_id === undefined) { @@ -100,6 +127,11 @@ } ); }, + /** + * Returns whether the image needs cropping for this theme. + * + * @return {boolean} Whether the image should be cropped. + */ shouldBeCropped: function() { if (this.get('themeFlexWidth') === true && this.get('themeFlexHeight') === true) { @@ -136,17 +168,25 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.ChoiceList * - * @constructor + * @class * @augments Backbone.Collection */ api.HeaderTool.ChoiceList = Backbone.Collection.extend({ model: api.HeaderTool.ImageModel, - // Ordered from most recently used to least. + /** + * Orders the collection from most recently used to least. + * + * @param {Backbone.Model} model The model to sort. + * @return {number} The sort order. + */ comparator: function(model) { return -model.get('header').timestamp; }, + /** + * Initializes the collection from the uploaded header images. + */ initialize: function() { var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''), isRandom = this.isRandomChoice(api.get().header_image); @@ -192,6 +232,11 @@ } }, + /** + * Removes an image's previous crop once it has been replaced. + * + * @param {Backbone.Model} model Model. + */ maybeRemoveOldCrop: function( model ) { var newID = model.get( 'header' ).attachment_id || false, oldCrop; @@ -211,12 +256,20 @@ } }, + /** + * Adds the random choice once a single image is left. + */ maybeAddRandomChoice: function() { if (this.size() === 1) { this.addRandomChoice(); } }, + /** + * Adds the random image choice to the collection. + * + * @param {string} initialChoice Initial choice. + */ addRandomChoice: function(initialChoice) { var isRandomSameType = RegExp(this.type).test(initialChoice), randomChoice = 'random-' + this.type + '-image'; @@ -234,14 +287,30 @@ }); }, + /** + * Returns whether a choice is one of the random image choices. + * + * @param {string} choice Choice. + * @return {boolean} Whether the choice is random. + */ isRandomChoice: function(choice) { return (/^random-(uploaded|default)-image$/).test(choice); }, + /** + * Returns whether the list title should be hidden. + * + * @return {boolean} Whether the title should be hidden. + */ shouldHideTitle: function() { return this.size() < 2; }, + /** + * Marks a single image as the selected one. + * + * @param {Backbone.Model} model Model. + */ setImage: function(model) { this.each(function(m) { m.set('selected', false); @@ -252,6 +321,9 @@ } }, + /** + * Clears the selection. + */ removeImage: function() { this.each(function(m) { m.set('selected', false); @@ -266,11 +338,14 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.DefaultsList * - * @constructor + * @class * @augments wp.customize.HeaderTool.ChoiceList * @augments Backbone.Collection */ api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({ + /** + * Initializes the collection from the theme's default header images. + */ initialize: function() { this.type = 'default'; this.data = _wpCustomizeHeader.defaults; diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index 607740014e5e4..c2fecd9232ced 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -3,6 +3,14 @@ */ /* global menus, _wpCustomizeNavMenusSettings, wpNavMenu, console */ + +/** + * The WordPress Customizer nav menus API. + * + * @param {Object} api The Customizer API. + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. + */ ( function( api, wp, $ ) { 'use strict'; @@ -44,7 +52,7 @@ * * @alias wp.customize.Menus.generatePlaceholderAutoIncrementId * - * @return {number} + * @return {number} A negative integer ID. */ api.Menus.generatePlaceholderAutoIncrementId = function() { return -Math.ceil( api.Menus.data.phpIntMax * Math.random() ); @@ -95,10 +103,10 @@ * @since 4.7.0 * @alias wp.customize.Menus.insertAutoDraftPost * - * @param {Object} params - Parameters for the draft post to create. - * @param {string} params.post_type - Post type to add. - * @param {string} params.post_title - Post title to use. - * @return {jQuery.promise} Promise resolved with the added post. + * @param {Object} params Parameters for the draft post to create. + * @param {string} params.post_type Post type to add. + * @param {string} params.post_title Post title to use. + * @return {JQuery.Promise<*>} Promise resolved with the added post. */ api.Menus.insertAutoDraftPost = function insertAutoDraftPost( params ) { var request, deferred = $.Deferred(); @@ -390,8 +398,8 @@ * @since 4.7.0 Changed function signature to take list of item types instead of single type/object. * @access private * - * @param {Array.} itemTypes List of objects containing type and key. - * @param {string} deprecated Formerly the object parameter. + * @param {Object[]} itemTypes List of objects containing type and key. + * @param {string} deprecated Formerly the object parameter. * @return {void} */ loadItems: function( itemTypes, deprecated ) { @@ -630,7 +638,7 @@ * @since 4.7.0 * @private * - * @param {jQuery.Event} event Event. + * @param {JQuery.Event} event Event. * @return {void} */ _submitNew: function( event ) { @@ -656,7 +664,7 @@ * @since 4.7.0 * @private * - * @param {jQuery} container + * @param {JQuery} container The container of the form for creating the new item. * @return {void} */ submitNew: function( container ) { @@ -904,11 +912,15 @@ }, 2000 ), /** + * Adds the active field class for the section container. + * * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. */ checked: function() {}, /** + * Removes the active field class for the section container. + * * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. */ unchecked: function() {}, @@ -919,7 +931,7 @@ * @since 4.3.0 * @private * - * @return {Array} Fields (columns) that are hidden. + * @return {string} Comma separated list of the fields (columns) that are hidden. */ hidden: function() { return $( '.hide-column-tog' ).not( ':checked' ).map( function() { @@ -945,8 +957,8 @@ * * @since 4.3.0 * - * @param {string} id - * @param {Object} options + * @param {string} id The ID for the section. + * @param {Object} options Options. */ initialize: function( id, options ) { var section = this; @@ -1014,7 +1026,7 @@ /** * Update the active field class for the content container for a given checkbox toggle. * - * @this {jQuery} + * @this {HTMLInputElement} * @return {void} */ handleFieldActiveToggle = function() { @@ -1126,7 +1138,7 @@ }, /** - * + * Refreshes the list of theme locations. */ refreshAssignedLocations: function() { var section = this, @@ -1141,7 +1153,9 @@ }, /** - * @param {Array} themeLocationSlugs Theme location slugs. + * Updates the section title to reflect the theme locations assigned to this menu. + * + * @param {string[]} themeLocationSlugs Theme location slugs. */ updateAssignedLocationsInSectionTitle: function( themeLocationSlugs ) { var section = this, @@ -1334,7 +1348,7 @@ * Handle setting addition. * * @since 4.9.0 - * @param {wp.customize.Setting} setting - Added setting. + * @param {wp.customize.Setting} setting Added setting. * @return {void} */ function addChangeEventListener( setting ) { @@ -1348,7 +1362,7 @@ * Handle setting removal. * * @since 4.9.0 - * @param {wp.customize.Setting} setting - Removed setting. + * @param {wp.customize.Setting} setting Removed setting. * @return {void} */ function removeChangeEventListener( setting ) { @@ -1363,7 +1377,7 @@ api.bind( 'removed', removeChangeEventListener ); updateNoticeVisibility(); - api.Section.prototype.attachEvents.apply( section, arguments ); + api.Section.prototype.attachEvents.call( section ); }, /** @@ -1483,7 +1497,7 @@ * * @since 4.9.0 * - * @param {string|null} locationId - The ID of the location to select. `null` clears all selections. + * @param {string|null} locationId The ID of the location to select. `null` clears all selections. * @return {void} */ selectDefaultLocation: function( locationId ) { @@ -1642,8 +1656,8 @@ * Refreshes advanced accessibility buttons for one menu item. * Shows or hides buttons based on the location of the menu item. * - * @param {Object} itemToRefresh The menu item that might need its advanced accessibility buttons refreshed - * + * @param {Object} itemToRefresh The menu item that might need its advanced accessibility buttons refreshed. + * * @since 6.6.0 */ refreshAdvancedAccessibilityOfItem: function( itemToRefresh ) { @@ -1723,7 +1737,7 @@ } control.renderContent(); control.deferred.embedded.resolve(); // This triggers control.ready(). - + // Mark all menu items as unprocessed. $( 'button.item-edit' ).data( 'needs_accessibility_refresh', true ); }, @@ -1802,7 +1816,7 @@ control.moveRight(); control.params.depth += 1; } - + moveBtn.focus(); // Re-focus after the container was moved. // Mark all menu items as unprocessed. @@ -2036,8 +2050,9 @@ }, /** + * Gets the depth of the menu item. * - * @return {number} + * @return {number} The depth of the menu item. */ getDepth: function() { var control = this, setting = control.setting(), depth = 0; @@ -2103,7 +2118,9 @@ **********************************************************************/ /** - * @return {wp.customize.controlConstructor.nav_menu|null} + * Gets the menu control that this menu item belongs to. + * + * @return {wp.customize.Menus.MenuControl|null} The menu control, or null if not found. */ getMenuControl: function() { var control = this, settingValue = control.setting(); @@ -2127,17 +2144,17 @@ /** * @since 4.6.0 * - * @param {Boolean} expanded - * @param {Object} [params] - * @return {Boolean} False if state already applied. + * @param {boolean} expanded The new state to apply. + * @param {Object} [params] Object containing options for expand/collapse. + * @return {boolean} False if state already applied. */ _toggleExpanded: api.Section.prototype._toggleExpanded, /** * @since 4.6.0 * - * @param {Object} [params] - * @return {Boolean} False if already expanded. + * @param {Object} [params] Object containing options for expansion. + * @return {boolean} False if already expanded. */ expand: api.Section.prototype.expand, @@ -2146,8 +2163,8 @@ * * @since 4.5.0 Added params.completeCallback. * - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. + * @param {Object} [params] Optional params. + * @param {Function} [params.completeCallback] Function to call when the form toggle has finished animating. */ expandForm: function( params ) { this.expand( params ); @@ -2156,8 +2173,8 @@ /** * @since 4.6.0 * - * @param {Object} [params] - * @return {Boolean} False if already collapsed. + * @param {Object} [params] Object containing options for collapse. + * @return {boolean} False if already collapsed. */ collapse: api.Section.prototype.collapse, @@ -2166,8 +2183,8 @@ * * @since 4.5.0 Added params.completeCallback. * - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. + * @param {Object} [params] Optional params. + * @param {Function} [params.completeCallback] Function to call when the form toggle has finished animating. */ collapseForm: function( params ) { this.collapse( params ); @@ -2179,9 +2196,9 @@ * @deprecated this is poor naming, and it is better to directly set control.expanded( showOrHide ) * @since 4.5.0 Added params.completeCallback. * - * @param {boolean} [showOrHide] - If not supplied, will be inverse of current visibility - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. + * @param {boolean} [showOrHide] If not supplied, will be inverse of current visibility. + * @param {Object} [params] Optional params. + * @param {Function} [params.completeCallback] Function to call when the form toggle has finished animating. */ toggleForm: function( showOrHide, params ) { if ( typeof showOrHide === 'undefined' ) { @@ -2198,9 +2215,9 @@ * Expand or collapse the menu item control. * * @since 4.6.0 - * @param {boolean} [showOrHide] - If not supplied, will be inverse of current visibility - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. + * @param {boolean} [showOrHide] If not supplied, will be inverse of current visibility. + * @param {Object} [params] Optional params. + * @param {Function} [params.completeCallback] Function to call when the form toggle has finished animating. */ onChangeExpanded: function( showOrHide, params ) { var self = this, $menuitem, $inside, complete; @@ -2267,8 +2284,8 @@ * * @since 4.5.0 Added params.completeCallback. * - * @param {Object} [params] - Params object. - * @param {Function} [params.completeCallback] - Optional callback function when focus has completed. + * @param {Object} [params] Params object. + * @param {Function} [params.completeCallback] Optional callback function when focus has completed. */ focus: function( params ) { params = params || {}; @@ -2338,7 +2355,7 @@ * * @private * - * @param {number} offset 1|-1 + * @param {number} offset The number of positions to move the item, either 1 or -1. */ _changePosition: function( offset ) { var control = this, @@ -2398,7 +2415,7 @@ * * @private * - * @param {number} offset 1|-1 + * @param {number} offset The number of levels to change the depth by, either 1 or -1. */ _changeDepth: function( offset ) { if ( 1 !== offset && -1 !== offset ) { @@ -2594,7 +2611,7 @@ * * @since 4.9.0 * - * @param {Object.} selections - A map of location selections. + * @param {Object.} selections A map of location selections. * @return {void} */ setSelections: function( selections ) { @@ -2781,7 +2798,7 @@ * Notice that the UI aspects here are handled by wpNavMenu.initSortables() * which is called in MenuSection.onChangeExpanded() * - * @param {Object} menuList - The element that has sortable(). + * @param {Object} menuList The element that has sortable(). */ _setupSortable: function( menuList ) { var control = this; @@ -2983,7 +3000,7 @@ /** * Enable/disable the reordering UI * - * @param {boolean} showOrHide to enable/disable reordering + * @param {boolean} showOrHide Whether to enable or disable reordering. */ toggleReordering: function( showOrHide ) { var addNewItemBtn = this.container.find( '.add-new-menu-item' ), @@ -3019,7 +3036,9 @@ }, /** - * @return {wp.customize.controlConstructor.nav_menu_item[]} + * Get all of the nav_menu_item controls for this menu. + * + * @return {wp.customize.Menus.MenuItemControl[]} The nav_menu_item controls for this menu. */ getMenuItemControls: function() { var menuControl = this, @@ -3116,15 +3135,15 @@ * has child items, this function will only be called once all of the * settings have been updated. */ - debouncedReflowMenuItems: _.debounce( function() { - this.reflowMenuItems.apply( this, arguments ); + debouncedReflowMenuItems: _.debounce( function( ...args ) { + this.reflowMenuItems.apply( this, args ); }, 0 ), /** * Add a new item to this menu. * - * @param {Object} item - Value for the nav_menu_item setting to be created. - * @return {wp.customize.Menus.controlConstructor.nav_menu_item} The newly-created nav_menu_item control instance. + * @param {Object} item Value for the nav_menu_item setting to be created. + * @return {wp.customize.Menus.MenuItemControl} The newly-created nav_menu_item control instance. */ addItemToMenu: function( item ) { var menuControl = this, customizeId, settingArgs, setting, menuItemControl, placeholderId, position = 0, priority = 10, @@ -3189,7 +3208,9 @@ * * @since 4.9.0 * - * @param {wp.customize.controlConstructor.nav_menu_item[]} optionalMenuItemControls + * @param {wp.customize.Menus.MenuItemControl[]} [optionalMenuItemControls] The menu item controls to + * consider. Defaults to all of + * this menu's item controls. */ updateInvitationVisibility: function ( optionalMenuItemControls ) { var menuItemControls = optionalMenuItemControls || this.getMenuItemControls(); @@ -3263,9 +3284,9 @@ * * @alias wp.customize.Menus.applySavedData * - * @param {Object} data - * @param {Array} data.nav_menu_updates - * @param {Array} data.nav_menu_item_updates + * @param {Object} data Data returned in the customize_save response. + * @param {Object[]} data.nav_menu_updates Result of saving each nav menu, with term_id, previous_term_id, error, status, and saved_value properties. + * @param {Object[]} data.nav_menu_item_updates Result of saving each nav menu item, with post_id, previous_post_id, error, and status properties. */ api.Menus.applySavedData = function( data ) { @@ -3495,7 +3516,7 @@ * * @alias wp.customize.Menus.focusMenuItemControl * - * @param {string} menuItemId + * @param {string} menuItemId The ID of the menu item whose control to focus. */ api.Menus.focusMenuItemControl = function( menuItemId ) { var control = api.Menus.getMenuItemControl( menuItemId ); @@ -3509,8 +3530,8 @@ * * @alias wp.customize.Menus.getMenuControl * - * @param menuId - * @return {wp.customize.controlConstructor.menus[]} + * @param {string|number} menuId The ID of the menu. + * @return {wp.customize.Menus.MenuControl|undefined} The menu control, or undefined if not found. */ api.Menus.getMenuControl = function( menuId ) { return api.control( 'nav_menu[' + menuId + ']' ); @@ -3521,17 +3542,20 @@ * * @alias wp.customize.Menus.getMenuItemControl * - * @param {string} menuItemId - * @return {Object|null} + * @param {string} menuItemId The ID of the menu item. + * @return {wp.customize.Menus.MenuItemControl|undefined} The menu item control, or undefined if not found. */ api.Menus.getMenuItemControl = function( menuItemId ) { return api.control( menuItemIdToSettingId( menuItemId ) ); }; /** + * Gets the setting ID for a given menu item ID. + * * @alias wp.customize.Menus~menuItemIdToSettingId * - * @param {string} menuItemId + * @param {string} menuItemId The ID of the menu item. + * @return {string} The setting ID for the menu item. */ function menuItemIdToSettingId( menuItemId ) { return 'nav_menu_item[' + menuItemId + ']'; @@ -3543,8 +3567,8 @@ * * @alias wp.customize.Menus~displayNavMenuName * - * @param {string} name - * @return {string} + * @param {string} [name] The menu name. + * @return {string} The sanitized display name, or a fallback "unnamed" string if empty. */ function displayNavMenuName( name ) { name = name || ''; diff --git a/src/js/_enqueues/wp/customize/preview-nav-menus.js b/src/js/_enqueues/wp/customize/preview-nav-menus.js index b5bec37b52aaf..978be42ef1a71 100644 --- a/src/js/_enqueues/wp/customize/preview-nav-menus.js +++ b/src/js/_enqueues/wp/customize/preview-nav-menus.js @@ -5,6 +5,13 @@ /* global _wpCustomizePreviewNavMenusExports */ /** @namespace wp.customize.navMenusPreview */ + +/** + * @param {JQueryStatic} $ The jQuery object. + * @param {_.UnderscoreStatic} _ The Underscore.js object. + * @param {Object} wp The WordPress global object. + * @param {Object} api The Customizer API. + */ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( $, _, wp, api ) { 'use strict'; @@ -90,15 +97,22 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( /** * Constructor. * + * The nav menu arguments are normally given as the container context, which is what the + * partial is constructed with when the document is scanned, and they may also be passed + * in the params. Either way they have to be present and to carry an args_hmac matching + * the one named in the ID, since the constructor throws when they do not. + * * @since 4.5.0 - * @param {string} id - Partial ID. - * @param {Object} options - * @param {Object} options.params - * @param {Object} options.params.navMenuArgs - * @param {string} options.params.navMenuArgs.args_hmac - * @param {string} [options.params.navMenuArgs.theme_location] - * @param {number} [options.params.navMenuArgs.menu] - * @param {Object} [options.constructingContainerContext] + * + * @param {string} id Partial ID. + * @param {Object} options Options. + * @param {Object} options.params Parameters for the partial. + * @param {Object} options.params.navMenuArgs Arguments the nav menu was rendered with. + * @param {string} options.params.navMenuArgs.args_hmac HMAC of those arguments, which has to match the ID. + * @param {string} [options.params.navMenuArgs.theme_location] Theme location the menu is assigned to. + * @param {number} [options.params.navMenuArgs.menu] ID of the menu. + * @param {Object} [options.constructingContainerContext] Context of the container element, used as the nav + * menu arguments when no params are supplied. */ initialize: function( id, options ) { var partial = this, matches, argsHmac; @@ -131,10 +145,10 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * Return whether the setting is related to this partial. * * @since 4.5.0 - * @param {wp.customize.Value|string} setting - Object or ID. - * @param {number|Object|false|null} newValue - New value, or null if the setting was just removed. - * @param {number|Object|false|null} oldValue - Old value, or null if the setting was just added. - * @return {boolean} + * @param {wp.customize.Value|string} setting Object or ID. + * @param {number|Object|false|null} newValue New value, or null if the setting was just removed. + * @param {number|Object|false|null} oldValue Old value, or null if the setting was just added. + * @return {boolean} True if the setting is related to this partial, false otherwise. */ isRelatedSetting: function( setting, newValue, oldValue ) { var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting, _newValue, _oldValue, urlParser; @@ -210,7 +224,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * * @since 4.5.0 * - * @return {Promise} + * @return {JQuery.Promise<*>} Promise that is resolved when the refresh is complete, or rejected if the partial is no longer associated with a menu. */ refresh: function() { var partial = this, menuId, deferred = $.Deferred(); @@ -234,7 +248,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * Render content. * * @inheritdoc - * @param {wp.customize.selectiveRefresh.Placement} placement + * @param {wp.customize.selectiveRefresh.Placement} placement The placement to render into. */ renderContent: function( placement ) { var partial = this, previousContainer = placement.container; @@ -263,7 +277,10 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( /** * Request full refresh if there are nav menu instances that lack partials which also match the supplied args. * - * @param {Object} navMenuInstanceArgs + * @since 4.5.0 + * + * @param {Object} navMenuInstanceArgs Arguments for a nav menu instance, which may include menu and/or theme_location. + * @return {boolean} Whether a full refresh was requested. */ self.handleUnplacedNavMenuInstances = function( navMenuInstanceArgs ) { var unplacedNavMenuInstances; @@ -282,10 +299,10 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * * @since 4.5.0 * - * @param {wp.customize.Value} setting - * @param {Object} [options] - * @param {boolean} options.fire Whether to invoke the callback after binding. - * This is used when a dynamic setting is added. + * @param {wp.customize.Value} setting The setting to listen to. + * @param {Object} [options] Options. + * @param {boolean} [options.fire] Whether to invoke the callback after binding. + * This is used when a dynamic setting is added. * @return {boolean} Whether the setting was bound. */ self.bindSettingListener = function( setting, options ) { @@ -330,7 +347,8 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * * @since 4.5.0 * - * @param {wp.customize.Value} setting + * @param {wp.customize.Value} setting The setting to stop listening to. + * @return {void} */ self.unbindSettingListener = function( setting ) { setting.unbind( this.onChangeNavMenuSetting ); @@ -344,6 +362,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * @since 4.5.0 * * @this {wp.customize.Value} + * @return {void} */ self.onChangeNavMenuSetting = function() { var setting = this; @@ -373,6 +392,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * @param {Object} newItem New value for nav_menu_item[] setting. * @param {Object} oldItem Old value for nav_menu_item[] setting. * @this {wp.customize.Value} + * @return {void} */ self.onChangeNavMenuItemSetting = function( newItem, oldItem ) { var item = newItem || oldItem, navMenuSetting; @@ -388,6 +408,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * @since 4.5.0 * * @this {wp.customize.Value} + * @return {void} */ self.onChangeNavMenuLocationsSetting = function() { var setting = this, hasNavMenuInstance; @@ -412,6 +433,8 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * Also this applies even if a nav menu is not partial-refreshable. * * @since 4.5.0 + * + * @return {void} */ self.highlightControls = function() { var selector = '.menu-item'; diff --git a/src/js/_enqueues/wp/customize/preview-widgets.js b/src/js/_enqueues/wp/customize/preview-widgets.js index e1191a65ad07f..0b67148432c3d 100644 --- a/src/js/_enqueues/wp/customize/preview-widgets.js +++ b/src/js/_enqueues/wp/customize/preview-widgets.js @@ -11,10 +11,10 @@ * * @namespace wp.customize.widgetsPreview * - * @param {jQuery} $ The jQuery object. - * @param {Object} _ The utilities library. - * @param {Object} wp Current WordPress environment instance. - * @param {Object} api Information from the API. + * @param {JQueryStatic} $ The jQuery object. + * @param {_.UnderscoreStatic} _ The Underscore.js object. + * @param {Object} wp The WordPress global object. + * @param {Object} api The Customizer API. * * @return {Object} Widget-related variables. */ @@ -93,10 +93,9 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * @alias wp.customize.widgetsPreview.WidgetPartial * @memberOf wp.customize.widgetsPreview * - * @param {string} id The partial's ID. - * @param {Object} options Options used to initialize the partial's - * instance. - * @param {Object} options.params The options parameters. + * @param {string} id The partial's ID. + * @param {Object} [options] Options used to initialize the partial's instance. + * @param {Object} [options.params] The options parameters. */ initialize: function( id, options ) { var partial = this, matches; @@ -124,7 +123,7 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @return {Promise|void} Either a promise postponing the refresh, or void. + * @return {JQuery.Promise<*>} Promise for the request to render the partial. */ refresh: function() { var partial = this, refreshDeferred; @@ -143,8 +142,7 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * removed from the widget control. * * @inheritDoc - * @param {wp.customize.selectiveRefresh.Placement} placement The placement - * function. + * @param {wp.customize.selectiveRefresh.Placement} placement The placement to render into. * * @return {void} */ @@ -164,15 +162,15 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @class + * @constructs * @augments wp.customize.selectiveRefresh.Partial * * @memberOf wp.customize.widgetsPreview * @alias wp.customize.widgetsPreview.SidebarPartial * - * @param {string} id The partial's ID. - * @param {Object} options Options used to initialize the partial's instance. - * @param {Object} options.params The options parameters. + * @param {string} id The partial's ID. + * @param {Object} [options] Options used to initialize the partial's instance. + * @param {Object} [options.params] The options parameters. */ initialize: function( id, options ) { var partial = this, matches; @@ -293,8 +291,8 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @return {Array} An array containing placement objects for each of the - * dynamic sidebar boundary nodes. + * @return {wp.customize.selectiveRefresh.Placement[]} A placement for each of the dynamic + * sidebar boundary nodes. */ placements: function() { var partial = this; @@ -320,7 +318,7 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * @throws {Error} If the setting doesn't exist in the API. * @throws {Error} If the API doesn't pass an array of widget IDs. * - * @return {Array} A shallow copy of the array containing widget IDs. + * @return {string[]} A shallow copy of the array containing widget IDs. */ getWidgetIds: function() { var sidebarPartial = this, settingId, widgetIds; @@ -344,8 +342,7 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @return {Array.} List of placements - * that were reflowed. + * @return {wp.customize.selectiveRefresh.Placement[]} List of placements that were reflowed. */ reflowWidgets: function() { var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = []; @@ -477,8 +474,8 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @param {Array} newWidgetIds New widget IDs. - * @param {Array} oldWidgetIds Old widget IDs. + * @param {string[]} newWidgetIds New widget IDs. + * @param {string[]} oldWidgetIds Old widget IDs. * * @return {void} */ @@ -535,7 +532,7 @@ wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( * * @since 4.5.0 * - * @return {Promise} A promise postponing the refresh. + * @return {JQuery.Promise<*>} Promise resolved once the sidebar's widgets have been reflowed, or rejected when the sidebar has no placements. */ refresh: function() { var partial = this, deferred = $.Deferred(); diff --git a/src/js/_enqueues/wp/customize/preview.js b/src/js/_enqueues/wp/customize/preview.js index 375cd2104ba0f..f1f83803ca117 100644 --- a/src/js/_enqueues/wp/customize/preview.js +++ b/src/js/_enqueues/wp/customize/preview.js @@ -1,9 +1,14 @@ -/* +/** + * @output wp-includes/js/customize-preview.js + */ + +/** * Script run inside a Customizer preview frame. * - * @output wp-includes/js/customize-preview.js + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. */ -(function( exports, $ ){ +(function( wp, $ ){ var api = wp.customize, debounce, currentHistoryState = {}; @@ -74,13 +79,16 @@ /** * Returns a debounced version of the function. * + * @param {Function} fn Function to debounce. + * @param {number} delay Delay in milliseconds. + * @param {Object} [context] Context to invoke the function in. Defaults to the calling context. * @todo Require Underscore.js for this file and retire this. + * + * @return {Function} Debounced function. */ debounce = function( fn, delay, context ) { var timeout; - return function() { - var args = arguments; - + return function( ...args ) { context = context || this; clearTimeout( timeout ); @@ -95,15 +103,17 @@ * @memberOf wp.customize * @alias wp.customize.Preview * - * @constructor + * @class * @augments wp.customize.Messenger * @augments wp.customize.Class * @mixes wp.customize.Events */ api.Preview = api.Messenger.extend(/** @lends wp.customize.Preview.prototype */{ /** - * @param {Object} params - Parameters to configure the messenger. - * @param {Object} options - Extend any instance parameter or method with this object. + * Initializes the previewer. + * + * @param {Object} params Parameters to configure the messenger. + * @param {Object} options Extend any instance parameter or method with this object. */ initialize: function( params, options ) { var preview = this, urlParser = document.createElement( 'a' ); @@ -142,7 +152,8 @@ * @since 4.7.0 * @access public * - * @param {jQuery.Event} event Event. + * @param {JQuery.Event} event Event. + * @return {void} */ handleLinkClick: function( event ) { var preview = this, link, isInternalJumpLink; @@ -188,7 +199,8 @@ * @since 4.7.0 * @access public * - * @param {jQuery.Event} event Event. + * @param {JQuery.Event} event Event. + * @return {void} */ handleFormSubmit: function( event ) { var preview = this, urlParser, form; @@ -232,7 +244,6 @@ * * @since 4.7.0 * @access protected - * @access private * * @return {void} */ @@ -272,12 +283,12 @@ * @since 4.7.0 * @access public * - * @param {HTMLAnchorElement|HTMLAreaElement} element Link element. - * @param {string} element.search Query string. - * @param {string} element.pathname Path. - * @param {string} element.host Host. - * @param {Object} [options] - * @param {Object} [options.allowAdminAjax=false] Allow admin-ajax.php requests. + * @param {HTMLAnchorElement|HTMLAreaElement} element Link element. + * @param {string} element.search Query string. + * @param {string} element.pathname Path. + * @param {string} element.host Host. + * @param {Object} [options] Options. + * @param {Object} [options.allowAdminAjax=false] Allow admin-ajax.php requests. * @return {boolean} Is appropriate for changeset link. */ api.isLinkPreviewable = function isLinkPreviewable( element, options ) { @@ -328,10 +339,10 @@ * @since 4.7.0 * @access protected * - * @param {HTMLAnchorElement|HTMLAreaElement} element Link element. - * @param {string} element.search Query string. - * @param {string} element.host Host. - * @param {string} element.protocol Protocol. + * @param {HTMLAnchorElement|HTMLAreaElement} element Link element. + * @param {string} element.search Query string. + * @param {string} element.host Host. + * @param {string} element.protocol Protocol. * @return {void} */ api.prepareLinkPreview = function prepareLinkPreview( element ) { @@ -399,11 +410,11 @@ /** * Rewrite Ajax requests to inject customizer state. * - * @param {Object} options Options. - * @param {string} options.type Type. - * @param {string} options.url URL. - * @param {Object} originalOptions Original options. - * @param {XMLHttpRequest} xhr XHR. + * @param {Object} options Options. + * @param {string} options.type Type. + * @param {string} options.url URL. + * @param {Object} originalOptions Original options. + * @param {XMLHttpRequest} xhr XHR. * @return {void} */ var prefilterAjax = function( options, originalOptions, xhr ) { @@ -714,9 +725,9 @@ /** * Create/update a setting value. * - * @param {string} id - Setting ID. - * @param {*} value - Setting value. - * @param {boolean} [createDirty] - Whether to create a setting as dirty. Defaults to false. + * @param {string} id Setting ID. + * @param {*} value Setting value. + * @param {boolean} [createDirty] Whether to create a setting as dirty. Defaults to false. */ setValue = function( id, value, createDirty ) { var setting = api( id ); @@ -791,7 +802,7 @@ /** * Handle update to changeset UUID. * - * @param {string} uuid - UUID. + * @param {string} uuid UUID. * @return {void} */ handleUpdatedChangesetUuid = function( uuid ) { @@ -888,8 +899,8 @@ return 'background_' + prop; } ); - api.when.apply( api, bg ).done( function() { - $.each( arguments, function() { + api.when.apply( api, bg ).done( function( ...settings ) { + $.each( settings, function() { this.bind( api.settingPreviewHandlers.background ); }); }); diff --git a/src/js/_enqueues/wp/customize/selective-refresh.js b/src/js/_enqueues/wp/customize/selective-refresh.js index 6744361066ce1..642880c9efe5e 100644 --- a/src/js/_enqueues/wp/customize/selective-refresh.js +++ b/src/js/_enqueues/wp/customize/selective-refresh.js @@ -5,6 +5,11 @@ /* global jQuery, JSON, _customizePartialRefreshExports, console */ /** @namespace wp.customize.selectiveRefresh */ + +/** + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} api The Customizer API. + */ wp.customize.selectiveRefresh = ( function( $, api ) { 'use strict'; var self, Partial, Placement; @@ -30,6 +35,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * A partial provides a rendering of one or more settings according to a template. * * @memberOf wp.customize.selectiveRefresh + * @alias wp.customize.selectiveRefresh.Partial * * @see PHP class WP_Customize_Partial. * @@ -37,7 +43,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @augments wp.customize.Class * @since 4.5.0 */ - Partial = self.Partial = api.Class.extend(/** @lends wp.customize.SelectiveRefresh.Partial.prototype */{ + Partial = self.Partial = api.Class.extend(/** @lends wp.customize.selectiveRefresh.Partial.prototype */{ id: null, @@ -45,7 +51,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * Default params. * * @since 4.9.0 - * @var {object} + * @member {Object} */ defaults: { selector: null, @@ -59,14 +65,14 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {string} id - Unique identifier for the partial instance. - * @param {Object} options - Options hash for the partial instance. - * @param {string} options.type - Type of partial (e.g. nav_menu, widget, etc) - * @param {string} options.selector - jQuery selector to find the container element in the page. - * @param {Array} options.settings - The IDs for the settings the partial relates to. - * @param {string} options.primarySetting - The ID for the primary setting the partial renders. - * @param {boolean} options.fallbackRefresh - Whether to refresh the entire preview in case of a partial refresh failure. - * @param {Object} [options.params] - Deprecated wrapper for the above properties. + * @param {string} id Unique identifier for the partial instance. + * @param {Object} [options] Options hash for the partial instance. + * @param {string} [options.type] Type of partial (e.g. nav_menu, widget, etc.). + * @param {string} [options.selector] jQuery selector to find the container element in the page. + * @param {string[]} [options.settings] The IDs for the settings the partial relates to. + * @param {string} [options.primarySetting] The ID for the primary setting the partial renders. + * @param {boolean} [options.fallbackRefresh] Whether to refresh the entire preview in case of a partial refresh failure. + * @param {Object} [options.params] Deprecated wrapper for the above properties. */ initialize: function( id, options ) { var partial = this; @@ -119,7 +125,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.7.0 * @access public * - * @param {Placement} placement The placement container element. + * @param {wp.customize.selectiveRefresh.Placement} placement The placement container element. * @return {void} */ createEditShortcutForPlacement: function( placement ) { @@ -148,8 +154,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.7.0 * @access public * - * @param {Placement} placement The placement for the partial. - * @param {jQuery} $editShortcut The shortcut element as a jQuery object. + * @param {wp.customize.selectiveRefresh.Placement} placement The placement for the partial. + * @param {JQuery} $editShortcut The shortcut element as a jQuery object. * @return {void} */ addEditShortcutToPlacement: function( placement, $editShortcut ) { @@ -229,7 +235,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.7.0 * @access public * - * @return {jQuery} The edit shortcut button element. + * @return {JQuery} The edit shortcut button element. */ createEditShortcut: function() { var partial = this, shortcutTitle, $buttonContainer, $button, $image; @@ -253,7 +259,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @return {Array.} + * @return {wp.customize.selectiveRefresh.Placement[]} The placements for this partial in the document. */ placements: function() { var partial = this, selector; @@ -285,7 +291,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @return {string[]} + * @return {string[]} The setting IDs related to this partial. */ settings: function() { var partial = this; @@ -303,7 +309,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {wp.customize.Value|string} setting ID or object for setting. + * @param {wp.customize.Value|string} setting ID or object for setting. * @return {boolean} Whether the setting is related to the partial. */ isRelatedSetting: function( setting /*... newValue, oldValue */ ) { @@ -344,7 +350,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {Placement} placement + * @param {wp.customize.selectiveRefresh.Placement} placement The placement to prepare. */ preparePlacement: function( placement ) { $( placement.container ).addClass( 'customize-partial-refreshing' ); @@ -364,7 +370,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.5.0 * * @this {wp.customize.selectiveRefresh.Partial} - * @return {jQuery.Promise} + * @return {JQuery.Promise<*>} Promise for the request to render the partial. */ refresh: function() { var partial = this, refreshPromise; @@ -404,10 +410,10 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {Placement} placement - * @param {Element|jQuery} [placement.container] - This param will be empty if there was no element matching the selector. - * @param {string|Object|boolean} placement.addedContent - Rendered HTML content, a data object for JS templates to render, or false if no render. - * @param {Object} [placement.context] - Optional context information about the container. + * @param {wp.customize.selectiveRefresh.Placement} placement The placement to render into. + * @param {Element|JQuery} [placement.container] This param will be empty if there was no element matching the selector. + * @param {string|Object|boolean} placement.addedContent Rendered HTML content, a data object for JS templates to render, or false if no render. + * @param {Object} [placement.context] Optional context information about the container. * @return {boolean} Whether the rendering was successful and the fallback was not invoked. */ renderContent: function( placement ) { @@ -526,17 +532,18 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * The placement is conceptually similar to a DOM Range or MutationRecord. * * @memberOf wp.customize.selectiveRefresh + * @alias wp.customize.selectiveRefresh.Placement * - * @class Placement + * @class * @augments wp.customize.Class * @since 4.5.0 */ - self.Placement = Placement = api.Class.extend(/** @lends wp.customize.selectiveRefresh.prototype */{ + self.Placement = Placement = api.Class.extend(/** @lends wp.customize.selectiveRefresh.Placement.prototype */{ /** * The partial with which the container is associated. * - * @param {wp.customize.selectiveRefresh.Partial} + * @member {wp.customize.selectiveRefresh.Partial} */ partial: null, @@ -547,6 +554,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * DOM element, such as in the case of a sidebar partial. * This container element itself will be replaced for partials that * have containerInclusive param defined as true. + * + * @member {JQuery} */ container: null, @@ -556,6 +565,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * This will normally be the same as endNode since most placements appear as elements. * This is primarily useful for widget sidebars which do not have intrinsic containers, but * for which an HTML comment is output before to mark the starting position. + * + * @member {Node} */ startNode: null, @@ -565,6 +576,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * This will normally be the same as startNode since most placements appear as elements. * This is primarily useful for widget sidebars which do not have intrinsic containers, but * for which an HTML comment is output before to mark the ending position. + * + * @member {Node} */ endNode: null, @@ -574,14 +587,14 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * This provides information about the placement which is included in the request * in order to render the partial properly. * - * @param {object} + * @member {Object} */ context: null, /** * The content for the partial when refreshed. * - * @param {string} + * @member {string|Object|boolean} */ addedContent: null, @@ -589,11 +602,11 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * DOM node(s) removed when the partial is refreshed. * * If the partial is containerInclusive, then the removedNodes will be - * the single Element that was the partial's former placement. If the + * the jQuery object for the partial's former placement. If the * partial is not containerInclusive, then the removedNodes will be a - * documentFragment containing the nodes removed. + * DocumentFragment containing the nodes removed. * - * @param {Element|DocumentFragment} + * @member {JQuery|DocumentFragment} */ removedNodes: null, @@ -602,14 +615,14 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {Object} args - * @param {Partial} args.partial - * @param {jQuery|Element} [args.container] - * @param {Node} [args.startNode] - * @param {Node} [args.endNode] - * @param {Object} [args.context] - * @param {string} [args.addedContent] - * @param {jQuery|DocumentFragment} [args.removedNodes] + * @param {Object} args The placement properties. + * @param {wp.customize.selectiveRefresh.Partial} args.partial The partial with which the container is associated. + * @param {JQuery|Element} [args.container] DOM element which contains the placement's contents. + * @param {Node} [args.startNode] DOM node for the initial boundary of the placement. + * @param {Node} [args.endNode] DOM node for the terminal boundary of the placement. + * @param {Object} [args.context] Context data included in the request in order to render the partial. + * @param {string|Object|boolean} [args.addedContent] The content for the partial when refreshed. + * @param {JQuery|DocumentFragment} [args.removedNodes] DOM node(s) removed when the partial is refreshed. */ initialize: function( args ) { var placement = this; @@ -645,7 +658,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.5.0 * @see wp.customize.previewer.query() * - * @return {Object} + * @return {Object} POST vars for a Customizer preview request. */ self.getCustomizeQuery = function() { var dirtyCustomized = {}; @@ -668,7 +681,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * Currently-requested partials and their associated deferreds. * * @since 4.5.0 - * @type {Object} + * @type {Object., partial: wp.customize.selectiveRefresh.Partial }>} */ self._pendingPartialRequests = {}; @@ -685,7 +698,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * Current jqXHR for the request to the partials. * * @since 4.5.0 - * @type {jQuery.jqXHR|null} + * @type {JQuery.jqXHR|null} * @private */ self._currentRequest = null; @@ -707,8 +720,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {wp.customize.selectiveRefresh.Partial} partial - * @return {jQuery.Promise} + * @param {wp.customize.selectiveRefresh.Partial} partial The partial to re-render. + * @return {JQuery.Promise<*>} Promise for the request to render the partial. */ self.requestPartial = function( partial ) { var partialRequest; @@ -856,9 +869,9 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * * @since 4.5.0 * - * @param {jQuery|HTMLElement} [rootElement] - * @param {object} [options] - * @param {boolean=true} [options.triggerRendered] + * @param {JQuery|HTMLElement} [rootElement] Element to scan for partials. Defaults to the document element. + * @param {Object} [options] Options. + * @param {boolean} [options.triggerRendered=true] Whether to trigger the rendered event for the placements found. */ self.addPartials = function( rootElement, options ) { var containerElements; @@ -969,7 +982,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.5.0 * @this {wp.customize.Values} * - * @param {wp.customize.Setting} setting + * @param {wp.customize.Setting} setting The setting that was added. */ watchSettingChange = function( setting ) { handleSettingChange.call( setting, setting(), null ); @@ -982,7 +995,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { * @since 4.5.0 * @this {wp.customize.Values} * - * @param {wp.customize.Setting} setting + * @param {wp.customize.Setting} setting The setting that was removed. */ unwatchSettingChange = function( setting ) { handleSettingChange.call( setting, null, setting() ); @@ -1016,7 +1029,7 @@ wp.customize.selectiveRefresh = ( function( $, api ) { /** * Handle rendering of partials. * - * @param {api.selectiveRefresh.Placement} placement + * @param {wp.customize.selectiveRefresh.Placement} placement The placement whose content was rendered. */ api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) { if ( placement.container ) { @@ -1027,8 +1040,8 @@ wp.customize.selectiveRefresh = ( function( $, api ) { /** * Handle setting validities in partial refresh response. * - * @param {object} data Response data. - * @param {object} data.setting_validities Setting validities. + * @param {Object} data Response data. + * @param {Object} data.setting_validities Setting validities. */ api.selectiveRefresh.bind( 'render-partials-response', function handleSettingValiditiesResponse( data ) { if ( data.setting_validities ) { diff --git a/src/js/_enqueues/wp/customize/views.js b/src/js/_enqueues/wp/customize/views.js index 02c984de70c43..16b36d782e3e2 100644 --- a/src/js/_enqueues/wp/customize/views.js +++ b/src/js/_enqueues/wp/customize/views.js @@ -2,6 +2,13 @@ * @output wp-includes/js/customize-views.js */ +/** + * The WordPress Customizer views API. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wp The WordPress global object. + * @param {_.UnderscoreStatic} _ The Underscore.js object. + */ (function( $, wp, _ ) { if ( ! wp || ! wp.customize ) { return; } @@ -18,23 +25,34 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.CurrentView * - * @constructor + * @class * @augments wp.Backbone.View */ api.HeaderTool.CurrentView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.CurrentView.prototype */{ template: wp.template('header-current'), + /** + * Initializes the view, rendering it whenever the model changes. + */ initialize: function() { this.listenTo(this.model, 'change', this.render); this.render(); }, + /** + * Renders the currently selected header image. + * + * @return {wp.customize.HeaderTool.CurrentView} Current view. + */ render: function() { this.$el.html(this.template(this.model.toJSON())); this.setButtons(); return this; }, + /** + * Shows or hides the header's action buttons. + */ setButtons: function() { var elements = $('#customize-control-header_image .actions .remove'); var addButton = $('#customize-control-header_image .actions .new'); @@ -64,7 +82,7 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.ChoiceView * - * @constructor + * @class * @augments wp.Backbone.View */ api.HeaderTool.ChoiceView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.ChoiceView.prototype */{ @@ -77,6 +95,9 @@ 'click .close': 'removeImage' }, + /** + * Initializes the view, marking it current when it matches the header image. + */ initialize: function() { var properties = [ this.model.get('header').url, @@ -90,6 +111,11 @@ } }, + /** + * Renders the choice. + * + * @return {wp.customize.HeaderTool.ChoiceView} Choice view. + */ render: function() { this.$el.html(this.template(this.extendedModel())); @@ -97,10 +123,18 @@ return this; }, + /** + * Toggles the selected class on the choice. + */ toggleSelected: function() { this.$el.toggleClass('selected', this.model.get('selected')); }, + /** + * Returns the model's attributes together with its collection type. + * + * @return {Object} Extended model. + */ extendedModel: function() { var c = this.model.get('collection'); return _.extend(this.model.toJSON(), { @@ -108,12 +142,18 @@ }); }, + /** + * Selects the choice as the header image. + */ select: function() { this.preventJump(); this.model.save(); api.HeaderTool.currentHeader.set(this.extendedModel()); }, + /** + * Keeps the sidebar at its current scroll position. + */ preventJump: function() { var container = $('.wp-full-overlay-sidebar-content'), scroll = container.scrollTop(); @@ -123,6 +163,11 @@ }); }, + /** + * Removes the image from the collection. + * + * @param {JQuery.Event} e Event. + */ removeImage: function(e) { e.stopPropagation(); this.model.destroy(); @@ -142,10 +187,13 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.ChoiceListView * - * @constructor + * @class * @augments wp.Backbone.View */ api.HeaderTool.ChoiceListView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.ChoiceListView.prototype */{ + /** + * Initializes the view, rendering it as the collection changes. + */ initialize: function() { this.listenTo(this.collection, 'add', this.addOne); this.listenTo(this.collection, 'remove', this.render); @@ -154,12 +202,23 @@ this.render(); }, + /** + * Renders each choice in the collection. + * + * @return {wp.customize.HeaderTool.ChoiceListView} Choice list view. + */ render: function() { this.$el.empty(); this.collection.each(this.addOne, this); this.toggleList(); + return this; }, + /** + * Renders a single choice into the list. + * + * @param {Backbone.Model} choice Choice. + */ addOne: function(choice) { var view; choice.set({ collection: this.collection }); @@ -167,6 +226,9 @@ this.$el.append(view.render().el); }, + /** + * Shows or hides the list title and the random button. + */ toggleList: function() { var title = this.$el.parents().prev('.customize-control-title'), randomButton = this.$el.find('.random').parent(); @@ -188,14 +250,26 @@ * @memberOf wp.customize.HeaderTool * @alias wp.customize.HeaderTool.CombinedList * - * @constructor + * @class * @augments wp.Backbone.View */ api.HeaderTool.CombinedList = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.CombinedList.prototype */{ + /** + * Initializes the view with the collections to combine. + * + * @param {Backbone.Collection[]} collections Collections. + */ initialize: function(collections) { this.collections = collections; this.on('all', this.propagate, this); }, + + /** + * Passes an event on to each of the combined collections. + * + * @param {string} event Event. + * @param {*} arg Argument. + */ propagate: function(event, arg) { _.each(this.collections, function(collection) { collection.trigger(event, arg); diff --git a/src/js/_enqueues/wp/customize/widgets.js b/src/js/_enqueues/wp/customize/widgets.js index 56459ad7452e1..5af1e8007de83 100644 --- a/src/js/_enqueues/wp/customize/widgets.js +++ b/src/js/_enqueues/wp/customize/widgets.js @@ -3,6 +3,13 @@ */ /* global _wpCustomizeWidgetsSettings */ + +/** + * The WordPress Customizer widgets API. + * + * @param {Object} wp The WordPress global object. + * @param {JQueryStatic} $ The jQuery object. + */ (function( wp, $ ){ if ( ! wp || ! wp.customize ) { return; } @@ -251,7 +258,7 @@ /** * Updates the count of the available widgets that have the `search_matched` attribute. - */ + */ updateSearchMatchesCount: function() { this.searchMatchesCount = this.collection.where({ search_matched: true }).length; }, @@ -271,7 +278,7 @@ /** * Changes visibility of available widgets. - */ + */ updateList: function() { this.collection.each( function( widget ) { var widgetTpl = $( '#widget-tpl-' + widget.id ); @@ -284,7 +291,9 @@ /** * Highlights a widget. - */ + * + * @param {JQuery} widgetTpl The widget template to highlight. + */ select: function( widgetTpl ) { this.selected = $( widgetTpl ); this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' ); @@ -293,6 +302,8 @@ /** * Highlights a widget on focus. + * + * @param {JQuery.Event} event The focus event. */ focus: function( event ) { this.select( $( event.currentTarget ) ); @@ -300,6 +311,8 @@ /** * Handles submit for keypress and click on widget. + * + * @param {JQuery.Event} event The keypress or click event. */ _submit: function( event ) { // Only proceed with keypress if it is Enter or Spacebar. @@ -312,7 +325,9 @@ /** * Adds a selected widget to the sidebar. - */ + * + * @param {JQuery} widgetTpl The widget template to add. + */ submit: function( widgetTpl ) { var widgetId, widget, widgetFormControl; @@ -342,6 +357,8 @@ /** * Opens the panel. + * + * @param {wp.customize.Widgets.SidebarControl} sidebarControl The sidebar control that opened the panel. */ open: function( sidebarControl ) { this.currentSidebarControl = sidebarControl; @@ -371,6 +388,8 @@ /** * Closes the panel. + * + * @param {Object} [options] Options for closing the panel. */ close: function( options ) { options = options || {}; @@ -389,6 +408,8 @@ /** * Adds keyboard accessibility to the panel. + * + * @param {JQuery.Event} event The keydown event. */ keyboardAccessible: function( event ) { var isEnter = ( event.which === 13 ), @@ -457,9 +478,11 @@ api.Widgets.formSyncHandlers = { /** - * @param {jQuery.Event} e - * @param {jQuery} widget - * @param {string} newForm + * Handles the widget-synced event for RSS widgets. + * + * @param {JQuery.Event} e The widget-synced event. + * @param {JQuery} widget The widget root element. + * @param {string} newForm The HTML for the updated widget form. */ rss: function( e, widget, newForm ) { var oldWidgetError = widget.find( '.widget-error:first' ), @@ -491,6 +514,9 @@ * * @constructs wp.customize.Widgets.WidgetControl * @augments wp.customize.Control + * + * @param {string} id Control ID. + * @param {Object} options Control options. */ initialize: function( id, options ) { var control = this; @@ -744,9 +770,9 @@ $reorderNav, updateAvailableSidebars, template; /** - * select the provided sidebar list item in the move widget area + * Selects the provided sidebar list item in the move widget area. * - * @param {jQuery} li + * @param {JQuery} li The sidebar list item to select. */ selectSidebarItem = function( li ) { li.siblings( '.selected' ).removeClass( 'selected' ); @@ -953,9 +979,9 @@ formSyncHandler = api.Widgets.formSyncHandlers[ this.params.widget_id_base ]; if ( formSyncHandler ) { - $( document ).on( 'widget-synced', function( e, widget ) { + $( document ).on( 'widget-synced', function( e, widget, ...args ) { if ( $widgetRoot.is( widget ) ) { - formSyncHandler.apply( document, arguments ); + formSyncHandler.call( document, e, widget, ...args ); } } ); } @@ -968,9 +994,9 @@ * * @since 4.1.0 * - * @param {boolean} active - * @param {Object} args - * @param {function} args.completeCallback + * @param {boolean} active Whether the widget is rendered. + * @param {Object} args Args. + * @param {Function} args.completeCallback Function to call once the class has been toggled. */ onChangeActive: function ( active, args ) { // Note: there is a second 'args' parameter being passed, merged on top of this.defaultActiveArguments. @@ -1039,8 +1065,8 @@ * are passed into this._getInputsSignature(), and they are iterated * over when copying sanitized values over to the form loaded. * - * @param {jQuery} container element in which to look for inputs - * @return {jQuery} inputs + * @param {JQuery} container Element in which to look for inputs. + * @return {JQuery} The inputs found within the container. * @private */ _getInputs: function( container ) { @@ -1051,8 +1077,8 @@ * Iterate over supplied inputs and create a signature string for all of them together. * This string can be used to compare whether or not the form has all of the same fields. * - * @param {jQuery} inputs - * @return {string} + * @param {JQuery} inputs The inputs to build a signature from. + * @return {string} Signature string for the inputs. * @private */ _getInputsSignature: function( inputs ) { @@ -1074,8 +1100,8 @@ /** * Get the state for an input depending on its type. * - * @param {jQuery|Element} input - * @return {string|boolean|Array|*} + * @param {JQuery|Element} input The input to read the state from. + * @return {string|boolean|string[]|*} State of the input. * @private */ _getInputState: function( input ) { @@ -1094,8 +1120,8 @@ /** * Update an input's state based on its type. * - * @param {jQuery|Element} input - * @param {string|boolean|Array|*} state + * @param {JQuery|Element} input The input element to update. + * @param {string|boolean|string[]|*} state The state to apply: the checked state for checkboxes and radio buttons, an array of values for multi-selects, and otherwise the input's value. * @private */ _setInputState: function ( input, state ) { @@ -1124,7 +1150,9 @@ **********************************************************************/ /** - * @return {wp.customize.controlConstructor.sidebar_widgets[]} + * Get the sidebar widgets control for the sidebar this widget is in. + * + * @return {wp.customize.Widgets.SidebarControl|undefined} The sidebar widgets control, or undefined if not found. */ getSidebarWidgetsControl: function() { var settingId, sidebarWidgetsControl; @@ -1143,10 +1171,10 @@ * Submit the widget form via Ajax and get back the updated instance, * along with the new widget control form to render. * - * @param {Object} [args] - * @param {Object|null} [args.instance=null] When the model changes, the instance is sent here; otherwise, the inputs from the form are used - * @param {Function|null} [args.complete=null] Function which is called when the request finishes. Context is bound to the control. First argument is any error. Following arguments are for success. - * @param {boolean} [args.ignoreActiveElement=false] Whether or not updating a field will be deferred if focus is still on the element. + * @param {Object} [args] Arguments for the update. + * @param {Object|null} [args.instance=null] When the model changes, the instance is sent here; otherwise, the inputs from the form are used. + * @param {Function|null} [args.complete=null] Function which is called when the request finishes. Context is bound to the control. First argument is any error. Following arguments are for success. + * @param {boolean} [args.ignoreActiveElement=false] Whether or not updating a field will be deferred if focus is still on the element. */ updateWidget: function( args ) { var self = this, instanceOverride, completeCallback, $widgetRoot, $widgetContent, @@ -1341,17 +1369,17 @@ /** * @since 4.1.0 * - * @param {Boolean} expanded - * @param {Object} [params] - * @return {Boolean} False if state already applied. + * @param {boolean} expanded The new state to apply. + * @param {Object} [params] Object containing options for expand/collapse. + * @return {boolean} False if state already applied. */ _toggleExpanded: api.Section.prototype._toggleExpanded, /** * @since 4.1.0 * - * @param {Object} [params] - * @return {Boolean} False if already expanded. + * @param {Object} [params] Object containing options for expansion. + * @return {boolean} False if already expanded. */ expand: api.Section.prototype.expand, @@ -1367,8 +1395,8 @@ /** * @since 4.1.0 * - * @param {Object} [params] - * @return {Boolean} False if already collapsed. + * @param {Object} [params] Object containing options for collapse. + * @return {boolean} False if already collapsed. */ collapse: api.Section.prototype.collapse, @@ -1386,7 +1414,7 @@ * * @deprecated this is poor naming, and it is better to directly set control.expanded( showOrHide ) * - * @param {boolean|undefined} [showOrHide] If not supplied, will be inverse of current visibility + * @param {boolean|undefined} [showOrHide] If not supplied, will be inverse of current visibility. */ toggleForm: function( showOrHide ) { if ( typeof showOrHide === 'undefined' ) { @@ -1398,8 +1426,10 @@ /** * Respond to change in the expanded state. * - * @param {boolean} expanded - * @param {Object} args merged on top of this.defaultActiveArguments + * @param {boolean} expanded The expanded state to transition to. + * @param {Object} args Object containing options for expand/collapse, merged on top of this.defaultExpandedArguments. + * @param {boolean} [args.unchanged] Whether the expanded state is unchanged. + * @param {Function} args.completeCallback Callback to be executed once the expand/collapse action is complete. */ onChangeExpanded: function ( expanded, args ) { var self = this, $widget, $inside, complete, prevComplete, expandControl, $toggleBtn; @@ -1498,7 +1528,7 @@ /** * Get the position (index) of the widget in the containing sidebar * - * @return {number} + * @return {number|void} Index of the widget in the sidebar, or undefined if not found. */ getWidgetSidebarPosition: function() { var sidebarWidgetIds, position; @@ -1528,9 +1558,11 @@ }, /** + * Moves the widget up or down one position in the sidebar. + * * @private * - * @param {number} offset 1|-1 + * @param {number} offset The number of positions to move the widget, either 1 or -1. */ _moveWidgetByOne: function( offset ) { var i, sidebarWidgetsSetting, sidebarWidgetIds, adjacentWidgetId; @@ -1549,7 +1581,7 @@ /** * Toggle visibility of the widget move area * - * @param {boolean} [showOrHide] + * @param {boolean} [showOrHide] If not supplied, will be inverse of current visibility. */ toggleWidgetMoveArea: function( showOrHide ) { var self = this, $moveWidgetArea; @@ -1605,7 +1637,7 @@ * @class wp.customize.Widgets.WidgetsPanel * @augments wp.customize.Panel */ - api.Widgets.WidgetsPanel = api.Panel.extend(/** @lends wp.customize.Widgets.WigetsPanel.prototype */{ + api.Widgets.WidgetsPanel = api.Panel.extend(/** @lends wp.customize.Widgets.WidgetsPanel.prototype */{ /** * Add and manage the display of the no-rendered-areas notice. @@ -1642,7 +1674,7 @@ /** * Determine whether or not the notice should be displayed. * - * @return {boolean} + * @return {boolean} True if the notice should be displayed, false otherwise. */ shouldShowNotice = function() { var activeSectionCount = getActiveSectionCount(); @@ -1712,7 +1744,7 @@ * * @since 4.4.0 * - * @return {boolean} + * @return {boolean} True if the panel is contextually active, false otherwise. */ isContextuallyActive: function() { var panel = this; @@ -2008,7 +2040,7 @@ /** * Enable/disable the reordering UI * - * @param {boolean} showOrHide to enable/disable reordering + * @param {boolean} showOrHide Whether to enable or disable reordering. * * @todo We should have a reordering state instead and rename this to onChangeReordering */ @@ -2048,7 +2080,7 @@ * Get the widget_form Customize controls associated with the current sidebar. * * @since 3.9.0 - * @return {wp.customize.controlConstructor.widget_form[]} + * @return {wp.customize.Widgets.WidgetControl[]} Widget form controls associated with the current sidebar. */ getWidgetFormControls: function() { var formControls = []; @@ -2065,8 +2097,10 @@ }, /** - * @param {string} widgetId or an id_base for adding a previously non-existing widget. - * @return {Object|false} widget_form control instance, or false on error. + * Add a widget to the sidebar. + * + * @param {string} widgetId Widget ID, or an id_base for adding a previously non-existing widget. + * @return {wp.customize.Widgets.WidgetControl|false} The widget_form control instance, or false on error. */ addWidget: function( widgetId ) { var self = this, controlHtml, $widget, controlType = 'widget_form', controlContainer, controlConstructor, @@ -2221,7 +2255,7 @@ /** * Highlight a widget control. * - * @param {string} widgetId + * @param {string} widgetId The ID of the widget to highlight. */ api.Widgets.highlightWidgetFormControl = function( widgetId ) { var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); @@ -2234,7 +2268,7 @@ /** * Focus a widget control. * - * @param {string} widgetId + * @param {string} widgetId The ID of the widget to focus. */ api.Widgets.focusWidgetFormControl = function( widgetId ) { var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); @@ -2246,8 +2280,8 @@ /** * Given a widget control, find the sidebar widgets control that contains it. - * @param {string} widgetId - * @return {Object|null} + * @param {string} widgetId The ID of the widget to find the sidebar widgets control for. + * @return {Object|null} Sidebar widgets control that contains the widget, or null if not found. */ api.Widgets.getSidebarWidgetControlContainingWidget = function( widgetId ) { var foundControl = null; @@ -2265,8 +2299,8 @@ /** * Given a widget ID for a widget appearing in the preview, get the widget form control associated with it. * - * @param {string} widgetId - * @return {Object|null} + * @param {string} widgetId The ID of the widget to find the form control for. + * @return {Object|null} Widget form control associated with the widget, or null if not found. */ api.Widgets.getWidgetFormControlForWidget = function( widgetId ) { var foundControl = null; @@ -2319,11 +2353,16 @@ * * This overrides the back button to serve the purpose of breadcrumb navigation. * - * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} focusConstruct - The object to initially focus. - * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} returnConstruct - The object to return focus. + * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} focusConstruct The object to initially focus. + * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} returnConstruct The object to return focus. */ function focusConstructWithBreadcrumb( focusConstruct, returnConstruct ) { focusConstruct.focus(); + /** + * Determines whether to return focus to the returnConstruct after the focusConstruct is collapsed. + * + * @param {boolean} isExpanded Whether the focusConstruct is expanded. + */ function onceCollapsed( isExpanded ) { if ( ! isExpanded ) { focusConstruct.expanded.unbind( onceCollapsed ); @@ -2334,8 +2373,10 @@ } /** - * @param {string} widgetId - * @return {Object} + * Parses a widget ID into its id_base and number components. + * + * @param {string} widgetId The widget ID to parse. + * @return {Object} Parsed widget ID with id_base and number properties. */ function parseWidgetId( widgetId ) { var matches, parsed = { @@ -2356,8 +2397,10 @@ } /** - * @param {string} widgetId - * @return {string} settingId + * Returns the setting ID for a given widget ID. + * + * @param {string} widgetId The widget ID. + * @return {string} The setting ID for the widget. */ function widgetIdToSettingId( widgetId ) { var parsed = parseWidgetId( widgetId ), settingId; diff --git a/src/js/_enqueues/wp/dashboard.js b/src/js/_enqueues/wp/dashboard.js index 0c92f1e1b3e47..1fbfdec57a508 100644 --- a/src/js/_enqueues/wp/dashboard.js +++ b/src/js/_enqueues/wp/dashboard.js @@ -67,7 +67,7 @@ jQuery( function($) { * @type {string[]} * * @global - */ + */ window.ajaxWidgets = ['dashboard_primary']; /** @@ -85,7 +85,7 @@ jQuery( function($) { /** * Fetch the latest representation of the widget via Ajax and show it. * - * @param {number} i Number of half-seconds to use as the timeout. + * @param {number} i Number of half-seconds to use as the timeout. * @param {string} id ID of the element which is going to be checked for changes. * * @return {void} @@ -163,7 +163,7 @@ jQuery( function($) { * Highlights the latest post for one second. * * @return {void} - */ + */ function highlightLatestPost () { var latestPost = $( '.drafts ul li' ) .first(), errorNotice = $( '#quick-press .notice-error' ); @@ -633,10 +633,10 @@ jQuery( function( $ ) { * * @since 5.5.2 * - * @param {Array} rawEvents The events that should have dynamic fields added to them. - * @param {string} timeFormat A time format acceptable by `wp.date.dateI18n()`. + * @param {Object[]} rawEvents The events that should have dynamic fields added to them. + * @param {string} timeFormat A time format acceptable by `wp.date.dateI18n()`. * - * @returns {Array} + * @return {Object[]} The events with dynamic fields added to them. */ populateDynamicEventFields: function( rawEvents, timeFormat ) { // Clone the parameter to avoid mutating it, so that this can remain a pure function. @@ -668,9 +668,9 @@ jQuery( function( $ ) { * * @since 5.5.2 * - * @param startTimestamp + * @param {number} startTimestamp The start timestamp of the event. * - * @returns {string|number} + * @return {string|number} A time zone string like `America/Chicago`, or a number representing the offset from UTC in minutes. */ getTimeZone: function( startTimestamp ) { /* @@ -703,9 +703,9 @@ jQuery( function( $ ) { * * @since 5.5.2 * - * @param {number} startTimestamp + * @param {number} startTimestamp The start timestamp of the event. * - * @returns {number} + * @return {number} The offset from UTC in minutes, with the sign flipped to be more intuitive. */ getFlippedTimeZoneOffset: function( startTimestamp ) { return new Date( startTimestamp ).getTimezoneOffset() * -1; @@ -716,9 +716,9 @@ jQuery( function( $ ) { * * @since 5.5.2 * - * @param {number} startTimestamp + * @param {number} startTimestamp The start timestamp of the event. * - * @returns {string} + * @return {string} A short time zone name, like `PST`, or a string like `GMT+5` if the abbreviation can't be determined. */ getTimeZoneAbbreviation: function( startTimestamp ) { var timeZoneAbbreviation, @@ -758,11 +758,11 @@ jQuery( function( $ ) { * * @since 5.5.2 * - * @param {int} startDate The Unix timestamp in milliseconds when the event starts. - * @param {int} endDate The Unix timestamp in milliseconds when the event ends. - * @param {string} timeZone A time zone string or offset which is parsable by `wp.date.i18n()`. + * @param {number} startDate The Unix timestamp in milliseconds when the event starts. + * @param {number} endDate The Unix timestamp in milliseconds when the event ends. + * @param {string} timeZone A time zone string or offset which is parsable by `wp.date.i18n()`. * - * @returns {string} + * @return {string} A formatted date string, like `Mon, Jan 1, 2024` or `Jan 1–3, 2024`. */ getFormattedDate: function( startDate, endDate, timeZone ) { var formattedDate; @@ -834,8 +834,8 @@ jQuery( function( $ ) { * @since 4.8.0 * @deprecated 5.6.0 * - * @type {object} -*/ + * @type {Object} + */ window.communityEventsData.l10n = window.communityEventsData.l10n || { enter_closest_city: '', error_occurred_please_try_again: '', diff --git a/src/js/_enqueues/wp/editor/base.js b/src/js/_enqueues/wp/editor/base.js index b5f1731d4afc5..23b948d860508 100644 --- a/src/js/_enqueues/wp/editor/base.js +++ b/src/js/_enqueues/wp/editor/base.js @@ -4,6 +4,12 @@ window.wp = window.wp || {}; +/** + * The editor functionality. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wp The WordPress global object. + */ ( function( $, wp ) { wp.editor = wp.editor || {}; @@ -11,11 +17,16 @@ window.wp = window.wp || {}; * Utility functions for the editor. * * @since 2.5.0 + * @return {Object} The editor utility functions. */ function SwitchEditors() { var tinymce, $$, - exports = {}; + exports = {}, + isPointingDevice = false; + /** + * Initializes the editor utility functions. + */ function init() { if ( ! tinymce && window.tinymce ) { tinymce = window.tinymce; @@ -32,7 +43,15 @@ window.wp = window.wp || {}; var id, mode, target = $$( event.target ); + if ( target.hasClass( 'wp-switch-editor' ) ) { + /* + * Determine whether the click event is fired by using + * a pointing device including Safari fallback and + * unknown hardware pointers. + */ + isPointingDevice = event.detail > 0 || ( event.pointerType !== undefined && event.pointerType !== '' ); + id = target.attr( 'data-wp-editor-id' ); mode = target.hasClass( 'switch-tmce' ) ? 'tmce' : 'html'; switchEditor( id, mode ); @@ -68,7 +87,7 @@ window.wp = window.wp || {}; * * @memberof switchEditors * - * @param {string} id The id of the editor you want to change the editor mode for. Default: `content`. + * @param {string} id The id of the editor you want to change the editor mode for. Default: `content`. * @param {string} mode The mode you want to switch to. Default: `toggle`. * @return {void} */ @@ -108,6 +127,30 @@ window.wp = window.wp || {}; addHTMLBookmarkInTextAreaContent( $textarea ); if ( editor ) { + // Store the original TinyMCE editor focus() method. + const originalEditorFocusInstance = editor.focus; + + /* + * Override the editor's focus method to conditionally skip + * focusing the editor based on the input device. Note that + * editor.focus() aleady uses a `skipFocus` parameter. When + * it is true, it calls activateEditor(editor) instead of + * focusEditor(editor). + */ + editor.focus = function ( skipFocus ) { + if ( ! isPointingDevice) { + skipFocus = true; + } + + originalEditorFocusInstance.call( editor, skipFocus ); + }; + + /* + * The editor show() method calls several other methods that + * end up setting focus to the editor. We want to skip + * setting focus when switching editors and the user is + * using a keyboard or a non-pointing device. + */ editor.show(); // No point to resize the iframe in iOS. @@ -191,7 +234,7 @@ window.wp = window.wp || {}; * the tag type, if it is a closing tag and check if the HTML tag is inside a shortcode tag, * e.g. `[caption]..`. * - * @param {string} content The test content where the cursor is. + * @param {string} content The test content where the cursor is. * @param {number} cursorPosition The cursor position inside the content. * * @return {(null|Object)} Null if cursor is not in a tag, Object if the cursor is inside a tag. @@ -236,11 +279,11 @@ window.wp = window.wp || {}; * Moving the selection to before or after the short code is better, since it allows to select * something, instead of just losing focus and going to the start of the content. * - * @param {string} content The text content to check against. - * @param {number} cursorPosition The cursor position to check. + * @param {string} content The text content to check against. + * @param {number} cursorPosition The cursor position to check. * - * @return {(undefined|Object)} Undefined if the cursor is not wrapped in a shortcode tag. - * Information about the wrapping shortcode tag if it's wrapped in one. + * @return {void|Object} Undefined if the cursor is not wrapped in a shortcode tag. + * Information about the wrapping shortcode tag if it's wrapped in one. */ function getShortcodeWrapperInfo( content, cursorPosition ) { var contentShortcodes = getShortCodePositionsInText( content ); @@ -258,6 +301,7 @@ window.wp = window.wp || {}; * Gets a list of unique shortcodes or shortcode-lookalikes in the content. * * @param {string} content The content we want to scan for shortcodes. + * @return {string[]} An array of unique shortcodes found in the content. */ function getShortcodesInText( content ) { var shortcodes = content.match( /\[+([\w_-])+/g ), @@ -290,7 +334,8 @@ window.wp = window.wp || {}; * The information can also be used in other cases when we need to lookup shortcode data, * as it's already structured! * - * @param {string} content The content we want to scan for shortcodes + * @param {string} content The content we want to scan for shortcodes. + * @return {Object[]} An array of objects with information about the shortcodes found in the content. */ function getShortCodePositionsInText( content ) { var allShortcodes = getShortcodesInText( content ), shortcodeInfo; @@ -360,8 +405,9 @@ window.wp = window.wp || {}; * * Using DomQuery syntax to create it, since it's used as both text and as a DOM element. * - * @param {Object} domLib DOM library instance. + * @param {Object} domLib DOM library instance. * @param {string} content The content to insert into the cursor marker element. + * @return {Object} The cursor marker element. */ function getCursorMarkerSpan( domLib, content ) { return domLib( '' ).css( { @@ -382,10 +428,10 @@ window.wp = window.wp || {}; * * @link getShortcodeWrapperInfo * - * @param {string} content Textarea content that the cursors are in + * @param {string} content Textarea content that the cursors are in * @param {{cursorStart: number, cursorEnd: number}} cursorPositions Cursor start and end positions * - * @return {{cursorStart: number, cursorEnd: number}} + * @return {{cursorStart: number, cursorEnd: number}} Adjusted cursor positions with `cursorStart` and `cursorEnd` properties. */ function adjustTextAreaSelectionCursors( content, cursorPositions ) { var voidElements = [ @@ -521,7 +567,9 @@ window.wp = window.wp || {}; endNode = editor.$( '.mce_SELRES_end' ).attr( 'data-mce-bogus', 1 ); if ( startNode.length ) { - editor.focus(); + if ( isPointingDevice ) { + editor.focus(); + } if ( ! endNode.length ) { editor.selection.select( startNode[0] ); @@ -572,7 +620,7 @@ window.wp = window.wp || {}; * I order to achieve the proper positioning, the editor media bar and toolbar are subtracted * from the window height, to get the proper viewport window, that the user sees. * - * @param {Object} editor TinyMCE editor instance. + * @param {Object} editor TinyMCE editor instance. * @param {Object} element HTMLElement that should be scrolled into view. */ function scrollVisualModeToStartElement( editor, element ) { @@ -649,7 +697,7 @@ window.wp = window.wp || {}; * and why this solution was chosen. * * @param {Object} editor The editor where we must find the selection. - * @return {(null|Object)} The selection range position in the editor. + * @return {void|Object} The selection range position in the editor. */ function findBookmarkedPosition( editor ) { // Get the TinyMCE `window` reference, since we need to access the raw selection. @@ -812,7 +860,7 @@ window.wp = window.wp || {}; * For `selection` parameter: * @link findBookmarkedPosition * - * @param {Object} editor TinyMCE's editor instance. + * @param {Object} editor TinyMCE's editor instance. * @param {Object} selection Selection data. */ function selectTextInTextArea( editor, selection ) { @@ -825,16 +873,53 @@ window.wp = window.wp || {}; start = selection.start, end = selection.end || selection.start; - if ( textArea.focus ) { - // Wait for the Visual editor to be hidden, then focus and scroll to the position. + /* + * Guard against the scenarios where editor.getElement() may return + * something that isn't a standard textarea element e.g. the editor + * may have been removed/destroyed/mutated. + */ + if ( ! textArea.focus ) { + return; + } + + /** + * Applies the selection range to the textarea. + */ + function applySelection() { + /* + * In Safari, the focus event fires before the browser has fully + * completed the focus transition. Calling setTimeout with a 0ms + * delay queues the callback function task into the task queue + * so that the callback is executed after all pending tasks have + * cleared. Safe for other browsers. + */ setTimeout( function() { + // Guard against the editor being destroyed during the timeout. + if ( ! textArea.isConnected ) { + return; + } + textArea.setSelectionRange( start, end ); + }, 0 ); + } + + // Logic for pointing devices. + if ( isPointingDevice ) { + setTimeout( function() { + applySelection(); if ( textArea.blur ) { - // Defocus before focusing. textArea.blur(); } textArea.focus(); }, 100 ); + } else { + /* + * For non-pointing devices: wait until users move focus into the + * textarea (e.g. via keyboard Tab), then restore the selection. + * By using `once`, the listener is invoked at most once after + * being added and it's automatically removed when invoked. + */ + textArea.addEventListener( 'focus', applySelection, { once: true } ); } } @@ -1211,9 +1296,27 @@ window.wp = window.wp || {}; * * @since 4.8.0 * - * @param {string} id The HTML id of the textarea that is used for the editor. - * Has to be jQuery compliant. No brackets, special chars, etc. - * @param {Object} settings Example: + * @param {string} id The HTML id of the textarea that is used for the editor. + * Has to be jQuery compliant. No brackets, special chars, etc. + * @param {Object} settings The settings for initializing the editor. + * + * @example + * ```javascript + * settings = { + * // See https://www.tinymce.com/docs/configure/integration-and-setup/. + * // Alternatively set to `true` to use the defaults. + * tinymce: { + * setup: function( editor ) { + * console.log( 'Editor initialized', editor ); + * } + * } + * + * // Alternatively set to `true` to use the defaults. + * quicktags: { + * buttons: 'strong,em,link' + * } + * } + * * settings = { * // See https://www.tinymce.com/docs/configure/integration-and-setup/. * // Alternatively set to `true` to use the defaults. @@ -1228,6 +1331,7 @@ window.wp = window.wp || {}; * buttons: 'strong,em,link' * } * } + * ``` */ wp.editor.initialize = function( id, settings ) { var init; @@ -1381,7 +1485,7 @@ window.wp = window.wp || {}; * @since 4.8.0 * * @param {string} id The HTML id of the editor textarea. - * @return The editor content. + * @return {void|string} The editor content. */ wp.editor.getContent = function( id ) { var editor; diff --git a/src/js/_enqueues/wp/editor/dfw.js b/src/js/_enqueues/wp/editor/dfw.js index 04b001e1c8059..ff640ca9dd121 100644 --- a/src/js/_enqueues/wp/editor/dfw.js +++ b/src/js/_enqueues/wp/editor/dfw.js @@ -2,6 +2,13 @@ * @output wp-admin/js/editor-expand.js */ +/** + * Handles the editor Distraction-Free Writing (DFW) functionality. + * + * @param {Window} window The global window object. + * @param {JQueryStatic} $ The jQuery object. + * @param {undefined} undefined The undefined value. + */ ( function( window, $, undefined ) { 'use strict'; @@ -166,8 +173,8 @@ * * @since 4.0.0 * - * @param {event} event The TinyMCE editor init event. - * @param {object} editor The editor to bind the vents on. + * @param {event} event The TinyMCE editor init event. + * @param {Object} editor The editor to bind the vents on. * * @return {void} */ @@ -785,7 +792,7 @@ * * @since 4.0.0 * - * @param {function} callback The function to run in the timeout. + * @param {Function} callback The function to run in the timeout. * * @return {void} */ @@ -1160,7 +1167,7 @@ * * @since 4.1.0 * - * @param event The event that triggers this function. + * @param {Event} event The event that triggers this function. * * @return {void} */ @@ -1299,7 +1306,7 @@ * * @since 4.1.0 * - * @param event The event that triggers this function. + * @param {Event} event The event that triggers this function. * * @return {void} */ @@ -1353,6 +1360,12 @@ setTimeout( function() { var position = document.activeElement.compareDocumentPosition( $editor.get( 0 ) ); + /** + * Determines whether the passed element has focus. + * + * @param {jQuery} $el The element to check for focus. + * @return {boolean} True if the element has focus, false otherwise. + */ function hasFocus( $el ) { return $.contains( $el.get( 0 ), document.activeElement ); } @@ -1460,8 +1473,8 @@ * * @since 4.1.0 * - * @param {event} event The TinyMCE editor setup event. - * @param {object} editor The editor to add the button to. + * @param {event} event The TinyMCE editor setup event. + * @param {Object} editor The editor to add the button to. * * @return {void} */ @@ -1509,18 +1522,24 @@ * * @since 4.1.0 * - * @param {event} event The TinyMCE editor init event. - * @param {object} editor The editor to bind events on. + * @param {event} event The TinyMCE editor init event. + * @param {Object} editor The editor to bind events on. * * @return {void} */ $document.on( 'tinymce-editor-init.focus', function( event, editor ) { var mceBind, mceUnbind; + /** + * Tracks when the TinyMCE editor receives focus. + */ function focus() { editorHasFocus = true; } + /** + * Tracks when the TinyMCE editor loses focus. + */ function blur() { editorHasFocus = false; } @@ -1562,12 +1581,12 @@ } ); /** - * Binds events on quicktags init. + * Binds events on quicktags init. * * @since 4.1.0 * - * @param {event} event The quicktags init event. - * @param {object} editor The editor to bind events on. + * @param {event} event The quicktags init event. + * @param {Object} editor The editor to bind events on. * * @return {void} */ diff --git a/src/js/_enqueues/wp/embed.js b/src/js/_enqueues/wp/embed.js index 315e573f5cb82..1f34177c3362f 100644 --- a/src/js/_enqueues/wp/embed.js +++ b/src/js/_enqueues/wp/embed.js @@ -1,6 +1,8 @@ /** * WordPress inline HTML embed * + * @param {Window} window The global window object. + * @param {Document} document The global document object. * @since 4.4.0 * @output wp-includes/js/wp-embed.js * @@ -28,7 +30,7 @@ /** * Receive embed message. * - * @param {MessageEvent} e + * @param {MessageEvent} e The message event. */ window.wp.receiveEmbedMessage = function( e ) { var data = e.data; @@ -85,12 +87,15 @@ } }; + /** + * Initializes the embed script on DOMContentLoaded. + */ function onLoad() { var iframes = document.querySelectorAll( 'iframe.wp-embedded-content' ), i, source, secret; for ( i = 0; i < iframes.length; i++ ) { - /** @var {IframeElement} */ + /** @type {HTMLIFrameElement}} */ source = iframes[ i ]; secret = source.getAttribute( 'data-secret' ); diff --git a/src/js/_enqueues/wp/emoji.js b/src/js/_enqueues/wp/emoji.js index 05582de672662..a1f0f4face234 100644 --- a/src/js/_enqueues/wp/emoji.js +++ b/src/js/_enqueues/wp/emoji.js @@ -1,56 +1,52 @@ +/** + * @output wp-includes/js/wp-emoji.js + */ + +/** + * Additional options accepted by wp.emoji.parse(). + * + * @typedef WPEmojiParseArgs + * @type {Object} + * @property {string} [className] Class name to give each generated image. + * @property {Record} [imgAttr] Attributes to set on each generated image, in + * place of the default ones. + */ + /** * wp-emoji.js is used to replace emoji with images in browsers when the browser * doesn't support emoji natively. * - * @output wp-includes/js/wp-emoji.js + * @param {Window} window The global window object. + * @param {WPEmojiSettings} settings The settings object. */ - -( function( window, settings ) { +( function ( window, settings ) { /** * Replaces emoji with images when browsers don't support emoji. * * @since 4.2.0 * @access private * - * @class + * @see Twemoji + * @link https://github.com/jdecked/twemoji * - * @see Twitter Emoji library - * @link https://github.com/twitter/twemoji - * - * @return {Object} The wpEmoji parse and test functions. + * @return {{ + * parse: ( object: HTMLElement|string, args?: WPEmojiParseArgs ) => HTMLElement|string, + * test: ( text: ?string ) => boolean + * }} The wpEmoji parse and test functions. */ function wpEmoji() { - var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver, - // Compression and maintain local scope. - document = window.document, + const document = window.document; // Private. - twemoji, timer, - loaded = false, - count = 0, - ie11 = window.navigator.userAgent.indexOf( 'Trident/7.0' ) > 0; + /** @type {Twemoji|undefined} */ + let twemoji; - /** - * Detect if the browser supports SVG. - * - * @since 4.6.0 - * @private - * - * @see Modernizr - * @link https://github.com/Modernizr/Modernizr/blob/master/feature-detects/svg/asimg.js - * - * @return {boolean} True if the browser supports svg, false if not. - */ - function browserSupportsSvgAsImage() { - if ( !! document.implementation.hasFeature ) { - return document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' ); - } + /** @type {number|undefined} */ + let timer; - // document.implementation.hasFeature is deprecated. It can be presumed - // if future browsers remove it, the browser will support SVGs as images. - return true; - } + let loaded = false; + let count = 0; /** * Runs when the document load event is fired, so we can do our first parse of @@ -87,74 +83,42 @@ // Initialize the mutation observer, which checks all added nodes for // replaceable emoji characters. - if ( MutationObserver ) { - new MutationObserver( function( mutationRecords ) { - var i = mutationRecords.length, - addedNodes, removedNodes, ii, node; - - while ( i-- ) { - addedNodes = mutationRecords[ i ].addedNodes; - removedNodes = mutationRecords[ i ].removedNodes; - ii = addedNodes.length; - - /* - * Checks if an image has been replaced by a text element - * with the same text as the alternate description of the replaced image. - * (presumably because the image could not be loaded). - * If it is, do absolutely nothing. - * - * Node type 3 is a TEXT_NODE. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType - */ - if ( - ii === 1 && removedNodes.length === 1 && - addedNodes[0].nodeType === 3 && - removedNodes[0].nodeName === 'IMG' && - addedNodes[0].data === removedNodes[0].alt && - 'load-failed' === removedNodes[0].getAttribute( 'data-error' ) - ) { - return; - } + new MutationObserver( ( mutationRecords ) => { + for ( const { addedNodes, removedNodes } of mutationRecords ) { + const addedNode = addedNodes[ 0 ]; + const removedNode = removedNodes[ 0 ]; + + /* + * Checks if an image has been replaced by a text element + * with the same text as the alternate description of the replaced image. + * (presumably because the image could not be loaded). + * If it is, leave this record alone, so that the text is not turned + * straight back into the image which just failed to load. + */ + if ( + addedNodes.length === 1 && removedNodes.length === 1 && + addedNode instanceof Text && + removedNode instanceof HTMLImageElement && + addedNode.data === removedNode.alt && + 'load-failed' === removedNode.dataset.error + ) { + continue; + } - // Loop through all the added nodes. - while ( ii-- ) { - node = addedNodes[ ii ]; - - // Node type 3 is a TEXT_NODE. - if ( node.nodeType === 3 ) { - if ( ! node.parentNode ) { - continue; - } - - if ( ie11 ) { - /* - * IE 11's implementation of MutationObserver is buggy. - * It unnecessarily splits text nodes when it encounters a HTML - * template interpolation symbol ( "{{", for example ). So, we - * join the text nodes back together as a work-around. - * - * Node type 3 is a TEXT_NODE. - */ - while( node.nextSibling && 3 === node.nextSibling.nodeType ) { - node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; - node.parentNode.removeChild( node.nextSibling ); - } - } - - node = node.parentNode; - } - - if ( test( node.textContent ) ) { - parse( node ); - } + // Loop through all the added nodes. + for ( const addedNode of addedNodes ) { + // Emoji in a text node are replaced by parsing the element which contains it. + const node = addedNode instanceof Text ? addedNode.parentElement : addedNode; + + if ( node instanceof HTMLElement && test( node.textContent ) ) { + parse( node ); } } - } ).observe( document.body, { - childList: true, - subtree: true - } ); - } + } + } ).observe( document.body, { + childList: true, + subtree: true + } ); parse( document.body ); } @@ -166,18 +130,19 @@ * * @memberOf wp.emoji * - * @param {string} text The string to test. + * @param {?string} text The string to test. * * @return {boolean} Whether the string contains emoji characters. */ function test( text ) { // Single char. U+20E3 to detect keycaps. U+00A9 "copyright sign" and U+00AE "registered sign" not included. - var single = /[\u203C\u2049\u20E3\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2300\u231A\u231B\u2328\u2388\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638\u2639\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692\u2693\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753\u2754\u2755\u2757\u2763\u2764\u2795\u2796\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05\u2B06\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]/, + const single = /[\u203C\u2049\u20E3\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2300\u231A\u231B\u2328\u2388\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638\u2639\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692\u2693\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753\u2754\u2755\u2757\u2763\u2764\u2795\u2796\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05\u2B06\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]/; + // Surrogate pair range. Only tests for the second half. - pair = /[\uDC00-\uDFFF]/; + const pair = /[\uDC00-\uDFFF]/; if ( text ) { - return pair.test( text ) || single.test( text ); + return pair.test( text ) || single.test( text ); } return false; @@ -188,21 +153,19 @@ * * - When passed an element the emoji characters are replaced inline. * - When passed a string the emoji characters are replaced and the result is - * returned. + * returned. * * @since 4.2.0 * * @memberOf wp.emoji * * @param {HTMLElement|string} object The element or string to parse. - * @param {Object} args Additional options for Twemoji. + * @param {WPEmojiParseArgs} [args] Additional options for Twemoji. * * @return {HTMLElement|string} A string where all emoji are now image tags of * emoji. Or the element that was passed as the first argument. */ function parse( object, args ) { - var params; - /* * If the browser has full support, twemoji is not loaded or our * object is not what was expected, we do not parse anything. @@ -215,11 +178,16 @@ // Compose the params for the twitter emoji library. args = args || {}; - params = { - base: browserSupportsSvgAsImage() ? settings.svgUrl : settings.baseUrl, - ext: browserSupportsSvgAsImage() ? settings.svgExt : settings.ext, + + // The caller may replace the attributes given to every generated image. + const attributes = typeof args.imgAttr === 'object' ? args.imgAttr : { role: 'img' }; + + /** @type {TwemojiParseOptions} */ + const params = { + base: settings.svgUrl, + ext: settings.svgExt, className: args.className || 'emoji', - callback: function( icon, options ) { + callback: ( icon, options ) => { // Ignore some standard characters that TinyMCE recommends in its character map. switch ( icon ) { case 'a9': @@ -242,47 +210,30 @@ return ''.concat( options.base, icon, options.ext ); }, - attributes: function() { - return { - role: 'img' - }; - }, - onerror: function() { - if ( twemoji.parentNode ) { - this.setAttribute( 'data-error', 'load-failed' ); - twemoji.parentNode.replaceChild( document.createTextNode( twemoji.alt ), twemoji ); + attributes: () => attributes, + onerror: function () { + /* + * Put the emoji character back in place of the image which failed to load. The + * attribute is what tells the MutationObserver above that this replacement is + * the one it must not turn straight back into an image. + */ + if ( this.parentNode ) { + this.dataset.error = 'load-failed'; + this.parentNode.replaceChild( document.createTextNode( this.alt ), this ); } }, - doNotParse: function( node ) { - if ( - node && - node.className && - typeof node.className === 'string' && - node.className.indexOf( 'wp-exclude-emoji' ) !== -1 - ) { - // Do not parse this node. Emojis will not be replaced in this node and all sub-nodes. - return true; - } - - return false; + doNotParse: ( element ) => { + // Emoji will not be replaced in this element, nor in any of its descendants. + return element.classList.contains( 'wp-exclude-emoji' ); } }; - if ( typeof args.imgAttr === 'object' ) { - params.attributes = function() { - return args.imgAttr; - }; - } - return twemoji.parse( object, params ); } load(); - return { - parse: parse, - test: test - }; + return { parse, test }; } window.wp = window.wp || {}; @@ -290,6 +241,6 @@ /** * @namespace wp.emoji */ - window.wp.emoji = new wpEmoji(); + window.wp.emoji = wpEmoji(); } )( window, window._wpemojiSettings ); diff --git a/src/js/_enqueues/wp/heartbeat.js b/src/js/_enqueues/wp/heartbeat.js index 65635177d9f66..6f89e1db47b6c 100644 --- a/src/js/_enqueues/wp/heartbeat.js +++ b/src/js/_enqueues/wp/heartbeat.js @@ -1,5 +1,9 @@ /** - * Heartbeat API + * @output wp-includes/js/heartbeat.js + */ + +/** + * Handles the Heartbeat API. * * Heartbeat is a simple server polling API that sends XHR requests to * the server every 15 - 60 seconds and triggers events (or callbacks) upon @@ -24,9 +28,10 @@ * - heartbeat-nonces-expired * * @since 3.6.0 - * @output wp-includes/js/heartbeat.js + * @param {JQueryStatic} $ The jQuery object. + * @param {Window} window The global window object. + * @param {undefined} undefined The undefined value. */ - ( function( $, window, undefined ) { /** @@ -35,7 +40,7 @@ * @since 3.6.0 * * @return {Object} An instance of the Heartbeat class. - * @constructor + * @class */ var Heartbeat = function() { var $document = $(document), @@ -239,8 +244,8 @@ /** * Handles pageshow event, specifically when page navigation is restored from back/forward cache. * - * @param {jQuery.Event} event - * @param {PageTransitionEvent} event.originalEvent + * @param {JQuery.Event} event The jQuery event object. + * @param {PageTransitionEvent} event.originalEvent The original PageTransitionEvent object. */ function ( event ) { if ( event.originalEvent.persisted ) { @@ -281,6 +286,7 @@ * @since 3.6.0 * @access private * + * @param {HTMLIFrameElement} frame The iframe element to check. * @return {boolean} Returns whether or not the iframe is from the same origin. */ function isLocalFrame( frame ) { @@ -784,12 +790,17 @@ /** * Enqueues data to send with the next XHR. * - * As the data is send asynchronously, this function doesn't return the XHR + * As the data is sent asynchronously, this function doesn't return the XHR * response. To see the response, use the custom jQuery event 'heartbeat-tick' - * on the document, example: + * on the document. + * + * @example + * ```javascript * $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) { * // code * }); + * ``` + * * If the same 'handle' is used more than once, the data is not overwritten when * the third argument is 'true'. Use `wp.heartbeat.isQueued('handle')` to see if * any data is already queued for that handle. @@ -824,7 +835,7 @@ * * @param {string} handle The handle for the data. * - * @return {boolean} True if the data is queued with this handle. + * @return {void|boolean} True if the data is queued with this handle. */ function isQueued( handle ) { if ( handle ) { diff --git a/src/js/_enqueues/wp/mce-view.js b/src/js/_enqueues/wp/mce-view.js index 863803f614816..4bbd71efc31f0 100644 --- a/src/js/_enqueues/wp/mce-view.js +++ b/src/js/_enqueues/wp/mce-view.js @@ -4,7 +4,7 @@ /* global tinymce */ -/* +/** * The TinyMCE view API. * * Note: this API is "experimental" meaning that it will probably change @@ -25,6 +25,11 @@ * | | |- ... * |- registered view * | |- ... + * + * @param {Window} window The global window object. + * @param {Object} wp The WordPress global object. + * @param {Object} shortcode The shortcode API. + * @param {JQueryStatic} $ The jQuery object. */ ( function( window, wp, shortcode, $ ) { 'use strict'; @@ -88,8 +93,8 @@ * replacing any matches with markers, * and creates a new instance for every match. * - * @param {string} content The string to scan. - * @param {tinymce.Editor} editor The editor. + * @param {string} content The string to scan. + * @param {tinymce.Editor} editor The editor. * * @return {string} The string with markers. */ @@ -190,7 +195,7 @@ /** * Get a view instance. * - * @param {(string|HTMLElement)} object The textual representation of the view or the view node. + * @param {string|HTMLElement} object The textual representation of the view or the view node. * * @return {wp.mce.View} The view instance or undefined. */ @@ -296,7 +301,7 @@ /** * Whether or not to display a loader. * - * @type {Boolean} + * @type {boolean} */ loader: true, @@ -308,7 +313,7 @@ /** * Returns the content to render in the view node. * - * @return {*} + * @return {*} The content. */ getContent: function() { return this.content; @@ -615,6 +620,9 @@ iframeDoc.close(); + /** + * Resizes the iframe to fit its content. + */ function resize() { var $iframe; @@ -643,6 +651,9 @@ }, 3000 ); } + /** + * Adds a MutationObserver to the iframe's body to watch for changes and resize accordingly. + */ function addObserver() { observer = new MutationObserver( _.debounce( resize, 100 ) ); @@ -675,6 +686,8 @@ /** * Sets a loader for all view nodes tied to this view instance. + * + * @param {string} dashicon The dashicon ID. Optional. */ setLoader: function( dashicon ) { this.setContent( @@ -705,7 +718,7 @@ * * @param {string} content The string to scan. * - * @return {Object} + * @return {void|Object} An object with the match index, content and options, or undefined if no match was found. */ match: function( content ) { var match = shortcode.next( this.type, content ); @@ -761,15 +774,27 @@ } ); } )( window, window.wp, window.wp.shortcode, window.jQuery ); -/* +/** * The WordPress core TinyMCE views. + * * Views for the gallery, audio, video, playlist and embed shortcodes, * and a view for embeddable URLs. + * + * @param {Window} window The global window object. + * @param {Object} views The wp.mce.views object. + * @param {Object} media The wp.media object. + * @param {JQueryStatic} $ The jQuery object. */ ( function( window, views, media, $ ) { var base, gallery, av, embed, schema, parser, serializer; + /** + * Verifies that a given string is valid HTML. + * + * @param {string} string The string to verify. + * @return {string} The verified string. + */ function verifyHTML( string ) { var settings = {}; diff --git a/src/js/_enqueues/wp/media/audiovideo.js b/src/js/_enqueues/wp/media/audiovideo.js index f0127cc507119..1eb419f0d5feb 100644 --- a/src/js/_enqueues/wp/media/audiovideo.js +++ b/src/js/_enqueues/wp/media/audiovideo.js @@ -7,7 +7,6 @@ var media = wp.media, l10n = window._wpMediaViewsL10n || {}; /** - * * Defines the wp.media.mixin object. * * @mixin @@ -44,6 +43,7 @@ wp.media.mixin = { * * @since 4.2.0 * + * @param {Object} t The MediaElement player object. * @return {void} */ removePlayer: function(t) { @@ -81,7 +81,6 @@ wp.media.mixin = { }, /** - * * Removes and resets all players. * * Allows any class that has set 'player' to a MediaElementPlayer @@ -196,8 +195,8 @@ wp.media.audio = { /** * Shortcode modeling for video. * - * `edit()` prepares the shortcode for the media modal. - * `shortcode()` builds the new shortcode after update. + * `edit()` prepares the shortcode for the media modal. + * `shortcode()` builds the new shortcode after update. * * @since 4.2.0 * diff --git a/src/js/_enqueues/wp/media/editor.js b/src/js/_enqueues/wp/media/editor.js index 1097bca966fdb..47eb074aaa8ce 100644 --- a/src/js/_enqueues/wp/media/editor.js +++ b/src/js/_enqueues/wp/media/editor.js @@ -4,8 +4,12 @@ /* global getUserSetting, tinymce, QTags */ -// WordPress, TinyMCE, and Media -// ----------------------------- +/** + * Handles the initialization, refreshing and rendering of media editor components. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {_.UnderscoreStatic} _ The Underscore.js object. + */ (function($, _){ /** * Stores the editors' `wp.media.controller.Frame` instances. @@ -16,11 +20,11 @@ /** * A helper mixin function to avoid truthy and falsey values being - * passed as an input that expects booleans. If key is undefined in the map, - * but has a default value, set it. + * passed as an input that expects booleans. If key is undefined in the map, + * but has a default value, set it. * * @param {Object} attrs Map of props from a shortcode or settings. - * @param {string} key The key within the passed map to check for a value. + * @param {string} key The key within the passed map to check for a value. * @return {mixed|undefined} The original or coerced value of key within attrs. */ wp.media.coerce = function ( attrs, key ) { @@ -107,7 +111,7 @@ /** * Create link markup that is suitable for passing to the editor * - * @param {Object} props Attachment details (align, link, size, etc). + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. * @return {string} The link markup */ @@ -133,7 +137,7 @@ /** * Create an Audio shortcode string that is suitable for passing to the editor * - * @param {Object} props Attachment details (align, link, size, etc). + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. * @return {string} The audio shortcode */ @@ -143,7 +147,7 @@ /** * Create a Video shortcode string that is suitable for passing to the editor * - * @param {Object} props Attachment details (align, link, size, etc). + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. * @return {string} The video shortcode */ @@ -155,8 +159,8 @@ * * @access private * - * @param {string} type The shortcode tag name: 'audio' or 'video'. - * @param {Object} props Attachment details (align, link, size, etc). + * @param {string} type The shortcode tag name: 'audio' or 'video'. + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. * @return {string} The media shortcode */ @@ -202,11 +206,11 @@ }, /** * Create image markup, optionally with a link and/or wrapped in a caption shortcode, - * that is suitable for passing to the editor + * that is suitable for passing to the editor * - * @param {Object} props Attachment details (align, link, size, etc). + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. - * @return {string} + * @return {string} The image markup. */ image: function( props, attachment ) { var img = {}, @@ -333,9 +337,11 @@ }; /** + * Factory function that creates a media collection controller for managing gallery, playlist, and other media shortcodes. + * * @class wp.media.collection * - * @param {Object} attributes + * @param {Object} attributes The attributes for the media collection. */ wp.media.collection = function(attributes) { var collections = {}; @@ -412,10 +418,10 @@ * Triggered when clicking 'Insert {label}' or 'Update {label}' * * @param {wp.media.model.Attachments} attachments A Backbone.Collection containing - * the media items belonging to a collection. - * The query[ this.tag ] property is a Backbone.Model - * containing the 'props' for the collection. - * @return {wp.shortcode} + * the media items belonging to a collection. + * The query[ this.tag ] property is a Backbone.Model + * containing the 'props' for the collection. + * @return {wp.shortcode} A wp.shortcode instance representing the collection. */ shortcode: function( attachments ) { var props = attachments.props.toJSON(), @@ -479,14 +485,14 @@ }, /** * Triggered when double-clicking a collection shortcode placeholder - * in the editor + * in the editor * * @param {string} content Content that is searched for possible - * shortcode markup matching the passed tag name, + * shortcode markup matching the passed tag name, * - * @this wp.media.{prop} + * @this {wp.media.view.MediaFrame.Select} * - * @return {wp.media.view.MediaFrame.Select} A media workflow. + * @return {void|wp.media.view.MediaFrame.Select} A media workflow. */ edit: function( content ) { var shortcode = wp.shortcode.next( this.tag, content ), @@ -606,7 +612,7 @@ /** * Get the featured image post ID * - * @return {wp.media.view.settings.post.featuredImageId|number} + * @return {wp.media.view.settings.post.featuredImageId|number} The post ID of the featured image, or -1 if none is set. */ get: function() { return wp.media.view.settings.post.featuredImageId; @@ -643,7 +649,7 @@ /** * The Featured Image workflow * - * @this wp.media.featuredImage + * @this {wp.media.featuredImage} * * @return {wp.media.view.MediaFrame.Select} A media workflow. */ @@ -660,7 +666,7 @@ this._frame.on( 'toolbar:create:featured-image', function( toolbar ) { /** - * @this wp.media.view.MediaFrame.Select + * @this {wp.media.view.MediaFrame.Select} */ this.createSelectToolbar( toolbar, { text: wp.media.view.l10n.setFeaturedImage @@ -683,9 +689,9 @@ }, /** * 'select' callback for Featured Image workflow, triggered when - * the 'Set Featured Image' button is clicked in the media modal. + * the 'Set Featured Image' button is clicked in the media modal. * - * @this wp.media.controller.FeaturedImage + * @this {wp.media.controller.FeaturedImage} */ select: function() { var selection = this.get('selection').single(); @@ -727,7 +733,8 @@ /** * Send content to the editor * - * @param {string} html Content to send to the editor + * @param {string} html Content to send to the editor. + * @return {void} */ insert: function( html ) { var editor, wpActiveEditor, @@ -777,12 +784,12 @@ /** * Setup 'workflow' and add to the 'workflows' cache. 'open' can - * subsequently be called upon it. + * subsequently be called upon it. * - * @param {string} id A slug used to identify the workflow. - * @param {Object} [options={}] + * @param {string} id A slug used to identify the workflow. + * @param {Object} [options={}] The options for the media workflow. * - * @this wp.media.editor + * @this {wp.media.editor} * * @return {wp.media.view.MediaFrame.Select} A media workflow. */ @@ -813,7 +820,7 @@ $.when.apply( $, selection.map( function( attachment ) { var display = state.display( attachment ).toJSON(); /** - * @this wp.media.editor + * @this {wp.media.editor} */ return this.send.attachment( display, attachment.toJSON() ); }, this ) ).done( function() { @@ -823,28 +830,28 @@ workflow.state('gallery-edit').on( 'update', function( selection ) { /** - * @this wp.media.editor + * @this {wp.media.editor} */ this.insert( wp.media.gallery.shortcode( selection ).string() ); }, this ); workflow.state('playlist-edit').on( 'update', function( selection ) { /** - * @this wp.media.editor + * @this {wp.media.editor} */ this.insert( wp.media.playlist.shortcode( selection ).string() ); }, this ); workflow.state('video-playlist-edit').on( 'update', function( selection ) { /** - * @this wp.media.editor + * @this {wp.media.editor} */ this.insert( wp.media.playlist.shortcode( selection ).string() ); }, this ); workflow.state('embed').on( 'select', function() { /** - * @this wp.media.editor + * @this {wp.media.editor} */ var state = workflow.state(), type = state.get('type'), @@ -889,7 +896,7 @@ * * @param {string} [id=''] A slug used to identify the workflow. * - * @return {wpActiveEditor|string|tinymce.activeEditor.id} + * @return {wpActiveEditor|string|tinymce.activeEditor.id} The current workflow id. */ id: function( id ) { if ( id ) { @@ -913,7 +920,7 @@ * * @param {string} id A slug used to identify the workflow. * - * @this wp.media.editor + * @this {wp.media.editor} * * @return {wp.media.view.MediaFrame} A media workflow. */ @@ -926,7 +933,7 @@ * * @param {string} id A slug used to identify the workflow. * - * @this wp.media.editor + * @this {wp.media.editor} */ remove: function( id ) { id = this.id( id ); @@ -936,11 +943,11 @@ send: { /** * Called when sending an attachment to the editor - * from the medial modal. + * from the medial modal. * - * @param {Object} props Attachment details (align, link, size, etc). + * @param {Object} props Attachment details (align, link, size, etc). * @param {Object} attachment The attachment object, media version of Post. - * @return {Promise} + * @return {Promise} A promise that resolves when the attachment has been sent to the editor. */ attachment: function( props, attachment ) { var caption = attachment.caption, @@ -994,8 +1001,8 @@ /** * Called when 'Insert From URL' source is not an image. Example: YouTube url. * - * @param {Object} embed - * @return {Promise} + * @param {Object} embed The embed object containing the link URL and link text. + * @return {Promise} A promise that resolves when the link has been sent to the editor. */ link: function( embed ) { return wp.media.post( 'send-link-to-editor', { @@ -1008,14 +1015,14 @@ } }, /** - * Open a workflow + * Opens a workflow. * * @param {string} [id=undefined] Optional. A slug used to identify the workflow. - * @param {Object} [options={}] + * @param {Object} [options={}] The options for the media workflow. * - * @this wp.media.editor + * @this {wp.media.editor} * - * @return {wp.media.view.MediaFrame} + * @return {wp.media.view.MediaFrame} A media workflow. */ open: function( id, options ) { var workflow; diff --git a/src/js/_enqueues/wp/media/models.js b/src/js/_enqueues/wp/media/models.js index edca0a14f2113..e10db02bfd4b2 100644 --- a/src/js/_enqueues/wp/media/models.js +++ b/src/js/_enqueues/wp/media/models.js @@ -17,7 +17,7 @@ window.wp = window.wp || {}; * @namespace * * @param {Object} attributes The properties passed to the main media controller. - * @return {wp.media.view.MediaFrame} A media workflow. + * @return {void|wp.media.view.MediaFrame} A media workflow. */ media = wp.media = function( attributes ) { var MediaFrame = media.view.MediaFrame, @@ -136,8 +136,12 @@ _.extend( media, /** @lends wp.media */{ /** * Scales a set of dimensions to fit within bounding dimensions. * - * @param {Object} dimensions - * @return {Object} + * @param {Object} dimensions The dimensions to scale. + * @param {number} dimensions.width The width to scale. + * @param {number} dimensions.height The height to scale. + * @param {number} dimensions.maxWidth The maxWidth to scale. + * @param {number} dimensions.maxHeight The maxHeight to scale. + * @return {Object} The scaled dimensions. */ fit: function( dimensions ) { var width = dimensions.width, @@ -182,9 +186,9 @@ _.extend( media, /** @lends wp.media */{ * Truncates a string by injecting an ellipsis into the middle. * Useful for filenames. * - * @param {string} string - * @param {number} [length=30] - * @param {string} [replacement=…] + * @param {string} string The string to truncate. + * @param {number} [length=30] The maximum length of the truncated string. + * @param {string} [replacement=…] The string to use as the ellipsis replacement. * @return {string} The string, unless length is greater than string.length. */ truncate: function( string, length, replacement ) { @@ -209,7 +213,7 @@ _.extend( media, /** @lends wp.media */{ * * @static * @param {string} id A string used to identify a model. - * @return {wp.media.model.Attachment} + * @return {wp.media.model.Attachment} The attachment model for the given id. */ media.attachment = function( id ) { return Attachment.get( id ); @@ -228,8 +232,8 @@ Attachments.all = new Attachments(); * * Shorthand for creating a new Attachments Query. * - * @param {Object} [props] - * @return {wp.media.model.Attachments} + * @param {Object} [props] The properties to filter the attachments by. + * @return {wp.media.model.Attachments} A collection of attachments matching the query. */ media.query = function( props ) { return new Attachments( null, { diff --git a/src/js/_enqueues/wp/media/views.js b/src/js/_enqueues/wp/media/views.js index d87046fcf0e2b..1eec769227e12 100644 --- a/src/js/_enqueues/wp/media/views.js +++ b/src/js/_enqueues/wp/media/views.js @@ -47,9 +47,9 @@ media.events = _.extend( {}, Backbone.Events ); /** * Makes it easier to bind events using transitions. * - * @param {string} selector - * @param {number} sensitivity - * @return {Promise} + * @param {string} selector The CSS selector for the element to bind the transition event to. + * @param {number} sensitivity The maximum time to wait for the transition event before resolving the promise. + * @return {Promise} A promise that resolves when the transition has completed. */ media.transition = function( selector, sensitivity ) { var deferred = $.Deferred(); diff --git a/src/js/_enqueues/wp/password-strength-meter.js b/src/js/_enqueues/wp/password-strength-meter.js index 506088b038c8f..3ed6d48d5ef25 100644 --- a/src/js/_enqueues/wp/password-strength-meter.js +++ b/src/js/_enqueues/wp/password-strength-meter.js @@ -3,9 +3,11 @@ */ /* global zxcvbn */ + +/** @namespace wp */ window.wp = window.wp || {}; -(function($){ +( function( $, wp ) { var __ = wp.i18n.__, sprintf = wp.i18n.sprintf; @@ -24,10 +26,10 @@ window.wp = window.wp || {}; * * @since 3.7.0 * - * @param {string} password1 The subject password. + * @param {string} password1 The subject password. * @param {Array} disallowedList An array of words that will lower the entropy of - * the password. - * @param {string} password2 The password confirmation. + * the password. + * @param {string} password2 The password confirmation. * * @return {number} The password strength score. */ @@ -146,4 +148,4 @@ window.wp = window.wp || {}; * @type {wp.passwordStrength.meter} */ window.passwordStrength = wp.passwordStrength.meter; -})(jQuery); +} )( jQuery, window.wp ); diff --git a/src/js/_enqueues/wp/revisions.js b/src/js/_enqueues/wp/revisions.js index b0c555e934361..3efb3dcb7ac5d 100644 --- a/src/js/_enqueues/wp/revisions.js +++ b/src/js/_enqueues/wp/revisions.js @@ -368,8 +368,8 @@ window.wp = window.wp || {}; * * @see wp.revisions.view.Frame * - * @param {object} attributes Model attributes - none are required. - * @param {object} options Options for the model. + * @param {Object} attributes Model attributes - none are required. + * @param {Object} options Options for the model. * @param {revisions.model.Revisions} options.revisions A collection of revisions. */ revisions.model.FrameState = Backbone.Model.extend({ @@ -533,7 +533,7 @@ window.wp = window.wp || {}; * * Top level frame that orchestrates the revisions experience. * - * @param {object} options The options hash for the view. + * @param {Object} options The options hash for the view. * @param {revisions.model.FrameState} options.model The frame state model. */ revisions.view.Frame = wp.Backbone.View.extend({ diff --git a/src/js/_enqueues/wp/sanitize.js b/src/js/_enqueues/wp/sanitize.js index c0b6b0bed9494..f67a8fd25a97f 100644 --- a/src/js/_enqueues/wp/sanitize.js +++ b/src/js/_enqueues/wp/sanitize.js @@ -2,8 +2,9 @@ * @output wp-includes/js/wp-sanitize.js */ -/* eslint-env es6 */ - +/** + * Provides helper functions to sanitize strings. + */ ( function () { window.wp = window.wp || {}; @@ -18,7 +19,7 @@ /** * Strip HTML tags. * - * @param {string} text - Text to strip the HTML tags from. + * @param {string} text Text to strip the HTML tags from. * * @return {string} Stripped text. */ @@ -51,7 +52,7 @@ /** * Strip HTML tags and convert HTML entities. * - * @param {string} text - Text to strip tags and convert HTML entities. + * @param {string} text Text to strip tags and convert HTML entities. * * @return {string} Sanitized text. */ diff --git a/src/js/_enqueues/wp/theme-plugin-editor.js b/src/js/_enqueues/wp/theme-plugin-editor.js index 7bcff376e9ff2..72a4471a93994 100644 --- a/src/js/_enqueues/wp/theme-plugin-editor.js +++ b/src/js/_enqueues/wp/theme-plugin-editor.js @@ -2,14 +2,15 @@ * @output wp-admin/js/theme-plugin-editor.js */ -/* eslint-env es2020 */ - /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 9, 1000] }] */ if ( ! window.wp ) { window.wp = {}; } +/** + * @param {JQueryStatic} $ The jQuery object. + */ wp.themePluginEditor = (function( $ ) { 'use strict'; var component, TreeLinks, @@ -28,9 +29,9 @@ wp.themePluginEditor = (function( $ ) { * * @since 4.9.0 * - * @param {jQuery} form - Form element. - * @param {Object} settings - Settings. - * @param {Object|boolean} settings.codeEditor - Code editor settings (or `false` if syntax highlighting is disabled). + * @param {jQuery} form Form element. + * @param {Object} settings Settings. + * @param {Object|boolean} settings.codeEditor Code editor settings (or `false` if syntax highlighting is disabled). * @return {void} */ component.init = function init( form, settings ) { @@ -186,7 +187,7 @@ wp.themePluginEditor = (function( $ ) { * Submit file via Ajax. * * @since 4.9.0 - * @param {jQuery.Event} event - Event. + * @param {jQuery.Event} event Event. * @return {void} */ component.submit = function( event ) { @@ -272,12 +273,12 @@ wp.themePluginEditor = (function( $ ) { * * @since 4.9.0 * - * @param {Object} notice - Notice. - * @param {string} notice.code - Code. - * @param {string} notice.type - Type. - * @param {string} notice.message - Message. - * @param {boolean} [notice.dismissible=false] - Dismissible. - * @param {Function} [notice.onDismiss] - Callback for when a user dismisses the notice. + * @param {Object} notice Notice. + * @param {string} notice.code Code. + * @param {string} notice.type Type. + * @param {string} notice.message Message. + * @param {boolean} [notice.dismissible=false] Dismissible. + * @param {Function} [notice.onDismiss] Callback for when a user dismisses the notice. * @return {jQuery} Notice element. */ component.addNotice = function( notice ) { @@ -313,7 +314,7 @@ wp.themePluginEditor = (function( $ ) { * * @since 4.9.0 * - * @param {string} code - Notice code. + * @param {string} code Notice code. * @return {boolean} Whether a notice was removed. */ component.removeNotice = function( code ) { @@ -365,7 +366,7 @@ wp.themePluginEditor = (function( $ ) { * * @since 4.9.0 * - * @param {Array} errors - List of linting errors. + * @param {Array} errors List of linting errors. * @return {void} */ codeEditorSettings.onChangeLintingErrors = function( errors ) { @@ -382,7 +383,7 @@ wp.themePluginEditor = (function( $ ) { * * @since 4.9.0 * - * @param {Array} errorAnnotations - Error annotations. + * @param {Array} errorAnnotations Error annotations. * @return {void} */ codeEditorSettings.onUpdateErrorNotice = function onUpdateErrorNotice( errorAnnotations ) { @@ -417,6 +418,9 @@ wp.themePluginEditor = (function( $ ) { editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings ); editor.codemirror.on( 'change', component.onChange ); + /** + * Handles the save shortcut (Ctrl+S / Cmd+S). + */ function onSaveShortcut() { component.form.trigger( 'submit' ); } @@ -476,10 +480,6 @@ wp.themePluginEditor = (function( $ ) { } ); }; - /* jshint ignore:start */ - /* jscs:disable */ - /* eslint-disable */ - /** * Creates a new TreeitemLink. * @@ -491,26 +491,24 @@ wp.themePluginEditor = (function( $ ) { */ var TreeitemLink = (function () { /** - * This content is licensed according to the W3C Software License at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document + * This content is licensed according to the W3C Software License at + * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document * - * File: TreeitemLink.js + * File: TreeitemLink.js * - * Desc: Treeitem widget that implements ARIA Authoring Practices - * for a tree being used as a file viewer + * Desc: Treeitem widget that implements ARIA Authoring Practices + * for a tree being used as a file viewer * - * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt + * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt */ /** - * @constructor + * @class * - * @desc - * Treeitem object for representing the state and user interactions for a - * treeItem widget + * Treeitem object for representing the state and user interactions for a + * treeItem widget * - * @param node - * An element with the role=tree attribute + * @param node An element with the role=tree attribute */ var TreeitemLink = function (node, treeObj, group) { @@ -601,15 +599,25 @@ wp.themePluginEditor = (function( $ ) { /* EVENT HANDLERS */ TreeitemLink.prototype.handleKeydown = function (event) { - var tgt = event.currentTarget, - flag = false, - _char = event.key, - clickEvent; - + var flag = false, + _char = event.key; + + /** + * Determines whether a character is a printable character. + * + * @param {string} str The character to check. + * @return {boolean} True if the character is printable, false otherwise. + */ function isPrintableCharacter(str) { return str.length === 1 && str.match(/\S/); } + /** + * Handles printable character key press. + * + * @param {TreeitemLink} item The tree item link instance. + * @return {void} + */ function printableCharacter(item) { if (_char == '*') { item.tree.expandAllSiblingItems(item); @@ -736,7 +744,7 @@ wp.themePluginEditor = (function( $ ) { } }; - TreeitemLink.prototype.handleFocus = function (event) { + TreeitemLink.prototype.handleFocus = function () { var node = this.domNode; if (this.isExpandable) { node = node.firstElementChild; @@ -744,7 +752,7 @@ wp.themePluginEditor = (function( $ ) { node.classList.add('focus'); }; - TreeitemLink.prototype.handleBlur = function (event) { + TreeitemLink.prototype.handleBlur = function () { var node = this.domNode; if (this.isExpandable) { node = node.firstElementChild; @@ -813,7 +821,14 @@ wp.themePluginEditor = (function( $ ) { }; TreeLinks.prototype.init = function () { - + /** + * Finds all treeitems and groups and creates object instances. + * + * @param {Element} node The DOM node to search for treeitems. + * @param {TreeLinks} tree The TreeLinks instance. + * @param {TreeitemLink|boolean} group The parent TreeitemLink instance or false if there is no parent. + * @return {void} + */ function findTreeitems(node, tree, group) { var elem = node.firstElementChild; @@ -1022,10 +1037,6 @@ wp.themePluginEditor = (function( $ ) { return TreeLinks; })(); - /* jshint ignore:end */ - /* jscs:enable */ - /* eslint-enable */ - return component; })( jQuery ); @@ -1035,7 +1046,7 @@ wp.themePluginEditor = (function( $ ) { * @since 4.9.0 * @deprecated 5.5.0 * - * @type {object} + * @type {Object} */ wp.themePluginEditor.l10n = wp.themePluginEditor.l10n || { saveAlert: '', diff --git a/src/js/_enqueues/wp/theme.js b/src/js/_enqueues/wp/theme.js index cfcea1fcc58b7..c495140302007 100644 --- a/src/js/_enqueues/wp/theme.js +++ b/src/js/_enqueues/wp/theme.js @@ -208,7 +208,7 @@ themes.Collection = Backbone.Collection.extend({ /** * Performs a search within the collection. * - * @uses RegExp + * @param {string} term The search term. */ search: function( term ) { var match, results, haystack, name, description, author; @@ -275,10 +275,6 @@ themes.Collection = Backbone.Collection.extend({ * which triggers events of `query:success` or `query:fail`. */ query: function( request ) { - /** - * @static - * @type Array - */ var queries = this.queries, self = this, query, isPaginated, count; @@ -484,7 +480,7 @@ themes.view.Theme = wp.Backbone.View.extend({ return; } - // Set focused theme to current element. + // Store the theme that had focus when expand is called. themes.focusedTheme = this.$el; this.trigger( 'theme:expand', self.model.cid ); @@ -524,7 +520,7 @@ themes.view.Theme = wp.Backbone.View.extend({ event = event || window.event; - // Set focus to current theme. + // Store the theme that had focus when preview is called. themes.focusedTheme = this.$el; // Construct a new Preview view. @@ -624,18 +620,16 @@ themes.view.Theme = wp.Backbone.View.extend({ if ( 0 === this.model.collection.indexOf( current ) ) { previousThemeButton .addClass( 'disabled' ) - .prop( 'disabled', true ); - - nextThemeButton.trigger( 'focus' ); + .attr( 'aria-disabled', true ) + .trigger( 'focus' ); } // Disable next if the next model is undefined. if ( _.isUndefined( this.model.collection.at( this.model.collection.indexOf( current ) + 1 ) ) ) { nextThemeButton .addClass( 'disabled' ) - .prop( 'disabled', true ); - - previousThemeButton.trigger( 'focus' ); + .attr( 'aria-disabled', true ) + .trigger( 'focus' ); } }, @@ -729,11 +723,14 @@ themes.view.Details = wp.Backbone.View.extend({ // Set initial focus and constrain tabbing within the theme browser modal. containFocus: function( $el ) { + // Set initial focus on the theme overlay modal dialog, only on first render. + var $themeOverlay = $( '.theme-overlay' ); + if ( $themeOverlay.hasClass( 'theme-overlay-initial' ) ) { + _.delay( function() { + $themeOverlay.trigger( 'focus' ).removeClass( 'theme-overlay-initial' ); + }, 100 ); + } - // Set initial focus on the primary action control. - _.delay( function() { - $( '.theme-overlay' ).trigger( 'focus' ); - }, 100 ); // Constrain tabbing within the modal. $el.on( 'keydown.wp-themes', function( event ) { @@ -789,10 +786,13 @@ themes.view.Details = wp.Backbone.View.extend({ // Restore scroll position. document.body.scrollTop = scroll; - // Return focus to the theme div. + // Return focus to the opener theme 'more-details' button. if ( themes.focusedTheme ) { - themes.focusedTheme.find('.more-details').trigger( 'focus' ); + themes.focusedTheme.find( '.more-details' ).trigger( 'focus' ); } + + // Add back the `theme-overlay-initial` class for the theme overlay. + $( '.theme-overlay' ).addClass( 'theme-overlay-initial' ); }); } @@ -807,12 +807,12 @@ themes.view.Details = wp.Backbone.View.extend({ if ( this.model.cid === this.model.collection.at(0).cid ) { this.$el.find( '.left' ) .addClass( 'disabled' ) - .prop( 'disabled', true ); + .attr( 'aria-disabled', true ); } if ( this.model.cid === this.model.collection.at( this.model.collection.length - 1 ).cid ) { this.$el.find( '.right' ) .addClass( 'disabled' ) - .prop( 'disabled', true ); + .attr( 'aria-disabled', true ); } }, @@ -964,6 +964,8 @@ themes.view.Preview = themes.view.Details.extend({ this.$el.fadeIn( 200, function() { $body.addClass( 'theme-installer-active full-overlay-active' ); + // Set initial focus on the theme installer overlay modal dialog. + self.$el.trigger( 'focus' ); }); this.$el.find( 'iframe' ).one( 'load', function() { @@ -980,9 +982,9 @@ themes.view.Preview = themes.view.Details.extend({ this.$el.fadeOut( 200, function() { $( 'body' ).removeClass( 'theme-installer-active full-overlay-active' ); - // Return focus to the theme div. + // Return focus to the opener theme 'more-details' button. if ( themes.focusedTheme ) { - themes.focusedTheme.find('.more-details').trigger( 'focus' ); + themes.focusedTheme.find( '.more-details' ).trigger( 'focus' ); } }).removeClass( 'iframe-ready' ); @@ -1358,6 +1360,8 @@ themes.view.Themes = wp.Backbone.View.extend({ // Trigger a route update for the current model. self.theme.trigger( 'theme:expand', nextModel.cid ); + // Set focus again to the 'Next' navigation button after the view fully re-rendeers. + $( '.theme-header .right' ).trigger( 'focus' ); themes.announceThemeDebounced( nextModel ); } }, @@ -1393,6 +1397,8 @@ themes.view.Themes = wp.Backbone.View.extend({ // Trigger a route update for the current model. self.theme.trigger( 'theme:expand', previousModel.cid ); + // Set focus again to the 'Previous' navigation button after the view fully re-rendeers. + $( '.theme-header .left' ).trigger( 'focus' ); themes.announceThemeDebounced( previousModel ); } }, @@ -1485,8 +1491,8 @@ themes.view.Search = wp.Backbone.View.extend({ * * @since 4.9.0 * - * @param {string} url - URL to navigate to. - * @param {Object} state - State. + * @param {string} url URL to navigate to. + * @param {Object} state State. * @return {void} */ function navigateRouter( url, state ) { @@ -1969,7 +1975,7 @@ themes.view.Installer = themes.view.Appearance.extend({ /** * Clears all the checked filters. * - * @uses filtersChecked() + * @param {Event} event The click event. */ clearFilters: function( event ) { var items = $( '.filter-group' ).find( ':checkbox' ), @@ -2082,9 +2088,9 @@ themes.RunInstaller = { self.view.collection.query( request ); self.view.collection.trigger( 'update' ); - // Open the theme preview. + // Open the theme preview. The slug comes from the URL, so escape it. self.view.collection.once( 'query:success', function() { - $( 'div[data-slug="' + slug + '"]' ).trigger( 'click' ); + $( 'div.theme[data-slug="' + $.escapeSelector( slug ) + '"]' ).trigger( 'click' ); }); } diff --git a/src/js/_enqueues/wp/updates.js b/src/js/_enqueues/wp/updates.js index ef4b47e66093e..6fb48411c52bd 100644 --- a/src/js/_enqueues/wp/updates.js +++ b/src/js/_enqueues/wp/updates.js @@ -1,33 +1,34 @@ /** - * Functions for ajaxified updates, deletions and installs inside the WordPress admin. - * - * @version 4.2.0 * @output wp-admin/js/updates.js */ /* global pagenow, _wpThemeSettings */ /** - * @param {jQuery} $ jQuery object. - * @param {object} wp WP object. - * @param {object} settings WP Updates settings. - * @param {string} settings.ajax_nonce Ajax nonce. - * @param {object=} settings.plugins Base names of plugins in their different states. - * @param {Array} settings.plugins.all Base names of all plugins. - * @param {Array} settings.plugins.active Base names of active plugins. - * @param {Array} settings.plugins.inactive Base names of inactive plugins. - * @param {Array} settings.plugins.upgrade Base names of plugins with updates available. - * @param {Array} settings.plugins.recently_activated Base names of recently activated plugins. - * @param {Array} settings.plugins['auto-update-enabled'] Base names of plugins set to auto-update. - * @param {Array} settings.plugins['auto-update-disabled'] Base names of plugins set to not auto-update. - * @param {object=} settings.themes Slugs of themes in their different states. - * @param {Array} settings.themes.all Slugs of all themes. - * @param {Array} settings.themes.upgrade Slugs of themes with updates available. - * @param {Arrat} settings.themes.disabled Slugs of disabled themes. - * @param {Array} settings.themes['auto-update-enabled'] Slugs of themes set to auto-update. - * @param {Array} settings.themes['auto-update-disabled'] Slugs of themes set to not auto-update. - * @param {object=} settings.totals Combined information for available update counts. - * @param {number} settings.totals.count Holds the amount of available updates. + * Provides functions for ajaxified updates, deletions and installs inside the WordPress admin. + * + * @version 4.2.0 + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} wp The WordPress global object. + * @param {Object} settings WP Updates settings. + * @param {string} settings.ajax_nonce Ajax nonce. + * @param {Object} settings.plugins Base names of plugins in their different states. + * @param {Array} settings.plugins.all Base names of all plugins. + * @param {Array} settings.plugins.active Base names of active plugins. + * @param {Array} settings.plugins.inactive Base names of inactive plugins. + * @param {Array} settings.plugins.upgrade Base names of plugins with updates available. + * @param {Array} settings.plugins.recently_activated Base names of recently activated plugins. + * @param {Array} settings.plugins['auto-update-enabled'] Base names of plugins set to auto-update. + * @param {Array} settings.plugins['auto-update-disabled'] Base names of plugins set to not auto-update. + * @param {Object} settings.themes Slugs of themes in their different states. + * @param {Array} settings.themes.all Slugs of all themes. + * @param {Array} settings.themes.upgrade Slugs of themes with updates available. + * @param {Array} settings.themes.disabled Slugs of disabled themes. + * @param {Array} settings.themes['auto-update-enabled'] Slugs of themes set to auto-update. + * @param {Array} settings.themes['auto-update-disabled'] Slugs of themes set to not auto-update. + * @param {Object} settings.totals Combined information for available update counts. + * @param {number} settings.totals.count Holds the amount of available updates. */ (function( $, wp, settings ) { var $document = $( document ), @@ -54,7 +55,7 @@ * @since 4.2.0 * @deprecated 5.5.0 * - * @type {object} + * @type {Object} */ wp.updates.l10n = { searchResults: '', @@ -155,7 +156,7 @@ * * @since 4.2.0 * - * @type {bool} + * @type {boolean} */ wp.updates.shouldRequestFilesystemCredentials = false; @@ -166,18 +167,19 @@ * @since 4.6.0 Added `available` property to indicate whether credentials have been provided. * * @type {Object} - * @property {Object} filesystemCredentials.ftp Holds FTP credentials. - * @property {string} filesystemCredentials.ftp.host FTP host. Default empty string. - * @property {string} filesystemCredentials.ftp.username FTP user name. Default empty string. - * @property {string} filesystemCredentials.ftp.password FTP password. Default empty string. - * @property {string} filesystemCredentials.ftp.connectionType Type of FTP connection. 'ssh', 'ftp', or 'ftps'. - * Default empty string. - * @property {Object} filesystemCredentials.ssh Holds SSH credentials. - * @property {string} filesystemCredentials.ssh.publicKey The public key. Default empty string. - * @property {string} filesystemCredentials.ssh.privateKey The private key. Default empty string. - * @property {string} filesystemCredentials.fsNonce Filesystem credentials form nonce. - * @property {bool} filesystemCredentials.available Whether filesystem credentials have been provided. - * Default 'false'. + * @property {Object} filesystemCredentials Holds all filesystem credentials. + * @property {Object} filesystemCredentials.ftp Holds FTP credentials. + * @property {string} filesystemCredentials.ftp.host FTP host. Default empty string. + * @property {string} filesystemCredentials.ftp.username FTP user name. Default empty string. + * @property {string} filesystemCredentials.ftp.password FTP password. Default empty string. + * @property {string} filesystemCredentials.ftp.connectionType Type of FTP connection. 'ssh', 'ftp', or 'ftps'. + * Default empty string. + * @property {Object} filesystemCredentials.ssh Holds SSH credentials. + * @property {string} filesystemCredentials.ssh.publicKey The public key. Default empty string. + * @property {string} filesystemCredentials.ssh.privateKey The private key. Default empty string. + * @property {string} filesystemCredentials.fsNonce Filesystem credentials form nonce. + * @property {boolean} filesystemCredentials.available Whether filesystem credentials have been provided. + * Default 'false'. */ wp.updates.filesystemCredentials = { ftp: { @@ -200,7 +202,7 @@ * @since 4.2.0 * @since 4.6.0 More accurately named `ajaxLocked`. * - * @type {bool} + * @type {boolean} */ wp.updates.ajaxLocked = false; @@ -209,7 +211,7 @@ * * @since 4.6.0 * - * @type {function} + * @type {Function} */ wp.updates.adminNotice = wp.template( 'wp-updates-admin-notice' ); @@ -240,14 +242,14 @@ * * @since 4.6.0 * - * @param {Object} data - * @param {*=} data.selector Optional. Selector of an element to be replaced with the admin notice. - * @param {string=} data.id Optional. Unique id that will be used as the notice's id attribute. - * @param {string=} data.className Optional. Class names that will be used in the admin notice. - * @param {string=} data.message Optional. The message displayed in the notice. - * @param {number=} data.successes Optional. The amount of successful operations. - * @param {number=} data.errors Optional. The amount of failed operations. - * @param {Array=} data.errorMessages Optional. Error messages of failed operations. + * @param {Object} data The data for the admin notice. + * @param {*} [data.selector] Optional. Selector of an element to be replaced with the admin notice. + * @param {string} [data.id] Optional. Unique id that will be used as the notice's id attribute. + * @param {string} [data.className] Optional. Class names that will be used in the admin notice. + * @param {string} [data.message] Optional. The message displayed in the notice. + * @param {number} [data.successes] Optional. The amount of successful operations. + * @param {number} [data.errors] Optional. The amount of failed operations. + * @param {Array} [data.errorMessages] Optional. Error messages of failed operations. * */ wp.updates.addAdminNotice = function( data ) { @@ -333,9 +335,9 @@ * * @since 4.6.0 * - * @param {Object} response - * @param {Array=} response.debug Optional. Debug information. - * @param {string=} response.errorCode Optional. Error code for an error that occurred. + * @param {Object} response The response object from the Ajax request. + * @param {Array} [response.debug] Optional. Debug information. + * @param {string} [response.errorCode] Optional. Error code for an error that occurred. */ wp.updates.ajaxAlways = function( response ) { if ( ! response.errorCode || 'unable_to_connect_to_filesystem' !== response.errorCode ) { @@ -427,16 +429,16 @@ * * @since 6.5.0 * - * @param {Object} data An object of data to use for the button. - * @param {string} data.slug The plugin's slug. - * @param {string} data.text The text to use for the button. - * @param {string} data.ariaLabel The value for the button's aria-label attribute. An empty string removes the attribute. - * @param {string=} data.status Optional. An identifier for the status. - * @param {string=} data.removeClasses Optional. A space-separated list of classes to remove from the button. - * @param {string=} data.addClasses Optional. A space-separated list of classes to add to the button. - * @param {string=} data.href Optional. The button's URL. - * @param {string=} data.pluginName Optional. The plugin's name. - * @param {string=} data.plugin Optional. The plugin file, relative to the plugins directory. + * @param {Object} data An object of data to use for the button. + * @param {string} data.slug The plugin's slug. + * @param {string} data.text The text to use for the button. + * @param {string} data.ariaLabel The value for the button's aria-label attribute. An empty string removes the attribute. + * @param {string} [data.status] Optional. An identifier for the status. + * @param {string} [data.removeClasses] Optional. A space-separated list of classes to remove from the button. + * @param {string} [data.addClasses] Optional. A space-separated list of classes to add to the button. + * @param {string} [data.href] Optional. The button's URL. + * @param {string} [data.pluginName] Optional. The plugin's name. + * @param {string} [data.plugin] Optional. The plugin file, relative to the plugins directory. */ wp.updates.setCardButtonStatus = function( data ) { var target = window.parent === window ? null : window.parent; @@ -476,11 +478,11 @@ * @since 4.2.0 * @since 4.6.0 More accurately named `updatePlugin`. * - * @param {Object} args Arguments. - * @param {string} args.plugin Plugin basename. - * @param {string} args.slug Plugin slug. - * @param {updatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.updatePluginSuccess - * @param {updatePluginError=} args.error Optional. Error callback. Default: wp.updates.updatePluginError + * @param {Object} args Arguments. + * @param {string} args.plugin Plugin basename. + * @param {string} args.slug Plugin slug. + * @param {updatePluginSuccess} [args.success] Optional. Success callback. Default: wp.updates.updatePluginSuccess + * @param {updatePluginError} [args.error] Optional. Error callback. Default: wp.updates.updatePluginError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -619,12 +621,12 @@ * @since 4.2.0 * @since 4.6.0 More accurately named `updatePluginError`. * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be updated. - * @param {string} response.plugin Basename of the plugin to be updated. - * @param {string=} response.pluginName Optional. Name of the plugin to be updated. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be updated. + * @param {string} response.plugin Basename of the plugin to be updated. + * @param {string} response.pluginName Optional. Name of the plugin to be updated. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.updatePluginError = function( response ) { var $pluginRow, $card, $message, errorMessage, buttonText, ariaLabel, @@ -736,10 +738,10 @@ * * @since 4.6.0 * - * @param {Object} args Arguments. - * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. - * @param {installPluginSuccess=} args.success Optional. Success callback. Default: wp.updates.installPluginSuccess - * @param {installPluginError=} args.error Optional. Error callback. Default: wp.updates.installPluginError + * @param {Object} args Arguments. + * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. + * @param {installPluginSuccess} args.success Optional. Success callback. Default: wp.updates.installPluginSuccess + * @param {installPluginError} args.error Optional. Error callback. Default: wp.updates.installPluginError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -851,11 +853,11 @@ * * @since 4.6.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be installed. - * @param {string=} response.pluginName Optional. Name of the plugin to be installed. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be installed. + * @param {string} response.pluginName Optional. Name of the plugin to be installed. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.installPluginError = function( response ) { var $card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ), @@ -922,10 +924,10 @@ * * @since 6.5.0 * - * @param {Object} args Arguments. - * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. - * @param {checkPluginDependenciesSuccess=} args.success Optional. Success callback. Default: wp.updates.checkPluginDependenciesSuccess - * @param {checkPluginDependenciesError=} args.error Optional. Error callback. Default: wp.updates.checkPluginDependenciesError + * @param {Object} args Arguments. + * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. + * @param {checkPluginDependenciesSuccess} args.success Optional. Success callback. Default: wp.updates.checkPluginDependenciesSuccess + * @param {checkPluginDependenciesError} args.error Optional. Error callback. Default: wp.updates.checkPluginDependenciesError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -1014,11 +1016,11 @@ * * @since 6.5.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be checked. - * @param {string=} response.pluginName Optional. Name of the plugin to be checked. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be checked. + * @param {string} response.pluginName Optional. Name of the plugin to be checked. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.checkPluginDependenciesError = function( response ) { var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ), @@ -1069,12 +1071,12 @@ * * @since 6.5.0 * - * @param {Object} args Arguments. - * @param {string} args.name The name of the plugin. - * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. - * @param {string} args.plugin The plugin file, relative to the plugins directory. - * @param {activatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.activatePluginSuccess - * @param {activatePluginError=} args.error Optional. Error callback. Default: wp.updates.activatePluginError + * @param {Object} args Arguments. + * @param {string} args.name The name of the plugin. + * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. + * @param {string} args.plugin The plugin file, relative to the plugins directory. + * @param {activatePluginSuccess} args.success Optional. Success callback. Default: wp.updates.activatePluginSuccess + * @param {activatePluginError} args.error Optional. Error callback. Default: wp.updates.activatePluginError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -1114,17 +1116,17 @@ * * @since 6.5.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the activated plugin. - * @param {string} response.pluginName Name of the activated plugin. - * @param {string} response.plugin The plugin file, relative to the plugins directory. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the activated plugin. + * @param {string} response.pluginName Name of the activated plugin. + * @param {string} response.plugin The plugin file, relative to the plugins directory. */ wp.updates.activatePluginSuccess = function( response ) { var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ), buttonText = _x( 'Activated!', 'plugin' ), ariaLabel = sprintf( /* translators: %s: The plugin name. */ - '%s activated successfully.', + __( '%s activated successfully.' ), response.pluginName ); @@ -1163,7 +1165,7 @@ text: _x( 'Active', 'plugin' ), ariaLabel: sprintf( /* translators: %s: The plugin name. */ - '%s is active.', + __( '%s is active.' ), response.pluginName ) } @@ -1177,11 +1179,11 @@ * * @since 6.5.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be activated. - * @param {string=} response.pluginName Optional. Name of the plugin to be activated. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be activated. + * @param {string} response.pluginName Optional. Name of the plugin to be activated. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.activatePluginError = function( response ) { var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ), @@ -1270,11 +1272,11 @@ * * @since 4.6.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be installed. - * @param {string=} response.pluginName Optional. Name of the plugin to be installed. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be installed. + * @param {string} response.pluginName Optional. Name of the plugin to be installed. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.installImporterError = function( response ) { var errorMessage = sprintf( @@ -1321,11 +1323,11 @@ * * @since 4.6.0 * - * @param {Object} args Arguments. - * @param {string} args.plugin Basename of the plugin to be deleted. - * @param {string} args.slug Slug of the plugin to be deleted. - * @param {deletePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.deletePluginSuccess - * @param {deletePluginError=} args.error Optional. Error callback. Default: wp.updates.deletePluginError + * @param {Object} args Arguments. + * @param {string} args.plugin Basename of the plugin to be deleted. + * @param {string} args.slug Slug of the plugin to be deleted. + * @param {deletePluginSuccess} args.success Optional. Success callback. Default: wp.updates.deletePluginSuccess + * @param {deletePluginError} args.error Optional. Error callback. Default: wp.updates.deletePluginError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -1480,12 +1482,12 @@ * * @since 4.6.0 * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be deleted. - * @param {string} response.plugin Base name of the plugin to be deleted - * @param {string=} response.pluginName Optional. Name of the plugin to be deleted. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. + * @param {Object} response Response from the server. + * @param {string} response.slug Slug of the plugin to be deleted. + * @param {string} response.plugin Base name of the plugin to be deleted + * @param {string} response.pluginName Optional. Name of the plugin to be deleted. + * @param {string} response.errorCode Error code for the error that occurred. + * @param {string} response.errorMessage The error that occurred. */ wp.updates.deletePluginError = function( response ) { var $plugin, $pluginUpdateRow, @@ -1537,10 +1539,10 @@ * * @since 4.6.0 * - * @param {Object} args Arguments. - * @param {string} args.slug Theme stylesheet. - * @param {updateThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.updateThemeSuccess - * @param {updateThemeError=} args.error Optional. Error callback. Default: wp.updates.updateThemeError + * @param {Object} args Arguments. + * @param {string} args.slug Theme stylesheet. + * @param {updateThemeSuccess} args.success Optional. Success callback. Default: wp.updates.updateThemeSuccess + * @param {updateThemeError} args.error Optional. Error callback. Default: wp.updates.updateThemeError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -1593,7 +1595,7 @@ * @since 4.6.0 * @since 5.5.0 Auto-update "time to next update" text cleared. * - * @param {Object} response + * @param {Object} response The response object from the Ajax request. * @param {string} response.slug Slug of the theme to be updated. * @param {Object} response.theme Updated theme. * @param {string} response.oldVersion Old version of the theme. @@ -1708,10 +1710,10 @@ * * @since 4.6.0 * - * @param {Object} args - * @param {string} args.slug Theme stylesheet. - * @param {installThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.installThemeSuccess - * @param {installThemeError=} args.error Optional. Error callback. Default: wp.updates.installThemeError + * @param {Object} args The arguments for the theme installation request. + * @param {string} args.slug Theme stylesheet. + * @param {installThemeSuccess} args.success Optional. Success callback. Default: wp.updates.installThemeSuccess + * @param {installThemeError} args.error Optional. Error callback. Default: wp.updates.installThemeError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -1900,10 +1902,10 @@ * * @since 4.6.0 * - * @param {Object} args - * @param {string} args.slug Theme stylesheet. - * @param {deleteThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.deleteThemeSuccess - * @param {deleteThemeError=} args.error Optional. Error callback. Default: wp.updates.deleteThemeError + * @param {Object} args The arguments for the theme deletion request. + * @param {string} args.slug Theme stylesheet. + * @param {deleteThemeSuccess} args.success Optional. Success callback. Default: wp.updates.deleteThemeSuccess + * @param {deleteThemeError} args.error Optional. Error callback. Default: wp.updates.deleteThemeError * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -2147,7 +2149,7 @@ * * @since 4.2.0 * - * @param {Event=} event Optional. Event interface. + * @param {Event} event Optional. Event interface. */ wp.updates.requestFilesystemCredentials = function( event ) { if ( false === wp.updates.filesystemCredentials.available ) { @@ -2169,7 +2171,7 @@ * * @since 4.6.0 * - * @param {Event=} event Optional. Event interface. + * @param {Event} event Optional. Event interface. */ wp.updates.maybeRequestFilesystemCredentials = function( event ) { if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { @@ -2325,12 +2327,13 @@ * * If the response deems to be invalid, an admin notice is being displayed. * - * @param {(Object|string)} response Response from the server. - * @param {function=} response.always Optional. Callback for when the Deferred is resolved or rejected. - * @param {string=} response.statusText Optional. Status message corresponding to the status code. - * @param {string=} response.responseText Optional. Request response as text. - * @param {string} action Type of action the response is referring to. Can be 'delete', - * 'update' or 'install'. + * @param {(Object|string)} response Response from the server. + * @param {Function} [response.always] Optional. Callback for when the Deferred is resolved or rejected. + * @param {string} [response.statusText] Optional. Status message corresponding to the status code. + * @param {string} [response.responseText] Optional. Request response as text. + * @param {string} action Type of action the response is referring to. Can be 'delete', + * 'update' or 'install'. + * @return {boolean} Whether the response is valid or not. */ wp.updates.isValidResponse = function( response, action ) { var error = __( 'An error occurred during the update process. Please try again.' ), @@ -2421,6 +2424,7 @@ * opens an "Are you sure?" alert. * * @since 4.2.0 + * @return {string|void} Message to display in the "Are you sure?" alert, or nothing. */ wp.updates.beforeunload = function() { if ( wp.updates.ajaxLocked ) { @@ -3301,7 +3305,10 @@ // Called from `wp-admin/includes/class-wp-upgrader-skins.php`. case 'decrementUpdateCount': - /** @property {string} message.upgradeType */ + /** + * @property {string} message The message associated with the update. + * @property {string} message.upgradeType The type of upgrade being performed. + */ wp.updates.decrementCount( message.upgradeType ); break; diff --git a/src/js/_enqueues/wp/util.js b/src/js/_enqueues/wp/util.js index f6425f2178bcb..e29fd3be462e8 100644 --- a/src/js/_enqueues/wp/util.js +++ b/src/js/_enqueues/wp/util.js @@ -18,7 +18,7 @@ window.wp = window.wp || {}; * * @param {string} id A string that corresponds to a DOM element with an id prefixed with "tmpl-". * For example, "attachment" maps to "tmpl-attachment". - * @return {function} A function that lazily-compiles the template requested. + * @return {Function} A function that lazily-compiles the template requested. */ wp.template = _.memoize(function ( id ) { var compiled, @@ -60,9 +60,9 @@ window.wp = window.wp || {}; * * Sends a POST request to WordPress. * - * @param {(string|Object)} action The slug of the action to fire in WordPress or options passed - * to jQuery.ajax. - * @param {Object=} data Optional. The data to populate $_POST with. + * @param {string|Object} action The slug of the action to fire in WordPress or options passed + * to jQuery.ajax. + * @param {Object} [data] Optional. The data to populate $_POST with. * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ @@ -77,9 +77,9 @@ window.wp = window.wp || {}; * * Sends a POST request to WordPress. * - * @param {(string|Object)} action The slug of the action to fire in WordPress or options passed - * to jQuery.ajax. - * @param {Object=} options Optional. The options passed to jQuery.ajax. + * @param {(string|Object)} action The slug of the action to fire in WordPress or options passed + * to jQuery.ajax. + * @param {Object} [options] Optional. The options passed to jQuery.ajax. * @return {$.promise} A jQuery promise that represents the request, * decorated with an abort() method. */ diff --git a/src/js/_enqueues/wp/utils/word-count.js b/src/js/_enqueues/wp/utils/word-count.js index 066fc5817b491..4c336582ecf63 100644 --- a/src/js/_enqueues/wp/utils/word-count.js +++ b/src/js/_enqueues/wp/utils/word-count.js @@ -148,8 +148,8 @@ * * @memberof wp.utils.wordcounter * - * @param {string} text Text to count elements in. - * @param {string} type Optional. Specify type to use. + * @param {string} text Text to count elements in. + * @param {string} type Optional. Specify type to use. * * @return {number} The number of items counted. */ diff --git a/src/js/_enqueues/wp/widgets/custom-html.js b/src/js/_enqueues/wp/widgets/custom-html.js index 0f1fde1642e94..73faf12af61da 100644 --- a/src/js/_enqueues/wp/widgets/custom-html.js +++ b/src/js/_enqueues/wp/widgets/custom-html.js @@ -9,6 +9,8 @@ /** * @namespace wp.customHtmlWidget * @memberOf wp + * + * @param {JQueryStatic} $ The jQuery object. */ wp.customHtmlWidgets = ( function( $ ) { 'use strict'; @@ -40,9 +42,9 @@ wp.customHtmlWidgets = ( function( $ ) { * @augments Backbone.View * @abstract * - * @param {Object} options - Options. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. + * @param {Object} options Options. + * @param {jQuery} options.el Control field container element. + * @param {jQuery} options.syncContainer Container element where fields are synced for the server. * * @return {void} */ @@ -122,7 +124,7 @@ wp.customHtmlWidgets = ( function( $ ) { /** * Show linting error notice. * - * @param {Array} errorAnnotations - Error annotations. + * @param {Array} errorAnnotations Error annotations. * @return {void} */ updateErrorNotice: function( errorAnnotations ) { @@ -203,7 +205,7 @@ wp.customHtmlWidgets = ( function( $ ) { * * @ignore * - * @param {Array} errorAnnotations - Error notifications. + * @param {Array} errorAnnotations Error notifications. * @return {void} */ onChangeLintingErrors: function onChangeLintingErrors( errorAnnotations ) { @@ -215,7 +217,7 @@ wp.customHtmlWidgets = ( function( $ ) { * * @ignore * - * @param {Array} errorAnnotations - Error annotations. + * @param {Array} errorAnnotations Error annotations. * @return {void} */ onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { @@ -285,8 +287,8 @@ wp.customHtmlWidgets = ( function( $ ) { * * @alias wp.customHtmlWidgets.handleWidgetAdded * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * * @return {void} */ @@ -382,8 +384,8 @@ wp.customHtmlWidgets = ( function( $ ) { * * @alias wp.customHtmlWidgets.handleWidgetUpdated * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * @return {void} */ component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) { @@ -413,7 +415,7 @@ wp.customHtmlWidgets = ( function( $ ) { * * @alias wp.customHtmlWidgets.init * - * @param {Object} settings - Options for code editor, exported from PHP. + * @param {Object} settings Options for code editor, exported from PHP. * * @return {void} */ diff --git a/src/js/_enqueues/wp/widgets/media-audio.js b/src/js/_enqueues/wp/widgets/media-audio.js index a57925364da70..ea85263298ed4 100644 --- a/src/js/_enqueues/wp/widgets/media-audio.js +++ b/src/js/_enqueues/wp/widgets/media-audio.js @@ -69,7 +69,7 @@ /** * Map model props to media frame props. * - * @param {Object} modelProps - Model props. + * @param {Object} modelProps Model props. * @return {Object} Media frame props. */ mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { diff --git a/src/js/_enqueues/wp/widgets/media-gallery.js b/src/js/_enqueues/wp/widgets/media-gallery.js index 020e9787a0f38..fe9f93cb381db 100644 --- a/src/js/_enqueues/wp/widgets/media-gallery.js +++ b/src/js/_enqueues/wp/widgets/media-gallery.js @@ -69,7 +69,7 @@ * View events. * * @since 4.9.0 - * @type {object} + * @type {Object} */ events: _.extend( {}, component.MediaWidgetControl.prototype.events, { 'click .media-widget-gallery-preview': 'editMedia' @@ -84,10 +84,10 @@ * @augments wp.mediaWidgets.MediaWidgetControl * * @since 4.9.0 - * @param {Object} options - Options. - * @param {Backbone.Model} options.model - Model. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. + * @param {Object} options Options. + * @param {Backbone.Model} options.model Model. + * @param {jQuery} options.el Control field container element. + * @param {jQuery} options.syncContainer Container element where fields are synced for the server. * @return {void} */ initialize: function initialize( options ) { @@ -320,7 +320,7 @@ * Clear the selected attachment when it is deleted in the media select frame. * * @since 4.9.0 - * @param {wp.media.models.Attachment} attachment - Attachment. + * @param {wp.media.models.Attachment} attachment Attachment. * @return {void} */ handleAttachmentDestroy: function handleAttachmentDestroy( attachment ) { diff --git a/src/js/_enqueues/wp/widgets/media-image.js b/src/js/_enqueues/wp/widgets/media-image.js index 7d15eff1f8cf1..ff0b996d275ad 100644 --- a/src/js/_enqueues/wp/widgets/media-image.js +++ b/src/js/_enqueues/wp/widgets/media-image.js @@ -31,7 +31,7 @@ /** * View events. * - * @type {object} + * @type {Object} */ events: _.extend( {}, component.MediaWidgetControl.prototype.events, { 'click .media-widget-preview.populated': 'editMedia' @@ -137,7 +137,7 @@ * * Prevent the image_title attribute from being initially set when adding an image from the media library. * - * @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame. + * @param {wp.media.view.MediaFrame.Select} mediaFrame Select frame. * @return {Object} Props. */ getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) { diff --git a/src/js/_enqueues/wp/widgets/media-video.js b/src/js/_enqueues/wp/widgets/media-video.js index 56a8ff1f3d5a4..180797f0ae291 100644 --- a/src/js/_enqueues/wp/widgets/media-video.js +++ b/src/js/_enqueues/wp/widgets/media-video.js @@ -87,7 +87,7 @@ /** * Map model props to media frame props. * - * @param {Object} modelProps - Model props. + * @param {Object} modelProps Model props. * @return {Object} Media frame props. */ mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { diff --git a/src/js/_enqueues/wp/widgets/media.js b/src/js/_enqueues/wp/widgets/media.js index d67e71fc664ee..ce366361d5862 100644 --- a/src/js/_enqueues/wp/widgets/media.js +++ b/src/js/_enqueues/wp/widgets/media.js @@ -7,6 +7,8 @@ /** * @namespace wp.mediaWidgets * @memberOf wp + * + * @param {JQueryStatic} $ The jQuery object. */ wp.mediaWidgets = ( function( $ ) { 'use strict'; @@ -43,7 +45,7 @@ wp.mediaWidgets = ( function( $ ) { * @constructs wp.mediaWidgets.PersistentDisplaySettingsLibrary * @augments wp.media.controller.Library * - * @param {Object} options - Options. + * @param {Object} options Options. * * @return {void} */ @@ -55,7 +57,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Sync changes to the current display settings back into the current customized. * - * @param {Backbone.Model} displaySettings - Modified display settings. + * @param {Backbone.Model} displaySettings Modified display settings. * @return {void} */ handleDisplaySettingChange: function handleDisplaySettingChange( displaySettings ) { @@ -70,7 +72,7 @@ wp.mediaWidgets = ( function( $ ) { * will sync back into the model storing the session's customized display * settings. * - * @param {Backbone.Model} model - Display settings model. + * @param {Backbone.Model} model Display settings model. * @return {Backbone.Model} Display settings model. */ display: function getDisplaySettingsModel( model ) { @@ -100,7 +102,7 @@ wp.mediaWidgets = ( function( $ ) { * * @since 4.9.0 * - * @param {Object} options - Options. + * @param {Object} options Options. * @return {void} */ initialize: function( options ) { @@ -135,7 +137,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Set the disabled state on the Add to Widget button. * - * @param {boolean} disabled - Disabled. + * @param {boolean} disabled Disabled. * @return {void} */ setAddToWidgetButtonDisabled: function setAddToWidgetButtonDisabled( disabled ) { @@ -145,7 +147,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Set or clear an error notice. * - * @param {string} notice - Notice. + * @param {string} notice Notice. * @return {void} */ setErrorNotice: function setErrorNotice( notice ) { @@ -356,7 +358,7 @@ wp.mediaWidgets = ( function( $ ) { * * Forked override of {wp.media.view.MediaFrame.Post#mainInsertToolbar()} to override text. * - * @param {wp.Backbone.View} view - Toolbar view. + * @param {wp.Backbone.View} view Toolbar view. * @this {wp.media.controller.Library} * @return {void} */ @@ -373,7 +375,7 @@ wp.mediaWidgets = ( function( $ ) { * * @ignore * - * @fires wp.media.controller.State#insert() + * @fires wp.media.controller.State#insert * @return {void} */ click: function onClick() { @@ -391,7 +393,7 @@ wp.mediaWidgets = ( function( $ ) { * * Forked override of {wp.media.view.MediaFrame.Post#mainEmbedToolbar()} to override text. * - * @param {wp.Backbone.View} toolbar - Toolbar view. + * @param {wp.Backbone.View} toolbar Toolbar view. * @this {wp.media.controller.Library} * @return {void} */ @@ -484,10 +486,10 @@ wp.mediaWidgets = ( function( $ ) { * @augments Backbone.View * @abstract * - * @param {Object} options - Options. - * @param {Backbone.Model} options.model - Model. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. + * @param {Object} options Options. + * @param {Backbone.Model} options.model Model. + * @param {jQuery} options.el Control field container element. + * @param {jQuery} options.syncContainer Container element where fields are synced for the server. * * @return {void} */ @@ -719,7 +721,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Handle click on link to Media Library to open modal, such as the link that appears when in the missing attachment error notice. * - * @param {jQuery.Event} event - Event. + * @param {jQuery.Event} event Event. * @return {void} */ handleMediaLibraryLinkClick: function handleMediaLibraryLinkClick( event ) { @@ -817,7 +819,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Get the instance props from the media selection frame. * - * @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame. + * @param {wp.media.view.MediaFrame.Select} mediaFrame Select frame. * @return {Object} Props. */ getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) { @@ -866,7 +868,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Map media frame props to model props. * - * @param {Object} mediaFrameProps - Media frame props. + * @param {Object} mediaFrameProps Media frame props. * @return {Object} Model props. */ mapMediaToModelProps: function mapMediaToModelProps( mediaFrameProps ) { @@ -917,7 +919,7 @@ wp.mediaWidgets = ( function( $ ) { /** * Map model props to media frame props. * - * @param {Object} modelProps - Model props. + * @param {Object} modelProps Model props. * @return {Object} Media frame props. */ mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { @@ -1026,9 +1028,9 @@ wp.mediaWidgets = ( function( $ ) { * cast the attribute values from the hidden inputs' string values into * the appropriate data types (integers or booleans). * - * @param {string|Object} key - Attribute name or attribute pairs. - * @param {mixed|Object} [val] - Attribute value or options object. - * @param {Object} [options] - Options when attribute name and value are passed separately. + * @param {string|Object} key Attribute name or attribute pairs. + * @param {mixed|Object} [val] Attribute value or options object. + * @param {Object} [options] Options when attribute name and value are passed separately. * @return {wp.mediaWidgets.MediaWidgetModel} This model. */ set: function set( key, val, options ) { @@ -1117,8 +1119,8 @@ wp.mediaWidgets = ( function( $ ) { * * @memberOf wp.mediaWidgets * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * * @return {void} */ @@ -1254,8 +1256,8 @@ wp.mediaWidgets = ( function( $ ) { * * @memberOf wp.mediaWidgets * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * * @return {void} */ diff --git a/src/js/_enqueues/wp/widgets/text.js b/src/js/_enqueues/wp/widgets/text.js index 48d72475eebe3..4b7af2e0d4a80 100644 --- a/src/js/_enqueues/wp/widgets/text.js +++ b/src/js/_enqueues/wp/widgets/text.js @@ -7,6 +7,8 @@ /** * @namespace wp.textWidgets + * + * @param {JQueryStatic} $ The jQuery object. */ wp.textWidgets = ( function( $ ) { 'use strict'; @@ -32,9 +34,9 @@ wp.textWidgets = ( function( $ ) { * @augments Backbone.View * @abstract * - * @param {Object} options - Options. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. + * @param {Object} options Options. + * @param {jQuery} options.el Control field container element. + * @param {jQuery} options.syncContainer Container element where fields are synced for the server. * * @return {void} */ @@ -374,8 +376,8 @@ wp.textWidgets = ( function( $ ) { * * @memberOf wp.textWidgets * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * * @return {void} */ @@ -482,8 +484,8 @@ wp.textWidgets = ( function( $ ) { * * @memberOf wp.textWidgets * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. + * @param {jQuery.Event} event Event. + * @param {jQuery} widgetContainer Widget container element. * @return {void} */ component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) { diff --git a/src/js/_enqueues/wp/wp-tooltip.js b/src/js/_enqueues/wp/wp-tooltip.js index 70fe2bfe7c1b2..79c56323fb81b 100644 --- a/src/js/_enqueues/wp/wp-tooltip.js +++ b/src/js/_enqueues/wp/wp-tooltip.js @@ -8,19 +8,29 @@ */ (() => { - const popovers = /** @type {NodeListOf} */ ( document.querySelectorAll( '.wp-is-tooltip' ) ); + const supportsPopover = /** @type {boolean} */ ( Object.prototype.hasOwnProperty.call( HTMLElement.prototype, 'popover' ) ); + let hidePopover = false; + if ( ! supportsPopover ) { + hidePopover = true; + } - /** @type {ReturnType} */ - let openTimeout; + const popovers = /** @type {NodeListOf} */ ( document.querySelectorAll( '.wp-is-tooltip' ) ); popovers.forEach( function( popover ) { const trigger = /** @type {HTMLButtonElement|HTMLAnchorElement|null} */ ( popover.querySelector( '.wp-tooltip__toggle' ) ); const panel = /** @type {HTMLSpanElement|null} */ ( popover.querySelector( 'span.wp-tooltip__bubble' ) ); + if ( hidePopover && panel ) { + panel.classList.add( 'hidden' ); + return; + } if ( ! trigger || ! panel ) { return; } + /** @type {ReturnType} */ + let openTimeout; + // Show Tooltip Function (with delay to prevent flickering). const showTooltip = () => { clearTimeout( openTimeout ); @@ -48,3 +58,62 @@ trigger.addEventListener( 'blur', hideTooltip ); }); })(); + +/** + * Add focus and hover support for the toggle tip's hint in `wp_get_toggletip()`. + * + * A toggle tip has no visible text label, so a hover/focus hint exposes the + * toggle button's accessible name to sighted users. The hint is suppressed while + * the toggle tip dialog itself is open, so the two never overlap. + * This script can be made obsolete when support is available for Interest Invokers. + */ +(() => { + + const toggletips = /** @type {NodeListOf} */ ( document.querySelectorAll( '.wp-is-toggletip' ) ); + + /** @type {ReturnType} */ + let openTimeout; + + toggletips.forEach( function( toggletip ) { + const trigger = /** @type {HTMLButtonElement|null} */ ( toggletip.querySelector( 'button.wp-tooltip__toggle' ) ); + const hint = /** @type {HTMLSpanElement|null} */ ( toggletip.querySelector( '.wp-tooltip__hint' ) ); + const dialog = /** @type {HTMLDialogElement|null} */ ( toggletip.querySelector( 'dialog.wp-tooltip__bubble' ) ); + + if ( ! trigger || ! hint ) { + return; + } + + // Show Hint Function (with delay to prevent flickering). + const showHint = () => { + clearTimeout( openTimeout ); + openTimeout = setTimeout( () => { + // Don't show the hint over an open toggle tip dialog. + if ( dialog && dialog.matches( ':popover-open' ) ) { + return; + } + // Only show if it's not already open. + if ( ! hint.matches( ':popover-open' ) ) { + // pass the triggering element so implicit position anchors work. + hint.showPopover( { source: trigger } ); + } + }, 300 ); + }; + // Hide Hint Function. + const hideHint = () => { + clearTimeout( openTimeout ); + if ( hint.matches( ':popover-open' ) ) { + hint.hidePopover(); + } + }; + + // Bind Hover and Focus Events. + trigger.addEventListener( 'mouseenter', showHint ); + trigger.addEventListener( 'focus', showHint ); + + trigger.addEventListener( 'mouseleave', hideHint ); + trigger.addEventListener( 'blur', hideHint ); + + // Hide the hint as soon as the toggle tip is opened. + trigger.addEventListener( 'click', hideHint ); + }); +})(); diff --git a/src/js/media/controllers/collection-add.js b/src/js/media/controllers/collection-add.js index 1c0a8067c9d24..bb6ab9c4c508b 100644 --- a/src/js/media/controllers/collection-add.js +++ b/src/js/media/controllers/collection-add.js @@ -14,7 +14,7 @@ var Selection = wp.media.model.Selection, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} [attributes.id=library] Unique identifier. * @param {string} attributes.title Title for the state. Displays in the frame's title region. * @param {boolean|string} [attributes.multiple=add] Whether multi-select is enabled. Accepts 'add' or true. @@ -33,7 +33,7 @@ var Selection = wp.media.model.Selection, * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. - * @param {int} [attributes.priority=100] The priority for the state link in the media menu. + * @param {number} [attributes.priority=100] The priority for the state link in the media menu. * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. * Defaults to false because for this state, because the library of the Edit Gallery state is the selection. * @param {string} attributes.type The collection's media type. (e.g. 'video'). @@ -51,6 +51,8 @@ CollectionAdd = Library.extend(/** @lends wp.media.controller.CollectionAdd.prot }, Library.prototype.defaults ), /** + * Initializes the CollectionAdd controller. + * * @since 3.9.0 */ initialize: function() { @@ -72,6 +74,8 @@ CollectionAdd = Library.extend(/** @lends wp.media.controller.CollectionAdd.prot }, /** + * Activates the CollectionAdd controller. + * * @since 3.9.0 */ activate: function() { diff --git a/src/js/media/controllers/collection-edit.js b/src/js/media/controllers/collection-edit.js index 1c4478f258512..a61b470007091 100644 --- a/src/js/media/controllers/collection-edit.js +++ b/src/js/media/controllers/collection-edit.js @@ -16,7 +16,7 @@ var Library = wp.media.controller.Library, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} attributes.title Title for the state. Displays in the media menu and the frame's title region. * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to edit. * If one is not supplied, an empty media.model.Selection collection is created. @@ -29,9 +29,9 @@ var Library = wp.media.controller.Library, * @param {boolean} [attributes.describe=true] Whether to offer UI to describe the attachments - e.g. captioning images in a gallery. * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable. * @param {boolean} [attributes.dragInfoText] Instructional text about the attachments being sortable. - * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. + * @param {number} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance. - * @param {int} [attributes.priority=60] The priority for the state link in the media menu. + * @param {number} [attributes.priority=60] The priority for the state link in the media menu. * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. * Defaults to false for this state, because the library passed in *is* the selection. * @param {view} [attributes.SettingsView] The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox). @@ -57,6 +57,8 @@ CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.pr }, /** + * Initializes the CollectionEdit controller. + * * @since 3.9.0 */ initialize: function() { @@ -81,6 +83,8 @@ CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.pr }, /** + * Activates the CollectionEdit controller. + * * @since 3.9.0 */ activate: function() { @@ -98,6 +102,8 @@ CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.pr }, /** + * Deactivates the CollectionEdit controller. + * * @since 3.9.0 */ deactivate: function() { @@ -117,7 +123,7 @@ CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.pr * * @since 3.9.0 * - * @param {wp.media.view.attachmentsBrowser} The attachments browser view. + * @param {wp.media.view.attachmentsBrowser} attachmentsBrowserView The attachments browser view. */ renderSettings: function( attachmentsBrowserView ) { var library = this.get('library'), diff --git a/src/js/media/controllers/cropper.js b/src/js/media/controllers/cropper.js index 2685f743ea8c7..0921839224eb0 100644 --- a/src/js/media/controllers/cropper.js +++ b/src/js/media/controllers/cropper.js @@ -170,6 +170,7 @@ Cropper = wp.media.controller.State.extend(/** @lends wp.media.controller.Croppe * * @since 4.2.0 * + * @param {wp.media.model.Attachment} attachment The image attachment. * @return {$.promise} A jQuery promise with the custom header crop details. */ doCrop: function( attachment ) { diff --git a/src/js/media/controllers/edit-image.js b/src/js/media/controllers/edit-image.js index cdc29487df0fd..828cec6aaaa22 100644 --- a/src/js/media/controllers/edit-image.js +++ b/src/js/media/controllers/edit-image.js @@ -12,7 +12,7 @@ var l10n = wp.media.view.l10n, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} attributes The attributes hash passed to the state. + * @param {Object} attributes The attributes hash passed to the state. * @param {wp.media.model.Attachment} attributes.model The attachment. * @param {string} [attributes.id=edit-image] Unique identifier. * @param {string} [attributes.title=Edit Image] Title for the state. Displays in the media menu and the frame's title region. diff --git a/src/js/media/controllers/embed.js b/src/js/media/controllers/embed.js index d6614ed24d8dc..e485260cc5fe3 100644 --- a/src/js/media/controllers/embed.js +++ b/src/js/media/controllers/embed.js @@ -13,17 +13,17 @@ var l10n = wp.media.view.l10n, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} attributes The attributes hash passed to the state. + * @param {Object} attributes The attributes hash passed to the state. * @param {string} [attributes.id=embed] Unique identifier. * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region. * @param {string} [attributes.content=embed] Initial mode for the content region. * @param {string} [attributes.menu=default] Initial mode for the menu region. * @param {string} [attributes.toolbar=main-embed] Initial mode for the toolbar region. * @param {string} [attributes.menu=false] Initial mode for the menu region. - * @param {int} [attributes.priority=120] The priority for the state link in the media menu. + * @param {number} [attributes.priority=120] The priority for the state link in the media menu. * @param {string} [attributes.type=link] The type of embed. Currently only link is supported. * @param {string} [attributes.url] The embed URL. - * @param {object} [attributes.metadata={}] Properties of the embed, which will override attributes.url if set. + * @param {Object} [attributes.metadata={}] Properties of the embed, which will override attributes.url if set. */ Embed = wp.media.controller.State.extend(/** @lends wp.media.controller.Embed.prototype */{ defaults: { @@ -89,7 +89,7 @@ Embed = wp.media.controller.State.extend(/** @lends wp.media.controller.Embed.pr /** * Try scanning the embed as an image to discover its dimensions. * - * @param {Object} attributes + * @param {Object} attributes The attributes for the embed scan. */ scanImage: function( attributes ) { var frame = this.frame, diff --git a/src/js/media/controllers/featured-image.js b/src/js/media/controllers/featured-image.js index 0f87ff659c42c..74b739a72522b 100644 --- a/src/js/media/controllers/featured-image.js +++ b/src/js/media/controllers/featured-image.js @@ -15,7 +15,7 @@ var Attachment = wp.media.model.Attachment, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} [attributes.id=featured-image] Unique identifier. * @param {string} [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region. * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. @@ -26,7 +26,7 @@ var Attachment = wp.media.model.Attachment, * @param {string} [attributes.menu=default] Initial mode for the menu region. * @param {string} [attributes.router=browse] Initial mode for the router region. * @param {string} [attributes.toolbar=featured-image] Initial mode for the toolbar region. - * @param {int} [attributes.priority=60] The priority for the state link in the media menu. + * @param {number} [attributes.priority=60] The priority for the state link in the media menu. * @param {boolean} [attributes.searchable=true] Whether the library is searchable. * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown. * Accepts 'all', 'uploaded', or 'unattached'. @@ -48,6 +48,8 @@ FeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prot }, Library.prototype.defaults ), /** + * Initializes the FeaturedImage controller. + * * @since 3.5.0 */ initialize: function() { @@ -84,6 +86,8 @@ FeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prot }, /** + * Activates the FeaturedImage controller. + * * @since 3.5.0 */ activate: function() { @@ -93,6 +97,8 @@ FeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prot }, /** + * Deactivates the FeaturedImage controller. + * * @since 3.5.0 */ deactivate: function() { @@ -102,6 +108,8 @@ FeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prot }, /** + * Updates the selection to match the current featured image. + * * @since 3.5.0 */ updateSelection: function() { diff --git a/src/js/media/controllers/image-details.js b/src/js/media/controllers/image-details.js index 2d4689e5a3c65..e2bd41f47da0e 100644 --- a/src/js/media/controllers/image-details.js +++ b/src/js/media/controllers/image-details.js @@ -15,7 +15,7 @@ var State = wp.media.controller.State, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} [attributes.id=image-details] Unique identifier. * @param {string} [attributes.title=Image Details] Title for the state. Displays in the frame's title region. * @param {wp.media.model.Attachment} attributes.image The image's model. @@ -24,7 +24,7 @@ var State = wp.media.controller.State, * @param {string|false} [attributes.router=false] Initial mode for the router region. * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region. * @param {boolean} [attributes.editing=false] Unused. - * @param {int} [attributes.priority=60] Unused. + * @param {number} [attributes.priority=60] Unused. * * @todo This state inherits some defaults from media.controller.Library.prototype.defaults, * however this may not do anything. @@ -42,9 +42,11 @@ ImageDetails = State.extend(/** @lends wp.media.controller.ImageDetails.prototyp }, Library.prototype.defaults ), /** + * Initializes the ImageDetails controller. + * * @since 3.9.0 * - * @param options Attributes + * @param {Object} options Attributes. */ initialize: function( options ) { this.image = options.image; @@ -52,6 +54,8 @@ ImageDetails = State.extend(/** @lends wp.media.controller.ImageDetails.prototyp }, /** + * Activates the ImageDetails controller. + * * @since 3.9.0 */ activate: function() { diff --git a/src/js/media/controllers/library.js b/src/js/media/controllers/library.js index db77c8dae8241..4d41d5ed0e353 100644 --- a/src/js/media/controllers/library.js +++ b/src/js/media/controllers/library.js @@ -15,7 +15,7 @@ var l10n = wp.media.view.l10n, * @augments Backbone.Model * @mixes media.selectionSync * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} [attributes.id=library] Unique identifier. * @param {string} [attributes.title=Media library] Title for the state. Displays in the media menu and the frame's title region. * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. @@ -58,6 +58,8 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** + * Initializes the Library controller. + * * If a library isn't provided, query all media items. * If a selection instance isn't provided, create one. * @@ -89,6 +91,8 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** + * Activates the Library controller. + * * @since 3.5.0 */ activate: function() { @@ -105,6 +109,8 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** + * Deactivates the Library controller. + * * @since 3.5.0 */ deactivate: function() { @@ -120,7 +126,7 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Reset the library to its initial state. + * Resets the library to its initial state. * * @since 3.5.0 */ @@ -131,7 +137,7 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Reset the attachment display settings defaults to the site options. + * Resets the attachment display settings defaults to the site options. * * If site options don't define them, fall back to a persistent user setting. * @@ -148,12 +154,12 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Create a model to represent display settings (alignment, etc.) for an attachment. + * Creates a model to represent display settings (alignment, etc.) for an attachment. * * @since 3.5.0 * - * @param {wp.media.model.Attachment} attachment - * @return {Backbone.Model} + * @param {wp.media.model.Attachment} attachment The attachment for which to create display settings. + * @return {Backbone.Model} A model representing the display settings for the attachment. */ display: function( attachment ) { var displays = this._displays; @@ -165,12 +171,12 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Given an attachment, create attachment display settings properties. + * Given an attachment, creates attachment display settings properties. * * @since 3.6.0 * - * @param {wp.media.model.Attachment} attachment - * @return {Object} + * @param {wp.media.model.Attachment} attachment The attachment for which to get the default display settings. + * @return {Object} The default display settings for the attachment. */ defaultDisplaySettings: function( attachment ) { var settings = _.clone( this._defaultDisplaySettings ); @@ -186,12 +192,12 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Whether an attachment is image. + * Determines whether an attachment is an image. * * @since 4.4.1 * - * @param {wp.media.model.Attachment} attachment - * @return {boolean} + * @param {wp.media.model.Attachment} attachment The attachment to check. + * @return {boolean} True if the attachment is an image, false otherwise. */ isImageAttachment: function( attachment ) { // If uploading, we know the filename but not the mime type. @@ -203,12 +209,12 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Whether an attachment can be embedded (audio or video). + * Determines whether an attachment can be embedded (audio or video). * * @since 3.6.0 * - * @param {wp.media.model.Attachment} attachment - * @return {boolean} + * @param {wp.media.model.Attachment} attachment The attachment to check. + * @return {boolean} True if the attachment can be embedded, false otherwise. */ canEmbed: function( attachment ) { // If uploading, we know the filename but not the mime type. @@ -224,6 +230,8 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar /** + * Resets the content mode to the default. + * * If the state is active, no items are selected, and the current * content mode is not an option in the state's router (provided * the state has a router), reset the content mode to the default. @@ -254,7 +262,7 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar * * @since 3.5.0 * - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment that was uploaded. */ uploading: function( attachment ) { var content = this.frame.content; @@ -270,7 +278,7 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar }, /** - * Persist the mode of the content region as a user setting. + * Persists the mode of the content region as a user setting. * * @since 3.5.0 */ diff --git a/src/js/media/controllers/media-library.js b/src/js/media/controllers/media-library.js index 1f0fe744673ab..6d311af854aca 100644 --- a/src/js/media/controllers/media-library.js +++ b/src/js/media/controllers/media-library.js @@ -22,9 +22,11 @@ MediaLibrary = Library.extend(/** @lends wp.media.controller.MediaLibrary.protot }, Library.prototype.defaults ), /** + * Initializes the MediaLibrary controller. + * * @since 3.9.0 * - * @param options + * @param {Object} options Attributes. */ initialize: function( options ) { this.media = options.media; @@ -35,6 +37,8 @@ MediaLibrary = Library.extend(/** @lends wp.media.controller.MediaLibrary.protot }, /** + * Activates the MediaLibrary controller. + * * @since 3.9.0 */ activate: function() { diff --git a/src/js/media/controllers/region.js b/src/js/media/controllers/region.js index c211bc9c8de25..fee3aa32cfce3 100644 --- a/src/js/media/controllers/region.js +++ b/src/js/media/controllers/region.js @@ -33,7 +33,7 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * * @since 3.5.0 * - * @param {string} mode + * @param {string} mode The mode to activate on the region. * * @fires Region#activate * @fires Region#deactivate @@ -72,7 +72,7 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * * @since 3.5.0 * - * @param {string} mode + * @param {string} mode The mode to render on the region. * * @fires Region#create * @fires Region#render @@ -94,8 +94,8 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * Region view creation takes place in an event callback on the frame. * * @event wp.media.controller.Region#create - * @type {object} - * @property {object} view + * @type {Object} + * @property {Object} view The view object for the region. */ this.trigger( 'create', set ); view = set.view; @@ -106,7 +106,7 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * Region view creation takes place in an event callback on the frame. * * @event wp.media.controller.Region#render - * @type {object} + * @type {Object} */ this.trigger( 'render', view ); if ( view ) { @@ -120,7 +120,7 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * * @since 3.5.0 * - * @return {wp.media.View} + * @return {wp.media.View} Returns the region's view. */ get: function() { return this.view.views.first( this.selector ); @@ -131,8 +131,8 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * * @since 3.5.0 * - * @param {Array|Object} views - * @param {Object} [options={}] + * @param {Array|Object} views The views to set on the region. + * @param {Object} [options={}] Optional. Additional options for setting the views on the region. * @return {wp.Backbone.Subviews} Subviews is returned to allow chaining. */ set: function( views, options ) { @@ -147,7 +147,7 @@ _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ * * @since 3.5.0 * - * @param {string} event + * @param {string} event The event to trigger on the region. * @return {undefined|wp.media.controller.Region} Returns itself to allow chaining. */ trigger: function( event ) { diff --git a/src/js/media/controllers/replace-image.js b/src/js/media/controllers/replace-image.js index 46dce6d1bab86..297d0422d2a75 100644 --- a/src/js/media/controllers/replace-image.js +++ b/src/js/media/controllers/replace-image.js @@ -14,7 +14,7 @@ var Library = wp.media.controller.Library, * @augments wp.media.controller.State * @augments Backbone.Model * - * @param {object} [attributes] The attributes hash passed to the state. + * @param {Object} [attributes] The attributes hash passed to the state. * @param {string} [attributes.id=replace-image] Unique identifier. * @param {string} [attributes.title=Replace Image] Title for the state. Displays in the media menu and the frame's title region. * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. @@ -25,7 +25,7 @@ var Library = wp.media.controller.Library, * @param {string} [attributes.menu=default] Initial mode for the menu region. * @param {string} [attributes.router=browse] Initial mode for the router region. * @param {string} [attributes.toolbar=replace] Initial mode for the toolbar region. - * @param {int} [attributes.priority=60] The priority for the state link in the media menu. + * @param {number} [attributes.priority=60] The priority for the state link in the media menu. * @param {boolean} [attributes.searchable=true] Whether the library is searchable. * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown. * Accepts 'all', 'uploaded', or 'unattached'. @@ -48,9 +48,11 @@ ReplaceImage = Library.extend(/** @lends wp.media.controller.ReplaceImage.protot }, Library.prototype.defaults ), /** + * Initializes the ReplaceImage controller. + * * @since 3.9.0 * - * @param options + * @param {Object} options Attributes. */ initialize: function( options ) { var library, comparator; @@ -87,6 +89,8 @@ ReplaceImage = Library.extend(/** @lends wp.media.controller.ReplaceImage.protot }, /** + * Activates the ReplaceImage controller. + * * @since 3.9.0 */ activate: function() { @@ -96,6 +100,8 @@ ReplaceImage = Library.extend(/** @lends wp.media.controller.ReplaceImage.protot }, /** + * Deactivates the ReplaceImage controller. + * * @since 5.9.0 */ deactivate: function() { @@ -105,6 +111,8 @@ ReplaceImage = Library.extend(/** @lends wp.media.controller.ReplaceImage.protot }, /** + * Updates the selection to match the current image. + * * @since 3.9.0 */ updateSelection: function() { diff --git a/src/js/media/controllers/state-machine.js b/src/js/media/controllers/state-machine.js index 50ebb10e6c739..d7ebd815a2c52 100644 --- a/src/js/media/controllers/state-machine.js +++ b/src/js/media/controllers/state-machine.js @@ -35,7 +35,7 @@ _.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller * * @since 3.5.0 * - * @param {string} id + * @param {string} id The ID of the state to fetch. If omitted, the active state is returned. * @return {wp.media.controller.State} Returns a State model from * the StateMachine collection. */ @@ -60,7 +60,7 @@ _.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller * * @since 3.5.0 * - * @param {string} id + * @param {string} id The ID of the state to set as active. * * @fires wp.media.controller.State#deactivate * @fires wp.media.controller.State#activate @@ -93,8 +93,8 @@ _.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller * * @since 3.5.0 * - * @return {wp.media.controller.State} Returns a State model from - * the StateMachine collection. + * @return {void|wp.media.controller.State} Returns a State model from + * the StateMachine collection. */ lastState: function() { if ( this._lastState ) { @@ -106,18 +106,24 @@ _.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller // Map all event binding and triggering on a StateMachine to its `states` collection. _.each([ 'on', 'off', 'trigger' ], function( method ) { /** + * Binds an event listener to events in the StateMachine's states collection. + * * @function on * @memberOf wp.media.controller.StateMachine * @instance * @return {wp.media.controller.StateMachine} Returns itself to allow chaining. */ /** + * Unbinds an event listener from the StateMachine's states collection. + * * @function off * @memberOf wp.media.controller.StateMachine * @instance * @return {wp.media.controller.StateMachine} Returns itself to allow chaining. */ /** + * Triggers an event on the StateMachine's states collection. + * * @function trigger * @memberOf wp.media.controller.StateMachine * @instance diff --git a/src/js/media/controllers/state.js b/src/js/media/controllers/state.js index bbc9b3826b2e7..1bacae9c0e734 100644 --- a/src/js/media/controllers/state.js +++ b/src/js/media/controllers/state.js @@ -6,11 +6,11 @@ * * A state has an event-driven lifecycle: * - * 'ready' triggers when a state is added to a state machine's collection. - * 'activate' triggers when a state is activated by a state machine. - * 'deactivate' triggers when a state is deactivated by a state machine. - * 'reset' is not triggered automatically. It should be invoked by the - * proper controller to reset the state to its default. + * 'ready' triggers when a state is added to a state machine's collection. + * 'activate' triggers when a state is activated by a state machine. + * 'deactivate' triggers when a state is deactivated by a state machine. + * 'reset' is not triggered automatically. It should be invoked by the + * proper controller to reset the state to its default. * * @memberOf wp.media.controller * @@ -71,6 +71,8 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype reset: function() {}, /** + * Ready event callback. + * * @since 3.5.0 * @access private */ @@ -79,14 +81,18 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Pre-activate event callback. + * * @since 3.5.0 * @access private - */ + */ _preActivate: function() { this.active = true; }, /** + * Post-activate event callback. + * * @since 3.5.0 * @access private */ @@ -106,6 +112,8 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Deactivate event callback. + * * @since 3.5.0 * @access private */ @@ -121,6 +129,9 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Renders the frame's title using the titleMode property. + * + * * @since 3.5.0 * @access private */ @@ -129,6 +140,9 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Renders the title in the media frame. + * + * @param {media.view.Title} view The title view. * @since 3.5.0 * @access private */ @@ -137,6 +151,8 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Renders and manages the router region. + * * @since 3.5.0 * @access private */ @@ -159,6 +175,8 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Renders and manages the menu region. + * * @since 3.5.0 * @access private */ @@ -188,6 +206,8 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** + * Updates the menu. + * * @since 3.5.0 * @access private */ @@ -205,7 +225,7 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype }, /** - * Create a view in the media menu for the state. + * Creates a view in the media menu for the state. * * @since 3.5.0 * @access private @@ -233,8 +253,13 @@ var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype } }); +/** + * Creates render methods for frame regions. + */ _.each(['toolbar','content'], function( region ) { /** + * Renders the region in the media frame. + * * @access private */ State.prototype[ '_' + region ] = function() { diff --git a/src/js/media/models/attachment.js b/src/js/media/models/attachment.js index 267624b7d6c48..6a911b147f372 100644 --- a/src/js/media/models/attachment.js +++ b/src/js/media/models/attachment.js @@ -14,11 +14,11 @@ Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp * Triggered when attachment details change * Overrides Backbone.Model.sync * - * @param {string} method - * @param {wp.media.model.Attachment} model - * @param {Object} [options={}] + * @param {string} method The method to be performed: 'read', 'update', or 'delete'. + * @param {wp.media.model.Attachment} model The attachment model being synced. + * @param {Object} [options={}] Optional. Additional options for the sync operation. * - * @return {Promise} + * @return {jQuery.Promise} A jQuery Promise that is resolved or rejected based on the success of the sync operation. */ sync: function( method, model, options ) { // If the attachment does not yet have an `id`, return an instantly @@ -113,12 +113,14 @@ Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp return resp; }, /** - * @param {Object} data The properties to be saved. + * Saves attachment details using the `save-attachment-compat` action. + * + * @param {Object} data The properties to be saved. * @param {Object} options Sync options. e.g. patch, wait, success, error. * - * @this Backbone.Model + * @this {Backbone.Model} * - * @return {Promise} + * @return {jQuery.Promise} A jQuery Promise that is resolved or rejected based on the success of the sync operation. */ saveCompat: function( data, options ) { var model = this; @@ -142,8 +144,8 @@ Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp * * @static * - * @param {Object} attrs - * @return {wp.media.model.Attachment} + * @param {Object} attrs The attributes for the new attachment model. + * @return {wp.media.model.Attachment} The newly created attachment model. */ create: function( attrs ) { var Attachments = wp.media.model.Attachments; @@ -156,8 +158,8 @@ Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp * it returns the specified attachment. * * @static - * @param {string} id A string used to identify a model. - * @param {Backbone.Model|undefined} attachment + * @param {string} id A string used to identify a model. + * @param {Backbone.Model|undefined} attachment The attachment model to retrieve or create. * @return {wp.media.model.Attachment} */ get: _.memoize( function( id, attachment ) { diff --git a/src/js/media/models/attachments.js b/src/js/media/models/attachments.js index fb31ba09ab9d6..b84b782ca5fc7 100644 --- a/src/js/media/models/attachments.js +++ b/src/js/media/models/attachments.js @@ -12,14 +12,14 @@ * @class * @augments Backbone.Collection * - * @param {array} [models] Models to initialize with the collection. - * @param {object} [options] Options hash for the collection. - * @param {string} [options.props] Options hash for the initial query properties. - * @param {string} [options.props.order] Initial order (ASC or DESC) for the collection. - * @param {string} [options.props.orderby] Initial attribute key to order the collection by. - * @param {string} [options.props.query] Whether the collection is linked to an attachments query. - * @param {string} [options.observe] - * @param {string} [options.filters] + * @param {wp.media.model.Attachment[]} [models] Models to initialize with the collection. + * @param {Object} [options] Options hash for the collection. + * @param {string} [options.props] Options hash for the initial query properties. + * @param {string} [options.props.order] Initial order (ASC or DESC) for the collection. + * @param {string} [options.props.orderby] Initial attribute key to order the collection by. + * @param {string} [options.props.query] Whether the collection is linked to an attachments query. + * @param {string} [options.observe] An attachments collection to observe and mirror. + * @param {string} [options.filters] Filters to apply to the collection. * */ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachments.prototype */{ @@ -28,8 +28,10 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen */ model: wp.media.model.Attachment, /** - * @param {Array} [models=[]] Array of models used to populate the collection. - * @param {Object} [options={}] + * Initializes the Attachments collection. + * + * @param {Array} [models=[]] Optional. Array of models used to populate the collection. + * @param {Object} [options={}] Optional. Additional options for the collection. */ initialize: function( models, options ) { var normalizedOrder; @@ -65,7 +67,7 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** - * Sort the collection when the order attribute changes. + * Sorts the collection when the order attribute changes. * * @access private */ @@ -75,12 +77,12 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** - * Set the default comparator only when the `orderby` property is set. + * Sets the default comparator only when the `orderby` property is set. * * @access private * - * @param {Backbone.Model} model - * @param {string} orderby + * @param {Backbone.Model} model The model that triggered the change. + * @param {string} orderby The new orderby value. */ _changeOrderby: function( model, orderby ) { // If a different comparator is defined, bail. @@ -95,13 +97,12 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** - * If the `query` property is set to true, query the server using - * the `props` values, and sync the results to this collection. + * Queries the server using the `props` values and syncs the results to this collection if the `query` property is set to true. * * @access private * - * @param {Backbone.Model} model - * @param {boolean} query + * @param {Backbone.Model} model The model that triggered the change. + * @param {boolean} query The new query value. */ _changeQuery: function( model, query ) { if ( query ) { @@ -112,9 +113,11 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** + * Updates the collection when a property that has a filter is changed. + * * @access private * - * @param {Backbone.Model} model + * @param {Backbone.Model} model The model that triggered the change. */ _changeFilteredProps: function( model ) { // If this is a query, updating the collection will be handled by @@ -160,8 +163,8 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen /** * Checks whether an attachment is valid. * - * @param {wp.media.model.Attachment} attachment - * @return {boolean} + * @param {wp.media.model.Attachment} attachment The attachment to validate. + * @return {boolean} True if the attachment is valid, false otherwise. */ validator: function( attachment ) { @@ -173,10 +176,10 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen }, this ); }, /** - * Add or remove an attachment to the collection depending on its validity. + * Adds or removes an attachment to the collection depending on its validity. * - * @param {wp.media.model.Attachment} attachment - * @param {Object} options + * @param {wp.media.model.Attachment} attachment The attachment to validate and potentially add or remove. + * @param {Object} options Additional options for the operation. * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ validate: function( attachment, options ) { @@ -193,10 +196,10 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen }, /** - * Add or remove all attachments from another collection depending on each one's validity. + * Adds or removes all attachments from another collection depending on each one's validity. * - * @param {wp.media.model.Attachments} attachments - * @param {Object} [options={}] + * @param {wp.media.model.Attachments} attachments The attachments collection to validate against. + * @param {Object} [options={}] Additional options for the operation. * * @fires wp.media.model.Attachments#reset * @@ -215,10 +218,9 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return this; }, /** - * Start observing another attachments collection change events - * and replicate them on this collection. + * Starts observing another attachments collection change events and replicates them on this collection. * - * @param {wp.media.model.Attachments} The attachments collection to observe. + * @param {wp.media.model.Attachments} attachments The attachments collection to observe. * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ observe: function( attachments ) { @@ -231,9 +233,9 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return this; }, /** - * Stop replicating collection change events from another attachments collection. + * Stops replicating collection change events from another attachments collection. * - * @param {wp.media.model.Attachments} The attachments collection to stop observing. + * @param {wp.media.model.Attachments} attachments The attachments collection to stop observing. * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ unobserve: function( attachments ) { @@ -251,7 +253,7 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return this; }, /** - * Update total attachment count when items are added to a collection. + * Updates total attachment count when items are added to a collection. * * @access private * @@ -263,7 +265,7 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** - * Update total attachment count when items are added to a collection. + * Updates total attachment count when items are added to a collection. * * @access private * @@ -275,11 +277,13 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** + * Validates an attachment against the collection's rules. + * * @access private * - * @param {wp.media.model.Attachments} attachment - * @param {wp.media.model.Attachments} attachments - * @param {Object} options + * @param {wp.media.model.Attachments} attachment The attachment to validate. + * @param {wp.media.model.Attachments} attachments The attachments collection the attachment belongs to. + * @param {Object} options Additional options for the operation. * * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ @@ -293,20 +297,21 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return this.validate( attachment, options ); }, /** + * Validates all attachments in a collection against the collection's rules. + * * @access private * - * @param {wp.media.model.Attachments} attachments - * @param {Object} options + * @param {wp.media.model.Attachments} attachments The attachments collection to validate against. + * @param {Object} options Additional options for the operation. * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ _validateAllHandler: function( attachments, options ) { return this.validateAll( attachments, options ); }, /** - * Start mirroring another attachments collection, clearing out any models already - * in the collection. + * Starts mirroring another attachments collection, clearing out any models already in the collection. * - * @param {wp.media.model.Attachments} The attachments collection to mirror. + * @param {wp.media.model.Attachments} attachments The attachments collection to mirror. * @return {wp.media.model.Attachments} Returns itself to allow chaining. */ mirror: function( attachments ) { @@ -333,7 +338,7 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return this; }, /** - * Stop mirroring another attachments collection. + * Stops mirroring another attachments collection. */ unmirror: function() { if ( ! this.mirroring ) { @@ -344,14 +349,14 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen delete this.mirroring; }, /** - * Retrieve more attachments from the server for the collection. + * Retrieves more attachments from the server for the collection. * * Only works if the collection is mirroring a Query Attachments collection, * and forwards to its `more` method. This collection class doesn't have * server persistence by itself. * - * @param {Object} options - * @return {Promise} + * @param {Object} options Additional options for the operation. + * @return {Promise} A promise that resolves when the request is complete. */ more: function( options ) { var deferred = jQuery.Deferred(), @@ -379,14 +384,13 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return deferred.promise(); }, /** - * Whether there are more attachments that haven't been sync'd from the server - * that match the collection's query. + * Checks whether there are more attachments that haven't been sync'd from the server that match the collection's query. * * Only works if the collection is mirroring a Query Attachments collection, * and forwards to its `hasMore` method. This collection class doesn't have * server persistence by itself. * - * @return {boolean} + * @return {boolean} True if there are more attachments to retrieve, false otherwise. */ hasMore: function() { return this.mirroring ? this.mirroring.hasMore() : false; @@ -420,7 +424,7 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen * the collection items. * * @param {Object|Array} response The raw response Object/Array. - * @param {Object} xhr + * @param {Object} xhr The XMLHttpRequest object. * @return {Array} The array of model attributes to be added to the collection */ parse: function( response, xhr ) { @@ -449,10 +453,9 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen }, /** - * If the collection is a query, create and mirror an Attachments Query collection. + * Creates and mirrors an Attachments Query collection if the collection is a query. * * @access private - * @param {Boolean} refresh Deprecated, refresh parameter no longer used. */ _requery: function() { var props; @@ -462,10 +465,9 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen } }, /** - * If this collection is sorted by `menuOrder`, recalculates and saves - * the menu order to the database. + * Recalculates and saves the menu order to the database if this collection is sorted by `menuOrder`. * - * @return {undefined|Promise} + * @return {undefined|Promise} Returns a promise if the menu order is saved, otherwise undefined. */ saveMenuOrder: function() { if ( 'menuOrder' !== this.props.get('orderby') ) { @@ -503,9 +505,9 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen * Used as the default comparator for instances of wp.media.model.Attachments * and its subclasses. @see wp.media.model.Attachments._changeOrderby(). * - * @param {Backbone.Model} a - * @param {Backbone.Model} b - * @param {Object} options + * @param {Backbone.Model} a The first attachment model to compare. + * @param {Backbone.Model} b The second attachment model to compare. + * @param {Object} options Additional options for the comparison. * @return {number} -1 if the first model should come before the second, * 0 if they are of the same rank and * 1 if the first model should come after. @@ -534,15 +536,17 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen /** @namespace wp.media.model.Attachments.filters */ filters: { /** + * Filters attachments based on a search query. + * * @static * Note that this client-side searching is *not* equivalent * to our server-side searching. * - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment to filter based on the search query. * - * @this wp.media.model.Attachments + * @this {wp.media.model.Attachments} * - * @return {Boolean} + * @return {boolean} True if the attachment matches the search filter, false otherwise. */ search: function( attachment ) { if ( ! this.props.get('search') ) { @@ -555,12 +559,14 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen }, this ); }, /** + * Filters attachments based on their type. + * * @static - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment to filter based on its type. * - * @this wp.media.model.Attachments + * @this {wp.media.model.Attachments} * - * @return {boolean} + * @return {boolean} True if the attachment matches the type filter, false otherwise. */ type: function( attachment ) { var type = this.props.get('type'), atts = attachment.toJSON(), mime, found; @@ -582,12 +588,14 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return found; }, /** + * Filters attachments based on their uploadedTo property. + * * @static - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment to filter based on its uploadedTo property. * - * @this wp.media.model.Attachments + * @this {wp.media.model.Attachments} * - * @return {boolean} + * @return {boolean} True if the attachment matches the uploadedTo filter, false otherwise. */ uploadedTo: function( attachment ) { var uploadedTo = this.props.get('uploadedTo'); @@ -598,12 +606,14 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen return uploadedTo === attachment.get('uploadedTo'); }, /** + * Filters attachments based on their status property. + * * @static - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment to filter based on its status property. * - * @this wp.media.model.Attachments + * @this {wp.media.model.Attachments} * - * @return {boolean} + * @return {boolean} True if the attachment matches the status filter, false otherwise. */ status: function( attachment ) { var status = this.props.get('status'); diff --git a/src/js/media/models/post-image.js b/src/js/media/models/post-image.js index 1642f42e2a52b..d5972e9be41f2 100644 --- a/src/js/media/models/post-image.js +++ b/src/js/media/models/post-image.js @@ -10,8 +10,8 @@ * @class * @augments Backbone.Model * - * @param {int} [attributes] Initial model attributes. - * @param {int} [attributes.attachment_id] ID of the attachment. + * @param {number} [attributes] Initial model attributes. + * @param {number} [attributes.attachment_id] ID of the attachment. **/ var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{ diff --git a/src/js/media/models/post-media.js b/src/js/media/models/post-media.js index fd642a724f6e1..56d76bbd24d0e 100644 --- a/src/js/media/models/post-media.js +++ b/src/js/media/models/post-media.js @@ -2,7 +2,7 @@ * wp.media.model.PostMedia * * Shared model class for audio and video. Updates the model after - * "Add Audio|Video Source" and "Replace Audio|Video" states return + * "Add Audio|Video Source" and "Replace Audio|Video" states return * * @memberOf wp.media.model * diff --git a/src/js/media/models/query.js b/src/js/media/models/query.js index 3c47215c39833..0c4b634cb5ffd 100644 --- a/src/js/media/models/query.js +++ b/src/js/media/models/query.js @@ -7,7 +7,7 @@ var Attachments = wp.media.model.Attachments, * A collection of attachments that match the supplied query arguments. * * Note: Do NOT change this.args after the query has been initialized. - * Things will break. + * Things will break. * * @memberOf wp.media.model * @@ -15,15 +15,17 @@ var Attachments = wp.media.model.Attachments, * @augments wp.media.model.Attachments * @augments Backbone.Collection * - * @param {array} [models] Models to initialize with the collection. - * @param {object} [options] Options hash. - * @param {object} [options.args] Attachments query arguments. - * @param {object} [options.args.posts_per_page] + * @param {wp.media.model.Attachment[]} [models] Models to initialize with the collection. + * @param {Object} [options] Options hash. + * @param {Object} [options.args] Attachments query arguments. + * @param {Object} [options.args.posts_per_page] */ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ /** + * Initializes the Query collection. + * * @param {Array} [models=[]] Array of initial models to populate the collection. - * @param {Object} [options={}] + * @param {Object} [options={}] Additional options for initializing the query. */ initialize: function( models, options ) { var allowed; @@ -86,7 +88,7 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ * Whether there are more attachments that haven't been sync'd from the server * that match the collection's query. * - * @return {boolean} + * @return {boolean} True if there are more attachments to fetch, false otherwise. */ hasMore: function() { return this._hasMore; @@ -94,8 +96,8 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ /** * Fetch more attachments from the server for the collection. * - * @param {Object} [options={}] - * @return {Promise} + * @param {Object} [options={}] Additional options for fetching more attachments. + * @return {Promise} A promise that resolves when the fetch is complete. */ more: function( options ) { var query = this; @@ -122,10 +124,10 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ * Overrides Backbone.Collection.sync * Overrides wp.media.model.Attachments.sync * - * @param {string} method - * @param {Backbone.Model} model - * @param {Object} [options={}] - * @return {Promise} + * @param {string} method The sync method to be used (e.g., 'read', 'create', 'update', 'delete'). + * @param {Backbone.Model} model The model to be synced. + * @param {Object} [options={}] Additional options for syncing the query. + * @return {Promise} A promise that resolves when the sync is complete. */ sync: function( method, model, options ) { var args, fallback; @@ -210,33 +212,33 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ * Caches query objects and reuses where possible. * * @static - * @method + * @function * - * @param {object} [props] - * @param {Object} [props.order] - * @param {Object} [props.orderby] - * @param {Object} [props.include] - * @param {Object} [props.exclude] - * @param {Object} [props.s] - * @param {Object} [props.post_mime_type] - * @param {Object} [props.posts_per_page] - * @param {Object} [props.menu_order] - * @param {Object} [props.post_parent] - * @param {Object} [props.post_status] - * @param {Object} [props.author] - * @param {Object} [options] + * @param {Object} [props] The properties to initialize the query with. + * @param {Object} [props.order] The order in which to sort the query results. + * @param {Object} [props.orderby] The property by which to order the query results. + * @param {Object} [props.include] The IDs of attachments to include in the query. + * @param {Object} [props.exclude] The IDs of attachments to exclude from the query. + * @param {Object} [props.s] The search term to filter attachments by. + * @param {Object} [props.post_mime_type] The MIME type to filter attachments by. + * @param {Object} [props.posts_per_page] The number of attachments to retrieve per page. + * @param {Object} [props.menu_order] The menu order to filter attachments by. + * @param {Object} [props.post_parent] The parent post ID to filter attachments by. + * @param {Object} [props.post_status] The status to filter attachments by. + * @param {Object} [props.author] The author ID to filter attachments by. + * @param {Object} [options] Additional options for the query. * * @return {wp.media.model.Query} A new Attachments Query collection. */ get: (function(){ - /** - * @static - * @type Array - */ var queries = []; /** - * @return {Query} + * Creates and returns an Attachments Query collection given the properties. + * + * @param {Object} [props] The properties to initialize the query with. + * @param {Object} [options] Additional options for the query. + * @return {Query} A new Attachments Query collection. */ return function( props, options ) { var args = {}, diff --git a/src/js/media/models/selection.js b/src/js/media/models/selection.js index a2fc899c8bbec..a0e301b37a685 100644 --- a/src/js/media/models/selection.js +++ b/src/js/media/models/selection.js @@ -18,8 +18,8 @@ Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ * Binds `single` instead of using the context argument to ensure * it receives no parameters. * - * @param {Array} [models=[]] Array of models used to populate the collection. - * @param {Object} [options={}] + * @param {Array} [models=[]] Array of models used to populate the collection. + * @param {Object} [options={}] Additional options for the selection. */ initialize: function( models, options ) { /** @@ -35,9 +35,9 @@ Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ * If the workflow does not support multi-select, clear out the selection * before adding a new attachment to it. * - * @param {Array} models - * @param {Object} options - * @return {wp.media.model.Attachment[]} + * @param {Array} models The models to add to the selection. + * @param {Object} options Additional options for adding the models. + * @return {wp.media.model.Attachment[]} The added attachments. */ add: function( models, options ) { if ( ! this.multiple ) { @@ -52,12 +52,10 @@ Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ /** * Fired when toggling (clicking on) an attachment in the modal. * - * @param {undefined|boolean|wp.media.model.Attachment} model + * Fires `selection:single` and `selection:unsingle` events on the model and collection. * - * @fires wp.media.model.Selection#selection:single - * @fires wp.media.model.Selection#selection:unsingle - * - * @return {Backbone.Model} + * @param {undefined|boolean|wp.media.model.Attachment} model The model to set as the single selection, or a boolean to clear it. + * @return {Backbone.Model} The single model in the selection, or the last model as a fallback. */ single: function( model ) { var previous = this._single; diff --git a/src/js/media/utils/selection-sync.js b/src/js/media/utils/selection-sync.js index 73cbed002a823..f79bc4d6fe4db 100644 --- a/src/js/media/utils/selection-sync.js +++ b/src/js/media/utils/selection-sync.js @@ -12,6 +12,8 @@ */ var selectionSync = { /** + * Syncs the selection in this state with the master selection. + * * @since 3.5.0 */ syncSelection: function() { diff --git a/src/js/media/views/attachment-compat.js b/src/js/media/views/attachment-compat.js index d24de569639bd..f2ba1872d76c4 100644 --- a/src/js/media/views/attachment-compat.js +++ b/src/js/media/views/attachment-compat.js @@ -30,6 +30,8 @@ AttachmentCompat = View.extend(/** @lends wp.media.view.AttachmentCompat.prototy }, /** + * Disposes of the view and its children. + * * @return {wp.media.view.AttachmentCompat} Returns itself to allow chaining. */ dispose: function() { @@ -42,7 +44,9 @@ AttachmentCompat = View.extend(/** @lends wp.media.view.AttachmentCompat.prototy return View.prototype.dispose.apply( this, arguments ); }, /** - * @return {wp.media.view.AttachmentCompat} Returns itself to allow chaining. + * Renders the view. + * + * @return {void|wp.media.view.AttachmentCompat} Returns itself to allow chaining. */ render: function() { var compat = this.model.get('compat'); @@ -56,13 +60,17 @@ AttachmentCompat = View.extend(/** @lends wp.media.view.AttachmentCompat.prototy return this; }, /** - * @param {Object} event + * Prevents the default action of the event. + * + * @param {JQuery.Event} event The jQuery event object associated with the action. */ preventDefault: function( event ) { event.preventDefault(); }, /** - * @param {Object} event + * Saves the attachment compat data. + * + * @param {JQuery.Event} event The jQuery event object associated with the action. */ save: function( event ) { var data = {}; @@ -79,6 +87,9 @@ AttachmentCompat = View.extend(/** @lends wp.media.view.AttachmentCompat.prototy this.model.saveCompat( data ).always( _.bind( this.postSave, this ) ); }, + /** + * Triggers the `attachment:compat:ready` event on the controller after saving the compat data. + */ postSave: function() { this.controller.trigger( 'attachment:compat:ready', ['ready'] ); } diff --git a/src/js/media/views/attachment-filters.js b/src/js/media/views/attachment-filters.js index a228043c39a5e..7c4d4ff6dda8d 100644 --- a/src/js/media/views/attachment-filters.js +++ b/src/js/media/views/attachment-filters.js @@ -39,6 +39,8 @@ AttachmentFilters = wp.media.View.extend(/** @lends wp.media.view.AttachmentFilt }, /** + * Creates the filters for the view. + * * @abstract */ createFilters: function() { @@ -46,7 +48,7 @@ AttachmentFilters = wp.media.View.extend(/** @lends wp.media.view.AttachmentFilt }, /** - * When the selected filter changes, update the Attachment Query properties to match. + * Updates the Attachment Query properties to match when the selected filter changes. */ change: function() { var filter = this.filters[ this.el.value ]; @@ -55,6 +57,9 @@ AttachmentFilters = wp.media.View.extend(/** @lends wp.media.view.AttachmentFilt } }, + /** + * Selects the filter based on the Attachment Query properties. + */ select: function() { var model = this.model, value = 'all', diff --git a/src/js/media/views/attachment.js b/src/js/media/views/attachment.js index 5761c959ea481..b30503486d7d4 100644 --- a/src/js/media/views/attachment.js +++ b/src/js/media/views/attachment.js @@ -17,7 +17,17 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ className: 'attachment', template: wp.template('attachment'), - attributes: function() { + /** + * Compute the accessible name for an attachment tile. + * + * Factored out of attributes() so render() can refresh the label when a + * model finishes loading after the view was created. See #65852. + * + * @since 7.2.0 + * + * @return {string} Accessible name for the attachment. + */ + getAriaLabel: function() { var ariaLabel = this.model.get( 'title' ); if ( ! ariaLabel ) { @@ -28,10 +38,14 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ } } + return ariaLabel; + }, + + attributes: function() { return { 'tabIndex': 0, 'role': 'checkbox', - 'aria-label': ariaLabel, + 'aria-label': this.getAriaLabel(), 'aria-checked': false, 'data-id': this.model.get( 'id' ) }; @@ -79,6 +93,8 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ this.listenTo( this.controller.states, 'attachment:compat:waiting attachment:compat:ready', this.updateSave ); }, /** + * Update the view after the model has been saved. + * * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ dispose: function() { @@ -97,6 +113,8 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ return this; }, /** + * Renders the attachment view. + * * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ render: function() { @@ -157,6 +175,17 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ this.views.render(); + /* + * Backbone only evaluates attributes() when the element is created. + * When a tile is built for an id-only model that is still fetching, + * the aria-label is computed from empty data and never refreshes. + * Re-apply it here once the model has data. Skip subclasses that + * reset attributes (e.g. Attachment.Details). See #65852, #47458. + */ + if ( undefined !== _.result( this, 'attributes' )['aria-label'] ) { + this.$el.attr( 'aria-label', this.getAriaLabel() ); + } + return this; }, @@ -167,7 +196,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ }, /** - * @param {Object} event + * Toggles the selection state of the attachment. + * + * @param {JQuery.Event} event The jQuery event object that triggered the selection toggle. */ toggleSelectionHandler: function( event ) { var method; @@ -221,7 +252,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ this.controller.trigger( 'selection:toggle' ); }, /** - * @param {Object} options + * Toggles the selection state of the attachment. + * + * @param {Object} options The options for toggling the selection state of the attachment. */ toggleSelection: function( options ) { var collection = this.collection, @@ -301,7 +334,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ this[ this.selected() ? 'select' : 'deselect' ](); }, /** - * @return {unresolved|boolean} + * Checks if the model is selected in the selection. + * + * @return {void|boolean} True if the model is selected in the selection, false otherwise. */ selected: function() { var selection = this.options.selection; @@ -310,8 +345,10 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ } }, /** - * @param {Backbone.Model} model - * @param {Backbone.Collection} collection + * Selects the model in the selection. + * + * @param {Backbone.Model} model The model to select. + * @param {Backbone.Collection} collection The collection containing the model. */ select: function( model, collection ) { var selection = this.options.selection, @@ -339,8 +376,10 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ } }, /** - * @param {Backbone.Model} model - * @param {Backbone.Collection} collection + * Deselects the model in the selection. + * + * @param {Backbone.Model} model The model to deselect. + * @param {Backbone.Collection} collection The collection containing the model. */ deselect: function( model, collection ) { var selection = this.options.selection; @@ -357,8 +396,10 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ .find( '.check' ).attr( 'tabindex', '-1' ); }, /** - * @param {Backbone.Model} model - * @param {Backbone.Collection} collection + * Updates the view to reflect whether the model is the single model in the selection. + * + * @param {Backbone.Model} model The model to check for details. + * @param {Backbone.Collection} collection The collection containing the model. */ details: function( model, collection ) { var selection = this.options.selection, @@ -372,8 +413,10 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ this.$el.toggleClass( 'details', details === this.model ); }, /** - * @param {string} size - * @return {Object} + * Gets the image size object for the specified size. + * + * @param {string} size The desired image size. + * @return {Object} Returns an object containing the image size information. */ imageSize: function( size ) { var sizes = this.model.get('sizes'), matched = false; @@ -405,7 +448,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ }; }, /** - * @param {Object} event + * Update the model's setting with the value from the input. + * + * @param {JQuery.Event} event The jQuery event object that triggered the setting update. */ updateSetting: function( event ) { var $setting = $( event.target ).closest('[data-setting]'), @@ -456,7 +501,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ }); }, /** - * @param {string} status + * Updates the view's save status. + * + * @param {string} status The new save status to apply to the view. * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ updateSave: function( status ) { @@ -498,7 +545,9 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ } }, /** - * @param {Object} event + * Removes the model from the collection. + * + * @param {JQuery.Event} event The jQuery event object that triggered the removal from the library. */ removeFromLibrary: function( event ) { // Catch enter and space events. @@ -513,11 +562,11 @@ Attachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{ }, /** - * Add the model if it isn't in the selection, if it is in the selection, - * remove it. + * Adds the model if it isn't in the selection, if it is in the selection, + * removes it. * - * @param {[type]} event [description] - * @return {[type]} [description] + * @param {JQuery.Event} event The jQuery event object that triggered the selection toggle. + * @return {void} */ checkClickHandler: function ( event ) { var selection = this.options.selection; @@ -546,39 +595,47 @@ _.each({ album: '_syncAlbum' }, function( method, setting ) { /** + * Updates the DOM when the model's caption changes. + * * @function _syncCaption * @memberOf wp.media.view.Attachment * @instance * - * @param {Backbone.Model} model - * @param {string} value + * @param {Backbone.Model} model The model containing the caption. + * @param {string} value The new caption value. * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ /** + * Updates the DOM when the model's title changes. + * * @function _syncTitle * @memberOf wp.media.view.Attachment * @instance * - * @param {Backbone.Model} model - * @param {string} value + * @param {Backbone.Model} model The model containing the title. + * @param {string} value The new title value. * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ /** + * Updates the DOM when the model's artist changes. + * * @function _syncArtist * @memberOf wp.media.view.Attachment * @instance * - * @param {Backbone.Model} model - * @param {string} value + * @param {Backbone.Model} model The model containing the artist. + * @param {string} value The new artist value. * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ /** + * Updates the DOM when the model's album changes. + * * @function _syncAlbum * @memberOf wp.media.view.Attachment * @instance * - * @param {Backbone.Model} model - * @param {string} value + * @param {Backbone.Model} model The model containing the album. + * @param {string} value The new album value. * @return {wp.media.view.Attachment} Returns itself to allow chaining. */ Attachment.prototype[ method ] = function( model, value ) { diff --git a/src/js/media/views/attachment/details.js b/src/js/media/views/attachment/details.js index 8f450be793cfb..8317dbdfdada5 100644 --- a/src/js/media/views/attachment/details.js +++ b/src/js/media/views/attachment/details.js @@ -33,8 +33,6 @@ Details = Attachment.extend(/** @lends wp.media.view.Attachment.Details.prototyp * * @since 5.5.0 * - * @param {MouseEvent} event A click event. - * * @return {void} */ copyAttachmentDetailsURLClipboard: function() { @@ -248,10 +246,9 @@ Details = Attachment.extend(/** @lends wp.media.view.Attachment.Details.prototyp * * This event can be used to make sure to move the focus correctly. * - * @since 4.0.0 + * Fires `attachment:details:shift-tab` and `attachment:keydown:arrow` events on the controller. * - * @fires wp.media.controller.MediaLibrary#attachment:details:shift-tab - * @fires wp.media.controller.MediaLibrary#attachment:keydown:arrow + * @since 4.0.0 * * @param {KeyboardEvent} event A keyboard event. * diff --git a/src/js/media/views/attachments.js b/src/js/media/views/attachments.js index b2e91624cb159..7122463722323 100644 --- a/src/js/media/views/attachments.js +++ b/src/js/media/views/attachments.js @@ -8,6 +8,7 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{ className: 'attachments', attributes: { + role: 'group', tabIndex: -1 }, @@ -17,20 +18,16 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{ * The constructor binds events to the collection this view represents when * adding or removing attachments or resetting the entire collection. * + * Listens for `collection:add`, `collection:remove`, `collection:reset`, + * `controller:library:selection:add`, `scrollElement:scroll`, `this:ready`, + * and `controller:open` events. + * * @since 3.5.0 * * @constructs * @memberof wp.media.view * * @augments wp.media.View - * - * @listens collection:add - * @listens collection:remove - * @listens collection:reset - * @listens controller:library:selection:add - * @listens scrollElement:scroll - * @listens this:ready - * @listens controller:open */ initialize: function() { this.el.id = _.uniqueId('__attachments-view-'); @@ -120,9 +117,9 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{ * Adjusts the amount of columns accordingly. First removes any existing event * handlers to prevent duplicate listeners. * - * @since 4.0.0 + * Listens for the `window:resize` event. * - * @listens window:resize + * @since 4.0.0 * * @return {void} */ @@ -268,9 +265,9 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{ * Fails gracefully if jQuery sortable doesn't exist or isn't passed * in the options. * - * @since 3.5.0 + * Fires `collection:reset`. * - * @fires collection:reset + * @since 3.5.0 * * @return {void} */ @@ -365,7 +362,7 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{ * * @since 3.5.0 * - * @param {wp.media.model.Attachment} attachment + * @param {wp.media.model.Attachment} attachment The attachment model for which to create a view. * * @return {wp.media.View} The created view. */ diff --git a/src/js/media/views/attachments/browser.js b/src/js/media/views/attachments/browser.js index 82b7359eb832a..8d7d4dca51b76 100644 --- a/src/js/media/views/attachments/browser.js +++ b/src/js/media/views/attachments/browser.js @@ -17,7 +17,7 @@ var View = wp.media.View, * @augments wp.Backbone.View * @augments Backbone.View * - * @param {object} [options] The options hash passed to the view. + * @param {Object} [options] The options hash passed to the view. * @param {boolean|string} [options.filters=false] Which filters to show in the browser's toolbar. * Accepts 'uploaded' and 'all'. * @param {boolean} [options.search=true] Whether to show the search interface in the @@ -33,6 +33,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro tagName: 'div', className: 'attachments-browser', + /** + * Initializes the AttachmentsBrowser view. + */ initialize: function() { _.defaults( this.options, { filters: false, @@ -147,12 +150,19 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } }, 200 ), + /** + * Edits the selection in the modal. This is used when the user clicks the "Edit" button in the modal. + * + * @param {wp.media.view.Modal} modal The modal view. + */ editSelection: function( modal ) { // When editing a selection, move focus to the "Go to library" button. modal.$( '.media-button-backToLibrary' ).focus(); }, /** + * Disposes of the view and its children. + * * @return {wp.media.view.AttachmentsBrowser} Returns itself to allow chaining. */ dispose: function() { @@ -161,6 +171,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro return this; }, + /** + * Creates the toolbar view. + */ createToolbar: function() { var LibraryViewSwitcher, Filters, toolbarOptions, showFilterByType = -1 !== $.inArray( this.options.filters, [ 'uploaded', 'all' ] ); @@ -174,8 +187,8 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } /** - * @member {wp.media.view.Toolbar} - */ + * @member {wp.media.view.Toolbar} + */ this.toolbar = new wp.media.view.Toolbar( toolbarOptions ); this.views.add( this.toolbar ); @@ -410,6 +423,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } }, + /** + * Updates the content of the attachments browser. + */ updateContent: function() { var view = this, noItemsView; @@ -441,6 +457,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } }, + /** + * Creates the uploader view. + */ createUploader: function() { this.uploader = new wp.media.view.UploaderInline({ controller: this.controller, @@ -453,6 +472,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro this.views.add( this.uploader ); }, + /** + * Toggles the uploader view. + */ toggleUploader: function() { if ( this.uploader.$el.hasClass( 'hidden' ) ) { this.uploader.show(); @@ -478,6 +500,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro this.createAttachments(); }, + /** + * Creates the attachments view. + */ createAttachments: function() { this.attachments = new wp.media.view.Attachments({ controller: this.controller, @@ -661,6 +686,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro this.firstAddedMediaItem.focus(); }, + /** + * Creates the attachments heading view. + */ createAttachmentsHeading: function() { this.attachmentsHeading = new wp.media.view.Heading( { text: l10n.attachmentsList, @@ -670,6 +698,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro this.views.add( this.attachmentsHeading ); }, + /** + * Creates the sidebar view. + */ createSidebar: function() { var options = this.options, selection = options.selection, @@ -694,6 +725,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } }, + /** + * Creates the single attachment view. + */ createSingle: function() { var sidebar = this.sidebar, single = this.options.selection.single(); @@ -726,6 +760,9 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro } }, + /** + * Disposes of the single attachment view. + */ disposeSingle: function() { var sidebar = this.sidebar; sidebar.unset('details'); diff --git a/src/js/media/views/button-group.js b/src/js/media/views/button-group.js index bf5fe968bc187..e0fd09b0d957d 100644 --- a/src/js/media/views/button-group.js +++ b/src/js/media/views/button-group.js @@ -35,7 +35,9 @@ ButtonGroup = wp.media.View.extend(/** @lends wp.media.view.ButtonGroup.prototyp }, /** - * @return {wp.media.view.ButtonGroup} + * Renders the button group. + * + * @return {wp.media.view.ButtonGroup} The button group. */ render: function() { this.$el.html( $( _.pluck( this.buttons, 'el' ) ).detach() ); diff --git a/src/js/media/views/button.js b/src/js/media/views/button.js index 5b380d13d19f0..0c8316340c2bb 100644 --- a/src/js/media/views/button.js +++ b/src/js/media/views/button.js @@ -47,6 +47,8 @@ var Button = wp.media.View.extend(/** @lends wp.media.view.Button.prototype */{ this.listenTo( this.model, 'change', this.render ); }, /** + * Renders the button. + * * @return {wp.media.view.Button} Returns itself to allow chaining. */ render: function() { @@ -70,7 +72,9 @@ var Button = wp.media.View.extend(/** @lends wp.media.view.Button.prototype */{ return this; }, /** - * @param {Object} event + * Handles the click event. + * + * @param {JQuery.Event} event The jQuery event object for the click action. */ click: function( event ) { if ( '#' === this.attributes.href ) { diff --git a/src/js/media/views/embed.js b/src/js/media/views/embed.js index d7b38161a5396..286eb16f8378c 100644 --- a/src/js/media/views/embed.js +++ b/src/js/media/views/embed.js @@ -8,9 +8,12 @@ * @augments wp.Backbone.View * @augments Backbone.View */ -var Embed = wp.media.View.extend(/** @lends wp.media.view.Ember.prototype */{ +var Embed = wp.media.View.extend(/** @lends wp.media.view.Embed.prototype */{ className: 'media-embed', + /** + * Initializes the embed view. + */ initialize: function() { /** * @member {wp.media.view.EmbedUrl} @@ -27,7 +30,9 @@ var Embed = wp.media.View.extend(/** @lends wp.media.view.Ember.prototype */{ }, /** - * @param {Object} view + * Sets the settings for the embed view. + * + * @param {Object} view The view object to be set as the settings for the embed view. */ settings: function( view ) { if ( this._settings ) { @@ -37,6 +42,9 @@ var Embed = wp.media.View.extend(/** @lends wp.media.view.Ember.prototype */{ this.views.add( view ); }, + /** + * Refreshes the embed view based on the type of embed. + */ refresh: function() { var type = this.model.get('type'), constructor; @@ -56,6 +64,9 @@ var Embed = wp.media.View.extend(/** @lends wp.media.view.Ember.prototype */{ }) ); }, + /** + * Toggles the loading state of the embed view. + */ loading: function() { this.$el.toggleClass( 'embed-loading', this.model.get('loading') ); } diff --git a/src/js/media/views/embed/url.js b/src/js/media/views/embed/url.js index 701b2859518e1..42c620dda4530 100644 --- a/src/js/media/views/embed/url.js +++ b/src/js/media/views/embed/url.js @@ -39,7 +39,9 @@ EmbedUrl = View.extend(/** @lends wp.media.view.EmbedUrl.prototype */{ } }, /** - * @return {wp.media.view.EmbedUrl} Returns itself to allow chaining. + * Renders the view. + * + * @return {void|wp.media.view.EmbedUrl} Returns itself to allow chaining. */ render: function() { var $input = this.$input; diff --git a/src/js/media/views/focus-manager.js b/src/js/media/views/focus-manager.js index d79961b05b89c..749d283c7245d 100644 --- a/src/js/media/views/focus-manager.js +++ b/src/js/media/views/focus-manager.js @@ -31,14 +31,14 @@ var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.pr }, /** - * Determines which focus management mode to use. - * - * @since 5.3.0 - * - * @param {Object} event jQuery event object. - * - * @return {void} - */ + * Determines which focus management mode to use. + * + * @since 5.3.0 + * + * @param {Object} event jQuery event object. + * + * @return {void} + */ focusManagementMode: function( event ) { if ( this.mode === 'constrainTabbing' ) { this.constrainTabbing( event ); @@ -218,8 +218,6 @@ var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.pr * * @since 5.3.0 * - * @param {Object} event jQuery event object. - * * @return {void} */ setupAriaTabs: function() { diff --git a/src/js/media/views/frame.js b/src/js/media/views/frame.js index 8805bc7de45e2..2e2145ba969ca 100644 --- a/src/js/media/views/frame.js +++ b/src/js/media/views/frame.js @@ -88,6 +88,10 @@ var Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{ }, /** * Map activeMode collection events to the frame. + * + * @param {Backbone.Model} model The model that triggered the event. + * @param {Backbone.Collection} collection The collection to which the model belongs. + * @param {Object} options The options object associated with the event. */ triggerModeEvents: function( model, collection, options ) { var collectionEvent, @@ -113,8 +117,8 @@ var Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{ /** * Activate a mode on the frame. * - * @param string mode Mode ID. - * @return {this} Returns itself to allow chaining. + * @param {string} mode Mode ID. + * @return {void|this} Returns itself to allow chaining. */ activateMode: function( mode ) { // Bail if the mode is already active. @@ -130,7 +134,7 @@ var Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{ /** * Deactivate a mode on the frame. * - * @param string mode Mode ID. + * @param {string} mode Mode ID. * @return {this} Returns itself to allow chaining. */ deactivateMode: function( mode ) { @@ -140,11 +144,8 @@ var Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{ } this.activeModes.remove( this.activeModes.where( { id: mode } ) ); this.$el.removeClass( 'mode-' + mode ); - /** - * Frame mode deactivation event. - * - * @event wp.media.view.Frame#{mode}:deactivate - */ + + // Fires a `#{mode}:deactivate` event on the frame. this.trigger( mode + ':deactivate' ); return this; @@ -152,8 +153,8 @@ var Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{ /** * Check if a mode is enabled on the frame. * - * @param string mode Mode ID. - * @return bool + * @param {string} mode Mode ID. + * @return {boolean} True if the mode is active, false otherwise. */ isModeActive: function( mode ) { return Boolean( this.activeModes.where( { id: mode } ).length ); diff --git a/src/js/media/views/frame/edit-attachments.js b/src/js/media/views/frame/edit-attachments.js index f6bb4b8afa2cc..f55a2169b16cd 100644 --- a/src/js/media/views/frame/edit-attachments.js +++ b/src/js/media/views/frame/edit-attachments.js @@ -201,12 +201,13 @@ EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta }, toggleNav: function() { - this.$( '.left' ).prop( 'disabled', ! this.hasPrevious() ); - this.$( '.right' ).prop( 'disabled', ! this.hasNext() ); + this.$( '.left' ).attr( 'aria-disabled', ! this.hasPrevious() ); + this.$( '.right' ).attr( 'aria-disabled', ! this.hasNext() ); }, /** * Rerender the view. + * @param {wp.media.model.Attachment} model The attachment model to render. */ rerender: function( model ) { this.stopListening( this.model ); @@ -237,8 +238,6 @@ EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta model = this.library.at( this.getCurrentIndex() - 1 ); this.trigger( 'refresh', model ); - // Move focus to the Previous button. When there are no more items, to the Next button. - this.focusNavButton( this.hasPrevious() ? '.left' : '.right' ); this.announceMediaItemDebounced( model ); }, @@ -254,22 +253,9 @@ EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta model = this.library.at( this.getCurrentIndex() + 1 ); this.trigger( 'refresh', model ); - // Move focus to the Next button. When there are no more items, to the Previous button. - this.focusNavButton( this.hasNext() ? '.right' : '.left' ); this.announceMediaItemDebounced( model ); }, - /** - * Set focus to the navigation buttons depending on the browsing direction. - * - * @since 5.3.0 - * - * @param {string} which A CSS selector to target the button to focus. - */ - focusNavButton: function( which ) { - $( which ).trigger( 'focus' ); - }, - getCurrentIndex: function() { return this.library.indexOf( this.model ); }, @@ -285,6 +271,8 @@ EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta * Respond to the keyboard events: Alt + right arrow, Alt + left arrow, * except when focus is in a form field. Requires the Alt modifier key to * avoid interfering with screen reader navigation. + * + * @param {Event} event The keyboard event. */ keyEvent: function( event ) { if ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName || 'SELECT' === event.target.nodeName ) && ! event.target.disabled ) { diff --git a/src/js/media/views/frame/manage.js b/src/js/media/views/frame/manage.js index ea16637fdf7a5..e619a94f6d49c 100644 --- a/src/js/media/views/frame/manage.js +++ b/src/js/media/views/frame/manage.js @@ -23,6 +23,8 @@ var MediaFrame = wp.media.view.MediaFrame, */ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{ /** + * Initializes the manage frame. + * * @constructs */ initialize: function() { @@ -87,6 +89,9 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype wp.media.frames.browse = this; }, + /** + * Binds the search input to the grid router. + */ bindSearchHandler: function() { var search = this.$( '#media-search-input' ), searchView = this.browserView.toolbar.get( 'search' ).$el, @@ -123,7 +128,7 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype }, /** - * Create the default states for the frame. + * Creates the default states for the frame. */ createStates: function() { var options = this.options; @@ -148,7 +153,7 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype }, /** - * Bind region mode activation events to proper handlers. + * Binds region mode activation events to proper handlers. */ bindRegionModeHandlers: function() { this.on( 'content:create:browse', this.browseContent, this ); @@ -160,6 +165,11 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype this.on( 'select:deactivate', this.unbindKeydown, this ); }, + /** + * Handles keydown events for the frame. + * + * @param {JQuery.Event} e The keydown event. + */ handleKeydown: function( e ) { if ( 27 === e.which ) { e.preventDefault(); @@ -167,14 +177,23 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype } }, + /** + * Binds the keydown event for the frame. + */ bindKeydown: function() { this.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) ); }, + /** + * Unbinds the keydown event for the frame. + */ unbindKeydown: function() { this.$body.off( 'keydown.select' ); }, + /** + * Fixes the position of the attachments browser when scrolling the page. + */ fixPosition: function() { var $browser, $toolbar; if ( ! this.isModeActive( 'select' ) ) { @@ -196,6 +215,8 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype /** * Click handler for the `Add New` button. + * + * @param {Event} event The click event. */ addNewClickHandler: function( event ) { event.preventDefault(); @@ -207,7 +228,9 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype }, /** - * Open the Edit Attachment modal. + * Opens the Edit Attachment modal. + * + * @param {wp.media.model.Attachment} model The attachment model to edit. */ openEditAttachmentModal: function( model ) { // Create a new EditAttachment frame, passing along the library and the attachment model. @@ -224,11 +247,11 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype }, /** - * Create an attachments browser view within the content region. + * Creates an attachments browser view within the content region. * * @param {Object} contentRegion Basic object with a `view` property, which * should be set with the proper region view. - * @this wp.media.controller.Region + * @this {wp.media.controller.Region} */ browseContent: function( contentRegion ) { var state = this.state(); @@ -260,10 +283,16 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype this.errors.on( 'add remove reset', this.sidebarVisibility, this ); }, + /** + * Handles the visibility of the sidebar + */ sidebarVisibility: function() { this.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length ); }, + /** + * Binds the deferred object of the browser view to the startHistory method. + */ bindDeferred: function() { if ( ! this.browserView.dfd ) { return; @@ -271,6 +300,9 @@ Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype this.browserView.dfd.done( _.bind( this.startHistory, this ) ); }, + /** + * Starts the history for the frame, if supported. + */ startHistory: function() { // Verify pushState support and activate. if ( window.history && window.history.pushState ) { diff --git a/src/js/media/views/frame/post.js b/src/js/media/views/frame/post.js index 08b32bb0cccd2..632779d56e7cb 100644 --- a/src/js/media/views/frame/post.js +++ b/src/js/media/views/frame/post.js @@ -234,6 +234,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }, this ); }, + /** + * Activates the frame. + */ activate: function() { // Hide menu items for states tied to particular media types if there are no items. _.each( this.counts, function( type ) { @@ -243,6 +246,12 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }, this ); }, + /** + * Handles the counts of media types. + * + * @param {wp.media.model.Attachments} model The attachment model that changed. + * @param {string} attr The attribute that changed on the model. + */ mediaTypeCounts: function( model, attr ) { if ( typeof this.counts[ attr ] !== 'undefined' && this.counts[ attr ].count < 1 ) { this.counts[ attr ].count++; @@ -252,7 +261,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ // Menus. /** - * @param {wp.Backbone.View} view + * Handles the main menu for the frame. + * + * @param {wp.Backbone.View} view The menu view for the main menu. */ mainMenu: function( view ) { view.set({ @@ -266,6 +277,12 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the visibility of menu items for the frame. + * + * @param {string} state The state to show or hide. + * @param {string} visibility The visibility of the menu item, either 'show' or 'hide'. + */ menuItemVisibility: function( state, visibility ) { var menu = this.menu.get(); if ( visibility === 'hide' ) { @@ -275,7 +292,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ } }, /** - * @param {wp.Backbone.View} view + * Handles the gallery menu for the frame. + * + * @param {wp.Backbone.View} view The menu view for the gallery menu. */ galleryMenu: function( view ) { var lastState = this.lastState(), @@ -304,6 +323,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the playlist menu for the frame. + * + * @param {wp.Backbone.View} view The menu view for the playlist menu. + */ playlistMenu: function( view ) { var lastState = this.lastState(), previous = lastState && lastState.id, @@ -331,6 +355,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the video playlist menu for the frame. + * + * @param {wp.Backbone.View} view The menu view. + */ videoPlaylistMenu: function( view ) { var lastState = this.lastState(), previous = lastState && lastState.id, @@ -359,6 +388,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }, // Content. + /** + * Handles the embed content for the frame. + */ embedContent: function() { var view = new wp.media.view.Embed({ controller: this, @@ -368,6 +400,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ this.content.set( view ); }, + /** + * Handles the edit selection content for the frame. + */ editSelectionContent: function() { var state = this.state(), selection = state.get('selection'), @@ -404,6 +439,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ this.trigger( 'edit:selection', this ); }, + /** + * Handles the edit image content for the frame. + */ editImageContent: function() { var image = this.state().get('image'), view = new wp.media.view.EditImage( { model: image, controller: this } ).render(); @@ -418,7 +456,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ // Toolbars. /** - * @param {wp.Backbone.View} view + * Handles the selection status toolbar for the frame + * + * @param {wp.Backbone.View} view The toolbar view. */ selectionStatusToolbar: function( view ) { var editable = this.state().get('editable'); @@ -437,7 +477,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }, /** - * @param {wp.Backbone.View} view + * Handles the main insert toolbar for the frame. + * + * @param {wp.Backbone.View} view The toolbar view. */ mainInsertToolbar: function( view ) { var controller = this; @@ -466,7 +508,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }, /** - * @param {wp.Backbone.View} view + * Handles the main gallery toolbar for the frame. + * + * @param {wp.Backbone.View} view The toolbar view. */ mainGalleryToolbar: function( view ) { var controller = this; @@ -498,6 +542,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the main playlist toolbar for the frame. + * + * @param {wp.Backbone.View} view The toolbar view. + */ mainPlaylistToolbar: function( view ) { var controller = this; @@ -528,6 +577,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the main video playlist toolbar for the frame. + * + * @param {wp.Backbone.View} view The toolbar view. + */ mainVideoPlaylistToolbar: function( view ) { var controller = this; @@ -558,6 +612,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the featured image toolbar for the frame. + * + * @param {wp.media.view.Toolbar} toolbar The toolbar view. + */ featuredImageToolbar: function( toolbar ) { this.createSelectToolbar( toolbar, { text: l10n.setFeaturedImage, @@ -565,12 +624,20 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }); }, + /** + * Handles the main embed toolbar for the frame. + * + * @param {wp.media.view.Toolbar} toolbar The toolbar view. + */ mainEmbedToolbar: function( toolbar ) { toolbar.view = new wp.media.view.Toolbar.Embed({ controller: this }); }, + /** + * Handles the edit image toolbar for the frame. + */ galleryEditToolbar: function() { var editing = this.state().get('editing'); this.toolbar.set( new wp.media.view.Toolbar({ @@ -583,6 +650,8 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ requires: { library: true, uploadingComplete: true }, /** + * Handles the click event for the insert button. + * * @fires wp.media.controller.State#update */ click: function() { @@ -601,6 +670,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }) ); }, + /** + * Handles the add to gallery toolbar for the frame. + */ galleryAddToolbar: function() { this.toolbar.set( new wp.media.view.Toolbar({ controller: this, @@ -612,6 +684,8 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ requires: { selection: true }, /** + * Handles the click event for the insert button. + * * @fires wp.media.controller.State#reset */ click: function() { @@ -630,6 +704,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }) ); }, + /** + * Handles the edit playlist toolbar for the frame. + */ playlistEditToolbar: function() { var editing = this.state().get('editing'); this.toolbar.set( new wp.media.view.Toolbar({ @@ -642,6 +719,8 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ requires: { library: true }, /** + * Handles the click event for the insert button. + * * @fires wp.media.controller.State#update */ click: function() { @@ -660,6 +739,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }) ); }, + /** + * Handles the add to playlist toolbar for the frame. + */ playlistAddToolbar: function() { this.toolbar.set( new wp.media.view.Toolbar({ controller: this, @@ -671,6 +753,8 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ requires: { selection: true }, /** + * Handles the click event for the insert button. + * * @fires wp.media.controller.State#reset */ click: function() { @@ -689,6 +773,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }) ); }, + /** + * Handles the edit video playlist toolbar for the frame. + */ videoPlaylistEditToolbar: function() { var editing = this.state().get('editing'); this.toolbar.set( new wp.media.view.Toolbar({ @@ -719,6 +806,9 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{ }) ); }, + /** + * Handles the add to video playlist toolbar for the frame. + */ videoPlaylistAddToolbar: function() { this.toolbar.set( new wp.media.view.Toolbar({ controller: this, diff --git a/src/js/media/views/frame/select.js b/src/js/media/views/frame/select.js index 3f3c0642eea53..38b91c31b5fea 100644 --- a/src/js/media/views/frame/select.js +++ b/src/js/media/views/frame/select.js @@ -108,7 +108,7 @@ Select = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Select.prototype /** * Render callback for the router region in the `browse` mode. * - * @param {wp.media.view.Router} routerView + * @param {wp.media.view.Router} routerView The router view for the `browse` mode. */ browseRouter: function( routerView ) { routerView.set({ @@ -126,7 +126,7 @@ Select = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Select.prototype /** * Render callback for the content region in the `browse` mode. * - * @param {wp.media.controller.Region} contentRegion + * @param {wp.media.controller.Region} contentRegion The content region for the `browse` mode. */ browseContent: function( contentRegion ) { var state = this.state(); @@ -167,9 +167,9 @@ Select = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Select.prototype /** * Toolbars * - * @param {Object} toolbar - * @param {Object} [options={}] - * @this wp.media.controller.Region + * @param {Object} toolbar The toolbar object for the `select` mode. + * @param {Object} [options={}] The options for creating the select toolbar view. + * @this {wp.media.controller.Region} */ createSelectToolbar: function( toolbar, options ) { options = options || this.options.button || {}; diff --git a/src/js/media/views/iframe.js b/src/js/media/views/iframe.js index d047560d73d00..fc150d8ef1278 100644 --- a/src/js/media/views/iframe.js +++ b/src/js/media/views/iframe.js @@ -11,6 +11,8 @@ var Iframe = wp.media.View.extend(/** @lends wp.media.view.Iframe.prototype */{ className: 'media-iframe', /** + * Renders the iframe view. + * * @return {wp.media.view.Iframe} Returns itself to allow chaining. */ render: function() { diff --git a/src/js/media/views/media-details.js b/src/js/media/views/media-details.js index 19b1fb0d9c253..5fdeb64a05cd1 100644 --- a/src/js/media/views/media-details.js +++ b/src/js/media/views/media-details.js @@ -16,6 +16,9 @@ var AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay, * @augments Backbone.View */ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.prototype */{ + /** + * Initializes the media details view. + */ initialize: function() { _.bindAll(this, 'success'); this.players = []; @@ -28,6 +31,11 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr AttachmentDisplay.prototype.initialize.apply( this, arguments ); }, + /** + * Handles events for the media details view. + * + * @return {Object} The events object. + */ events: function(){ return _.extend( { 'click .remove-setting' : 'removeSetting', @@ -37,6 +45,11 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr }, AttachmentDisplay.prototype.events ); }, + /** + * Prepares the data for the media details view. + * + * @return {Object} The prepared data. + */ prepare: function() { return _.defaults({ model: this.model.toJSON() @@ -44,11 +57,11 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr }, /** - * Remove a setting's UI when the model unsets it + * Removes a setting's UI when the model unsets it * - * @fires wp.media.view.MediaDetails#media:setting:remove + * Fires `wp.media.view.MediaDetails#media:setting:remove` when a setting is removed. * - * @param {Event} e + * @param {JQuery.Event} e The jQuery event object. */ removeSetting : function(e) { var wrap = $( e.currentTarget ).parent(), setting; @@ -63,8 +76,9 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr }, /** + * Sets the tracks for the media details view. * - * @fires wp.media.view.MediaDetails#media:setting:remove + * Fires `wp.media.view.MediaDetails#media:setting:remove` when the tracks are updated. */ setTracks : function() { var tracks = ''; @@ -77,16 +91,27 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr this.trigger( 'media:setting:remove', this ); }, + /** + * Adds a source to the media details view. + * + * @param {JQuery.Event} e The jQuery event object. + */ addSource : function( e ) { this.controller.lastMime = $( e.currentTarget ).data( 'mime' ); this.controller.setState( 'add-' + this.controller.defaults.id + '-source' ); }, + /** + * Loads the media player for the media details view. + */ loadPlayer: function () { this.players.push( new MediaElementPlayer( this.media, this.settings ) ); this.scriptXhr = false; }, + /** + * Sets the media player for the media details view. + */ setPlayer : function() { var src; @@ -104,12 +129,19 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr }, /** + * Sets the media for the media details view. + * * @abstract */ setMedia : function() { return this; }, + /** + * Handles the success event for the media details view. + * + * @param {MediaElementPlayer} mejs The media element player instance. + */ success : function(mejs) { var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay; @@ -123,7 +155,9 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr }, /** - * @return {media.view.MediaDetails} Returns itself to allow chaining. + * Renders the media details view. + * + * @return {wp.media.view.MediaDetails} Returns itself to allow chaining. */ render: function() { AttachmentDisplay.prototype.render.apply( this, arguments ); @@ -139,6 +173,9 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr return this.setMedia(); }, + /** + * Scrolls the media details view to the top. + */ scrollToTop: function() { this.$( '.embed-media-settings' ).scrollTop( 0 ); } @@ -147,8 +184,8 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr /** * When multiple players in the DOM contain the same src, things get weird. * - * @param {HTMLElement} elem - * @return {HTMLElement} + * @param {HTMLElement} elem The HTML element containing the media sources to be prepared. + * @return {HTMLElement} The prepared element. */ prepareSrc : function( elem ) { var i = MediaDetails.instances++; diff --git a/src/js/media/views/media-frame.js b/src/js/media/views/media-frame.js index 1140bf2795ff4..9d99f3a5e81a9 100644 --- a/src/js/media/views/media-frame.js +++ b/src/js/media/views/media-frame.js @@ -27,6 +27,8 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }, /** + * Initializes the media frame. + * * @constructs */ initialize: function() { @@ -141,6 +143,8 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }, /** + * Renders the media frame. + * * @return {wp.media.view.MediaFrame} Returns itself to allow chaining. */ render: function() { @@ -154,18 +158,24 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ return Frame.prototype.render.apply( this, arguments ); }, /** - * @param {Object} title - * @this wp.media.controller.Region + * Creates the title view. + * + * @param {Object} title The title object for creating the title view. + * @this {wp.media.controller.Region} */ createTitle: function( title ) { + // A modal's dialog element points `aria-labelledby` at its frame heading. title.view = new wp.media.View({ controller: this, - tagName: 'h1' + tagName: 'h1', + attributes: this.modal ? { id: this.modal.titleId } : {} }); }, /** - * @param {Object} menu - * @this wp.media.controller.Region + * Creates the menu view. + * + * @param {Object} menu The menu object for creating the menu view. + * @this {wp.media.controller.Region} */ createMenu: function( menu ) { menu.view = new wp.media.view.Menu({ @@ -180,6 +190,11 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ this.menuView = menu.view; }, + /** + * Toggles the menu visibility. + * + * @param {JQuery.Event} event The click event. + */ toggleMenu: function( event ) { var menu = this.$el.find( '.media-menu' ); @@ -188,8 +203,10 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }, /** - * @param {Object} toolbar - * @this wp.media.controller.Region + * Creates the toolbar view. + * + * @param {Object} toolbar The toolbar object for creating the toolbar view. + * @this {wp.media.controller.Region} */ createToolbar: function( toolbar ) { toolbar.view = new wp.media.view.Toolbar({ @@ -197,8 +214,10 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }); }, /** - * @param {Object} router - * @this wp.media.controller.Region + * Creates the router view. + * + * @param {Object} router The router object for creating the router view. + * @this {wp.media.controller.Region} */ createRouter: function( router ) { router.view = new wp.media.view.Router({ @@ -213,7 +232,9 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ this.routerView = router.view; }, /** - * @param {Object} options + * Creates the iframe states. + * + * @param {Object} options The options for creating the iframe states. */ createIframeStates: function( options ) { var settings = wp.media.view.settings, @@ -250,8 +271,10 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }, /** - * @param {Object} content - * @this wp.media.controller.Region + * Creates the iframe content view. + * + * @param {Object} content The content object for creating the iframe content view. + * @this {wp.media.controller.Region} */ iframeContent: function( content ) { this.$el.addClass('hide-toolbar'); @@ -260,10 +283,18 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }); }, + /** + * Cleans up the iframe content view. + */ iframeContentCleanup: function() { this.$el.removeClass('hide-toolbar'); }, + /** + * Creates the iframe menu. + * + * @param {wp.media.view.Menu} view The menu view. + */ iframeMenu: function( view ) { var views = {}; @@ -281,6 +312,9 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ view.set( views ); }, + /** + * Hijacks the Thickbox close function to close the media modal. + */ hijackThickbox: function() { var frame = this; @@ -297,6 +331,9 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ }; }, + /** + * Restores the Thickbox close function. + */ restoreThickbox: function() { if ( ! this._tb_remove ) { return; @@ -310,6 +347,8 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{ // Map some of the modal's methods to the frame. _.each(['open','close','attach','detach','escape'], function( method ) { /** + * Opens the media frame modal. + * * @function open * @memberOf wp.media.view.MediaFrame * @instance @@ -317,6 +356,8 @@ _.each(['open','close','attach','detach','escape'], function( method ) { * @return {wp.media.view.MediaFrame} Returns itself to allow chaining. */ /** + * Closes the media frame modal. + * * @function close * @memberOf wp.media.view.MediaFrame * @instance @@ -324,6 +365,8 @@ _.each(['open','close','attach','detach','escape'], function( method ) { * @return {wp.media.view.MediaFrame} Returns itself to allow chaining. */ /** + * Attaches the media frame to the DOM. + * * @function attach * @memberOf wp.media.view.MediaFrame * @instance @@ -331,6 +374,8 @@ _.each(['open','close','attach','detach','escape'], function( method ) { * @return {wp.media.view.MediaFrame} Returns itself to allow chaining. */ /** + * Detaches the media frame from the DOM. + * * @function detach * @memberOf wp.media.view.MediaFrame * @instance @@ -338,6 +383,8 @@ _.each(['open','close','attach','detach','escape'], function( method ) { * @return {wp.media.view.MediaFrame} Returns itself to allow chaining. */ /** + * Triggers the escape action on the media frame modal. + * * @function escape * @memberOf wp.media.view.MediaFrame * @instance diff --git a/src/js/media/views/menu-item.js b/src/js/media/views/menu-item.js index 6acb5c361be07..09ae9b4a70923 100644 --- a/src/js/media/views/menu-item.js +++ b/src/js/media/views/menu-item.js @@ -36,6 +36,9 @@ MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{ } }, + /** + * Handles the click event. + */ click: function() { var state = this.options.state; @@ -47,6 +50,8 @@ MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{ }, /** + * Renders the menu item. + * * @return {wp.media.view.MenuItem} returns itself to allow chaining. */ render: function() { diff --git a/src/js/media/views/menu.js b/src/js/media/views/menu.js index cf967c83bb4f6..e0e2324402636 100644 --- a/src/js/media/views/menu.js +++ b/src/js/media/views/menu.js @@ -25,6 +25,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ 'aria-orientation': 'horizontal' }, + /** + * Initializes the menu view. + */ initialize: function() { this._views = {}; @@ -46,9 +49,11 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ }, /** - * @param {Object} options - * @param {string} id - * @return {wp.media.View} + * Creates a view for the given options and id. + * + * @param {Object} options The options for creating the view. + * @param {string} id The id of the view to create. + * @return {wp.media.View} The view instance. */ toView: function( options, id ) { options = options || {}; @@ -56,6 +61,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ return new this.ItemView( options ).render(); }, + /** + * Updates the menu when the state changes. + */ ready: function() { /** * call 'ready' directly on the parent class @@ -67,6 +75,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ this.focusManager.setupAriaTabs(); }, + /** + * Sets the menu items. + */ set: function() { /** * call 'set' directly on the parent class @@ -75,6 +86,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ this.visibility(); }, + /** + * Unsets the menu items. + */ unset: function() { /** * call 'unset' directly on the parent class @@ -83,6 +97,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ this.visibility(); }, + /** + * Updates the menu visibility. + */ visibility: function() { var region = this.region, view = this.controller[ region ].get(), @@ -97,7 +114,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ } }, /** - * @param {string} id + * Selects the menu item with the given id. + * + * @param {string} id The menu item id. */ select: function( id ) { var view = this.get( id ); @@ -113,10 +132,18 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ this.focusManager.setupAriaTabs(); }, + /** + * Deselects the menu items. + */ deselect: function() { this.$el.children().removeClass('active'); }, + /** + * Hides the menu item with the given id. + * + * @param {string} id The menu item id. + */ hide: function( id ) { var view = this.get( id ); @@ -127,6 +154,11 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{ view.$el.addClass('hidden'); }, + /** + * Shows the menu item with the given id. + * + * @param {string} id The menu item id. + */ show: function( id ) { var view = this.get( id ); diff --git a/src/js/media/views/modal.js b/src/js/media/views/modal.js index cfc396bf8039b..629329ed88789 100644 --- a/src/js/media/views/modal.js +++ b/src/js/media/views/modal.js @@ -32,21 +32,30 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ hasCloseButton: true }); + this.titleId = _.uniqueId( 'media-frame-title-' ); + this.focusManager = new wp.media.view.FocusManager({ el: this.el }); }, /** - * @return {Object} + * Prepares the data for the modal template. + * + * @since 7.2.0 Added the `titleId` property. + * + * @return {Object} The prepared data. */ prepare: function() { return { title: this.options.title, - hasCloseButton: this.options.hasCloseButton + hasCloseButton: this.options.hasCloseButton, + titleId: this.titleId }; }, /** + * Attaches the modal to the DOM and triggers the ready event. + * * @return {wp.media.view.Modal} Returns itself to allow chaining. */ attach: function() { @@ -68,6 +77,8 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ }, /** + * Detaches the modal from the DOM and triggers the detach event. + * * @return {wp.media.view.Modal} Returns itself to allow chaining. */ detach: function() { @@ -81,6 +92,8 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ }, /** + * Opens the modal and triggers the open event. + * * @return {wp.media.view.Modal} Returns itself to allow chaining. */ open: function() { @@ -124,7 +137,10 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ }, /** - * @param {Object} options + * Closes the modal and triggers the close event. + * + * @param {Object} [options={}] The options for closing the modal. + * @param {boolean} [options.escape] Whether the modal is being closed due to the escape key. * @return {wp.media.view.Modal} Returns itself to allow chaining. */ close: function( options ) { @@ -167,13 +183,17 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ return this; }, /** + * Closes the modal and triggers the escape event. + * * @return {wp.media.view.Modal} Returns itself to allow chaining. */ escape: function() { return this.close({ escape: true }); }, /** - * @param {Object} event + * Handles the escape key press event to close the modal. + * + * @param {JQuery.Event} event The jQuery event object. */ escapeHandler: function( event ) { event.preventDefault(); @@ -185,7 +205,7 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ * * @since 6.7 * - * @param {Object} event The keydown event object. + * @param {JQuery.Event} event The jQuery event object. */ selectHandler: function( event ) { var selection = this.controller.state().get( 'selection' ); @@ -204,6 +224,8 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ }, /** + * Sets the content of the modal by registering views to the '.media-modal-content' selector. + * * @param {Array|Object} content Views to register to '.media-modal-content' * @return {wp.media.view.Modal} Returns itself to allow chaining. */ @@ -216,7 +238,7 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ * Triggers a modal event and if the `propagate` option is set, * forwards events to the modal's controller. * - * @param {string} id + * @param {string} id The ID of the event to propagate. * @return {wp.media.view.Modal} Returns itself to allow chaining. */ propagate: function( id ) { @@ -229,7 +251,9 @@ Modal = wp.media.View.extend(/** @lends wp.media.view.Modal.prototype */{ return this; }, /** - * @param {Object} event + * Handles keydown events within the modal. + * + * @param {JQuery.Event} event The jQuery keydown event object. */ keydown: function( event ) { // Close the modal when escape is pressed. diff --git a/src/js/media/views/priority-list.js b/src/js/media/views/priority-list.js index 65e7cde20ddd2..f0ed9dbeab84e 100644 --- a/src/js/media/views/priority-list.js +++ b/src/js/media/views/priority-list.js @@ -22,9 +22,11 @@ var PriorityList = wp.media.View.extend(/** @lends wp.media.view.PriorityList.pr } }, /** - * @param {string} id - * @param {wp.media.View|Object} view - * @param {Object} options + * Adds a view to the list, sorted by its priority. + * + * @param {string} id The ID of the view to set. + * @param {wp.media.View|Object} view The view to set. + * @param {Object} options The options for setting the view. * @return {wp.media.view.PriorityList} Returns itself to allow chaining. */ set: function( id, view, options ) { @@ -65,15 +67,19 @@ var PriorityList = wp.media.View.extend(/** @lends wp.media.view.PriorityList.pr return this; }, /** - * @param {string} id - * @return {wp.media.View} + * Retrieves a view by its ID. + * + * @param {string} id The ID of the view to retrieve. + * @return {wp.media.View} Returns the view if found, otherwise undefined. */ get: function( id ) { return this._views[ id ]; }, /** - * @param {string} id - * @return {wp.media.view.PriorityList} + * Removes a view by its ID. + * + * @param {string} id The ID of the view to remove. + * @return {wp.media.view.PriorityList} Returns itself to allow chaining. */ unset: function( id ) { var view = this.get( id ); @@ -86,8 +92,10 @@ var PriorityList = wp.media.View.extend(/** @lends wp.media.view.PriorityList.pr return this; }, /** - * @param {Object} options - * @return {wp.media.View} + * Creates a view from an object of options. + * + * @param {Object} options The options for creating the view. + * @return {wp.media.View} Returns the created view. */ toView: function( options ) { return new wp.media.View( options ); diff --git a/src/js/media/views/search.js b/src/js/media/views/search.js index 875f4b7050e6e..306d7dcdce727 100644 --- a/src/js/media/views/search.js +++ b/src/js/media/views/search.js @@ -24,6 +24,8 @@ Search = wp.media.View.extend(/** @lends wp.media.view.Search.prototype */{ }, /** + * Renders the search input. + * * @return {wp.media.view.Search} Returns itself to allow chaining. */ render: function() { @@ -31,6 +33,11 @@ Search = wp.media.View.extend(/** @lends wp.media.view.Search.prototype */{ return this; }, + /** + * Searches the media library. + * + * @param {JQuery.Event} event The input event. + */ search: _.debounce( function( event ) { var searchTerm = event.target.value.trim(); diff --git a/src/js/media/views/settings.js b/src/js/media/views/settings.js index e91055a72fe6a..c737a3b52e0bb 100644 --- a/src/js/media/views/settings.js +++ b/src/js/media/views/settings.js @@ -20,17 +20,27 @@ Settings = View.extend(/** @lends wp.media.view.Settings.prototype */{ 'change textarea': 'updateHandler' }, + /** + * Initializes the settings view. + */ initialize: function() { this.model = this.model || new Backbone.Model(); this.listenTo( this.model, 'change', this.updateChanges ); }, + /** + * Prepares the data for rendering. + * + * @return {Object} The data to be used in the template. + */ prepare: function() { return _.defaults({ model: this.model.toJSON() }, this.options ); }, /** + * Renders the settings view. + * * @return {wp.media.view.Settings} Returns itself to allow chaining. */ render: function() { @@ -40,7 +50,9 @@ Settings = View.extend(/** @lends wp.media.view.Settings.prototype */{ return this; }, /** - * @param {string} key + * Updates the selected value for a setting. + * + * @param {string} key The key of the setting to update. */ update: function( key ) { var value = this.model.get( key ), @@ -87,7 +99,9 @@ Settings = View.extend(/** @lends wp.media.view.Settings.prototype */{ } }, /** - * @param {Object} event + * Updates the model when a setting is changed. + * + * @param {JQuery.Event} event The jQuery event object associated with the setting change. */ updateHandler: function( event ) { var $setting = $( event.target ).closest('[data-setting]'), @@ -116,6 +130,11 @@ Settings = View.extend(/** @lends wp.media.view.Settings.prototype */{ } }, + /** + * Updates the view when the model changes. + * + * @param {Backbone.Model} model The model that changed. + */ updateChanges: function( model ) { if ( model.hasChanged() ) { _( model.changed ).chain().keys().each( this.update, this ); diff --git a/src/js/media/views/settings/attachment-display.js b/src/js/media/views/settings/attachment-display.js index de26d4f0a46f3..de153f745c928 100644 --- a/src/js/media/views/settings/attachment-display.js +++ b/src/js/media/views/settings/attachment-display.js @@ -16,6 +16,9 @@ AttachmentDisplay = Settings.extend(/** @lends wp.media.view.Settings.Attachment className: 'attachment-display-settings', template: wp.template('attachment-display-settings'), + /** + * Initializes the attachment display settings view. + */ initialize: function() { var attachment = this.options.attachment; @@ -31,6 +34,9 @@ AttachmentDisplay = Settings.extend(/** @lends wp.media.view.Settings.Attachment } }, + /** + * Disposes of the attachment display settings view. + */ dispose: function() { var attachment = this.options.attachment; if ( attachment ) { @@ -42,6 +48,8 @@ AttachmentDisplay = Settings.extend(/** @lends wp.media.view.Settings.Attachment Settings.prototype.dispose.apply( this, arguments ); }, /** + * Renders the attachment display settings view. + * * @return {wp.media.view.AttachmentDisplay} Returns itself to allow chaining. */ render: function() { @@ -60,6 +68,9 @@ AttachmentDisplay = Settings.extend(/** @lends wp.media.view.Settings.Attachment return this; }, + /** + * Updates the linkTo setting. + */ updateLinkTo: function() { var linkTo = this.model.get('link'), $input = this.$('.link-to-custom'), diff --git a/src/js/media/views/toolbar.js b/src/js/media/views/toolbar.js index ff98d13b0a316..68d58d93faffc 100644 --- a/src/js/media/views/toolbar.js +++ b/src/js/media/views/toolbar.js @@ -18,6 +18,9 @@ Toolbar = View.extend(/** @lends wp.media.view.Toolbar.prototype */{ tagName: 'div', className: 'media-toolbar', + /** + * Initializes the toolbar view. + */ initialize: function() { var state = this.controller.state(), selection = this.selection = state.get('selection'), @@ -52,6 +55,8 @@ Toolbar = View.extend(/** @lends wp.media.view.Toolbar.prototype */{ } }, /** + * Disposes of the toolbar view. + * * @return {wp.media.view.Toolbar} Returns itself to allow chaining */ dispose: function() { @@ -68,14 +73,19 @@ Toolbar = View.extend(/** @lends wp.media.view.Toolbar.prototype */{ return View.prototype.dispose.apply( this, arguments ); }, + /** + * Prepares the data for rendering. + */ ready: function() { this.refresh(); }, /** - * @param {string} id - * @param {Backbone.View|Object} view - * @param {Object} [options={}] + * Sets a view by its ID. + * + * @param {string} id The ID of the view to set. + * @param {Backbone.View|Object} view The view to set. + * @param {Object} [options={}] The options for setting the view. * @return {wp.media.view.Toolbar} Returns itself to allow chaining. */ set: function( id, view, options ) { @@ -109,15 +119,19 @@ Toolbar = View.extend(/** @lends wp.media.view.Toolbar.prototype */{ return this; }, /** - * @param {string} id - * @return {wp.media.view.Button} + * Retrieves a view by its ID. + * + * @param {string} id The ID of the view to retrieve. + * @return {wp.media.view.Button} The view associated with the given ID, or undefined if no view is found. */ get: function( id ) { return this._views[ id ]; }, /** - * @param {string} id - * @param {Object} options + * Unsets a view by its ID. + * + * @param {string} id The ID of the view to unset. + * @param {Object} [options={}] The options for unsetting the view. * @return {wp.media.view.Toolbar} Returns itself to allow chaining. */ unset: function( id, options ) { @@ -132,6 +146,9 @@ Toolbar = View.extend(/** @lends wp.media.view.Toolbar.prototype */{ return this; }, + /** + * Refreshes the toolbar view. + */ refresh: function() { var state = this.controller.state(), library = state.get('library'), diff --git a/src/js/media/views/uploader/editor.js b/src/js/media/views/uploader/editor.js index 824d7253f80d8..4ea1c310b73c9 100644 --- a/src/js/media/views/uploader/editor.js +++ b/src/js/media/views/uploader/editor.js @@ -28,6 +28,8 @@ EditorUploader = View.extend(/** @lends wp.media.view.EditorUploader.prototype * /** * Bind drag'n'drop events to callbacks. + * + * @return {wp.media.view.EditorUploader} Chainable. */ initialize: function() { this.initialized = false; @@ -64,7 +66,7 @@ EditorUploader = View.extend(/** @lends wp.media.view.EditorUploader.prototype * /** * Check browser support for drag'n'drop. * - * @return {boolean} + * @return {boolean} True if the browser supports drag'n'drop, false otherwise. */ browserSupport: function() { var supports = false, div = document.createElement('div'); @@ -130,6 +132,7 @@ EditorUploader = View.extend(/** @lends wp.media.view.EditorUploader.prototype * * and upload the file immediately. * * @param {jQuery.Event} event The 'drop' event. + * @return {void|boolean} False to prevent default behavior. */ drop: function( event ) { var $wrap, uploadView; @@ -174,6 +177,8 @@ EditorUploader = View.extend(/** @lends wp.media.view.EditorUploader.prototype * /** * Add the files to the uploader. + * + * @return {wp.media.view.EditorUploader} Chainable. */ addFiles: function() { if ( this.files.length ) { diff --git a/src/js/media/views/uploader/inline.js b/src/js/media/views/uploader/inline.js index 992d2eed02542..eedca1aa24d03 100644 --- a/src/js/media/views/uploader/inline.js +++ b/src/js/media/views/uploader/inline.js @@ -60,11 +60,13 @@ UploaderInline = View.extend(/** @lends wp.media.view.UploaderInline.prototype * return data; }, /** + * Disposes of the inline uploader and its associated views. + * * @return {wp.media.view.UploaderInline} Returns itself to allow chaining. */ dispose: function() { if ( this.disposing ) { - /** + /* * call 'dispose' directly on the parent class */ return View.prototype.dispose.apply( this, arguments ); @@ -79,10 +81,12 @@ UploaderInline = View.extend(/** @lends wp.media.view.UploaderInline.prototype * return this.remove(); }, /** + * Disposes of the inline uploader and its associated views. + * * @return {wp.media.view.UploaderInline} Returns itself to allow chaining. */ remove: function() { - /** + /* * call 'remove' directly on the parent class */ var result = View.prototype.remove.apply( this, arguments ); @@ -99,7 +103,9 @@ UploaderInline = View.extend(/** @lends wp.media.view.UploaderInline.prototype * } }, /** - * @return {wp.media.view.UploaderInline} + * Replaces the placeholder with the uploader browser and refreshes the uploader. + * + * @return {void|wp.media.view.UploaderInline} Returns itself to allow chaining. */ ready: function() { var $browser = this.options.$browser, diff --git a/src/js/media/views/uploader/status.js b/src/js/media/views/uploader/status.js index f629e0a34365f..390b17f9155ec 100644 --- a/src/js/media/views/uploader/status.js +++ b/src/js/media/views/uploader/status.js @@ -33,11 +33,13 @@ UploaderStatus = View.extend(/** @lends wp.media.view.UploaderStatus.prototype * this.errors.on( 'add', this.error, this ); }, /** - * @return {wp.media.view.UploaderStatus} + * Disposes of the uploader status and its associated views. + * + * @return {wp.media.view.UploaderStatus} Returns the instance of the UploaderStatus view. */ dispose: function() { wp.Uploader.queue.off( null, null, this ); - /** + /* * call 'dispose' directly on the parent class */ View.prototype.dispose.apply( this, arguments ); @@ -103,14 +105,19 @@ UploaderStatus = View.extend(/** @lends wp.media.view.UploaderStatus.prototype * } }, /** - * @param {string} filename - * @return {string} + * Escapes the filename to prevent XSS attacks. + * + * @param {string} filename The name of the file to be escaped. + * @return {string} Escaped filename. */ filename: function( filename ) { return _.escape( filename ); }, /** - * @param {Backbone.Model} error + * Handles an error event from the uploader queue. + * + * @param {Backbone.Model} error The error model from the uploader queue. + * @return {void} */ error: function( error ) { var statusError = new wp.media.view.UploaderStatusError( { @@ -131,6 +138,9 @@ UploaderStatus = View.extend(/** @lends wp.media.view.UploaderStatus.prototype * }, 1500 ); }, + /** + * Dismisses the error messages and resets the uploader errors. + */ dismiss: function() { var errors = this.views.get('.upload-errors'); diff --git a/src/js/media/views/uploader/window.js b/src/js/media/views/uploader/window.js index 84b158f7cce61..0cd97f7c9dd76 100644 --- a/src/js/media/views/uploader/window.js +++ b/src/js/media/views/uploader/window.js @@ -13,11 +13,11 @@ var $ = jQuery, * @augments wp.Backbone.View * @augments Backbone.View * - * @param {object} [options] Options hash passed to the view. - * @param {object} [options.uploader] Uploader properties. + * @param {Object} [options] Options hash passed to the view. + * @param {Object} [options.uploader] Uploader properties. * @param {jQuery} [options.uploader.browser] * @param {jQuery} [options.uploader.dropzone] jQuery collection of the dropzone. - * @param {object} [options.uploader.params] + * @param {Object} [options.uploader.params] */ UploaderWindow = wp.media.View.extend(/** @lends wp.media.view.UploaderWindow.prototype */{ tagName: 'div', diff --git a/src/js/media/views/view.js b/src/js/media/views/view.js index e8a4b3621a7ba..08906f9b0982c 100644 --- a/src/js/media/views/view.js +++ b/src/js/media/views/view.js @@ -17,6 +17,11 @@ * @augments Backbone.View */ var View = wp.Backbone.View.extend(/** @lends wp.media.View.prototype */{ + /** + * Constructs the media view. + * + * @param {Object} [options] Options for the view. + */ constructor: function( options ) { if ( options && options.controller ) { this.controller = options.controller; @@ -24,6 +29,8 @@ var View = wp.Backbone.View.extend(/** @lends wp.media.View.prototype */{ wp.Backbone.View.apply( this, arguments ); }, /** + * Disposes of the media view. + * * @todo The internal comment mentions this might have been a stop-gap * before Backbone 0.9.8 came out. Figure out if Backbone core takes * care of this in Backbone.View now. @@ -54,6 +61,8 @@ var View = wp.Backbone.View.extend(/** @lends wp.media.View.prototype */{ return this; }, /** + * Removes the media view. + * * @return {wp.media.View} Returns itself to allow chaining. */ remove: function() { diff --git a/src/wp-activate.php b/src/wp-activate.php index ca06d2d537267..1de0f60c6cfd5 100644 --- a/src/wp-activate.php +++ b/src/wp-activate.php @@ -64,6 +64,11 @@ nocache_headers(); +/** + * @global WP_Query $wp_query WordPress Query object. + */ +global $wp_query; + // Fix for page title. $wp_query->is_404 = false; diff --git a/src/wp-admin/admin-ajax.php b/src/wp-admin/admin-ajax.php index 3ad60f95766e3..5e3d484fae988 100644 --- a/src/wp-admin/admin-ajax.php +++ b/src/wp-admin/admin-ajax.php @@ -79,6 +79,7 @@ 'add-user', 'closed-postboxes', 'hidden-columns', + 'meta-box-reordering', 'update-welcome-panel', 'menu-get-metabox', 'wp-link-ajax', diff --git a/src/wp-admin/admin-footer.php b/src/wp-admin/admin-footer.php index fef0c06bbf725..32f24e536e599 100644 --- a/src/wp-admin/admin-footer.php +++ b/src/wp-admin/admin-footer.php @@ -114,6 +114,14 @@ ?>
- + diff --git a/src/wp-admin/admin-header.php b/src/wp-admin/admin-header.php index 92fbd3a4a2f79..055d801533701 100644 --- a/src/wp-admin/admin-header.php +++ b/src/wp-admin/admin-header.php @@ -95,23 +95,54 @@ <?php echo esc_html( $admin_title ); ?> - - admin_url( 'admin-ajax.php', 'relative' ), + 'pagenow' => $current_screen->id, + 'typenow' => $current_screen->post_type, + 'adminpage' => $admin_body_class, + 'thousandsSeparator' => $wp_locale->number_format['thousands_sep'], + 'decimalPoint' => $wp_locale->number_format['decimal_point'], + 'isRtl' => (int) is_rtl(), + ), + JSON_HEX_TAG | JSON_UNESCAPED_SLASHES + ) + ) +); /** * Fires when enqueuing scripts for all admin pages. @@ -214,6 +245,10 @@ $admin_body_class .= ' block-editor-page wp-embed-responsive'; } +if ( ! wp_is_meta_box_reordering_enabled() ) { + $admin_body_class .= ' meta-box-reordering-disabled'; +} + $admin_body_class .= ' wp-theme-' . sanitize_html_class( get_template() ); if ( is_child_theme() ) { $admin_body_class .= ' wp-child-theme-' . sanitize_html_class( get_stylesheet() ); @@ -246,6 +281,8 @@ * and no-js cannot be removed. * * @since 2.3.0 + * @since 7.2.0 Also applied in the Customizer context, where the body tag does not + * have the wp-admin class. * * @param string $classes Space-separated list of CSS classes. */ @@ -253,11 +290,13 @@ $admin_body_classes = ltrim( $admin_body_classes . ' ' . $admin_body_class ); ?> - - _.delay(function() {wp.a11y.speak(' . wp_json_encode( $speak_message, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ");}, 1500);jQuery( 'button#{$button_unique_id}' ).on( 'click', function() {jQuery(this).parents('div.media-item').slideUp(200, function(){jQuery(this).remove();wp.a11y.speak( wp.i18n.__( 'Error dismissed.' ) );jQuery( '#plupload-browse-button' ).trigger( 'focus' );})});\n"; + $js_function = <<<'JS' + /** + * Announces the upload failure and wires up its dismiss button. + * + * @param {JQueryStatic} $ The jQuery object. + * @param {Object} args PHP exports. + * @param {string} args.speakMessage Message announced to assistive technology. + * @param {string} args.buttonSelector Selector for the notice's dismiss button. + * @return {void} + */ + ( $, { speakMessage, buttonSelector } ) => { + setTimeout( () => wp.a11y.speak( speakMessage ), 1500 ); + $( buttonSelector ).on( 'click', function () { + $( this ) + .parents( 'div.media-item' ) + .slideUp( 200, function () { + $( this ).remove(); + wp.a11y.speak( wp.i18n.__( 'Error dismissed.' ) ); + $( '#plupload-browse-button' ).trigger( 'focus' ); + } ); + } ); + } + JS; + wp_print_inline_script_tag( + sprintf( + '( %s )( jQuery, %s )', + $js_function, + wp_json_encode( + array( + 'speakMessage' => $speak_message, + 'buttonSelector' => 'button#' . $button_unique_id, + ), + JSON_HEX_TAG | JSON_UNESCAPED_SLASHES + ) + ) + ); exit; } diff --git a/src/wp-admin/comment.php b/src/wp-admin/comment.php index b834f7b594062..ed93797a64faf 100644 --- a/src/wp-admin/comment.php +++ b/src/wp-admin/comment.php @@ -372,8 +372,8 @@ * * @since 2.1.0 * - * @param string $location The URI the user will be redirected to. - * @param int $comment_id The ID of the comment being edited. + * @param string $location The URI the user will be redirected to. + * @param int $comment_id The ID of the comment being edited. */ $location = apply_filters( 'comment_edit_redirect', $location, $comment_id ); diff --git a/src/wp-admin/css/about.css b/src/wp-admin/css/about.css index 9d6d8adff4a34..f0c81acac8ec8 100644 --- a/src/wp-admin/css/about.css +++ b/src/wp-admin/css/about.css @@ -1,23 +1,23 @@ -/*------------------------------------------------------------------------------ - 22.0 - About Pages - - 1.0 Global: About, Credits, Freedoms, Privacy, Get Involved - 1.1 Layout - 1.2 Typography & Elements - 1.3 Header - 2.0 Credits Page - 3.0 Freedoms Page - 4.0 Privacy Page - x.2.0 Legacy About Styles: Global - x.2.1 Typography - x.2.2 Structure - x.2.3 Point Releases - x.3.0 Legacy About Styles: About Page - x.3.1 Typography - x.3.2 Structure - x.4.0 Legacy About Styles: Credits & Freedoms Pages - x.5.0 Legacy About Styles: Media Queries -------------------------------------------------------------------------------*/ +/** + * About Pages + * + * 1.0 Global: About, Credits, Freedoms, Privacy, Get Involved + * 1.1 Layout + * 1.2 Typography & Elements + * 1.3 Header + * 2.0 Credits Page + * 3.0 Freedoms Page + * 4.0 Privacy Page + * 5.0 Legacy About Styles: Global + * 5.1 Typography + * 5.2 Structure + * 5.3 Point Releases + * 6.0 Legacy About Styles: About Page + * 6.1 Typography + * 6.2 Structure + * 7.0 Legacy About Styles: Credits & Freedoms Pages + * 8.0 Legacy About Styles: Media Queries + */ .about__container { /* Section backgrounds */ @@ -47,9 +47,9 @@ --gap: 2rem; } -/*------------------------------------------------------------------------------ - 1.0 - Global: About, Credits, Freedoms, Privacy, Get Involved -------------------------------------------------------------------------------*/ +/** + * 1.0 Global: About, Credits, Freedoms, Privacy, Get Involved + */ .about-php, .credits-php, @@ -78,6 +78,7 @@ } } +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__container { max-width: 1000px; margin: 24px auto; @@ -141,8 +142,11 @@ background-position: center; } -/* 1.1 - Layout */ +/** + * 1.1 Layout + */ +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__section { margin: 0; } @@ -239,6 +243,7 @@ grid-template-columns: 3fr 2fr; } +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__section .is-section-header { grid-column-start: 1; grid-column-end: -1; @@ -332,10 +337,12 @@ } .about__section.has-2-columns:not(.is-wider-right,.is-wider-left) div:has(img) { + /* stylelint-disable-next-line property-disallowed-list -- Only applies to decorative images. */ order: 1; } .about__section.has-2-columns:not(.is-wider-right,.is-wider-left) div:not(:has(img)) { + /* stylelint-disable-next-line property-disallowed-list -- Only applies to decorative images. */ order: 0; } @@ -390,8 +397,11 @@ } } -/* 1.2 - Typography & Elements */ +/** + * 1.2 Typography & Elements + */ +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__container { line-height: 1.4; color: var(--text); @@ -560,11 +570,13 @@ font-size: inherit; } +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__section { font-size: 1.125rem; line-height: 1.55; } +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .about__section.is-feature { font-size: 1.6em; } @@ -590,7 +602,9 @@ } } -/* 1.3 - Header */ +/** + * 1.3 Header + */ .about__header { position: relative; @@ -807,10 +821,9 @@ } } - -/*------------------------------------------------------------------------------ - 2.0 - Credits Page -------------------------------------------------------------------------------*/ +/** + * 2.0 Credits Page + */ .about__section .wp-people-group-title { margin-bottom: calc(var(--gap) * 2 - 10px); @@ -923,20 +936,18 @@ } } - -/*------------------------------------------------------------------------------ - 3.0 - Freedoms Page -------------------------------------------------------------------------------*/ +/** + * 3.0 Freedoms Page + */ .about__section .column .freedom-image { margin-bottom: var(--gap); max-height: 180px; } - -/*------------------------------------------------------------------------------ - 4.0 - Privacy Page -------------------------------------------------------------------------------*/ +/** + * 4.0 Privacy Page + */ .about__section .column .privacy-image { display: block; @@ -945,10 +956,9 @@ max-width: 25rem; } - -/*------------------------------------------------------------------------------ - x.2.0 - Legacy About Styles: Global -------------------------------------------------------------------------------*/ +/** + * 5.0 Legacy About Styles: Global + */ .about-wrap { position: relative; @@ -995,8 +1005,6 @@ margin: 1.5em auto; } -/* WordPress Version Badge */ - .wp-badge { background: #0073aa url(../images/w-logo-white.png?ver=20160308) no-repeat; background-position: center 25px; @@ -1024,8 +1032,6 @@ right: 0; } -/* Tabs */ - .about-wrap .nav-tab { padding-right: 15px; padding-left: 15px; @@ -1033,7 +1039,9 @@ line-height: 1.33333333; } -/* x.2.1 - Typography */ +/** + * 5.1 Typography + */ .about-wrap h1 { margin: 0.2em 200px 0 0; @@ -1094,7 +1102,9 @@ color: #555d66; } -/* x.2.2 - Structure */ +/** + * 5.2 Structure + */ .about-wrap .has-1-columns, .about-wrap .has-2-columns, @@ -1212,7 +1222,9 @@ align-self: end; } -/* x.2.3 - Point Releases */ +/** + * 5.3 Point Releases + */ .about-wrap .point-releases { margin-top: 5px; @@ -1235,11 +1247,13 @@ margin-top: 40px; } -/*------------------------------------------------------------------------------ - x.3.0 - Legacy About Styles: About Page -------------------------------------------------------------------------------*/ +/** + * 6.0 Legacy About Styles: About Page + */ -/* x.3.1 - Typography */ +/** + * 6.1 Typography + */ .about-wrap .lead-description { font-size: 1.5em; @@ -1250,7 +1264,9 @@ margin-top: 0.6em; } -/* x.3.2 - Structure */ +/** + * 6.2 Structure + */ .about-wrap .headline-feature { margin: 0 auto 40px; @@ -1266,8 +1282,6 @@ width: 100%; } -/* Go to Dashboard Home link */ - .about-wrap .return-to-dashboard { margin: 30px 0 0 -5px; font-size: 14px; @@ -1279,11 +1293,9 @@ padding: 0 5px; } -/*------------------------------------------------------------------------------ - x.4.0 - Legacy About Styles: Credits & Freedoms Pages -------------------------------------------------------------------------------*/ - -/* Credits */ +/** + * 7.0 Legacy About Styles: Credits & Freedoms Pages + */ .about-wrap h2.wp-people-group { margin: 2.6em 0 1.33em; @@ -1352,8 +1364,6 @@ white-space: nowrap; } -/* Freedoms */ - .freedoms-php .about-wrap ol { margin: 40px 60px; } @@ -1368,9 +1378,9 @@ margin: 0.6em 0; } -/*------------------------------------------------------------------------------ - x.5.0 - Legacy About Styles: Media Queries -------------------------------------------------------------------------------*/ +/** + * 8.0 Legacy About Styles: Media Queries + */ @media screen and (max-width: 782px) { .about-wrap .has-3-columns, diff --git a/src/wp-admin/css/admin-menu.css b/src/wp-admin/css/admin-menu.css index 3747613282be1..7889a3e76008c 100644 --- a/src/wp-admin/css/admin-menu.css +++ b/src/wp-admin/css/admin-menu.css @@ -11,7 +11,6 @@ top: 0; bottom: -120px; z-index: 1; /* positive z-index to avoid elastic scrolling woes in Safari */ - /* Only visible in Windows High Contrast mode */ outline: 1px solid transparent; } @@ -39,8 +38,6 @@ width: 36px; } -/* New Menu icons */ - /* hide background-image for icons above */ .menu-icon-dashboard div.wp-menu-image, .menu-icon-post div.wp-menu-image, @@ -58,17 +55,12 @@ background-image: none !important; } -/*------------------------------------------------------------------------------ - 7.0 - Main Navigation (Left Menu) -------------------------------------------------------------------------------*/ - #adminmenuwrap { position: relative; float: left; z-index: 9990; } -/* side admin menu */ #adminmenu * { -webkit-user-select: none; user-select: none; @@ -111,7 +103,7 @@ #adminmenu a:focus, .folded #adminmenu .wp-submenu-head:hover { box-shadow: inset 4px 0 0 0 currentColor; - transition: box-shadow .1s linear; + transition: box-shadow 0.1s linear; border-radius: 0; } @@ -225,7 +217,7 @@ padding-right: 16px; padding-left: 14px; /* Exclude from the transition the outline for Windows High Contrast mode */ - transition: all .1s ease-in-out, outline 0s; + transition: all 0.1s ease-in-out, outline 0s; } #adminmenu .wp-has-current-submenu ul > li > a, @@ -288,31 +280,31 @@ background-size: 20px auto; } -div.wp-menu-image:before { +div.wp-menu-image::before { color: #a7aaad; color: rgba(240, 246, 252, 0.6); padding: 7px 0; - transition: all .1s ease-in-out; + transition: all 0.1s ease-in-out; } -#adminmenu div.wp-menu-image:before { +#adminmenu div.wp-menu-image::before { color: #a7aaad; color: rgba(240, 246, 252, 0.6); } -#adminmenu li.wp-has-current-submenu:hover div.wp-menu-image:before, -#adminmenu .wp-has-current-submenu div.wp-menu-image:before, -#adminmenu .current div.wp-menu-image:before, -#adminmenu a.wp-has-current-submenu:hover div.wp-menu-image:before, -#adminmenu a.current:hover div.wp-menu-image:before, -#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image:before, -#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image:before { +#adminmenu li.wp-has-current-submenu:hover div.wp-menu-image::before, +#adminmenu .wp-has-current-submenu div.wp-menu-image::before, +#adminmenu .current div.wp-menu-image::before, +#adminmenu a.wp-has-current-submenu:hover div.wp-menu-image::before, +#adminmenu a.current:hover div.wp-menu-image::before, +#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image::before, +#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image::before { color: #fff; } -#adminmenu li:hover div.wp-menu-image:before, -#adminmenu li a:focus div.wp-menu-image:before, -#adminmenu li.opensub div.wp-menu-image:before { +#adminmenu li:hover div.wp-menu-image::before, +#adminmenu li a:focus div.wp-menu-image::before, +#adminmenu li.opensub div.wp-menu-image::before { color: #72aee6; } @@ -336,8 +328,8 @@ ul#adminmenu a.wp-has-current-submenu { position: relative; } -ul#adminmenu a.wp-has-current-submenu:after, -ul#adminmenu > li.current > a.current:after { +ul#adminmenu a.wp-has-current-submenu::after, +ul#adminmenu > li.current > a.current::after { right: 0; border: solid 8px transparent; content: " "; @@ -350,20 +342,20 @@ ul#adminmenu > li.current > a.current:after { margin-top: -8px; } -.folded ul#adminmenu li:hover a.wp-has-current-submenu:after, -.folded ul#adminmenu li.wp-has-current-submenu:focus-within a.wp-has-current-submenu:after { +.folded ul#adminmenu li:hover a.wp-has-current-submenu::after, +.folded ul#adminmenu li.wp-has-current-submenu:focus-within a.wp-has-current-submenu::after { display: none; } -.folded ul#adminmenu a.wp-has-current-submenu:after, -.folded ul#adminmenu > li a.current:after { +.folded ul#adminmenu a.wp-has-current-submenu::after, +.folded ul#adminmenu > li a.current::after { border-width: 4px; margin-top: -4px; } /* flyout menu arrow */ -#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover:after, -#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { +#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover::after, +#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { right: 0; border: 8px solid transparent; content: " "; @@ -375,15 +367,15 @@ ul#adminmenu > li.current > a.current:after { z-index: 10000; } -.folded ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover:after, -.folded ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { +.folded ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover::after, +.folded ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { border-width: 4px; margin-top: -4px; top: 18px; } -#adminmenu li.wp-has-submenu.wp-not-current-submenu.opensub:hover:after, -#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { +#adminmenu li.wp-has-submenu.wp-not-current-submenu.opensub:hover::after, +#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { border-right-color: #2c3338; } @@ -474,7 +466,7 @@ ul#adminmenu > li.current > a.current:after { #collapse-button:focus { color: #72aee6; box-shadow: inset 4px 0 0 0 currentColor; - transition: box-shadow .1s linear; + transition: box-shadow 0.1s linear; } #collapse-button:focus { @@ -494,6 +486,7 @@ ul#adminmenu > li.current > a.current:after { #collapse-button .collapse-button-label { top: 8px; + padding: 0 0 0 36px; } #collapse-button .collapse-button-icon { @@ -501,44 +494,37 @@ ul#adminmenu > li.current > a.current:after { height: 34px; } -#collapse-button .collapse-button-label { - padding: 0 0 0 36px; -} - .folded #collapse-button .collapse-button-label { display: none; } -#collapse-button .collapse-button-icon:after { +#collapse-button .collapse-button-icon::after { content: "\f148"; - content: "\f148" / ''; + content: "\f148" / ""; display: block; position: relative; top: 7px; text-align: center; - font: normal 20px/1 dashicons !important; + font: 400 20px/1 dashicons !important; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* rtl:ignore */ -.folded #collapse-button .collapse-button-icon:after, -.rtl #collapse-button .collapse-button-icon:after { +.folded #collapse-button .collapse-button-icon::after, +.rtl #collapse-button .collapse-button-icon::after { transform: rotate(180deg); } -.rtl.folded #collapse-button .collapse-button-icon:after { +.rtl.folded #collapse-button .collapse-button-icon::after { transform: none; } -#collapse-button .collapse-button-icon:after, +#collapse-button .collapse-button-icon::after, #collapse-button .collapse-button-label { - transition: all .1s ease-in-out; + transition: all 0.1s ease-in-out; } -/** - * Toolbar menu toggle - */ li#wp-admin-bar-menu-toggle { display: none; } @@ -594,7 +580,6 @@ li#wp-admin-bar-menu-toggle { padding-left: 14px; } - .auto-fold #adminmenu li.menu-top .wp-submenu > li > a { padding-left: 12px; } @@ -627,20 +612,20 @@ li#wp-admin-bar-menu-toggle { margin-bottom: 0; } - .auto-fold ul#adminmenu li:hover a.wp-has-current-submenu:after, - .auto-fold ul#adminmenu li:focus-within a.wp-has-current-submenu:after { + .auto-fold ul#adminmenu li:hover a.wp-has-current-submenu::after, + .auto-fold ul#adminmenu li:focus-within a.wp-has-current-submenu::after { display: none; } - .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover:after, - .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { + .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover::after, + .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { border-width: 4px; margin-top: -4px; top: 16px; } - .auto-fold ul#adminmenu a.wp-has-current-submenu:after, - .auto-fold ul#adminmenu > li a.current:after { + .auto-fold ul#adminmenu a.wp-has-current-submenu::after, + .auto-fold ul#adminmenu > li a.current::after { border-width: 4px; margin-top: -4px; } @@ -656,18 +641,19 @@ li#wp-admin-bar-menu-toggle { } /* rtl:ignore */ - .auto-fold #collapse-button .collapse-button-icon:after { + .auto-fold #collapse-button .collapse-button-icon::after { transform: rotate(180deg); } - .rtl.auto-fold #collapse-button .collapse-button-icon:after { + .rtl.auto-fold #collapse-button .collapse-button-icon::after { transform: none; } } @media screen and (max-width: 782px) { - .auto-fold #wpcontent { + .auto-fold #wpcontent, + .auto-fold #wpfooter { position: relative; margin-left: 0; padding-left: 10px; @@ -722,14 +708,14 @@ li#wp-admin-bar-menu-toggle { } /* Switch the arrow side */ - .auto-fold ul#adminmenu a.wp-has-current-submenu:after, - .auto-fold ul#adminmenu > li.current > a.current:after { + .auto-fold ul#adminmenu a.wp-has-current-submenu::after, + .auto-fold ul#adminmenu > li.current > a.current::after { border-width: 8px; margin-top: -8px; } - .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover:after, - .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { + .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:hover::after, + .auto-fold ul#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { display: none; } @@ -748,8 +734,8 @@ li#wp-admin-bar-menu-toggle { box-shadow: none; } - .auto-fold #adminmenu .selected .wp-submenu:after, - .auto-fold #adminmenu .wp-menu-open .wp-submenu:after { + .auto-fold #adminmenu .selected .wp-submenu::after, + .auto-fold #adminmenu .wp-menu-open .wp-submenu::after { display: none; } @@ -761,8 +747,8 @@ li#wp-admin-bar-menu-toggle { display: block; } - .auto-fold ul#adminmenu li:hover a.wp-has-current-submenu:after, - .auto-fold ul#adminmenu li:focus-within a.wp-has-current-submenu:after { + .auto-fold ul#adminmenu li:hover a.wp-has-current-submenu::after, + .auto-fold ul#adminmenu li:focus-within a.wp-has-current-submenu::after { display: block; } @@ -820,11 +806,11 @@ li#wp-admin-bar-menu-toggle { border: 1px solid transparent; } - #wpadminbar #wp-admin-bar-menu-toggle .ab-icon:before { + #wpadminbar #wp-admin-bar-menu-toggle .ab-icon::before { content: "\f228"; display: inline-block; float: left; - font: normal 40px/45px dashicons; + font: 400 40px/45px dashicons; vertical-align: middle; outline: none; margin: 0; @@ -839,7 +825,7 @@ li#wp-admin-bar-menu-toggle { box-sizing: border-box; } - .wp-responsive-open #wpadminbar #wp-admin-bar-menu-toggle .ab-icon:before { + .wp-responsive-open #wpadminbar #wp-admin-bar-menu-toggle .ab-icon::before { color: #72aee6; } } diff --git a/src/wp-admin/css/code-editor.css b/src/wp-admin/css/code-editor.css index 92c39405ba147..ab1ce6ccd1821 100644 --- a/src/wp-admin/css/code-editor.css +++ b/src/wp-admin/css/code-editor.css @@ -14,14 +14,14 @@ top: 0; } -.wrap [class*="CodeMirror-lint-marker"]:before { - font: normal 18px/1 dashicons; +.wrap [class*="CodeMirror-lint-marker"]::before { + font: 400 18px/1 dashicons; position: relative; top: -2px; } -.wp-core-ui [class*="CodeMirror-lint-message"]:before { - font: normal 16px/1 dashicons; +.wp-core-ui [class*="CodeMirror-lint-message"]::before { + font: 400 16px/1 dashicons; left: 16px; position: absolute; } @@ -38,8 +38,8 @@ border-left: 4px solid #dba617; } -.wrap .CodeMirror-lint-marker-warning:before, -.wp-core-ui .CodeMirror-lint-message-warning:before { +.wrap .CodeMirror-lint-marker-warning::before, +.wp-core-ui .CodeMirror-lint-message-warning::before { content: "\f534"; color: #dba617; } @@ -49,8 +49,8 @@ border-left: 4px solid #d63638; } -.wrap .CodeMirror-lint-marker-error:before, -.wp-core-ui .CodeMirror-lint-message-error:before { +.wrap .CodeMirror-lint-marker-error::before, +.wp-core-ui .CodeMirror-lint-message-error::before { content: "\f153"; color: #d63638; } diff --git a/src/wp-admin/css/color-picker.css b/src/wp-admin/css/color-picker.css index 8264432dd39cc..2c66a2cfcfac4 100644 --- a/src/wp-admin/css/color-picker.css +++ b/src/wp-admin/css/color-picker.css @@ -34,8 +34,8 @@ color: #1d2327; } -.wp-color-result:hover:after, -.wp-color-result:focus:after { +.wp-color-result:hover::after, +.wp-color-result:focus::after { color: #1d2327; border-color: #a7aaad; border-left: 1px solid #8c8f94; @@ -81,7 +81,7 @@ } .wp-picker-container .iris-square-slider .ui-slider-handle:focus { - background-color: #50575e + background-color: #50575e; } .wp-picker-container .iris-picker { diff --git a/src/wp-admin/css/colors/_admin.scss b/src/wp-admin/css/colors/_admin.scss index 366f1b86b4f16..8eed01dc9311a 100644 --- a/src/wp-admin/css/colors/_admin.scss +++ b/src/wp-admin/css/colors/_admin.scss @@ -1,23 +1,22 @@ -@use 'sass:color'; -@use 'sass:string'; -@forward 'variables' show $scheme-name, $base-color, $body-background, $button-color, $custom-welcome-panel, $dashboard-accent-1, $dashboard-accent-2, $dashboard-icon-background, $form-checked, $highlight-color, $icon-color, $link, $link-focus, $low-contrast-theme, $menu-bubble-text, $menu-collapse-focus-icon, $menu-collapse-text, $menu-highlight-background, $menu-highlight-icon, $menu-highlight-text, $menu-submenu-text, $menu-submenu-focus-text, $menu-submenu-background, $notification-color, $text-color; -@use 'variables'; -@use 'mixins'; -@use 'tokens'; +@use "sass:color"; +@use "sass:string"; +@forward "variables" show $scheme-name, $base-color, $body-background, $button-color, $custom-welcome-panel, $dashboard-accent-1, $dashboard-accent-2, $dashboard-icon-background, $form-checked, $highlight-color, $icon-color, $link, $link-focus, $low-contrast-theme, $menu-bubble-text, $menu-collapse-focus-icon, $menu-collapse-text, $menu-highlight-background, $menu-highlight-icon, $menu-highlight-text, $menu-submenu-text, $menu-submenu-focus-text, $menu-submenu-background, $notification-color, $text-color; +@use "variables"; +@use "mixins"; +@use "tokens"; /** * This function name uses British English to maintain backward compatibility, as developers * may use the function in their own admin CSS files. See #56811. */ @function url-friendly-colour( $color ) { - @return '%23' + string.slice( '#{ $color }', 2, -1 ); + @return "%23" + string.slice( "#{ $color }", 2, -1 ); } body { background: variables.$body-background; } - /* Links */ a { @@ -30,11 +29,11 @@ a { } } -#post-body .misc-pub-post-status:before, -#post-body #visibility:before, -.curtime #timestamp:before, -#post-body .misc-pub-revisions:before, -span.wp-media-buttons-icon:before { +#post-body .misc-pub-post-status::before, +#post-body #visibility::before, +.curtime #timestamp::before, +#post-body .misc-pub-revisions::before, +span.wp-media-buttons-icon::before { color: currentColor; } @@ -154,7 +153,6 @@ input[type="radio"]:focus { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color); } - /* Core UI */ .wp-core-ui { @@ -183,6 +181,7 @@ input[type="radio"]:focus { color: variables.$text-color; background-color: variables.$base-color; } + .wp-ui-text-primary { color: variables.$base-color; } @@ -191,6 +190,7 @@ input[type="radio"]:focus { color: variables.$menu-highlight-text; background-color: variables.$menu-highlight-background; } + .wp-ui-text-highlight { color: variables.$menu-highlight-background; } @@ -199,6 +199,7 @@ input[type="radio"]:focus { color: variables.$menu-bubble-text; background-color: variables.$menu-bubble-background; } + .wp-ui-text-notification { color: variables.$menu-bubble-background; } @@ -208,7 +209,6 @@ input[type="radio"]:focus { } } - /* List tables */ // .page-title-action uses secondary button styling @@ -240,15 +240,14 @@ input[type="radio"]:focus { box-shadow: none; } -.view-switch a.current:before { +.view-switch a.current::before { color: variables.$menu-background; } -.view-switch a:hover:before { +.view-switch a:hover::before { color: variables.$menu-bubble-background; } - /* Admin Menu */ #adminmenuback, @@ -261,7 +260,7 @@ input[type="radio"]:focus { color: variables.$menu-text; } -#adminmenu div.wp-menu-image:before { +#adminmenu div.wp-menu-image::before { color: variables.$menu-icon; } @@ -273,12 +272,11 @@ input[type="radio"]:focus { background-color: variables.$menu-highlight-background; } -#adminmenu li.menu-top:hover div.wp-menu-image:before, -#adminmenu li.opensub > a.menu-top div.wp-menu-image:before { +#adminmenu li.menu-top:hover div.wp-menu-image::before, +#adminmenu li.opensub > a.menu-top div.wp-menu-image::before { color: variables.$menu-highlight-icon; } - /* Active tabs use a bottom border color that matches the page background color. */ .about-wrap .nav-tab-active, @@ -288,7 +286,6 @@ input[type="radio"]:focus { border-bottom-color: variables.$body-background; } - /* Admin Menu: submenu */ #adminmenu .wp-submenu, @@ -298,8 +295,8 @@ input[type="radio"]:focus { background: variables.$menu-submenu-background; } -#adminmenu li.wp-has-submenu.wp-not-current-submenu.opensub:hover:after, -#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within:after { +#adminmenu li.wp-has-submenu.wp-not-current-submenu.opensub:hover::after, +#adminmenu li.wp-has-submenu.wp-not-current-submenu:focus-within::after { border-right-color: variables.$menu-submenu-background; } @@ -313,12 +310,12 @@ input[type="radio"]:focus { #adminmenu .wp-has-current-submenu.opensub .wp-submenu a { color: variables.$menu-submenu-text; - &:focus, &:hover { + &:focus, + &:hover { color: variables.$menu-submenu-focus-text; } } - /* Admin Menu: current */ #adminmenu .wp-submenu li.current a, @@ -326,14 +323,15 @@ input[type="radio"]:focus { #adminmenu .wp-has-current-submenu.opensub .wp-submenu li.current a { color: variables.$menu-submenu-current-text; - &:hover, &:focus { + &:hover, + &:focus { color: variables.$menu-submenu-focus-text; } } -ul#adminmenu a.wp-has-current-submenu:after, -ul#adminmenu > li.current > a.current:after { - border-right-color: variables.$body-background; +ul#adminmenu a.wp-has-current-submenu::after, +ul#adminmenu > li.current > a.current::after { + border-right-color: variables.$body-background; } #adminmenu li.current a.menu-top, @@ -344,18 +342,17 @@ ul#adminmenu > li.current > a.current:after { background: variables.$menu-current-background; } -#adminmenu li.wp-has-current-submenu div.wp-menu-image:before, -#adminmenu a.current:hover div.wp-menu-image:before, -#adminmenu li.current div.wp-menu-image:before, -#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image:before, -#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image:before, -#adminmenu li:hover div.wp-menu-image:before, -#adminmenu li a:focus div.wp-menu-image:before, -#adminmenu li.opensub div.wp-menu-image:before { +#adminmenu li.wp-has-current-submenu div.wp-menu-image::before, +#adminmenu a.current:hover div.wp-menu-image::before, +#adminmenu li.current div.wp-menu-image::before, +#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image::before, +#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image::before, +#adminmenu li:hover div.wp-menu-image::before, +#adminmenu li a:focus div.wp-menu-image::before, +#adminmenu li.opensub div.wp-menu-image::before { color: variables.$menu-current-icon; } - /* Admin Menu: bubble */ #adminmenu .menu-counter, @@ -373,7 +370,6 @@ ul#adminmenu > li.current > a.current:after { background: variables.$menu-bubble-current-background; } - /* Admin Menu: collapse button */ #collapse-button { @@ -401,9 +397,9 @@ ul#adminmenu > li.current > a.current:after { } #wpadminbar .ab-icon, -#wpadminbar .ab-icon:before, -#wpadminbar .ab-item:before, -#wpadminbar .ab-item:after { +#wpadminbar .ab-icon::before, +#wpadminbar .ab-item::before, +#wpadminbar .ab-item::after { color: variables.$menu-icon; } @@ -422,14 +418,13 @@ ul#adminmenu > li.current > a.current:after { color: variables.$menu-submenu-focus-text; } -#wpadminbar:not(.mobile) li:hover .ab-icon:before, -#wpadminbar:not(.mobile) li:hover .ab-item:before, -#wpadminbar:not(.mobile) li:hover .ab-item:after, -#wpadminbar:not(.mobile) li:hover #adminbarsearch:before { +#wpadminbar:not(.mobile) li:hover .ab-icon::before, +#wpadminbar:not(.mobile) li:hover .ab-item::before, +#wpadminbar:not(.mobile) li:hover .ab-item::after, +#wpadminbar:not(.mobile) li:hover #adminbarsearch::before { color: variables.$menu-submenu-focus-text; } - /* Admin Bar: submenu */ #wpadminbar .menupop .ab-sub-wrapper { @@ -449,7 +444,7 @@ ul#adminmenu > li.current > a.current:after { } #wpadminbar .quicklinks li .blavatar, -#wpadminbar .menupop .menupop > .ab-item:before { +#wpadminbar .menupop .menupop > .ab-item::before { color: variables.$menu-icon; } @@ -462,36 +457,35 @@ ul#adminmenu > li.current > a.current:after { #wpadminbar .quicklinks .menupop.hover ul li a:focus, #wpadminbar.nojs .quicklinks .menupop:hover ul li a:hover, #wpadminbar.nojs .quicklinks .menupop:hover ul li a:focus, -#wpadminbar li:hover .ab-icon:before, -#wpadminbar li:hover .ab-item:before, -#wpadminbar li a:focus .ab-icon:before, -#wpadminbar li .ab-item:focus:before, -#wpadminbar li .ab-item:focus .ab-icon:before, -#wpadminbar li.hover .ab-icon:before, -#wpadminbar li.hover .ab-item:before, -#wpadminbar li:hover #adminbarsearch:before, -#wpadminbar li #adminbarsearch.adminbar-focused:before { +#wpadminbar li:hover .ab-icon::before, +#wpadminbar li:hover .ab-item::before, +#wpadminbar li a:focus .ab-icon::before, +#wpadminbar li .ab-item:focus::before, +#wpadminbar li .ab-item:focus .ab-icon::before, +#wpadminbar li.hover .ab-icon::before, +#wpadminbar li.hover .ab-item::before, +#wpadminbar li:hover #adminbarsearch::before, +#wpadminbar li #adminbarsearch.adminbar-focused::before { color: variables.$menu-submenu-focus-text; } #wpadminbar .quicklinks li a:hover .blavatar, #wpadminbar .quicklinks li a:focus .blavatar, #wpadminbar .quicklinks .ab-sub-wrapper .menupop.hover > a .blavatar, -#wpadminbar .menupop .menupop > .ab-item:hover:before, -#wpadminbar.mobile .quicklinks .hover .ab-icon:before, -#wpadminbar.mobile .quicklinks .hover .ab-item:before { +#wpadminbar .menupop .menupop > .ab-item:hover::before, +#wpadminbar.mobile .quicklinks .hover .ab-icon::before, +#wpadminbar.mobile .quicklinks .hover .ab-item::before { color: variables.$menu-submenu-focus-text; } -#wpadminbar.mobile .quicklinks .ab-icon:before, -#wpadminbar.mobile .quicklinks .ab-item:before { +#wpadminbar.mobile .quicklinks .ab-icon::before, +#wpadminbar.mobile .quicklinks .ab-item::before { color: variables.$menu-icon; } - /* Admin Bar: search */ -#wpadminbar #adminbarsearch:before { +#wpadminbar #adminbarsearch::before { color: variables.$menu-icon; } @@ -512,7 +506,7 @@ ul#adminmenu > li.current > a.current:after { color: variables.$adminbar-recovery-exit-text; } -#wpadminbar .ab-top-menu > #wp-admin-bar-recovery-mode.hover >.ab-item, +#wpadminbar .ab-top-menu > #wp-admin-bar-recovery-mode.hover > .ab-item, #wpadminbar.nojq .quicklinks .ab-top-menu > #wp-admin-bar-recovery-mode > .ab-item:focus, #wpadminbar:not(.mobile) .ab-top-menu > #wp-admin-bar-recovery-mode:hover > .ab-item, #wpadminbar:not(.mobile) .ab-top-menu > #wp-admin-bar-recovery-mode > .ab-item:focus { @@ -527,11 +521,15 @@ ul#adminmenu > li.current > a.current:after { background-color: variables.$adminbar-avatar-frame; } +#wpadminbar #wp-admin-bar-user-info .howdy, #wpadminbar #wp-admin-bar-user-info .display-name { color: variables.$menu-text; } -#wpadminbar #wp-admin-bar-user-info a:hover .display-name { +#wpadminbar #wp-admin-bar-user-info a:hover .howdy, +#wpadminbar #wp-admin-bar-user-info a:focus .howdy, +#wpadminbar #wp-admin-bar-user-info a:hover .display-name, +#wpadminbar #wp-admin-bar-user-info a:focus .display-name { color: variables.$menu-submenu-focus-text; } @@ -539,7 +537,6 @@ ul#adminmenu > li.current > a.current:after { color: variables.$menu-submenu-text; } - /* Pointers */ .wp-pointer .wp-pointer-content h3 { @@ -547,7 +544,7 @@ ul#adminmenu > li.current > a.current:after { border-color: color.adjust(variables.$highlight-color, $lightness: -5%); } -.wp-pointer .wp-pointer-content h3:before { +.wp-pointer .wp-pointer-content h3::before { color: variables.$highlight-color; } @@ -558,7 +555,6 @@ ul#adminmenu > li.current > a.current:after { border-bottom-color: variables.$highlight-color; } - /* Media */ .media-item .bar, @@ -581,17 +577,16 @@ ul#adminmenu > li.current > a.current:after { box-shadow: 0 0 0 1px #fff, 0 0 0 3px variables.$highlight-color; } - /* Themes */ .theme-browser .theme.active .theme-name, -.theme-browser .theme.add-new-theme a:hover:after, -.theme-browser .theme.add-new-theme a:focus:after { +.theme-browser .theme.add-new-theme a:hover::after, +.theme-browser .theme.add-new-theme a:focus::after { background: variables.$highlight-color; } -.theme-browser .theme.add-new-theme a:hover span:after, -.theme-browser .theme.add-new-theme a:focus span:after { +.theme-browser .theme.add-new-theme a:hover span::after, +.theme-browser .theme.add-new-theme a:focus span::after { color: variables.$highlight-color; } @@ -605,7 +600,7 @@ body.more-filters-opened .more-filters { background-color: variables.$menu-background; } -body.more-filters-opened .more-filters:before { +body.more-filters-opened .more-filters::before { color: variables.$menu-text; } @@ -615,8 +610,8 @@ body.more-filters-opened .more-filters:focus { color: variables.$menu-highlight-text; } -body.more-filters-opened .more-filters:hover:before, -body.more-filters-opened .more-filters:focus:before { +body.more-filters-opened .more-filters:hover::before, +body.more-filters-opened .more-filters:focus::before { color: variables.$menu-highlight-text; } @@ -627,24 +622,22 @@ body.more-filters-opened .more-filters:focus:before { color: variables.$menu-highlight-text; } -.widgets-chooser li.widgets-chooser-selected:before, -.widgets-chooser li.widgets-chooser-selected:focus:before { +.widgets-chooser li.widgets-chooser-selected::before, +.widgets-chooser li.widgets-chooser-selected:focus::before { color: variables.$menu-highlight-text; } - /* Nav Menus */ -.nav-menus-php .item-edit:focus:before { +.nav-menus-php .item-edit:focus::before { box-shadow: 0 0 0 1px color.adjust(variables.$button-color, $lightness: 10%), 0 0 2px 1px variables.$button-color; } - /* Responsive Component */ -div#wp-responsive-toggle a:before { +div#wp-responsive-toggle a::before { color: variables.$menu-icon; } @@ -658,7 +651,7 @@ div#wp-responsive-toggle a:before { background: variables.$menu-submenu-background; } -.wp-responsive-open #wpadminbar #wp-admin-bar-menu-toggle .ab-icon:before { +.wp-responsive-open #wpadminbar #wp-admin-bar-menu-toggle .ab-icon::before { color: variables.$menu-icon; } @@ -673,6 +666,7 @@ div#wp-responsive-toggle a:before { } /* Customizer */ +/* stylelint-disable-next-line no-duplicate-selectors -- This file is split in sections and contains duplicate selectors based on the sections. */ .wp-core-ui { #customize-controls .control-section:hover > .accordion-section-title, #customize-controls .control-section .accordion-section-title:hover, @@ -708,11 +702,11 @@ div#wp-responsive-toggle a:before { color: variables.$link; } - .customize-screen-options-toggle:focus:before, - #customize-controls .customize-info .customize-help-toggle:focus:before, - &.wp-customizer button:focus .toggle-indicator:before, - .menu-item-bar .item-delete:focus:before, - #available-menu-items .item-add:focus:before, + .customize-screen-options-toggle:focus::before, + #customize-controls .customize-info .customize-help-toggle:focus::before, + &.wp-customizer button:focus .toggle-indicator::before, + .menu-item-bar .item-delete:focus::before, + #available-menu-items .item-add:focus::before, #customize-save-button-wrapper .save:focus, #publish-settings:focus { box-shadow: @@ -732,7 +726,7 @@ div#wp-responsive-toggle a:before { color: variables.$link; } - .control-panel-themes .theme-section .customize-themes-section-title.selected:after { + .control-panel-themes .theme-section .customize-themes-section-title.selected::after { background: variables.$button-color; } @@ -740,14 +734,14 @@ div#wp-responsive-toggle a:before { color: variables.$link; } - #customize-theme-controls .control-section:hover > .accordion-section-title:after, - #customize-theme-controls .control-section .accordion-section-title:hover:after, - #customize-theme-controls .control-section.open .accordion-section-title:after, - #customize-theme-controls .control-section .accordion-section-title:focus:after, - #customize-outer-theme-controls .control-section:hover > .accordion-section-title:after, - #customize-outer-theme-controls .control-section .accordion-section-title:hover:after, - #customize-outer-theme-controls .control-section.open .accordion-section-title:after, - #customize-outer-theme-controls .control-section .accordion-section-title:focus:after { + #customize-theme-controls .control-section:hover > .accordion-section-title::after, + #customize-theme-controls .control-section .accordion-section-title:hover::after, + #customize-theme-controls .control-section.open .accordion-section-title::after, + #customize-theme-controls .control-section .accordion-section-title:focus::after, + #customize-outer-theme-controls .control-section:hover > .accordion-section-title::after, + #customize-outer-theme-controls .control-section .accordion-section-title:hover::after, + #customize-outer-theme-controls .control-section.open .accordion-section-title::after, + #customize-outer-theme-controls .control-section .accordion-section-title:focus::after { color: variables.$link; } @@ -764,8 +758,8 @@ div#wp-responsive-toggle a:before { border-bottom-color: variables.$button-color; } - .wp-full-overlay-footer .devices button:hover:before, - .wp-full-overlay-footer .devices button:focus:before { + .wp-full-overlay-footer .devices button:hover::before, + .wp-full-overlay-footer .devices button:focus::before { color: variables.$button-color; } @@ -783,10 +777,10 @@ div#wp-responsive-toggle a:before { &.wp-customizer .theme-overlay .theme-header .close:focus, &.wp-customizer .theme-overlay .theme-header .close:hover, - &.wp-customizer .theme-overlay .theme-header .right:focus, - &.wp-customizer .theme-overlay .theme-header .right:hover, - &.wp-customizer .theme-overlay .theme-header .left:focus, - &.wp-customizer .theme-overlay .theme-header .left:hover { + &.wp-customizer .theme-overlay .theme-header .right:focus:not(.disabled), + &.wp-customizer .theme-overlay .theme-header .right:hover:not(.disabled), + &.wp-customizer .theme-overlay .theme-header .left:focus:not(.disabled), + &.wp-customizer .theme-overlay .theme-header .left:hover:not(.disabled) { border-bottom-color: variables.$button-color; color: variables.$link; } diff --git a/src/wp-admin/css/colors/_mixins.scss b/src/wp-admin/css/colors/_mixins.scss index 9575f1f2d623b..cd8bef2a02c76 100644 --- a/src/wp-admin/css/colors/_mixins.scss +++ b/src/wp-admin/css/colors/_mixins.scss @@ -1,5 +1,5 @@ -@use 'sass:color'; -@use 'tokens'; +@use "sass:color"; +@use "tokens"; /* * Button mixin - creates a primary button effect. @@ -36,11 +36,11 @@ } &:disabled, + &[aria-disabled="true"], &.disabled { background: tokens.$gray-100; border-color: transparent; color: tokens.$gray-600; - cursor: not-allowed; } &.active, @@ -85,11 +85,11 @@ } &:disabled, + &[aria-disabled="true"], &.disabled { background: transparent; border-color: tokens.$gray-300; color: tokens.$gray-600; - cursor: not-allowed; } } @@ -123,10 +123,10 @@ } &:disabled, + &[aria-disabled="true"], &.disabled { background: transparent; border-color: tokens.$gray-400; color: tokens.$gray-600; - cursor: not-allowed; } } diff --git a/src/wp-admin/css/colors/_tokens.scss b/src/wp-admin/css/colors/_tokens.scss index c918ee0e5f256..d36ed1398d3c0 100644 --- a/src/wp-admin/css/colors/_tokens.scss +++ b/src/wp-admin/css/colors/_tokens.scss @@ -16,11 +16,11 @@ // // ========================================================================== - -// -------------------------------------------------------------------------- -// Grid Units (Spacing) -// -------------------------------------------------------------------------- -// Based on 4px base unit. Use for padding, margin, and gap values. +/** + * Grid Units (Spacing) + * + * Based on 4px base unit. Use for padding, margin, and gap values. + */ $grid-unit-05: 4px; // Scales/grid unit 05 $grid-unit-10: 8px; // Scales/grid unit 10 @@ -32,10 +32,9 @@ $grid-unit-50: 40px; // Scales/grid unit 50 $grid-unit-60: 48px; // Scales/grid unit 60 $grid-unit-70: 56px; // Scales/grid unit 70 - -// -------------------------------------------------------------------------- -// Border Radius -// -------------------------------------------------------------------------- +/** + * Border Radius + */ $radius-xs: 1px; // radius-xs $radius-s: 2px; // radius-s - Buttons, inputs @@ -44,29 +43,29 @@ $radius-l: 8px; // radius-l - Cards, dashboard widgets $radius-30: 12px; // Radius 30 $radius-full: 9999px; // radius-full - Pills, avatars, circles - -// -------------------------------------------------------------------------- -// Gray Scale -// -------------------------------------------------------------------------- -// Neutral colors for backgrounds, borders, and text. +/** + * Gray Scale + * + * Neutral colors for backgrounds, borders, and text. + */ $gray-100: #f0f0f0; // Scales/Grays/gray-100 - Page background, disabled inputs $gray-200: #e0e0e0; // Scales/Grays/gray-200 -$gray-300: #dddddd; // Scales/Grays/gray-300 -$gray-400: #cccccc; // Scales/Grays/gray-400 - Disabled borders +$gray-300: #ddd; // Scales/Grays/gray-300 +$gray-400: #ccc; // Scales/Grays/gray-400 - Disabled borders $gray-600: #949494; // Scales/Grays/gray-600 - Input borders, disabled text $gray-700: #757575; // Scales/Grays/gray-700 $gray-800: #2f2f2f; // Scales/Grays/gray-800 $gray-900: #1e1e1e; // Scales/Grays/gray-900 - Primary text -$white: #ffffff; // Scales/Black & White/white +$white: #fff; // Scales/Black & White/white - -// -------------------------------------------------------------------------- -// Theme Colors (Static reference values) -// -------------------------------------------------------------------------- -// For actual theme color usage, use var(--wp-admin-theme-color) instead. -// These are provided for reference and for contexts where CSS vars aren't available. +/** + * Theme Colors (Static reference values) + * + * For actual theme color usage, use var(--wp-admin-theme-color) instead. + * These are provided for reference and for contexts where CSS vars aren't available. + */ $theme-reference: #3858e9; // Scales/Theme/theme (modern scheme) $theme-darker-10-reference: #2145e6; // Scales/Theme/theme-darker-10 @@ -76,12 +75,12 @@ $theme-alpha-08: rgba(56, 88, 233, 0.08); // Scales/Theme/theme-alpha-08 (8% opa $brand-9: #4465db; // Scales/brand-9 - Focus ring color (static, not theme-dependent) - -// -------------------------------------------------------------------------- -// Semantic Colors -// -------------------------------------------------------------------------- -// Use these for notices, alerts, and status indicators. -// These are intentionally NOT theme-dependent for consistency. +/** + * Semantic Colors + * + * Use these for notices, alerts, and status indicators. + * These are intentionally NOT theme-dependent for consistency. + */ $alert-yellow: #f0b849; // Scales/Yellow/alert-yellow - Warnings $alert-green: #4ab866; // Scales/Green/alert-green - Success @@ -95,20 +94,18 @@ $alert-red-bg: #fcf0f0; // Error notice background $synced-color: #7a00df; // Scales/Purple/--wp-block-synced-color - -// -------------------------------------------------------------------------- -// Text Colors -// -------------------------------------------------------------------------- +/** + * Text Colors + */ $text-primary: $gray-900; // Primary text color $text-secondary: $gray-700; // Secondary text -$text-tertiary: #5d5d5d; // Alias/text/text-tertiary - Placeholder, hints +$text-tertiary: #5d5d5d; // Alias/text/text-tertiary - Placeholder, hints $text-disabled: $gray-600; // Disabled text - -// -------------------------------------------------------------------------- -// Component Tokens -// -------------------------------------------------------------------------- +/** + * Component Tokens + */ // Inputs $input-bg: $white; // Alias/bg/bg-input @@ -154,10 +151,9 @@ $card-padding-lg-v: $grid-unit-30; // 24px - Large cards vertical $page-padding-large: 48px; // Alias/page-large $page-padding-small: 24px; // Alias/page-small - -// -------------------------------------------------------------------------- -// Typography Scale -// -------------------------------------------------------------------------- +/** + * Typography Scale + */ // Font Sizes $font-size-xs: 11px; // xs - Small labels, button small @@ -166,42 +162,35 @@ $font-size-m: 13px; // m - Base body text, buttons $font-size-l: 15px; // l - Body large, heading large $font-size-xl: 20px; // xl - Heading XL -// Line Heights -$line-height-xs: 16px; // xs -$line-height-s: 20px; // s - Most UI elements -$line-height-m: 24px; // m - Body large - -// -------------------------------------------------------------------------- -// Elevation (Box Shadows) -// -------------------------------------------------------------------------- +/** + * Elevation (Box Shadows) + */ $elevation-xs: - 0 4px 4px rgba(0, 0, 0, 0.01), - 0 3px 3px rgba(0, 0, 0, 0.02), - 0 1px 2px rgba(0, 0, 0, 0.02), - 0 1px 1px rgba(0, 0, 0, 0.03); + 0 4px 4px rgba(0, 0, 0, 0.01), + 0 3px 3px rgba(0, 0, 0, 0.02), + 0 1px 2px rgba(0, 0, 0, 0.02), + 0 1px 1px rgba(0, 0, 0, 0.03); $elevation-s: - 0 8px 8px rgba(0, 0, 0, 0.02), - 0 1px 2px rgba(0, 0, 0, 0.05); + 0 8px 8px rgba(0, 0, 0, 0.02), + 0 1px 2px rgba(0, 0, 0, 0.05); $elevation-m: - 0 16px 16px rgba(0, 0, 0, 0.02), - 0 4px 5px rgba(0, 0, 0, 0.03), - 0 2px 3px rgba(0, 0, 0, 0.05); + 0 16px 16px rgba(0, 0, 0, 0.02), + 0 4px 5px rgba(0, 0, 0, 0.03), + 0 2px 3px rgba(0, 0, 0, 0.05); $elevation-l: - 0 50px 43px rgba(0, 0, 0, 0.02), - 0 30px 36px rgba(0, 0, 0, 0.04), - 0 15px 27px rgba(0, 0, 0, 0.07), - 0 5px 15px rgba(0, 0, 0, 0.08); + 0 50px 43px rgba(0, 0, 0, 0.02), + 0 30px 36px rgba(0, 0, 0, 0.04), + 0 15px 27px rgba(0, 0, 0, 0.07), + 0 5px 15px rgba(0, 0, 0, 0.08); - -// -------------------------------------------------------------------------- -// Layout -// -------------------------------------------------------------------------- +/** + * Layout + */ $modal-width-small: 384px; // Layout/Modal small $modal-width-medium: 512px; // Layout/Modal medium $modal-width-large: 840px; // Layout/Modal large - diff --git a/src/wp-admin/css/colors/_variables.scss b/src/wp-admin/css/colors/_variables.scss index d37c2b1392f00..6c0c15f4bb3ab 100644 --- a/src/wp-admin/css/colors/_variables.scss +++ b/src/wp-admin/css/colors/_variables.scss @@ -15,7 +15,6 @@ $icon-color: hsl(color.channel($base-color, "hue", $space: hsl), 7%, 95%) !defau $highlight-color: #0073aa !default; $notification-color: #d54e21 !default; - // global $body-background: $gray-100 !default; @@ -42,7 +41,7 @@ $menu-current-text: $menu-highlight-text !default; $menu-current-icon: $menu-highlight-icon !default; $menu-current-background: $menu-highlight-background !default; -$menu-submenu-text: color.mix( $base-color, $text-color, 30% ) !default; +$menu-submenu-text: color.mix($base-color, $text-color, 30%) !default; $menu-submenu-background: color.adjust($base-color, $lightness: -7%) !default; $menu-submenu-background-alt: color.adjust(color.adjust($menu-background, $lightness: 7%), $saturation: -7%) !default; @@ -64,9 +63,9 @@ $adminbar-input-background: color.adjust($menu-background, $lightness: 7%) !defa $adminbar-recovery-exit-text: $menu-bubble-text !default; $adminbar-recovery-exit-background: $menu-bubble-background !default; -$adminbar-recovery-exit-background-alt: color.mix(black, $adminbar-recovery-exit-background, 10%) !default; +$adminbar-recovery-exit-background-alt: color.mix(#000, $adminbar-recovery-exit-background, 10%) !default; -$menu-customizer-text: color.mix( $base-color, $text-color, 40% ) !default; +$menu-customizer-text: color.mix($base-color, $text-color, 40%) !default; // Dashboard Colors diff --git a/src/wp-admin/css/colors/sunrise/colors.scss b/src/wp-admin/css/colors/sunrise/colors.scss index 3a00c91778d79..a1ef34054906e 100644 --- a/src/wp-admin/css/colors/sunrise/colors.scss +++ b/src/wp-admin/css/colors/sunrise/colors.scss @@ -1,10 +1,10 @@ @use "../_admin.scss" with ( - $scheme-name: "sunrise", - $base-color: #8a312d, - $highlight-color: #ad631e, - $notification-color: #ccaf0b, - $menu-highlight-text: #fff, - $menu-highlight-icon: #fff, - $menu-bubble-text: #1e1e1e, - $menu-submenu-focus-text: #fff + $scheme-name: "sunrise", + $base-color: #8a312d, + $highlight-color: #ad631e, + $notification-color: #ccaf0b, + $menu-highlight-text: #fff, + $menu-highlight-icon: #fff, + $menu-bubble-text: #1e1e1e, + $menu-submenu-focus-text: #fff ); diff --git a/src/wp-admin/css/common.css b/src/wp-admin/css/common.css index 980702d31fb80..10112851eda1f 100644 --- a/src/wp-admin/css/common.css +++ b/src/wp-admin/css/common.css @@ -111,7 +111,7 @@ } /* modern clearfix */ -.wp-clearfix:after { +.wp-clearfix::after { content: ""; display: table; clear: both; @@ -155,7 +155,7 @@ font-weight: 600; padding: 15px 23px 14px; /* Background and color set to prevent false positives in automated accessibility tests. */ - background: #ffffff; + background: #fff; color: var(--wp-admin-theme-color, #3858e9); z-index: 100000; line-height: normal; @@ -226,7 +226,7 @@ body { color: #3c434a; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 13px; - line-height: 1.4em; + line-height: 1.4; min-width: 600px; } @@ -261,7 +261,7 @@ td { a { color: #2271b1; transition-property: border, background, color; - transition-duration: .05s; + transition-duration: 0.05s; transition-timing-function: ease-in-out; } @@ -303,10 +303,10 @@ q { quotes: none; } -blockquote:before, -blockquote:after, -q:before, -q:after { +blockquote::before, +blockquote::after, +q::before, +q::after { content: ""; content: none; } @@ -340,7 +340,7 @@ h6 { h1 { color: #1d2327; font-size: 2em; - margin: .67em 0; + margin: 0.67em 0; } h2, @@ -442,7 +442,7 @@ code { .subsubsub a { line-height: 2; - padding: .2em; + padding: 0.2em; text-decoration: none; } @@ -481,6 +481,10 @@ code { text-decoration: none; } +.widefat .column-comment a:not(.row-actions a) { + text-decoration: underline; +} + .widefat td, .widefat th { padding: 8px 10px; @@ -511,7 +515,7 @@ code { .widefat td ol, .widefat td ul { font-size: 13px; - line-height: 1.5em; + line-height: 1.5; } .widefat th, @@ -519,7 +523,7 @@ code { .widefat thead td, .widefat tfoot td { text-align: left; - line-height: 1.3em; + line-height: 1.3; } .widefat th:not(tbody th), @@ -582,7 +586,7 @@ code { .js-update-details-toggle[aria-expanded="true"] .dashicons::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } .no-js .widefat thead .check-column input, @@ -715,6 +719,7 @@ div#widgets-right .widget-top:hover, background-color: #c5d9ed; } +/* stylelint-disable-next-line selector-class-pattern -- The class ac_match comes from jquery.suggest and can't be changed. */ .ac_match, .subsubsub a.current { color: #000; @@ -732,7 +737,6 @@ ul.striped > :nth-child(odd), } /* Helper classes for plugins to leverage the active WordPress color scheme */ - .highlight { background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); color: #3c434a; @@ -742,6 +746,7 @@ ul.striped > :nth-child(odd), color: #fff; background-color: #2c3338; } + .wp-ui-text-primary { color: #2c3338; } @@ -750,6 +755,7 @@ ul.striped > :nth-child(odd), color: #fff; background-color: #2271b1; } + .wp-ui-text-highlight { color: #2271b1; } @@ -758,6 +764,7 @@ ul.striped > :nth-child(odd), color: #fff; background-color: #d63638; } + .wp-ui-text-notification { color: #d63638; } @@ -772,7 +779,7 @@ img.emoji { border: none !important; height: 1em !important; width: 1em !important; - margin: 0 .07em !important; + margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; @@ -793,12 +800,13 @@ img.emoji { .menu-item-handle, .checkbox, .side-info, +/* stylelint-disable-next-line selector-id-pattern -- The ID selector rich_editing can't be changed because of backward compatibility reasons. */ #your-profile #rich_editing, .widefat thead th, .widefat thead td, .widefat tfoot th, .widefat tfoot td { - line-height: 1.4em; + line-height: 1.4; } .widget .widget-top, @@ -822,16 +830,16 @@ img.emoji { } /* @todo can we combine these into a class or use an existing dashicon one? */ -.welcome-panel .welcome-panel-close:before, -.tagchecklist .ntdelbutton .remove-tag-icon:before, -#bulk-titles .ntdelbutton:before, -.notice-dismiss:before { +.welcome-panel .welcome-panel-close::before, +.tagchecklist .ntdelbutton .remove-tag-icon::before, +#bulk-titles .ntdelbutton::before, +.notice-dismiss::before { background: none; color: #1e1e1e; content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; display: block; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; height: 1em; text-align: center; width: 1em; @@ -839,11 +847,11 @@ img.emoji { -moz-osx-font-smoothing: grayscale; } -.welcome-panel .welcome-panel-close:before { +.welcome-panel .welcome-panel-close::before { margin: 0; } -.tagchecklist .ntdelbutton .remove-tag-icon:before { +.tagchecklist .ntdelbutton .remove-tag-icon::before { margin-left: 2px; border-radius: 50%; color: var(--wp-admin-theme-color, #3858e9); @@ -855,24 +863,21 @@ img.emoji { outline: 0; } -.tagchecklist .ntdelbutton:hover .remove-tag-icon:before, -.tagchecklist .ntdelbutton:focus .remove-tag-icon:before, -#bulk-titles .ntdelbutton:hover:before, -#bulk-titles .ntdelbutton:focus:before { +.tagchecklist .ntdelbutton:hover .remove-tag-icon::before, +.tagchecklist .ntdelbutton:focus .remove-tag-icon::before, +#bulk-titles .ntdelbutton:hover::before, +#bulk-titles .ntdelbutton:focus::before { color: #d63638; } -.tagchecklist .ntdelbutton:focus .remove-tag-icon:before { +.tagchecklist .ntdelbutton:focus .remove-tag-icon::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; } -.key-labels label { - line-height: 24px; -} - -strong, b { +strong, +b { font-weight: 600; } @@ -914,6 +919,7 @@ hr { #nav-menu-footer .menu-delete, #delete-link a.delete, a#remove-post-thumbnail, +/* stylelint-disable-next-line selector-class-pattern -- The class privacy_requests can't be changed because of backward compatibility reasons. */ .privacy_requests .remove-personal-data .remove-personal-data-handle { color: #b32d2e; } @@ -933,14 +939,15 @@ span.required, #nav-menu-footer .menu-delete:hover, #delete-link a.delete:hover, a#remove-post-thumbnail:hover, +/* stylelint-disable-next-line selector-class-pattern -- The class privacy_requests can't be changed because of backward compatibility reasons. */ .privacy_requests .remove-personal-data .remove-personal-data-handle:hover { color: #b32d2e; border: none; } .application-password-display .success { - color: #007017; - margin-left: 0.5rem; + color: #007017; + margin-left: 0.5rem; } /*------------------------------------------------------------------------------ @@ -1115,23 +1122,20 @@ th.action-links { float: right; display: flex; align-items: center; - column-gap: .5rem; + column-gap: 0.5rem; } .wp-filter .search-form input[type="search"] { width: 280px; max-width: 100%; + min-height: 32px; + padding: 0 8px; } .wp-filter .search-form select { margin: 0; } -.wp-filter .search-form input[type="search"] { - min-height: 32px; - padding: 0 8px; -} - .wp-filter .search-form select, .wp-filter .filter-items select { min-height: 32px; @@ -1171,21 +1175,21 @@ th.action-links { box-shadow: none; } -.wp-filter .drawer-toggle:before { +.wp-filter .drawer-toggle::before { content: "\f111"; - content: "\f111" / ''; + content: "\f111" / ""; margin: 0 5px 0 0; color: #646970; - font: normal 16px/1 dashicons; + font: 400 16px/1 dashicons; vertical-align: text-bottom; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .wp-filter .button.drawer-toggle:hover, -.wp-filter .drawer-toggle:hover:before, +.wp-filter .drawer-toggle:hover::before, .wp-filter .button.drawer-toggle:focus, -.wp-filter .drawer-toggle:focus:before { +.wp-filter .drawer-toggle:focus::before { background-color: transparent; color: var(--wp-admin-theme-color); } @@ -1205,7 +1209,7 @@ th.action-links { transform: none; } -.wp-filter .drawer-toggle.current:before { +.wp-filter .drawer-toggle.current::before { color: #fff; } @@ -1252,7 +1256,7 @@ th.action-links { background: var(--wp-admin-theme-color); } -.show-filters .wp-filter .drawer-toggle:before { +.show-filters .wp-filter .drawer-toggle::before { color: #fff; } @@ -1429,6 +1433,7 @@ th.action-links { position: relative; max-width: 100%; } + .wp-filter .search-form { margin: 11px 0; flex-wrap: wrap; @@ -1558,8 +1563,8 @@ div.updated a:focus { border-radius: 2px; } -.notice-dismiss:hover:before, -.notice-dismiss:active:before { +.notice-dismiss:hover::before, +.notice-dismiss:active::before { color: #1e1e1e; opacity: 0.7; } @@ -1570,7 +1575,7 @@ div.updated a:focus { outline: 2px solid transparent; } -.notice-dismiss:focus:before { +.notice-dismiss:focus::before { color: #1e1e1e; } @@ -1614,12 +1619,12 @@ div.error.notice-alt { background-color: #fff; } -#plugin-information-footer .update-now:not(.button-disabled):before { +#plugin-information-footer .update-now:not(.button-disabled)::before { color: #d63638; content: "\f463"; - content: "\f463" / ''; + content: "\f463" / ""; display: inline-block; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; margin: -3px 5px 0 -2px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -1627,21 +1632,21 @@ div.error.notice-alt { } #plugin-information-footer .notice { - margin-top: -5px; -} - -.update-message p:before, -.updating-message p:before, -.updated-message p:before, -.import-php .updating-message:before, -.button.updating-message:before, -.button.updated-message:before, -.button.installed:before, -.button.installing:before, -.button.activating-message:before, -.button.activated-message:before { + margin-top: -5px; +} + +.update-message p::before, +.updating-message p::before, +.updated-message p::before, +.import-php .updating-message::before, +.button.updating-message::before, +.button.updated-message::before, +.button.installed::before, +.button.installing::before, +.button.activating-message::before, +.button.activated-message::before { display: inline-block; - font: normal 20px/1 'dashicons'; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; vertical-align: top; @@ -1672,34 +1677,34 @@ div.error.notice-alt { } /* Update icon. */ -.update-message p:before, -.updating-message p:before, -.import-php .updating-message:before, -.button.updating-message:before, -.button.installing:before, -.button.activating-message:before { +.update-message p::before, +.updating-message p::before, +.import-php .updating-message::before, +.button.updating-message::before, +.button.installing::before, +.button.activating-message::before { color: #d63638; content: "\f463"; - content: "\f463" / ''; + content: "\f463" / ""; } /* Spins the update icon. */ -.updating-message p:before, -.import-php .updating-message:before, -.button.updating-message:before, -.button.installing:before, -.button.activating-message:before, +.updating-message p::before, +.import-php .updating-message::before, +.button.updating-message::before, +.button.installing::before, +.button.activating-message::before, .plugins .column-auto-updates .dashicons-update.spin, .theme-overlay .theme-autoupdate .dashicons-update.spin { animation: rotation 2s infinite linear; } @media (prefers-reduced-motion: reduce) { - .updating-message p:before, - .import-php .updating-message:before, - .button.updating-message:before, - .button.installing:before, - .button.activating-message:before, + .updating-message p::before, + .import-php .updating-message::before, + .button.updating-message::before, + .button.installing::before, + .button.activating-message::before, .plugins .column-auto-updates .dashicons-update.spin, .theme-overlay .theme-autoupdate .dashicons-update.spin { animation: none; @@ -1711,28 +1716,28 @@ div.error.notice-alt { } /* Updated icon (check mark). */ -.updated-message p:before, -.installed p:before, -.button.updated-message:before, -.button.activated-message:before { +.updated-message p::before, +.installed p::before, +.button.updated-message::before, +.button.activated-message::before { color: #68de7c; content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; } /* Error icon. */ -.update-message.notice-error p:before { +.update-message.notice-error p::before { color: #d63638; content: "\f534"; - content: "\f534" / ''; + content: "\f534" / ""; } -.wrap .notice p:before, -.import-php .updating-message:before { +.wrap .notice p::before, +.import-php .updating-message::before { margin-right: 6px; } -.import-php .updating-message:before { +.import-php .updating-message::before { vertical-align: bottom; } @@ -1774,7 +1779,7 @@ form.upgrade .hint { } h2.wp-current-version { - margin-bottom: .3em; + margin-bottom: 0.3em; } p.update-last-checked { @@ -1798,12 +1803,12 @@ p.auto-update-status { margin-left: 2em; } -.button.updating-message:before, -.button.updated-message:before, -.button.installed:before, -.button.installing:before, -.button.activated-message:before, -.button.activating-message:before { +.button.updating-message::before, +.button.updated-message::before, +.button.installed::before, +.button.installing::before, +.button.activated-message::before, +.button.activating-message::before { margin: 0 5px 0 -2px; line-height: 1.9; /* 38px (20px * 1.9) - matches button */ vertical-align: top; @@ -1818,39 +1823,38 @@ p.auto-update-status { margin-bottom: 4px; } -#plugin-information-footer .button.installed:before, -#plugin-information-footer .button.installing:before, -#plugin-information-footer .button.updating-message:before, -#plugin-information-footer .button.updated-message:before, -#plugin-information-footer .button.activated-message:before, -#plugin-information-footer .button.activating-message:before { +#plugin-information-footer .button.installed::before, +#plugin-information-footer .button.installing::before, +#plugin-information-footer .button.updating-message::before, +#plugin-information-footer .button.updated-message::before, +#plugin-information-footer .button.activated-message::before, +#plugin-information-footer .button.activating-message::before { margin: 0 5px 0 -2px; line-height: 1.9; /* 38px (20px * 1.9) - matches button */ vertical-align: top; } -#plugin-information-footer .button.update-now.updating-message:before { +#plugin-information-footer .button.update-now.updating-message::before { margin: 0 5px 0 -2px; } -.button-primary.updating-message:before, -.button-primary.activating-message:before { +.button-primary.updating-message::before, +.button-primary.activating-message::before { color: #fff; } -.button-primary.updated-message:before, -.button-primary.activated-message:before { +.button-primary.updated-message::before, +.button-primary.activated-message::before { color: #9ec2e6; } .button.updated-message, .button.activated-message { transition-property: border, background, color; - transition-duration: .05s; + transition-duration: 0.05s; transition-timing-function: ease-in-out; } - /* @todo: this does not need its own section anymore */ /*------------------------------------------------------------------------------ 6.0 - Admin Header @@ -1875,6 +1879,7 @@ p.auto-update-status { #contextual-help-wrap { overflow: auto; margin-left: 0; + padding: 0; } #screen-meta-links { @@ -1934,11 +1939,11 @@ p.auto-update-status { transform: none; } -#screen-meta-links .show-settings:after { +#screen-meta-links .show-settings::after { right: 0; content: "\f140"; - content: "\f140" / ''; - font: normal 20px/1.5 dashicons; /* line-height 1.5 = 30px to match compact button */ + content: "\f140" / ""; + font: 400 20px/1.5 dashicons; /* line-height 1.5 = 30px to match compact button */ display: inline-block; padding: 0 5px 0 0; vertical-align: top; @@ -1947,22 +1952,25 @@ p.auto-update-status { text-decoration: none; } -#screen-meta-links .screen-meta-active:after { +#screen-meta-links .screen-meta-active::after { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } /* end screen options and help tabs */ +/* This class appears to be unused in Core. */ .toggle-arrow { background-repeat: no-repeat; background-position: top left; background-color: transparent; height: 22px; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- The toggle-arrow class appears to be unused; it is kept here only for potential backward compatibility issues. */ line-height: 22px; display: block; } +/* This class appears to be unused in Core. */ .toggle-arrow-active { background-position: bottom left; } @@ -1982,19 +1990,25 @@ p.auto-update-status { line-height: 2.35; } +.additional-settings-prefs { + margin-top: 14px; +} + +/* This ID appears to be unused in Core. */ #number-of-columns { display: inline-block; vertical-align: middle; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- The number-of-columns ID appears to be unused; it is kept here only for potential backward compatibility issues. */ line-height: 30px; } -.metabox-prefs input[type=checkbox] { +.metabox-prefs input[type="checkbox"] { margin-top: 0; margin-right: 6px; } .metabox-prefs label input, -.metabox-prefs label input[type=checkbox] { +.metabox-prefs label input[type="checkbox"] { margin: -4px 5px 0 0; } @@ -2036,10 +2050,6 @@ p.auto-update-status { 6.2 - Help Menu ------------------------------------------------------------------------------*/ -#contextual-help-wrap { - padding: 0; -} - #contextual-help-columns { position: relative; } @@ -2098,7 +2108,7 @@ p.auto-update-status { padding: 0; margin: 0 -1px 0 0; border-left: 2px solid var(--wp-admin-theme-color); - background: color-mix(in srgb, var(--wp-admin-theme-color) 8%, white); + background: color-mix(in srgb, var(--wp-admin-theme-color) 8%, #fff); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.02), 0 1px 0 rgba(0, 0, 0, 0.02); } @@ -2144,6 +2154,7 @@ html.wp-toolbar { -ms-overflow-style: scrollbar; /* See ticket #48545 */ } +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ .widefat th, .widefat td { color: #50575e; @@ -2279,12 +2290,17 @@ html.wp-toolbar { width: 1.62rem; } +.js.meta-box-reordering-disabled .postbox .handle-order-higher, +.js.meta-box-reordering-disabled .postbox .handle-order-lower { + display: none; +} + /* Post box order buttons in the block editor meta boxes area. */ .edit-post-meta-boxes-area .postbox .handle-order-higher, .edit-post-meta-boxes-area .postbox .handle-order-lower { width: 44px; height: 44px; - color: #1d2327 + color: #1d2327; } .postbox .handle-order-higher[aria-disabled="true"], @@ -2321,6 +2337,8 @@ html.wp-toolbar { padding: 0 12px 12px; line-height: 1.4; font-size: 13px; + margin: 11px 0; + position: relative; } .stuffbox .inside { @@ -2330,11 +2348,6 @@ html.wp-toolbar { margin-top: 0; } -.postbox .inside { - margin: 11px 0; - position: relative; -} - .postbox .inside > p:last-child, .rss-widget ul li:last-child { margin-bottom: 1px !important; @@ -2362,6 +2375,7 @@ html.wp-toolbar { } /* @todo: what is this doing here */ +/* stylelint-disable-next-line selector-id-pattern -- The ID selector dashboard_right_now can't be changed because of backward compatibility reasons. */ #dashboard_right_now .versions .b, #post-status-display, #post-visibility-display, @@ -2372,7 +2386,6 @@ html.wp-toolbar { .plugins .name, #pass-strength-result.strong, #pass-strength-result.short, -#ed_reply_toolbar #ed_reply_strong, .item-controls .item-order a, .feature-filter .feature-name, #comment-status-display { @@ -2464,7 +2477,7 @@ h1.nav-tab-wrapper, /* Back-compat for pre-4.4 */ } /* Back-compat for plugins. Deprecated. Use .wp-clearfix instead. */ -.nav-tab-wrapper:not(.wp-clearfix):after { +.nav-tab-wrapper:not(.wp-clearfix)::after { content: ""; display: table; clear: both; @@ -2496,13 +2509,16 @@ h1.nav-tab-wrapper, /* Back-compat for pre-4.4 */ #template > div { margin-right: 16em; } + #template .notice { margin-top: 1em; margin-right: 3%; } + #template .notice p { width: auto; } + #template .submit .spinner { float: none; vertical-align: top; @@ -2553,7 +2569,7 @@ h1.nav-tab-wrapper, /* Back-compat for pre-4.4 */ position: absolute; right: 10px; left: auto; - color: #787c82; + color: #50575e; border-radius: 50px; top: 50%; transform: translateY(-50%); @@ -2597,6 +2613,7 @@ table .column-rating { } /* Scrollbar fix for bulk upgrade iframe */ +/* stylelint-disable-next-line no-duplicate-selectors -- For historical reasons this file is split in sections and contains duplicate selectors based on the sections. */ body.iframe { height: 98%; } @@ -2605,6 +2622,7 @@ body.iframe { .lp-show-latest p { display: none; } + .lp-show-latest p:last-child, .lp-show-latest .lp-error p { display: block; @@ -2673,7 +2691,7 @@ body.iframe { color: #000; font-size: 14px; font-weight: 400; - margin-bottom: .2em; + margin-bottom: 0.2em; } .importer-action { @@ -2771,6 +2789,7 @@ div.star-holder .star-rating { .star-rating { white-space: nowrap; } + .star-rating .star { display: inline-block; width: 20px; @@ -2783,28 +2802,28 @@ div.star-holder .star-rating { font-weight: 400; font-style: normal; vertical-align: top; - transition: color .1s ease-in; + transition: color 0.1s ease-in; text-align: center; color: #dba617; } -.star-rating .star-full:before { +.star-rating .star-full::before { content: "\f155"; - content: "\f155" / ''; + content: "\f155" / ""; } -.star-rating .star-half:before { +.star-rating .star-half::before { content: "\f459"; - content: "\f459" / ''; + content: "\f459" / ""; } .rtl .star-rating .star-half { transform: rotateY(180deg); } -.star-rating .star-empty:before { +.star-rating .star-empty::before { content: "\f154"; - content: "\f154" / ''; + content: "\f154" / ""; } div.action-links { @@ -2940,12 +2959,12 @@ div.action-links { left: 0; min-height: 100%; /* Height of title + tabs + install now */ - min-height: calc( 100% - 152px ); + min-height: calc(100% - 152px); } #plugin-information-content.with-banner { /* Height of banner + tabs + install now */ - min-height: calc( 100% - 346px ); + min-height: calc(100% - 346px); } #section-holder { @@ -3050,12 +3069,6 @@ div.action-links { vertical-align: middle; } -#plugin-information .fyi ul.contributors li { - display: inline-block; - margin-right: 8px; - vertical-align: middle; -} - #plugin-information .fyi ul.contributors li img { vertical-align: middle; margin-right: 4px; @@ -3230,11 +3243,12 @@ div.action-links { } /* Thickbox for the Plugin details modal. */ +/* stylelint-disable selector-id-pattern -- Many IDs used by Thickbox contain uppercase charqacters and can't be changed. */ #TB_window.plugin-details-modal { background: #fff; } -#TB_window.plugin-details-modal.thickbox-loading:before { +#TB_window.plugin-details-modal.thickbox-loading::before { content: ""; display: block; width: 20px; @@ -3251,8 +3265,7 @@ div.action-links { @media print, (min-resolution: 120dpi) { - - #TB_window.plugin-details-modal.thickbox-loading:before { + #TB_window.plugin-details-modal.thickbox-loading::before { background-image: url(../images/spinner-2x.gif); } } @@ -3289,10 +3302,10 @@ div.action-links { display: none; } -.plugin-details-modal #TB_closeWindowButton:after { +.plugin-details-modal #TB_closeWindowButton::after { content: "\f335"; - content: "\f335" / ''; - font: normal 32px/29px 'dashicons'; + content: "\f335" / ""; + font: 400 32px/29px dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -3304,6 +3317,7 @@ div.action-links { top: -30px; } } +/* stylelint-enable */ /* @todo: move this. */ img { @@ -3318,9 +3332,9 @@ img { .bulk-action-notice .toggle-indicator::before, .privacy-text-box .toggle-indicator::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; display: inline-block; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-decoration: none; @@ -3331,25 +3345,25 @@ img { .bulk-action-notice .bulk-action-errors-collapsed .toggle-indicator::before, .privacy-text-box.closed .toggle-indicator::before { content: "\f140"; - content: "\f140" / ''; + content: "\f140" / ""; } .postbox .handle-order-higher .order-higher-indicator::before { content: "\f343"; - content: "\f343" / ''; + content: "\f343" / ""; color: inherit; } .postbox .handle-order-lower .order-lower-indicator::before { content: "\f347"; - content: "\f347" / ''; + content: "\f347" / ""; color: inherit; } .postbox .handle-order-higher .order-higher-indicator::before, .postbox .handle-order-lower .order-lower-indicator::before { position: relative; - top: 0.11rem; + top: 0.11rem; width: 20px; height: 20px; } @@ -3357,9 +3371,6 @@ img { .postbox .handlediv .toggle-indicator::before { width: 20px; border-radius: 50%; -} - -.postbox .handlediv .toggle-indicator::before { position: relative; top: 0.05rem; text-indent: -1px; /* account for the dashicon glyph uneven horizontal alignment */ @@ -3370,9 +3381,10 @@ img { } .bulk-action-notice .toggle-indicator::before { + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- This line-height value is used for a dashicon. */ line-height: 16px; vertical-align: top; - color: #787c82; + color: #50575e; } .postbox .handle-order-higher:focus, @@ -3410,10 +3422,11 @@ img { } #template textarea, +/* stylelint-disable-next-line selector-class-pattern -- This class uses selectors that contain uppercase character in .CodeMirror external library. */ #template .CodeMirror { width: 100%; min-height: 60vh; - height: calc( 100vh - 295px ); + height: calc(100vh - 295px); border: 1px solid #dcdcde; box-sizing: border-box; } @@ -3429,6 +3442,7 @@ img { margin: 0; padding: 0; } + #templateside > ul { box-sizing: border-box; margin-top: 0; @@ -3440,10 +3454,12 @@ img { border: 1px solid #dcdcde; border-left: none; } + #templateside ul ul { padding-left: 12px; } -#templateside > ul > li > ul[role=group] { + +#templateside > ul > li > ul[role="group"] { padding-left: 0; } @@ -3464,14 +3480,17 @@ img { position: absolute; pointer-events: none; } -[role="treeitem"][aria-expanded="false"] > .folder-label .icon:after { + +[role="treeitem"][aria-expanded="false"] > .folder-label .icon::after { content: "\f139"; - content: "\f139" / ''; + content: "\f139" / ""; } -[role="treeitem"][aria-expanded="true"] > .folder-label .icon:after { + +[role="treeitem"][aria-expanded="true"] > .folder-label .icon::after { content: "\f140"; - content: "\f140" / ''; + content: "\f140" / ""; } + [role="treeitem"] .folder-label { display: block; padding: 3px 3px 3px 12px; @@ -3502,6 +3521,7 @@ img { margin: 0; position: relative; } + [role="treeitem"] li { position: relative; } @@ -3516,6 +3536,7 @@ img { top: -13px; bottom: 10px; } + .tree-folder > li::before { content: ""; position: absolute; @@ -3527,6 +3548,7 @@ img { width: 7px; border-bottom: 1px solid #c3c4c7; } + .tree-folder > li::after { content: ""; position: absolute; @@ -3541,6 +3563,7 @@ img { #templateside .current-file { margin: -4px 0 -2px; } + .tree-folder > .current-file::before { left: 4px; height: 15px; @@ -3548,6 +3571,7 @@ img { border-left: none; top: 3px; } + .tree-folder > .current-file::after { bottom: -4px; height: 7px; @@ -3582,6 +3606,7 @@ img { .fileedit-sub #plugin { max-width: 40%; } + .fileedit-sub .alignright { text-align: right; } @@ -3594,21 +3619,21 @@ img { margin-top: 1em; margin-bottom: 1em; } + #file-editor-linting-error > .notice { margin: 0; display: inline-block; } + #file-editor-linting-error > .notice > p { width: auto; } + #template .submit { margin-top: 1em; padding: 0; } -#template .submit input[type=submit][disabled] { - cursor: not-allowed; -} #templateside { float: right; width: 16em; @@ -3673,7 +3698,7 @@ img { .fileedit-sub { padding: 10px 0 8px; - line-height: 180%; + line-height: 1.8; } #file-editor-warning .file-editor-warning-content { @@ -3681,20 +3706,20 @@ img { } /* @todo: can we use a common class for these? */ -.nav-menus-php .item-edit:before, -.wp-customizer .control-section .accordion-section-title:after, -.wp-customizer .accordion-section-title:after, -.widget-top .widget-action .toggle-indicator:before { +.nav-menus-php .item-edit::before, +.wp-customizer .control-section .accordion-section-title::after, +.wp-customizer .accordion-section-title::after, +.widget-top .widget-action .toggle-indicator::before { content: "\f140"; - content: "\f140" / ''; - font: normal 20px/1 dashicons; + content: "\f140" / ""; + font: 400 20px/1 dashicons; display: block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-decoration: none; } -.widget-top .widget-action .toggle-indicator:before { +.widget-top .widget-action .toggle-indicator::before { padding: 1px 2px 1px 0; border-radius: 50%; } @@ -3724,18 +3749,18 @@ img { outline: 2px solid transparent; } -.widget-top .widget-action:focus .toggle-indicator:before { +.widget-top .widget-action:focus .toggle-indicator::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; } -#customize-info.open .accordion-section-title:after, -.nav-menus-php .menu-item-edit-active .item-edit:before, -.widget.open .widget-top .widget-action .toggle-indicator:before, -.widget.widget-in-question .widget-top .widget-action .toggle-indicator:before { +#customize-info.open .accordion-section-title::after, +.nav-menus-php .menu-item-edit-active .item-edit::before, +.widget.open .widget-top .widget-action .toggle-indicator::before, +.widget.widget-in-question .widget-top .widget-action .toggle-indicator::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } /*! @@ -3786,7 +3811,7 @@ img { cursor: pointer; } -.js .accordion-section-title:after { +.js .accordion-section-title::after { position: absolute; top: 12px; right: 10px; @@ -3798,8 +3823,8 @@ img { outline: 1px solid transparent; } -.accordion-section-title:hover:after, -.accordion-section-title:focus:after { +.accordion-section-title:hover::after, +.accordion-section-title:focus::after { border-color: #a7aaad transparent; /* Only visible in Windows High Contrast mode */ outline: 1px solid transparent; @@ -3809,7 +3834,7 @@ img { cursor: auto; } -.cannot-expand .accordion-section-title:after { +.cannot-expand .accordion-section-title::after { display: none; } @@ -3822,8 +3847,8 @@ img { background: #fff; } -.control-section .accordion-section-title:after, -.customize-pane-child .accordion-section-title:after { +.control-section .accordion-section-title::after, +.customize-pane-child .accordion-section-title::after { top: calc(50% - 10px); /* Arrow height is 20px, so use half of that to vertically center */ } @@ -3870,7 +3895,8 @@ img { background-color: #fff; position: relative; } - .my-sites.striped li:after { + + .my-sites.striped li::after { content: ""; width: 1px; height: 100%; @@ -3881,20 +3907,25 @@ img { } } + @media only screen and (min-width: 600px) and (max-width: 699px) { - .my-sites li{ + .my-sites li { float: left; width: 44%; } + .my-sites.striped li { background-color: #fff; } + .my-sites.striped li:nth-of-type(2n+1) { clear: left; } - .my-sites.striped li:nth-of-type(2n+2):after { + + .my-sites.striped li:nth-of-type(2n+2)::after { content: none; } + .my-sites li:nth-of-type(4n+1), .my-sites li:nth-of-type(4n+2) { background-color: #f6f7f7; @@ -3908,9 +3939,11 @@ img { width: 27.333333%; background-color: #fff; } - .my-sites.striped li:nth-of-type(3n+3):after { + + .my-sites.striped li:nth-of-type(3n+3)::after { content: none; } + .my-sites li:nth-of-type(6n+1), .my-sites li:nth-of-type(6n+2), .my-sites li:nth-of-type(6n+3) { @@ -3925,12 +3958,15 @@ img { padding: 8px 2%; background-color: #fff; } + .my-sites.striped li:nth-of-type(4n+1) { clear: left; } - .my-sites.striped li:nth-of-type(4n+4):after { + + .my-sites.striped li:nth-of-type(4n+4)::after { content: none; } + .my-sites li:nth-of-type(8n+1), .my-sites li:nth-of-type(8n+2), .my-sites li:nth-of-type(8n+3), @@ -3946,12 +3982,15 @@ img { padding: 8px 2%; background-color: #fff; } + .my-sites.striped li:nth-of-type(5n+1) { clear: left; } - .my-sites.striped li:nth-of-type(5n+5):after { + + .my-sites.striped li:nth-of-type(5n+5)::after { content: none; } + .my-sites li:nth-of-type(10n+1), .my-sites li:nth-of-type(10n+2), .my-sites li:nth-of-type(10n+3), @@ -3968,12 +4007,15 @@ img { padding: 8px 2%; background-color: #fff; } + .my-sites.striped li:nth-of-type(6n+1) { clear: left; } - .my-sites.striped li:nth-of-type(6n+6):after { + + .my-sites.striped li:nth-of-type(6n+6)::after { content: none; } + .my-sites li:nth-of-type(12n+1), .my-sites li:nth-of-type(12n+2), .my-sites li:nth-of-type(12n+3), @@ -3995,7 +4037,7 @@ img { * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { + (min-resolution: 120dpi) { /* Back-compat for pre-3.8 */ div.star-holder, div.star-holder .star-rating { @@ -4093,7 +4135,7 @@ img { margin: 20px 0 10px; padding: 5px 10px; font-size: 14px; - line-height: 175%; + line-height: 1.75; } .wp-core-ui .notice.is-dismissible { @@ -4148,8 +4190,10 @@ img { /* Theme/Plugin File Editor */ #template textarea, + /* stylelint-disable-next-line selector-class-pattern -- This class uses selectors that contain uppercase character in .CodeMirror external library. */ #template .CodeMirror { box-sizing: border-box; + width: 100%; } #templateside { @@ -4169,6 +4213,7 @@ img { display: block; padding: 5px; } + #templateside li.howto { padding: 12px; } @@ -4186,36 +4231,37 @@ img { width: auto; } - #template .CodeMirror, - #template textarea { - width: 100%; - } - #templateside ul ul { padding-left: 1.5em; } + [role="treeitem"] .folder-label { display: block; padding: 5px; } + .tree-folder > li::before, .tree-folder > li::after, .tree-folder .tree-folder::after { left: -8px; } + .tree-folder > li::before { top: 0; height: 13px; } + .tree-folder > .current-file::before { left: -5px; top: 7px; width: 4px; } + .tree-folder > .current-file::after { height: 9px; left: -8px; } + .wrap #templateside span.notice { margin-left: -5px; width: 100%; @@ -4255,10 +4301,6 @@ img { margin-bottom: 0; } - #wpfooter { - display: none; - } - #comments-form .checkforspam { display: none; } @@ -4322,7 +4364,7 @@ img { margin-bottom: 20px; /* Add margins beneath links for better spacing between boxes and elements */ } - #screen-meta-links .show-settings:after { + #screen-meta-links .show-settings::after { line-height: 1.9; } @@ -4398,8 +4440,8 @@ img { } @media screen and (max-width: 320px) { - /* Prevent default center alignment and larger font for the Right Now widget when - the network dashboard is viewed on a small mobile device. */ + /* Prevent default center alignment and larger font for the Right Now widget when the network dashboard is viewed on a small mobile device. */ + /* stylelint-disable-next-line selector-id-pattern -- The ID selector network_dashboard_right_now can't be changed because of backward compatibility reasons. */ #network_dashboard_right_now .subsubsub { font-size: 14px; text-align: left; diff --git a/src/wp-admin/css/customize-controls.css b/src/wp-admin/css/customize-controls.css index 646af6c4407df..7cdc6e97ae4d3 100644 --- a/src/wp-admin/css/customize-controls.css +++ b/src/wp-admin/css/customize-controls.css @@ -38,7 +38,7 @@ body { line-height: 1.5; overflow-y: auto; text-align: left; - top: calc( 50% - 100px ); + top: calc(50% - 100px); } #customize-controls #customize-notifications-area .notice.notification-overlay.notification-changeset-locked .customize-changeset-locked-message.has-avatar { @@ -48,6 +48,7 @@ body { #customize-controls #customize-notifications-area .notice.notification-overlay.notification-changeset-locked .currently-editing { margin-top: 0; } + #customize-controls #customize-notifications-area .notice.notification-overlay.notification-changeset-locked .action-buttons { margin-bottom: 0; } @@ -76,6 +77,7 @@ body { body:not(.ready) #customize-save-button-wrapper .save { visibility: hidden; } + #customize-save-button-wrapper .save { float: left; border-radius: 3px; @@ -99,7 +101,7 @@ body:not(.ready) #customize-save-button-wrapper .save { margin: 0; z-index: -1; background: #f0f0f1; - transition: left .18s; + transition: left 0.18s; border-right: 1px solid #dcdcde; border-left: 1px solid #dcdcde; height: 100%; @@ -126,7 +128,7 @@ body:not(.ready) #customize-save-button-wrapper .save { .outer-section-open .wp-full-overlay.expanded #customize-sidebar-outer-content { visibility: visible; left: 100%; - transition: left .18s; + transition: left 0.18s; } @media (prefers-reduced-motion: reduce) { @@ -223,15 +225,17 @@ body.trashing #publish-settings { #customize-control-trash_changeset { margin-top: 20px; } + #customize-control-trash_changeset .button-link { position: relative; padding-left: 24px; display: inline-block; } -#customize-control-trash_changeset .button-link:before { + +#customize-control-trash_changeset .button-link::before { content: "\f182"; - content: "\f182" / ''; - font: normal 22px dashicons; + content: "\f182" / ""; + font: 400 22px dashicons; text-decoration: none; position: absolute; left: 0; @@ -263,6 +267,7 @@ body.trashing #publish-settings { #customize-control-changeset_preview_link { position: relative; display: block; + margin-top: 6px; } .preview-link-wrapper .customize-copy-preview-link.preview-control-element.button { @@ -278,8 +283,8 @@ body.trashing #publish-settings { position: relative; } -.customize-copy-preview-link:before, -.customize-copy-preview-link:after { +.customize-copy-preview-link::before, +.customize-copy-preview-link::after { content: ""; height: 40px; position: absolute; @@ -287,13 +292,13 @@ body.trashing #publish-settings { top: 0; } -.customize-copy-preview-link:before { +.customize-copy-preview-link::before { left: -10px; width: 9px; opacity: 0.75; } -.customize-copy-preview-link:after { +.customize-copy-preview-link::after { left: -5px; width: 4px; opacity: 0.8; @@ -381,10 +386,6 @@ body.trashing #publish-settings { margin-top: 12px; } -#customize-control-changeset_preview_link { - margin-top: 6px; -} - #customize-control-changeset_status { margin-bottom: 0; padding-bottom: 0; @@ -437,13 +438,13 @@ body.trashing #publish-settings { padding: 10px 10px 11px 14px; } -#customize-controls .customize-info.open .accordion-section-title:after, -#customize-controls .customize-info .accordion-section-title:hover:after, -#customize-controls .customize-info .accordion-section-title:focus:after { +#customize-controls .customize-info.open .accordion-section-title::after, +#customize-controls .customize-info .accordion-section-title:hover::after, +#customize-controls .customize-info .accordion-section-title:focus::after { color: #2c3338; } -#customize-controls .customize-info .accordion-section-title:after { +#customize-controls .customize-info .accordion-section-title::after { display: none; } @@ -462,7 +463,7 @@ body.trashing #publish-settings { #customize-controls .customize-info .panel-title { font-size: 20px; font-weight: 200; - line-height: 26px; + line-height: 1.3; display: block; overflow: hidden; white-space: nowrap; @@ -489,7 +490,7 @@ body.trashing #publish-settings { border: none; } -#customize-controls .customize-info .customize-help-toggle:before { +#customize-controls .customize-info .customize-help-toggle::before { position: absolute; top: 5px; left: 6px; @@ -509,12 +510,15 @@ body.trashing #publish-settings { #customize-controls .customize-info .customize-panel-description.open + .no-widget-areas-rendered-notice { border-top: none; } + .no-widget-areas-rendered-notice { font-style: italic; } + .no-widget-areas-rendered-notice p:first-child { margin-top: 0; } + .no-widget-areas-rendered-notice p:last-child { margin-bottom: 0; } @@ -549,9 +553,9 @@ body.trashing #publish-settings { border-bottom: 1px solid #dcdcde; border-left: 4px solid #fff; transition: - .15s color ease-in-out, - .15s background-color ease-in-out, - .15s border-color ease-in-out; + 0.15s color ease-in-out, + 0.15s background-color ease-in-out, + 0.15s border-color ease-in-out; } .accordion-section-title:has(button.accordion-trigger), @@ -589,10 +593,10 @@ body.trashing #publish-settings { border-left: 4px solid #fff; } -#customize-theme-controls .accordion-section-title:after, -#customize-outer-theme-controls .accordion-section-title:after { +#customize-theme-controls .accordion-section-title::after, +#customize-outer-theme-controls .accordion-section-title::after { content: "\f345"; - content: "\f345" / ''; + content: "\f345" / ""; color: #a7aaad; pointer-events: none; } @@ -786,6 +790,7 @@ div.customize-section-description p:last-child { h3.customize-section-title { padding: 10px 10px 12px 14px; margin: 0; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Can't be unitless because of backward compatibility reasons. */ line-height: 21px; color: #50575e; } @@ -826,9 +831,9 @@ h3.customize-section-title { @media (prefers-reduced-motion: no-preference) { .customize-controls-close { transition: - color .15s ease-in-out, - border-color .15s ease-in-out, - background .15s ease-in-out; + color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + background 0.15s ease-in-out; } } @@ -847,9 +852,9 @@ h3.customize-section-title { box-shadow: none; cursor: pointer; transition: - color .15s ease-in-out, - border-color .15s ease-in-out, - background .15s ease-in-out; + color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + background 0.15s ease-in-out; } .customize-section-back { @@ -903,27 +908,27 @@ h3.customize-section-title { outline-offset: -2px; } -.customize-controls-close:before { - font: normal 22px/45px dashicons; +.customize-controls-close::before { + font: 400 22px/45px dashicons; content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; position: relative; top: -3px; left: 13px; } -.customize-panel-back:before, -.customize-section-back:before { - font: normal 20px/72px dashicons; +.customize-panel-back::before, +.customize-section-back::before { + font: 400 20px/72px dashicons; content: "\f341"; - content: "\f341" / ''; + content: "\f341" / ""; position: relative; left: 9px; } .wp-full-overlay-sidebar .wp-full-overlay-header { background-color: #f0f0f1; - transition: padding ease-in-out .18s; + transition: padding ease-in-out 0.18s; } .in-sub-panel .wp-full-overlay-sidebar .wp-full-overlay-header { @@ -1000,10 +1005,10 @@ p.customize-section-description { margin-bottom: 5px; } -.customize-section-description a.external-link:after { +.customize-section-description a.external-link::after { font: 16px/11px dashicons; content: "\f504"; - content: "\f504" / ''; + content: "\f504" / ""; top: 3px; position: relative; padding-left: 3px; @@ -1013,6 +1018,7 @@ p.customize-section-description { .customize-control-color .color-picker, .customize-control-upload div { + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Can't be unitless because of backward compatibility reasons. */ line-height: 28px; } @@ -1080,7 +1086,6 @@ p.customize-section-description { line-height: 0; } - .customize-control .thumbnail-image img { cursor: pointer; } @@ -1170,6 +1175,7 @@ p.customize-section-description { height: 100%; position: absolute; } + #customize-preview iframe + iframe { visibility: hidden; } @@ -1179,7 +1185,6 @@ p.customize-section-description { border-right: 1px solid #dcdcde; } - /** * Notifications */ @@ -1193,7 +1198,7 @@ p.customize-section-description { #customize-controls .customize-control-widget_form.has-error .widget .widget-top, .customize-control-nav_menu_item.has-error .menu-item-bar .menu-item-handle { box-shadow: inset 0 0 0 2px #d63638; - transition: .15s box-shadow linear; + transition: 0.15s box-shadow linear; } #customize-controls .customize-control-notifications-container li.notice { @@ -1202,6 +1207,7 @@ p.customize-section-description { padding: 9px 14px; overflow: hidden; } + #customize-controls .customize-control-notifications-container .notice.is-dismissible { padding-right: 38px; } @@ -1252,20 +1258,24 @@ p.customize-section-description { #customize-controls .customize-section-title > .customize-control-notifications-container .notice { margin: 0; } + #customize-controls .panel-meta > .customize-control-notifications-container, #customize-controls .customize-section-title > .customize-control-notifications-container { border-top: 1px solid #dcdcde; } + #customize-controls #customize-notifications-area .notice, #customize-controls .panel-meta > .customize-control-notifications-container .notice, #customize-controls .customize-section-title > .customize-control-notifications-container .notice { padding: 9px 14px; } + #customize-controls #customize-notifications-area .notice.is-dismissible, #customize-controls .panel-meta > .customize-control-notifications-container .notice.is-dismissible, #customize-controls .customize-section-title > .customize-control-notifications-container .notice.is-dismissible { padding-right: 38px; } + #customize-controls #customize-notifications-area .notice + .notice, #customize-controls .panel-meta > .customize-control-notifications-container .notice + .notice, #customize-controls .customize-section-title > .customize-control-notifications-container .notice + .notice { @@ -1273,8 +1283,13 @@ p.customize-section-description { } @keyframes customize-fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } } #customize-controls .notice.notification-overlay, @@ -1312,6 +1327,7 @@ p.customize-section-description { #customize-control-show_on_front.has-error { margin-bottom: 0; } + #customize-control-show_on_front.has-error .customize-control-notifications-container { margin-top: 12px; } @@ -1327,11 +1343,13 @@ p.customize-section-description { cursor: pointer; } +/* @todo maybe no more used? */ .accordion-section .dropdown-content { overflow: hidden; float: left; min-width: 30px; height: 16px; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Legacy UI likely no longer used. */ line-height: 16px; margin-right: 16px; padding: 4px 5px; @@ -1350,10 +1368,10 @@ p.customize-section-description { background: #f0f0f1; } -.customize-control .dropdown-arrow:after { +.customize-control .dropdown-arrow::after { content: "\f140"; - content: "\f140" / ''; - font: normal 20px/1 dashicons; + content: "\f140" / ""; + font: 400 20px/1 dashicons; display: block; padding: 0; text-indent: 0; @@ -1498,6 +1516,7 @@ p.customize-section-description { .customize-control-header .inner, .customize-control-header .inner .dashicons { + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Used for dashicons. */ line-height: 20px; top: 8px; } @@ -1518,7 +1537,7 @@ p.customize-section-description { } /* Convoluted, but 'outline' support isn't good enough yet */ -.customize-control-header .header-view:after { +.customize-control-header .header-view::after { border: 0; } @@ -1526,7 +1545,7 @@ p.customize-section-description { outline: none; } -.customize-control-header .header-view.selected:after { +.customize-control-header .header-view.selected::after { content: ""; position: absolute; height: auto; @@ -1593,28 +1612,33 @@ p.customize-section-description { } .button-see-me { - animation: bounce .7s 1; + animation: bounce 0.7s 1; transform-origin: center bottom; } @keyframes bounce { - from, 20%, 53%, 80%, to { - animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); - transform: translate3d(0,0,0); - } - - 40%, 43% { - animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + from, + 20%, + 53%, + 80%, + to { + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); transform: translate3d(0, -12px, 0); } 70% { - animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); transform: translate3d(0, -6px, 0); } 90% { - transform: translate3d(0,-1px,0); + transform: translate3d(0, -1px, 0); } } @@ -1664,6 +1688,7 @@ p.customize-section-description { padding: 6px 8px; tab-size: 2; } + .customize-control-code_editor textarea, .customize-control-code_editor .CodeMirror { height: 14em; @@ -1689,19 +1714,19 @@ p.customize-section-description { .customize-section-description-container + #customize-control-custom_css:last-child textarea { border-right: 0; border-left: 0; - height: calc( 100vh - 185px ); + height: calc(100vh - 185px); resize: none; } .customize-section-description-container + #customize-control-custom_css:last-child { margin-left: -12px; width: 299px; - width: calc( 100% + 24px ); + width: calc(100% + 24px); margin-bottom: -12px; } .customize-section-description-container + #customize-control-custom_css:last-child .CodeMirror { - height: calc( 100vh - 185px ); + height: calc(100vh - 185px); } .CodeMirror-lint-tooltip, @@ -1729,7 +1754,7 @@ p.customize-section-description { } .customize-section-description-container + #customize-control-custom_css:last-child textarea { - height: calc( 100vh - 140px ); + height: calc(100vh - 140px); } } @@ -1776,8 +1801,7 @@ p.customize-section-description { .control-panel-themes .accordion-section-title span.customize-action, #customize-controls .customize-section-title span.customize-action, -#customize-controls .control-section-themes .accordion-section-title span.customize-action, -#customize-controls .customize-section-title span.customize-action { +#customize-controls .control-section-themes .accordion-section-title span.customize-action { font-size: 13px; display: block; font-weight: 400; @@ -1797,7 +1821,7 @@ p.customize-section-description { font-weight: 400; } -#customize-theme-controls .control-panel-themes > .accordion-section-title:after { +#customize-theme-controls .control-panel-themes > .accordion-section-title::after { display: none; } @@ -1805,7 +1829,7 @@ p.customize-section-description { position: fixed; top: 0; left: 0; - transition: .18s left ease-in-out; + transition: 0.18s left ease-in-out; margin: 0 0 0 300px; padding: 71px 0 25px; overflow-y: scroll; @@ -1837,13 +1861,13 @@ p.customize-section-description { #customize-save-button-wrapper, #customize-header-actions .spinner, #customize-header-actions .customize-controls-preview-toggle { - transition: .18s margin ease-in-out; + transition: 0.18s margin ease-in-out; } #customize-footer-actions, #customize-footer-actions .collapse-sidebar { bottom: 0; - transition: .18s bottom ease-in-out; + transition: 0.18s bottom ease-in-out; } .in-themes-panel:not(.animating) #customize-header-actions .spinner, @@ -1882,11 +1906,11 @@ p.customize-section-description { line-height: 2.30769231; } -.themes-filter-bar .feature-filter-toggle:before { +.themes-filter-bar .feature-filter-toggle::before { content: "\f111"; - content: "\f111" / ''; + content: "\f111" / ""; margin: 0 5px 0 0; - font: normal 16px/1 dashicons; + font: 400 16px/1 dashicons; vertical-align: text-bottom; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -1917,7 +1941,7 @@ p.customize-section-description { .filter-drawer .filter-group { margin: 0 25px 0 0; - width: calc( (100% - 75px) / 3); + width: calc((100% - 75px) / 3); min-width: 200px; max-width: 320px; } @@ -1927,20 +1951,22 @@ p.customize-section-description { 0% { opacity: 0; } + 50% { opacity: 0; } + 100% { opacity: 1; } } .control-panel-themes .customize-themes-full-container.animate { - animation: .6s themes-fade-in 1; + animation: 0.6s themes-fade-in 1; } .in-themes-panel:not(.animating) .control-panel-themes .filter-themes-count { - animation: .6s themes-fade-in 1; + animation: 0.6s themes-fade-in 1; } .control-panel-themes .filter-themes-count .themes-displayed { @@ -1968,6 +1994,7 @@ p.customize-section-description { .control-section .customize-section-text-before { padding: 0 0 8px 15px; margin: 15px 0 0; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Legacy UI likely no longer used. */ line-height: 16px; border-bottom: 1px solid #dcdcde; color: #50575e; @@ -2006,7 +2033,7 @@ p.customize-section-description { background: #f6f7f7; } -.customize-themes-section-title:not(.selected):after { +.customize-themes-section-title:not(.selected)::after { content: ""; display: block; position: absolute; @@ -2019,9 +2046,9 @@ p.customize-section-description { background: #fff; } -.control-panel-themes .theme-section .customize-themes-section-title.selected:after { +.control-panel-themes .theme-section .customize-themes-section-title.selected::after { content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; font: 16px/1 dashicons; box-sizing: border-box; width: 20px; @@ -2069,7 +2096,8 @@ p.customize-section-description { background: #fff; } -.customize-control-theme .theme .theme-name, .customize-control-theme .theme .theme-actions { +.customize-control-theme .theme .theme-name, +.customize-control-theme .theme .theme-actions { background: #fff; border: none; } @@ -2086,28 +2114,28 @@ p.customize-section-description { /* 5 columns above 2100px */ @media screen and (min-width: 2101px) { .customize-control.customize-control-theme { - width: calc( ( 100% - 125px ) / 5 - 1px ); /* 1px offset accounts for browser rounding, typical all grids */ + width: calc(( 100% - 125px ) / 5 - 1px); /* 1px offset accounts for browser rounding, typical all grids */ } } /* 4 columns up to 2100px */ @media screen and (min-width: 1601px) and (max-width: 2100px) { .customize-control.customize-control-theme { - width: calc( ( 100% - 100px ) / 4 - 1px ); + width: calc(( 100% - 100px ) / 4 - 1px); } } /* 3 columns up to 1600px */ @media screen and (min-width: 1201px) and (max-width: 1600px) { .customize-control.customize-control-theme { - width: calc( ( 100% - 75px ) / 3 - 1px ); + width: calc(( 100% - 75px ) / 3 - 1px); } } /* 2 columns up to 1200px */ @media screen and (min-width: 851px) and (max-width: 1200px) { .customize-control.customize-control-theme { - width: calc( ( 100% - 50px ) / 2 - 1px ); + width: calc(( 100% - 50px ) / 2 - 1px); } } @@ -2121,7 +2149,7 @@ p.customize-section-description { .wp-customizer .theme-browser .themes { padding: 0 0 25px 25px; - transition: .18s margin-top linear; + transition: 0.18s margin-top linear; } .wp-customizer .theme-browser .theme .theme-actions { @@ -2148,6 +2176,7 @@ p.customize-section-description { box-sizing: border-box; border-bottom: 1px solid #dcdcde; } + .customize-preview-header.themes-filter-bar, .customize-preview-header.themes-filter-bar .search-form { display: flex; @@ -2208,9 +2237,11 @@ p.customize-section-description { width: 100%; margin: 0 0 25px; } + .filter-drawer { top: 46px; } + .wp-customizer .theme-browser .themes { padding: 0 0 25px 25px; overflow: hidden; @@ -2226,7 +2257,7 @@ p.customize-section-description { @media screen and (max-width: 1018px) { .filter-drawer .filter-group { - width: calc( (100% - 50px) / 2); + width: calc((100% - 50px) / 2); } } @@ -2244,8 +2275,7 @@ p.customize-section-description { } .customize-preview-header.themes-filter-bar, - .customize-preview-header.themes-filter-bar .search-form - .themes-filter-bar .themes-filter-container { + .customize-preview-header.themes-filter-bar .search-form .themes-filter-bar .themes-filter-container { display: grid; gap: 4px; } @@ -2266,7 +2296,7 @@ p.customize-section-description { @media screen and (max-width: 792px) { .filter-drawer .filter-group { - width: calc( 100% - 25px); + width: calc(100% - 25px); } } @@ -2276,7 +2306,6 @@ p.customize-section-description { /* Mobile - toggle between themes and filters */ @media screen and (max-width: 600px) { - .filter-drawer { top: 132px; } @@ -2322,7 +2351,7 @@ p.customize-section-description { overflow: hidden; } - .wp-customizer .showing-themes .control-panel-themes .customize-themes-mobile-back:before { + .wp-customizer .showing-themes .control-panel-themes .customize-themes-mobile-back::before { left: 0; top: 0; height: 46px; @@ -2369,7 +2398,7 @@ p.customize-section-description { This is likely required because of the way that sections and panels are positioned. */ .wp-customizer.modal-open #customize-header-actions, .wp-customizer.modal-open .control-panel-themes .filter-themes-count, -.wp-customizer.modal-open .control-panel-themes .customize-themes-section-title.selected:after { +.wp-customizer.modal-open .control-panel-themes .customize-themes-section-title.selected::after { z-index: -1; } @@ -2389,7 +2418,7 @@ p.customize-section-description { } .wp-customizer .theme-rating .num-ratings { - line-height: 20px; + line-height: 1.5384; } .wp-customizer .theme-overlay .theme-wrap { @@ -2420,21 +2449,21 @@ p.customize-section-description { } .wp-customizer .theme-overlay .theme-header button, -.wp-customizer .theme-overlay .theme-header .close:before { +.wp-customizer .theme-overlay .theme-header .close::before { color: #3c434a; } .wp-customizer .theme-overlay .theme-header .close:focus, .wp-customizer .theme-overlay .theme-header .close:hover, -.wp-customizer .theme-overlay .theme-header .right:focus, -.wp-customizer .theme-overlay .theme-header .right:hover, -.wp-customizer .theme-overlay .theme-header .left:focus, -.wp-customizer .theme-overlay .theme-header .left:hover { +.wp-customizer .theme-overlay .theme-header .right:focus:not(.disabled), +.wp-customizer .theme-overlay .theme-header .right:hover:not(.disabled), +.wp-customizer .theme-overlay .theme-header .left:focus:not(.disabled), +.wp-customizer .theme-overlay .theme-header .left:hover:not(.disabled) { background: #fff; } -.wp-customizer .theme-overlay .theme-header .close:focus:before, -.wp-customizer .theme-overlay .theme-header .close:hover:before { +.wp-customizer .theme-overlay .theme-header .close:focus::before, +.wp-customizer .theme-overlay .theme-header .close:hover::before { color: var(--wp-admin-theme-color); } @@ -2516,20 +2545,19 @@ body.cheatin p { .reordering .add-new-widget, .reordering .add-new-menu-item { opacity: 0.2; - pointer-events: none; - cursor: not-allowed; /* doesn't work in conjunction with pointer-events */ + pointer-events: none; /* Also resets the cursor style. */ } -.add-new-widget:before, -.add-new-menu-item:before, -#available-menu-items .new-content-item .add-content:before { +.add-new-widget::before, +.add-new-menu-item::before, +#available-menu-items .new-content-item .add-content::before { content: "\f132"; - content: "\f132" / ''; + content: "\f132" / ""; display: inline-block; position: relative; left: -2px; top: 0; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; vertical-align: middle; transition: all 0.2s; -webkit-font-smoothing: antialiased; @@ -2577,15 +2605,15 @@ body.cheatin p { box-shadow: none; } -.widget-reorder-nav span:before, -.menu-item-reorder-nav button:before { +.widget-reorder-nav span::before, +.menu-item-reorder-nav button::before { display: inline-block; position: absolute; top: 0; right: 0; width: 100%; height: 100%; - font: normal 20px/43px dashicons; + font: 400 20px/43px dashicons; text-align: center; text-indent: 0; -webkit-font-smoothing: antialiased; @@ -2600,16 +2628,16 @@ body.cheatin p { background: #f0f0f1; } -.move-widget-down:before, -.menus-move-down:before { +.move-widget-down::before, +.menus-move-down::before { content: "\f347"; - content: "\f347" / ''; + content: "\f347" / ""; } -.move-widget-up:before, -.menus-move-up:before { +.move-widget-up::before, +.menus-move-up::before { content: "\f343"; - content: "\f343" / ''; + content: "\f343" / ""; } #customize-theme-controls .first-widget .move-widget-up, @@ -2645,9 +2673,9 @@ body.adding-widget .add-new-widget:hover, box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5); } -body.adding-widget .add-new-widget:before, -.adding-menu-items .add-new-menu-item:before, -#accordion-section-add_menu .add-new-menu-item.open:before { +body.adding-widget .add-new-widget::before, +.adding-menu-items .add-new-menu-item::before, +#accordion-section-add_menu .add-new-menu-item.open::before { transform: rotate(45deg); } @@ -2664,7 +2692,7 @@ body.adding-widget .add-new-widget:before, margin: 0; z-index: 4; background: #f0f0f1; - transition: left .18s; + transition: left 0.18s; border-right: 1px solid #dcdcde; } @@ -2774,11 +2802,11 @@ body.adding-widget .add-new-widget:before, display: block; } -#available-widgets-filter .clear-results:before, -#available-menu-items-search .clear-results:before { +#available-widgets-filter .clear-results::before, +#available-menu-items-search .clear-results::before { content: "\f335"; - content: "\f335" / ''; - font: normal 20px/1 dashicons; + content: "\f335" / ""; + font: 400 20px/1 dashicons; vertical-align: middle; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -2799,11 +2827,11 @@ body.adding-widget .add-new-widget:before, outline: 2px solid transparent; } -#available-menu-items-search .search-icon:after, -#available-widgets-filter .search-icon:after, -.themes-filter-bar .search-icon:after { +#available-menu-items-search .search-icon::after, +#available-widgets-filter .search-icon::after, +.themes-filter-bar .search-icon::after { content: "\f179"; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; vertical-align: middle; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -2849,9 +2877,9 @@ body.adding-widget .add-new-widget:before, border-bottom: 1px solid #dcdcde; border-left: 4px solid #fff; transition: - .15s color ease-in-out, - .15s background-color ease-in-out, - .15s border-color ease-in-out; + 0.15s color ease-in-out, + 0.15s background-color ease-in-out, + 0.15s border-color ease-in-out; cursor: pointer; display: none; } @@ -2861,7 +2889,6 @@ body.adding-widget .add-new-widget:before, position: static; } - /* Responsive */ .customize-controls-preview-toggle { display: none; @@ -2967,7 +2994,7 @@ body.adding-widget .add-new-widget:before, border-top: 4px solid #f0f0f1; color: #50575e; cursor: pointer; - transition: color .1s ease-in-out, background .1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; } #customize-footer-actions, @@ -2982,19 +3009,19 @@ body.adding-widget .add-new-widget:before, margin-top: -46px; } - .customize-controls-preview-toggle .preview:before, - .customize-controls-preview-toggle .controls:before { - font: normal 20px/1 dashicons; + .customize-controls-preview-toggle .preview::before, + .customize-controls-preview-toggle .controls::before { + font: 400 20px/1 dashicons; content: "\f177"; - content: "\f177" / ''; + content: "\f177" / ""; position: relative; top: 4px; margin-right: 6px; } - .customize-controls-preview-toggle .controls:before { + .customize-controls-preview-toggle .controls::before { content: "\f540"; - content: "\f540" / ''; + content: "\f540" / ""; } .preview-only #customize-controls { @@ -3055,7 +3082,7 @@ body.adding-widget .add-new-widget:before, font-weight: 200; padding: 9px 10px 12px 14px; margin: 0; - line-height: 24px; + line-height: 1.2; color: #50575e; display: block; overflow: hidden; diff --git a/src/wp-admin/css/customize-nav-menus.css b/src/wp-admin/css/customize-nav-menus.css index 37008d6d8e29a..9d5c7861e40ae 100644 --- a/src/wp-admin/css/customize-nav-menus.css +++ b/src/wp-admin/css/customize-nav-menus.css @@ -127,7 +127,6 @@ cursor: pointer; } - /** * Menu items reordering styles */ @@ -140,14 +139,14 @@ right: 0; } -.menus-move-left:before { +.menus-move-left::before { content: "\f341"; - content: "\f341" / ''; + content: "\f341" / ""; } -.menus-move-right:before { +.menus-move-right::before { content: "\f345"; - content: "\f345" / ''; + content: "\f345" / ""; } .reordering .menu-item .item-controls, @@ -178,9 +177,9 @@ text-align: center; } -.wp-customizer .menu-item.menu-item-edit-active .item-edit .toggle-indicator:before { +.wp-customizer .menu-item.menu-item-edit-active .item-edit .toggle-indicator::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } .wp-customizer .menu-item-settings p.description { @@ -257,7 +256,7 @@ padding: 20px; } -#customize-controls .customize-info .customize-help-toggle:before { +#customize-controls .customize-info .customize-help-toggle::before { padding: 4px; } @@ -277,11 +276,11 @@ outline: 2px solid transparent; } -.customize-screen-options-toggle:before { +.customize-screen-options-toggle::before { -moz-osx-font-smoothing: grayscale; border: none; content: "\f111"; - content: "\f111" / ''; + content: "\f111" / ""; display: block; font: 18px/1 dashicons; padding: 5px; @@ -293,8 +292,8 @@ top: 6px; } -.customize-screen-options-toggle:focus:before, -#customize-controls .customize-info .customize-help-toggle:focus:before { +.customize-screen-options-toggle:focus::before, +#customize-controls .customize-info .customize-help-toggle:focus::before { border-radius: 100%; } @@ -308,7 +307,7 @@ .wp-customizer .metabox-prefs label { display: block; padding-right: 0; - line-height: 30px; + line-height: 2.3076; } /* rework the arrow indicator implementation for NVDA bug same as #32715 */ @@ -322,15 +321,15 @@ text-indent: 1px; /* account for the dashicon alignment */ } -.wp-customizer .menu-item .item-edit .toggle-indicator:before, -#available-menu-items .accordion-section-title .toggle-indicator:before { +.wp-customizer .menu-item .item-edit .toggle-indicator::before, +#available-menu-items .accordion-section-title .toggle-indicator::before { content: "\f140"; - content: "\f140" / ''; + content: "\f140" / ""; display: block; padding: 1px 2px 1px 0; border-radius: 50%; - color: #787c82; - font: normal 20px/1 dashicons; + color: #50575e; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-decoration: none !important; @@ -353,73 +352,246 @@ } /* WARNING: The 20px factor is hard-coded in JS. */ -.menu-item-depth-0 { margin-left: 0; } -.menu-item-depth-1 { margin-left: 20px; } -.menu-item-depth-2 { margin-left: 40px; } -.menu-item-depth-3 { margin-left: 60px; } -.menu-item-depth-4 { margin-left: 80px; } -.menu-item-depth-5 { margin-left: 100px; } -.menu-item-depth-6 { margin-left: 120px; } -.menu-item-depth-7 { margin-left: 140px; } -.menu-item-depth-8 { margin-left: 160px; } /* Not likely to be used or useful beyond this depth */ -.menu-item-depth-9 { margin-left: 180px; } -.menu-item-depth-10 { margin-left: 200px; } -.menu-item-depth-11 { margin-left: 220px; } +.menu-item-depth-0 { + margin-left: 0; +} + +.menu-item-depth-1 { + margin-left: 20px; +} + +.menu-item-depth-2 { + margin-left: 40px; +} + +.menu-item-depth-3 { + margin-left: 60px; +} + +.menu-item-depth-4 { + margin-left: 80px; +} + +.menu-item-depth-5 { + margin-left: 100px; +} + +.menu-item-depth-6 { + margin-left: 120px; +} + +.menu-item-depth-7 { + margin-left: 140px; +} + +.menu-item-depth-8 { + margin-left: 160px; +} /* Not likely to be used or useful beyond this depth */ +.menu-item-depth-9 { + margin-left: 180px; +} + +.menu-item-depth-10 { + margin-left: 200px; +} + +.menu-item-depth-11 { + margin-left: 220px; +} /* @todo handle .menu-item-settings width */ -.menu-item-depth-0 > .menu-item-bar { margin-right: 0; } -.menu-item-depth-1 > .menu-item-bar { margin-right: 20px; } -.menu-item-depth-2 > .menu-item-bar { margin-right: 40px; } -.menu-item-depth-3 > .menu-item-bar { margin-right: 60px; } -.menu-item-depth-4 > .menu-item-bar { margin-right: 80px; } -.menu-item-depth-5 > .menu-item-bar { margin-right: 100px; } -.menu-item-depth-6 > .menu-item-bar { margin-right: 120px; } -.menu-item-depth-7 > .menu-item-bar { margin-right: 140px; } -.menu-item-depth-8 > .menu-item-bar { margin-right: 160px; } -.menu-item-depth-9 > .menu-item-bar { margin-right: 180px; } -.menu-item-depth-10 > .menu-item-bar { margin-right: 200px; } -.menu-item-depth-11 > .menu-item-bar { margin-right: 220px; } +.menu-item-depth-0 > .menu-item-bar { + margin-right: 0; +} + +.menu-item-depth-1 > .menu-item-bar { + margin-right: 20px; +} + +.menu-item-depth-2 > .menu-item-bar { + margin-right: 40px; +} + +.menu-item-depth-3 > .menu-item-bar { + margin-right: 60px; +} + +.menu-item-depth-4 > .menu-item-bar { + margin-right: 80px; +} + +.menu-item-depth-5 > .menu-item-bar { + margin-right: 100px; +} + +.menu-item-depth-6 > .menu-item-bar { + margin-right: 120px; +} + +.menu-item-depth-7 > .menu-item-bar { + margin-right: 140px; +} + +.menu-item-depth-8 > .menu-item-bar { + margin-right: 160px; +} + +.menu-item-depth-9 > .menu-item-bar { + margin-right: 180px; +} + +.menu-item-depth-10 > .menu-item-bar { + margin-right: 200px; +} + +.menu-item-depth-11 > .menu-item-bar { + margin-right: 220px; +} /* Submenu left margin. */ -.menu-item-depth-0 .menu-item-transport { margin-left: 0; } -.menu-item-depth-1 .menu-item-transport { margin-left: -20px; } -.menu-item-depth-3 .menu-item-transport { margin-left: -60px; } -.menu-item-depth-4 .menu-item-transport { margin-left: -80px; } -.menu-item-depth-2 .menu-item-transport { margin-left: -40px; } -.menu-item-depth-5 .menu-item-transport { margin-left: -100px; } -.menu-item-depth-6 .menu-item-transport { margin-left: -120px; } -.menu-item-depth-7 .menu-item-transport { margin-left: -140px; } -.menu-item-depth-8 .menu-item-transport { margin-left: -160px; } -.menu-item-depth-9 .menu-item-transport { margin-left: -180px; } -.menu-item-depth-10 .menu-item-transport { margin-left: -200px; } -.menu-item-depth-11 .menu-item-transport { margin-left: -220px; } +.menu-item-depth-0 .menu-item-transport { + margin-left: 0; +} + +.menu-item-depth-1 .menu-item-transport { + margin-left: -20px; +} + +.menu-item-depth-3 .menu-item-transport { + margin-left: -60px; +} + +.menu-item-depth-4 .menu-item-transport { + margin-left: -80px; +} + +.menu-item-depth-2 .menu-item-transport { + margin-left: -40px; +} + +.menu-item-depth-5 .menu-item-transport { + margin-left: -100px; +} + +.menu-item-depth-6 .menu-item-transport { + margin-left: -120px; +} + +.menu-item-depth-7 .menu-item-transport { + margin-left: -140px; +} + +.menu-item-depth-8 .menu-item-transport { + margin-left: -160px; +} + +.menu-item-depth-9 .menu-item-transport { + margin-left: -180px; +} + +.menu-item-depth-10 .menu-item-transport { + margin-left: -200px; +} + +.menu-item-depth-11 .menu-item-transport { + margin-left: -220px; +} /* WARNING: The 20px factor is hard-coded in JS. */ -.reordering .menu-item-depth-0 { margin-left: 0; } -.reordering .menu-item-depth-1 { margin-left: 15px; } -.reordering .menu-item-depth-2 { margin-left: 30px; } -.reordering .menu-item-depth-3 { margin-left: 45px; } -.reordering .menu-item-depth-4 { margin-left: 60px; } -.reordering .menu-item-depth-5 { margin-left: 75px; } -.reordering .menu-item-depth-6 { margin-left: 90px; } -.reordering .menu-item-depth-7 { margin-left: 105px; } -.reordering .menu-item-depth-8 { margin-left: 120px; } /* Not likely to be used or useful beyond this depth */ -.reordering .menu-item-depth-9 { margin-left: 135px; } -.reordering .menu-item-depth-10 { margin-left: 150px; } -.reordering .menu-item-depth-11 { margin-left: 165px; } - -.reordering .menu-item-depth-0 > .menu-item-bar { margin-right: 0; } -.reordering .menu-item-depth-1 > .menu-item-bar { margin-right: 15px; } -.reordering .menu-item-depth-2 > .menu-item-bar { margin-right: 30px; } -.reordering .menu-item-depth-3 > .menu-item-bar { margin-right: 45px; } -.reordering .menu-item-depth-4 > .menu-item-bar { margin-right: 60px; } -.reordering .menu-item-depth-5 > .menu-item-bar { margin-right: 75px; } -.reordering .menu-item-depth-6 > .menu-item-bar { margin-right: 90px; } -.reordering .menu-item-depth-7 > .menu-item-bar { margin-right: 105px; } -.reordering .menu-item-depth-8 > .menu-item-bar { margin-right: 120px; } -.reordering .menu-item-depth-9 > .menu-item-bar { margin-right: 135px; } -.reordering .menu-item-depth-10 > .menu-item-bar { margin-right: 150px; } -.reordering .menu-item-depth-11 > .menu-item-bar { margin-right: 165px; } +.reordering .menu-item-depth-0 { + margin-left: 0; +} + +.reordering .menu-item-depth-1 { + margin-left: 15px; +} + +.reordering .menu-item-depth-2 { + margin-left: 30px; +} + +.reordering .menu-item-depth-3 { + margin-left: 45px; +} + +.reordering .menu-item-depth-4 { + margin-left: 60px; +} + +.reordering .menu-item-depth-5 { + margin-left: 75px; +} + +.reordering .menu-item-depth-6 { + margin-left: 90px; +} + +.reordering .menu-item-depth-7 { + margin-left: 105px; +} + +.reordering .menu-item-depth-8 { + margin-left: 120px; +} /* Not likely to be used or useful beyond this depth */ +.reordering .menu-item-depth-9 { + margin-left: 135px; +} + +.reordering .menu-item-depth-10 { + margin-left: 150px; +} + +.reordering .menu-item-depth-11 { + margin-left: 165px; +} + +.reordering .menu-item-depth-0 > .menu-item-bar { + margin-right: 0; +} + +.reordering .menu-item-depth-1 > .menu-item-bar { + margin-right: 15px; +} + +.reordering .menu-item-depth-2 > .menu-item-bar { + margin-right: 30px; +} + +.reordering .menu-item-depth-3 > .menu-item-bar { + margin-right: 45px; +} + +.reordering .menu-item-depth-4 > .menu-item-bar { + margin-right: 60px; +} + +.reordering .menu-item-depth-5 > .menu-item-bar { + margin-right: 75px; +} + +.reordering .menu-item-depth-6 > .menu-item-bar { + margin-right: 90px; +} + +.reordering .menu-item-depth-7 > .menu-item-bar { + margin-right: 105px; +} + +.reordering .menu-item-depth-8 > .menu-item-bar { + margin-right: 120px; +} + +.reordering .menu-item-depth-9 > .menu-item-bar { + margin-right: 135px; +} + +.reordering .menu-item-depth-10 > .menu-item-bar { + margin-right: 150px; +} + +.reordering .menu-item-depth-11 > .menu-item-bar { + margin-right: 165px; +} .control-section-nav_menu.menu .menu-item-edit-active { margin-left: 0; @@ -451,7 +623,7 @@ */ .adding-menu-items .control-section { - opacity: .4; + opacity: 0.4; } .adding-menu-items .control-panel.control-section, @@ -470,14 +642,14 @@ display: none; } -.menu-item-bar .item-delete:before { +.menu-item-bar .item-delete::before { content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; position: absolute; top: 9px; left: 5px; border-radius: 50%; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -526,17 +698,17 @@ } /* rework the arrow indicator implementation for NVDA bug see #32715 */ -#available-menu-items .accordion-section-title:after { +#available-menu-items .accordion-section-title::after { content: none !important; } -#available-menu-items .accordion-section-title:hover .toggle-indicator:before, -#available-menu-items .button-link:hover .toggle-indicator:before, -#available-menu-items .button-link:focus .toggle-indicator:before { +#available-menu-items .accordion-section-title:hover .toggle-indicator::before, +#available-menu-items .button-link:hover .toggle-indicator::before, +#available-menu-items .button-link:focus .toggle-indicator::before { color: #1d2327; } -#available-menu-items .open .accordion-section-title .toggle-indicator:before { +#available-menu-items .open .accordion-section-title .toggle-indicator::before { content: "\f142"; color: #1d2327; } @@ -623,9 +795,6 @@ #available-menu-items .menu-item-handle { cursor: pointer; -} - -#available-menu-items .menu-item-handle { box-shadow: none; margin-top: -1px; } @@ -656,16 +825,16 @@ color: #1d2327; } -#available-menu-items .item-add:before { +#available-menu-items .item-add::before { content: "\f543"; - content: "\f543" / ''; + content: "\f543" / ""; position: relative; left: 2px; top: 3px; display: inline-block; height: 20px; border-radius: 50%; - font: normal 20px/1.05 dashicons; /* line height is to account for the dashicon's vertical alignment */ + font: 400 20px/1.05 dashicons; /* line height is to account for the dashicon's vertical alignment */ } #available-menu-items .menu-item-handle.item-added .item-type, @@ -675,9 +844,9 @@ color: #646970; } -#available-menu-items .menu-item-handle.item-added .item-add:before { +#available-menu-items .menu-item-handle.item-added .item-add::before { content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; } #available-menu-items .accordion-section-title.loading .spinner, @@ -710,7 +879,7 @@ margin-top: -1px; } -#available-menu-items-search .accordion-section-title:after { +#available-menu-items-search .accordion-section-title::after { display: none; } @@ -720,7 +889,7 @@ } #available-menu-items-search.loading .accordion-section-content div { - opacity: .5; + opacity: 0.5; } #available-menu-items-search.loading.loading-more .accordion-section-content div { @@ -768,15 +937,15 @@ body.adding-menu-items #customize-preview iframe { .added-menu-item .menu-item-handle.loading { padding: 10px 15px 10px 8px; cursor: default; - opacity: .5; + opacity: 0.5; background: #fff; - color: #787c82; + color: #50575e; } .added-menu-item .menu-item-handle { transition-property: opacity, background, color; transition-duration: 1.25s; - transition-timing-function: cubic-bezier( .25, -2.5, .75, 8 ); /* Replacement for .hide().fadeIn('slow') in JS to add emphasis when it's loaded. */ + transition-timing-function: cubic-bezier(0.25, -2.5, 0.75, 8); /* Replacement for .hide().fadeIn('slow') in JS to add emphasis when it's loaded. */ } /* Add/delete Menus */ @@ -829,6 +998,7 @@ li.assigned-to-menu-location .add-new-menu-item { .menu-item-handle { margin-top: -1px; } + .ui-sortable-disabled .menu-item-handle { cursor: default; } @@ -868,18 +1038,17 @@ li.assigned-to-menu-location .add-new-menu-item { */ .wp-customizer .menu-item .submitbox .submitdelete:focus, -.customize-screen-options-toggle:focus:before, -#customize-controls .customize-info .customize-help-toggle:focus:before, -.wp-customizer button:focus .toggle-indicator:before, +.customize-screen-options-toggle:focus::before, +#customize-controls .customize-info .customize-help-toggle:focus::before, +.wp-customizer button:focus .toggle-indicator::before, .menu-delete:focus, -.menu-item-bar .item-delete:focus:before, -#available-menu-items .item-add:focus:before { +.menu-item-bar .item-delete:focus::before, +#available-menu-items .item-add:focus::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; } - @media screen and (max-width: 782px) { #available-menu-items #available-menu-items-search .accordion-section-content { top: 71px; /* 63 + 8 for 40px input */ diff --git a/src/wp-admin/css/customize-widgets.css b/src/wp-admin/css/customize-widgets.css index 6e1bda06b13dc..0eb5f9d04ec70 100644 --- a/src/wp-admin/css/customize-widgets.css +++ b/src/wp-admin/css/customize-widgets.css @@ -25,7 +25,7 @@ } .customize-control .widget-action { - color: #787c82; + color: #50575e; } .customize-control .widget-top:hover .widget-action, @@ -68,6 +68,7 @@ border: 1px solid #dcdcde; overflow: auto; } + .customize-control-widget_form.wide-widget-control .widget-inside > .form { padding: 20px; } @@ -75,6 +76,7 @@ .customize-control-widget_form.wide-widget-control .widget-top { transition: background-color 0.4s; } + .customize-control-widget_form.wide-widget-control.expanding .widget-top, .customize-control-widget_form.wide-widget-control.expanded:not(.collapsing) .widget-top { background-color: #dcdcde; @@ -86,15 +88,15 @@ line-height: 1.23076923; } -.customize-control-widget_form.expanded .widget-action .toggle-indicator:before { +.customize-control-widget_form.expanded .widget-action .toggle-indicator::before { content: "\f142"; } -.customize-control-widget_form.wide-widget-control .widget-action .toggle-indicator:before { +.customize-control-widget_form.wide-widget-control .widget-action .toggle-indicator::before { content: "\f139"; } -.customize-control-widget_form.wide-widget-control.expanded .widget-action .toggle-indicator:before { +.customize-control-widget_form.wide-widget-control.expanded .widget-action .toggle-indicator::before { content: "\f141"; } @@ -129,9 +131,9 @@ background-color: #f6f7f7; } -.move-widget:before { +.move-widget::before { content: "\f504"; - content: "\f504" / ''; + content: "\f504" / ""; } #customize-theme-controls .move-widget-area { @@ -169,14 +171,14 @@ user-select: none; } -#customize-theme-controls .widget-area-select li:before { +#customize-theme-controls .widget-area-select li::before { display: none; content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; position: absolute; top: 12px; left: 10px; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -190,7 +192,7 @@ background: var(--wp-admin-theme-color); } -#customize-theme-controls .widget-area-select .selected:before { +#customize-theme-controls .widget-area-select .selected::before { display: block; } @@ -212,12 +214,15 @@ .wp-customizer div.mce-tooltip { z-index: 500100 !important; } + .wp-customizer .ui-autocomplete.wplink-autocomplete { z-index: 500110; /* originally 100110, but z-index of .wp-full-overlay is 500000 */ } + .wp-customizer #wp-link-backdrop { z-index: 500100; /* originally 100100, but z-index of .wp-full-overlay is 500000 */ } + .wp-customizer #wp-link-wrap { z-index: 500105; /* originally 100105, but z-index of .wp-full-overlay is 500000 */ } @@ -245,7 +250,7 @@ #available-widgets .widget-tpl.selected { background: #f6f7f7; border-bottom-color: #c3c4c7; - color: var(--wp-admin-theme-color);; + color: var(--wp-admin-theme-color); border-left: 4px solid var(--wp-admin-theme-color); } @@ -282,7 +287,6 @@ body.adding-widget #customize-preview { opacity: 0.4; } - /** * Widget Icon styling * No plurals in naming. @@ -293,9 +297,9 @@ body.adding-widget #customize-preview { position: relative; } -#available-widgets .widget-title:before { +#available-widgets .widget-title::before { content: "\f132"; - content: "\f132" / ''; + content: "\f132" / ""; position: absolute; top: -3px; right: 100%; @@ -303,7 +307,7 @@ body.adding-widget #customize-preview { width: 20px; height: 20px; color: #2c3338; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; text-align: center; box-sizing: border-box; -webkit-font-smoothing: antialiased; @@ -311,233 +315,233 @@ body.adding-widget #customize-preview { } /* dashicons-smiley */ -#available-widgets [class*="easy"] .widget-title:before { +#available-widgets [class*="easy"] .widget-title::before { content: "\f328"; - content: "\f328" / ''; + content: "\f328" / ""; top: -4px; } /* dashicons-star-filled */ -#available-widgets [class*="super"] .widget-title:before, -#available-widgets [class*="like"] .widget-title:before { +#available-widgets [class*="super"] .widget-title::before, +#available-widgets [class*="like"] .widget-title::before { content: "\f155"; - content: "\f155" / ''; + content: "\f155" / ""; top: -4px; } /* dashicons-wordpress */ -#available-widgets [class*="meta"] .widget-title:before { +#available-widgets [class*="meta"] .widget-title::before { content: "\f120"; - content: "\f120" / ''; + content: "\f120" / ""; } /* dashicons-archive */ -#available-widgets [class*="archives"] .widget-title:before { +#available-widgets [class*="archives"] .widget-title::before { content: "\f480"; - content: "\f480" / ''; + content: "\f480" / ""; top: -4px; } /* dashicons-category */ -#available-widgets [class*="categor"] .widget-title:before { +#available-widgets [class*="categor"] .widget-title::before { content: "\f318"; - content: "\f318" / ''; + content: "\f318" / ""; top: -4px; } /* dashicons-admin-comments */ -#available-widgets [class*="comment"] .widget-title:before, -#available-widgets [class*="testimonial"] .widget-title:before, -#available-widgets [class*="chat"] .widget-title:before { +#available-widgets [class*="comment"] .widget-title::before, +#available-widgets [class*="testimonial"] .widget-title::before, +#available-widgets [class*="chat"] .widget-title::before { content: "\f101"; - content: "\f101" / ''; + content: "\f101" / ""; } /* dashicons-admin-post */ -#available-widgets [class*="post"] .widget-title:before { +#available-widgets [class*="post"] .widget-title::before { content: "\f109"; - content: "\f109" / ''; + content: "\f109" / ""; } /* dashicons-admin-page */ -#available-widgets [class*="page"] .widget-title:before { +#available-widgets [class*="page"] .widget-title::before { content: "\f105"; - content: "\f105" / ''; + content: "\f105" / ""; } /* dashicons-text */ -#available-widgets [class*="text"] .widget-title:before { +#available-widgets [class*="text"] .widget-title::before { content: "\f478"; - content: "\f478" / ''; + content: "\f478" / ""; } /* dashicons-admin-links */ -#available-widgets [class*="link"] .widget-title:before { +#available-widgets [class*="link"] .widget-title::before { content: "\f103"; - content: "\f103" / ''; + content: "\f103" / ""; } /* dashicons-search */ -#available-widgets [class*="search"] .widget-title:before { +#available-widgets [class*="search"] .widget-title::before { content: "\f179"; - content: "\f179" / ''; + content: "\f179" / ""; } /* dashicons-menu */ -#available-widgets [class*="menu"] .widget-title:before, -#available-widgets [class*="nav"] .widget-title:before { +#available-widgets [class*="menu"] .widget-title::before, +#available-widgets [class*="nav"] .widget-title::before { content: "\f333"; - content: "\f333" / ''; + content: "\f333" / ""; } /* dashicons-tagcloud */ -#available-widgets [class*="tag"] .widget-title:before { +#available-widgets [class*="tag"] .widget-title::before { content: "\f479"; - content: "\f479" / ''; + content: "\f479" / ""; } /* dashicons-rss */ -#available-widgets [class*="rss"] .widget-title:before { +#available-widgets [class*="rss"] .widget-title::before { content: "\f303"; - content: "\f303" / ''; + content: "\f303" / ""; top: -6px; } /* dashicons-calendar */ -#available-widgets [class*="event"] .widget-title:before, -#available-widgets [class*="calendar"] .widget-title:before { +#available-widgets [class*="event"] .widget-title::before, +#available-widgets [class*="calendar"] .widget-title::before { content: "\f145"; - content: "\f145" / ''; + content: "\f145" / ""; top: -4px; } /* dashicons-format-image */ -#available-widgets [class*="image"] .widget-title:before, -#available-widgets [class*="photo"] .widget-title:before, -#available-widgets [class*="slide"] .widget-title:before, -#available-widgets [class*="instagram"] .widget-title:before { +#available-widgets [class*="image"] .widget-title::before, +#available-widgets [class*="photo"] .widget-title::before, +#available-widgets [class*="slide"] .widget-title::before, +#available-widgets [class*="instagram"] .widget-title::before { content: "\f128"; - content: "\f128" / ''; + content: "\f128" / ""; } /* dashicons-format-gallery */ -#available-widgets [class*="album"] .widget-title:before, -#available-widgets [class*="galler"] .widget-title:before { +#available-widgets [class*="album"] .widget-title::before, +#available-widgets [class*="galler"] .widget-title::before { content: "\f161"; - content: "\f161" / ''; + content: "\f161" / ""; } /* dashicons-format-video */ -#available-widgets [class*="video"] .widget-title:before, -#available-widgets [class*="tube"] .widget-title:before { +#available-widgets [class*="video"] .widget-title::before, +#available-widgets [class*="tube"] .widget-title::before { content: "\f126"; - content: "\f126" / ''; + content: "\f126" / ""; } /* dashicons-format-audio */ -#available-widgets [class*="music"] .widget-title:before, -#available-widgets [class*="radio"] .widget-title:before, -#available-widgets [class*="audio"] .widget-title:before { +#available-widgets [class*="music"] .widget-title::before, +#available-widgets [class*="radio"] .widget-title::before, +#available-widgets [class*="audio"] .widget-title::before { content: "\f127"; - content: "\f127" / ''; + content: "\f127" / ""; } /* dashicons-admin-users */ -#available-widgets [class*="login"] .widget-title:before, -#available-widgets [class*="user"] .widget-title:before, -#available-widgets [class*="member"] .widget-title:before, -#available-widgets [class*="avatar"] .widget-title:before, -#available-widgets [class*="subscriber"] .widget-title:before, -#available-widgets [class*="profile"] .widget-title:before, -#available-widgets [class*="grofile"] .widget-title:before { +#available-widgets [class*="login"] .widget-title::before, +#available-widgets [class*="user"] .widget-title::before, +#available-widgets [class*="member"] .widget-title::before, +#available-widgets [class*="avatar"] .widget-title::before, +#available-widgets [class*="subscriber"] .widget-title::before, +#available-widgets [class*="profile"] .widget-title::before, +#available-widgets [class*="grofile"] .widget-title::before { content: "\f110"; - content: "\f110" / ''; + content: "\f110" / ""; } /* dashicons-cart */ -#available-widgets [class*="commerce"] .widget-title:before, -#available-widgets [class*="shop"] .widget-title:before, -#available-widgets [class*="cart"] .widget-title:before { +#available-widgets [class*="commerce"] .widget-title::before, +#available-widgets [class*="shop"] .widget-title::before, +#available-widgets [class*="cart"] .widget-title::before { content: "\f174"; - content: "\f174" / ''; + content: "\f174" / ""; top: -4px; } /* dashicons-shield */ -#available-widgets [class*="secur"] .widget-title:before, -#available-widgets [class*="firewall"] .widget-title:before { +#available-widgets [class*="secur"] .widget-title::before, +#available-widgets [class*="firewall"] .widget-title::before { content: "\f332"; - content: "\f332" / ''; + content: "\f332" / ""; } /* dashicons-chart-bar */ -#available-widgets [class*="analytic"] .widget-title:before, -#available-widgets [class*="stat"] .widget-title:before, -#available-widgets [class*="poll"] .widget-title:before { +#available-widgets [class*="analytic"] .widget-title::before, +#available-widgets [class*="stat"] .widget-title::before, +#available-widgets [class*="poll"] .widget-title::before { content: "\f185"; - content: "\f185" / ''; + content: "\f185" / ""; } /* dashicons-feedback */ -#available-widgets [class*="form"] .widget-title:before { +#available-widgets [class*="form"] .widget-title::before { content: "\f175"; - content: "\f175" / ''; + content: "\f175" / ""; } /* dashicons-email-alt */ -#available-widgets [class*="subscribe"] .widget-title:before, -#available-widgets [class*="news"] .widget-title:before, -#available-widgets [class*="contact"] .widget-title:before, -#available-widgets [class*="mail"] .widget-title:before { +#available-widgets [class*="subscribe"] .widget-title::before, +#available-widgets [class*="news"] .widget-title::before, +#available-widgets [class*="contact"] .widget-title::before, +#available-widgets [class*="mail"] .widget-title::before { content: "\f466"; - content: "\f466" / ''; + content: "\f466" / ""; } /* dashicons-share */ -#available-widgets [class*="share"] .widget-title:before, -#available-widgets [class*="socia"] .widget-title:before { +#available-widgets [class*="share"] .widget-title::before, +#available-widgets [class*="socia"] .widget-title::before { content: "\f237"; - content: "\f237" / ''; + content: "\f237" / ""; } /* dashicons-translation */ -#available-widgets [class*="lang"] .widget-title:before, -#available-widgets [class*="translat"] .widget-title:before { +#available-widgets [class*="lang"] .widget-title::before, +#available-widgets [class*="translat"] .widget-title::before { content: "\f326"; - content: "\f326" / ''; + content: "\f326" / ""; } /* dashicons-location-alt */ -#available-widgets [class*="locat"] .widget-title:before, -#available-widgets [class*="map"] .widget-title:before { +#available-widgets [class*="locat"] .widget-title::before, +#available-widgets [class*="map"] .widget-title::before { content: "\f231"; - content: "\f231" / ''; + content: "\f231" / ""; } /* dashicons-download */ -#available-widgets [class*="download"] .widget-title:before { +#available-widgets [class*="download"] .widget-title::before { content: "\f316"; - content: "\f316" / ''; + content: "\f316" / ""; } /* dashicons-cloud */ -#available-widgets [class*="weather"] .widget-title:before { +#available-widgets [class*="weather"] .widget-title::before { content: "\f176"; - content: "\f176" / ''; + content: "\f176" / ""; top: -4px; } /* dashicons-facebook */ -#available-widgets [class*="facebook"] .widget-title:before { +#available-widgets [class*="facebook"] .widget-title::before { content: "\f304"; - content: "\f304" / ''; + content: "\f304" / ""; } /* dashicons-twitter */ -#available-widgets [class*="tweet"] .widget-title:before, -#available-widgets [class*="twitter"] .widget-title:before { +#available-widgets [class*="tweet"] .widget-title::before, +#available-widgets [class*="twitter"] .widget-title::before { content: "\f301"; - content: "\f301" / ''; + content: "\f301" / ""; } @media screen and (max-height: 700px) and (min-width: 981px) { @@ -572,8 +576,9 @@ body.adding-widget #customize-preview { height: 39px; } - .widget-reorder-nav span:before { - line-height: 39px; + .widget-reorder-nav span::before { + /* Line height used for the reorder dashicons where the font size is 20px and the desired line-height is 39px. */ + line-height: 1.95; } /* Compact the move widget areas. */ @@ -581,7 +586,7 @@ body.adding-widget #customize-preview { padding: 9px 15px 11px 42px; } - #customize-theme-controls .widget-area-select li:before { + #customize-theme-controls .widget-area-select li::before { top: 8px; } } diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css index 17a9e312b85c6..b4c5dc8ef76e0 100644 --- a/src/wp-admin/css/dashboard.css +++ b/src/wp-admin/css/dashboard.css @@ -67,7 +67,7 @@ } #dashboard-widgets .postbox-container .empty-container { - outline: 2px dashed rgb(0, 0, 0, 0.15); + outline: 2px dashed rgba(0, 0, 0, 0.15); outline-offset: -2px; border-radius: 8px; height: 250px; @@ -77,22 +77,22 @@ /* Only highlight drop zones when dragging. */ .is-dragging-metaboxes #dashboard-widgets .meta-box-sortables { border-radius: 8px; - background: rgb(var(--wp-admin-theme-color--rgb), 0.04); + background: rgba(var(--wp-admin-theme-color--rgb), 0.04); min-height: 100px; } .is-dragging-metaboxes #dashboard-widgets .postbox-container .empty-container { - background: rgb(0, 0, 0, 0.01); + background: rgba(0, 0, 0, 0.01); } -#dashboard-widgets .postbox-container .empty-container:after { +#dashboard-widgets .postbox-container .empty-container::after { content: attr(data-emptystring); margin: auto; position: absolute; top: 50%; left: 0; right: 0; - transform: translateY( -50% ); + transform: translateY(-50%); padding: 0 2em; text-align: center; color: #646970; @@ -101,7 +101,6 @@ display: none; } - /* @todo: this was originally in this section, but likely belongs elsewhere */ #the-comment-list td.comment p.comment-author { margin-top: 0; @@ -165,6 +164,12 @@ } .welcome-panel-header { + box-sizing: border-box; + margin-left: auto; + margin-right: auto; + max-width: 1500px; + width: 100%; + padding: 48px 0 80px 48px; position: relative; color: #fff; } @@ -226,16 +231,13 @@ line-height: 1.23076923; /* Chrome rounding, needs to be 16px equivalent */ text-decoration: none; z-index: 1; /* Raise above the version image. */ -} - -.welcome-panel .welcome-panel-close:before { - transition: all .1s ease-in-out; - content: '\f335'; - font-size: 24px; color: #fff; } -.welcome-panel .welcome-panel-close { +.welcome-panel .welcome-panel-close::before { + transition: all 0.1s ease-in-out; + content: "\f335"; + font-size: 24px; color: #fff; } @@ -266,15 +268,6 @@ background-color: #151515; } -.welcome-panel-header { - box-sizing: border-box; - margin-left: auto; - margin-right: auto; - max-width: 1500px; - width: 100%; - padding: 48px 0 80px 48px; -} - .welcome-panel .welcome-panel-column-container { box-sizing: border-box; width: 100%; @@ -285,7 +278,7 @@ grid-template-columns: repeat(3, 1fr); gap: 32px; align-self: flex-end; - background: #ffffff; + background: #fff; border: 1px solid #c3c4c7; border-top: 0; border-radius: 0 0 8px 8px; @@ -357,12 +350,12 @@ /* Welcome Panel and Right Now common Icons style */ /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-icon:before, -#dashboard_right_now li a:before, -#dashboard_right_now li span:before, -#dashboard_right_now .search-engines-info:before { +.welcome-panel .welcome-icon::before, +#dashboard_right_now li a::before, +#dashboard_right_now li span::before, +#dashboard_right_now .search-engines-info::before { color: #646970; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; display: inline-block; padding: 0 10px 0 0; position: relative; @@ -375,115 +368,115 @@ /* Welcome Panel specific Icons styles */ /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-write-blog:before, -.welcome-panel .welcome-edit-page:before { +.welcome-panel .welcome-write-blog::before, +.welcome-panel .welcome-edit-page::before { content: "\f119"; - content: "\f119" / ''; + content: "\f119" / ""; top: -3px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-add-page:before { +.welcome-panel .welcome-add-page::before { content: "\f132"; - content: "\f132" / ''; + content: "\f132" / ""; top: -1px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-setup-home:before { +.welcome-panel .welcome-setup-home::before { content: "\f102"; - content: "\f102" / ''; + content: "\f102" / ""; top: -1px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-view-site:before { +.welcome-panel .welcome-view-site::before { content: "\f115"; - content: "\f115" / ''; + content: "\f115" / ""; top: -2px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-widgets-menus:before { +.welcome-panel .welcome-widgets-menus::before { content: "\f116"; - content: "\f116" / ''; + content: "\f116" / ""; top: -2px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-widgets:before { +.welcome-panel .welcome-widgets::before { content: "\f538"; - content: "\f538" / ''; + content: "\f538" / ""; top: -2px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-menus:before { +.welcome-panel .welcome-menus::before { content: "\f163"; - content: "\f163" / ''; + content: "\f163" / ""; top: -2px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-comments:before { +.welcome-panel .welcome-comments::before { content: "\f117"; - content: "\f117" / ''; + content: "\f117" / ""; top: -1px; } /* @deprecated 5.9.0 -- Icons removed from welcome panel. */ -.welcome-panel .welcome-learn-more:before { +.welcome-panel .welcome-learn-more::before { content: "\f118"; - content: "\f118" / ''; + content: "\f118" / ""; top: -1px; } /* Right Now specific Icons styles */ -#dashboard_right_now .search-engines-info:before, -#dashboard_right_now li a:before, -#dashboard_right_now li > span:before { /* get only the first level span to exclude screen-reader-text in mu-storage */ +#dashboard_right_now .search-engines-info::before, +#dashboard_right_now li a::before, +#dashboard_right_now li > span::before { /* get only the first level span to exclude screen-reader-text in mu-storage */ padding: 0 5px 0 0; /* generic icon for items added by CPTs ? */ content: "\f159"; - content: "\f159" / ''; + content: "\f159" / ""; } -#dashboard_right_now .page-count a:before, -#dashboard_right_now .page-count span:before { +#dashboard_right_now .page-count a::before, +#dashboard_right_now .page-count span::before { content: "\f105"; - content: "\f105" / ''; + content: "\f105" / ""; } -#dashboard_right_now .post-count a:before, -#dashboard_right_now .post-count span:before { +#dashboard_right_now .post-count a::before, +#dashboard_right_now .post-count span::before { content: "\f109"; - content: "\f109" / ''; + content: "\f109" / ""; } -#dashboard_right_now .comment-count a:before { +#dashboard_right_now .comment-count a::before { content: "\f101"; - content: "\f101" / ''; + content: "\f101" / ""; } -#dashboard_right_now .comment-mod-count a:before { +#dashboard_right_now .comment-mod-count a::before { content: "\f125"; - content: "\f125" / ''; + content: "\f125" / ""; } -#dashboard_right_now .storage-count a:before { +#dashboard_right_now .storage-count a::before { content: "\f104"; - content: "\f104" / ''; + content: "\f104" / ""; } -#dashboard_right_now .storage-count.warning a:before { +#dashboard_right_now .storage-count.warning a::before { content: "\f153"; - content: "\f153" / ''; + content: "\f153" / ""; } -#dashboard_right_now .search-engines-info:before { +#dashboard_right_now .search-engines-info::before { content: "\f348"; - content: "\f348" / ''; + content: "\f348" / ""; color: #d63638; } @@ -523,9 +516,9 @@ .community-events-form { margin: 15px 0 5px; display: flex; - gap: 5px; - align-items: center; - flex-wrap: wrap; + gap: 5px; + align-items: center; + flex-wrap: wrap; } .community-events-form .regular-text { @@ -568,7 +561,7 @@ } .community-events ul { - background-color: rgba(var(--wp-admin-theme-color--rgb),.08); + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); padding-left: 0; padding-right: 0; padding-bottom: 0; @@ -579,6 +572,7 @@ padding: 8px 12px; color: #2c3338; } + .community-events li:first-child { border-top: 1px solid #e9e9ed; } @@ -599,7 +593,7 @@ .community-events .ce-separator::before { content: "\2022"; - content: "\2022" / ''; + content: "\2022" / ""; } .event-icon { @@ -609,17 +603,19 @@ display: none; /* Hide on smaller screens */ } -.event-icon:before { +.event-icon::before { color: #646970; font-size: 18px; } -.event-meetup .event-icon:before { + +.event-meetup .event-icon::before { content: "\f484"; - content: "\f484" / ''; + content: "\f484" / ""; } -.event-wordcamp .event-icon:before { + +.event-wordcamp .event-icon::before { content: "\f486"; - content: "\f486" / ''; + content: "\f486" / ""; } .community-events .event-title { @@ -672,6 +668,7 @@ body #dashboard-widgets .postbox form .submit { margin-top: 0; } +/* stylelint-disable-next-line selector-class-pattern -- The class rssSummary can't be changed because of backward compatibility reasons. */ .rssSummary { color: #646970; margin-top: 4px; @@ -776,8 +773,8 @@ body #dashboard-widgets .postbox form .submit { margin: 0 0 1em; } -#dashboard_right_now .warning a:before, -#dashboard_right_now .warning span:before { +#dashboard_right_now .warning a::before, +#dashboard_right_now .warning span::before { color: #d63638; } @@ -792,7 +789,8 @@ body #dashboard-widgets .postbox form .submit { margin: 12px; } -#dashboard_quick_press .drafts { +#dashboard_quick_press .drafts, +#dashboard_quick_press .no-drafts { padding: 10px 0 0; } @@ -808,11 +806,6 @@ body #dashboard-widgets .postbox form .submit { margin: 0; } -#dashboard-widgets .postbox form .submit { - margin: -39px 0; - float: right; -} - #description-wrap { margin-top: 12px; } @@ -827,7 +820,8 @@ body #dashboard-widgets .postbox form .submit { /* Dashboard Quick Draft - Drafts list */ -.js #dashboard_quick_press .drafts { +.js #dashboard_quick_press .drafts, +.js #dashboard_quick_press .no-drafts { border-top: 1px solid #f0f0f1; } @@ -874,7 +868,8 @@ body #dashboard-widgets .postbox form .submit { #dashboard-widgets h4, /* Back-compat for pre-4.4 */ #dashboard-widgets h3, -#dashboard_quick_press .drafts h2 { +#dashboard_quick_press .drafts h2, +#dashboard_quick_press .no-drafts p { margin: 0 12px 8px; padding: 0; font-size: 14px; @@ -894,10 +889,10 @@ body #dashboard-widgets .postbox form .submit { /* Dashboard activity widget */ -#dashboard_activity .comment-meta span.approve:before { +#dashboard_activity .comment-meta span.approve::before { content: "\f227"; - content: "\f227" / ''; - font: 20px/.5 dashicons; + content: "\f227" / ""; + font: 20px/0.5 dashicons; margin-left: 5px; vertical-align: middle; position: relative; @@ -1008,7 +1003,7 @@ body #dashboard-widgets .postbox form .submit { background-color: #fcf9e8; } -#activity-widget #the-comment-list .unapproved:before { +#activity-widget #the-comment-list .unapproved::before { content: ""; display: block; position: absolute; @@ -1054,7 +1049,7 @@ body #dashboard-widgets .postbox form .submit { #dashboard-widgets .postbox form .submit { float: none; - margin: .5em 0 0; + margin: 0.5em 0 0; padding: 0; border: none; } @@ -1063,7 +1058,7 @@ body #dashboard-widgets .postbox form .submit { min-width: 0; } -#dashboard-widgets li a, +#dashboard-widgets li:not(.activity-block li):not(.comment) a, #dashboard-widgets .button-link, .community-events-footer a { text-decoration: none; @@ -1169,9 +1164,9 @@ a.rsswidget { padding: 0; } -.rss-widget cite:before { +.rss-widget cite::before { content: "\2014"; - content: "\2014" / ''; + content: "\2014" / ""; } .dashboard-comment-wrap { @@ -1186,6 +1181,7 @@ a.rsswidget { #dashboard_browser_nag a { text-decoration: underline; + color: #fff; } #dashboard_browser_nag p.browser-update-nag.has-browser-icon { @@ -1211,10 +1207,6 @@ a.rsswidget { box-shadow: none; } -#dashboard_browser_nag a { - color: #fff; -} - #dashboard_browser_nag.postbox .postbox-header { border-color: transparent; } @@ -1316,8 +1308,8 @@ a.rsswidget { display: none; } - #dashboard-widgets #postbox-container-3 .empty-container:after, - #dashboard-widgets #postbox-container-4 .empty-container:after { + #dashboard-widgets #postbox-container-3 .empty-container::after, + #dashboard-widgets #postbox-container-4 .empty-container::after { display: none; } @@ -1343,7 +1335,7 @@ a.rsswidget { display: none; } - #dashboard-widgets .postbox-container .empty-container:after { + #dashboard-widgets .postbox-container .empty-container::after { display: block; } } @@ -1371,22 +1363,26 @@ a.rsswidget { display: none; } - #dashboard-widgets #postbox-container-4 .empty-container:after { + #dashboard-widgets #postbox-container-4 .empty-container::after { display: none; } - #dashboard-widgets .postbox-container .empty-container:after { + #dashboard-widgets .postbox-container .empty-container::after { display: block; } } /* Always show the "Drag boxes here" CSS generated content on large screens. */ @media only screen and (min-width: 1801px) { - #dashboard-widgets .postbox-container .empty-container:after { + #dashboard-widgets .postbox-container .empty-container::after { display: block; } } +.js.meta-box-reordering-disabled #dashboard-widgets .postbox-container .empty-container { + display: none; +} + @media screen and (max-width: 870px) { /* @deprecated 5.9.0 -- Lists removed from welcome panel. */ .welcome-panel .welcome-panel-column li { diff --git a/src/wp-admin/css/deprecated-media.css b/src/wp-admin/css/deprecated-media.css index 36fafeb65f76b..58d33187fd22c 100644 --- a/src/wp-admin/css/deprecated-media.css +++ b/src/wp-admin/css/deprecated-media.css @@ -26,7 +26,7 @@ div#media-upload-header { padding: 0 7px; display: block; float: left; - line-height: 28px; + line-height: 2.3333; border-top: 1px solid #f6f7f7; border-bottom: 1px solid #dcdcde; background-color: #f6f7f7; @@ -36,7 +36,7 @@ div#media-upload-header { #sidemenu li { display: inline; - line-height: 200%; + line-height: 2; list-style: none; text-align: center; white-space: nowrap; @@ -54,7 +54,7 @@ div#media-upload-header { color: #000; } -#media-upload:after { /* clearfix */ +#media-upload::after { /* clearfix */ content: ""; display: table; clear: both; @@ -68,11 +68,6 @@ div#media-upload-header { padding: 0; } -.media-upload-form label.form-help, -td.help { - color: #646970; -} - form { margin: 1em; } @@ -85,10 +80,12 @@ th { position: relative; } -.media-upload-form label.form-help, td.help { +.media-upload-form label.form-help, +td.help { font-family: sans-serif; font-style: italic; font-weight: 400; + color: #646970; } .media-upload-form p.help { @@ -165,6 +162,7 @@ span.required { padding: 2px 8px; } +/* stylelint-disable-next-line selector-class-pattern -- Legacy UI likely no longer used. */ .describe td.A1 { width: 132px; } @@ -235,12 +233,14 @@ span.required { margin: 5px 0; } +/* stylelint-disable-next-line selector-class-pattern -- Legacy UI only kept for backward compatibility. */ .menu_order { float: right; font-size: 11px; margin: 8px 10px 0; } +/* stylelint-disable-next-line selector-class-pattern -- Legacy UI only kept for backward compatibility. */ .menu_order_input { border: 1px solid #dcdcde; font-size: 10px; @@ -308,7 +308,7 @@ h4.media-sub-title { #gallery-settings .title, h3.media-title, h4.media-sub-title { - font-family: Georgia,"Times New Roman",Times,serif; + font-family: Georgia, "Times New Roman", Times, serif; font-weight: 400; color: #50575e; } @@ -319,7 +319,7 @@ h4.media-sub-title { } #gallery-settings .describe th.label { - padding-top: .5em; + padding-top: 0.5em; text-align: left; } @@ -404,8 +404,7 @@ table.not-image tr.image-only { * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { - + (min-resolution: 120dpi) { .image-align-none-label { background-image: url(../images/align-none-2x.png?ver=20120916); background-size: 21px 15px; diff --git a/src/wp-admin/css/edit.css b/src/wp-admin/css/edit.css index c02a15aa3995a..73c07eef4a7c1 100644 --- a/src/wp-admin/css/edit.css +++ b/src/wp-admin/css/edit.css @@ -59,7 +59,7 @@ #titlediv #title { padding: 3px 8px; font-size: 1.7em; - line-height: 100%; + line-height: 1; height: 1.7em; width: 100%; outline: none; @@ -175,7 +175,7 @@ body.post-type-wp_navigation .inline-edit-status { /* Only highlight drop zones when dragging and only in the 2 columns layout. */ .is-dragging-metaboxes .metabox-holder .postbox-container .meta-box-sortables { border-radius: 8px; - background: rgb(var(--wp-admin-theme-color--rgb), 0.04); + background: rgba(var(--wp-admin-theme-color--rgb), 0.04); /* * This min-height is meant to limit jumpiness while dragging. It's equivalent * to the minimum height of the sortable-placeholder which is given by the height @@ -335,7 +335,7 @@ form#tags-filter { } #side-sortables input#post_password { - width: 94% + width: 94%; } #side-sortables .tagsdiv #newtag { @@ -402,9 +402,6 @@ form#tags-filter { .wp-editor-expand #wp-content-editor-container { box-shadow: none; margin-top: -1px; -} - -.wp-editor-expand #wp-content-editor-container { border-bottom: 0 none; } @@ -459,13 +456,18 @@ form#tags-filter { line-height: 2.33333333; /* 28px */ } -#aa, #jj, #hh, #mn { +#aa, +#jj, +#hh, +#mn { padding: 6px 1px; font-size: 12px; line-height: 1.16666666; /* 14px */ } -#jj, #hh, #mn { +#jj, +#hh, +#mn { width: 2em; } @@ -479,74 +481,64 @@ form#tags-filter { height: auto !important; } -#post-body .misc-pub-post-status:before, -#post-body #visibility:before, -.curtime #timestamp:before, -#post-body .misc-pub-uploadedby:before, -#post-body .misc-pub-uploadedto:before, -#post-body .misc-pub-revisions:before, -#post-body .misc-pub-response-to:before, -#post-body .misc-pub-comment-status:before { - color: #8c8f94; -} - -#post-body .misc-pub-post-status:before, -#post-body #visibility:before, -.curtime #timestamp:before, -#post-body .misc-pub-uploadedby:before, -#post-body .misc-pub-uploadedto:before, -#post-body .misc-pub-revisions:before, -#post-body .misc-pub-response-to:before, -#post-body .misc-pub-comment-status:before { - font: normal 20px/1 dashicons; +#post-body .misc-pub-post-status::before, +#post-body #visibility::before, +.curtime #timestamp::before, +#post-body .misc-pub-uploadedby::before, +#post-body .misc-pub-uploadedto::before, +#post-body .misc-pub-revisions::before, +#post-body .misc-pub-response-to::before, +#post-body .misc-pub-comment-status::before { + font: 400 20px/1 dashicons; display: inline-block; margin-left: -1px; padding-right: 3px; vertical-align: top; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + color: #8c8f94; } -#post-body .misc-pub-post-status:before, -#post-body .misc-pub-comment-status:before { +#post-body .misc-pub-post-status::before, +#post-body .misc-pub-comment-status::before { content: "\f173"; - content: "\f173" / ''; + content: "\f173" / ""; } -#post-body #visibility:before { +#post-body #visibility::before { content: "\f177"; - content: "\f177" / ''; + content: "\f177" / ""; } -.curtime #timestamp:before { +.curtime #timestamp::before { content: "\f145"; - content: "\f145" / ''; + content: "\f145" / ""; position: relative; top: -1px; } -#post-body .misc-pub-uploadedby:before { +#post-body .misc-pub-uploadedby::before { content: "\f110"; - content: "\f110" / ''; + content: "\f110" / ""; position: relative; top: -1px; } -#post-body .misc-pub-uploadedto:before { +#post-body .misc-pub-uploadedto::before { content: "\f318"; - content: "\f318" / ''; + content: "\f318" / ""; position: relative; top: -1px; } -#post-body .misc-pub-revisions:before { +#post-body .misc-pub-revisions::before { content: "\f321"; - content: "\f321" / ''; + content: "\f321" / ""; } -#post-body .misc-pub-response-to:before { +#post-body .misc-pub-response-to::before { content: "\f101"; - content: "\f101" / ''; + content: "\f101" / ""; } #timestampdiv { @@ -846,7 +838,6 @@ form#tags-filter { .privacy-settings-tabs-wrapper { /* IE 11 */ - display: -ms-inline-grid; -ms-grid-columns: 1fr 1fr; vertical-align: top; /* modern browsers */ @@ -876,7 +867,7 @@ form#tags-filter { .privacy-settings-tab:focus, .health-check-tab:focus { color: #1d2327; - outline: 1px solid #787c82; + outline: 1px solid #50575e; box-shadow: none; } @@ -1027,7 +1018,7 @@ form#tags-filter { .privacy-settings-view-passed[aria-expanded="true"] .icon, .health-check-accordion-trigger[aria-expanded="true"] .icon, .site-health-view-passed[aria-expanded="true"] .icon { - transform: translateY(-30%) rotate(-135deg) + transform: translateY(-30%) rotate(-135deg); } .privacy-settings-accordion-panel, @@ -1087,12 +1078,11 @@ form#tags-filter { .privacy-settings-accordion-panel div > *:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(div):not(.privacy-policy-tutorial):not(.wp-policy-help):not(.privacy-text-copy):not(span.success):not(.notice p) { margin: 0; padding: 1em; - border-left: 2px solid #787c82; + border-left: 2px solid #50575e; } /* Media queries */ @media screen and (max-width: 782px) { - .privacy-settings-body, .health-check-body { margin: 0 12px; @@ -1129,7 +1119,6 @@ form#tags-filter { } @media only screen and (max-width: 1004px) { - .privacy-settings-body, .health-check-body { margin: 0 22px; @@ -1275,12 +1264,12 @@ form#tags-filter { margin-top: -4px; margin-right: 7px; color: #dcdcde; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -a.post-format-icon:hover:before { +a.post-format-icon:hover::before { color: #135e96; } @@ -1303,52 +1292,52 @@ label.post-format-icon { .post-format-icon.post-format-standard::before { content: "\f109"; - content: "\f109" / ''; + content: "\f109" / ""; } .post-format-icon.post-format-image::before { content: "\f128"; - content: "\f128" / ''; + content: "\f128" / ""; } .post-format-icon.post-format-gallery::before { content: "\f161"; - content: "\f161" / ''; + content: "\f161" / ""; } .post-format-icon.post-format-audio::before { content: "\f127"; - content: "\f127" / ''; + content: "\f127" / ""; } .post-format-icon.post-format-video::before { content: "\f126"; - content: "\f126" / ''; + content: "\f126" / ""; } .post-format-icon.post-format-chat::before { content: "\f125"; - content: "\f125" / ''; + content: "\f125" / ""; } .post-format-icon.post-format-status::before { content: "\f130"; - content: "\f130" / ''; + content: "\f130" / ""; } .post-format-icon.post-format-aside::before { content: "\f123"; - content: "\f123" / ''; + content: "\f123" / ""; } .post-format-icon.post-format-quote::before { content: "\f122"; - content: "\f122" / ''; + content: "\f122" / ""; } .post-format-icon.post-format-link::before { content: "\f103"; - content: "\f103" / ''; + content: "\f103" / ""; } /*------------------------------------------------------------------------------ @@ -1395,6 +1384,7 @@ div.tabs-panel-active:focus { /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; } + .options-discussion-php .indent-children ul, #front-page-warning, #front-static-pages ul, @@ -1523,6 +1513,7 @@ p.description code, p.popular-tags { border: none; + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- The popular tags in the Plugin install use varying inline font sizes so the line-height needs a unit. */ line-height: 2em; padding: 8px 12px 12px; text-align: justify; @@ -1624,8 +1615,8 @@ p.popular-tags a { margin-left: 2em; } -.comment-ays .comment-content a[href]:after { - content: "(" attr( href ) ")"; +.comment-ays .comment-content a[href]::after { + content: "(" attr(href) ")"; display: inline-block; padding: 0 4px; color: #646970; @@ -1637,7 +1628,7 @@ p.popular-tags a { margin-top: 10px; } -.comment-ays .comment-content p.edit-comment a[href]:after { +.comment-ays .comment-content p.edit-comment a[href]::after { content: ""; padding: 0; } @@ -1777,16 +1768,12 @@ table.links-table { transition-duration: 0.6s; transition-property: transform; transition-timing-function: ease-in-out; -} - -.focus-on #adminmenuback, -.focus-on #adminmenuwrap { - transform: translateX( -100% ); + transform: translateX(-100%); } .focus-off #adminmenuback, .focus-off #adminmenuwrap { - transform: translateX( 0 ); + transform: translateX(0); transition-duration: 0.2s; transition-property: transform; transition-timing-function: ease-in-out; @@ -1799,7 +1786,7 @@ table.links-table { * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { + (min-resolution: 120dpi) { #content-resize-handle, #post-body .wp_themeSkin .mceStatusbar a.mceResize { background: transparent url(../images/resize-2x.gif) no-repeat scroll right bottom; @@ -1946,13 +1933,13 @@ table.links-table { width: 28px; } - .post-format-options a div:before { + .post-format-options a div::before { font-size: 26px !important; } /* Publish Metabox Options */ #post-visibility-select { - line-height: 280%; + line-height: 2.8; } #post-visibility-select #password-span { @@ -2004,7 +1991,7 @@ table.links-table { margin-top: 15px; } - .category-add input[type=text], + .category-add input[type="text"], .category-add select { max-width: none; margin-bottom: 15px; @@ -2093,8 +2080,8 @@ table.links-table { margin-left: -2px !important; } - .wp-media-buttons .add_media span.wp-media-buttons-icon:before, - .wp-media-buttons #insert-jetpack-contact-form span.jetpack-contact-form-icon:before { + .wp-media-buttons .add_media span.wp-media-buttons-icon::before, + .wp-media-buttons #insert-jetpack-contact-form span.jetpack-contact-form-icon::before { font-size: 20px !important; } diff --git a/src/wp-admin/css/farbtastic.css b/src/wp-admin/css/farbtastic.css index 2bb73bfc7ce8b..bc3232c1a24dc 100644 --- a/src/wp-admin/css/farbtastic.css +++ b/src/wp-admin/css/farbtastic.css @@ -1,41 +1,40 @@ - .farbtastic { - position: relative; + position: relative; } .farbtastic * { - position: absolute; - cursor: crosshair; + position: absolute; + cursor: crosshair; } .farbtastic, .farbtastic .wheel { - width: 195px; - height: 195px; + width: 195px; + height: 195px; } .farbtastic .color, .farbtastic .overlay { - top: 47px; - left: 47px; - width: 101px; - height: 101px; + top: 47px; + left: 47px; + width: 101px; + height: 101px; } .farbtastic .wheel { - background: url(../images/wheel.png) no-repeat; - width: 195px; - height: 195px; + background: url(../images/wheel.png) no-repeat; + width: 195px; + height: 195px; } .farbtastic .overlay { - background: url(../images/mask.png) no-repeat; + background: url(../images/mask.png) no-repeat; } .farbtastic .marker { - width: 17px; - height: 17px; - margin: -8px 0 0 -8px; - overflow: hidden; - background: url(../images/marker.png) no-repeat; + width: 17px; + height: 17px; + margin: -8px 0 0 -8px; + overflow: hidden; + background: url(../images/marker.png) no-repeat; } diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index f7e6accfce0fd..2ace16f733004 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -1,4 +1,3 @@ -/* Include margin and padding in the width calculation of input and textarea. */ input, select, textarea, @@ -143,10 +142,10 @@ input[type="radio"] { min-width: 1rem; -webkit-appearance: none; box-shadow: none; - transition: .05s border-color ease-in-out; + transition: 0.05s border-color ease-in-out; } -input[type="radio"]:checked + label:before { +input[type="radio"]:checked + label::before { color: #949494; } @@ -189,8 +188,8 @@ input[type="radio"]:checked::before { input[type="checkbox"]:checked::before { /* Use the "Yes" SVG Dashicon */ - content: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23ffffff%27%2F%3E%3C%2Fsvg%3E"); - content: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23ffffff%27%2F%3E%3C%2Fsvg%3E") / ''; + content: url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23ffffff%27%2F%3E%3C%2Fsvg%3E); + content: url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23ffffff%27%2F%3E%3C%2Fsvg%3E) / ""; margin: -0.1875rem 0 0 -0.25rem; height: 1.3125rem; width: 1.3125rem; @@ -268,24 +267,24 @@ textarea[readonly] { box-shadow: 0 0 2px rgba(214, 54, 56, 0.8); } -.form-table .form-required.form-invalid td:after { +.form-table .form-required.form-invalid td::after { content: "\f534"; - content: "\f534" / ''; - font: normal 20px/1 dashicons; + content: "\f534" / ""; + font: 400 20px/1 dashicons; color: #d63638; margin-left: -25px; vertical-align: middle; } /* Adjust error indicator for password layout */ -.form-table .form-required.user-pass1-wrap.form-invalid td:after { +.form-table .form-required.user-pass1-wrap.form-invalid td::after { content: ""; } -.form-table .form-required.user-pass1-wrap.form-invalid .password-input-wrapper:after { +.form-table .form-required.user-pass1-wrap.form-invalid .password-input-wrapper::after { content: "\f534"; - content: "\f534" / ''; - font: normal 20px/1 dashicons; + content: "\f534" / ""; + font: 400 20px/1 dashicons; color: #d63638; margin: 0 6px 0 -29px; vertical-align: middle; @@ -302,7 +301,7 @@ select.disabled, textarea:disabled, textarea.disabled { background: #f0f0f0; - border-color: #cccccc; + border-color: #ccc; box-shadow: none; color: #949494; } @@ -324,18 +323,14 @@ input[type="checkbox"][aria-disabled="true"], input[type="radio"]:disabled, input[type="radio"].disabled, input[type="radio"][aria-disabled="true"], -input[type="checkbox"]:disabled:checked:before, -input[type="checkbox"].disabled:checked:before, -input[type="radio"]:disabled:checked:before, -input[type="radio"].disabled:checked:before { +input[type="checkbox"]:disabled:checked::before, +input[type="checkbox"].disabled:checked::before, +input[type="radio"]:disabled:checked::before, +input[type="radio"].disabled:checked::before { opacity: 0.7; cursor: default; } -/*------------------------------------------------------------------------------ - 2.0 - Forms -------------------------------------------------------------------------------*/ - /* Select styles are based on the default button in buttons.css */ .wp-core-ui select { font-size: 14px; @@ -349,7 +344,7 @@ input[type="radio"].disabled:checked:before { max-width: 25rem; -webkit-appearance: none; /* The SVG is arrow-down-alt2 from Dashicons. */ - background: #fff url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%231e1e1e%22%2F%3E%3C%2Fsvg%3E') no-repeat right 8px top 55%; + background: #fff url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%231e1e1e%22%2F%3E%3C%2Fsvg%3E) no-repeat right 8px top 55%; background-size: 16px 16px; cursor: pointer; vertical-align: middle; @@ -377,7 +372,7 @@ input[type="radio"].disabled:checked:before { border-color: #dcdcde; background-color: #f6f7f7; /* The SVG is arrow-down-alt2 from Dashicons. */ - background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23a0a5aa%22%2F%3E%3C%2Fsvg%3E'); + background-image: url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23a0a5aa%22%2F%3E%3C%2Fsvg%3E); box-shadow: none; text-shadow: 0 1px 0 #fff; cursor: default; @@ -675,7 +670,7 @@ fieldset label, #pass-strength-result { background-color: #f0f0f0; - border: 1px solid #cccccc; + border: 1px solid #ccc; border-radius: 2px; color: #1e1e1e; margin: -1px 1px 5px; @@ -718,19 +713,23 @@ fieldset label, font-family: Consolas, Monaco, monospace; } -#pass1.short, #pass1-text.short { +#pass1.short, +#pass1-text.short { border-color: #e65054; } -#pass1.bad, #pass1-text.bad { +#pass1.bad, +#pass1-text.bad { border-color: #f86368; } -#pass1.good, #pass1-text.good { +#pass1.good, +#pass1-text.good { border-color: #f0c33c; } -#pass1.strong, #pass1-text.strong { +#pass1.strong, +#pass1-text.strong { border-color: #68de7c; } @@ -895,10 +894,6 @@ ul#add-to-blog-users { outline: 2px solid transparent; } -/*------------------------------------------------------------------------------ - 15.0 - Comments Screen -------------------------------------------------------------------------------*/ - .form-table { border-collapse: collapse; margin-top: 0.5em; @@ -992,17 +987,13 @@ table.form-table td .updated p { margin: 0.3em 0; } -/*------------------------------------------------------------------------------ - 18.0 - Users -------------------------------------------------------------------------------*/ - #profile-page .form-table textarea { width: 500px; margin-bottom: 6px; } #profile-page .form-table #rich_editing { - margin-right: 5px + margin-right: 5px; } #your-profile legend { @@ -1024,6 +1015,7 @@ table.form-table td .updated p { padding: 5px 15px 15px; box-sizing: border-box; margin-bottom: 3px; + cursor: pointer; } .color-option:hover, @@ -1037,6 +1029,7 @@ table.form-table td .updated p { border-spacing: 0; border-collapse: collapse; } + .color-palette .color-palette-shade, .color-palette td { display: table-cell; @@ -1045,10 +1038,6 @@ table.form-table td .updated p { border: none; } -.color-option { - cursor: pointer; -} - .create-application-password .form-field { max-width: 25em; } @@ -1083,15 +1072,11 @@ table.form-table td .updated p { display: block; } -/*------------------------------------------------------------------------------ - 19.0 - Tools -------------------------------------------------------------------------------*/ - .tool-box .title { margin: 8px 0; font-size: 18px; font-weight: 400; - line-height: 24px; + line-height: 1.3333; } .label-responsive { @@ -1114,9 +1099,9 @@ table.form-table td .updated p { padding: 16px 24px; min-width: 255px; max-width: 520px; - border: 1px solid rgb(0, 0, 0, 0.1); + border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; - background: #ffffff; + background: #fff; box-sizing: border-box; } @@ -1154,7 +1139,7 @@ table.form-table td .updated p { border-radius: 5px; border: 1px solid #c3c4c7; font-style: normal; - line-height: 16px; + line-height: 1.1429; font-size: 14px; text-decoration: none; } @@ -1163,7 +1148,7 @@ table.form-table td .updated p { outline: none; } -.pressthis-bookmarklet:after { +.pressthis-bookmarklet::after { content: ""; width: 70%; height: 55%; @@ -1176,7 +1161,7 @@ table.form-table td .updated p { box-shadow: 0 10px 8px rgba(0, 0, 0, 0.6); } -.pressthis-bookmarklet:hover:after { +.pressthis-bookmarklet:hover::after { transform: skew(20deg) rotate(9deg); box-shadow: 0 10px 8px rgba(0, 0, 0, 0.7); } @@ -1187,11 +1172,11 @@ table.form-table td .updated p { padding: 0 12px 8px 9px; } -.pressthis-bookmarklet span:before { - color: #787c82; - font: normal 20px/1 dashicons; +.pressthis-bookmarklet span::before { + color: #50575e; + font: 400 20px/1 dashicons; content: "\f157"; - content: "\f157" / ''; + content: "\f157" / ""; position: relative; display: inline-block; top: 4px; @@ -1218,10 +1203,6 @@ table.form-table td .updated p { color: #50575e; } -/*------------------------------------------------------------------------------ - 20.0 - Settings -------------------------------------------------------------------------------*/ - .timezone-info code { white-space: nowrap; } @@ -1297,10 +1278,6 @@ table.form-table td .updated p { display: inline-block; } -/*------------------------------------------------------------------------------ - 21.0 - Network Admin -------------------------------------------------------------------------------*/ - .setup-php textarea { max-width: 100%; } @@ -1335,10 +1312,6 @@ table.form-table td .updated p { margin-bottom: 4px; } -/*------------------------------------------------------------------------------ - Credentials check dialog for Install and Updates -------------------------------------------------------------------------------*/ - .request-filesystem-credentials-dialog { display: none; /* The customizer uses visibility: hidden on the body for full-overlays. */ @@ -1361,7 +1334,7 @@ table.form-table td .updated p { .request-filesystem-credentials-form legend { font-size: 1em; - padding: 1.33em 0; + padding: 1.33em 0 0; font-weight: 600; } @@ -1386,16 +1359,6 @@ table.form-table td .updated p { margin-bottom: 1em; } -.request-filesystem-credentials-dialog .ftp-username, -.request-filesystem-credentials-dialog .ftp-password { - float: left; - width: 48%; -} - -.request-filesystem-credentials-dialog .ftp-password { - margin-left: 4%; -} - .request-filesystem-credentials-dialog .request-filesystem-credentials-action-buttons { text-align: right; } @@ -1444,10 +1407,6 @@ table.form-table td .updated p { margin-bottom: 1em; } -.request-filesystem-credentials-form legend { - padding-bottom: 0; -} - .request-filesystem-credentials-form #ssh-keys legend { font-size: 1.3em; } @@ -1457,9 +1416,6 @@ table.form-table td .updated p { clear: both; } -/*------------------------------------------------------------------------------ - Privacy Policy settings screen -------------------------------------------------------------------------------*/ .tools-privacy-policy-page form { margin-bottom: 1.3em; } @@ -1490,39 +1446,47 @@ table.form-table td .updated p { .privacy_requests thead td:first-child, .privacy_requests tfoot td:first-child { - border-left: 4px solid #fff; + border-left: 4px solid transparent; } .privacy_requests tbody td.check-column { - border-left: 4px solid #fff; - background: #fff; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); -} - -.privacy_requests .row-actions { - color: #787c82; + border-left: 4px solid transparent; } .privacy_requests .row-actions.processing { position: static; } -.privacy_requests tbody .has-request-results th { - box-shadow: none; -} - .privacy_requests tbody .request-results th .notice { margin: 0 0 5px; } -.privacy_requests tbody td:not(.check-column), -.privacy_requests tbody th { - background: #fff; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); +/* + * The results row is injected after its request row, so it lands on the opposite + * stripe. Invert it to match. + */ +.privacy_requests tbody tr.request-results:nth-child(even) { + background-color: #f6f7f7; } -.privacy_requests tbody .has-request-results td { - box-shadow: none; +.privacy_requests tbody tr.request-results:nth-child(odd) { + background-color: transparent; +} + +/* + * Where supported, skip the injected rows in the stripe count instead, so they + * no longer shift the rows below. The rules above are the fallback. + */ +@supports selector(:nth-child(1 of :not(.request-results))) { + .privacy_requests tbody > tr:nth-child(odd), + .privacy_requests tbody > tr.request-results:nth-child(even) { + background-color: transparent; + } + + .privacy_requests tbody > tr:nth-child(odd of :not(.request-results)), + .privacy_requests tbody > tr:nth-child(odd of :not(.request-results)) + tr.request-results { + background-color: #f6f7f7; + } } .privacy_requests .next_steps .button { @@ -1531,12 +1495,10 @@ table.form-table td .updated p { } .privacy_requests tr.status-request-confirmed td.check-column { - background-color: #fff; border-left-color: #3858e9; } .privacy_requests tr.status-request-failed td.check-column { - background-color: #f6f7f7; border-left-color: #cc1818; } @@ -1576,9 +1538,6 @@ table.form-table td .updated p { margin: 0; } -/* =Media Queries --------------------------------------------------------------- */ - @media screen and (max-width: 782px) { /* Input Elements */ textarea { @@ -1620,10 +1579,10 @@ table.form-table td .updated p { margin-bottom: 8px; } - input[type="checkbox"]:checked:before, - .widefat th input[type="checkbox"]:before, - .widefat thead td input[type="checkbox"]:before, - .widefat tfoot td input[type="checkbox"]:before { + input[type="checkbox"]:checked::before, + .widefat th input[type="checkbox"]::before, + .widefat thead td input[type="checkbox"]::before, + .widefat tfoot td input[type="checkbox"]::before { width: 1.875rem; height: 1.875rem; margin: -0.1875rem -0.3125rem; @@ -1640,7 +1599,7 @@ table.form-table td .updated p { margin-top: -0.1875rem; } - input[type="radio"]:checked:before { + input[type="radio"]:checked::before { vertical-align: middle; width: 0.5625rem; height: 0.5625rem; @@ -1718,7 +1677,7 @@ table.form-table td .updated p { box-sizing: border-box; } - .form-table .form-required.form-invalid td:after { + .form-table .form-required.form-invalid td::after { float: right; margin: -30px 3px 0 0; } @@ -1727,7 +1686,6 @@ table.form-table td .updated p { input[type="search"].small-text, input[type="password"].small-text, input[type="number"].small-text, - input[type="number"].small-text, .form-table input[type="text"].small-text { width: auto; max-width: 4.375em; /* 70px, enough for 4 digits to fit comfortably */ @@ -1790,6 +1748,7 @@ table.form-table td .updated p { margin-bottom: 10px; vertical-align: middle; } + .js.plugins-php .search-box .wp-filter-search { width: 100%; margin-bottom: 0; @@ -2030,6 +1989,7 @@ table.form-table td .updated p { 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } diff --git a/src/wp-admin/css/install.css b/src/wp-admin/css/install.css index 03da01045a271..92f6f4962d4d7 100644 --- a/src/wp-admin/css/install.css +++ b/src/wp-admin/css/install.css @@ -32,7 +32,8 @@ a:focus { outline: 2px solid transparent; } -h1, h2 { +h1, +h2 { border-bottom: 1px solid #dcdcde; clear: both; color: #646970; @@ -45,23 +46,30 @@ h3 { font-size: 16px; } -p, li, dd, dt { +p, +li, +dd, +dt { padding-bottom: 2px; font-size: 14px; line-height: 1.5; } -code, .code { +code, +.code { font-family: Consolas, Monaco, monospace; } -ul, ol, dl { +ul, +ol, +dl { padding: 5px 5px 5px 22px; } a img { - border: 0 + border: 0; } + abbr { border: 0; font-variant: normal; @@ -87,7 +95,7 @@ fieldset { color: #3c434a; /* same as login.css */ font-size: 20px; font-weight: 400; - line-height: 1.3em; + line-height: 1.3; text-decoration: none; text-align: center; text-indent: -9999px; @@ -97,13 +105,17 @@ fieldset { .step { margin: 20px 0 15px; } -.step, th { + +.step, +th { text-align: left; padding: 0; } + .language-chooser.wp-core-ui .step .button.button-large { font-size: 14px; } + textarea { border: 1px solid #dcdcde; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; @@ -121,7 +133,7 @@ textarea { margin-bottom: 9px; padding: 10px 20px 10px 0; font-size: 14px; - vertical-align: top + vertical-align: top; } .form-table th { @@ -166,15 +178,14 @@ textarea { width: 100%; } -input, -submit { +input { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } -.form-table input[type=text], -.form-table input[type=email], -.form-table input[type=url], -.form-table input[type=password], +.form-table input[type="text"], +.form-table input[type="email"], +.form-table input[type="url"], +.form-table input[type="password"], #pass-strength-result { width: 100%; } @@ -209,13 +220,14 @@ submit { margin: 25px 0 20px; } -#error-page code, .code { +#error-page code, +.code { font-family: Consolas, Monaco, monospace; } .message { border-left: 4px solid #d63638; - padding: .7em .6em; + padding: 0.7em 0.6em; background-color: #fcf0f1; } @@ -225,26 +237,25 @@ submit { #pwd, #dbhost, #prefix, +/* stylelint-disable selector-id-pattern -- These ID selectors use a single underscore but cannot be changed because of backward compatibility reasons. */ #user_login, #admin_email, +/* stylelint-enable */ #pass1, #pass2 { direction: ltr; } - /* localization */ body.rtl, .rtl textarea, -.rtl input, -.rtl submit { +.rtl input { font-family: Tahoma, sans-serif; } :lang(he-il) body.rtl, :lang(he-il) .rtl textarea, -:lang(he-il) .rtl input, -:lang(he-il) .rtl submit { +:lang(he-il) .rtl input { font-family: Arial, sans-serif; } @@ -252,13 +263,13 @@ body.rtl, body { margin-top: 115px; } + #logo a { margin: -125px auto 30px; } } @media screen and (max-width: 782px) { - .form-table { margin-top: 0; } @@ -386,8 +397,8 @@ body.language-chooser { margin-right: 15px; } -.button.hide-if-no-js, -.hide-if-no-js { +.hide-if-no-js, +.button.wp-hide-pw.user-new-password-toggle.hide-if-no-js { display: none; } @@ -395,10 +406,8 @@ body.language-chooser { * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { - + (min-resolution: 120dpi) { .spinner { background-image: url(../images/spinner-2x.gif); } - } diff --git a/src/wp-admin/css/l10n.css b/src/wp-admin/css/l10n.css index 2d0b9b2145f69..18458c4872469 100644 --- a/src/wp-admin/css/l10n.css +++ b/src/wp-admin/css/l10n.css @@ -49,27 +49,37 @@ body.locale-he-il .press-this a.wp-switch-editor { } /* zh_CN: Enlarge dashboard widget 'Configure' link */ -.locale-zh-cn .hdnle a { font-size: 12px; } +.locale-zh-cn .hdnle a { + font-size: 12px; +} /* zn_CH: Enlarge font size, set font-size: normal */ -.locale-zh-cn form.upgrade .hint { font-style: normal; font-size: 100%; } +.locale-zh-cn form.upgrade .hint { + font-style: normal; + font-size: 100%; +} /* zh_CN: Enlarge font-size. */ -.locale-zh-cn #sort-buttons { font-size: 1em !important; } +.locale-zh-cn #sort-buttons { + font-size: 1em !important; +} /* de_DE: Text needs more space for translation */ .locale-de-de #customize-header-actions .button, .locale-de-de-formal #customize-header-actions .button { padding: 0 5px 1px; /* default 0 10px 1px */ } + .locale-de-de #customize-header-actions .spinner, .locale-de-de-formal #customize-header-actions .spinner { margin: 16px 3px 0; /* default 16px 4px 0 5px */ } + body[class*="locale-de-"] .inline-edit-row fieldset label span.title, body[class*="locale-de-"] .inline-edit-row fieldset.inline-edit-date legend { width: 7em; /* default 6em */ } + body[class*="locale-de-"] .inline-edit-row fieldset label span.input-text-wrap, body[class*="locale-de-"] .inline-edit-row fieldset .timestamp-wrap { margin-left: 7em; /* default 6em */ @@ -79,31 +89,39 @@ body[class*="locale-de-"] .inline-edit-row fieldset .timestamp-wrap { .locale-ru-ru #adminmenu { width: inherit; /* back-compat for pre-3.2 */ } + .locale-ru-ru #adminmenu, .locale-ru-ru #wpbody { margin-left: 0; /* back-compat for pre-3.2 */ } + .locale-ru-ru .inline-edit-row fieldset label span.title, .locale-ru-ru .inline-edit-row fieldset.inline-edit-date legend { width: 8em; /* default 6em */ } + .locale-ru-ru .inline-edit-row fieldset label span.input-text-wrap, .locale-ru-ru .inline-edit-row fieldset .timestamp-wrap { margin-left: 8em; /* default 6em */ } + .locale-ru-ru.post-php .tagsdiv .newtag, .locale-ru-ru.post-new-php .tagsdiv .newtag { width: 165px; /* default 180px - 15px */ } + .locale-ru-ru.press-this .posting { margin-right: 277px; /* default 252px + 25px */ } + .locale-ru-ru .press-this-sidebar { width: 265px; /* default 240px + 25px */ } + .locale-ru-ru #customize-header-actions .button { padding: 0 5px 1px; /* default 0 10px 1px */ } + .locale-ru-ru #customize-header-actions .spinner { margin: 16px 3px 0; /* default 16px 4px 0 5px */ } @@ -113,6 +131,7 @@ body[class*="locale-de-"] .inline-edit-row fieldset .timestamp-wrap { .locale-lt-lt .inline-edit-row fieldset.inline-edit-date legend { width: 8em; /* default 6em */ } + .locale-lt-lt .inline-edit-row fieldset label span.input-text-wrap, .locale-lt-lt .inline-edit-row fieldset .timestamp-wrap { margin-left: 8em; /* default 6em */ diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css index 8b03e3c08d353..f6105ad5a59fb 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -58,14 +58,14 @@ background-color: #646970; color: #fff; font-size: 11px; - line-height: 1.90909090; + line-height: 1.9090909; text-align: center; } -.column-response .post-com-count-no-comments:after, -.column-response .post-com-count-approved:after, -.column-comments .post-com-count-no-comments:after, -.column-comments .post-com-count-approved:after { +.column-response .post-com-count-no-comments::after, +.column-response .post-com-count-approved::after, +.column-comments .post-com-count-no-comments::after, +.column-comments .post-com-count-approved::after { content: ""; display: block; margin-left: 8px; @@ -82,10 +82,10 @@ background: #3858e9; } -.column-response a.post-com-count-approved:hover:after, -.column-response a.post-com-count-approved:focus:after, -.column-comments a.post-com-count-approved:hover:after, -.column-comments a.post-com-count-approved:focus:after { +.column-response a.post-com-count-approved:hover::after, +.column-response a.post-com-count-approved:focus::after, +.column-comments a.post-com-count-approved:hover::after, +.column-comments a.post-com-count-approved:focus::after { border-top-color: #3858e9; } @@ -114,7 +114,7 @@ /* comments */ .commentlist li { - padding: 1em 1em .2em; + padding: 1em 1em 0.2em; margin: 0; border-bottom: 1px solid #c3c4c7; } @@ -126,7 +126,7 @@ .commentlist p { padding: 0; - margin: 0 0 .8em; + margin: 0 0 0.8em; } #submitted-on, @@ -165,7 +165,7 @@ #replyrow legend { margin: 0; - padding: .2em 5px 0; + padding: 0.2em 5px 0; font-size: 13px; line-height: 1.4; font-weight: 600; @@ -269,10 +269,10 @@ th .comment-grey-bubble { top: 2px; } -th .comment-grey-bubble:before { +th .comment-grey-bubble::before { content: "\f101"; - content: "\f101" / ''; - font: normal 20px/.5 dashicons; + content: "\f101" / ""; + font: 400 20px/0.5 dashicons; display: inline-block; padding: 0; top: 4px; @@ -358,7 +358,7 @@ th.plugin-title strong, td.column-title strong, td.plugin-title strong { display: block; - margin-bottom: .2em; + margin-bottom: 0.2em; font-size: 14px; } @@ -483,8 +483,8 @@ table.media .column-title .filename { margin-left: 7px; } -.sorting-indicator:before { - font: normal 20px/1 dashicons; +.sorting-indicator::before { + font: 400 20px/1 dashicons; display: inline-block; padding: 0; top: -4px; @@ -498,35 +498,35 @@ table.media .column-title .filename { color: #a7aaad; } -.sorting-indicator.asc:before { +.sorting-indicator.asc::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } -.sorting-indicator.desc:before { +.sorting-indicator.desc::before { content: "\f140"; - content: "\f140" / ''; + content: "\f140" / ""; } -th.sorted.desc .sorting-indicator.desc:before { +th.sorted.desc .sorting-indicator.desc::before { color: #1d2327; } -th.sorted.asc .sorting-indicator.asc:before { +th.sorted.asc .sorting-indicator.asc::before { color: #1d2327; } -th.sorted.asc a:focus .sorting-indicator.asc:before, -th.sorted.asc:hover .sorting-indicator.asc:before, -th.sorted.desc a:focus .sorting-indicator.desc:before, -th.sorted.desc:hover .sorting-indicator.desc:before { +th.sorted.asc a:focus .sorting-indicator.asc::before, +th.sorted.asc:hover .sorting-indicator.asc::before, +th.sorted.desc a:focus .sorting-indicator.desc::before, +th.sorted.desc:hover .sorting-indicator.desc::before { color: #a7aaad; } -th.sorted.asc a:focus .sorting-indicator.desc:before, -th.sorted.asc:hover .sorting-indicator.desc:before, -th.sorted.desc a:focus .sorting-indicator.asc:before, -th.sorted.desc:hover .sorting-indicator.asc:before { +th.sorted.asc a:focus .sorting-indicator.desc::before, +th.sorted.asc:hover .sorting-indicator.desc::before, +th.sorted.desc a:focus .sorting-indicator.asc::before, +th.sorted.desc:hover .sorting-indicator.asc::before { color: #1d2327; } @@ -547,7 +547,7 @@ th.sorted.desc:hover .sorting-indicator.asc:before { cursor: pointer; } -.wp-list-table .toggle-row:focus:before { +.wp-list-table .toggle-row:focus::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; @@ -557,7 +557,7 @@ th.sorted.desc:hover .sorting-indicator.asc:before { box-shadow: none; } -.wp-list-table .toggle-row:before { +.wp-list-table .toggle-row::before { position: absolute; top: -5px; left: 10px; @@ -566,16 +566,16 @@ th.sorted.desc:hover .sorting-indicator.asc:before { padding: 1px 2px 1px 0; color: #3c434a; /* same as table headers sort arrows */ content: "\f140"; - content: "\f140" / ''; - font: normal 20px/1 dashicons; + content: "\f140" / ""; + font: 400 20px/1 dashicons; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -.wp-list-table .is-expanded .toggle-row:before { +.wp-list-table .is-expanded .toggle-row::before { content: "\f142"; - content: "\f142" / ''; + content: "\f142" / ""; } .check-column { @@ -613,12 +613,12 @@ th.sorted.desc:hover .sorting-indicator.asc:before { width: 16px; } -.locked-indicator-icon:before { +.locked-indicator-icon::before { color: #8c8f94; content: "\f160"; - content: "\f160" / ''; + content: "\f160" / ""; display: inline-block; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; vertical-align: middle; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -777,10 +777,10 @@ th.sorted a span { border: 1px solid transparent; } -.view-switch a:before { - color: #c3c4c7; +.view-switch a::before { + color: #757575; display: inline-block; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; vertical-align: middle; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -791,28 +791,28 @@ th.sorted a span { border-color: var(--wp-admin-theme-color, #3858e9); } -.view-switch a:hover:before, -.view-switch a:focus:before { - color: #787c82; +.view-switch a:hover::before, +.view-switch a:focus::before { + color: #1e1e1e; } -.view-switch a.current:before { +.view-switch a.current::before { color: #2271b1; } -.view-switch .view-list:before { +.view-switch .view-list::before { content: "\f163"; - content: "\f163" / ''; + content: "\f163" / ""; } -.view-switch .view-excerpt:before { +.view-switch .view-excerpt::before { content: "\f164"; - content: "\f164" / ''; + content: "\f164" / ""; } -.view-switch .view-grid:before { +.view-switch .view-grid::before { content: "\f509"; - content: "\f509" / ''; + content: "\f509" / ""; } .filter { @@ -824,6 +824,7 @@ th.sorted a span { margin-left: -10px; margin-top: 13px; } + .screen-per-page { width: 4em; } @@ -839,7 +840,7 @@ th.sorted a span { } #posts-filter fieldset legend { - padding: 0 0 .2em 1px; + padding: 0 0 0.2em 1px; } p.pagenav { @@ -882,10 +883,12 @@ p.pagenav { display: inline-block; } +/* stylelint-disable selector-class-pattern -- These class selectors use a single underscore but cannot be changed because of backward compatibility reasons. */ .row-actions .network_only, .row-actions .network_active { color: #000; } +/* stylelint-enable */ .no-js .row-actions, tr:hover .row-actions, @@ -900,7 +903,6 @@ tr:hover .row-actions, padding: 2px 0 0; } - /*------------------------------------------------------------------------------ 10.1 - Inline Editing ------------------------------------------------------------------------------*/ @@ -1036,7 +1038,7 @@ tr.inline-edit-row td { .inline-edit-row fieldset label, .inline-edit-row fieldset span.inline-edit-categories-label { display: block; - margin: .2em 0; + margin: 0.2em 0; line-height: 2.5; } @@ -1052,7 +1054,7 @@ tr.inline-edit-row td { } .inline-edit-row fieldset label.inline-edit-tags span.title { - margin: .2em 0; + margin: 0.2em 0; width: auto; } @@ -1080,15 +1082,15 @@ tr.inline-edit-row td { } .inline-edit-row .inline-edit-or { - margin: .2em 6px .2em 0; + margin: 0.2em 6px 0.2em 0; line-height: 2.5; } -.inline-edit-row .input-text-wrap input[type=text] { +.inline-edit-row .input-text-wrap input[type="text"] { width: 100%; } -.inline-edit-row fieldset label input[type=checkbox] { +.inline-edit-row fieldset label input[type="checkbox"] { vertical-align: middle; } @@ -1099,7 +1101,7 @@ tr.inline-edit-row td { } .inline-edit-row select, -.inline-edit-row input:where(:not([type=checkbox],[type=radio],[type=submit],[type=button])) { +.inline-edit-row input:where(:not([type="checkbox"],[type="radio"],[type="submit"],[type="button"])) { min-height: 32px; padding: 0 8px 0 8px; } @@ -1114,7 +1116,7 @@ tr.inline-edit-row td { } #wpbody-content .quick-edit-row fieldset .inline-edit-group label.alignleft:first-child { - margin-right: 0.5em + margin-right: 0.5em; } .inline-edit-col-right .input-text-wrap input.inline-edit-menu-order-input { @@ -1131,10 +1133,10 @@ tr.inline-edit-row td { float: left; } -.inline-edit-row fieldset input[name=jj], -.inline-edit-row fieldset input[name=hh], -.inline-edit-row fieldset input[name=mn], -.inline-edit-row fieldset input[name=aa] { +.inline-edit-row fieldset input[name="jj"], +.inline-edit-row fieldset input[name="hh"], +.inline-edit-row fieldset input[name="mn"], +.inline-edit-row fieldset input[name="aa"] { vertical-align: middle; text-align: center; padding: 0 4px; @@ -1184,14 +1186,14 @@ ul.cat-checklist { } ul.cat-checklist input[name="post_category[]"]:indeterminate::before { - content: ''; - border-top: 2px solid grey; + content: ""; + border-top: 2px solid #808080; width: 65%; height: 2px; position: absolute; - top: calc( 50% + 1px ); + top: calc(50% + 1px); left: 50%; - transform: translate( -50%, -50% ); + transform: translate(-50%, -50%); } #bulk-titles .ntdelbutton, @@ -1200,7 +1202,7 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { display: inline-block; margin: 0; padding: 3px 0; - line-height: 20px; + line-height: 1.5384; vertical-align: top; } @@ -1216,7 +1218,7 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { border-radius: 3px; } -#bulk-titles .ntdelbutton:before { +#bulk-titles .ntdelbutton::before { display: inline-block; vertical-align: top; } @@ -1239,8 +1241,8 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { padding: 8px 0 0 2px; } -.plugins tbody th.check-column input[type=checkbox], -.plugins tbody td.check-column input[type=checkbox] { +.plugins tbody th.check-column input[type="checkbox"], +.plugins tbody td.check-column input[type="checkbox"] { margin-top: 4px; } @@ -1287,11 +1289,6 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { list-style-type: disc; } -.plugins .row-actions { - font-size: 13px; - padding: 0; -} - .plugins .inactive td, .plugins .inactive th, .plugins .active td, @@ -1352,7 +1349,6 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { white-space: nowrap; } - .plugins .plugin-title .dashicons, .plugins .plugin-title img.plugin-icon, .plugins .plugin-title img.updates-table-screenshot { @@ -1362,7 +1358,7 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { height: 64px; } -.plugins .plugin-title .dashicons:before { +.plugins .plugin-title .dashicons::before { padding: 2px; background-color: #f0f0f1; box-shadow: inset 0 0 10px rgba(167, 170, 173, 0.15); @@ -1391,6 +1387,7 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { .plugins .row-actions { white-space: normal; min-width: 12em; + font-size: 13px; } .plugins .update .second, @@ -1452,21 +1449,21 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { color: #b32d2e; } -.plugin-card .update-now:before { +.plugin-card .update-now::before { color: #d63638; content: "\f463"; - content: "\f463" / ''; + content: "\f463" / ""; display: inline-block; - font: normal 16px/1.875 dashicons; /* line-height 1.875 = 30px to match button */ + font: 400 16px/1.875 dashicons; /* line-height 1.875 = 30px to match button */ margin: 0 5px 0 -2px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; vertical-align: top; } -.plugin-card .updating-message:before { +.plugin-card .updating-message::before { content: "\f463"; - content: "\f463" / ''; + content: "\f463" / ""; animation: rotation 2s infinite linear; } @@ -1474,19 +1471,20 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } } -.plugin-card .updated-message:before { +.plugin-card .updated-message::before { color: #68de7c; content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; } -.plugin-card .updated-message:before, -.plugin-card .updating-message:before { +.plugin-card .updated-message::before, +.plugin-card .updating-message::before { line-height: 1; position: relative; top: -2px; @@ -1528,9 +1526,9 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { } .plugin-card { - width: calc( 50% - 8px ); - background-color: #ffffff; - border: 1px solid rgb(0, 0, 0, 0.1); + width: calc(50% - 8px); + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; box-sizing: border-box; overflow: hidden; @@ -1538,13 +1536,13 @@ ul.cat-checklist input[name="post_category[]"]:indeterminate::before { @media screen and (min-width: 1600px) { .plugin-card { - width: calc( (100% - 32px) / 3 ); + width: calc((100% - 32px) / 3); } } @media screen and (min-width: 2300px) { .plugin-card { - width: calc( (100% - 48px) / 4 ); + width: calc((100% - 48px) / 4); } } @@ -1569,18 +1567,21 @@ div.action-links, margin-inline: 0; } -.plugin-card .name, .plugin-card .desc > p { +.plugin-card .name, +.plugin-card .desc > p { margin-left: 148px; } @media (min-width: 1101px) { - .plugin-card .name, .plugin-card .desc > p { + .plugin-card .name, + .plugin-card .desc > p { margin-right: 128px; } } @media (min-width: 481px) and (max-width: 781px) { - .plugin-card .name, .plugin-card .desc > p { + .plugin-card .name, + .plugin-card .desc > p { margin-right: 128px; } } @@ -1612,9 +1613,9 @@ div.action-links, align-items: center; display: flex; flex-wrap: wrap; - margin-top: .5em; + margin-top: 0.5em; column-gap: 1%; - row-gap: .5em; + row-gap: 0.5em; } .plugin-card .plugin-dependency:nth-child(2), @@ -1667,7 +1668,7 @@ div.action-links, clear: both; padding: 16px; background-color: #f6f7f7; - border-top: 1px solid rgb(0, 0, 0, 0.1); + border-top: 1px solid rgba(0, 0, 0, 0.1); overflow: hidden; } @@ -1711,11 +1712,11 @@ div.action-links, float: right; clear: right; width: 65%; - width: calc( 100% - 180px ); + width: calc(100% - 180px); } -.plugin-card .column-compatibility span:before { - font: normal 20px/.5 dashicons; +.plugin-card .column-compatibility span::before { + font: 400 20px/0.5 dashicons; display: inline-block; padding: 0; top: 4px; @@ -1728,15 +1729,15 @@ div.action-links, color: #3c434a; } -.plugin-card .column-compatibility .compatibility-incompatible:before { +.plugin-card .column-compatibility .compatibility-incompatible::before { content: "\f158"; - content: "\f158" / ''; + content: "\f158" / ""; color: #d63638; } -.plugin-card .column-compatibility .compatibility-compatible:before { +.plugin-card .column-compatibility .compatibility-compatible::before { content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; color: #007017; } @@ -1771,6 +1772,7 @@ div.action-links, .wp-list-table tr.site-archived { background: #fcf0f1; } + .wp-list-table .site-spammed, .wp-list-table tr.site-spammed, .wp-list-table .site-mature, @@ -1980,13 +1982,14 @@ div.action-links, .plugins .active th.check-column, .plugins .active td.check-column, - .plugin-update-tr.active td { + .plugin-update-tr.active td, + .plugins tr.paused td.check-column { border-left: 4px solid transparent; } .plugins .active th.check-column input, .plugins .active td.check-column input { - margin-left: 0px; + margin-left: 0; } .plugins tr.active, @@ -1994,6 +1997,10 @@ div.action-links, border-left: 4px solid var(--wp-admin-theme-color); } + .plugins tr.active.paused { + border-left: 4px solid #b32d2e; + } + .wp-list-table .column-primary .toggle-row { display: block; } @@ -2067,10 +2074,10 @@ div.action-links, margin: 0; } - .column-response .post-com-count-no-comments:after, - .column-response .post-com-count-approved:after, - .column-comments .post-com-count-no-comments:after, - .column-comments .post-com-count-approved:after { + .column-response .post-com-count-no-comments::after, + .column-response .post-com-count-approved::after, + .column-comments .post-com-count-no-comments::after, + .column-comments .post-com-count-approved::after { content: none; } @@ -2147,8 +2154,8 @@ div.action-links, line-height: 1.5; } - .row-actions span.approve:before, - .row-actions span.unapprove:before { + .row-actions span.approve::before, + .row-actions span.unapprove::before { content: "| "; } @@ -2197,14 +2204,14 @@ div.action-links, } .inline-edit-row select, - .inline-edit-row input:where(:not([type=checkbox],[type=radio],[type=submit],[type=button])) { + .inline-edit-row input:where(:not([type="checkbox"],[type="radio"],[type="submit"],[type="button"])) { min-height: 40px; } - .inline-edit-row fieldset input[name=jj], - .inline-edit-row fieldset input[name=hh], - .inline-edit-row fieldset input[name=mn], - .inline-edit-row fieldset input[name=aa] { + .inline-edit-row fieldset input[name="jj"], + .inline-edit-row fieldset input[name="hh"], + .inline-edit-row fieldset input[name="mn"], + .inline-edit-row fieldset input[name="aa"] { font-size: 16px; line-height: 2; padding: 3px 4px; @@ -2215,7 +2222,7 @@ div.action-links, .inline-edit-row fieldset ul.cat-checklist label { padding: 6px 0; font-size: 16px; - line-height: 28px; + line-height: 1.75; } #bulk-titles .ntdelitem { @@ -2229,9 +2236,9 @@ div.action-links, overflow: hidden; } - #bulk-titles .ntdelbutton:before { + #bulk-titles .ntdelbutton::before { font-size: 20px; - line-height: 28px; + line-height: 1.4; } .inline-edit-row fieldset label span.title, @@ -2340,8 +2347,7 @@ div.action-links, .plugins tr.active + tr.inactive th.check-column, .plugins tr.active + tr.inactive td.check-column, - .plugins tr.active + tr.inactive td.column-description, - .plugins .plugin-update-tr:before { + .plugins tr.active + tr.inactive td.column-description { box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); } @@ -2351,13 +2357,8 @@ div.action-links, border-top: none; } - /* mimic the checkbox th */ - .plugins .plugin-update-tr:before { - content: ""; - display: table-cell; - } - .plugins #the-list .plugin-update-tr .plugin-update { + flex: 0 1 100%; border-left: none; } @@ -2365,12 +2366,6 @@ div.action-links, margin-left: 0; } - .plugins .active.update + .plugin-update-tr:before, - .plugins .active.updated + .plugin-update-tr:before { - background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); - border-left: 4px solid var(--wp-admin-theme-color); - } - .plugins .plugin-update-tr .update-message { margin-left: 0; } @@ -2411,7 +2406,7 @@ div.action-links, table.plugin-install td.column-name strong { font-size: 1.4em; - line-height: 1.6em; + line-height: 1.6; } table.plugin-install #the-list td { diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index 4765e604a938d..1489356612442 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -17,12 +17,9 @@ body { a { color: var(--wp-admin-theme-color-darker-10); transition-property: border, background, color; - transition-duration: .05s; + transition-duration: 0.05s; transition-timing-function: ease-in-out; text-underline-position: under; -} - -a { outline: 0; } @@ -160,7 +157,7 @@ p { } .login form.shake { - animation: shake 0.2s cubic-bezier(.19,.49,.38,.79) both; + animation: shake 0.2s cubic-bezier(0.19, 0.49, 0.38, 0.79) both; animation-iteration-count: 3; transform: translateX(0); } @@ -169,9 +166,11 @@ p { 25% { transform: translateX(-20px); } + 75% { transform: translateX(20px); } + 100% { transform: translateX(0); } @@ -184,6 +183,7 @@ p { } } +/* stylelint-disable-next-line selector-class-pattern -- This class selector uses a single underscore but cannot be changed because of backward compatibility reasons. */ .login-action-confirm_admin_email #login { width: 60vw; max-width: 650px; @@ -191,6 +191,7 @@ p { } @media screen and (max-width: 782px) { + /* stylelint-disable-next-line selector-class-pattern -- This class selector uses a single underscore but cannot be changed because of backward compatibility reasons. */ .login-action-confirm_admin_email #login { box-sizing: border-box; margin-top: 0; @@ -201,11 +202,23 @@ p { } .login form .forgetmenot { + display: flex; + align-items: center; + gap: 4px; + /* Matches the height of the Log In button beside it, so the row centers on it. */ + min-height: 40px; font-weight: 400; float: left; margin-bottom: 0; } +/* Centering aligns margin boxes, so margins left from the inline layout would offset these. */ +.login form .forgetmenot input[type="checkbox"], +.login form .forgetmenot label { + margin-top: 0; + margin-bottom: 0; +} + .login .button-primary { float: right; } @@ -237,7 +250,7 @@ p { .login .admin-email__heading { border-bottom: 1px #f0f0f1 solid; color: #50575e; - font-weight: normal; + font-weight: 400; padding-bottom: 0.5em; text-align: left; } @@ -257,6 +270,7 @@ p { } #login form .indicator-hint, +/* stylelint-disable-next-line selector-id-pattern -- This ID selector uses a single underscore but cannot be changed because of backward compatibility reasons. */ #login #reg_passmail { margin-bottom: 16px; } @@ -398,6 +412,7 @@ body.interim-login { width: auto; } +/* stylelint-disable-next-line selector-id-pattern -- This ID selector uses a single underscore but cannot be changed because of backward compatibility reasons. */ .interim-login #login_error, .interim-login.login .message { margin: 0 0 16px; @@ -476,14 +491,13 @@ input::-ms-reveal { } } - @media screen and (max-width: 782px) { - .interim-login input[type=checkbox] { + .interim-login input[type="checkbox"] { width: 1rem; height: 1rem; } - .interim-login input[type=checkbox]:checked:before { + .interim-login input[type="checkbox"]:checked::before { width: 1.3125rem; height: 1.3125rem; margin: -0.1875rem 0 0 -0.25rem; diff --git a/src/wp-admin/css/media.css b/src/wp-admin/css/media.css index 3d7b0c9455c83..08155c862049e 100644 --- a/src/wp-admin/css/media.css +++ b/src/wp-admin/css/media.css @@ -1,7 +1,6 @@ -/*------------------------------------------------------------------------------ - 14.0 - Media Screen -------------------------------------------------------------------------------*/ - +/** + * Media Screen + */ .media-item .describe { border-collapse: collapse; width: 100%; @@ -189,7 +188,7 @@ height: 22px; margin: 0 6px 7px; width: 200px; - line-height: 2em; + line-height: 2; padding: 0; overflow: hidden; border-radius: 22px; @@ -214,7 +213,7 @@ padding: 0; color: #fff; text-align: center; - line-height: 22px; + line-height: 1.6923; font-weight: 400; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } @@ -251,10 +250,9 @@ margin: 0 10px 0 15px; } -/*------------------------------------------------------------------------------ - 14.1 - Media Library -------------------------------------------------------------------------------*/ - +/** + * Media Library + */ .find-box { background-color: #fff; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); @@ -351,13 +349,13 @@ outline-offset: -2px; } -#find-posts-close:before { - font: normal 20px/36px dashicons; +#find-posts-close::before { + font: 400 20px/36px dashicons; vertical-align: top; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; content: "\f158"; - content: "\f158" / ''; + content: "\f158" / ""; } .find-box-buttons { @@ -381,7 +379,6 @@ } @media screen and (max-width: 660px) { - .find-box { top: 0; bottom: 0; @@ -665,9 +662,9 @@ border color while dragging a file over the uploader drop area */ overflow: hidden; } -.upload-php .media-modal-close .media-modal-icon:before { +.upload-php .media-modal-close .media-modal-icon::before { content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; font-size: 22px; } @@ -675,7 +672,7 @@ border color while dragging a file over the uploader drop area */ .edit-attachment-frame .edit-media-header .left, .edit-attachment-frame .edit-media-header .right { cursor: pointer; - color: #787c82; + color: #50575e; background-color: transparent; height: 50px; width: 50px; @@ -684,7 +681,7 @@ border color while dragging a file over the uploader drop area */ text-align: center; border: 0; border-left: 1px solid #dcdcde; - transition: color .1s ease-in-out, background .1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; } .upload-php .media-modal-close { @@ -705,9 +702,9 @@ border color while dragging a file over the uploader drop area */ right: 150px; /* leave space for prev/next/close */ } -.edit-attachment-frame .edit-media-header .right:before, -.edit-attachment-frame .edit-media-header .left:before { - font: normal 20px/50px dashicons !important; +.edit-attachment-frame .edit-media-header .right::before, +.edit-attachment-frame .edit-media-header .left::before { + font: 400 20px/50px dashicons !important; display: inline; font-weight: 300; } @@ -728,28 +725,29 @@ border color while dragging a file over the uploader drop area */ .upload-php .media-modal-close:focus, .edit-attachment-frame .edit-media-header .left:focus, .edit-attachment-frame .edit-media-header .right:focus { - /* Only visible in Windows High Contrast mode */ - outline: 2px solid transparent; - outline-offset: -2px; + /* Always visible also in Windows High Contrast mode */ + outline: 1px solid #c3c4c7; + outline-offset: -1px; } -.upload-php .media-modal-close:focus .media-modal-icon:before, -.upload-php .media-modal-close:hover .media-modal-icon:before { +.upload-php .media-modal-close:focus .media-modal-icon::before, +.upload-php .media-modal-close:hover .media-modal-icon::before { color: #000; } -.edit-attachment-frame .edit-media-header .left:before { +.edit-attachment-frame .edit-media-header .left::before { content: "\f341"; - content: "\f341" / ''; + content: "\f341" / ""; } -.edit-attachment-frame .edit-media-header .right:before { +.edit-attachment-frame .edit-media-header .right::before { content: "\f345"; - content: "\f345" / ''; + content: "\f345" / ""; } -.edit-attachment-frame .edit-media-header [disabled], -.edit-attachment-frame .edit-media-header [disabled]:hover { +.edit-attachment-frame .edit-media-header [aria-disabled="true"], +.edit-attachment-frame .edit-media-header [aria-disabled="true"]:hover, +.edit-attachment-frame .edit-media-header [aria-disabled="true"]:focus { color: #c3c4c7; background: inherit; cursor: default; @@ -793,7 +791,7 @@ border color while dragging a file over the uploader drop area */ margin: 0 auto 16px; max-width: 100%; max-height: 90%; - max-height: calc( 100% - 56px ); /* leave space for actions underneath */ + max-height: calc(100% - 56px); /* leave space for actions underneath */ background-image: linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7), linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7); background-position: 0 0, 10px 10px; background-size: 20px 20px; @@ -874,9 +872,9 @@ border color while dragging a file over the uploader drop area */ margin-left: 8px; } -/*------------------------------------------------------------------------------ - 14.2 - Image Editor -------------------------------------------------------------------------------*/ +/** + * Image Editor + */ .wp_attachment_details .attachment-alt-text { margin-bottom: 5px; } @@ -979,7 +977,7 @@ border color while dragging a file over the uploader drop area */ display: none; } -.imgedit-wait:before { +.imgedit-wait::before { content: ""; display: block; width: 20px; @@ -1028,9 +1026,9 @@ border color while dragging a file over the uploader drop area */ padding: 1em 0 0; } -.imgedit-menu .button:after, -.imgedit-menu .button:before { - font: normal 16px/1 dashicons; +.imgedit-menu .button::after, +.imgedit-menu .button::before { + font: 400 16px/1 dashicons; margin-right: 8px; vertical-align: middle; position: relative; @@ -1039,14 +1037,14 @@ border color while dragging a file over the uploader drop area */ -moz-osx-font-smoothing: grayscale; } -.imgedit-menu .imgedit-rotate.button:after { - content: '\f140'; +.imgedit-menu .imgedit-rotate.button::after { + content: "\f140"; margin-left: 2px; margin-right: 0; } -.imgedit-menu .imgedit-rotate.button[aria-expanded="true"]:after { - content: '\f142'; +.imgedit-menu .imgedit-rotate.button[aria-expanded="true"]::after { + content: "\f142"; } .imgedit-menu .button.disabled { @@ -1059,49 +1057,45 @@ border color while dragging a file over the uploader drop area */ transform: none; } -.imgedit-crop:before { +.imgedit-crop::before { content: "\f165"; - content: "\f165" / ''; + content: "\f165" / ""; } -.imgedit-scale:before { +.imgedit-scale::before { content: "\f211"; - content: "\f211" / ''; + content: "\f211" / ""; } -.imgedit-rotate:before { +.imgedit-rotate::before { content: "\f167"; - content: "\f167" / ''; + content: "\f167" / ""; } -.imgedit-undo:before { +.imgedit-undo::before { content: "\f171"; - content: "\f171" / ''; + content: "\f171" / ""; } -.imgedit-redo:before { +.imgedit-redo::before { content: "\f172"; - content: "\f172" / ''; + content: "\f172" / ""; } .imgedit-crop-wrap { position: relative; -} - -.imgedit-crop-wrap img { + padding: 20px; background-image: linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7), linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7); background-position: 0 0, 10px 10px; background-size: 20px 20px; } -.imgedit-crop-wrap { - padding: 20px; +.imgedit-crop-wrap img { background-image: linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7), linear-gradient(45deg, #c3c4c7 25%, transparent 25%, transparent 75%, #c3c4c7 75%, #c3c4c7); background-position: 0 0, 10px 10px; background-size: 20px 20px; } - .imgedit-crop { margin: 0 8px 0 0; } @@ -1147,7 +1141,7 @@ border color while dragging a file over the uploader drop area */ .imgedit-applyto .imgedit-label { display: block; - padding: .5em 0 0; + padding: 0.5em 0 0; } .imgedit-popup-menu, @@ -1164,7 +1158,7 @@ border color while dragging a file over the uploader drop area */ } .imgedit-popup-menu { - width: calc( 100% - 20px ); + width: calc(100% - 20px); position: absolute; background: #fff; padding: 10px; @@ -1282,7 +1276,8 @@ span.imgedit-scale-warn { margin-bottom: 0; } -audio, video { +audio, +video { display: inline-block; max-width: 100%; } @@ -1307,8 +1302,8 @@ audio, video { * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { - .imgedit-wait:before { + (min-resolution: 120dpi) { + .imgedit-wait::before { background-image: url(../images/spinner-2x.gif); } } @@ -1366,7 +1361,7 @@ audio, video { } /* Restructure image editor on narrow viewports. */ - .imgedit-crop-wrap img{ + .imgedit-crop-wrap img { width: 100%; } @@ -1456,8 +1451,9 @@ audio, video { height: 40px; } - .edit-attachment-frame .edit-media-header .right:before, - .edit-attachment-frame .edit-media-header .left:before { + .edit-attachment-frame .edit-media-header .right::before, + .edit-attachment-frame .edit-media-header .left::before { + /* stylelint-disable-next-line declaration-property-unit-allowed-list -- Used for dashicons. */ line-height: 40px !important; } @@ -1486,7 +1482,7 @@ audio, video { } @media only screen and (max-width: 640px), screen and (max-height: 400px) { - .upload-php .mode-grid .media-sidebar{ + .upload-php .mode-grid .media-sidebar { max-width: 100%; } } @@ -1495,6 +1491,7 @@ audio, video { .media-item .attachment-tools { align-items: baseline; } + .media-item .edit-attachment.copy-to-clipboard-container { flex-direction: column; } diff --git a/src/wp-admin/css/nav-menus.css b/src/wp-admin/css/nav-menus.css index 8e3eadaad53bc..9574e67286a1a 100644 --- a/src/wp-admin/css/nav-menus.css +++ b/src/wp-admin/css/nav-menus.css @@ -1,5 +1,3 @@ -/* nav-menu */ - /* @todo: determine if this is truly for nav menus only */ .no-js #message { display: block; @@ -67,7 +65,7 @@ ul.add-menu-item-tabs li { #menu-settings-column .posttypediv div.tabs-panel, #menu-settings-column .taxonomydiv div.tabs-panel { /* Allow space for content after tab panels in nav menu editor. */ - max-height: calc( 100% - 75px ); + max-height: calc(100% - 75px); height: 100%; } @@ -124,7 +122,7 @@ ul.add-menu-item-tabs li { #nav-menu-bulk-actions-bottom { margin: 1em 0; - margin: calc( 1em + 9px ) 0; + margin: calc(1em + 9px) 0; } .bulk-actions input.button { @@ -198,7 +196,7 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { appearance: none; font-size: inherit; border: 0; - line-height: 2.1em; + line-height: 2.1; background: none; cursor: pointer; text-decoration: underline; @@ -385,7 +383,7 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { } .customlinkdiv p { - margin-top: 0 + margin-top: 0; } #nav-menu-theme-locations .howto select { @@ -412,9 +410,12 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { font-size: 12px; margin-left: 20px; margin-top: 5px; + cursor: pointer; } -.button.right, .button-secondary.right, .button-primary.right { +.button.right, +.button-secondary.right, +.button-primary.right { float: right; } @@ -428,6 +429,9 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { } .button-controls { + display: flex; + align-items: center; + justify-content: space-between; clear: both; margin: 10px 0; } @@ -516,7 +520,7 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { margin-top: -3px; } -.menu-item-title input[type=checkbox] { +.menu-item-title input[type="checkbox"] { display: inline-block; margin-top: -4px; } @@ -562,7 +566,7 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { height: auto; min-height: 20px; max-width: 382px; - line-height: 2.30769230; + line-height: 2.3076923; overflow: hidden; word-wrap: break-word; } @@ -632,44 +636,149 @@ li.menu-item.ui-sortable-helper .menu-item-transport .menu-item-bar { } /* WARNING: The factor of 30px is hardcoded into the nav-menus JavaScript. */ -.menu-item-depth-0 { margin-left: 0; } -.menu-item-depth-1 { margin-left: 30px; } -.menu-item-depth-2 { margin-left: 60px; } -.menu-item-depth-3 { margin-left: 90px; } -.menu-item-depth-4 { margin-left: 120px; } -.menu-item-depth-5 { margin-left: 150px; } -.menu-item-depth-6 { margin-left: 180px; } -.menu-item-depth-7 { margin-left: 210px; } -.menu-item-depth-8 { margin-left: 240px; } -.menu-item-depth-9 { margin-left: 270px; } -.menu-item-depth-10 { margin-left: 300px; } -.menu-item-depth-11 { margin-left: 330px; } - -.menu-item-depth-0 .menu-item-transport { margin-left: 0; } -.menu-item-depth-1 .menu-item-transport { margin-left: -30px; } -.menu-item-depth-2 .menu-item-transport { margin-left: -60px; } -.menu-item-depth-3 .menu-item-transport { margin-left: -90px; } -.menu-item-depth-4 .menu-item-transport { margin-left: -120px; } -.menu-item-depth-5 .menu-item-transport { margin-left: -150px; } -.menu-item-depth-6 .menu-item-transport { margin-left: -180px; } -.menu-item-depth-7 .menu-item-transport { margin-left: -210px; } -.menu-item-depth-8 .menu-item-transport { margin-left: -240px; } -.menu-item-depth-9 .menu-item-transport { margin-left: -270px; } -.menu-item-depth-10 .menu-item-transport { margin-left: -300px; } -.menu-item-depth-11 .menu-item-transport { margin-left: -330px; } - -body.menu-max-depth-0 { min-width: 950px !important; } -body.menu-max-depth-1 { min-width: 980px !important; } -body.menu-max-depth-2 { min-width: 1010px !important; } -body.menu-max-depth-3 { min-width: 1040px !important; } -body.menu-max-depth-4 { min-width: 1070px !important; } -body.menu-max-depth-5 { min-width: 1100px !important; } -body.menu-max-depth-6 { min-width: 1130px !important; } -body.menu-max-depth-7 { min-width: 1160px !important; } -body.menu-max-depth-8 { min-width: 1190px !important; } -body.menu-max-depth-9 { min-width: 1220px !important; } -body.menu-max-depth-10 { min-width: 1250px !important; } -body.menu-max-depth-11 { min-width: 1280px !important; } +.menu-item-depth-0 { + margin-left: 0; +} + +.menu-item-depth-1 { + margin-left: 30px; +} + +.menu-item-depth-2 { + margin-left: 60px; +} + +.menu-item-depth-3 { + margin-left: 90px; +} + +.menu-item-depth-4 { + margin-left: 120px; +} + +.menu-item-depth-5 { + margin-left: 150px; +} + +.menu-item-depth-6 { + margin-left: 180px; +} + +.menu-item-depth-7 { + margin-left: 210px; +} + +.menu-item-depth-8 { + margin-left: 240px; +} + +.menu-item-depth-9 { + margin-left: 270px; +} + +.menu-item-depth-10 { + margin-left: 300px; +} + +.menu-item-depth-11 { + margin-left: 330px; +} + +.menu-item-depth-0 .menu-item-transport { + margin-left: 0; +} + +.menu-item-depth-1 .menu-item-transport { + margin-left: -30px; +} + +.menu-item-depth-2 .menu-item-transport { + margin-left: -60px; +} + +.menu-item-depth-3 .menu-item-transport { + margin-left: -90px; +} + +.menu-item-depth-4 .menu-item-transport { + margin-left: -120px; +} + +.menu-item-depth-5 .menu-item-transport { + margin-left: -150px; +} + +.menu-item-depth-6 .menu-item-transport { + margin-left: -180px; +} + +.menu-item-depth-7 .menu-item-transport { + margin-left: -210px; +} + +.menu-item-depth-8 .menu-item-transport { + margin-left: -240px; +} + +.menu-item-depth-9 .menu-item-transport { + margin-left: -270px; +} + +.menu-item-depth-10 .menu-item-transport { + margin-left: -300px; +} + +.menu-item-depth-11 .menu-item-transport { + margin-left: -330px; +} + +body.menu-max-depth-0 { + min-width: 950px !important; +} + +body.menu-max-depth-1 { + min-width: 980px !important; +} + +body.menu-max-depth-2 { + min-width: 1010px !important; +} + +body.menu-max-depth-3 { + min-width: 1040px !important; +} + +body.menu-max-depth-4 { + min-width: 1070px !important; +} + +body.menu-max-depth-5 { + min-width: 1100px !important; +} + +body.menu-max-depth-6 { + min-width: 1130px !important; +} + +body.menu-max-depth-7 { + min-width: 1160px !important; +} + +body.menu-max-depth-8 { + min-width: 1190px !important; +} + +body.menu-max-depth-9 { + min-width: 1220px !important; +} + +body.menu-max-depth-10 { + min-width: 1250px !important; +} + +body.menu-max-depth-11 { + min-width: 1280px !important; +} /* Menu item controls */ .item-type { @@ -730,7 +839,7 @@ body.menu-max-depth-11 { min-width: 1280px !important; } margin: 0; } -.nav-menus-php .item-edit:before { +.nav-menus-php .item-edit::before { margin-top: 10px; margin-left: 4px; width: 20px; @@ -738,11 +847,11 @@ body.menu-max-depth-11 { min-width: 1280px !important; } text-indent: -1px; /* account for the dashicon alignment */ } -.no-js.nav-menus-php .item-edit:before { +.no-js.nav-menus-php .item-edit::before { display: none; } -.rtl .nav-menus-php .item-edit:before { +.rtl .nav-menus-php .item-edit::before { text-indent: 1px; /* account for the dashicon alignment */ } @@ -750,7 +859,7 @@ body.menu-max-depth-11 { min-width: 1280px !important; } box-shadow: none; } -.nav-menus-php .item-edit:focus:before { +.nav-menus-php .item-edit:focus::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; @@ -796,7 +905,7 @@ body.menu-max-depth-11 { min-width: 1280px !important; } } .add-menu-item-pagelinks { - margin: .5em -10px; + margin: 0.5em -10px; text-align: center; } @@ -841,10 +950,6 @@ body.menu-max-depth-11 { min-width: 1280px !important; } padding-bottom: 7px; } -#cancel-save { - cursor: pointer; -} - /* Major/minor publishing actions (classes) */ .nav-menus-php .major-publishing-actions { padding: 10px 0; @@ -867,12 +972,6 @@ body.menu-max-depth-11 { min-width: 1280px !important; } display: block; } -.button-controls { - display: flex; - align-items: center; - justify-content: space-between; -} - .button-controls-customlinkdiv { justify-content: flex-end; } @@ -934,7 +1033,7 @@ body.menu-max-depth-11 { min-width: 1280px !important; } } .nav-menus-php .menu-name-label.howto span { - margin-top: 13px + margin-top: 13px; } #menu-name { @@ -1007,19 +1106,19 @@ body.menu-max-depth-11 { min-width: 1280px !important; } } @media only screen and (min-width: 783px) { - @supports (position: sticky) and (scroll-margin-bottom: 130px) { - + @supports (position: sticky) and (scroll-margin-bottom: 130px) { #nav-menu-footer { - position: sticky; - bottom: 0; - z-index: 10; - box-shadow: 0 -1px 0 0 #ddd; - } - - #save_menu_header { - display: none; - } - } + position: sticky; + bottom: 0; + z-index: 10; + box-shadow: 0 -1px 0 0 #ddd; + } + + /* stylelint-disable-next-line selector-id-pattern -- This ID selector uses a single underscore but cannot be changed because of backward compatibility reasons. */ + #save_menu_header { + display: none; + } + } } @media only screen and (max-width: 768px) { diff --git a/src/wp-admin/css/revisions.css b/src/wp-admin/css/revisions.css index da238456178fc..69ca277fab3d0 100644 --- a/src/wp-admin/css/revisions.css +++ b/src/wp-admin/css/revisions.css @@ -1,6 +1,3 @@ -/*------------------------------------------------------------------------------ - 11.2 - Post Revisions -------------------------------------------------------------------------------*/ .revisions-control-frame, .revisions-diff-frame { position: relative; @@ -75,9 +72,9 @@ vertical-align: middle; opacity: 0; width: 100%; - width: calc( 100% - 30px ); + width: calc(100% - 30px); top: 50%; - top: calc( 50% - 10px ); + top: calc(50% - 10px); transition: opacity 0.5s; } @@ -383,10 +380,6 @@ table.diff .diff-addedline ins { background-color: #fff; } -.revisions-tooltip { - display: none; -} - .arrow { width: 70px; height: 16px; @@ -398,7 +391,14 @@ table.diff .diff-addedline ins { z-index: 10000; } -.arrow:after { +.arrow::after { + content: ""; + position: absolute; + left: 20px; + top: -20px; + width: 25px; + height: 25px; + transform: rotate(45deg); z-index: 9999; background-color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); @@ -413,18 +413,8 @@ table.diff .diff-addedline ins { left: 20%; } -.arrow:after { - content: ""; - position: absolute; - left: 20px; - top: -20px; - width: 25px; - height: 25px; - transform: rotate(45deg); -} - .revisions-tooltip, -.revisions-tooltip-arrow:after { +.revisions-tooltip-arrow::after { border-width: 1px; border-style: solid; } @@ -455,9 +445,6 @@ div.revisions-controls > .wp-slider > .ui-slider-handle { width: 18px; z-index: 2; touch-action: none; -} - -.wp-slider .ui-slider-handle { background: #f6f7f7; border: 1px solid #c3c4c7; box-shadow: 0 1px 0 #c3c4c7; @@ -486,48 +473,48 @@ div.revisions-controls > .wp-slider > .ui-slider-handle { outline: 2px solid transparent; } -.wp-slider .ui-slider-handle:before { +.wp-slider .ui-slider-handle::before { background: none; position: absolute; top: 2px; left: 2px; color: #50575e; content: "\f229"; - content: "\f229" / ''; - font: normal 18px/1 dashicons; + content: "\f229" / ""; + font: 400 18px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -.wp-slider .ui-slider-handle:hover:before, -.wp-slider .ui-slider-handle.ui-state-hover:before { +.wp-slider .ui-slider-handle:hover::before, +.wp-slider .ui-slider-handle.ui-state-hover::before { color: #1d2327; } -.wp-slider .ui-slider-handle.from-handle:before, -.wp-slider .ui-slider-handle.to-handle:before { +.wp-slider .ui-slider-handle.from-handle::before, +.wp-slider .ui-slider-handle.to-handle::before { font-size: 20px !important; margin: -1px 0 0 -1px; } -.wp-slider .ui-slider-handle.from-handle:before { +.wp-slider .ui-slider-handle.from-handle::before { content: "\f139"; - content: "\f139" / ''; + content: "\f139" / ""; } -.wp-slider .ui-slider-handle.to-handle:before { +.wp-slider .ui-slider-handle.to-handle::before { content: "\f141"; - content: "\f141" / ''; + content: "\f141" / ""; } -.rtl .wp-slider .ui-slider-handle.from-handle:before { +.rtl .wp-slider .ui-slider-handle.from-handle::before { content: "\f141"; - content: "\f141" / ''; + content: "\f141" / ""; } -.rtl .wp-slider .ui-slider-handle.to-handle:before { +.rtl .wp-slider .ui-slider-handle.to-handle::before { content: "\f139"; - content: "\f139" / ''; + content: "\f139" / ""; right: -1px; } @@ -545,8 +532,8 @@ div.revisions-controls > .wp-slider > .ui-slider-handle { } .wp-slider.ui-slider-horizontal .ui-slider-handle { - top: -.25em; - margin-left: -.6em; + top: -0.25em; + margin-left: -0.6em; } .wp-slider.ui-slider-horizontal .ui-slider-range { @@ -562,14 +549,10 @@ div.revisions-controls > .wp-slider > .ui-slider-handle { right: 0; } -/* =Media Queries --------------------------------------------------------------- */ - /** - * HiDPI Displays + * Media Queries */ -@media print, - (min-resolution: 120dpi) { +@media print, (min-resolution: 120dpi) { .revision-tick.completed-false { background-image: url(../images/spinner-2x.gif); } diff --git a/src/wp-admin/css/site-health.css b/src/wp-admin/css/site-health.css index cf6c24e4a955c..a5b6f97e62c8c 100644 --- a/src/wp-admin/css/site-health.css +++ b/src/wp-admin/css/site-health.css @@ -61,6 +61,7 @@ are styled in the Privacy section of edit.css */ .green .site-health-progress #bar { stroke: #00a32a; } + .green .site-health-progress .site-health-progress-label { color: #00a32a; } @@ -68,13 +69,14 @@ are styled in the Privacy section of edit.css */ .orange .site-health-progress #bar { stroke: #dba617; } + .orange .site-health-progress .site-health-progress-label { color: #dba617; } .site-health-progress-label { font-weight: 600; - line-height: 20px; + line-height: 1.5384; margin-left: 0.3rem; } @@ -82,20 +84,18 @@ are styled in the Privacy section of edit.css */ 0% { stroke: #c3c4c7; } + 50% { stroke: var(--wp-admin-theme-color); } + 100% { stroke: #c3c4c7; } } .health-check-tabs-wrapper { - /* IE 11 */ - display: -ms-inline-grid; - -ms-grid-columns: 1fr 1fr 1fr 1fr; vertical-align: top; - /* modern browsers */ display: inline-grid; grid-template-columns: 1fr 1fr 1fr 1fr; } @@ -103,15 +103,16 @@ are styled in the Privacy section of edit.css */ .health-check-tabs-wrapper.tab-count-1 { grid-template-columns: 1fr; } + .health-check-tabs-wrapper.tab-count-2 { grid-template-columns: 1fr 1fr; } + .health-check-tabs-wrapper.tab-count-3 { grid-template-columns: 1fr 1fr 1fr; } .health-check-tab { - display: block; /* IE 11 */ text-decoration: none; color: inherit; padding: 0.5rem 1rem 1rem; @@ -124,6 +125,7 @@ are styled in the Privacy section of edit.css */ background: transparent; border: none; } + .health-check-offscreen-nav-wrapper:focus .health-check-offscreen-nav { left: initial; } @@ -136,24 +138,26 @@ are styled in the Privacy section of edit.css */ top: 100%; width: 13rem; } + .health-check-offscreen-nav-wrapper.visible .health-check-offscreen-nav { display: inline-block; } -.health-check-offscreen-nav:before { + +.health-check-offscreen-nav::before { position: absolute; content: ""; width: 0; height: 0; border-style: solid; border-width: 0 10px 5px; - border-color: transparent transparent #ffffff; + border-color: transparent transparent #fff; right: 20px; top: 5px; } .health-check-offscreen-nav .health-check-tab { background: #fff; - box-shadow: 0 2px 5px 0 rgba( 0, 0, 0, 0.75 ); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.75); } .health-check-offscreen-nav .health-check-tab.active { @@ -190,26 +194,26 @@ are styled in the Privacy section of edit.css */ .health-check-body .pass::before, .health-check-body .good::before { content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; color: #00a32a; } .health-check-body .warning::before { content: "\f460"; - content: "\f460" / ''; + content: "\f460" / ""; color: #dba617; } .health-check-body .info::before { content: "\f348"; - content: "\f348" / ''; + content: "\f348" / ""; color: #72aee6; } .health-check-body .fail::before, .health-check-body .error::before { content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; color: #d63638; } @@ -296,6 +300,11 @@ are styled in the Privacy section of edit.css */ } /* Styling unique to the dashboard widget. */ +/* stylelint-disable selector-id-pattern -- These ID selectors use a single underscore but cannot be changed because of backward compatibility reasons. */ +.no-js #dashboard_site_health { + display: none; +} + #dashboard_site_health .site-health-details { padding-left: 16px; } @@ -315,23 +324,24 @@ are styled in the Privacy section of edit.css */ column-gap: 16px; align-items: center; } + #dashboard_site_health .site-health-progress-label { margin-left: 0; } -.health-check-widget-title-section { - margin-bottom: 0; - text-align: center; -} - @media screen and (max-width: 480px) { #dashboard_site_health .health-check-widget { grid-template-columns: 100%; } } +/* stylelint-enable */ -@media screen and (max-width: 782px) { +.health-check-widget-title-section { + margin-bottom: 0; + text-align: center; +} +@media screen and (max-width: 782px) { .site-health-issues-wrapper .health-check-accordion-trigger { flex-direction: column; align-items: flex-start; @@ -364,4 +374,3 @@ are styled in the Privacy section of edit.css */ margin-bottom: 0; } } - diff --git a/src/wp-admin/css/site-icon.css b/src/wp-admin/css/site-icon.css index 93f36f093caf9..6783574249f5e 100644 --- a/src/wp-admin/css/site-icon.css +++ b/src/wp-admin/css/site-icon.css @@ -79,7 +79,7 @@ gap: 16px; } -.site-icon-preview:after { +.site-icon-preview::after { --after-size: 150%; aspect-ratio: 1/1; content: ""; @@ -87,7 +87,7 @@ position: absolute; top: 0; left: 0; - width: var(--after-size);; + width: var(--after-size); transform: translate(calc(var(--after-size) * -0.125), calc(var(--after-size) * -0.125)); filter: blur(5px); opacity: 0.5; diff --git a/src/wp-admin/css/themes.css b/src/wp-admin/css/themes.css index 24be8ac58c5be..a04dca590aacd 100644 --- a/src/wp-admin/css/themes.css +++ b/src/wp-admin/css/themes.css @@ -1,12 +1,6 @@ -/*------------------------------------------------------------------------------ - 16.0 - Themes -------------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ - 16.1 - Manage Themes -------------------------------------------------------------------------------*/ - +/** + * Manage Themes + */ .themes-php { overflow-y: scroll; } @@ -33,7 +27,7 @@ body.js .theme-browser.search-loading { align-items: center; position: relative; top: 0; - gap: .5rem; + gap: 0.5rem; width: 100%; justify-content: end; } @@ -64,8 +58,8 @@ body.js .theme-browser.search-loading { margin: 0 4% 4% 0; position: relative; width: 30.6%; - background: #ffffff; - border: 1px solid rgb(0, 0, 0, 0.1); + background: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; box-sizing: border-box; overflow: hidden; @@ -86,11 +80,11 @@ body.js .theme-browser.search-loading { height: 18px; margin: 0; padding: 16px 15px; - border-top: 1px solid rgb(0, 0, 0, 0.1); + border-top: 1px solid rgba(0, 0, 0, 0.1); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - background: #ffffff; + background: #fff; } /* Activate and Customize buttons, shown on hover and focus */ @@ -156,7 +150,7 @@ body.js .theme-browser.search-loading { transition: opacity 0.2s ease-in-out; } -.theme-browser .theme .theme-screenshot:after { +.theme-browser .theme .theme-screenshot::after { content: ""; display: block; padding-top: 66.66666%; /* using a 3/2 aspect ratio */ @@ -257,6 +251,7 @@ body.js .theme-browser.search-loading { .theme-browser .theme.active .theme-actions .button-primary { border-color: #fff; + margin-right: 0; } .theme-id-container { @@ -276,10 +271,6 @@ body.js .theme-browser.search-loading { box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1); } -.theme-browser .theme.active .theme-actions .button-primary { - margin-right: 0; -} - /* Active theme secondary buttons need white background for visibility on dark overlay */ .theme-browser .theme.active .theme-actions .button:not(.button-primary) { background: #fff; @@ -291,6 +282,22 @@ body.js .theme-browser.search-loading { .theme-browser .theme.active .theme-actions .button:not(.button-primary):focus { background: #fff; + box-shadow: + 0 0 0 var(--wp-admin-border-width-focus, 1.5px) #fff, + inset 0 0 0 1px var(--wp-admin-theme-color, #3858e9); + outline: 1px solid transparent; +} + +/* Active theme card: uses white outer ring against the colored banner. */ +.theme-browser .theme.active .theme-actions .button.disabled:focus { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) #fff, inset 0 0 0 1px var(--wp-admin-theme-color, #3858e9) !important; + outline: 1px solid transparent; +} + +/* Other theme cards: standard focus ring on the card white background. */ +.theme-browser .theme:not(.active) .theme-actions .button.disabled:focus { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9) !important; + outline: 1px solid transparent; } .theme-browser .theme .theme-author { @@ -328,7 +335,7 @@ body.js .theme-browser.search-loading { z-index: 1; } -.theme-browser .theme.add-new-theme a:after { +.theme-browser .theme.add-new-theme a::after { display: block; content: ""; background: transparent; @@ -345,15 +352,15 @@ body.js .theme-browser.search-loading { box-sizing: border-box; } -.theme-browser .theme.add-new-theme span:after { +.theme-browser .theme.add-new-theme span::after { background: #dcdcde; background: rgba(140, 143, 148, 0.1); border-radius: 50%; display: inline-block; content: "\f132"; - content: "\f132" / ''; + content: "\f132" / ""; -webkit-font-smoothing: antialiased; - font: normal 74px/115px dashicons; + font: 400 74px/115px dashicons; width: 100px; height: 100px; vertical-align: middle; @@ -369,7 +376,7 @@ body.js .theme-browser.search-loading { z-index: 4; } -.rtl .theme-browser .theme.add-new-theme span:after { +.rtl .theme-browser .theme.add-new-theme span::after { text-indent: 4px; } @@ -378,14 +385,14 @@ body.js .theme-browser.search-loading { background: none; } -.theme-browser .theme.add-new-theme a:hover span:after, -.theme-browser .theme.add-new-theme a:focus span:after { +.theme-browser .theme.add-new-theme a:hover span::after, +.theme-browser .theme.add-new-theme a:focus span::after { background: #fff; color: #2271b1; } -.theme-browser .theme.add-new-theme a:hover:after, -.theme-browser .theme.add-new-theme a:focus:after { +.theme-browser .theme.add-new-theme a:hover::after, +.theme-browser .theme.add-new-theme a:focus::after { border-color: transparent; color: #fff; background: #2271b1; @@ -448,15 +455,15 @@ body.js .theme-browser.search-loading { border: 0; border-left: 1px solid #dcdcde; background-color: transparent; - transition: color .1s ease-in-out, background .1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; } -.theme-overlay .theme-header .close:before { - font: normal 22px/50px dashicons !important; - color: #787c82; +.theme-overlay .theme-header .close::before { + font: 400 22px/50px dashicons !important; + color: #50575e; display: inline-block; content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; font-weight: 300; } @@ -464,7 +471,7 @@ body.js .theme-browser.search-loading { .theme-overlay .theme-header .right, .theme-overlay .theme-header .left { cursor: pointer; - color: #787c82; + color: #50575e; background-color: transparent; height: 48px; width: 54px; @@ -472,7 +479,7 @@ body.js .theme-browser.search-loading { text-align: center; border: 0; border-right: 1px solid #dcdcde; - transition: color .1s ease-in-out, background .1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; } .theme-overlay .theme-header .close:focus, @@ -486,8 +493,8 @@ body.js .theme-browser.search-loading { color: #000; } -.theme-overlay .theme-header .close:focus:before, -.theme-overlay .theme-header .close:hover:before { +.theme-overlay .theme-header .close:focus::before, +.theme-overlay .theme-header .close:hover::before { color: #000; } @@ -507,21 +514,21 @@ body.js .theme-browser.search-loading { cursor: inherit; } -.theme-overlay .theme-header .right:before, -.theme-overlay .theme-header .left:before { - font: normal 20px/50px dashicons !important; +.theme-overlay .theme-header .right::before, +.theme-overlay .theme-header .left::before { + font: 400 20px/50px dashicons !important; display: inline; font-weight: 300; } -.theme-overlay .theme-header .left:before { +.theme-overlay .theme-header .left::before { content: "\f341"; - content: "\f341" / ''; + content: "\f341" / ""; } -.theme-overlay .theme-header .right:before { +.theme-overlay .theme-header .right::before { content: "\f345"; - content: "\f345" / ''; + content: "\f345" / ""; } .theme-overlay .theme-wrap { @@ -627,7 +634,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); } -.theme-overlay .screenshot:after { +.theme-overlay .screenshot::after { content: ""; display: block; padding-top: 75%; /* using a 4/3 aspect ratio */ @@ -645,6 +652,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { position: absolute; width: 302px; } + .theme-overlay.small-screenshot .theme-info { margin-left: 350px; width: auto; @@ -662,7 +670,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { cursor: pointer; } -.theme-overlay .screenshot.thumb:after { +.theme-overlay .screenshot.thumb::after { content: ""; display: block; padding-top: 100%; /* using a 1/1 aspect ratio */ @@ -670,7 +678,6 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { .theme-overlay .screenshot.thumb img { cursor: pointer; - height: auto; position: absolute; left: 0; top: 0; @@ -859,7 +866,8 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { width: 22.7%; margin: 0 3% 3% 0; } - .theme-browser .theme .theme-screenshot:after { + + .theme-browser .theme .theme-screenshot::after { padding-top: 75%; /* using a 4/3 aspect ratio */ } @@ -919,6 +927,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { .theme-overlay .theme-info { width: 50%; } + .single-theme .theme-wrap { padding: 10px; } @@ -947,7 +956,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { .theme-browser.rendered .theme:hover .theme-screenshot img, .theme-browser.rendered .theme.focus .theme-screenshot img { - opacity: 1.0; + opacity: 1; } } @@ -1016,11 +1025,11 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { .theme-install-php .wp-filter p.search-box { display: grid; - row-gap: .5rem; + row-gap: 0.5rem; } - .theme-browser .theme.add-new-theme span:after { - font: normal 60px/90px dashicons; + .theme-browser .theme.add-new-theme span::after { + font: 400 60px/90px dashicons; width: 80px; height: 80px; top: 30%; @@ -1033,13 +1042,16 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { margin: 0 -12px 0 -10px; padding: 10px; } + .single-theme .theme-overlay .theme-about { padding: 10px; overflow: visible; } + .single-theme .current-label { display: none; } + .single-theme .theme-overlay .theme-actions { position: static; } @@ -1056,11 +1068,9 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { padding: 3px; } - -/*------------------------------------------------------------------------------ - 16.2 - Install Themes -------------------------------------------------------------------------------*/ - +/** + * Install Themes + */ .update-php .wrap { max-width: 40rem; } @@ -1070,18 +1080,18 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { background: #2271b1; } -.theme-browser .theme .notice-success p:before { +.theme-browser .theme .notice-success p::before { color: #68de7c; content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; display: inline-block; - font: normal 20px/1 'dashicons'; + font: 400 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; vertical-align: top; } -.theme-install.updated-message:before { +.theme-install.updated-message::before { content: ""; } @@ -1092,7 +1102,7 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { /* Override column gap adjustment in media library. */ @media only screen and (max-width: 1000px) { .theme-install-php .wp-filter p.search-box { - column-gap: .5rem; + column-gap: 0.5rem; } } @@ -1144,8 +1154,8 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap { .upload-theme .wp-upload-form input[type="file"], .upload-plugin .wp-upload-form input[type="file"] { background: transparent; - margin: 0; - padding: 30px 0 30px 30px; + margin: 0; + padding: 30px 0 30px 30px; } .wp-upload-form input[type="submit"].button { @@ -1188,6 +1198,7 @@ p.no-themes-local { margin: 20px 0; max-width: 100%; } + .upload-theme .install-help { font-size: 15px; padding: 20px 0 0; @@ -1224,13 +1235,13 @@ p.no-themes-local { .update-from-upload-comparison tr:last-child td { height: 1.4rem; - vertical-align: top; + vertical-align: top; } .update-from-upload-comparison tr:first-child th { - font-weight: bold; + font-weight: 700; height: 1.4rem; - vertical-align: bottom; + vertical-align: bottom; } .update-from-upload-comparison td.name-label { @@ -1250,10 +1261,9 @@ p.no-themes-local { margin-top: 1.4rem; } -/*------------------------------------------------------------------------------ - 16.3 - Custom Header Screen -------------------------------------------------------------------------------*/ - +/** + * Custom Header Screen + */ .appearance_page_custom-header #headimg { border: 1px solid #dcdcde; overflow: hidden; @@ -1284,11 +1294,9 @@ p.no-themes-local { vertical-align: middle; } - -/*------------------------------------------------------------------------------ - 16.4 - Custom Background Screen -------------------------------------------------------------------------------*/ - +/** + * Custom Background Screen + */ div#custom-background-image { min-height: 100px; border: 1px solid #dcdcde; @@ -1313,11 +1321,11 @@ div#custom-background-image img { } .background-position-control .background-position-center-icon, -.background-position-control .background-position-center-icon:before { +.background-position-control .background-position-center-icon::before { display: inline-block; line-height: 1; text-align: center; - transition: background-color .1s ease-in; + transition: background-color 0.1s ease-in; } .background-position-control .background-position-center-icon { @@ -1327,7 +1335,7 @@ div#custom-background-image img { width: 20px; } -.background-position-control .background-position-center-icon:before { +.background-position-control .background-position-center-icon::before { background-color: #50575e; border-radius: 50%; content: ""; @@ -1335,8 +1343,8 @@ div#custom-background-image img { width: 12px; } -.background-position-control .button:hover .background-position-center-icon:before, -.background-position-control input[type="radio"]:focus ~ .button .background-position-center-icon:before { +.background-position-control .button:hover .background-position-center-icon::before, +.background-position-control input[type="radio"]:focus ~ .button .background-position-center-icon::before { background-color: #1d2327; } @@ -1374,7 +1382,7 @@ div#custom-background-image img { } .background-position-control .button-group:first-child > label:first-child .dashicons { - transform: rotate( 45deg ); + transform: rotate(45deg); } .background-position-control .button-group:first-child > label:last-child .button { @@ -1382,7 +1390,7 @@ div#custom-background-image img { } .background-position-control .button-group:first-child > label:last-child .dashicons { - transform: rotate( -45deg ); + transform: rotate(-45deg); } .background-position-control .button-group:last-child > label:first-child .button { @@ -1390,7 +1398,7 @@ div#custom-background-image img { } .background-position-control .button-group:last-child > label:first-child .dashicons { - transform: rotate( -45deg ); + transform: rotate(-45deg); } .background-position-control .button-group:last-child > label:last-child .button { @@ -1398,25 +1406,30 @@ div#custom-background-image img { } .background-position-control .button-group:last-child > label:last-child .dashicons { - transform: rotate( 45deg ); + transform: rotate(45deg); } .background-position-control .button-group + .button-group { margin-top: -1px; } -/*------------------------------------------------------------------------------ - 23.0 - Full Overlay w/ Sidebar -------------------------------------------------------------------------------*/ - +/** + * Full Overlay w/ Sidebar + */ body.full-overlay-active { overflow: hidden; /* Hide all the content, the Customizer overlay is then made visible to be the only available content. */ visibility: hidden; } +/* Make sure the ARIA live regions are visible, as they inherit the hidden visibility from the body. */ +.a11y-speak-intro-text, +.a11y-speak-region { + visibility: visible; +} + .wp-full-overlay { - background: transparent; + background: #1d2327; z-index: 500000; position: fixed; overflow: visible; @@ -1447,6 +1460,7 @@ body.full-overlay-active { .wp-full-overlay.collapsed .wp-full-overlay-sidebar { overflow: visible; + margin-left: -300px; } .wp-full-overlay.collapsed, @@ -1458,10 +1472,6 @@ body.full-overlay-active { margin-left: 300px; } -.wp-full-overlay.collapsed .wp-full-overlay-sidebar { - margin-left: -300px; -} - @media screen and (min-width: 1667px) { .wp-full-overlay.expanded { margin-left: 18%; @@ -1482,7 +1492,7 @@ body.full-overlay-active { } } -.wp-full-overlay-sidebar:after { +.wp-full-overlay-sidebar::after { content: ""; display: block; position: absolute; @@ -1500,6 +1510,7 @@ body.full-overlay-active { top: 0; bottom: 0; height: 100%; + background-color: #f0f0f1; } .wp-full-overlay-sidebar .wp-full-overlay-header { @@ -1549,11 +1560,14 @@ body.full-overlay-active { width: 45px; height: 45px; background: #f0f0f1; + border-top: 0; border-right: 1px solid #dcdcde; + border-bottom: 0; + border-left: 0; color: #3c434a; cursor: pointer; text-decoration: none; - transition: color .1s ease-in-out, background .1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; } .theme-install-overlay .close-full-overlay:hover, @@ -1569,28 +1583,36 @@ body.full-overlay-active { box-shadow: none; } -.theme-install-overlay .close-full-overlay:before { - font: normal 22px/1 dashicons; +.theme-install-overlay .close-full-overlay:focus, +.theme-install-overlay .previous-theme:focus, +.theme-install-overlay .next-theme:focus { + /* Always visible also in Windows High Contrast mode */ + outline: 1px solid #c3c4c7; + outline-offset: -1px; +} + +.theme-install-overlay .close-full-overlay::before { + font: 400 22px/1 dashicons; content: "\f335"; - content: "\f335" / ''; + content: "\f335" / ""; position: relative; top: 7px; left: 13px; } -.theme-install-overlay .previous-theme:before { - font: normal 20px/1 dashicons; +.theme-install-overlay .previous-theme::before { + font: 400 20px/1 dashicons; content: "\f341"; - content: "\f341" / ''; + content: "\f341" / ""; position: relative; top: 6px; left: 14px; } -.theme-install-overlay .next-theme:before { - font: normal 20px/1 dashicons; +.theme-install-overlay .next-theme::before { + font: 400 20px/1 dashicons; content: "\f345"; - content: "\f345" / ''; + content: "\f345" / ""; position: relative; top: 6px; left: 13px; @@ -1605,20 +1627,11 @@ body.full-overlay-active { color: #c3c4c7; background: #f0f0f1; cursor: default; - pointer-events: none; } -.theme-install-overlay .close-full-overlay, -.theme-install-overlay .previous-theme, -.theme-install-overlay .next-theme { - border-left: 0; - border-top: 0; - border-bottom: 0; -} - -.theme-install-overlay .close-full-overlay:before, -.theme-install-overlay .previous-theme:before, -.theme-install-overlay .next-theme:before { +.theme-install-overlay .close-full-overlay::before, +.theme-install-overlay .previous-theme::before, +.theme-install-overlay .next-theme::before { top: 2px; left: 0; } @@ -1674,12 +1687,12 @@ body.full-overlay-active { display: none; } -.wp-full-overlay .collapse-sidebar-arrow:before { +.wp-full-overlay .collapse-sidebar-arrow::before { display: block; content: "\f148"; - content: "\f148" / ''; + content: "\f148" / ""; background: #f0f0f1; - font: normal 20px/1 dashicons; + font: 400 20px/1 dashicons; padding: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -1690,12 +1703,12 @@ body.full-overlay-active { } /* rtl:ignore */ -.wp-full-overlay.collapsed .collapse-sidebar-arrow:before, -.rtl .wp-full-overlay .collapse-sidebar-arrow:before { +.wp-full-overlay.collapsed .collapse-sidebar-arrow::before, +.rtl .wp-full-overlay .collapse-sidebar-arrow::before { transform: rotate(180.001deg); /* Firefox: promoting to its own layer to trigger anti-aliasing */ } -.rtl .wp-full-overlay.collapsed .collapse-sidebar-arrow:before { +.rtl .wp-full-overlay.collapsed .collapse-sidebar-arrow::before { transform: none; } @@ -1712,14 +1725,6 @@ body.full-overlay-active { /* Device/preview size toggles */ -.wp-full-overlay { - background: #1d2327; -} - -.wp-full-overlay-main { - background-color: #f0f0f1; -} - .expanded .wp-full-overlay-footer { position: fixed; bottom: 0; @@ -1727,7 +1732,7 @@ body.full-overlay-active { min-width: 299px; max-width: 599px; width: 18%; - width: calc( 18% - 1px ); + width: calc(18% - 1px); height: 45px; border-top: 1px solid #dcdcde; background: #f0f0f1; @@ -1755,9 +1760,9 @@ body.full-overlay-active { border-top: 1px solid transparent; border-bottom: 4px solid transparent; transition: - .15s color ease-in-out, - .15s background-color ease-in-out, - .15s border-color ease-in-out; + 0.15s color ease-in-out, + 0.15s background-color ease-in-out, + 0.15s border-color ease-in-out; } .wp-full-overlay-footer .devices button:focus { @@ -1765,10 +1770,10 @@ body.full-overlay-active { outline: none; } -.wp-full-overlay-footer .devices button:before { +.wp-full-overlay-footer .devices button::before { display: inline-block; -webkit-font-smoothing: antialiased; - font: normal 20px/20px "dashicons"; + font: 400 20px/20px dashicons; vertical-align: top; margin: 0 0 -2px; padding: 4px 8px; @@ -1789,28 +1794,28 @@ body.full-overlay-active { border-bottom-color: #2271b1; } -.wp-full-overlay-footer .devices button.active:before { +.wp-full-overlay-footer .devices button.active::before { color: #1d2327; } -.wp-full-overlay-footer .devices button:hover:before, -.wp-full-overlay-footer .devices button:focus:before { +.wp-full-overlay-footer .devices button:hover::before, +.wp-full-overlay-footer .devices button:focus::before { color: #2271b1; } -.wp-full-overlay-footer .devices .preview-desktop:before { +.wp-full-overlay-footer .devices .preview-desktop::before { content: "\f472"; - content: "\f472" / ''; + content: "\f472" / ""; } -.wp-full-overlay-footer .devices .preview-tablet:before { +.wp-full-overlay-footer .devices .preview-tablet::before { content: "\f471"; - content: "\f471" / ''; + content: "\f471" / ""; } -.wp-full-overlay-footer .devices .preview-mobile:before { +.wp-full-overlay-footer .devices .preview-mobile::before { content: "\f470"; - content: "\f470" / ''; + content: "\f470" / ""; } .wp-full-overlay-footer .devices .devices__preview-label { @@ -1825,7 +1830,7 @@ body.full-overlay-active { } } -.collapsed .wp-full-overlay-footer .devices button:before { +.collapsed .wp-full-overlay-footer .devices button::before { display: none; } @@ -1847,11 +1852,9 @@ body.full-overlay-active { left: 50%; } - -/*------------------------------------------------------------------------------ - 24.0 - Customize Loader -------------------------------------------------------------------------------*/ - +/** + * Customize Loader + */ .no-customize-support .hide-if-no-customize, .customize-support .hide-if-customize, .no-customize-support.wp-core-ui .hide-if-no-customize, @@ -1873,6 +1876,7 @@ body.full-overlay-active { right: 0; height: 100%; } + #customize-container { display: none; } @@ -1891,8 +1895,8 @@ body.full-overlay-active { .theme-install-overlay iframe { height: 100%; width: 100%; - z-index: 20; transition: opacity 0.3s; + isolation: isolate; /* Creates a new stacking context to make the iframe sit on top of the spinner. */ } #customize-controls { @@ -1948,7 +1952,7 @@ body.full-overlay-active { top: 0; } -.install-theme-info .theme-screenshot:after { +.install-theme-info .theme-screenshot::after { content: ""; display: block; padding-top: 66.66666666%; @@ -1976,8 +1980,8 @@ body.full-overlay-active { line-height: 2.30769231; /* 30px for 32px height with 13px font */ } -.theme-install-overlay .wp-full-overlay-header .button.updating-message:before, -.theme-install-overlay .wp-full-overlay-header .button.updated-message:before { +.theme-install-overlay .wp-full-overlay-header .button.updating-message::before, +.theme-install-overlay .wp-full-overlay-header .button.updated-message::before { line-height: 1.5; /* 30px (20px * 1.5) - matches the button above */ } @@ -1994,7 +1998,6 @@ body.full-overlay-active { .theme-install-overlay .wp-full-overlay-main { position: absolute; - z-index: 0; background-color: #f0f0f1; } @@ -2002,10 +2005,10 @@ body.full-overlay-active { background-color: #f0f0f1; } -#customize-preview.wp-full-overlay-main:before, -.customize-loading #customize-container:before, -#customize-controls .notice.notification-overlay.notification-loading:before, -.theme-install-overlay .wp-full-overlay-main:before { +#customize-preview.wp-full-overlay-main::before, +.customize-loading #customize-container::before, +#customize-controls .notice.notification-overlay.notification-loading::before, +.theme-install-overlay .wp-full-overlay-main::before { content: ""; display: block; width: 20px; @@ -2013,35 +2016,31 @@ body.full-overlay-active { position: absolute; left: 50%; top: 50%; - z-index: -1; margin: -10px 0 0 -10px; transform: translateZ(0); background: transparent url(../images/spinner.gif) no-repeat center center; background-size: 20px 20px; } -#customize-preview.wp-full-overlay-main.iframe-ready:before, -.theme-install-overlay.iframe-ready .wp-full-overlay-main:before { +#customize-preview.wp-full-overlay-main.iframe-ready::before, +.theme-install-overlay.iframe-ready .wp-full-overlay-main::before { background-image: none; } -/* =Media Queries --------------------------------------------------------------- */ - /** * HiDPI Displays */ @media print, - (min-resolution: 120dpi) { + (min-resolution: 120dpi) { .wp-full-overlay .collapse-sidebar-arrow { background-image: url(../images/arrows-2x.png); background-size: 15px 123px; } - #customize-preview.wp-full-overlay-main:before, - .customize-loading #customize-container:before, - #customize-controls .notice.notification-overlay.notification-loading:before, - .theme-install-overlay .wp-full-overlay-main:before { + #customize-preview.wp-full-overlay-main::before, + .customize-loading #customize-container::before, + #customize-controls .notice.notification-overlay.notification-loading::before, + .theme-install-overlay .wp-full-overlay-main::before { background-image: url(../images/spinner-2x.gif); } } @@ -2082,8 +2081,8 @@ body.full-overlay-active { box-sizing: border-box; } - .upload-plugin .wp-upload-form input[type=file], - .upload-theme .wp-upload-form input[type=file] { + .upload-plugin .wp-upload-form input[type="file"], + .upload-theme .wp-upload-form input[type="file"] { padding: 30px 0 30px 30px; width: 100%; } diff --git a/src/wp-admin/css/widgets.css b/src/wp-admin/css/widgets.css index 99039d3c7c66a..0e2782dd71121 100644 --- a/src/wp-admin/css/widgets.css +++ b/src/wp-admin/css/widgets.css @@ -1,5 +1,3 @@ -/* General Widgets Styles */ - .widget { margin: 0 auto 10px; position: relative; @@ -9,6 +7,7 @@ .widget.open { z-index: 99; } + .widget.open:focus-within { z-index: 100; } @@ -57,7 +56,7 @@ } .deleting .widget-title, -.deleting .widget-top .widget-action .toggle-indicator:before { +.deleting .widget-top .widget-action .toggle-indicator::before { color: #a7aaad; } @@ -124,16 +123,20 @@ background: transparent; text-align: center; } + .media-widget-control .media-widget-preview .notice { text-align: initial; } + .media-frame .media-widget-embed-notice p code, .media-widget-control .notice p code { padding: 0 3px 0 0; } + .media-frame .media-widget-embed-notice { margin-top: 16px; } + .media-widget-control .media-widget-preview img { max-width: 100%; vertical-align: middle; @@ -141,6 +144,7 @@ background-position: 0 0, 10px 10px; background-size: 20px 20px; } + .media-widget-control .media-widget-preview .wp-video-shortcode { background: #000; } @@ -171,7 +175,7 @@ } .media-widget-video-link .dashicons { - font: normal 60px/1 'dashicons'; + font: 400 60px/1 dashicons; position: relative; width: 100%; top: -90px; @@ -260,7 +264,6 @@ color: #fff; } - /* Widget Dragging Helpers */ .widget.ui-draggable-dragging { min-width: 100%; @@ -330,12 +333,12 @@ display: block; } -.sidebar-name .toggle-indicator:before { +.sidebar-name .toggle-indicator::before { padding: 1px 2px 1px 0; border-radius: 50%; } -.sidebar-name .handlediv:focus .toggle-indicator:before { +.sidebar-name .handlediv:focus .toggle-indicator::before { box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent; @@ -516,7 +519,7 @@ div#widgets-right .closed .widgets-sortables { /* Dragging a widget over a closed sidebar */ #widgets-right .widgets-holder-wrap.widget-hover { - border-color: #787c82; + border-color: #50575e; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); } @@ -555,7 +558,7 @@ div#widgets-right .closed .widgets-sortables { color: #646970; background: #f0f0f1; padding: 0 15px; - line-height: 3.30769230; + line-height: 3.3076923; border-left: 1px solid #dcdcde; } @@ -656,16 +659,10 @@ div#widgets-right .closed .widgets-sortables { cursor: default; } - /* Widgets Area Chooser */ .widget-liquid-left #widgets-left.chooser #available-widgets .widget, .widget-liquid-left #widgets-left.chooser .inactive-sidebar { transition: opacity 0.1s linear; -} - -.widget-liquid-left #widgets-left.chooser #available-widgets .widget, -.widget-liquid-left #widgets-left.chooser .inactive-sidebar { - /* -webkit-filter: blur(1px); */ opacity: 0.2; pointer-events: none; } @@ -734,12 +731,12 @@ div#widgets-right .widget-top:hover, color: #fff; } -.widgets-chooser .widgets-chooser-selected:before { +.widgets-chooser .widgets-chooser-selected::before { content: "\f147"; - content: "\f147" / ''; + content: "\f147" / ""; display: block; -webkit-font-smoothing: antialiased; - font: normal 26px/1 dashicons; + font: 400 26px/1 dashicons; color: #fff; position: absolute; top: 7px; @@ -764,9 +761,11 @@ div#widgets-right .widget-top:hover, .text-widget-fields { position: relative; } + .text-widget-fields [hidden] { display: none; } + .text-widget-fields .wp-pointer.wp-pointer-top { position: absolute; z-index: 3; @@ -774,10 +773,12 @@ div#widgets-right .widget-top:hover, right: 10px; left: 10px; } + .text-widget-fields .wp-pointer .wp-pointer-arrow { left: auto; right: 15px; } + .text-widget-fields .wp-pointer .wp-pointer-buttons { line-height: 1.4; } @@ -785,16 +786,15 @@ div#widgets-right .widget-top:hover, .custom-html-widget-fields > p > .CodeMirror { border: 1px solid #dcdcde; } + .custom-html-widget-fields code { padding-top: 1px; padding-bottom: 1px; } + ul.CodeMirror-hints { z-index: 101; /* Due to z-index 100 set on .widget.open */ } -.widget-control-actions .custom-html-widget-save-button.button.validation-blocked { - cursor: not-allowed; -} /* =Media Queries -------------------------------------------------------------- */ diff --git a/src/wp-admin/css/wp-tooltip.css b/src/wp-admin/css/wp-tooltip.css index e72c51a72781f..856de7e0bc9d2 100644 --- a/src/wp-admin/css/wp-tooltip.css +++ b/src/wp-admin/css/wp-tooltip.css @@ -67,7 +67,8 @@ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08); } -.wp-tooltip.wp-is-tooltip .wp-tooltip__bubble { +.wp-tooltip.wp-is-tooltip .wp-tooltip__bubble, +.wp-tooltip .wp-tooltip__hint { background: #000; color: #f0f0f0; text-align: center; @@ -75,7 +76,7 @@ line-height: 1.4; } -.wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__text { +.wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble:not(.wp-tooltip__hint) .wp-tooltip__text { display: block; padding-inline-end: 24px; } @@ -94,13 +95,14 @@ position-try-fallbacks: flip-block, flip-inline; } - .wp-tooltip.wp-is-tooltip .wp-tooltip__bubble { + .wp-tooltip.wp-is-tooltip .wp-tooltip__bubble, + .wp-tooltip .wp-tooltip__hint { margin: 0; } /* Arrow: gray border (::before) under a white fill (::after). */ - .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble::before, - .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble::after { + .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble:not(.wp-tooltip__hint)::before, + .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble:not(.wp-tooltip__hint)::after { content: ""; position: absolute; top: 100%; @@ -111,12 +113,12 @@ border-bottom: 0; } - .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble::before { + .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble:not(.wp-tooltip__hint)::before { margin-left: -8px; border-top-color: #c3c4c7; } - .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble::after { + .wp-tooltip:not(.wp-is-tooltip) .wp-tooltip__bubble:not(.wp-tooltip__hint)::after { margin-left: -7px; border-width: 7px; border-bottom: 0; diff --git a/src/wp-admin/customize.php b/src/wp-admin/customize.php index 6496c824c9b10..5acfefb2ac3fa 100644 --- a/src/wp-admin/customize.php +++ b/src/wp-admin/customize.php @@ -185,6 +185,12 @@ * @since 5.5.0 */ do_action( 'customize_controls_head' ); + +/** This filter is documented in wp-admin/admin-header.php */ +$additional_body_class = apply_filters( 'admin_body_class', '' ); +if ( is_string( $additional_body_class ) && '' !== $additional_body_class ) { + $body_class .= ' ' . $additional_body_class; +} ?> @@ -288,7 +294,7 @@ $class .= ' active'; } ?> - diff --git a/src/wp-admin/edit-form-advanced.php b/src/wp-admin/edit-form-advanced.php index 8c80b94c04ffc..8b1dd3d1f9604 100644 --- a/src/wp-admin/edit-form-advanced.php +++ b/src/wp-admin/edit-form-advanced.php @@ -67,9 +67,9 @@ * @name $post_ID * @var int */ -$post_ID = isset( $post_ID ) ? (int) $post_ID : 0; -$user_ID = isset( $user_ID ) ? (int) $user_ID : 0; -$action = $action ?? ''; +$post_ID = isset( $post_ID ) ? (int) $post_ID : 0; +$user_ID = isset( $user_ID ) ? (int) $user_ID : 0; +$action ??= ''; if ( (int) get_option( 'page_for_posts' ) === $post->ID && empty( $post->post_content ) ) { add_action( 'edit_form_after_title', '_wp_posts_page_notice' ); diff --git a/src/wp-admin/edit-form-blocks.php b/src/wp-admin/edit-form-blocks.php index a6d198ff15343..693919d3d5bf1 100644 --- a/src/wp-admin/edit-form-blocks.php +++ b/src/wp-admin/edit-form-blocks.php @@ -342,6 +342,7 @@ static function ( $classes ) { /** * Styles */ +// Prefetched for the block editor by wp_prefetch_admin_assets(), which needs updating if this changes. wp_enqueue_style( 'wp-edit-post' ); /** diff --git a/src/wp-admin/font-library.php b/src/wp-admin/font-library.php index abc2ea4f4da70..0daff32ba5bac 100644 --- a/src/wp-admin/font-library.php +++ b/src/wp-admin/font-library.php @@ -18,11 +18,11 @@ ); } -// Check if Gutenberg build files are available +// Check if the build files are available. if ( ! function_exists( 'wp_font_library_wp_admin_render_page' ) ) { wp_die( - '

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

' . - '

' . __( 'The Font Library requires Gutenberg build files. Please run npm install to build the necessary files.' ) . '

', + '

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

' . + '

' . __( 'The Font Library requires build files. Please build WordPress and try again.' ) . '

', 503 ); } diff --git a/src/wp-admin/images/about-texture.png b/src/wp-admin/images/about-texture.png index dd3254f3f0cb4..27758e5447ddc 100644 Binary files a/src/wp-admin/images/about-texture.png and b/src/wp-admin/images/about-texture.png differ diff --git a/src/wp-admin/images/browser-rtl.png b/src/wp-admin/images/browser-rtl.png index a4d369563b8b1..4135c755cdbb2 100644 Binary files a/src/wp-admin/images/browser-rtl.png and b/src/wp-admin/images/browser-rtl.png differ diff --git a/src/wp-admin/images/browser.png b/src/wp-admin/images/browser.png index 83ead4747b789..7bd43a31246ed 100644 Binary files a/src/wp-admin/images/browser.png and b/src/wp-admin/images/browser.png differ diff --git a/src/wp-admin/images/icons32-2x.png b/src/wp-admin/images/icons32-2x.png index b86b72725098d..21213bcfddb4e 100644 Binary files a/src/wp-admin/images/icons32-2x.png and b/src/wp-admin/images/icons32-2x.png differ diff --git a/src/wp-admin/images/icons32-vs-2x.png b/src/wp-admin/images/icons32-vs-2x.png index 54e2fb2f5fbb4..9b2dc61f39805 100644 Binary files a/src/wp-admin/images/icons32-vs-2x.png and b/src/wp-admin/images/icons32-vs-2x.png differ diff --git a/src/wp-admin/images/icons32-vs.png b/src/wp-admin/images/icons32-vs.png index e46d6bebb78eb..5b6154ecbe933 100644 Binary files a/src/wp-admin/images/icons32-vs.png and b/src/wp-admin/images/icons32-vs.png differ diff --git a/src/wp-admin/images/icons32.png b/src/wp-admin/images/icons32.png index e491b1a8d28b3..f72b25a248fbd 100644 Binary files a/src/wp-admin/images/icons32.png and b/src/wp-admin/images/icons32.png differ diff --git a/src/wp-admin/images/imgedit-icons-2x.png b/src/wp-admin/images/imgedit-icons-2x.png index 98dd4124047bf..5a588f3e8520a 100644 Binary files a/src/wp-admin/images/imgedit-icons-2x.png and b/src/wp-admin/images/imgedit-icons-2x.png differ diff --git a/src/wp-admin/images/imgedit-icons.png b/src/wp-admin/images/imgedit-icons.png index 0d544ee9b83b4..26a099fbd1633 100644 Binary files a/src/wp-admin/images/imgedit-icons.png and b/src/wp-admin/images/imgedit-icons.png differ diff --git a/src/wp-admin/images/mask.png b/src/wp-admin/images/mask.png index 0fc9cbe630948..edf22931475b3 100644 Binary files a/src/wp-admin/images/mask.png and b/src/wp-admin/images/mask.png differ diff --git a/src/wp-admin/images/media-button.png b/src/wp-admin/images/media-button.png index 752ee452321a7..ad81bb4623dca 100644 Binary files a/src/wp-admin/images/media-button.png and b/src/wp-admin/images/media-button.png differ diff --git a/src/wp-admin/images/menu-2x.png b/src/wp-admin/images/menu-2x.png index 7131763a59325..a99af044ee76e 100644 Binary files a/src/wp-admin/images/menu-2x.png and b/src/wp-admin/images/menu-2x.png differ diff --git a/src/wp-admin/images/menu-vs-2x.png b/src/wp-admin/images/menu-vs-2x.png index 99b382369ff8f..1eb445ca068e5 100644 Binary files a/src/wp-admin/images/menu-vs-2x.png and b/src/wp-admin/images/menu-vs-2x.png differ diff --git a/src/wp-admin/images/menu-vs.png b/src/wp-admin/images/menu-vs.png index fe281087de4f5..511193641a8df 100644 Binary files a/src/wp-admin/images/menu-vs.png and b/src/wp-admin/images/menu-vs.png differ diff --git a/src/wp-admin/images/menu.png b/src/wp-admin/images/menu.png index c1d15af82be52..a885ec7f5b0ef 100644 Binary files a/src/wp-admin/images/menu.png and b/src/wp-admin/images/menu.png differ diff --git a/src/wp-admin/images/post-formats.png b/src/wp-admin/images/post-formats.png index cae309e5d5ed7..4b711c8c32f5c 100644 Binary files a/src/wp-admin/images/post-formats.png and b/src/wp-admin/images/post-formats.png differ diff --git a/src/wp-admin/images/post-formats32-vs.png b/src/wp-admin/images/post-formats32-vs.png index f5653407321f2..0abd1fd4e1540 100644 Binary files a/src/wp-admin/images/post-formats32-vs.png and b/src/wp-admin/images/post-formats32-vs.png differ diff --git a/src/wp-admin/images/post-formats32.png b/src/wp-admin/images/post-formats32.png index 69ec095e2b30e..d65bf654a9743 100644 Binary files a/src/wp-admin/images/post-formats32.png and b/src/wp-admin/images/post-formats32.png differ diff --git a/src/wp-admin/images/w-logo-gray.png b/src/wp-admin/images/w-logo-gray.png index 435486e7ed70d..c6013b8c45327 100644 Binary files a/src/wp-admin/images/w-logo-gray.png and b/src/wp-admin/images/w-logo-gray.png differ diff --git a/src/wp-admin/images/w-logo-white.png b/src/wp-admin/images/w-logo-white.png index ed5efcdc00019..31ddf906d5243 100644 Binary files a/src/wp-admin/images/w-logo-white.png and b/src/wp-admin/images/w-logo-white.png differ diff --git a/src/wp-admin/images/wheel.png b/src/wp-admin/images/wheel.png index 9b9fdf4a37ade..5357d02108672 100644 Binary files a/src/wp-admin/images/wheel.png and b/src/wp-admin/images/wheel.png differ diff --git a/src/wp-admin/import.php b/src/wp-admin/import.php index ce17a70f20cf3..98ecd9bb3836a 100644 --- a/src/wp-admin/import.php +++ b/src/wp-admin/import.php @@ -118,8 +118,7 @@ // Looks like an importer is installed, but not active. $plugins = get_plugins( '/' . $plugin_slug ); if ( ! empty( $plugins ) ) { - $keys = array_keys( $plugins ); - $plugin_file = $plugin_slug . '/' . $keys[0]; + $plugin_file = $plugin_slug . '/' . array_key_first( $plugins ); $url = wp_nonce_url( add_query_arg( array( diff --git a/src/wp-admin/includes/admin-filters.php b/src/wp-admin/includes/admin-filters.php index 5337cc02c88c9..0fec0867cf418 100644 --- a/src/wp-admin/includes/admin-filters.php +++ b/src/wp-admin/includes/admin-filters.php @@ -48,6 +48,7 @@ add_action( 'admin_head', 'wp_admin_canonical_url' ); add_action( 'admin_head', 'wp_site_icon' ); add_action( 'admin_head', 'wp_admin_viewport_meta' ); +add_action( 'admin_head', 'wp_prefetch_admin_assets' ); add_action( 'customize_controls_head', 'wp_admin_viewport_meta' ); add_filter( 'nav_menu_meta_box_object', '_wp_nav_menu_meta_box_object' ); @@ -120,7 +121,6 @@ add_action( 'admin_init', 'default_password_nag_handler' ); add_action( 'admin_notices', 'default_password_nag' ); -add_action( 'admin_notices', 'new_user_email_admin_notice' ); add_action( 'profile_update', 'default_password_nag_edit_user', 10, 2 ); diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index 747bcc75e53eb..cbf412ce4c634 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -1747,7 +1747,7 @@ function wp_ajax_add_meta() { 'meta_value' => $value, 'meta_id' => $meta_id, ), - $c + $count ), 'position' => 0, 'supplemental' => array( 'postid' => $meta->post_id ), @@ -1874,6 +1874,20 @@ function wp_ajax_hidden_columns() { wp_die( 1 ); } +/** + * Handles the meta box reordering setting via Ajax. + * + * @since 7.2.0 + */ +function wp_ajax_meta_box_reordering() { + check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' ); + + $enabled = isset( $_POST['enabled'] ) && '1' === (string) $_POST['enabled']; + update_user_option( get_current_user_id(), 'meta_box_reordering', $enabled ? 'enabled' : 'disabled' ); + + wp_die( 1 ); +} + /** * Handles updating whether to display the welcome panel via AJAX. * @@ -2059,6 +2073,13 @@ function wp_ajax_menu_quick_search() { function wp_ajax_get_permalink() { check_ajax_referer( 'getpermalink', 'getpermalinknonce' ); $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0; + if ( ! $post_id ) { + // Bypass call to get_preview_post_link() for unspecified post ID. + wp_die( '' ); + } + if ( ! current_user_can( 'edit_post', $post_id ) ) { + wp_die( -1 ); + } wp_die( get_preview_post_link( $post_id ) ); } @@ -2070,8 +2091,15 @@ function wp_ajax_get_permalink() { function wp_ajax_sample_permalink() { check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' ); $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0; - $title = $_POST['new_title'] ?? ''; - $slug = $_POST['new_slug'] ?? null; + if ( ! $post_id ) { + // Bypass call to get_sample_permalink_html() for unspecified post ID. + wp_die( '' ); + } + if ( ! current_user_can( 'edit_post', $post_id ) ) { + wp_die( -1 ); + } + $title = $_POST['new_title'] ?? ''; + $slug = $_POST['new_slug'] ?? null; wp_die( get_sample_permalink_html( $post_id, $title, $slug ) ); } @@ -4615,6 +4643,12 @@ function wp_ajax_activate_plugin() { wp_send_json_error( $status ); } + // A network-only plugin is activated for the entire network. + if ( is_multisite() && is_network_only_plugin( $status['plugin'] ) && ! current_user_can( 'manage_network_plugins' ) ) { + $status['errorMessage'] = __( 'Sorry, you are not allowed to activate this plugin.' ); + wp_send_json_error( $status ); + } + if ( is_plugin_active( $status['plugin'] ) ) { $status['errorMessage'] = sprintf( /* translators: %s: Plugin name. */ diff --git a/src/wp-admin/includes/bookmark.php b/src/wp-admin/includes/bookmark.php index c64bac144c588..aae87b9abc60f 100644 --- a/src/wp-admin/includes/bookmark.php +++ b/src/wp-admin/includes/bookmark.php @@ -121,10 +121,13 @@ function wp_delete_link( $link_id ) { * @since 2.1.0 * * @param int $link_id Link ID to look up. - * @return int[] The IDs of the requested link's categories. + * @return int[]|WP_Error The IDs of the requested link's categories, or else a WP_Error if the `link_category` taxonomy was unregistered. */ function wp_get_link_cats( $link_id = 0 ) { $cats = wp_get_object_terms( $link_id, 'link_category', array( 'fields' => 'ids' ) ); + if ( is_wp_error( $cats ) ) { + return $cats; + } return array_unique( $cats ); } @@ -170,6 +173,8 @@ function get_link_to_edit( $link ) { * } * @param bool $wp_error Optional. Whether to return a WP_Error object on failure. Default false. * @return int|WP_Error The link ID on success. The value 0 or WP_Error on failure. + * + * @phpstan-return ( $wp_error is false ? int : int|WP_Error ) */ function wp_insert_link( $linkdata, $wp_error = false ) { global $wpdb; diff --git a/src/wp-admin/includes/class-bulk-upgrader-skin.php b/src/wp-admin/includes/class-bulk-upgrader-skin.php index f406d160e4a57..d81eba885ddcd 100644 --- a/src/wp-admin/includes/class-bulk-upgrader-skin.php +++ b/src/wp-admin/includes/class-bulk-upgrader-skin.php @@ -141,7 +141,18 @@ public function error( $errors ) { } $this->error = implode( ', ', $messages ); } - echo ''; + $js_function = <<<'JS' + ( selector ) => { + jQuery( selector ).hide(); + } + JS; + wp_print_inline_script_tag( + sprintf( + '( %s )( %s );', + $js_function, + wp_json_encode( '.waiting-' . $this->upgrader->update_current, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) + ) + ); } /** @@ -172,7 +183,18 @@ public function bulk_footer() { public function before( $title = '' ) { $this->in_loop = true; printf( '

' . $this->upgrader->strings['skin_before_update_header'] . '

', $title, $this->upgrader->update_current, $this->upgrader->update_count ); - echo ''; + $js_function = <<<'JS' + ( selector ) => { + jQuery( selector ).css( 'display', 'inline-block' ); + } + JS; + wp_print_inline_script_tag( + sprintf( + '( %s )( %s );', + $js_function, + wp_json_encode( '.waiting-' . $this->upgrader->update_current, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) + ) + ); // This progress messages div gets moved via JavaScript when clicking on "More details.". echo '

'; $this->flush_output(); @@ -200,7 +222,18 @@ public function after( $title = '' ) { ) ); - echo ''; + $js_function = <<<'JS' + ( selector ) => { + jQuery( selector ).show(); + } + JS; + wp_print_inline_script_tag( + sprintf( + '( %s )( %s );', + $js_function, + wp_json_encode( '#progress-' . $this->upgrader->update_current, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) + ) + ); } if ( $this->result && ! is_wp_error( $this->result ) ) { if ( ! $this->error ) { @@ -210,7 +243,18 @@ public function after( $title = '' ) { '

'; } - echo ''; + $js_function = <<<'JS' + ( selector ) => { + jQuery( selector ).hide(); + } + JS; + wp_print_inline_script_tag( + sprintf( + '( %s )( %s );', + $js_function, + wp_json_encode( '.waiting-' . $this->upgrader->update_current, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) + ) + ); } $this->reset(); diff --git a/src/wp-admin/includes/class-custom-background.php b/src/wp-admin/includes/class-custom-background.php index 7f8f23485086a..e147739162baa 100644 --- a/src/wp-admin/includes/class-custom-background.php +++ b/src/wp-admin/includes/class-custom-background.php @@ -593,8 +593,8 @@ public function ajax_background_add() { * @since 3.4.0 * @deprecated 3.5.0 * - * @param array $form_fields - * @return array $form_fields + * @param array $form_fields An array of attachment form fields. + * @return array Unmodified form fields. */ public function attachment_fields_to_edit( $form_fields ) { return $form_fields; @@ -604,8 +604,8 @@ public function attachment_fields_to_edit( $form_fields ) { * @since 3.4.0 * @deprecated 3.5.0 * - * @param array $tabs - * @return array $tabs + * @param array $tabs An array of media upload tabs. + * @return array Unmodified upload tabs. */ public function filter_upload_tabs( $tabs ) { return $tabs; diff --git a/src/wp-admin/includes/class-custom-image-header.php b/src/wp-admin/includes/class-custom-image-header.php index 97a1a16052d12..a4cf43b1ce26c 100644 --- a/src/wp-admin/includes/class-custom-image-header.php +++ b/src/wp-admin/includes/class-custom-image-header.php @@ -572,7 +572,7 @@ public function step_1() { $header_image_style .= 'height:' . $custom_header->height . 'px;'; } ?> -
+
step_2_manage_upload(); $attachment_id = $data['attachment_id']; $file = $data['file']; @@ -1138,8 +1138,8 @@ public function admin_page() { * * @since 3.4.0 * - * @param array $form_fields - * @return array $form_fields + * @param array $form_fields An array of attachment form fields. + * @return array Unmodified form fields. */ public function attachment_fields_to_edit( $form_fields ) { return $form_fields; @@ -1150,8 +1150,8 @@ public function attachment_fields_to_edit( $form_fields ) { * * @since 3.4.0 * - * @param array $tabs - * @return array $tabs + * @param array $tabs An array of media upload tabs. + * @return array Unmodified upload tabs. */ public function filter_upload_tabs( $tabs ) { return $tabs; @@ -1184,8 +1184,8 @@ final public function set_header_image( $choice ) { 'attachment_id' => $choice['attachment_id'], 'url' => $choice['url'], 'thumbnail_url' => $choice['url'], - 'height' => $choice['height'], - 'width' => $choice['width'], + 'height' => absint( $choice['height'] ), + 'width' => absint( $choice['width'] ), ); update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() ); @@ -1216,7 +1216,13 @@ final public function set_header_image( $choice ) { } } - set_theme_mod( 'header_image', sanitize_url( $header_image_data['url'] ) ); + $header_image_data['url'] = sanitize_url( $header_image_data['url'] ); + + if ( isset( $header_image_data['thumbnail_url'] ) ) { + $header_image_data['thumbnail_url'] = sanitize_url( $header_image_data['thumbnail_url'] ); + } + + set_theme_mod( 'header_image', $header_image_data['url'] ); set_theme_mod( 'header_image_data', $header_image_data ); } @@ -1589,9 +1595,8 @@ public function get_uploaded_header_images() { $alt_text_key = '_wp_attachment_image_alt'; foreach ( $header_images as &$header_image ) { - $header_meta = get_post_meta( $header_image['attachment_id'] ); - $header_image['timestamp'] = $header_meta[ $timestamp_key ] ?? ''; - $header_image['alt_text'] = $header_meta[ $alt_text_key ] ?? ''; + $header_image['timestamp'] = get_post_meta( $header_image['attachment_id'], $timestamp_key, true ); + $header_image['alt_text'] = get_post_meta( $header_image['attachment_id'], $alt_text_key, true ); } return $header_images; diff --git a/src/wp-admin/includes/class-language-pack-upgrader-skin.php b/src/wp-admin/includes/class-language-pack-upgrader-skin.php index b93ed6c8bc32e..be2c7caabed3a 100644 --- a/src/wp-admin/includes/class-language-pack-upgrader-skin.php +++ b/src/wp-admin/includes/class-language-pack-upgrader-skin.php @@ -16,6 +16,14 @@ * @see WP_Upgrader_Skin */ class Language_Pack_Upgrader_Skin extends WP_Upgrader_Skin { + /** + * The upgrader instance. + * + * @since 3.7.0 + * @var Language_Pack_Upgrader + */ + public $upgrader; + public $language_update = null; public $done_header = false; public $done_footer = false; diff --git a/src/wp-admin/includes/class-plugin-installer-skin.php b/src/wp-admin/includes/class-plugin-installer-skin.php index 13b4dd7097cc9..ecfb1f7bd59b5 100644 --- a/src/wp-admin/includes/class-plugin-installer-skin.php +++ b/src/wp-admin/includes/class-plugin-installer-skin.php @@ -16,6 +16,14 @@ * @see WP_Upgrader_Skin */ class Plugin_Installer_Skin extends WP_Upgrader_Skin { + /** + * The upgrader instance. + * + * @since 2.8.0 + * @var Plugin_Upgrader + */ + public $upgrader; + public $api; public $type; public $url; diff --git a/src/wp-admin/includes/class-plugin-upgrader-skin.php b/src/wp-admin/includes/class-plugin-upgrader-skin.php index 0e3e778360061..1505e3d3a4977 100644 --- a/src/wp-admin/includes/class-plugin-upgrader-skin.php +++ b/src/wp-admin/includes/class-plugin-upgrader-skin.php @@ -16,6 +16,13 @@ * @see WP_Upgrader_Skin */ class Plugin_Upgrader_Skin extends WP_Upgrader_Skin { + /** + * The upgrader instance. + * + * @since 2.8.0 + * @var Plugin_Upgrader + */ + public $upgrader; /** * Holds the plugin slug in the Plugin Directory. diff --git a/src/wp-admin/includes/class-plugin-upgrader.php b/src/wp-admin/includes/class-plugin-upgrader.php index f5290ff5258f6..53e8f4af6b5a1 100644 --- a/src/wp-admin/includes/class-plugin-upgrader.php +++ b/src/wp-admin/includes/class-plugin-upgrader.php @@ -356,7 +356,7 @@ public function bulk_upgrade( $plugins, $args = array() ) { ) ); - $this->skin->before( $result ); + $this->skin->before(); $this->skin->error( $result ); $this->skin->after(); } elseif ( isset( $upgrade_data->requires_php ) && ! is_php_version_compatible( $upgrade_data->requires_php ) ) { @@ -370,7 +370,7 @@ public function bulk_upgrade( $plugins, $args = array() ) { ) ); - $this->skin->before( $result ); + $this->skin->before(); $this->skin->error( $result ); $this->skin->after(); } else { @@ -542,9 +542,7 @@ public function plugin_info() { } // Assume the requested plugin is the first in the list. - $plugin_files = array_keys( $plugin ); - - return $this->result['destination_name'] . '/' . $plugin_files[0]; + return $this->result['destination_name'] . '/' . array_key_first( $plugin ); } /** diff --git a/src/wp-admin/includes/class-theme-installer-skin.php b/src/wp-admin/includes/class-theme-installer-skin.php index 70f3452606fdd..bd320ccb401c2 100644 --- a/src/wp-admin/includes/class-theme-installer-skin.php +++ b/src/wp-admin/includes/class-theme-installer-skin.php @@ -16,6 +16,14 @@ * @see WP_Upgrader_Skin */ class Theme_Installer_Skin extends WP_Upgrader_Skin { + /** + * The upgrader instance. + * + * @since 2.8.0 + * @var Theme_Upgrader + */ + public $upgrader; + public $api; public $type; public $url; diff --git a/src/wp-admin/includes/class-theme-upgrader-skin.php b/src/wp-admin/includes/class-theme-upgrader-skin.php index cd4c6c6db3b40..e8c60f5f57da7 100644 --- a/src/wp-admin/includes/class-theme-upgrader-skin.php +++ b/src/wp-admin/includes/class-theme-upgrader-skin.php @@ -17,6 +17,14 @@ */ class Theme_Upgrader_Skin extends WP_Upgrader_Skin { + /** + * The upgrader instance. + * + * @since 2.8.0 + * @var Theme_Upgrader + */ + public $upgrader; + /** * Holds the theme slug in the Theme Directory. * diff --git a/src/wp-admin/includes/class-theme-upgrader.php b/src/wp-admin/includes/class-theme-upgrader.php index 9a963d433cf7e..c665ca063122a 100644 --- a/src/wp-admin/includes/class-theme-upgrader.php +++ b/src/wp-admin/includes/class-theme-upgrader.php @@ -454,7 +454,7 @@ public function bulk_upgrade( $themes, $args = array() ) { ) ); - $this->skin->before( $result ); + $this->skin->before(); $this->skin->error( $result ); $this->skin->after(); } elseif ( isset( $upgrade_data['requires_php'] ) && ! is_php_version_compatible( $upgrade_data['requires_php'] ) ) { @@ -468,7 +468,7 @@ public function bulk_upgrade( $themes, $args = array() ) { ) ); - $this->skin->before( $result ); + $this->skin->before(); $this->skin->error( $result ); $this->skin->after(); } else { diff --git a/src/wp-admin/includes/class-wp-application-passwords-list-table.php b/src/wp-admin/includes/class-wp-application-passwords-list-table.php index 9a60853016fc5..a5e143e30eccb 100644 --- a/src/wp-admin/includes/class-wp-application-passwords-list-table.php +++ b/src/wp-admin/includes/class-wp-application-passwords-list-table.php @@ -147,6 +147,8 @@ protected function column_default( $item, $column_name ) { * @since 5.6.0 * * @param string $which The location of the bulk actions: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function display_tablenav( $which ) { ?> @@ -214,7 +216,12 @@ public function print_js_template_row() { $classes .= ' hidden'; } - printf( '', esc_attr( $classes ), esc_attr( wp_strip_all_tags( $display_name ) ) ); + // The primary column is a `` row header, matching the + // server-rendered markup in WP_List_Table::single_row_columns(). + $tag = $is_primary ? 'th' : 'td'; + $scope = $is_primary ? ' scope="row"' : ''; + + printf( '<%1$s class="%2$s" data-colname="%3$s"%4$s>', $tag, esc_attr( $classes ), esc_attr( wp_strip_all_tags( $display_name ) ), $scope ); switch ( $column_name ) { case 'name': @@ -259,7 +266,7 @@ public function print_js_template_row() { ''; } - echo ''; + echo ""; } echo ''; diff --git a/src/wp-admin/includes/class-wp-automatic-updater.php b/src/wp-admin/includes/class-wp-automatic-updater.php index cd9426c6ef88b..aa4db87effc2a 100644 --- a/src/wp-admin/includes/class-wp-automatic-updater.php +++ b/src/wp-admin/includes/class-wp-automatic-updater.php @@ -170,10 +170,10 @@ public function is_vcs_checkout( $context ) { * * @since 3.7.0 * - * @param bool $checkout Whether a VCS checkout was discovered at `$context` - * or ABSPATH, or anywhere higher. - * @param string $context The filesystem context (a path) against which - * filesystem status should be checked. + * @param bool $checkout Whether a VCS checkout was discovered at `$context` + * or ABSPATH, or anywhere higher. + * @param string $context The filesystem context (a path) against which + * filesystem status should be checked. */ return apply_filters( 'automatic_updates_is_vcs_checkout', $checkout, $context ); } @@ -1130,7 +1130,7 @@ protected function send_email( $type, $core_update, $result = null ) { * * @since 3.7.0 * - * @param array $email { + * @param array $email { * Array of email arguments that will be passed to wp_mail(). * * @type string $to The email recipient. An array of emails diff --git a/src/wp-admin/includes/class-wp-comments-list-table.php b/src/wp-admin/includes/class-wp-comments-list-table.php index 2b927a7f81a6a..7294f89d1bd3b 100644 --- a/src/wp-admin/includes/class-wp-comments-list-table.php +++ b/src/wp-admin/includes/class-wp-comments-list-table.php @@ -62,6 +62,8 @@ public function __construct( $args = array() ) { * @param string $name Comment author name. * @param int $comment_id Comment ID. * @return string Avatar with the user name. + * + * @phpstan-return non-falsy-string */ public function floated_admin_avatar( $name, $comment_id ) { $comment = get_comment( $comment_id ); diff --git a/src/wp-admin/includes/class-wp-community-events.php b/src/wp-admin/includes/class-wp-community-events.php index a31b3651b9a1c..d6a0c8161add9 100644 --- a/src/wp-admin/includes/class-wp-community-events.php +++ b/src/wp-admin/includes/class-wp-community-events.php @@ -39,7 +39,7 @@ class WP_Community_Events { * * @since 4.8.0 * - * @param int $user_id WP user ID. + * @param int $user_id WP user ID. * @param false|array $user_location { * Stored location data for the user. false to pass no location. * diff --git a/src/wp-admin/includes/class-wp-debug-data.php b/src/wp-admin/includes/class-wp-debug-data.php index aada2f88dfaa6..76e1cc2c9419f 100644 --- a/src/wp-admin/includes/class-wp-debug-data.php +++ b/src/wp-admin/includes/class-wp-debug-data.php @@ -643,6 +643,7 @@ private static function get_wp_media(): array { $imagick = new Imagick(); $imagemagick_version = $imagick->getVersion(); } else { + $imagick = null; $imagemagick_version = __( 'Not available' ); } @@ -694,7 +695,7 @@ private static function get_wp_media(): array { ); // If Imagick is used as our editor, provide some more information about its limitations. - if ( 'WP_Image_Editor_Imagick' === _wp_image_editor_choose() && isset( $imagick ) && $imagick instanceof Imagick ) { + if ( 'WP_Image_Editor_Imagick' === _wp_image_editor_choose() && $imagick instanceof Imagick ) { $limits = array( 'area' => ( defined( 'imagick::RESOURCETYPE_AREA' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_AREA ) ) : $not_available ), 'disk' => ( defined( 'imagick::RESOURCETYPE_DISK' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_DISK ) : $not_available ), diff --git a/src/wp-admin/includes/class-wp-internal-pointers.php b/src/wp-admin/includes/class-wp-internal-pointers.php index 9a2135b5279fd..22233884b4beb 100644 --- a/src/wp-admin/includes/class-wp-internal-pointers.php +++ b/src/wp-admin/includes/class-wp-internal-pointers.php @@ -109,8 +109,8 @@ public static function enqueue_scripts( $hook_suffix ) { * @since 3.3.0 * * @param string $pointer_id The pointer ID. - * @param string $selector The HTML elements, on which the pointer should be attached. - * @param array $args Arguments to be passed to the pointer JS (see wp-pointer.js). + * @param string $selector The HTML elements, on which the pointer should be attached. + * @param array $args Arguments to be passed to the pointer JS (see wp-pointer.js). */ private static function print_js( $pointer_id, $selector, $args ) { if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) ) { diff --git a/src/wp-admin/includes/class-wp-links-list-table.php b/src/wp-admin/includes/class-wp-links-list-table.php index ae1f50175c35b..6da144bf502ad 100644 --- a/src/wp-admin/includes/class-wp-links-list-table.php +++ b/src/wp-admin/includes/class-wp-links-list-table.php @@ -60,7 +60,7 @@ public function prepare_items() { 'hide_empty' => 0, ); - if ( 'all' !== $cat_id ) { + if ( 0 !== $cat_id ) { $args['category'] = $cat_id; } if ( ! empty( $s ) ) { diff --git a/src/wp-admin/includes/class-wp-list-table.php b/src/wp-admin/includes/class-wp-list-table.php index 5e6bcdb0d237c..a63719d1d3bb2 100644 --- a/src/wp-admin/includes/class-wp-list-table.php +++ b/src/wp-admin/includes/class-wp-list-table.php @@ -30,6 +30,13 @@ class WP_List_Table { * @since 3.1.0 * * @var array + * @phpstan-var array{ + * plural: string, + * singular: string, + * ajax: bool, + * screen: string|WP_Screen|null, + * ... + * } */ protected $_args; @@ -133,19 +140,27 @@ class WP_List_Table { * @param array|string $args { * Array or string of arguments. * - * @type string $plural Plural value used for labels and the objects being listed. - * This affects things such as CSS class-names and nonces used - * in the list table, e.g. 'posts'. Default empty. - * @type string $singular Singular label for an object being listed, e.g. 'post'. - * Default empty - * @type bool $ajax Whether the list table supports Ajax. This includes loading - * and sorting data, for example. If true, the class will call - * the _js_vars() method in the footer to provide variables - * to any scripts handling Ajax events. Default false. - * @type string $screen String containing the hook name used to determine the current - * screen. If left null, the current screen will be automatically set. - * Default null. + * @type string $plural Plural value used for labels and the objects being listed. + * This affects things such as CSS class-names and nonces used + * in the list table, e.g. 'posts'. Default empty. + * @type string $singular Singular label for an object being listed, e.g. 'post'. + * Default empty. + * @type bool $ajax Whether the list table supports Ajax. This includes loading + * and sorting data, for example. If true, the class will call + * the _js_vars() method in the footer to provide variables + * to any scripts handling Ajax events. Default false. + * @type string|WP_Screen|null $screen String containing the hook name used to determine the current + * screen, or a `WP_Screen` instance. If left null, the current + * screen will be automatically set. Default null. * } + * + * @phpstan-param array{ + * plural?: string, + * singular?: string, + * ajax?: bool, + * screen?: string|WP_Screen|null, + * ... + * }|string $args */ public function __construct( $args = array() ) { $args = wp_parse_args( @@ -427,13 +442,21 @@ public function search_box( $text, $input_id ) { * @since 6.1.0 * * @param array $link_data { - * An array of link data. + * An array of link data, keyed by view. * - * @type string $url The link URL. - * @type string $label The link label. - * @type bool $current Optional. Whether this is the currently selected view. + * @type array ...$0 { + * Data for a single view link. + * + * @type string $url The link URL. + * @type string $label The link label. + * @type bool $current Optional. Whether this is the currently selected view. + * } * } * @return string[] An array of link markup. Keys match the `$link_data` input array. + * + * @phpstan-template TKey of array-key + * @phpstan-param array|string $link_data + * @phpstan-return ($link_data is array ? array : array{ 0: '' }) */ protected function get_views_links( $link_data = array() ) { if ( ! is_array( $link_data ) ) { @@ -729,7 +752,7 @@ protected function months_dropdown( $post_type ) { * * @since 5.7.0 * - * @param object[]|false $months 'Months' drop-down results. Default false. + * @param object[]|false $months 'Months' drop-down results. Default false. * @param string $post_type The post type. */ $months = apply_filters( 'pre_months_dropdown_query', false, $post_type ); @@ -1026,6 +1049,8 @@ protected function get_items_per_page( $option, $default_value = 20 ) { * @since 3.1.0 * * @param string $which The location of the pagination: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function pagination( $which ) { if ( empty( $this->_pagination_args['total_items'] ) ) { @@ -1661,6 +1686,8 @@ public function display() { * @since 3.1.0 * * @return string[] Array of CSS classes for the table tag. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { $mode = get_user_setting( 'posts_list_mode', 'list' ); @@ -1676,6 +1703,8 @@ protected function get_table_classes() { * @since 3.1.0 * * @param string $which The location of the navigation: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function display_tablenav( $which ) { if ( 'bottom' === $which && ! $this->has_items() ) { @@ -1918,6 +1947,8 @@ public function ajax_response() { * Sends required variables to JavaScript land. * * @since 3.1.0 + * @since 7.2.0 Prints the script through wp_print_inline_script_tag() so it can carry + * attributes, such as a per-request nonce, added via wp_inline_script_attributes. */ public function _js_vars() { $args = array( @@ -1928,6 +1959,8 @@ public function _js_vars() { ), ); - printf( "\n", wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ); + wp_print_inline_script_tag( + sprintf( 'var list_args = %s;', wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) + ); } } diff --git a/src/wp-admin/includes/class-wp-ms-sites-list-table.php b/src/wp-admin/includes/class-wp-ms-sites-list-table.php index 1ffa24ea24106..a12954827ee55 100644 --- a/src/wp-admin/includes/class-wp-ms-sites-list-table.php +++ b/src/wp-admin/includes/class-wp-ms-sites-list-table.php @@ -318,6 +318,8 @@ protected function get_bulk_actions() { * @global string $mode List table view mode. * * @param string $which The location of the pagination nav markup: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function pagination( $which ) { global $mode; diff --git a/src/wp-admin/includes/class-wp-ms-themes-list-table.php b/src/wp-admin/includes/class-wp-ms-themes-list-table.php index 81c35414d9053..0ecacb8f27fc5 100644 --- a/src/wp-admin/includes/class-wp-ms-themes-list-table.php +++ b/src/wp-admin/includes/class-wp-ms-themes-list-table.php @@ -73,6 +73,8 @@ public function __construct( $args = array() ) { * Gets the list of CSS classes for the table tag. * * @return string[] The list of CSS classes. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { // @todo Remove and add CSS for .themes. @@ -724,7 +726,7 @@ public function column_description( $theme ) { $pre . $theme->errors()->get_error_message(), array( 'type' => 'error', - 'additional_classes' => 'inline', + 'additional_classes' => array( 'inline' ), ) ); } diff --git a/src/wp-admin/includes/class-wp-ms-users-list-table.php b/src/wp-admin/includes/class-wp-ms-users-list-table.php index 145299bcc26cb..adead723ab190 100644 --- a/src/wp-admin/includes/class-wp-ms-users-list-table.php +++ b/src/wp-admin/includes/class-wp-ms-users-list-table.php @@ -16,16 +16,24 @@ */ class WP_MS_Users_List_Table extends WP_List_Table { /** - * @return bool + * Checks if the current user has permissions to perform an Ajax action. + * + * @since 3.1.0 + * + * @return bool Whether the current user can perform an Ajax action. */ public function ajax_user_can() { return current_user_can( 'manage_network_users' ); } /** + * Prepares the users list for display. + * + * @since 3.1.0 + * * @global string $mode List table view mode. - * @global string $usersearch - * @global string $role + * @global string $usersearch User search query. + * @global string $role The user role to filter by. Only 'super' (super admins) is supported. */ public function prepare_items() { global $mode, $usersearch, $role; @@ -106,7 +114,11 @@ public function prepare_items() { } /** - * @return array + * Gets the available bulk actions for the users list table. + * + * @since 3.1.0 + * + * @return array Bulk action labels keyed by action name. */ protected function get_bulk_actions() { $actions = array(); @@ -120,14 +132,22 @@ protected function get_bulk_actions() { } /** + * Displays a message when there are no items. + * + * @since 3.1.0 */ public function no_items() { _e( 'No users found.' ); } /** - * @global string $role - * @return array + * Gets the list of views (all, super admin) available for the users list table. + * + * @since 3.1.0 + * + * @global string $role The user role to filter by. Only 'super' (super admins) is supported. + * + * @return array View link markup keyed by view name ('all' or 'super'). */ protected function get_views() { global $role; @@ -170,9 +190,15 @@ protected function get_views() { } /** + * Generates the list table pagination. + * + * @since 3.1.0 + * * @global string $mode List table view mode. * - * @param string $which + * @param string $which The location of the pagination: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function pagination( $which ) { global $mode; @@ -185,7 +211,11 @@ protected function pagination( $which ) { } /** - * @return string[] Array of column titles keyed by their column name. + * Gets the list of columns for the users list table. + * + * @since 3.1.0 + * + * @return array Array of column titles keyed by their column name. */ public function get_columns() { $users_columns = array( @@ -201,14 +231,20 @@ public function get_columns() { * * @since MU (3.0.0) * - * @param string[] $users_columns An array of user columns. Default 'cb', 'username', - * 'name', 'email', 'registered', 'blogs'. + * @param array $users_columns Column titles keyed by column name. Default keys are 'cb', + * 'username', 'name', 'email', 'registered', and 'blogs'. */ return apply_filters( 'wpmu_users_columns', $users_columns ); } /** - * @return array + * Gets the list of sortable columns for the users list table. + * + * @since 3.1.0 + * + * @return array> Sortable columns. + * + * @phpstan-return array */ protected function get_sortable_columns() { return array( @@ -349,12 +385,14 @@ public function column_registered( $user ) { } /** + * Outputs the sites column content. + * * @since 4.3.0 * - * @param WP_User $user - * @param string $classes - * @param string $data - * @param string $primary + * @param WP_User $user The current WP_User object. + * @param string $classes CSS classes for the cell. + * @param string $data Custom data attributes for the cell. + * @param string $primary The primary column name. */ protected function _column_blogs( $user, $classes, $data, $primary ) { echo ''; diff --git a/src/wp-admin/includes/class-wp-plugin-install-list-table.php b/src/wp-admin/includes/class-wp-plugin-install-list-table.php index 7c54aefca1310..3f6d2a104d099 100644 --- a/src/wp-admin/includes/class-wp-plugin-install-list-table.php +++ b/src/wp-admin/includes/class-wp-plugin-install-list-table.php @@ -16,14 +16,54 @@ */ class WP_Plugin_Install_List_Table extends WP_List_Table { - public $order = 'ASC'; + /** + * Sort order of the plugins list: Either 'ASC' or 'DESC'. + * + * @since 4.0.0 + * + * @var string + * @phpstan-var 'ASC'|'DESC' + */ + public $order = 'ASC'; + + /** + * Plugin field to sort the list by, or null to keep the API's order. + * + * Not set by core. Sorting only applies when the plugins are objects, since + * {@see self::order_callback()} reads object properties, whereas the plugins + * returned by the API have been arrays since WordPress 5.1. + * + * @since 4.0.0 + * + * @var string|null + */ public $orderby = null; - public $groups = array(); + /** + * Plugin group names keyed by group slug, as returned by the Plugin Installation API. + * + * @since 4.0.0 + * + * @var array + */ + public $groups = array(); + + /** + * Error returned by the Plugin Installation API, if any. + * + * @since 4.0.0 + * @since 4.2.0 Declared as a private property. + * + * @var WP_Error|null + */ private $error; /** - * @return bool + * Checks if the current user has permissions to perform an Ajax action. + * + * @since 3.1.0 + * + * @return bool Whether the current user can perform an Ajax action. */ public function ajax_user_can() { return current_user_can( 'install_plugins' ); @@ -80,11 +120,15 @@ protected function get_installed_plugin_slugs() { } /** - * @global array $tabs - * @global string $tab - * @global int $paged - * @global string $type - * @global string $term + * Prepares the plugins list for display. + * + * @since 3.1.0 + * + * @global array $tabs Labels of the tabs shown on the Add Plugins screen, keyed by tab slug. + * @global string $tab The current active tab. + * @global int $paged The current page number. + * @global string $type The type of search being performed. + * @global string $term The search term. */ public function prepare_items() { require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; @@ -128,8 +172,9 @@ public function prepare_items() { * * @since 2.7.0 * - * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include - * 'featured', 'popular', 'recommended', 'favorites', and 'upload'. + * @param array $tabs Labels of the tabs shown on the Add Plugins screen, keyed by tab + * slug. Default keys include 'featured', 'popular', 'recommended', + * 'favorites', and 'upload'. */ $tabs = apply_filters( 'install_plugins_tabs', $tabs ); @@ -287,6 +332,9 @@ public function prepare_items() { } /** + * Outputs the message when no plugins are found. + * + * @since 3.1.0 */ public function no_items() { if ( isset( $this->error ) ) { @@ -307,10 +355,14 @@ public function no_items() { } /** - * @global array $tabs - * @global string $tab + * Gets the list of views (tabs) available for the plugins list table. * - * @return array + * @since 3.1.0 + * + * @global array $tabs Labels of the tabs shown on the Add Plugins screen, keyed by tab slug. + * @global string $tab The current active tab. + * + * @return array View link markup keyed by view ID ('plugin-install-' followed by the tab slug). */ protected function get_views() { global $tabs, $tab; @@ -332,6 +384,8 @@ protected function get_views() { /** * Overrides parent views so we can use the filter bar display. * + * @since 4.0.0 + * * @global string $tab The current tab. */ public function views() { @@ -403,9 +457,15 @@ public function display() { } /** - * @global string $tab + * Generates the table navigation. + * + * @since 3.1.0 + * + * @global string $tab The current active tab. * - * @param string $which + * @param string $which The location of the navigation: Either 'top' or 'bottom'. + * + * @phpstan-param 'top'|'bottom' $which */ protected function display_tablenav( $which ) { if ( 'featured' === $GLOBALS['tab'] ) { @@ -439,23 +499,39 @@ protected function display_tablenav( $which ) { } /** - * @return array + * Gets a list of CSS classes for the list table container element. + * + * Unlike in the parent class, these are applied to a `div` element rather than a `table` element. + * + * @since 3.1.0 + * + * @return string[] Array of CSS classes for the container element. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { return array( 'widefat', $this->_args['plural'] ); } /** - * @return string[] Array of column titles keyed by their column name. + * Gets the list of columns for the plugins list table. + * + * @since 3.1.0 + * + * @return array Array of column titles keyed by their column name. */ public function get_columns() { return array(); } /** - * @param object $plugin_a - * @param object $plugin_b - * @return int + * Callback for sorting plugins. + * + * @since 4.0.0 + * + * @param array|object $plugin_a The first plugin data. + * @param array|object $plugin_b The second plugin data. + * @return int Comparison result. */ private function order_callback( $plugin_a, $plugin_b ) { $orderby = $this->orderby; diff --git a/src/wp-admin/includes/class-wp-plugins-list-table.php b/src/wp-admin/includes/class-wp-plugins-list-table.php index d8945e103064e..c63a37992b6db 100644 --- a/src/wp-admin/includes/class-wp-plugins-list-table.php +++ b/src/wp-admin/includes/class-wp-plugins-list-table.php @@ -68,6 +68,8 @@ public function __construct( $args = array() ) { * @since 3.1.0 * * @return string[] Array of CSS classes for the table tag. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { return array( 'widefat', $this->_args['plural'] ); diff --git a/src/wp-admin/includes/class-wp-post-comments-list-table.php b/src/wp-admin/includes/class-wp-post-comments-list-table.php index 4454a77fe768f..936f9a05acf6f 100644 --- a/src/wp-admin/includes/class-wp-post-comments-list-table.php +++ b/src/wp-admin/includes/class-wp-post-comments-list-table.php @@ -32,7 +32,13 @@ protected function get_column_info() { } /** - * @return array + * Gets a list of CSS classes for the WP_List_Table table tag. + * + * @since 3.1.0 + * + * @return string[] Array of CSS classes for the table tag. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { $classes = parent::get_table_classes(); diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 8a319986766b8..00edeed1acfa1 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -631,9 +631,15 @@ public function current_action() { } /** + * Gets a list of CSS classes for the WP_List_Table table tag. + * + * @since 3.1.0 + * * @global string $mode List table view mode. * - * @return array + * @return string[] Array of CSS classes for the table tag. + * + * @phpstan-return non-empty-list */ protected function get_table_classes() { global $mode; @@ -1135,7 +1141,7 @@ protected function _column_title( $post, $classes, $data, $primary ) { * @return string The post title, or 'no title' if no title. */ protected function get_primary_column_aria_label( $item ) { - return isset( $item->post_title ) && ! empty( $item->post_title ) ? $item->post_title : __( 'no title' ); + return ! empty( $item->post_title ) ? $item->post_title : __( 'no title' ); } /** @@ -1854,7 +1860,7 @@ public function inline_edit() { * @see wp_dropdown_users() * * @param array $users_opt An array of arguments passed to wp_dropdown_users(). - * @param bool $bulk A flag to denote if it's a bulk action. + * @param bool $bulk A flag to denote if it's a bulk action. */ $users_opt = apply_filters( 'quick_edit_dropdown_authors_args', $users_opt, $bulk ); diff --git a/src/wp-admin/includes/class-wp-screen.php b/src/wp-admin/includes/class-wp-screen.php index b0b689d412edb..0008130355efb 100644 --- a/src/wp-admin/includes/class-wp-screen.php +++ b/src/wp-admin/includes/class-wp-screen.php @@ -205,8 +205,8 @@ final class WP_Screen { * * @global string $hook_suffix * - * @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen. - * Defaults to the current $hook_suffix global. + * @param string|WP_Screen|null $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen. + * Defaults to the current $hook_suffix global. * @return WP_Screen Screen object. */ public static function get( $hook_name = '' ) { @@ -1006,11 +1006,32 @@ public function show_screen_options() { $this->_screen_settings = ''; + $additional_settings = ''; + $has_meta_boxes = $this->has_meta_boxes(); + + if ( $has_meta_boxes ) { + $additional_settings .= $this->get_meta_box_reordering_option(); + } + if ( 'post' === $this->base ) { - $expand = ''; - $this->_screen_settings = $expand; + $additional_settings .= ''; + } + + if ( $additional_settings ) { + $fieldset_class = 'metabox-prefs additional-settings-prefs'; + + // The editor expand setting is revealed by JavaScript, so keep the fieldset hidden when it is the only setting. + if ( ! $has_meta_boxes ) { + $fieldset_class .= ' editor-expand hidden'; + } + + $this->_screen_settings = '
'; + $this->_screen_settings .= '' . __( 'Additional settings' ) . ''; + $this->_screen_settings .= $additional_settings; + $this->_screen_settings .= '
'; } /** @@ -1122,6 +1143,9 @@ public function render_meta_boxes_preferences() {

+ has_meta_boxes() ) : ?> + +

' + . ''; + } + + /** + * Checks whether the screen has meta boxes. + * + * @since 7.2.0 + * + * @global array $wp_meta_boxes Global meta box state. + * + * @return bool Whether the screen has meta boxes. + */ + private function has_meta_boxes() { + global $wp_meta_boxes; + + return ! empty( $wp_meta_boxes[ $this->id ] ); + } + /** * Renders the list table columns preferences. * diff --git a/src/wp-admin/includes/class-wp-site-health-auto-updates.php b/src/wp-admin/includes/class-wp-site-health-auto-updates.php index 1904acd4e08c5..3c0c8b3844b22 100644 --- a/src/wp-admin/includes/class-wp-site-health-auto-updates.php +++ b/src/wp-admin/includes/class-wp-site-health-auto-updates.php @@ -63,9 +63,9 @@ static function ( $test ) { * @since 5.2.0 * @since 5.5.1 The `$value` parameter can accept an array. * - * @param string $constant The name of the constant to check. - * @param bool|string|array $value The value that the constant should be, if set, - * or an array of acceptable values. + * @param string $constant The name of the constant to check. + * @param bool|string|array $value The value that the constant should be, if set, + * or an array of acceptable values. * @return array|null The test results if there are any constants set incorrectly, * or null if the test passed. */ diff --git a/src/wp-admin/includes/class-wp-site-health.php b/src/wp-admin/includes/class-wp-site-health.php index 6dee7ab524886..31e940b2076e1 100644 --- a/src/wp-admin/includes/class-wp-site-health.php +++ b/src/wp-admin/includes/class-wp-site-health.php @@ -77,9 +77,7 @@ public function show_site_health_tab( $tab ) { * @return WP_Site_Health|null */ public static function get_instance() { - if ( null === self::$instance ) { - self::$instance = new WP_Site_Health(); - } + self::$instance ??= new WP_Site_Health(); return self::$instance; } diff --git a/src/wp-admin/includes/class-wp-site-icon.php b/src/wp-admin/includes/class-wp-site-icon.php index ea0ab35007327..82a94570bc953 100644 --- a/src/wp-admin/includes/class-wp-site-icon.php +++ b/src/wp-admin/includes/class-wp-site-icon.php @@ -41,22 +41,22 @@ class WP_Site_Icon { /* * Square, medium sized tiles for IE11+. * - * See https://msdn.microsoft.com/library/dn455106(v=vs.85).aspx + * @link https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/samples/dn455106(v=vs.85) */ 270, /* * App icon for Android/Chrome. * - * @link https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android - * @link https://developer.chrome.com/multidevice/android/installtohomescreen + * @link https://developer.chrome.com/blog/support-for-theme-color-in-chrome-39-for-android + * @link https://web.dev/articles/icons-and-browser-colors */ 192, /* * App icons up to iPhone 6 Plus. * - * See https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html + * @link https://developer.apple.com/design/human-interface-guidelines/app-icons */ 180, @@ -171,7 +171,7 @@ public function additional_sizes( $sizes = array() ) { foreach ( $this->site_icon_sizes as $size ) { if ( $size < $this->min_size ) { $only_crop_sizes[ 'site_icon-' . $size ] = array( - 'width ' => $size, + 'width' => $size, 'height' => $size, 'crop' => true, ); diff --git a/src/wp-admin/includes/class-wp-terms-list-table.php b/src/wp-admin/includes/class-wp-terms-list-table.php index 561888fed8394..9481f0967a744 100644 --- a/src/wp-admin/includes/class-wp-terms-list-table.php +++ b/src/wp-admin/includes/class-wp-terms-list-table.php @@ -395,8 +395,8 @@ public function column_name( $tag ) { * * @see WP_Terms_List_Table::column_name() * - * @param string $pad_tag_name The term name, padded if not top-level. - * @param WP_Term $tag Term object. + * @param string $pad_tag_name The term name, padded if not top-level. + * @param WP_Term $tag Term object. */ $name = apply_filters( 'term_name', $pad . ' ' . $tag->name, $tag ); diff --git a/src/wp-admin/includes/class-wp-themes-list-table.php b/src/wp-admin/includes/class-wp-themes-list-table.php index 0e9a0fe8b9f2d..3a8f11aba2779 100644 --- a/src/wp-admin/includes/class-wp-themes-list-table.php +++ b/src/wp-admin/includes/class-wp-themes-list-table.php @@ -134,7 +134,14 @@ public function no_items() { } /** - * @param string $which + * Displays the table navigation, including the pagination. + * + * @since 3.1.0 + * + * @param string $which Optional. The location of the navigation: Either 'top' or 'bottom'. + * Default 'top'. + * + * @phpstan-param 'top'|'bottom' $which */ public function tablenav( $which = 'top' ) { if ( $this->get_pagination_arg( 'total_pages' ) <= 1 ) { @@ -340,6 +347,8 @@ public function search_theme( $theme ) { * Send required variables to JavaScript land * * @since 3.4.0 + * @since 7.2.0 Prints the script through wp_print_inline_script_tag() so it can carry + * attributes, such as a per-request nonce, added via wp_inline_script_attributes. * * @param array $extra_args */ @@ -357,7 +366,9 @@ public function _js_vars( $extra_args = array() ) { $args = array_merge( $args, $extra_args ); } - printf( "\n", wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ); + wp_print_inline_script_tag( + sprintf( 'var theme_list_args = %s;', wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) + ); parent::_js_vars(); } } diff --git a/src/wp-admin/includes/class-wp-upgrader-skin.php b/src/wp-admin/includes/class-wp-upgrader-skin.php index 831da3aebae2a..89fde5fc44e1e 100644 --- a/src/wp-admin/includes/class-wp-upgrader-skin.php +++ b/src/wp-admin/includes/class-wp-upgrader-skin.php @@ -235,6 +235,8 @@ public function after() {} * Outputs JavaScript that calls function to decrement the update counts. * * @since 3.9.0 + * @since 7.2.0 Prints the script through wp_print_inline_script_tag() so it can carry + * attributes, such as a per-request nonce, added via wp_inline_script_attributes. * * @param string $type Type of update count to decrement. Likely values include 'plugin', * 'theme', 'translation', etc. @@ -245,27 +247,37 @@ protected function decrement_update_count( $type ) { } if ( defined( 'IFRAME_REQUEST' ) ) { - echo ''; + // language=JavaScript + $js_function = <<<'JAVASCRIPT' + ( upgradeType ) => { + window.parent.postMessage( + JSON.stringify( { + action: "decrementUpdateCount", + upgradeType + } ), + window.location.protocol + "//" + window.location.hostname + + ( "" !== window.location.port ? ":" + window.location.port : "" ) + ); + } + JAVASCRIPT; } else { - echo ''; + $js_function = <<<'JS' + ( upgradeType ) => { + const wp = window.wp; + if ( wp && wp.updates && wp.updates.decrementCount ) { + wp.updates.decrementCount( upgradeType ); + } + } + JS; } + + wp_print_inline_script_tag( + sprintf( + '( %s )( %s );', + $js_function, + wp_json_encode( $type, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) + ) + ); } /** diff --git a/src/wp-admin/includes/dashboard.php b/src/wp-admin/includes/dashboard.php index 7a78025214f10..488e01aa92481 100644 --- a/src/wp-admin/includes/dashboard.php +++ b/src/wp-admin/includes/dashboard.php @@ -656,6 +656,9 @@ function wp_dashboard_recent_drafts( $drafts = false ) { $drafts = get_posts( $query_args ); if ( ! $drafts ) { + echo '
'; + echo '

' . __( 'There are no recent drafts.' ) . '

'; + echo '
'; return; } } @@ -1372,7 +1375,7 @@ function wp_dashboard_events_news() { * @since 4.8.0 */ function wp_print_community_events_markup() { - $community_events_notice = '

' . __( 'This widget requires JavaScript.' ) . '

'; + $community_events_notice = '

' . __( 'The WordPress Events and News feeds require JavaScript.' ) . '

'; $community_events_notice .= ''; $community_events_notice .= ''; @@ -1998,7 +2001,7 @@ function wp_dashboard_site_health() { $issues_total = $issue_counts['recommended'] + $issue_counts['critical']; ?>
-
+
'; @@ -2238,9 +2287,6 @@ function media_upload_form( $errors = null ) { */ $plupload_init = apply_filters( 'plupload_init', $plupload_init ); - ?> -
- + 0 ) { + preloaded.each( function () { + prepareMediaItem( { id: this.id.replace( /[^0-9]/g, '' ) }, '' ); + } ); + } + updateMediaForm(); + } ); + JS + ); + ?>
+ +
@@ -2587,16 +2651,20 @@ function media_upload_gallery_form( $errors ) { $form_class .= ' html-uploader'; } + wp_print_inline_script_tag( + <<<'JS' + jQuery( function ( $ ) { + var preloaded = $( '.media-item.preloaded' ); + if ( preloaded.length > 0 ) { + preloaded.each( function () { + prepareMediaItem( { id: this.id.replace( /[^0-9]/g, '' ) }, '' ); + } ); + updateMediaForm(); + } + } ); + JS + ); ?> -
@@ -2916,15 +2984,21 @@ function media_upload_library_form( $errors ) {
- + 0 ) { + preloaded.each( function () { + prepareMediaItem( { id: this.id.replace( /[^0-9]/g, '' ) }, '' ); + } ); + updateMediaForm(); + } + } ); + JS + ); + ?>
@@ -2945,6 +3019,8 @@ function media_upload_library_form( $errors ) { * * @param string $default_view * @return string HTML content of the form. + * + * @phpstan-return non-falsy-string */ function wp_media_insert_url_form( $default_view = 'image' ) { /** This filter is documented in wp-admin/includes/media.php */ @@ -3370,7 +3446,7 @@ function attachment_submitbox_metadata() { post_parent ) { $post_parent = get_post( $post->post_parent ); - if ( $post_parent ) { + if ( $post_parent && current_user_can( 'read_post', $post_parent->ID ) ) { $uploaded_to_title = $post_parent->post_title ? $post_parent->post_title : __( '(no title)' ); $uploaded_to_link = get_edit_post_link( $post->post_parent, 'raw' ); ?> @@ -3549,7 +3625,7 @@ function attachment_submitbox_metadata() { * @since 3.6.0 * * @param array $metadata An existing array with data. - * @param array $data Data supplied by ID3 tags. + * @param array $data Data supplied by ID3 tags. */ function wp_add_id3_tag_data( &$metadata, $data ) { foreach ( array( 'id3v2', 'id3v1' ) as $version ) { diff --git a/src/wp-admin/includes/menu.php b/src/wp-admin/includes/menu.php index a95cf9e33956e..f1c2985e93e8e 100644 --- a/src/wp-admin/includes/menu.php +++ b/src/wp-admin/includes/menu.php @@ -208,6 +208,10 @@ * @param string $class_to_add The CSS class to add. * @param string $classes The string to add the CSS class to. * @return string The string with the CSS class added. + * + * @phpstan-template T of string + * @phpstan-param T $class_to_add + * @phpstan-return ( $classes is empty ? T : non-empty-string ) */ function add_cssclass( $class_to_add, $classes ) { if ( empty( $classes ) ) { diff --git a/src/wp-admin/includes/meta-boxes.php b/src/wp-admin/includes/meta-boxes.php index 535a00cd3fe94..9149f50daadd8 100644 --- a/src/wp-admin/includes/meta-boxes.php +++ b/src/wp-admin/includes/meta-boxes.php @@ -1257,6 +1257,8 @@ function link_target_meta_box( $link ) { * if it matches the current link's relationship. * Default empty string. * @param mixed $deprecated Deprecated. Not used. + * + * @phpstan-param '' $deprecated */ function xfn_check( $xfn_relationship, $xfn_value = '', $deprecated = '' ) { global $link; diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php index f021aedb8a5fb..c1ee93a2849e5 100644 --- a/src/wp-admin/includes/misc.php +++ b/src/wp-admin/includes/misc.php @@ -1570,12 +1570,14 @@ function _wp_privacy_settings_filter_draft_page_titles( $title, $page ) { * @return array|false { * Array of PHP version data. False on failure. * - * @type string $recommended_version The PHP version recommended by WordPress. - * @type string $minimum_version The minimum required PHP version. - * @type bool $is_supported Whether the PHP version is actively supported. - * @type bool $is_secure Whether the PHP version receives security updates. - * @type bool $is_acceptable Whether the PHP version is still acceptable or warnings - * should be shown and an update recommended. + * @type string $recommended_version The PHP version recommended by WordPress. + * @type string $minimum_version The minimum required PHP version. + * @type bool $is_supported Whether the PHP version is actively supported. + * @type bool $is_secure Whether the PHP version receives security updates. + * @type bool $is_acceptable Whether the PHP version is still acceptable or warnings + * should be shown and an update recommended. + * @type bool $is_lower_than_future_minimum Whether the PHP version is lower than the minimum PHP + * version WordPress will require in a future release. * } */ function wp_check_php_version() { diff --git a/src/wp-admin/includes/ms-admin-filters.php b/src/wp-admin/includes/ms-admin-filters.php index b1d73825f1f4b..003b727e45132 100644 --- a/src/wp-admin/includes/ms-admin-filters.php +++ b/src/wp-admin/includes/ms-admin-filters.php @@ -11,9 +11,6 @@ add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' ); // User hooks. -add_action( 'user_admin_notices', 'new_user_email_admin_notice' ); -add_action( 'network_admin_notices', 'new_user_email_admin_notice' ); - add_action( 'admin_page_access_denied', '_access_denied_splash', 99 ); // Site hooks. diff --git a/src/wp-admin/includes/ms.php b/src/wp-admin/includes/ms.php index 56e17113653d2..0ae6381ee9855 100644 --- a/src/wp-admin/includes/ms.php +++ b/src/wp-admin/includes/ms.php @@ -1003,6 +1003,7 @@ function confirm_delete_users( $users ) { 'include' => $blog_users, 'show' => 'display_name_with_login', 'id' => "reassign_user_{$details->userblog_id}_{$delete_user->ID}", + 'blog_id' => $details->userblog_id, ) ); ?> @@ -1210,6 +1211,8 @@ function get_site_screen_help_tab_args() { * @since 4.9.0 * * @return string Help sidebar content. + * + * @phpstan-return non-falsy-string */ function get_site_screen_help_sidebar_content() { return '

' . __( 'For more information:' ) . '

' . diff --git a/src/wp-admin/includes/network.php b/src/wp-admin/includes/network.php index 15c58c65a3148..7dc6c9895869c 100644 --- a/src/wp-admin/includes/network.php +++ b/src/wp-admin/includes/network.php @@ -240,7 +240,7 @@ function network_step1( $errors = false ) { if ( allow_subdomain_install() && allow_subdirectory_install() ) : ?> -

+

@@ -289,7 +289,7 @@ function network_step1( $errors = false ) { $is_www = str_starts_with( $hostname, 'www.' ); if ( $is_www ) : ?> -

+

-

+

@@ -378,8 +378,8 @@ function network_step1( $errors = false ) { @@ -387,8 +387,8 @@ function network_step1( $errors = false ) { @@ -470,7 +470,7 @@ function network_step2( $errors = false ) { if ( $_POST || ! is_multisite() ) { ?> -

+

' . __( 'Caution:' ) . ' '; diff --git a/src/wp-admin/includes/plugin-install.php b/src/wp-admin/includes/plugin-install.php index dc232f1df7018..ffae71c5b81f6 100644 --- a/src/wp-admin/includes/plugin-install.php +++ b/src/wp-admin/includes/plugin-install.php @@ -309,6 +309,8 @@ function install_dashboard() { * @since 4.6.0 The `$type_selector` parameter was deprecated. * * @param bool $deprecated Not used. + * + * @phpstan-param true $deprecated */ function install_search_form( $deprecated = true ) { $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; @@ -593,8 +595,7 @@ function install_plugin_information() { // Default to the Description tab, Do not translate, API returns English. $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { - $section_titles = array_keys( (array) $api->sections ); - $section = reset( $section_titles ); + $section = array_key_first( (array) $api->sections ); } iframe_header( __( 'Plugin Installation' ) ); @@ -895,15 +896,15 @@ function install_plugin_information() { * @since 6.5.0 * * @param string $name Plugin name. - * @param array|object $data { + * @param array|object $data { * An array or object of plugin data. Can be retrieved from the API. * * @type string $slug The plugin slug. * @type string[] $requires_plugins An array of plugin dependency slugs. * @type string $version The plugin's version string. Used when getting the install status. * } - * @param bool $compatible_php The result of a PHP compatibility check. - * @param bool $compatible_wp The result of a WP compatibility check. + * @param bool $compatible_php The result of a PHP compatibility check. + * @param bool $compatible_wp The result of a WP compatibility check. * @return string The markup for the dependency row button. An empty string if the user does not have capabilities. */ function wp_get_plugin_action_button( $name, $data, $compatible_php, $compatible_wp ) { diff --git a/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index 94d4a585a80f1..c627e6d8f55d5 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/wp-admin/includes/plugin.php @@ -598,11 +598,17 @@ function is_plugin_active_for_network( $plugin ) { * Checks for "Site Wide Only: true" for backward compatibility. * * @since 3.0.0 + * @since 7.1.1 The `$plugin` path is normalized with `plugin_basename()` and `trim()`, + * matching how `activate_plugin()` resolves it. * - * @param string $plugin Path to the plugin file relative to the plugins directory. + * @param string $plugin Path to the plugin file. Accepts a path relative to the plugins + * directory, or an absolute path, with or without surrounding whitespace. * @return bool True if plugin is network only, false otherwise. */ function is_network_only_plugin( $plugin ) { + // Normalize the path the same way activate_plugin() does, so both agree on the file. + $plugin = plugin_basename( trim( $plugin ) ); + $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); if ( $plugin_data ) { return $plugin_data['Network']; @@ -900,6 +906,9 @@ function activate_plugins( $plugins, $redirect = '', $network_wide = false, $sil * @param string $deprecated Not used. * @return bool|null|WP_Error True on success, false if `$plugins` is empty, `WP_Error` on failure. * `null` if filesystem credentials are required to proceed. + * + * @phpstan-param '' $deprecated + * @phpstan-return ( $plugins is empty ? false : true|null|WP_Error ) */ function delete_plugins( $plugins, $deprecated = '' ) { global $wp_filesystem; @@ -1105,6 +1114,8 @@ function validate_active_plugins() { * * @param string $plugin Path to the plugin file relative to the plugins directory. * @return int|WP_Error 0 on success, WP_Error on failure. + * + * @phpstan-return ( $plugin is empty ? WP_Error : 0|WP_Error ) */ function validate_plugin( $plugin ) { if ( validate_file( $plugin ) ) { @@ -1264,7 +1275,7 @@ function validate_plugin_requirements( $plugin ) { * @since 6.9.0 * * @param bool|WP_Error $met_requirements True if the plugin meets requirements, WP_Error if not. - * @param string $plugin Path to the plugin file relative to the plugins directory. + * @param string $plugin Path to the plugin file relative to the plugins directory. */ return apply_filters( 'validate_plugin_requirements', true, $plugin ); } @@ -1388,6 +1399,8 @@ function uninstall_plugin( $plugin ) { * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. * @param int|float $position Optional. The position in the menu order this item should appear. * @return string The resulting page's hook_suffix. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) { global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages; @@ -1483,6 +1496,8 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $call * @param callable $callback Optional. The function to be called to output the content for this page. * @param int|float $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, @@ -1596,6 +1611,8 @@ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1620,6 +1637,8 @@ function add_management_page( $page_title, $menu_title, $capability, $menu_slug, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1644,6 +1663,8 @@ function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $c * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1668,6 +1689,8 @@ function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1692,6 +1715,8 @@ function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $c * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { if ( current_user_can( 'edit_users' ) ) { @@ -1721,6 +1746,8 @@ function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1745,6 +1772,8 @@ function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1769,6 +1798,8 @@ function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1793,6 +1824,8 @@ function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1817,6 +1850,8 @@ function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1841,6 +1876,8 @@ function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param non-falsy-string $menu_slug */ function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -2136,6 +2173,8 @@ function get_plugin_page_hook( $plugin_page, $parent_page ) { * @param string $parent_page The slug name for the parent menu (or the file name of a standard * WordPress admin page). * @return string Hook name for the plugin page. + * + * @phpstan-return non-falsy-string */ function get_plugin_page_hookname( $plugin_page, $parent_page ) { global $admin_page_hooks; diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index 39d267b623037..a255673aad601 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -24,6 +24,20 @@ function _wp_translate_postdata( $update = false, $post_data = null ) { $post_data = &$_POST; } + /* + * A raw `ID` on the create path (no `post_ID`) is an attempt to overwrite an + * existing post while bypassing the per-post capability checks below, which only + * run on the update path. Reject it outright: legitimate post creation never + * carries an `ID`. + */ + if ( ! $update && ! empty( $post_data['ID'] ) ) { + if ( 'page' === $post_data['post_type'] ) { + return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to edit pages as this user.' ) ); + } else { + return new WP_Error( 'edit_others_posts', __( 'Sorry, you are not allowed to edit posts as this user.' ) ); + } + } + if ( $update ) { $post_data['ID'] = (int) $post_data['post_ID']; } @@ -1393,10 +1407,25 @@ function wp_edit_attachments_query_vars( $q = false ) { * @param array|false $q Optional. Array of query variables to use to build the query. * Defaults to the `$_GET` superglobal. * @return array { - * Array containing the post mime types and available post mime types. + * Array containing the post mime types and the available post mime types, in that order. + * + * @type array $0 Post mime types. See get_post_mime_types(). + * @type string[] $1 Available post mime types. + * } * - * @type array[] $post_mime_types Post mime types. - * @type string[] $avail_post_mime_types Available post mime types. + * @phpstan-return array{ + * 0: array, + * 1: string[], * } */ function wp_edit_attachments_query( $q = false ) { @@ -2607,7 +2636,7 @@ function the_block_editor_meta_box_post_form_hidden_fields( $post ) { * @since 5.9.0 * @access private * - * @param bool $value Whether the CPT supports block editor or not. + * @param bool $value Whether the CPT supports block editor or not. * @param string $post_type Post type. * @return bool Whether the block editor should be disabled or not. */ diff --git a/src/wp-admin/includes/revision.php b/src/wp-admin/includes/revision.php index 2f15f1c9e2faf..ec58011f7a3a0 100644 --- a/src/wp-admin/includes/revision.php +++ b/src/wp-admin/includes/revision.php @@ -325,8 +325,7 @@ function wp_prepare_revisions_for_js( $post, $selected_revision_id, $from = null if ( ! $compare_two_mode ) { $found = array_search( $selected_revision_id, array_keys( $revisions ), true ); if ( $found ) { - $from = array_keys( array_slice( $revisions, $found - 1, 1, true ) ); - $from = reset( $from ); + $from = array_key_first( array_slice( $revisions, $found - 1, 1, true ) ); } else { $from = 0; } diff --git a/src/wp-admin/includes/screen.php b/src/wp-admin/includes/screen.php index 3388ced49a4aa..3781aacdd1fa6 100644 --- a/src/wp-admin/includes/screen.php +++ b/src/wp-admin/includes/screen.php @@ -194,6 +194,19 @@ function get_hidden_meta_boxes( $screen ) { return apply_filters( 'hidden_meta_boxes', $hidden, $screen, $use_defaults ); } +/** + * Determines whether meta box reordering is enabled. + * + * @since 7.2.0 + * + * @return bool Whether meta box reordering is enabled. + */ +function wp_is_meta_box_reordering_enabled() { + $setting = get_user_option( 'meta_box_reordering' ); + + return false === $setting ? true : 'disabled' !== $setting; +} + /** * Register and configure an admin screen option * diff --git a/src/wp-admin/includes/taxonomy.php b/src/wp-admin/includes/taxonomy.php index 470d36d55ffb1..dbdab1af4fab8 100644 --- a/src/wp-admin/includes/taxonomy.php +++ b/src/wp-admin/includes/taxonomy.php @@ -117,6 +117,10 @@ function wp_create_categories( $categories, $post_id = 0 ) { * @param bool $wp_error Optional. Default false. * @return int|WP_Error The ID number of the new or updated Category on success. Zero or a WP_Error on failure, * depending on param `$wp_error`. + * + * @phpstan-return ( + * $wp_error is false ? int : int|WP_Error + * ) */ function wp_insert_category( $catarr, $wp_error = false ) { $cat_defaults = array( @@ -218,6 +222,12 @@ function wp_update_category( $catarr ) { * @return mixed Returns null if the term does not exist. * Returns an array of the term ID and the term taxonomy ID if the pairing exists. * Returns 0 if term ID 0 is passed to the function. + * + * @phpstan-return ( + * $tag_name is 0 + * ? 0 + * : ( $tag_name is '' ? null : array{ term_id: string, term_taxonomy_id: string }|null ) + * ) */ function tag_exists( $tag_name ) { return term_exists( $tag_name, 'post_tag' ); diff --git a/src/wp-admin/includes/template.php b/src/wp-admin/includes/template.php index 418bfd7def697..c01d9ffaf8ad0 100644 --- a/src/wp-admin/includes/template.php +++ b/src/wp-admin/includes/template.php @@ -1808,7 +1808,7 @@ function do_settings_sections( $page ) { * * @global array $wp_settings_fields Storage array of settings fields and their pages/sections. * - * @param string $page Slug title of the admin page whose settings fields you want to show. + * @param string $page Slug title of the admin page whose settings fields you want to show. * @param string $section Slug title of the settings section whose fields you want to show. */ function do_settings_fields( $page, $section ) { @@ -1974,6 +1974,8 @@ function get_settings_errors( $setting = '', $sanitize = false ) { * @since 3.0.0 * @since 5.3.0 Legacy `error` and `updated` CSS classes are mapped to * `notice-error` and `notice-success`. + * @since 7.2.0 Uses `wp_admin_notice()` to echo the notices so that the CSS + * classes, filters, and hooks are handled consistently. * * @param string $setting Optional slug title of a specific setting whose errors you want. * @param bool $sanitize Whether to re-sanitize the setting value before returning errors. @@ -1992,32 +1994,49 @@ function settings_errors( $setting = '', $sanitize = false, $hide_on_update = fa return; } - $output = ''; - foreach ( $settings_errors as $key => $details ) { - if ( 'updated' === $details['type'] ) { - $details['type'] = 'success'; + $type = trim( $details['type'] ); + + if ( 'updated' === $type ) { + $type = 'success'; } - if ( in_array( $details['type'], array( 'error', 'success', 'warning', 'info' ), true ) ) { - $details['type'] = 'notice-' . $details['type']; + $additional_classes = array( 'settings-error' ); + + /* + * Backward compatibility: `wp_admin_notice()` generates the admin notice + * CSS classes based on the passed message type. For example, 'error', + * 'success', 'warning', 'info'. Custom types will be treated as + * additional classes and appended to the end of the CSS classes. + */ + if ( ! in_array( $type, array( 'error', 'success', 'warning', 'info' ), true ) ) { + $additional_classes = array_merge( $additional_classes, explode( ' ', $type ) ); + $type = ''; } - $css_id = sprintf( + /* + * Note that the setting error code contains underscores, for example: + * `settings_updated`. This will build a CSS ID selector that contains + * underscores, which are currently not allowed by the WordPress CSS + * Coding Standards. Kept for backwards compatibility. + */ + $css_id = sprintf( 'setting-error-%s', - esc_attr( $details['code'] ) - ); - $css_class = sprintf( - 'notice %s settings-error is-dismissible', - esc_attr( $details['type'] ) + $details['code'], ); - $output .= "
\n"; - $output .= "

{$details['message']}

"; - $output .= "
\n"; + wp_admin_notice( + "{$details['message']}", + array( + 'type' => $type, + 'code' => $details['code'], + 'id' => $css_id, + 'paragraph_wrap' => true, + 'dismissible' => true, + 'additional_classes' => $additional_classes, + ) + ); } - - echo $output; } /** @@ -2124,6 +2143,8 @@ function _admin_search_query() { * * @param string $title Optional. Title of the Iframe page. Default empty. * @param bool $deprecated Not used. + * + * @phpstan-param false $deprecated */ function iframe_header( $title = '', $deprecated = false ) { global $hook_suffix, $admin_body_class, $body_id, $wp_locale; @@ -2140,19 +2161,50 @@ function iframe_header( $title = '', $deprecated = false ) { <?php bloginfo( 'name' ); ?> › <?php echo $title; ?> — <?php _e( 'WordPress' ); ?> - - admin_url( 'admin-ajax.php', 'relative' ), + 'pagenow' => $current_screen->id ?? '', + 'typenow' => $current_screen->post_type ?? '', + 'adminpage' => $admin_body_class, + 'thousandsSeparator' => $wp_locale->number_format['thousands_sep'], + 'decimalPoint' => $wp_locale->number_format['decimal_point'], + 'isRtl' => (int) is_rtl(), + ), + JSON_HEX_TAG | JSON_UNESCAPED_SLASHES + ) + ) + ); + /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_enqueue_scripts', $hook_suffix ); @@ -2191,14 +2243,12 @@ function tb_close(){var win=window.dialogArguments||opener||parent||top;win.tb_r $admin_body_classes = ltrim( $admin_body_classes . ' ' . $admin_body_class ); ?> class="wp-admin wp-core-ui no-js iframe "> - - +
- - + + + + + + + @@ -148,7 +147,7 @@ function display_setup_form( $error = null ) { -

+

@@ -156,12 +155,15 @@ function display_setup_form( $error = null ) { @@ -179,28 +181,32 @@ function display_setup_form( $error = null ) { - + - + @@ -470,17 +476,30 @@ function display_setup_form( $error = null ) { } if ( ! wp_is_mobile() ) { - ?> - - - diff --git a/src/wp-admin/my-sites.php b/src/wp-admin/my-sites.php index 71ebc3858ec34..30fbdb8458a12 100644 --- a/src/wp-admin/my-sites.php +++ b/src/wp-admin/my-sites.php @@ -124,7 +124,7 @@ $settings_html = apply_filters( 'myblogs_options', '', 'global' ); if ( $settings_html ) { - echo '

' . __( 'Global Settings' ) . '

'; + echo '

' . __( 'Global Settings' ) . '

'; echo $settings_html; } @@ -134,7 +134,7 @@ switch_to_blog( $user_blog->userblog_id ); echo '
  • '; - echo "

    {$user_blog->blogname}

    "; + echo "

    {$user_blog->blogname}

    "; $actions = "" . __( 'Visit' ) . ''; diff --git a/src/wp-admin/network/site-new.php b/src/wp-admin/network/site-new.php index 4eafec5938dd3..70316ab330e30 100644 --- a/src/wp-admin/network/site-new.php +++ b/src/wp-admin/network/site-new.php @@ -140,6 +140,11 @@ do_action( 'network_site_new_created_user', $user_id ); } + /** + * @global wpdb $wpdb WordPress database abstraction object. + */ + global $wpdb; + $wpdb->hide_errors(); $id = wpmu_create_blog( $newdomain, $path, $title, $user_id, $meta, get_current_network_id() ); $wpdb->show_errors(); diff --git a/src/wp-admin/network/site-users.php b/src/wp-admin/network/site-users.php index 6e32b5e8dd40d..113189099e1e9 100644 --- a/src/wp-admin/network/site-users.php +++ b/src/wp-admin/network/site-users.php @@ -371,7 +371,7 @@ if ( current_user_can( 'create_users' ) && apply_filters( 'show_network_site_users_add_new_form', true ) ) : ?>

    - +
  • diff --git a/src/wp-admin/options-connectors.php b/src/wp-admin/options-connectors.php index c67d857b2b60d..ddad78f4f135f 100644 --- a/src/wp-admin/options-connectors.php +++ b/src/wp-admin/options-connectors.php @@ -20,8 +20,8 @@ if ( ! class_exists( '\WordPress\AiClient\AiClient' ) || ! function_exists( 'wp_options_connectors_wp_admin_render_page' ) ) { wp_die( - '

    ' . __( 'Connectors are not available.' ) . '

    ' . - '

    ' . __( 'The Connectors page requires build files. Please run npm install to build the necessary files.' ) . '

    ', + '

    ' . __( 'The Connectors are not available.' ) . '

    ' . + '

    ' . __( 'The Connectors page requires build files. Please build WordPress and try again.' ) . '

    ', 503 ); } diff --git a/src/wp-admin/options-general.php b/src/wp-admin/options-general.php index 6a9a6d2f3812d..1e6e00ea703d8 100644 --- a/src/wp-admin/options-general.php +++ b/src/wp-admin/options-general.php @@ -22,6 +22,9 @@ /* translators: Date and time format for exact current time, mainly about timezones, see https://www.php.net/manual/datetime.format.php */ $timezone_format = _x( 'Y-m-d H:i:s', 'timezone date format' ); +$new_admin_email = get_option( 'new_admin_email' ); +$pending_new_admin_email = $new_admin_email && get_option( 'admin_email' ) !== $new_admin_email; + add_action( 'admin_head', 'options_general_add_js' ); $options_help = '

    ' . __( 'The fields on this screen determine some of the basics of your site setup.' ) . '

    ' . @@ -67,6 +70,36 @@

    +' . __( 'Administration email updated.' ) . ''; + wp_admin_notice( + $message, + array( + 'id' => 'message', + 'dismissible' => true, + 'type' => 'success', + ) + ); +} + +$pending_admin_email_cancel_request_link = sprintf( + ' %2$s', + esc_url( wp_nonce_url( admin_url( 'options.php?dismiss=new_admin_email' ), 'dismiss-' . get_current_blog_id() . '-new_admin_email' ) ), + _x( 'Cancel request', 'admin email change' ) +); + +if ( $pending_new_admin_email ) { + $message = sprintf( + /* translators: %s: New administration email address. */ + __( 'The administration email address has not been updated yet. Please check the inbox at %s for a confirmation email.' ), + '' . esc_html( $new_admin_email ) . '' + ); + $message .= $pending_admin_email_cancel_request_link; + wp_admin_notice( $message, array( 'type' => 'info' ) ); +} +?> + @@ -190,7 +223,7 @@ class="" data-choose-text="" data-update-text="" data-update="" - data-state="" + data-state="" > @@ -266,22 +299,18 @@ class=""
    - - + - diff --git a/src/wp-admin/options.php b/src/wp-admin/options.php index b45cbb00387ce..8f065f64473e6 100644 --- a/src/wp-admin/options.php +++ b/src/wp-admin/options.php @@ -57,7 +57,7 @@ // Handle admin email change requests. if ( ! empty( $_GET['adminhash'] ) ) { $new_admin_details = get_option( 'adminhash' ); - $redirect = 'options-general.php?updated=false'; + $redirect = add_query_arg( array( 'updated' => 'false' ), 'options-general.php' ); if ( is_array( $new_admin_details ) && hash_equals( $new_admin_details['hash'], $_GET['adminhash'] ) @@ -66,7 +66,13 @@ update_option( 'admin_email', $new_admin_details['newemail'] ); delete_option( 'adminhash' ); delete_option( 'new_admin_email' ); - $redirect = 'options-general.php?updated=true'; + $redirect = add_query_arg( + array( + 'updated' => 'true', + 'admin_email_updated' => 'true', + ), + 'options-general.php', + ); } wp_redirect( admin_url( $redirect ) ); @@ -396,6 +402,11 @@ get_results( "SELECT * FROM $wpdb->options ORDER BY option_name" ); foreach ( (array) $options as $option ) : diff --git a/src/wp-admin/plugin-editor.php b/src/wp-admin/plugin-editor.php index 4beee7b8409da..c72333fe144b9 100644 --- a/src/wp-admin/plugin-editor.php +++ b/src/wp-admin/plugin-editor.php @@ -71,8 +71,7 @@ $plugin = $file; } } else { - $plugin = array_keys( $plugins ); - $plugin = $plugin[0]; + $plugin = array_key_first( $plugins ); } } @@ -316,7 +315,7 @@
    Warning: Making changes to active plugins is not recommended.' ), array( diff --git a/src/wp-admin/setup-config.php b/src/wp-admin/setup-config.php index ec4d1a8bbbdbc..aaa91fc24b72b 100644 --- a/src/wp-admin/setup-config.php +++ b/src/wp-admin/setup-config.php @@ -14,6 +14,52 @@ */ define( 'WP_INSTALLING', true ); +if ( ! defined( 'ABSPATH' ) ) { + define( 'ABSPATH', dirname( __DIR__ ) . '/' ); +} + +/* + * Check whether a wp-config.php file already exists, either in the WordPress root + * or one level above it (but not as part of another installation). + * This mirrors the lookup in wp-load.php. + */ +if ( file_exists( ABSPATH . 'wp-config.php' ) ) { + $existing_config_location = 'root'; +} elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) { + $existing_config_location = 'parent'; +} else { + $existing_config_location = ''; +} + +if ( $existing_config_location ) { + /* + * A configuration file already exists, so there is nothing to set up here. + * Load WordPress through that file, like any other request would, so that the + * site's locale is known and the message below can be translated. + */ + require_once ABSPATH . 'wp-load.php'; + + nocache_headers(); + + if ( 'root' === $existing_config_location ) { + $message = sprintf( + /* translators: 1: wp-config.php, 2: install.php */ + __( 'The file %1$s already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now.' ), + 'wp-config.php', + 'install.php' + ); + } else { + $message = sprintf( + /* translators: 1: wp-config.php, 2: install.php */ + __( 'The file %1$s already exists one level above your WordPress installation. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now.' ), + 'wp-config.php', + 'install.php' + ); + } + + wp_die( '

    ' . $message . '

    ', 409 ); +} + /** * We are blissfully unaware of anything. */ @@ -26,10 +72,6 @@ */ error_reporting( 0 ); -if ( ! defined( 'ABSPATH' ) ) { - define( 'ABSPATH', dirname( __DIR__ ) . '/' ); -} - require ABSPATH . 'wp-settings.php'; /** Load WordPress Administration Upgrade API */ @@ -55,32 +97,6 @@ ); } -// Check if wp-config.php has been created. -if ( file_exists( ABSPATH . 'wp-config.php' ) ) { - wp_die( - '

    ' . sprintf( - /* translators: 1: wp-config.php, 2: install.php */ - __( 'The file %1$s already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now.' ), - 'wp-config.php', - 'install.php' - ) . '

    ', - 409 - ); -} - -// Check if wp-config.php exists above the root directory but is not part of another installation. -if ( @file_exists( ABSPATH . '../wp-config.php' ) && ! @file_exists( ABSPATH . '../wp-settings.php' ) ) { - wp_die( - '

    ' . sprintf( - /* translators: 1: wp-config.php, 2: install.php */ - __( 'The file %1$s already exists one level above your WordPress installation. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now.' ), - 'wp-config.php', - 'install.php' - ) . '

    ', - 409 - ); -} - $step = isset( $_GET['step'] ) ? (int) $_GET['step'] : -1; /** diff --git a/src/wp-admin/theme-install.php b/src/wp-admin/theme-install.php index 8e6fc5d1eea2c..a611a6819367f 100644 --- a/src/wp-admin/theme-install.php +++ b/src/wp-admin/theme-install.php @@ -281,7 +281,7 @@ ?>
    -
    +

    @@ -390,7 +390,11 @@

    <# } #> + <# if ( data.compatible_wp && data.compatible_php ) { #> + + <# } else { #> + <# } #>
    <# } else { #> - + <# } #> <# } #> <# if ( data.customize_url ) { #> @@ -432,12 +436,12 @@ $aria_label = sprintf( _x( 'Cannot Activate %s', 'theme' ), '{{ data.name }}' ); ?> <# if ( data.activate_url ) { #> - + <# } #> <# if ( data.customize_url ) { #> - + <# } else { #> - + <# } #> <# } #> <# } else { #> @@ -453,8 +457,8 @@ /* translators: %s: Theme name. */ $aria_label = sprintf( _x( 'Cannot Install %s', 'theme' ), '{{ data.name }}' ); ?> - - + + <# } #> <# } #>
    @@ -473,13 +477,13 @@ <# if ( data.installed ) { #> @@ -491,16 +495,16 @@ <# if ( ! data.active ) { #> <# } else { #> - + <# } #> <# } else { #> - + <# } #> <# } else { #> <# if ( data.compatible_wp && data.compatible_php ) { #> <# } else { #> - + <# } #> <# } #> diff --git a/src/wp-admin/themes.php b/src/wp-admin/themes.php index ac2cd4a9824cb..a0686c645766a 100644 --- a/src/wp-admin/themes.php +++ b/src/wp-admin/themes.php @@ -664,7 +664,7 @@ - +

    @@ -1057,19 +1057,19 @@ function wp_theme_auto_update_setting_template() { diff --git a/src/wp-admin/update.php b/src/wp-admin/update.php index a6c59ec06dab2..a0ba9cfc069b2 100644 --- a/src/wp-admin/update.php +++ b/src/wp-admin/update.php @@ -87,7 +87,7 @@ wp_redirect( admin_url( 'update.php?action=activate-plugin&success=true&plugin=' . urlencode( $plugin ) . '&_wpnonce=' . $_GET['_wpnonce'] ) ); die(); } - iframe_header( __( 'Plugin Reactivation' ), true ); + iframe_header( __( 'Plugin Reactivation' ) ); if ( isset( $_GET['success'] ) ) { echo '

    ' . __( 'Plugin reactivated successfully.' ) . '

    '; } diff --git a/src/wp-admin/upload.php b/src/wp-admin/upload.php index 7cf0f6fe10108..3c30e2eb4d2b3 100644 --- a/src/wp-admin/upload.php +++ b/src/wp-admin/upload.php @@ -262,6 +262,11 @@ function () { $post_ids = array(); if ( 'delete_all' === $doaction ) { + /** + * @global wpdb $wpdb WordPress database abstraction object. + */ + global $wpdb; + $post_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='attachment' AND post_status = 'trash'" ); $doaction = 'delete'; } elseif ( isset( $_REQUEST['media'] ) ) { diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 5d45c63801bfe..75a5033973c3c 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -104,6 +104,11 @@ wp_die( __( 'Sorry, you are not allowed to edit this user.' ) ); } +/** + * @global wpdb $wpdb WordPress database abstraction object. + */ +global $wpdb; + // Execute confirmed email change. See send_confirmation_on_profile_email(). if ( IS_PROFILE_PAGE && isset( $_GET['newuseremail'] ) && $current_user->ID ) { $new_email = get_user_meta( $current_user->ID, '_new_email', true ); @@ -261,9 +266,15 @@

    - +

    + + @@ -454,7 +465,7 @@
    - + ID ) ) : ?> @@ -591,12 +602,13 @@ $pending_change_message .= sprintf( ' %2$s', esc_url( wp_nonce_url( self_admin_url( 'profile.php?dismiss=' . $current_user->ID . '_new_email' ), 'dismiss-' . $current_user->ID . '_new_email' ) ), - __( 'Cancel' ) + _x( 'Cancel request', 'user email change' ) ); wp_admin_notice( $pending_change_message, array( - 'additional_classes' => array( 'updated', 'inline' ), + 'type' => 'info', + 'additional_classes' => array( 'inline' ), ) ); endif; @@ -640,8 +652,8 @@ - + @@ -745,11 +757,11 @@ @@ -776,8 +788,8 @@ @@ -786,8 +798,8 @@