diff --git a/.env.example b/.env.example index 6974d8554611a..dddbb4be4c260 100644 --- a/.env.example +++ b/.env.example @@ -14,6 +14,10 @@ LOCAL_PORT=8889 # Where to run WordPress from. Valid options are 'src' and 'build'. LOCAL_DIR=src +# Whether or not to enable text compression (gzip) in the web server. +# Valid options are 'on' and 'off'. +LOCAL_NGINX_COMPRESSION=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/check-built-files.yml b/.github/workflows/check-built-files.yml deleted file mode 100644 index 01a239c4eb3b0..0000000000000 --- a/.github/workflows/check-built-files.yml +++ /dev/null @@ -1,54 +0,0 @@ -# Checks for uncommitted changes to built files in pull requests. -name: Check Built Files (PRs) - -on: - # Because all commits happen through SVN and should always be manually reviewed by a committer, this workflow only - # runs for pull requests. - # - # Other workflows that run for the push event will detect changes to versioned files and fail. - pull_request: - branches: - - trunk - - '6.[8-9]' - - '[7-9].[0-9]' - paths: - # Any change to a CSS, JavaScript, JSON, or SASS file should run checks. - - '**.css' - - '**.js' - - '**.json' - - '**.sass' - # These files configure npm and the task runner. Changes could affect the outcome. - - 'package*.json' - - '.npmrc' - - '.nvmrc' - - 'Gruntfile.js' - - 'webpack.config.js' - - 'tools/gutenberg/**' - - 'tools/vendors/**' - - 'tools/webpack/**' - # These files configure Composer. Changes could affect the outcome. - - 'composer.*' - # Confirm any changes to relevant workflow files. - - '.github/workflows/check-built-files.yml' - - '.github/workflows/reusable-check-built-files.yml' - # Changes to the default themes should be handled by the themes workflows. - - '!src/wp-content/themes/twenty**' - -# Cancels all previous workflow runs for pull requests that have not completed. -concurrency: - # The concurrency group contains the workflow name and the branch name for pull requests - # or the commit hash for any other events. - group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} - cancel-in-progress: true - -# Disable permissions for all available scopes by default. -# Any needed permissions should be configured at the job level. -permissions: {} - -jobs: - check-for-built-file-changes: - name: Check built files - if: ${{ github.repository == 'wordpress/wordpress-develop' }} - uses: ./.github/workflows/reusable-check-built-files.yml - permissions: - contents: read diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index 809abd1da9230..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: @@ -50,7 +91,14 @@ jobs: uses: ./.github/workflows/reusable-coding-standards-php.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) # Runs the JavaScript coding standards checks. jshint: @@ -58,7 +106,14 @@ jobs: uses: ./.github/workflows/reusable-coding-standards-javascript.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) slack-notifications: name: Slack Notifications diff --git a/.github/workflows/commit-built-file-changes.yml b/.github/workflows/commit-built-file-changes.yml deleted file mode 100644 index 9a959187505c9..0000000000000 --- a/.github/workflows/commit-built-file-changes.yml +++ /dev/null @@ -1,166 +0,0 @@ -# Commits all missed changes to built files back to pull request branches. -name: Commit Built File Changes (PRs) - -on: - workflow_run: - workflows: - - 'Check Built Files (PRs)' - - 'Test Default Themes & Create ZIPs' - types: - - completed - -# Cancels all previous workflow runs for pull requests that have not completed. -concurrency: - # The concurrency group contains the workflow name and the branch name for pull requests - # or the commit hash for any other events. - group: ${{ github.workflow }}-${{ github.event_name == 'workflow_run' && format( '{0}-{1}', github.event.workflow_run.head_branch, github.event.workflow_run.head_repository.name ) || github.sha }} - -# Disable permissions for all available scopes by default. -# Any needed permissions should be configured at the job level. -permissions: {} - -jobs: - # Checks a PR for uncommitted changes to built files. - # - # Performs the following steps: - # - Attempts to download the artifact containing the PR diff. - # - Checks for the existence of an artifact. - # - Unzips the artifact. - # - Generates a token for authenticating with the GitHub App. - # - Checks out the repository. - # - Applies the patch file. - # - Displays the result of git diff. - # - Configures the Git author. - # - Stages changes. - # - Commits changes. - # - Pushes changes. - update-built-files: - name: Check and update built files - runs-on: ubuntu-24.04 - if: ${{ github.repository == 'wordpress/wordpress-develop' }} - timeout-minutes: 10 - permissions: - # The actual `git push` is authenticated via a dedicated GitHub App installation token - # generated below, so `GITHUB_TOKEN` only needs read access to the triggering workflow's artifacts. - actions: read # Required to list and download the artifact uploaded by the triggering workflow run. - steps: - - name: Download artifact - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - with: - script: | - const artifacts = await github.rest.actions.listWorkflowRunArtifacts( { - owner: context.repo.owner, - repo: context.repo.repo, - run_id: process.env.RUN_ID, - } ); - - const matchArtifact = artifacts.data.artifacts.filter( ( artifact ) => { - return artifact.name === 'pr-built-file-changes' - } )[0]; - - if ( ! matchArtifact ) { - core.info( 'No artifact found!' ); - return; - } - - const download = await github.rest.actions.downloadArtifact( { - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - } ); - - const fs = require( 'fs' ); - fs.writeFileSync( '${{ github.workspace }}/pr-built-file-changes.zip', Buffer.from( download.data ) ) - env: - RUN_ID: ${{ github.event.workflow_run.id }} - - - name: Check for artifact - id: artifact-check - run: | - if [ -f "pr-built-file-changes.zip" ]; then - echo "exists=true" >> "$GITHUB_OUTPUT" - else - echo "exists=false" >> "$GITHUB_OUTPUT" - fi - - - name: Unzip the artifact containing the PR data - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - run: unzip pr-built-file-changes.zip - - - name: Generate Installation Token - id: generate_token - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - env: - GH_APP_ID: ${{ vars.GH_PR_BUILT_FILES_APP_ID }} - GH_APP_PRIVATE_KEY: ${{ secrets.GH_PR_BUILT_FILES_PRIVATE_KEY }} - run: | - # Generate JWT - JWT=$(python3 - <> "$GITHUB_OUTPUT" - - - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - with: - repository: ${{ github.event.workflow_run.head_repository.full_name }} - ref: ${{ github.event.workflow_run.head_branch }} - path: 'pr-repo' - show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - token: ${{ steps.generate_token.outputs.access-token }} - persist-credentials: true - - - name: Apply patch - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - run: git apply "$GITHUB_WORKSPACE/changes.diff" - - - name: Display changes to versioned files - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - run: git diff - - - name: Configure git user name and email - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - env: - GH_APP_ID: ${{ vars.GH_PR_BUILT_FILES_APP_ID }} - run: | - git config user.name "wordpress-develop-pr-bot[bot]" - git config user.email "${GH_APP_ID}+wordpress-develop-pr-bot[bot]@users.noreply.github.com" - - - name: Stage changes - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - run: git add . - - - name: Commit changes - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - run: | - git commit -m "Automation: Updating built files with changes." - - - name: Push changes - if: ${{ steps.artifact-check.outputs.exists == 'true' }} - working-directory: 'pr-repo' - run: git push diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml index 890314f25be49..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: @@ -57,7 +70,14 @@ jobs: uses: ./.github/workflows/reusable-end-to-end-tests.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) strategy: fail-fast: false matrix: 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 140e5f679701a..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 diff --git a/.github/workflows/javascript-tests.yml b/.github/workflows/javascript-tests.yml index 8d96c826d7a57..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: @@ -53,7 +92,14 @@ jobs: uses: ./.github/workflows/reusable-javascript-tests.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) slack-notifications: name: Slack Notifications diff --git a/.github/workflows/javascript-type-checking.yml b/.github/workflows/javascript-type-checking.yml index 2572bb4c2fe36..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: @@ -46,7 +47,14 @@ jobs: uses: ./.github/workflows/reusable-javascript-type-checking-v1.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) slack-notifications: name: Slack Notifications diff --git a/.github/workflows/local-docker-environment.yml b/.github/workflows/local-docker-environment.yml index 856db171726b6..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' diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 3690e6822512f..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: @@ -50,7 +63,17 @@ jobs: determine-matrix: name: Determine Matrix runs-on: ubuntu-24.04 - if: ${{ ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) && ! contains( github.event.before, '00000000' ) }} + 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' ) + ) + ) + ) && + ! contains( github.event.before, '00000000' ) permissions: actions: read env: diff --git a/.github/workflows/php-compatibility.yml b/.github/workflows/php-compatibility.yml index 9e30670cdae7e..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: @@ -42,7 +80,14 @@ jobs: uses: ./.github/workflows/reusable-php-compatibility.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) slack-notifications: name: Slack Notifications diff --git a/.github/workflows/phpstan-static-analysis.yml b/.github/workflows/phpstan-static-analysis.yml index 7d7043ac0c1ec..6a26c75b16525 100644 --- a/.github/workflows/phpstan-static-analysis.yml +++ b/.github/workflows/phpstan-static-analysis.yml @@ -42,7 +42,14 @@ jobs: uses: ./.github/workflows/reusable-phpstan-static-analysis-v1.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) slack-notifications: name: Slack Notifications 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 2b9bbfe891640..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,19 +84,102 @@ 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. - # - # This condition is the union of the conditions on the jobs that need it, reduced. - # The org matrices require `WordPress/wordpress-develop` or a pull request, and the - # fork matrix requires a pull request, so `wordpress-develop` or a pull request - # covers every case. Keep it in step with those jobs: a narrower condition orphans - # them, because a job that needs a skipped job is skipped too, and a broader one - # downloads a build that nothing consumes. prepare-gutenberg: + name: Prepare Gutenberg Assets uses: ./.github/workflows/reusable-prepare-gutenberg.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) # # Creates a PHPUnit test job for each PHP/MySQL combination. @@ -76,24 +191,52 @@ 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: ${{ startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }} + 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: 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. @@ -144,14 +287,14 @@ jobs: phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} tests-domain: ${{ matrix.tests-domain }} report: ${{ matrix.report || false }} - gutenberg-artifact: gutenberg-build + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} # # 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. @@ -159,23 +302,52 @@ 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: ${{ startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }} + 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: 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. @@ -200,7 +372,7 @@ jobs: memcached: ${{ matrix.memcached }} phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} report: false - gutenberg-artifact: gutenberg-build + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} # @@ -217,29 +389,51 @@ 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: ${{ startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }} + 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: 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 }} @@ -250,7 +444,7 @@ jobs: memcached: ${{ matrix.memcached }} phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} report: false - gutenberg-artifact: gutenberg-build + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} # @@ -264,13 +458,23 @@ 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: ${{ startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }} + 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: @@ -285,7 +489,7 @@ jobs: db-type: ${{ matrix.db-type }} db-version: ${{ matrix.db-version }} phpunit-test-groups: ${{ matrix.phpunit-test-groups }} - gutenberg-artifact: gutenberg-build + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} # @@ -298,13 +502,20 @@ 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: ${{ ! startsWith( github.repository, 'WordPress/' ) && github.event_name == 'pull_request' }} + if: | + needs.select-test-coverage.outputs.assets-only != 'true' && + ! startsWith( github.repository, 'WordPress/' ) && + 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: @@ -350,7 +561,51 @@ jobs: memcached: ${{ matrix.memcached || false }} phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} phpunit-test-groups: ${{ matrix.phpunit-test-groups || '' }} - gutenberg-artifact: gutenberg-build + 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: @@ -359,7 +614,7 @@ jobs: 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' }} 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-check-built-files.yml b/.github/workflows/reusable-check-built-files.yml deleted file mode 100644 index 043c24581cc36..0000000000000 --- a/.github/workflows/reusable-check-built-files.yml +++ /dev/null @@ -1,104 +0,0 @@ -## -# A reusable workflow that checks for uncommitted changes to built files in pull requests. -## -name: Check Built Files (PRs) - -on: - workflow_call: - -permissions: {} - -jobs: - # Checks a PR for uncommitted changes to built files. - # - # When changes are detected, the patch is stored as an artifact for processing by the Commit Built File Changes - # workflow. - # - # Performs the following steps: - # - Checks out the repository. - # - Sets up Node.js. - # - Installs Composer dependencies. - # - Logs general debug information about the runner. - # - Installs npm dependencies. - # - Builds CSS file using SASS. - # - Builds Emoji files. - # - Builds bundled Root Certificate files. - # - Builds WordPress. - # - Checks for changes to versioned files. - # - Displays the result of git diff for debugging purposes. - # - Saves the diff to a patch file. - # - Uploads the patch file as an artifact. - update-built-files: - name: Check and update built files - runs-on: ubuntu-24.04 - timeout-minutes: 10 - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - 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 - - # Since Composer dependencies are installed using `composer update` and no lock file is in version control, - # passing a custom cache suffix ensures that the cache is flushed at least once per week. - - name: Install Composer dependencies - uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0 - with: - custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") - - - name: Log debug information - run: | - npm --version - node --version - curl --version - git --version - - - name: Install npm Dependencies - run: npm ci - - - name: Run SASS precommit tasks - run: npm run grunt precommit:css - - - name: Run Emoji precommit task - run: npm run grunt precommit:emoji - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Run certificate tasks - run: npm run grunt copy:certificates - - - name: Build WordPress - run: npm run build:dev - - - name: Check for changes to versioned files - id: built-file-check - run: | - if git diff --quiet; then - echo "uncommitted_changes=false" >> "$GITHUB_OUTPUT" - else - echo "uncommitted_changes=true" >> "$GITHUB_OUTPUT" - fi - - - name: Display changes to versioned files - if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff - - - name: Save diff to a file - if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff > ./changes.diff - - # Uploads the diff file as an artifact. - - name: Upload diff file as artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - with: - name: pr-built-file-changes - path: changes.diff diff --git a/.github/workflows/reusable-cleanup-pull-requests.yml b/.github/workflows/reusable-cleanup-pull-requests.yml index 012f99adbec3b..59f5fe59be799 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,10 +58,14 @@ 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) { @@ -97,8 +103,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 36a71d1711d2f..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: npx 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 a9b911e718cba..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' }} @@ -148,12 +155,13 @@ jobs: run: npm ci - name: Install Playwright browsers - run: npx playwright install --with-deps chromium + run: npm exec --no -- playwright install --with-deps chromium - name: Start Docker environment 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 6a7f49fba468c..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 @@ -73,16 +85,24 @@ on: type: boolean default: false gutenberg-artifact: - description: 'The name of a same-workflow artifact containing the prepared Gutenberg build. Optional: callers that omit it download Gutenberg per job.' + description: 'Whether the Gutenberg-sourced assets are sourced from zip artifact.' required: false - type: string - default: '' + type: boolean + default: false gutenberg-sha: description: 'The immutable Gutenberg source SHA verified by the calling workflow.' 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,17 +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 - # Branches >= 5.9 call this workflow at @trunk without the producer job, so they - # pass no artifact. They skip this step and fall back to a per-job download. - - name: Download prepared Gutenberg build - if: inputs.gutenberg-artifact != '' + # 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.gutenberg-artifact }} + 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: + # 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 @@ -161,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. @@ -187,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. @@ -205,21 +269,8 @@ jobs: run: | docker -v - - name: Pull Docker images (with retry) - run: | - for attempt in 1 2 3; do - if npm run env:pull; then - break - fi - - if [ "$attempt" -eq 3 ]; then - echo "npm run env:pull failed after $attempt attempts." - exit 1 - fi - - echo "npm run env:pull failed (attempt $attempt); retrying..." - sleep $(( attempt * 10 )) - done + - name: Pull Docker images + run: npm run env:pull - name: Start Docker environment run: | @@ -271,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: | @@ -279,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 0fe5dfe6d564b..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: | @@ -112,11 +119,16 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run CSS precommit tasks + if: ${{ inputs.directory == 'src' }} + run: npm run grunt precommit:css + - name: Ensure certificates files are updated if: ${{ inputs.test-certificates }} 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 @@ -139,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/test-and-zip-default-themes.yml b/.github/workflows/test-and-zip-default-themes.yml index f50c00bdeafe9..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/**' @@ -69,7 +71,14 @@ jobs: permissions: contents: read timeout-minutes: 10 - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) strategy: fail-fast: false matrix: @@ -119,7 +128,14 @@ jobs: permissions: contents: read timeout-minutes: 10 - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) strategy: fail-fast: false matrix: @@ -146,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 @@ -231,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' diff --git a/.github/workflows/test-build-processes.yml b/.github/workflows/test-build-processes.yml index d344c5371bad5..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: @@ -51,7 +66,14 @@ jobs: uses: ./.github/workflows/reusable-test-core-build-process.yml permissions: contents: read - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) strategy: fail-fast: false matrix: diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index ffc650ec370fb..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' @@ -52,6 +54,7 @@ env: jobs: # Downloads and verifies the Gutenberg build once for all coverage jobs. prepare-gutenberg: + name: Prepare Gutenberg Assets uses: ./.github/workflows/reusable-prepare-gutenberg.yml permissions: contents: read @@ -76,7 +79,7 @@ jobs: php: '8.3' multisite: ${{ matrix.multisite }} coverage-report: ${{ matrix.coverage-report }} - gutenberg-artifact: gutenberg-build + gutenberg-artifact: ${{ needs.prepare-gutenberg.result != 'skipped' }} gutenberg-sha: ${{ needs.prepare-gutenberg.outputs.gutenberg-sha }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/test-old-branches.yml b/.github/workflows/test-old-branches.yml index 054f1e98a2a1b..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 * *' @@ -25,7 +25,7 @@ on: permissions: {} env: - CURRENTLY_SUPPORTED_BRANCH: '7.0' + CURRENTLY_SUPPORTED_BRANCH: '7.1' jobs: dispatch-workflows-for-old-branches: @@ -45,13 +45,15 @@ jobs: 'test-build-processes.yml' ] branch: [ - '7.0', + '7.1', '7.0', '6.9', '6.8', '6.7', '6.6', '6.5', '6.4', '6.3', '6.2', '6.1','6.0', '5.9', '5.8', '5.7', '5.6', '5.5', '5.4', '5.3', '5.2', '5.1', '5.0', '4.9', '4.8', '4.7' ] include: # PHP Compatibility testing was introduced in 5.5. + - branch: '7.1' + workflow: 'php-compatibility.yml' - branch: '7.0' workflow: 'php-compatibility.yml' - branch: '6.9' @@ -88,6 +90,8 @@ jobs: # End-to-end testing was introduced in 5.3 but was later removed as there were no meaningful assertions. # Starting in 5.8 with #52905, some additional tests with real assertions were introduced. # Branches 5.8 and newer should be tested to confirm no regressions are introduced. + - branch: '7.1' + workflow: 'end-to-end-tests.yml' - branch: '7.0' workflow: 'end-to-end-tests.yml' - branch: '6.9' @@ -118,9 +122,9 @@ jobs: # Performance testing was introduced in 6.2 using Puppeteer but was overhauled to use Playwright instead in 6.4. # Since the workflow frequently failed for 6.2 and 6.3 due to the flaky nature of the Puppeteer tests, # the workflow was removed from those two branches. - - branch: '7.0' + - branch: '7.1' workflow: 'performance.yml' - - branch: '6.9' + - branch: '7.0' workflow: 'performance.yml' # Run all branches monthly, but only the currently supported one twice per month. diff --git a/.github/workflows/upgrade-develop-testing.yml b/.github/workflows/upgrade-develop-testing.yml index 831b470beb418..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. @@ -44,7 +51,16 @@ jobs: build: name: Build uses: ./.github/workflows/reusable-build-package.yml - if: ${{ startsWith( github.repository, 'WordPress/' ) && ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }} + if: | + 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' ) + ) + ) + ) permissions: contents: read @@ -72,7 +88,7 @@ jobs: db-type: [ 'mysql' ] db-version: [ '5.7', '8.4' ] # WordPress 5.3 is the oldest version that supports PHP 7.4. - wp: [ '5.3', '6.9', '7.0' ] + wp: [ '5.3', '7.0', '7.1' ] multisite: [ false, true ] with: os: ${{ matrix.os }} @@ -84,10 +100,18 @@ 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 - if: ${{ github.repository != 'WordPress/wordpress-develop' }} + 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' ) + ) needs: [ build ] permissions: contents: read @@ -98,7 +122,7 @@ jobs: php: [ '7.4', '8.4' ] db-type: [ 'mysql' ] db-version: [ '8.4' ] - wp: [ '6.9', '7.0' ] + wp: [ '7.0', '7.1' ] multisite: [ false, true ] with: os: ${{ matrix.os }} diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 930a82b3139b1..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: [ '6.9', '7.0' ] + 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' }} diff --git a/.github/workflows/workflow-lint.yml b/.github/workflows/workflow-lint.yml index acb74cf5971c7..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: @@ -33,7 +35,14 @@ jobs: lint: name: Lint GitHub Action files uses: ./.github/workflows/reusable-workflow-lint.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }} + 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' ) + ) + ) permissions: security-events: write actions: read diff --git a/.gitignore b/.gitignore index 15876fa47fee8..03dfe96ce5672 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ wp-tests-config.php /packagehash.txt /.gutenberg-hash /artifacts +/tools/css-selector-fuzz/lexbor/harness /setup.log /coverage diff --git a/.nvmrc b/.nvmrc index 209e3ef4b6247..82d5d714347ef 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 +24.18 diff --git a/.version-support-mysql.json b/.version-support-mysql.json index 7ab8aa38df392..c7bda38ff5fe9 100644 --- a/.version-support-mysql.json +++ b/.version-support-mysql.json @@ -1,4 +1,12 @@ { + "7-2": [ + "9.7", + "8.4", + "8.0", + "5.7", + "5.6", + "5.5" + ], "7-1": [ "9.7", "8.4", diff --git a/.version-support-php.json b/.version-support-php.json index de510694c65c9..fc0128345fdb5 100644 --- a/.version-support-php.json +++ b/.version-support-php.json @@ -1,4 +1,13 @@ { + "7-2": [ + "7.4", + "8.0", + "8.1", + "8.2", + "8.3", + "8.4", + "8.5" + ], "7-1": [ "7.4", "8.0", diff --git a/Gruntfile.js b/Gruntfile.js index 61f18481e23a8..f72ded777eb7c 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 ); @@ -926,6 +928,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 +946,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 +1076,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 * - * 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. + * + * @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; } } }, @@ -1744,6 +1793,8 @@ module.exports = function(grunt) { grunt.task.run( '_' + this.nameArgs ); } ); + grunt.registerMultiTask( 'imagemin', 'Losslessly optimizes PNG, JPEG and GIF images.', require( './tools/imagemin/task.js' )( grunt ) ); + grunt.registerTask( 'precommit:image', [ 'imagemin:core' ] ); @@ -1751,6 +1802,7 @@ module.exports = function(grunt) { grunt.registerTask( 'precommit:js', [ 'webpack:prod', 'jshint:corejs', + 'lint:jsdoc', 'typecheck:js', 'uglify:imgareaselect', 'uglify:jqueryform', @@ -1786,6 +1838,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 +1855,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 +1873,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 +1887,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 ); @@ -2279,8 +2354,8 @@ module.exports = function(grunt) { grunt.registerTask( 'qunit', 'Runs QUnit tests.', function() { var done = this.async(); grunt.util.spawn( { - cmd: 'npx', - args: [ 'playwright', 'test', '--config', 'tests/qunit/playwright.config.js' ], + cmd: 'npm', + args: [ 'exec', '--no', '--', 'playwright', 'test', '--config', 'tests/qunit/playwright.config.js' ], opts: { stdio: 'inherit' } }, function( error, result, code ) { if ( code !== 0 ) { @@ -2308,6 +2383,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(); @@ -2363,15 +2450,15 @@ module.exports = function(grunt) { grunt.registerTask( 'wp-packages:update', 'Update WordPress packages', function() { const distTag = grunt.option('dist-tag') || 'latest'; grunt.log.writeln( `Updating WordPress packages (--dist-tag=${distTag})` ); - spawn( 'npx', [ 'wp-scripts', 'packages-update', `--dist-tag=${distTag}` ], { + spawn( 'npm', [ 'exec', '--no', '--', 'wp-scripts', 'packages-update', `--dist-tag=${distTag}` ], { cwd: __dirname, stdio: 'inherit', } ); } ); grunt.registerTask( 'browserslist:update', 'Update the local database of browser supports', function() { - grunt.log.writeln( `Updating browsers list` ); - spawn( 'npx', [ 'update-browserslist-db@latest' ], { + grunt.log.writeln( 'Updating browsers list' ); + spawn( 'npm', [ 'exec', '--no', '--', 'update-browserslist-db' ], { cwd: __dirname, stdio: 'inherit', } ); diff --git a/SECURITY.md b/SECURITY.md index 20b9b8e4b3890..13e8007009af8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,6 +10,7 @@ Full details of the WordPress Security Policy and the list of covered projects a | Version | Supported | |---------| --------- | +| 7.1.x | Yes | | 7.0.x | Yes | | 6.9.x | Yes | | 6.8.x | Yes | diff --git a/composer.json b/composer.json index 87a4463017a0c..f911555e136ce 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "wordpress/wordpress", - "version": "7.1.0", + "version": "7.2.0", "license": "GPL-2.0-or-later", "description": "WordPress is open source software you can use to create a beautiful website, blog, or app.", "homepage": "https://wordpress.org", @@ -29,6 +29,7 @@ "ext-igbinary": "*", "ext-imagick": "*", "ext-intl": "*", + "ext-libxml": "*", "ext-mbstring": "*", "ext-memcached": "*", "ext-mysqli": "*", @@ -51,7 +52,7 @@ "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": "2.2.14", "phpstan/phpstan-phpunit": "2.0.18", "yoast/phpunit-polyfills": "^1.1.0" }, diff --git a/docker-compose.yml b/docker-compose.yml index 7ab6ae8c9b4d5..06a2d2a40cec7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,13 +14,14 @@ services: environment: LOCAL_DIR: ${LOCAL_DIR-src} + LOCAL_NGINX_COMPRESSION: ${LOCAL_NGINX_COMPRESSION:-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' < /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' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'" depends_on: php: @@ -79,10 +80,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 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 78985e8f955c0..b0cc6e695d85a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "WordPress", - "version": "7.1.0", + "version": "7.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "WordPress", - "version": "7.1.0", + "version": "7.2.0", "license": "GPL-2.0-or-later", "dependencies": { "backbone": "1.6.1", @@ -40,7 +40,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", @@ -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", @@ -89,13 +90,27 @@ "sinon-test": "~3.1.6", "source-map-loader": "5.0.0", "typescript": "6.0.3", + "update-browserslist-db": "1.3.1", "uuid": "14.0.1", "wait-on": "9.0.10", "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": { @@ -4111,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": { @@ -4818,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", @@ -5867,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", @@ -8757,59 +9040,14 @@ "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=", + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, - "optional": true, - "dependencies": { - "file-type": "^4.2.0" - }, + "license": "MIT", "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", - "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" + "node": ">=14" } }, "node_modules/argparse": { @@ -8838,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", @@ -8890,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", @@ -8938,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", @@ -9115,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", @@ -9177,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", @@ -9739,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", @@ -9851,491 +9955,150 @@ "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, - "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" + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" } }, - "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": { + "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, - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "optional": true, "dependencies": { - "execa": "^0.7.0", - "executable": "^4.1.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-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/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, "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" + "ms": "2.0.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/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", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "optional": true, "dependencies": { - "execa": "^1.0.0", - "find-versions": "^3.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "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-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, - "optional": true, + "license": "MIT", "dependencies": { - "bin-version": "^3.0.0", - "semver": "^5.6.0", - "semver-truncate": "^1.1.2" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=6" + "node": ">=0.10.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-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, - "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/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": { - "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" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "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==", + "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": { - "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" + "bytes": "1", + "string_decoder": "0.10" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "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/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", - "optional": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "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==", + "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", @@ -10359,40 +10122,6 @@ "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" - } - }, "node_modules/browserslist": { "version": "4.28.6", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", @@ -10460,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", @@ -10487,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", @@ -10519,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", @@ -10553,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", @@ -10695,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", @@ -10729,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", @@ -10817,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", @@ -11108,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", @@ -11267,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", @@ -11287,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", @@ -11343,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", @@ -11438,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", @@ -11506,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", @@ -11555,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", @@ -11623,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", @@ -11926,52 +11366,7 @@ }, "engines": { "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", @@ -12045,63 +11440,6 @@ "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==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -12209,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", @@ -12275,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", @@ -12370,326 +11650,87 @@ "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" - } - }, - "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=", - "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", @@ -12898,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", @@ -13135,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", @@ -13197,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", @@ -13286,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", @@ -14619,155 +13546,12 @@ }, "node_modules/events-universal": { "version": "1.0.1", - "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" + "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/exit": { @@ -14789,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", @@ -14934,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", @@ -15031,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", @@ -15258,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", @@ -15367,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", @@ -15401,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", @@ -15638,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", @@ -16001,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", @@ -16040,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", @@ -16214,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", @@ -16301,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", @@ -16336,27 +14760,7 @@ "license": "MIT", "dependencies": { "encoding": "^0.1.12", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/gifsicle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-4.0.1.tgz", - "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" + "safe-buffer": "^5.1.1" } }, "node_modules/glob": { @@ -16393,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", @@ -16571,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", @@ -16982,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", @@ -17883,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", @@ -17905,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", @@ -17933,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", @@ -18348,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", @@ -18626,235 +16848,6 @@ "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_modules/imagesloaded": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/imagesloaded/-/imagesloaded-5.0.0.tgz", @@ -18922,21 +16915,7 @@ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { - "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": ">=0.8.19" } }, "node_modules/inflight": { @@ -19086,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", @@ -19142,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", @@ -19240,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", @@ -19284,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", @@ -19330,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", @@ -19359,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", @@ -19392,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", @@ -19442,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", @@ -19466,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", @@ -19488,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", @@ -19508,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", @@ -19546,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", @@ -19575,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", @@ -19622,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", @@ -19659,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", @@ -19686,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", @@ -19764,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", @@ -19984,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", @@ -22272,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", @@ -22590,14 +20346,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", @@ -22723,29 +20471,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", @@ -23136,62 +20861,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", @@ -23381,30 +21050,6 @@ "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_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lookup-closest-locale": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", @@ -23422,57 +21067,13 @@ "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", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", "dev": true, "dependencies": { - "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" + "tslib": "^2.0.3" } }, "node_modules/lru-cache": { @@ -23566,18 +21167,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", @@ -23888,13 +21477,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", @@ -23930,29 +21512,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", @@ -23992,39 +21551,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", @@ -24068,16 +21594,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", @@ -24346,43 +21862,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", @@ -24472,37 +21951,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", @@ -24563,13 +22011,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", @@ -24834,31 +22275,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", @@ -25280,30 +22696,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", @@ -25329,33 +22721,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", @@ -25384,18 +22749,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", @@ -25479,24 +22832,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", @@ -25675,38 +23010,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", @@ -25762,50 +23065,6 @@ "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" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -25829,60 +23088,28 @@ "license": "MIT", "dependencies": { "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "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": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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=", + "node_modules/p-locate/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "optional": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-retry": { @@ -25898,20 +23125,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", @@ -26090,15 +23303,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", @@ -26109,12 +23313,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", @@ -26134,17 +23332,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", @@ -26271,29 +23458,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", @@ -26417,15 +23581,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", @@ -27372,17 +24527,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", @@ -27502,13 +24646,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", @@ -27567,13 +24704,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", @@ -27696,17 +24826,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", @@ -27930,93 +25049,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", @@ -28071,21 +25103,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", @@ -28140,19 +25157,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", @@ -28208,46 +25212,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", @@ -28434,13 +25398,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", @@ -28450,16 +25407,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", @@ -28495,15 +25442,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", @@ -28761,15 +25699,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", @@ -28929,20 +25858,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", @@ -28969,47 +25884,14 @@ }, "node_modules/semver": { "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, + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -29224,46 +26106,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", @@ -29271,31 +26113,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", @@ -29550,120 +26367,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", @@ -29725,33 +26428,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", @@ -29791,20 +26467,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", @@ -29824,13 +26486,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", @@ -29921,104 +26576,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", @@ -30044,14 +26607,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", @@ -30076,45 +26631,19 @@ }, "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==", + "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", @@ -30167,16 +26696,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", @@ -30389,26 +26908,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", @@ -30418,23 +26917,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", @@ -30446,26 +26928,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", @@ -31062,50 +27524,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", @@ -31283,42 +27701,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", @@ -31518,16 +27900,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", @@ -31643,54 +28015,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", @@ -31741,29 +28065,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", @@ -32122,21 +28423,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", @@ -32169,13 +28455,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", @@ -32214,61 +28493,10 @@ "@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.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", "dev": true, "funding": [ { @@ -32332,13 +28560,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", @@ -32366,39 +28587,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", @@ -32414,22 +28602,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", @@ -33585,16 +29757,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 7b8cdfe8eb8c0..60f56cc977063 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,29 @@ { "name": "WordPress", - "version": "7.1.0", + "version": "7.2.0", "description": "WordPress is open source software you can use to create a beautiful website, blog, or app.", "repository": { "type": "svn", "url": "https://develop.svn.wordpress.org/trunk" }, "gutenberg": { - "sha": "ea285b45692aed6c4f95353671393402f97f0aa7", + "sha": "5715a61334c4d29f21b67cf34b46061dc1b62502", "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", @@ -52,7 +65,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", @@ -77,6 +89,7 @@ "sinon-test": "~3.1.6", "source-map-loader": "5.0.0", "typescript": "6.0.3", + "update-browserslist-db": "1.3.1", "uuid": "14.0.1", "wait-on": "9.0.10", "webpack": "5.108.4" @@ -116,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", @@ -145,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 3dcf0f6c2c0de..7639da5e7037c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -24,14 +24,11 @@ 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 - - tests/phpstan/baselines/booleanAnd.alwaysTrue.neon - tests/phpstan/baselines/booleanAnd.leftAlwaysTrue.neon - - tests/phpstan/baselines/booleanAnd.rightAlwaysFalse.neon - tests/phpstan/baselines/booleanAnd.rightAlwaysTrue.neon - tests/phpstan/baselines/booleanNot.alwaysFalse.neon - tests/phpstan/baselines/booleanNot.alwaysTrue.neon @@ -39,18 +36,14 @@ includes: - tests/phpstan/baselines/booleanOr.alwaysTrue.neon - tests/phpstan/baselines/booleanOr.rightAlwaysTrue.neon - tests/phpstan/baselines/catch.neverThrown.neon - - tests/phpstan/baselines/class.nameCase.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 - - tests/phpstan/baselines/greater.invalid.neon - tests/phpstan/baselines/greaterOrEqual.alwaysTrue.neon - tests/phpstan/baselines/identical.alwaysFalse.neon - tests/phpstan/baselines/identical.alwaysTrue.neon @@ -59,43 +52,28 @@ includes: - 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/parameter.unresolvableType.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/property.unusedType.neon - - tests/phpstan/baselines/return.empty.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.alwaysFalse.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: @@ -139,3 +117,23 @@ 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 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..fe83cc7e9f2ae 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} */ @@ -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(); @@ -1263,6 +1260,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 +1484,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); @@ -2245,6 +2243,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..fd227b798eafb 100644 --- a/src/js/_enqueues/admin/postbox.js +++ b/src/js/_enqueues/admin/postbox.js @@ -246,10 +246,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) { @@ -353,8 +353,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. diff --git a/src/js/_enqueues/admin/privacy-tools.js b/src/js/_enqueues/admin/privacy-tools.js index 480766ad051d7..f783c24d57f5a 100644 --- a/src/js/_enqueues/admin/privacy-tools.js +++ b/src/js/_enqueues/admin/privacy-tools.js @@ -1,27 +1,49 @@ /** - * 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. + * + * @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. + * + * @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. + * + * @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 +57,6 @@ jQuery( function( $ ) { itemList = ''; } - $requestRow.addClass( 'has-request-results' ); - if ( $requestRow.hasClass( 'status-request-confirmed' ) ) { resultRowClasses = resultRowClasses + ' status-request-confirmed'; } @@ -51,7 +71,7 @@ jQuery( function( $ ) { '

' + summaryMessage + '

' + itemList + '' + - '' + + '' + ''; }); } @@ -76,6 +96,12 @@ jQuery( function( $ ) { clearResultsAfterRow( $requestRow ); setExportProgress( 0 ); + /** + * Handles a successful export. + * + * @param {string} zipUrl The URL of the generated ZIP file, if available. + * @return {void} + */ function onExportDoneSuccess( zipUrl ) { var summaryMessage = __( 'This user’s personal data export link was sent.' ); @@ -96,6 +122,12 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Handles an export failure. + * + * @param {string} errorMessage The error message to display. + * @return {void} + */ function onExportFailure( errorMessage ) { var summaryMessage = __( 'An error occurred while attempting to export personal data.' ); @@ -108,6 +140,12 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Updates the progress of the export process. + * + * @param {number} exporterIndex The index of the exporter to process. + * @return {void} + */ function setExportProgress( exporterIndex ) { var progress = ( exportersCount > 0 ? exporterIndex / exportersCount : 0 ), progressString = Math.round( progress * 100 ).toString() + '%'; @@ -115,6 +153,13 @@ jQuery( function( $ ) { $progress.html( progressString ); } + /** + * Performs the next export request. + * + * @param {number} exporterIndex The index of the exporter to process. + * @param {number} pageIndex The index of the page to process for the current exporter. + * @return {void} + */ function doNextExport( exporterIndex, pageIndex ) { $.ajax( { @@ -181,6 +226,11 @@ jQuery( function( $ ) { clearResultsAfterRow( $requestRow ); setErasureProgress( 0 ); + /** + * Handles a successful erasure. + * + * @return {void} + */ function onErasureDoneSuccess() { var summaryMessage = __( 'No personal data was found for this user.' ), classes = 'notice-success'; @@ -207,6 +257,9 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Handles an erasure failure. + */ function onErasureFailure() { var summaryMessage = __( 'An error occurred while attempting to find and erase personal data.' ); @@ -217,6 +270,12 @@ jQuery( function( $ ) { setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 ); } + /** + * Updates the progress of the erasure process. + * + * @param {number} eraserIndex The index of the eraser to process. + * @return {void} + */ function setErasureProgress( eraserIndex ) { var progress = ( erasersCount > 0 ? eraserIndex / erasersCount : 0 ), progressString = Math.round( progress * 100 ).toString() + '%'; @@ -224,6 +283,13 @@ jQuery( function( $ ) { $progress.html( progressString ); } + /** + * Performs the next erasure request. + * + * @param {number} eraserIndex The index of the eraser to process. + * @param {number} pageIndex The 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..27a01211636fd 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'); 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..1310033f4c1ff 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 () { 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..4397a72eaf9ee 100644 --- a/src/js/_enqueues/lib/emoji-loader.js +++ b/src/js/_enqueues/lib/emoji-loader.js @@ -2,18 +2,16 @@ * @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 + * @type {Object} + * @property {?object} source The source object containing emoji-related URLs. + * @property {?string} source.concatemoji The URL for the concatenated emoji script. + * @property {?string} source.twemoji The URL for the Twemoji script. + * @property {?string} source.wpemoji The URL for the WP Emoji script. */ const selector = 'script#wp-emoji-settings'; @@ -29,9 +27,9 @@ window._wpemojiSettings = settings; /** * Support tests. * @typedef SupportTests - * @type {object} - * @property {?boolean} flag - * @property {?boolean} emoji + * @type {Object} + * @property {?boolean} flag Whether the browser supports flag emojis. + * @property {?boolean} emoji Whether the browser supports general emojis. */ const sessionStorageKey = 'wpEmojiSettingsSupports'; @@ -44,7 +42,7 @@ const tests = [ 'flag', 'emoji' ]; * * @private * - * @returns {boolean} + * @return {boolean} True if the browser supports offloading to a Worker. */ function supportsWorkerOffloading() { return ( @@ -58,9 +56,9 @@ function supportsWorkerOffloading() { /** * @typedef SessionSupportTests - * @type {object} - * @property {number} timestamp - * @property {SupportTests} supportTests + * @type {Object} + * @property {number} timestamp The timestamp when the support tests were last updated. + * @property {SupportTests} supportTests The support tests for the browser. */ /** @@ -70,7 +68,7 @@ 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 { @@ -130,8 +128,8 @@ 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 {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. */ @@ -180,7 +178,7 @@ function emojiSetsRenderIdentically( context, set1, set2 ) { * @private * * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} emoji Emoji to test. + * @param {string} emoji Emoji to test. * * @return {boolean} True if the center point is empty. */ @@ -211,10 +209,10 @@ 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 {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. * * @return {boolean} True if the browser can render emoji, false if it cannot. */ @@ -281,13 +279,13 @@ 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; } @@ -304,9 +302,9 @@ 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 {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. * * @return {SupportTests} Support tests. diff --git a/src/js/_enqueues/lib/image-edit.js b/src/js/_enqueues/lib/image-edit.js index d1603051d7078..3ddc6eded840e 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. @@ -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/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..64bfd3fe754be 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 ) { @@ -2580,7 +2612,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 +2623,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 +2634,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 +2687,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 +2729,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 +2746,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 +2831,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 +2893,8 @@ }, /** + * Attaches events to the panel. + * * @since 4.1.0 */ attachEvents: function () { @@ -2906,7 +2954,7 @@ * * @since 4.1.0 * - * @return {Array} + * @return {wp.customize.Section[]} Array of sections. */ sections: function () { return this._children( 'panel', 'section' ); @@ -2936,10 +2984,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 +3098,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 +3110,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 +3125,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 +3156,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 +3211,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 +3266,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 +3372,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 +3447,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ updateTheme: function( event ) { @@ -3426,7 +3477,7 @@ * * @since 4.9.0 * - * @param {jQuery.Event} event - Event. + * @param {JQuery.Event} event Event. * @return {void} */ deleteTheme: function( event ) { @@ -3484,7 +3535,7 @@ * Default params. * * @since 4.9.0 - * @var {object} + * @member {Object} */ defaults: { label: '', @@ -3508,22 +3559,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 +3822,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 +3960,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 +3978,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 +4006,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 +4319,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 +4369,8 @@ /** * Open the media modal. + * + * @param {JQuery.Event} event Event. */ openFrame: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4376,6 +4434,8 @@ /** * Reset the setting to the default value. + * + * @param {JQuery.Event} event Event. */ restoreDefault: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4390,7 +4450,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 +4530,7 @@ * set up internal event bindings. */ ready: function() { - api.UploadControl.prototype.ready.apply( this, arguments ); + api.UploadControl.prototype.ready.call( this ); }, /** @@ -4478,7 +4538,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 +4599,8 @@ /** * Open the media modal to the library state. + * + * @param {JQuery.Event} event Event. */ openFrame: function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { @@ -4611,9 +4673,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 +4803,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 +4898,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 +4936,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 +4998,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 +5029,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 +5100,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 +5159,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 +5173,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 +5230,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 +5315,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 +5366,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 +5398,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 +5516,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 +5538,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 +5634,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 +5779,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 +5967,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 +6038,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 +6202,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 +6264,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 +6299,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 +6334,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 +6372,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 +6580,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 +6594,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 +6608,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 +6767,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 +7075,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 +7151,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 +7372,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 +7389,10 @@ } ); } } + + /** + * Cancels the highlight reminder for the schedule button. + */ function cancelHighlightScheduleButton() { if ( cancelScheduleButtonReminder ) { cancelScheduleButtonReminder(); @@ -7476,7 +7566,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 +7604,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 +7634,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 +7885,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 +8276,7 @@ /** * Lock user. * - * @type {object} + * @type {Object} */ lockUser: null, @@ -8195,8 +8288,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 +8312,7 @@ * * @since 4.9.0 * - * @return {jQuery} Notification container. + * @return {JQuery} Notification container. */ render: function() { var notification = this, li, data, takeOverButton, request; @@ -8285,9 +8378,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 +8460,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 +8486,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 +8843,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 +8981,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 +9022,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 +9044,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 +9438,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..274868f52d859 100644 --- a/src/js/_enqueues/wp/emoji.js +++ b/src/js/_enqueues/wp/emoji.js @@ -2,6 +2,8 @@ * wp-emoji.js is used to replace emoji with images in browsers when the browser * doesn't support emoji natively. * + * @param {Window} window The global window object. + * @param {Object} settings The settings object. * @output wp-includes/js/wp-emoji.js */ @@ -188,7 +190,7 @@ * * - 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 * 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..d330831c490eb 100644 --- a/src/js/_enqueues/wp/media/audiovideo.js +++ b/src/js/_enqueues/wp/media/audiovideo.js @@ -44,6 +44,7 @@ wp.media.mixin = { * * @since 4.2.0 * + * @param {Object} t The MediaElement player object. * @return {void} */ removePlayer: function(t) { @@ -196,8 +197,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..ff5d72ad2801e 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; @@ -1485,8 +1481,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 +1965,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 +2078,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..59d0ef2e6b1cb 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,10 +1116,10 @@ * * @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' ), @@ -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..d00a0d5f6ae07 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 ); 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..152c150200a75 100644 --- a/src/js/media/views/attachment.js +++ b/src/js/media/views/attachment.js @@ -79,6 +79,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 +99,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() { @@ -167,7 +171,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 +227,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 +309,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 +320,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 +351,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 +371,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 +388,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 +423,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 +476,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 +520,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 +537,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 +570,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..e3bc0d09e643b 100644 --- a/src/js/media/views/frame/edit-attachments.js +++ b/src/js/media/views/frame/edit-attachments.js @@ -207,6 +207,7 @@ EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta /** * Rerender the view. + * @param {wp.media.model.Attachment} model The attachment model to render. */ rerender: function( model ) { this.stopListening( this.model ); @@ -285,6 +286,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-admin/about.php b/src/wp-admin/about.php index f8c48bb195b3c..1bfc3018e0556 100644 --- a/src/wp-admin/about.php +++ b/src/wp-admin/about.php @@ -14,7 +14,7 @@ $title = _x( 'About', 'page title' ); list( $display_version ) = explode( '-', wp_get_wp_version() ); -$display_major_version = '7.0'; +$display_major_version = '7.1'; $release_notes_url = sprintf( /* translators: %s: WordPress version number. */ @@ -34,21 +34,19 @@ sanitize_title( $display_major_version ) ); +$version_text = sprintf( + /* translators: %s: Version number. */ + __( 'WordPress %s' ), + $display_version +); + require_once ABSPATH . 'wp-admin/admin-header.php'; ?>
-

- -

+

@@ -62,22 +60,30 @@
-

-

+

+ +

+

-

+

-
- +
+

- +
@@ -85,29 +91,29 @@
- +
-

+

-
- +
+

-

+

-
- +
+

- +
@@ -115,14 +121,14 @@
- +
-

+

-
- +
+

@@ -137,8 +143,8 @@
-

-

+

+

@@ -147,7 +153,7 @@

-

+

@@ -177,7 +183,7 @@
- + <?php echo esc_attr( $version_text ); ?>

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..265c91923eea9 100644 --- a/src/wp-admin/admin-header.php +++ b/src/wp-admin/admin-header.php @@ -100,18 +100,45 @@ wp_enqueue_script( 'svg-painter' ); $admin_body_class = preg_replace( '/[^a-z0-9_-]+/i', '-', $hook_suffix ); -?> - - 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. @@ -246,6 +273,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 +282,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/contribute.php b/src/wp-admin/contribute.php index 4a6989adffa25..9a57a1b57915d 100644 --- a/src/wp-admin/contribute.php +++ b/src/wp-admin/contribute.php @@ -12,22 +12,11 @@ // Used in the HTML title tag. $title = __( 'Get Involved' ); -list( $display_version ) = explode( '-', get_bloginfo( 'version' ) ); -$header_alt_text = sprintf( - /* translators: %s: Version number. */ - __( 'WordPress %s' ), - $display_version -); - require_once ABSPATH . 'wp-admin/admin-header.php'; ?>
-
- <?php echo esc_attr( $header_alt_text ); ?> -
-

diff --git a/src/wp-admin/credits.php b/src/wp-admin/credits.php index 960c334913474..75993cf6652a7 100644 --- a/src/wp-admin/credits.php +++ b/src/wp-admin/credits.php @@ -13,13 +13,6 @@ // Used in the HTML title tag. $title = __( 'Credits' ); -list( $display_version ) = explode( '-', get_bloginfo( 'version' ) ); -$header_alt_text = sprintf( - /* translators: %s: Version number. */ - __( 'WordPress %s' ), - $display_version -); - require_once ABSPATH . 'wp-admin/admin-header.php'; $credits = wp_credits(); @@ -27,10 +20,6 @@
-
- <?php echo esc_attr( $header_alt_text ); ?> -
-

diff --git a/src/wp-admin/css/about.css b/src/wp-admin/css/about.css index 721a98078f0d6..9d6d8adff4a34 100644 --- a/src/wp-admin/css/about.css +++ b/src/wp-admin/css/about.css @@ -21,8 +21,8 @@ .about__container { /* Section backgrounds */ - --background: #ebe8e5; - --subtle-background: #ebe8e5; + --background: #3858e9; + --subtle-background: #f4f4f4; /* Main text color */ --text: #1e1e1e; @@ -34,7 +34,7 @@ --accent-3: #ececec; /* hr background */ /* Header background on small screens */ - --accent-gradient: linear-gradient(90deg, #000000 4.7%, var(--accent-1) 83.84%)/*rtl:linear-gradient(-90deg, #000000 4.7%, var(--accent-1) 83.84%)*/; + --accent-gradient: linear-gradient(90deg, #000 4.7%, var(--accent-1) 83.84%)/*rtl:linear-gradient(-90deg, #000 4.7%, var(--accent-1) 83.84%)*/; /* Navigation colors. */ --nav-background: #fff; @@ -278,7 +278,7 @@ .about__section.has-2-columns.is-wider-right, .about__section.has-2-columns.is-wider-left, .about__section.has-3-columns { - display: block; + grid-template-columns: 1fr; margin-bottom: calc(var(--gap) / 2); } @@ -293,13 +293,11 @@ margin-bottom: calc(var(--gap) * 2); } - .about__section.has-2-columns.has-gutters .column, .about__section.has-2-columns.has-gutters .column, .about__section.has-3-columns.has-gutters .column { margin-bottom: var(--gap); } - .about__section.has-2-columns.has-gutters .column:last-child, .about__section.has-2-columns.has-gutters .column:last-child, .about__section.has-3-columns.has-gutters .column:last-child { margin-bottom: 0; @@ -329,10 +327,18 @@ @media screen and (max-width: 600px) { .about__section.has-2-columns { - display: block; + grid-template-columns: 1fr; margin-bottom: var(--gap); } + .about__section.has-2-columns:not(.is-wider-right,.is-wider-left) div:has(img) { + order: 1; + } + + .about__section.has-2-columns:not(.is-wider-right,.is-wider-left) div:not(:has(img)) { + order: 0; + } + .about__section.has-2-columns:not(.has-gutters) .column:nth-of-type(n) { padding-top: calc(var(--gap) / 2); padding-bottom: calc(var(--gap) / 2); @@ -351,12 +357,12 @@ } .about__section .column.is-left-padding-zero { - padding-right: 0; - } + padding-right: 0; + } - .about__section .column.is-right-padding-zero { - padding-left: 0; - } + .about__section .column.is-right-padding-zero { + padding-left: 0; + } } @media screen and (max-width: 480px) { @@ -437,9 +443,6 @@ .about__container p { text-wrap: pretty; -} - -.about__container p { font-size: inherit; line-height: inherit; } @@ -449,7 +452,7 @@ margin-bottom: 1rem; font-size: 1.5rem; font-weight: 300; - line-height: 160%; + line-height: 1.6; } .about__section a { @@ -531,7 +534,7 @@ margin: calc(var(--gap) / 2) var(--gap); height: 0; border: none; - border-top: 4px solid var(--accent-3); + border-top: 6px solid var(--accent-3); } .about__container hr.is-small { @@ -581,6 +584,10 @@ .about__container h3.is-larger-heading { font-size: 2em; } + + .about__container h1 { + text-shadow: 0 0 2px var(--background); + } } /* 1.3 - Header */ @@ -596,48 +603,49 @@ padding-right: 26rem; /* Space for the background image. */ min-height: clamp(10rem, 25vw, 18.75rem); border-radius: var(--border-radius); - background-image: url( "../images/about-header-default.webp?ver=20260514" ); + background-image: url(../images/about-header-default.svg?ver=7.1); background-repeat: no-repeat; background-position: right center; background-size: cover; background-color: var(--background); color: var(--text-light); + margin-bottom: 0.25rem; } -.credits-php .about__header { - background-image: url( "../images/about-header-credits.webp?ver=20260514" ); +.credits-php .about__header { + background-image: url(../images/about-header-credits.svg?ver=7.1); } -.freedoms-php .about__header { - background-image: url( "../images/about-header-freedoms.webp?ver=20260514" ); +.freedoms-php .about__header { + background-image: url(../images/about-header-freedoms.svg?ver=7.1); } -.privacy-php .about__header { - background-image: url( "../images/about-header-privacy.webp?ver=20260514" ); +.privacy-php .about__header { + background-image: url(../images/about-header-privacy.svg?ver=7.1); } .contribute-php .about__header { - background-image: url( "../images/about-header-get-involved.webp?ver=20260514" ); + background-image: url(../images/about-header-get-involved.svg?ver=7.1); } [dir="rtl"] .about__header { - background-image: url( "../images/about-header-default-rtl.webp?ver=20260514" ); + background-image: url(../images/about-header-default-rtl.svg?ver=7.1); } -[dir="rtl"] .credits-php .about__header { - background-image: url( "../images/about-header-credits-rtl.webp?ver=20260514" ); +[dir="rtl"] .credits-php .about__header { + background-image: url(../images/about-header-credits-rtl.svg?ver=7.1); } -[dir="rtl"] .freedoms-php .about__header { - background-image: url( "../images/about-header-freedoms-rtl.webp?ver=20260514" ); +[dir="rtl"] .freedoms-php .about__header { + background-image: url(../images/about-header-freedoms-rtl.svg?ver=7.1); } -[dir="rtl"] .privacy-php .about__header { - background-image: url( "../images/about-header-privacy-rtl.webp?ver=20260514" ); +[dir="rtl"] .privacy-php .about__header { + background-image: url(../images/about-header-privacy-rtl.svg?ver=7.1); } [dir="rtl"] .contribute-php .about__header { - background-image: url( "../images/about-header-get-involved-rtl.webp?ver=20260514" ); + background-image: url(../images/about-header-get-involved-rtl.svg?ver=7.1); } .about__header-image { @@ -657,7 +665,7 @@ font-size: clamp(2rem, 20vw - 9rem, 4rem); line-height: 1; font-weight: 600; - color: var(--text); + color: var(--text-light); } .about-php .about__header-title h1, @@ -676,7 +684,7 @@ padding: 0; font-size: 1.6rem; line-height: 1.15; - color: var(--text); + color: var(--text-light); } .about__header-navigation { @@ -1069,7 +1077,7 @@ .about-wrap figcaption { font-size: 13px; text-align: center; - color: white; + color: #fff; text-overflow: ellipsis; } diff --git a/src/wp-admin/css/admin-menu.css b/src/wp-admin/css/admin-menu.css index aa6a8bc1414aa..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; } @@ -800,10 +786,12 @@ li#wp-admin-bar-menu-toggle { display: block; padding: 0; overflow: hidden; + outline: none; text-decoration: none; + border: 1px solid transparent; background: none; - height: 46px; - box-sizing: border-box; + height: 44px; + margin-left: -1px; } .wp-responsive-open #wpadminbar #wp-admin-bar-menu-toggle a { @@ -814,17 +802,22 @@ li#wp-admin-bar-menu-toggle { display: block; } - #wpadminbar #wp-admin-bar-menu-toggle .ab-icon:before { + #wpadminbar #wp-admin-bar-menu-toggle a:hover { + border: 1px solid transparent; + } + + #wpadminbar #wp-admin-bar-menu-toggle .ab-icon::before { content: "\f228"; display: inline-block; float: left; - font: normal 40px/46px dashicons; + font: 400 40px/45px dashicons; vertical-align: middle; + outline: none; margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - height: 46px; - width: 52px; + height: 44px; + width: 50px; padding: 0; border: none; text-align: center; @@ -832,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/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 91d6a4b66bc8c..366f1b86b4f16 100644 --- a/src/wp-admin/css/colors/_admin.scss +++ b/src/wp-admin/css/colors/_admin.scss @@ -416,11 +416,9 @@ ul#adminmenu > li.current > a.current:after { background: variables.$menu-submenu-background; } -#wpadminbar > #wp-toolbar li:hover span.ab-label, -#wpadminbar > #wp-toolbar li.hover span.ab-label, -/* The adminbar menu may output either links or focusable div elements. */ -/* As such, we target the focus state without specifying the element type. */ -#wpadminbar > #wp-toolbar :focus span.ab-label { +#wpadminbar:not(.mobile) > #wp-toolbar li:hover span.ab-label, +#wpadminbar:not(.mobile) > #wp-toolbar li.hover span.ab-label, +#wpadminbar:not(.mobile) > #wp-toolbar a:focus span.ab-label { color: variables.$menu-submenu-focus-text; } @@ -451,9 +449,7 @@ ul#adminmenu > li.current > a.current:after { } #wpadminbar .quicklinks li .blavatar, -#wpadminbar .menupop .menupop > .ab-item:before, -#wpadminbar.mobile .quicklinks .ab-icon:before, -#wpadminbar.mobile .quicklinks .ab-item:before { +#wpadminbar .menupop .menupop > .ab-item:before { color: variables.$menu-icon; } @@ -478,17 +474,21 @@ ul#adminmenu > li.current > a.current:after { color: variables.$menu-submenu-focus-text; } -// Note that the icon of the site-name item is not wrapped within a span with class ab-icon like other items. #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.mobile .quicklinks .ab-item:focus: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 { + color: variables.$menu-icon; +} + + /* Admin Bar: search */ #wpadminbar #adminbarsearch:before { @@ -531,16 +531,14 @@ ul#adminmenu > li.current > a.current:after { color: variables.$menu-text; } +#wpadminbar #wp-admin-bar-user-info a:hover .display-name { + color: variables.$menu-submenu-focus-text; +} + #wpadminbar #wp-admin-bar-user-info .username { color: variables.$menu-submenu-text; } -#wpadminbar #wp-admin-bar-user-info a:hover .display-name, -#wpadminbar #wp-admin-bar-user-info a:focus .display-name, -#wpadminbar #wp-admin-bar-user-info a:hover .username, -#wpadminbar #wp-admin-bar-user-info a:focus .username { - color: variables.$menu-submenu-focus-text; -} /* Pointers */ diff --git a/src/wp-admin/css/colors/_mixins.scss b/src/wp-admin/css/colors/_mixins.scss index 9575f1f2d623b..7b3802307a637 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. 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..535307832dedb 100644 --- a/src/wp-admin/css/common.css +++ b/src/wp-admin/css/common.css @@ -2553,7 +2553,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%); @@ -3372,7 +3372,7 @@ img { .bulk-action-notice .toggle-indicator::before { line-height: 16px; vertical-align: top; - color: #787c82; + color: #50575e; } .postbox .handle-order-higher:focus, @@ -4255,9 +4255,6 @@ img { margin-bottom: 0; } - #wpfooter { - display: none; - } #comments-form .checkforspam { display: none; diff --git a/src/wp-admin/css/customize-controls.css b/src/wp-admin/css/customize-controls.css index 3dfdfea790fb3..646af6c4407df 100644 --- a/src/wp-admin/css/customize-controls.css +++ b/src/wp-admin/css/customize-controls.css @@ -2493,12 +2493,20 @@ body.cheatin p { * Widgets and Menus common styles */ +.customize-control-nav_menu-buttons, +.customize-control-widgets-buttons { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + align-items: center; + gap: 8px; +} + /* higher specificity than .wp-core-ui .button */ #customize-theme-controls .add-new-widget, #customize-theme-controls .add-new-menu-item { cursor: pointer; - float: right; - margin: 0 0 0 10px; + margin: 0; transition: all 0.2s; -webkit-user-select: none; user-select: none; @@ -2530,7 +2538,6 @@ body.cheatin p { /* Reordering */ .reorder-toggle { - float: right; padding: 5px 8px; text-decoration: none; cursor: pointer; diff --git a/src/wp-admin/css/customize-nav-menus.css b/src/wp-admin/css/customize-nav-menus.css index cb3052e75f3b5..9c98728841bc3 100644 --- a/src/wp-admin/css/customize-nav-menus.css +++ b/src/wp-admin/css/customize-nav-menus.css @@ -329,7 +329,7 @@ display: block; padding: 1px 2px 1px 0; border-radius: 50%; - color: #787c82; + color: #50575e; font: normal 20px/1 dashicons; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -770,7 +770,7 @@ body.adding-menu-items #customize-preview iframe { cursor: default; opacity: .5; background: #fff; - color: #787c82; + color: #50575e; } .added-menu-item .menu-item-handle { @@ -860,10 +860,6 @@ li.assigned-to-menu-location .add-new-menu-item { } .customize-control-nav_menu .customize-control-nav_menu-buttons { - display: flex; - flex-direction: row-reverse; - align-items: center; - gap: 8px; margin-top: 12px; } diff --git a/src/wp-admin/css/customize-widgets.css b/src/wp-admin/css/customize-widgets.css index 6e1bda06b13dc..db86274af00f1 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, diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css index 17a9e312b85c6..09f49cbe4daf9 100644 --- a/src/wp-admin/css/dashboard.css +++ b/src/wp-admin/css/dashboard.css @@ -792,7 +792,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; } @@ -827,7 +828,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 +876,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; @@ -1063,7 +1066,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; diff --git a/src/wp-admin/css/edit.css b/src/wp-admin/css/edit.css index c02a15aa3995a..e564d362a5a85 100644 --- a/src/wp-admin/css/edit.css +++ b/src/wp-admin/css/edit.css @@ -876,7 +876,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; } @@ -1087,7 +1087,7 @@ 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 */ 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..0475984e19105 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -1188,7 +1188,7 @@ table.form-table td .updated p { } .pressthis-bookmarklet span:before { - color: #787c82; + color: #50575e; font: normal 20px/1 dashicons; content: "\f157"; content: "\f157" / ''; @@ -1490,39 +1490,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 +1539,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; } 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..711a618ca5c79 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -778,7 +778,7 @@ th.sorted a span { } .view-switch a:before { - color: #c3c4c7; + color: #757575; display: inline-block; font: normal 20px/1 dashicons; vertical-align: middle; @@ -793,7 +793,7 @@ th.sorted a span { .view-switch a:hover:before, .view-switch a:focus:before { - color: #787c82; + color: #1e1e1e; } .view-switch a.current:before { @@ -1980,7 +1980,8 @@ 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; } @@ -1994,6 +1995,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; } @@ -2340,8 +2345,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 +2355,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 +2364,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; } diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index 4765e604a938d..2b224fc3330aa 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -201,11 +201,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; } diff --git a/src/wp-admin/css/media.css b/src/wp-admin/css/media.css index 3d7b0c9455c83..09c69d83cbb41 100644 --- a/src/wp-admin/css/media.css +++ b/src/wp-admin/css/media.css @@ -675,7 +675,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; 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..f43db18a84efe 100644 --- a/src/wp-admin/css/site-health.css +++ b/src/wp-admin/css/site-health.css @@ -296,6 +296,10 @@ are styled in the Privacy section of edit.css */ } /* Styling unique to the dashboard widget. */ +.no-js #dashboard_site_health { + display: none; +} + #dashboard_site_health .site-health-details { padding-left: 16px; } 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..5ffb62ca033cd 100644 --- a/src/wp-admin/css/themes.css +++ b/src/wp-admin/css/themes.css @@ -453,7 +453,7 @@ body.js .theme-browser.search-loading { .theme-overlay .theme-header .close:before { font: normal 22px/50px dashicons !important; - color: #787c82; + color: #50575e; display: inline-block; content: "\f335"; content: "\f335" / ''; @@ -464,7 +464,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; diff --git a/src/wp-admin/css/widgets.css b/src/wp-admin/css/widgets.css index 99039d3c7c66a..44a3eaf03f6a7 100644 --- a/src/wp-admin/css/widgets.css +++ b/src/wp-admin/css/widgets.css @@ -516,7 +516,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); } 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/font-library.php b/src/wp-admin/font-library.php index 6129211f45545..0daff32ba5bac 100644 --- a/src/wp-admin/font-library.php +++ b/src/wp-admin/font-library.php @@ -18,36 +18,20 @@ ); } -// 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 ); } // Set the page title -$title = _x( 'Fonts', 'Font Library admin page title' ); -$js_required_message = __( 'The Fonts screen requires JavaScript. Please enable JavaScript in your browser settings to install and manage fonts.' ); +$title = _x( 'Fonts', 'Font Library admin page title' ); require_once ABSPATH . 'wp-admin/admin-header.php'; -?> -
-

- 'error', - 'additional_classes' => array( 'hide-if-js' ), - ) - ); - ?> -
-
-
- <?php echo esc_attr( $header_alt_text ); ?> -
-

diff --git a/src/wp-admin/images/about-header-credits-rtl.svg b/src/wp-admin/images/about-header-credits-rtl.svg new file mode 100644 index 0000000000000..001e47d6949f8 --- /dev/null +++ b/src/wp-admin/images/about-header-credits-rtl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-credits-rtl.webp b/src/wp-admin/images/about-header-credits-rtl.webp deleted file mode 100644 index b65ce15238ea9..0000000000000 Binary files a/src/wp-admin/images/about-header-credits-rtl.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-credits.svg b/src/wp-admin/images/about-header-credits.svg new file mode 100644 index 0000000000000..ac6dfef6883ea --- /dev/null +++ b/src/wp-admin/images/about-header-credits.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-credits.webp b/src/wp-admin/images/about-header-credits.webp deleted file mode 100644 index b83bb5b49e1c4..0000000000000 Binary files a/src/wp-admin/images/about-header-credits.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-default-rtl.svg b/src/wp-admin/images/about-header-default-rtl.svg new file mode 100644 index 0000000000000..d8574fc4c3b75 --- /dev/null +++ b/src/wp-admin/images/about-header-default-rtl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-default-rtl.webp b/src/wp-admin/images/about-header-default-rtl.webp deleted file mode 100644 index 7de0c9a4ffec2..0000000000000 Binary files a/src/wp-admin/images/about-header-default-rtl.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-default.svg b/src/wp-admin/images/about-header-default.svg new file mode 100644 index 0000000000000..ca71da7d8a2be --- /dev/null +++ b/src/wp-admin/images/about-header-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-default.webp b/src/wp-admin/images/about-header-default.webp deleted file mode 100644 index 020a92a7265ae..0000000000000 Binary files a/src/wp-admin/images/about-header-default.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-freedoms-rtl.svg b/src/wp-admin/images/about-header-freedoms-rtl.svg new file mode 100644 index 0000000000000..5eb445f4b8a4a --- /dev/null +++ b/src/wp-admin/images/about-header-freedoms-rtl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-freedoms-rtl.webp b/src/wp-admin/images/about-header-freedoms-rtl.webp deleted file mode 100644 index 506c20f4cf620..0000000000000 Binary files a/src/wp-admin/images/about-header-freedoms-rtl.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-freedoms.svg b/src/wp-admin/images/about-header-freedoms.svg new file mode 100644 index 0000000000000..e996bcc373802 --- /dev/null +++ b/src/wp-admin/images/about-header-freedoms.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-freedoms.webp b/src/wp-admin/images/about-header-freedoms.webp deleted file mode 100644 index 4740e8ab087b0..0000000000000 Binary files a/src/wp-admin/images/about-header-freedoms.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-get-involved-rtl.svg b/src/wp-admin/images/about-header-get-involved-rtl.svg new file mode 100644 index 0000000000000..3db4448e465af --- /dev/null +++ b/src/wp-admin/images/about-header-get-involved-rtl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-get-involved-rtl.webp b/src/wp-admin/images/about-header-get-involved-rtl.webp deleted file mode 100644 index 4cd5b89c61c00..0000000000000 Binary files a/src/wp-admin/images/about-header-get-involved-rtl.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-get-involved.svg b/src/wp-admin/images/about-header-get-involved.svg new file mode 100644 index 0000000000000..17b2717ddf63b --- /dev/null +++ b/src/wp-admin/images/about-header-get-involved.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-get-involved.webp b/src/wp-admin/images/about-header-get-involved.webp deleted file mode 100644 index 33a6708b9f2fa..0000000000000 Binary files a/src/wp-admin/images/about-header-get-involved.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-privacy-rtl.svg b/src/wp-admin/images/about-header-privacy-rtl.svg new file mode 100644 index 0000000000000..e2b3084e14b55 --- /dev/null +++ b/src/wp-admin/images/about-header-privacy-rtl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-privacy-rtl.webp b/src/wp-admin/images/about-header-privacy-rtl.webp deleted file mode 100644 index 0ee585216df5e..0000000000000 Binary files a/src/wp-admin/images/about-header-privacy-rtl.webp and /dev/null differ diff --git a/src/wp-admin/images/about-header-privacy.svg b/src/wp-admin/images/about-header-privacy.svg new file mode 100644 index 0000000000000..ed37fb636362b --- /dev/null +++ b/src/wp-admin/images/about-header-privacy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/wp-admin/images/about-header-privacy.webp b/src/wp-admin/images/about-header-privacy.webp deleted file mode 100644 index 5178051483f75..0000000000000 Binary files a/src/wp-admin/images/about-header-privacy.webp and /dev/null differ diff --git a/src/wp-admin/images/about-release-badge.svg b/src/wp-admin/images/about-release-badge.svg index 751068ebe62ed..845f4817a441f 100644 --- a/src/wp-admin/images/about-release-badge.svg +++ b/src/wp-admin/images/about-release-badge.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/wp-admin/images/about-release-logo.svg b/src/wp-admin/images/about-release-logo.svg deleted file mode 100644 index d497949fe8b74..0000000000000 --- a/src/wp-admin/images/about-release-logo.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - 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/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index c51751940a976..c05633428ae68 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -12,7 +12,7 @@ // /** - * Handles the Heartbeat API in the no-privilege context via AJAX . + * Handles the Heartbeat API in the no-privilege context via AJAX. * * Runs when the user is not logged in. * @@ -2059,6 +2059,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 +2077,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 +4629,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/class-custom-image-header.php b/src/wp-admin/includes/class-custom-image-header.php index 97a1a16052d12..367ba04cdc340 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']; @@ -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 81e40122d5bc5..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; @@ -248,7 +256,7 @@ private function do_overwrite() { $is_invalid_parent = false; if ( ! empty( $new_theme_data['Template'] ) ) { - $is_invalid_parent = ! in_array( $new_theme_data['Template'], array_keys( $all_themes ), true ); + $is_invalid_parent = ! isset( $all_themes[ $new_theme_data['Template'] ] ); } $rows = array( 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..b3dccaf478a83 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 @@ -214,7 +214,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 +264,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-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-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..2792b4b3ec3d0 100644 --- a/src/wp-admin/includes/class-wp-list-table.php +++ b/src/wp-admin/includes/class-wp-list-table.php @@ -133,18 +133,18 @@ 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. * } */ public function __construct( $args = array() ) { @@ -427,11 +427,15 @@ 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. */ @@ -729,7 +733,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 ); @@ -1918,6 +1922,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 +1934,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-themes-list-table.php b/src/wp-admin/includes/class-wp-ms-themes-list-table.php index 81c35414d9053..eb49de155107c 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 @@ -724,7 +724,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-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 8a319986766b8..d3d631b9b4467 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1135,7 +1135,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 +1854,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..a60ecca955595 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 = '' ) { 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 2ddfaadc4b39d..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; } @@ -2759,20 +2757,20 @@ public function get_test_autoloaded_options() { */ public function get_test_search_engine_visibility() { $result = array( - 'label' => __( 'Search engine indexing is enabled.', 'default' ), + 'label' => __( 'Search engine indexing is enabled.' ), 'status' => 'good', 'badge' => array( - 'label' => __( 'Privacy', 'default' ), + 'label' => __( 'Privacy' ), 'color' => 'blue', ), 'description' => sprintf( '

%s

', - __( 'Search engines can crawl and index your site. No action needed.', 'default' ) + __( 'Search engines can crawl and index your site. No action needed.' ) ), 'actions' => sprintf( '

%2$s

', esc_url( admin_url( 'options-reading.php#blog_public' ) ), - __( 'Review your visibility settings', 'default' ) + __( 'Review your visibility settings' ) ), 'test' => 'search_engine_visibility', ); @@ -2780,11 +2778,11 @@ public function get_test_search_engine_visibility() { // If indexing is discouraged, flip to “recommended”: if ( ! get_option( 'blog_public' ) ) { $result['status'] = 'recommended'; - $result['label'] = __( 'Search engines are discouraged from indexing this site.', 'default' ); + $result['label'] = __( 'Search engines are discouraged from indexing this site.' ); $result['badge']['color'] = 'blue'; $result['description'] = sprintf( '

%s

', - __( 'Your site is hidden from search engines. Consider enabling indexing if this is a public site.', 'default' ) + __( 'Your site is hidden from search engines. Consider enabling indexing if this is a public site.' ) ); } diff --git a/src/wp-admin/includes/class-wp-site-icon.php b/src/wp-admin/includes/class-wp-site-icon.php index ea0ab35007327..3a7a160fc874a 100644 --- a/src/wp-admin/includes/class-wp-site-icon.php +++ b/src/wp-admin/includes/class-wp-site-icon.php @@ -41,22 +41,21 @@ class WP_Site_Icon { /* * Square, medium sized tiles for IE11+. * - * See https://msdn.microsoft.com/library/dn455106(v=vs.85).aspx + * @link https://msdn.microsoft.com/library/dn455106(v=vs.85).aspx */ 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 */ 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/library/prerelease/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html */ 180, @@ -171,7 +170,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..518b786f62370 100644 --- a/src/wp-admin/includes/class-wp-themes-list-table.php +++ b/src/wp-admin/includes/class-wp-themes-list-table.php @@ -340,6 +340,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 +359,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 0fe5c62064b64..488e01aa92481 100644 --- a/src/wp-admin/includes/dashboard.php +++ b/src/wp-admin/includes/dashboard.php @@ -568,11 +568,13 @@ function wp_dashboard_quick_press( $message = false, $notice_type = 'error' ) { $post->post_title = ''; // Remove the auto draft title. } } else { - $post = get_default_post_to_edit( 'post', true ); - $user_id = get_current_user_id(); + $post = get_default_post_to_edit( 'post', true ); + $user_id = get_current_user_id(); + $user_blogs = get_blogs_of_user( $user_id ); + $current_blog_id = get_current_blog_id(); // Don't create an option if this is a super admin who does not belong to this site. - if ( in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user_id ) ), true ) ) { + if ( isset( $user_blogs[ $current_blog_id ] ) ) { update_user_option( $user_id, 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID. } } @@ -654,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; } } @@ -1370,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 .= ''; @@ -1996,7 +2001,7 @@ function wp_dashboard_site_health() { $issues_total = $issue_counts['recommended'] + $issue_counts['critical']; ?>
-
+
'; @@ -2234,13 +2277,10 @@ function media_upload_form( $errors = null ) { * * @since 3.3.0 * - * @param array $plupload_init An array of default settings used by Plupload. + * @param array $plupload_init An array of default settings used by Plupload. */ $plupload_init = apply_filters( 'plupload_init', $plupload_init ); - ?> -
- + 0 ) { + preloaded.each( function () { + prepareMediaItem( { id: this.id.replace( /[^0-9]/g, '' ) }, '' ); + } ); + } + updateMediaForm(); + } ); + JS + ); + ?>

+ +
@@ -2587,16 +2645,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 +2978,21 @@ function media_upload_library_form( $errors ) {
- + 0 ) { + preloaded.each( function () { + prepareMediaItem( { id: this.id.replace( /[^0-9]/g, '' ) }, '' ); + } ); + updateMediaForm(); + } + } ); + JS + ); + ?>
@@ -3370,7 +3438,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 +3617,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/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.php b/src/wp-admin/includes/ms.php index 56e17113653d2..155170aaf4f41 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, ) ); ?> diff --git a/src/wp-admin/includes/plugin-install.php b/src/wp-admin/includes/plugin-install.php index dc232f1df7018..b37b956d3455c 100644 --- a/src/wp-admin/includes/plugin-install.php +++ b/src/wp-admin/includes/plugin-install.php @@ -593,8 +593,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 +894,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..53d933d07e4d8 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']; @@ -1264,7 +1270,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 ); } diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index 39d267b623037..c39135316978f 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,10 @@ 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[] $post_mime_types Post mime types. - * @type string[] $avail_post_mime_types Available post mime types. + * @type array $0 Post mime types. See get_post_mime_types(). + * @type string[] $1 Available post mime types. * } */ function wp_edit_attachments_query( $q = false ) { @@ -2607,7 +2621,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/privacy-tools.php b/src/wp-admin/includes/privacy-tools.php index e7b949842ffd1..17e660c8c0d0e 100644 --- a/src/wp-admin/includes/privacy-tools.php +++ b/src/wp-admin/includes/privacy-tools.php @@ -74,7 +74,7 @@ function _wp_personal_data_handle_actions() { if ( isset( $_POST['privacy_action_email_retry'] ) ) { check_admin_referer( 'bulk-privacy_requests' ); - $request_id = absint( current( array_keys( (array) wp_unslash( $_POST['privacy_action_email_retry'] ) ) ) ); + $request_id = absint( array_key_first( (array) wp_unslash( $_POST['privacy_action_email_retry'] ) ) ); $result = _wp_privacy_resend_request( $request_id ); if ( is_wp_error( $result ) ) { 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/template.php b/src/wp-admin/includes/template.php index 418bfd7def697..b535b3acbfc66 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 ) { @@ -2140,19 +2140,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 +2222,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 "> -
- + get_col_length( $wpdb->comments, 'comment_content' ); - if ( is_wp_error( $content_length ) ) { - return; - } - if ( false === $content_length ) { $content_length = array( 'type' => 'byte', 'length' => 65535, ); - } elseif ( ! is_array( $content_length ) ) { - $length = (int) $content_length > 0 ? (int) $content_length : 65535; - $content_length = array( - 'type' => 'byte', - 'length' => $length, - ); } - if ( 'byte' !== $content_length['type'] || 0 === $content_length['length'] ) { + if ( ! is_array( $content_length ) || 'byte' !== $content_length['type'] || 0 === $content_length['length'] ) { // Sites with malformed DB schemas are on their own. return; } diff --git a/src/wp-admin/includes/user.php b/src/wp-admin/includes/user.php index 2aeeba0b035b4..c6c08c4eaf76c 100644 --- a/src/wp-admin/includes/user.php +++ b/src/wp-admin/includes/user.php @@ -169,8 +169,8 @@ function edit_user( $user_id = 0 ) { * @since 1.5.1 * * @param string $user_login The username. - * @param string $pass1 The password (passed by reference). - * @param string $pass2 The confirmed password (passed by reference). + * @param string $pass1 The password (passed by reference). + * @param string $pass2 The confirmed password (passed by reference). */ do_action_ref_array( 'check_passwords', array( $user->user_login, &$pass1, &$pass2 ) ); @@ -717,7 +717,7 @@ function wp_is_authorize_application_redirect_url_valid( $url ) { * @since 6.3.2 * * @param string[] $bad_protocols Array of invalid protocols. - * @param string $url The redirect URL to be validated. + * @param string $url The redirect URL to be validated. */ $invalid_protocols = apply_filters( 'wp_authorize_application_redirect_url_invalid_protocols', $bad_protocols, $url ); $invalid_protocols = array_map( 'strtolower', $invalid_protocols ); diff --git a/src/wp-admin/install.php b/src/wp-admin/install.php index b6b7a08f2a5aa..3d5a142b482dd 100644 --- a/src/wp-admin/install.php +++ b/src/wp-admin/install.php @@ -114,20 +114,19 @@ function display_setup_form( $error = null ) { - - - '; - } else { - ?> - -

- - + + + + + + + + + + +

+ + @@ -179,28 +178,32 @@ function display_setup_form( $error = null ) {

- + - + -
- + > + />
- /> + /> -

+

- -

+ /> + +

@@ -470,17 +473,30 @@ function display_setup_form( $error = null ) { } if ( ! wp_is_mobile() ) { - ?> - - - diff --git a/src/wp-admin/nav-menus.php b/src/wp-admin/nav-menus.php index 9998852d06d82..6a9925b0d4708 100644 --- a/src/wp-admin/nav-menus.php +++ b/src/wp-admin/nav-menus.php @@ -196,7 +196,7 @@ // If this menu item is a child of the previous. if ( ! empty( $menu_item_data['menu_item_parent'] ) - && in_array( (int) $menu_item_data['menu_item_parent'], array_keys( $dbids_to_orders ), true ) + && isset( $dbids_to_orders[ (int) $menu_item_data['menu_item_parent'] ] ) && isset( $orders_to_dbids[ $dbids_to_orders[ $menu_item_id ] - 1 ] ) && ( (int) $menu_item_data['menu_item_parent'] === $orders_to_dbids[ $dbids_to_orders[ $menu_item_id ] - 1 ] ) ) { @@ -230,7 +230,7 @@ ) { $_possible_parent_id = (int) get_post_meta( $orders_to_dbids[ $dbids_to_orders[ $parent_db_id ] - 1 ], '_menu_item_menu_item_parent', true ); - if ( in_array( $_possible_parent_id, array_keys( $dbids_to_orders ), true ) ) { + if ( isset( $dbids_to_orders[ $_possible_parent_id ] ) ) { $menu_item_data['menu_item_parent'] = $_possible_parent_id; } else { $menu_item_data['menu_item_parent'] = 0; @@ -256,7 +256,7 @@ // Else this menu item is not a child of the previous. } elseif ( empty( $menu_item_data['menu_order'] ) || empty( $menu_item_data['menu_item_parent'] ) - || ! in_array( (int) $menu_item_data['menu_item_parent'], array_keys( $dbids_to_orders ), true ) + || ! isset( $dbids_to_orders[ (int) $menu_item_data['menu_item_parent'] ] ) || empty( $orders_to_dbids[ $dbids_to_orders[ $menu_item_id ] - 1 ] ) || $orders_to_dbids[ $dbids_to_orders[ $menu_item_id ] - 1 ] !== (int) $menu_item_data['menu_item_parent'] ) { diff --git a/src/wp-admin/options-connectors.php b/src/wp-admin/options-connectors.php index 7dc3b13508abe..ddad78f4f135f 100644 --- a/src/wp-admin/options-connectors.php +++ b/src/wp-admin/options-connectors.php @@ -20,36 +20,20 @@ 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 ); } // Set the page title. -$title = __( 'Connectors' ); -$js_required_message = __( 'The Connectors screen requires JavaScript. Please enable JavaScript in your browser settings to manage your connectors.' ); +$title = __( 'Connectors' ); // Set parent file for menu highlighting. $parent_file = 'options-general.php'; require_once ABSPATH . 'wp-admin/admin-header.php'; -?> -
-

- 'error', - 'additional_classes' => array( 'hide-if-js' ), - ) - ); - ?> -
-" data-choose-text="" data-update-text="" data-update="" - data-state="" + data-state="" > diff --git a/src/wp-admin/options-reading.php b/src/wp-admin/options-reading.php index d52d51bbe3ae4..8ea14a7178256 100644 --- a/src/wp-admin/options-reading.php +++ b/src/wp-admin/options-reading.php @@ -16,6 +16,8 @@ // Used in the HTML title tag. $title = __( 'Reading Settings' ); $parent_file = 'options-general.php'; +// Check whether the blog_privacy_selector action is in use, for later reuse. +$has_action_blog_privacy_selector = has_action( 'blog_privacy_selector' ); add_action( 'admin_head', 'options_reading_add_js' ); @@ -41,7 +43,7 @@ get_current_screen()->add_help_tab( array( 'id' => 'site-visibility', - 'title' => has_action( 'blog_privacy_selector' ) ? __( 'Site visibility' ) : __( 'Search engine visibility' ), + 'title' => $has_action_blog_privacy_selector ? __( 'Site visibility' ) : __( 'Search engine visibility' ), 'content' => '

' . __( 'You can choose whether or not your site will be crawled by robots, ping services, and spiders. If you want those services to ignore your site, click the checkbox next to “Discourage search engines from indexing this site” and click the Save Changes button at the bottom of the screen.' ) . '

' . '

' . __( 'Note that even when set to discourage search engines, your site is still visible on the web and not all search engines adhere to this directive.' ) . '

' . '

' . __( 'When this setting is in effect, a reminder is shown in the At a Glance box of the Dashboard that says, “Search engines discouraged”, to remind you that you have directed search engines to not crawl your site.' ) . '

', @@ -188,13 +190,13 @@ -
- -

-
- -

-

+

+ + /> +
+ /> + +

- + -

+> - + />
/> -

+

- -

+ /> + +

diff --git a/src/wp-admin/plugin-editor.php b/src/wp-admin/plugin-editor.php index 4beee7b8409da..b129a7652b28b 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 ); } } diff --git a/src/wp-admin/privacy.php b/src/wp-admin/privacy.php index 1445e5b1ec2b4..bbe6d5ddfc885 100644 --- a/src/wp-admin/privacy.php +++ b/src/wp-admin/privacy.php @@ -12,22 +12,11 @@ // Used in the HTML title tag. $title = __( 'Privacy' ); -list( $display_version ) = explode( '-', get_bloginfo( 'version' ) ); -$header_alt_text = sprintf( - /* translators: %s: Version number. */ - __( 'WordPress %s' ), - $display_version -); - require_once ABSPATH . 'wp-admin/admin-header.php'; ?>
-
- <?php echo esc_attr( $header_alt_text ); ?> -
-

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/user-edit.php b/src/wp-admin/user-edit.php index 5d45c63801bfe..8055de6b36385 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -931,7 +931,7 @@ * * @since 2.8.0 * - * @param bool $enable Whether to display the capabilities. Default true. + * @param bool $enable Whether to display the capabilities. Default true. * @param WP_User $profile_user The current WP_User object. */ $display_additional_caps = apply_filters( 'additional_capabilities_display', true, $profile_user ); diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index 3136705f60a03..453a0de54fa55 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -154,7 +154,7 @@ * * @since 5.6.0 * - * @param array $new_user_email { + * @param array $new_user_email { * Used to build wp_mail(). * * @type string $to The email address of the invited user. @@ -162,9 +162,9 @@ * @type string $message The content of the email. * @type string $headers Headers. * } - * @param int $user_id The invited user's ID. - * @param array $role Array containing role information for the invited user. - * @param string $newuser_key The key of the invitation. + * @param int $user_id The invited user's ID. + * @param array $role Array containing role information for the invited user. + * @param string $newuser_key The key of the invitation. * */ $new_user_email = apply_filters( 'invited_user_email', $new_user_email, $user_id, $role, $newuser_key ); diff --git a/src/wp-admin/users.php b/src/wp-admin/users.php index a94a9eff4a9cf..1a2177a21dbf7 100644 --- a/src/wp-admin/users.php +++ b/src/wp-admin/users.php @@ -339,6 +339,11 @@
    - + have_posts() ) : $tmp_content_width = $GLOBALS['content_width']; $GLOBALS['content_width'] = 306; + // The global is unset until a loop has run, so this may be reached before it exists. + $tmp_more = $GLOBALS['more'] ?? null; echo $args['before_widget']; ?> @@ -148,7 +150,6 @@ public function widget( $args, $instance ) { have_posts() ) : $ephemera->the_post(); - $tmp_more = $GLOBALS['more']; $GLOBALS['more'] = 0; ?>
  • diff --git a/src/wp-content/themes/twentyfourteen/readme.txt b/src/wp-content/themes/twentyfourteen/readme.txt index fbf080fe3e729..5dfa462763d84 100644 --- a/src/wp-content/themes/twentyfourteen/readme.txt +++ b/src/wp-content/themes/twentyfourteen/readme.txt @@ -1,9 +1,9 @@ === Twenty Fourteen === Contributors: wordpressdotorg Requires at least: 3.6 -Tested up to: 7.0 +Tested up to: 7.1 Requires PHP: 5.2.4 -Stable tag: 4.5 +Stable tag: 4.6 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Tags: blog, news, two-columns, three-columns, left-sidebar, right-sidebar, custom-background, custom-header, custom-menu, editor-style, featured-images, flexible-header, footer-widgets, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready, accessibility-ready, block-patterns @@ -60,6 +60,11 @@ Source: https://stocksnap.io/photo/fog-mountain-ZKN6UKFKEO == Changelog == += 4.6 = +* Released: August 19, 2026 + +https://wordpress.org/documentation/article/twenty-fourteen-changelog/#Version_4.6 + = 4.5 = * Released: May 20, 2026 diff --git a/src/wp-content/themes/twentyfourteen/style.css b/src/wp-content/themes/twentyfourteen/style.css index e742d4e3a75d7..9cede1ff688f3 100644 --- a/src/wp-content/themes/twentyfourteen/style.css +++ b/src/wp-content/themes/twentyfourteen/style.css @@ -4,9 +4,9 @@ Theme URI: https://wordpress.org/themes/twentyfourteen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: In 2014, our default theme lets you create a responsive magazine website with a sleek, modern design. Feature your favorite homepage content in either a grid or a slider. Use the three widget areas to customize your website, and change your content's layout with a full-width page template and a contributor page to show off your authors. Creating a magazine website with WordPress has never been easier. -Version: 4.5 +Version: 4.6 Requires at least: 3.6 -Tested up to: 7.0 +Tested up to: 7.1 Requires PHP: 5.2.4 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html diff --git a/src/wp-content/themes/twentynineteen/.nvmrc b/src/wp-content/themes/twentynineteen/.nvmrc new file mode 100644 index 0000000000000..209e3ef4b6247 --- /dev/null +++ b/src/wp-content/themes/twentynineteen/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/src/wp-content/themes/twentynineteen/images/pattern_01.jpg b/src/wp-content/themes/twentynineteen/images/pattern_01.jpg index e01b19df0ed10..bd98509fbffc0 100644 Binary files a/src/wp-content/themes/twentynineteen/images/pattern_01.jpg and b/src/wp-content/themes/twentynineteen/images/pattern_01.jpg differ diff --git a/src/wp-content/themes/twentynineteen/images/pattern_02.jpg b/src/wp-content/themes/twentynineteen/images/pattern_02.jpg index 56c7f70943244..ce406c749a457 100644 Binary files a/src/wp-content/themes/twentynineteen/images/pattern_02.jpg and b/src/wp-content/themes/twentynineteen/images/pattern_02.jpg differ diff --git a/src/wp-content/themes/twentynineteen/images/pattern_03.jpg b/src/wp-content/themes/twentynineteen/images/pattern_03.jpg index bd69d37a29112..a97d35b6585cb 100644 Binary files a/src/wp-content/themes/twentynineteen/images/pattern_03.jpg and b/src/wp-content/themes/twentynineteen/images/pattern_03.jpg differ diff --git a/src/wp-content/themes/twentynineteen/images/pattern_04.jpg b/src/wp-content/themes/twentynineteen/images/pattern_04.jpg index b7419fe4f4be2..77e956091dab8 100644 Binary files a/src/wp-content/themes/twentynineteen/images/pattern_04.jpg and b/src/wp-content/themes/twentynineteen/images/pattern_04.jpg differ diff --git a/src/wp-content/themes/twentynineteen/inc/template-tags.php b/src/wp-content/themes/twentynineteen/inc/template-tags.php index 63e9f78e1b505..99bb2b8602553 100644 --- a/src/wp-content/themes/twentynineteen/inc/template-tags.php +++ b/src/wp-content/themes/twentynineteen/inc/template-tags.php @@ -170,6 +170,11 @@ function twentynineteen_post_thumbnail() { if ( ! function_exists( 'twentynineteen_get_user_avatar_markup' ) ) : /** * Returns the HTML markup to generate a user avatar. + * + * @param mixed $id_or_email Optional. The avatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * Default null, which uses the current user ID. + * @return string HTML markup for the user avatar. */ function twentynineteen_get_user_avatar_markup( $id_or_email = null ) { @@ -184,6 +189,9 @@ function twentynineteen_get_user_avatar_markup( $id_or_email = null ) { if ( ! function_exists( 'twentynineteen_discussion_avatars_list' ) ) : /** * Displays a list of avatars involved in a discussion for a given post. + * + * @param array $comment_authors Comment authors to display avatars for. Each entry is a user ID, + * or an email address for authors without an account. */ function twentynineteen_discussion_avatars_list( $comment_authors ) { if ( empty( $comment_authors ) ) { @@ -203,13 +211,17 @@ function twentynineteen_discussion_avatars_list( $comment_authors ) { if ( ! function_exists( 'twentynineteen_comment_form' ) ) : /** * Displays the comment form. + * + * @param bool|string $order Whether to display the form. Accepts 'asc' or 'desc' to display it only + * when the value matches the 'comment_order' option, or true to always + * display it. */ function twentynineteen_comment_form( $order ) { if ( true === $order || strtolower( $order ) === strtolower( get_option( 'comment_order', 'asc' ) ) ) { comment_form( array( - 'title_reply' => null, + 'title_reply' => '', ) ); } diff --git a/src/wp-content/themes/twentynineteen/package-lock.json b/src/wp-content/themes/twentynineteen/package-lock.json index e573413168e38..347fd52915112 100644 --- a/src/wp-content/themes/twentynineteen/package-lock.json +++ b/src/wp-content/themes/twentynineteen/package-lock.json @@ -1,12 +1,12 @@ { "name": "twentynineteen", - "version": "3.3.0", + "version": "3.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "twentynineteen", - "version": "3.3.0", + "version": "3.4.0", "devDependencies": { "@wordpress/browserslist-config": "^6.34.0", "autoprefixer": "^10.4.22", diff --git a/src/wp-content/themes/twentynineteen/package.json b/src/wp-content/themes/twentynineteen/package.json index 36db278d2ca76..36b01c71a079c 100644 --- a/src/wp-content/themes/twentynineteen/package.json +++ b/src/wp-content/themes/twentynineteen/package.json @@ -1,6 +1,6 @@ { "name": "twentynineteen", - "version": "3.3.0", + "version": "3.4.0", "description": "Default WP Theme", "bugs": { "url": "https://core.trac.wordpress.org/" diff --git a/src/wp-content/themes/twentynineteen/readme.txt b/src/wp-content/themes/twentynineteen/readme.txt index a135531f9ee85..4bd3d1f9dc1ee 100644 --- a/src/wp-content/themes/twentynineteen/readme.txt +++ b/src/wp-content/themes/twentynineteen/readme.txt @@ -2,9 +2,9 @@ Contributors: wordpressdotorg Tags: one-column, accessibility-ready, custom-colors, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, rtl-language-support, sticky-post, threaded-comments, translation-ready, block-patterns Requires at least: 4.7 -Tested up to: 7.0 +Tested up to: 7.1 Requires PHP: 5.2.4 -Stable tag: 3.3 +Stable tag: 3.4 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -40,6 +40,11 @@ GNU General Public License for more details. == Changelog == += 3.4 = +* Released: August 19, 2026 + +https://wordpress.org/documentation/article/twenty-nineteen-changelog/#Version_3.4 + = 3.3 = * Released: May 20, 2026 diff --git a/src/wp-content/themes/twentynineteen/screenshot.png b/src/wp-content/themes/twentynineteen/screenshot.png index fa27e95463571..b965e8509669c 100644 Binary files a/src/wp-content/themes/twentynineteen/screenshot.png and b/src/wp-content/themes/twentynineteen/screenshot.png differ diff --git a/src/wp-content/themes/twentynineteen/style-rtl.css b/src/wp-content/themes/twentynineteen/style-rtl.css index 7fa379ed02370..017abd64e1dbc 100644 --- a/src/wp-content/themes/twentynineteen/style-rtl.css +++ b/src/wp-content/themes/twentynineteen/style-rtl.css @@ -5,10 +5,10 @@ Theme URI: https://wordpress.org/themes/twentynineteen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: Our 2019 default theme is designed to show off the power of the block editor. It features custom styles for all the default blocks, and is built so that what you see in the editor looks like what you'll see on your website. Twenty Nineteen is designed to be adaptable to a wide range of websites, whether you’re running a photo blog, launching a new business, or supporting a non-profit. Featuring ample whitespace and modern sans-serif headlines paired with classic serif body text, it's built to be beautiful on all screen sizes. -Tested up to: 7.0 +Tested up to: 7.1 Requires at least: 4.7 Requires PHP: 5.2.4 -Version: 3.3 +Version: 3.4 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: twentynineteen diff --git a/src/wp-content/themes/twentynineteen/style.css b/src/wp-content/themes/twentynineteen/style.css index 07abd805b7718..560d7923297fe 100644 --- a/src/wp-content/themes/twentynineteen/style.css +++ b/src/wp-content/themes/twentynineteen/style.css @@ -5,10 +5,10 @@ Theme URI: https://wordpress.org/themes/twentynineteen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: Our 2019 default theme is designed to show off the power of the block editor. It features custom styles for all the default blocks, and is built so that what you see in the editor looks like what you'll see on your website. Twenty Nineteen is designed to be adaptable to a wide range of websites, whether you’re running a photo blog, launching a new business, or supporting a non-profit. Featuring ample whitespace and modern sans-serif headlines paired with classic serif body text, it's built to be beautiful on all screen sizes. -Tested up to: 7.0 +Tested up to: 7.1 Requires at least: 4.7 Requires PHP: 5.2.4 -Version: 3.3 +Version: 3.4 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: twentynineteen diff --git a/src/wp-content/themes/twentynineteen/style.scss b/src/wp-content/themes/twentynineteen/style.scss index 699ce75c1fd47..e160aadc3d045 100644 --- a/src/wp-content/themes/twentynineteen/style.scss +++ b/src/wp-content/themes/twentynineteen/style.scss @@ -4,10 +4,10 @@ Theme URI: https://wordpress.org/themes/twentynineteen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: Our 2019 default theme is designed to show off the power of the block editor. It features custom styles for all the default blocks, and is built so that what you see in the editor looks like what you'll see on your website. Twenty Nineteen is designed to be adaptable to a wide range of websites, whether you’re running a photo blog, launching a new business, or supporting a non-profit. Featuring ample whitespace and modern sans-serif headlines paired with classic serif body text, it's built to be beautiful on all screen sizes. -Tested up to: 7.0 +Tested up to: 7.1 Requires at least: 4.7 Requires PHP: 5.2.4 -Version: 3.3 +Version: 3.4 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: twentynineteen diff --git a/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg b/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg index 145d1f7116484..285ff1d527033 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/direct-light.jpg b/src/wp-content/themes/twentyseventeen/assets/images/direct-light.jpg index 8f3d814c57b19..6fec4604cbf2d 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/direct-light.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/direct-light.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg b/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg index a3bd2c6dc0049..613bb27a92da8 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/header.jpg b/src/wp-content/themes/twentyseventeen/assets/images/header.jpg index ef2c07aff98eb..f386a9678996c 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/header.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/header.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg b/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg index cf81066b2eebc..6594ec2cc1e46 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/stripes.jpg b/src/wp-content/themes/twentyseventeen/assets/images/stripes.jpg index 2e0920ff7e257..2ac342490a1d4 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/stripes.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/stripes.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/assets/images/white-border.jpg b/src/wp-content/themes/twentyseventeen/assets/images/white-border.jpg index 40773b14bd028..5897e2d0a1662 100644 Binary files a/src/wp-content/themes/twentyseventeen/assets/images/white-border.jpg and b/src/wp-content/themes/twentyseventeen/assets/images/white-border.jpg differ diff --git a/src/wp-content/themes/twentyseventeen/functions.php b/src/wp-content/themes/twentyseventeen/functions.php index 1f3d347f971f9..e693c0fe16f8e 100644 --- a/src/wp-content/themes/twentyseventeen/functions.php +++ b/src/wp-content/themes/twentyseventeen/functions.php @@ -467,7 +467,7 @@ function twentyseventeen_scripts() { wp_enqueue_style( 'twentyseventeen-fonts', twentyseventeen_fonts_url(), array(), $font_version ); // Theme stylesheet. - wp_enqueue_style( 'twentyseventeen-style', get_stylesheet_uri(), array(), '20260520' ); + wp_enqueue_style( 'twentyseventeen-style', get_stylesheet_uri(), array(), '20260819' ); // Theme block stylesheet. wp_enqueue_style( 'twentyseventeen-block-style', get_theme_file_uri( '/assets/css/blocks.css' ), array( 'twentyseventeen-style' ), '20240729' ); diff --git a/src/wp-content/themes/twentyseventeen/readme.txt b/src/wp-content/themes/twentyseventeen/readme.txt index b7ee61dc1df8c..f83048242adf4 100644 --- a/src/wp-content/themes/twentyseventeen/readme.txt +++ b/src/wp-content/themes/twentyseventeen/readme.txt @@ -1,9 +1,9 @@ === Twenty Seventeen === Contributors: wordpressdotorg Requires at least: 4.7 -Tested up to: 7.0 +Tested up to: 7.1 Requires PHP: 5.2.4 -Version: 4.1 +Version: 4.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Tags: one-column, two-columns, right-sidebar, flexible-header, accessibility-ready, custom-colors, custom-header, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready, block-patterns @@ -71,6 +71,11 @@ Source: https://stocksnap.io/photo/striped-fabric-9CBVWF2CDU == Changelog == += 4.2 = +* Released: August 19, 2026 + +https://wordpress.org/documentation/article/twenty-seventeen-changelog/#Version_4.2 + = 4.1 = * Released: May 20, 2026 diff --git a/src/wp-content/themes/twentyseventeen/screenshot.png b/src/wp-content/themes/twentyseventeen/screenshot.png index 25f1f9bf92557..a154c54cdb82d 100644 Binary files a/src/wp-content/themes/twentyseventeen/screenshot.png and b/src/wp-content/themes/twentyseventeen/screenshot.png differ diff --git a/src/wp-content/themes/twentyseventeen/style.css b/src/wp-content/themes/twentyseventeen/style.css index cd0bb51f124c0..52a44d117071f 100644 --- a/src/wp-content/themes/twentyseventeen/style.css +++ b/src/wp-content/themes/twentyseventeen/style.css @@ -4,8 +4,8 @@ Theme URI: https://wordpress.org/themes/twentyseventeen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: Twenty Seventeen brings your site to life with header video and immersive featured images. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device. -Version: 4.1 -Tested up to: 7.0 +Version: 4.2 +Tested up to: 7.1 Requires at least: 4.7 Requires PHP: 5.2.4 License: GNU General Public License v2 or later diff --git a/src/wp-content/themes/twentysixteen/functions.php b/src/wp-content/themes/twentysixteen/functions.php index 50c3a14c753e0..72bfab48f0d21 100644 --- a/src/wp-content/themes/twentysixteen/functions.php +++ b/src/wp-content/themes/twentysixteen/functions.php @@ -409,7 +409,7 @@ function twentysixteen_scripts() { wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '20251101' ); // Theme stylesheet. - wp_enqueue_style( 'twentysixteen-style', get_stylesheet_uri(), array(), '20260520' ); + wp_enqueue_style( 'twentysixteen-style', get_stylesheet_uri(), array(), '20260819' ); // Theme block stylesheet. wp_enqueue_style( 'twentysixteen-block-style', get_template_directory_uri() . '/css/blocks.css', array( 'twentysixteen-style' ), '20260105' ); @@ -458,7 +458,7 @@ function twentysixteen_scripts() { */ function twentysixteen_block_editor_styles() { // Block styles. - wp_enqueue_style( 'twentysixteen-block-editor-style', get_template_directory_uri() . '/css/editor-blocks.css', array(), '20260105' ); + wp_enqueue_style( 'twentysixteen-block-editor-style', get_template_directory_uri() . '/css/editor-blocks.css', array(), '20260530' ); // Add custom fonts. $font_version = ( 0 === strpos( (string) twentysixteen_fonts_url(), get_template_directory_uri() . '/' ) ) ? '20230328' : null; wp_enqueue_style( 'twentysixteen-fonts', twentysixteen_fonts_url(), array(), $font_version ); diff --git a/src/wp-content/themes/twentysixteen/readme.txt b/src/wp-content/themes/twentysixteen/readme.txt index 6b11b572a1189..ad93bd43f9266 100644 --- a/src/wp-content/themes/twentysixteen/readme.txt +++ b/src/wp-content/themes/twentysixteen/readme.txt @@ -1,9 +1,9 @@ === Twenty Sixteen === Contributors: wordpressdotorg Requires at least: 4.4 -Tested up to: 7.0 +Tested up to: 7.1 Requires PHP: 5.2.4 -Version: 3.8 +Version: 3.9 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Tags: one-column, two-columns, right-sidebar, accessibility-ready, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-images, flexible-header, microformats, post-formats, rtl-language-support, sticky-post, threaded-comments, translation-ready, blog, block-patterns @@ -68,6 +68,11 @@ Image used in screenshot.png: A photo by Austin Schmid (https://unsplash.com/sch == Changelog == += 3.9 = +* Released: August 19, 2026 + +https://wordpress.org/documentation/article/twenty-sixteen-changelog/#Version_3.9 + = 3.8 = * Released: May 20, 2026 diff --git a/src/wp-content/themes/twentysixteen/style.css b/src/wp-content/themes/twentysixteen/style.css index f2df1eddb0afe..23c11e1da8e9c 100644 --- a/src/wp-content/themes/twentysixteen/style.css +++ b/src/wp-content/themes/twentysixteen/style.css @@ -4,8 +4,8 @@ Theme URI: https://wordpress.org/themes/twentysixteen/ Author: the WordPress team Author URI: https://wordpress.org/ Description: Twenty Sixteen is a modernized take on an ever-popular WordPress layout — the horizontal masthead with an optional right sidebar that works perfectly for blogs and websites. It has custom color options with beautiful default color schemes, a harmonious fluid grid using a mobile-first approach, and impeccable polish in every detail. Twenty Sixteen will make your WordPress look beautiful everywhere. -Version: 3.8 -Tested up to: 7.0 +Version: 3.9 +Tested up to: 7.1 Requires at least: 4.4 Requires PHP: 5.2.4 License: GNU General Public License v2 or later diff --git a/src/wp-content/themes/twentyten/header.php b/src/wp-content/themes/twentyten/header.php index 02648fb8364a8..3758f0ed0b564 100644 --- a/src/wp-content/themes/twentyten/header.php +++ b/src/wp-content/themes/twentyten/header.php @@ -42,7 +42,7 @@ ?> - + -

-