diff --git a/.eslintrc.js b/.eslintrc.js
index c38d6646522a30..9d0776c1730c69 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -105,6 +105,7 @@ module.exports = {
'flatMap',
'flatten',
'flattenDeep',
+ 'flow',
'flowRight',
'forEach',
'fromPairs',
@@ -151,6 +152,7 @@ module.exports = {
'sum',
'sumBy',
'take',
+ 'throttle',
'times',
'toString',
'trim',
@@ -162,7 +164,6 @@ module.exports = {
'uniqWith',
'upperFirst',
'values',
- 'words',
'xor',
'zip',
],
@@ -355,7 +356,7 @@ module.exports = {
},
},
{
- files: [ 'bin/**/*.js', 'packages/env/**' ],
+ files: [ 'bin/**/*.js', 'bin/**/*.mjs', 'packages/env/**' ],
rules: {
'no-console': 'off',
},
diff --git a/bin/api-docs/gen-block-lib-list.js b/bin/api-docs/gen-block-lib-list.js
index 969ed2617fc0ab..60b0a99b096ab8 100644
--- a/bin/api-docs/gen-block-lib-list.js
+++ b/bin/api-docs/gen-block-lib-list.js
@@ -1,7 +1,7 @@
/**
* Generates core block documentation using block.json files.
* Reads from : packages/block-library/src
- * Publishes to: docs/reference-guides/core-blocks.ms
+ * Publishes to: docs/reference-guides/core-blocks.md
*/
/**
diff --git a/bin/api-docs/gen-theme-reference.js b/bin/api-docs/gen-theme-reference.js
index 8a6633bf878a8c..d051261963daf4 100644
--- a/bin/api-docs/gen-theme-reference.js
+++ b/bin/api-docs/gen-theme-reference.js
@@ -1,7 +1,7 @@
/**
- * Generates core block documentation using block.json files.
- * Reads from : packages/block-library/src
- * Publishes to: docs/reference-guides/core-blocks.ms
+ * Generates theme.json documentation using theme.json schema.
+ * Reads from : schemas/json/theme.json
+ * Publishes to: docs/reference-guides/theme-json-reference/theme-json-living.md
*/
/**
diff --git a/bin/cherry-pick.mjs b/bin/cherry-pick.mjs
index 0bf1d7926b5bdb..8d1da80b316d53 100644
--- a/bin/cherry-pick.mjs
+++ b/bin/cherry-pick.mjs
@@ -6,11 +6,10 @@ import readline from 'readline';
import { spawnSync } from 'node:child_process';
-const LABEL = process.argv[2] || "Backport to WP Minor Release";
+const LABEL = process.argv[ 2 ] || 'Backport to WP Minor Release';
const BRANCH = getCurrentBranch();
-const GITHUB_CLI_AVAILABLE = spawnSync( 'gh', ['auth', 'status'] )
- ?.stderr
- ?.toString()
+const GITHUB_CLI_AVAILABLE = spawnSync( 'gh', [ 'auth', 'status' ] )
+ ?.stderr?.toString()
.includes( '✓ Logged in to github.com as' );
const AUTO_PROPAGATE_RESULTS_TO_GITHUB = GITHUB_CLI_AVAILABLE;
@@ -28,30 +27,34 @@ const AUTO_PROPAGATE_RESULTS_TO_GITHUB = GITHUB_CLI_AVAILABLE;
* * Reports the results
*/
async function main() {
- if ( !GITHUB_CLI_AVAILABLE ) {
+ if ( ! GITHUB_CLI_AVAILABLE ) {
await reportGhUnavailable();
}
- console.log( `You are on branch "${BRANCH}".` );
+ console.log( `You are on branch "${ BRANCH }".` );
console.log( `This script will:` );
- console.log( `• Cherry-pick the merged PRs labeled as "${LABEL}" to this branch` );
+ console.log(
+ `• Cherry-pick the merged PRs labeled as "${ LABEL }" to this branch`
+ );
console.log( `• Ask whether you want to push this branch` );
console.log( `• Comment on each PR` );
console.log( `• Remove the label from each PR` );
- console.log( `The last two actions will be performed USING YOUR GITHUB ACCOUNT that` )
- console.log( `you've linked to your GitHub CLI (gh command)` )
+ console.log(
+ `The last two actions will be performed USING YOUR GITHUB ACCOUNT that`
+ );
+ console.log( `you've linked to your GitHub CLI (gh command)` );
console.log( `` );
await promptDoYouWantToProceed();
console.log( `$ git pull origin ${ BRANCH } --rebase...` );
- cli( 'git', ['pull', 'origin', BRANCH, '--rebase'], true );
+ cli( 'git', [ 'pull', 'origin', BRANCH, '--rebase' ], true );
console.log( `$ git fetch origin trunk...` );
- cli( 'git', ['fetch', 'origin', 'trunk'], true );
+ cli( 'git', [ 'fetch', 'origin', 'trunk' ], true );
const PRs = await fetchPRs();
console.log( 'Trying to cherry-pick one by one...' );
- const [successes, failures] = cherryPickAll( PRs );
+ const [ successes, failures ] = cherryPickAll( PRs );
console.log( 'Cherry-picking finished!' );
reportSummaryNextSteps( successes, failures );
@@ -60,17 +63,17 @@ async function main() {
if ( AUTO_PROPAGATE_RESULTS_TO_GITHUB ) {
console.log( `About to push to origin/${ BRANCH }` );
await promptDoYouWantToProceed();
- cli( 'git', ['push', 'origin', BRANCH] );
+ cli( 'git', [ 'push', 'origin', BRANCH ] );
console.log( `Commenting and removing labels...` );
successes.forEach( GHcommentAndRemoveLabel );
} else {
- console.log( "Cherry-picked PRs with copy-able comments:" );
+ console.log( 'Cherry-picked PRs with copy-able comments:' );
successes.forEach( reportSuccessManual );
}
}
if ( failures.length ) {
- console.log( "PRs that could not be cherry-picked automatically:" );
+ console.log( 'PRs that could not be cherry-picked automatically:' );
failures.forEach( reportFailure );
}
console.log( `Done!` );
@@ -79,9 +82,9 @@ async function main() {
/**
* Synchronously executes a CLI command and returns the result or throws an error on failure.
*
- * @param {string} command A command to execute.
- * @param {string[]} args CLI args.
- * @param {boolean} pipe If true, pipes the output to this process's stdout and stderr.
+ * @param {string} command A command to execute.
+ * @param {string[]} args CLI args.
+ * @param {boolean} pipe If true, pipes the output to this process's stdout and stderr.
* @return {string} Command's output.
*/
function cli( command, args, pipe = false ) {
@@ -91,7 +94,11 @@ function cli( command, args, pipe = false ) {
stdio: 'pipe',
encoding: 'utf-8',
};
- const result = spawnSync( command, args, ...( pipe ? [ pipeOptions ] : [] ) );
+ const result = spawnSync(
+ command,
+ args,
+ ...( pipe ? [ pipeOptions ] : [] )
+ );
if ( result.status !== 0 ) {
throw new Error( result.stderr?.toString()?.trim() );
}
@@ -105,30 +112,39 @@ function cli( command, args, pipe = false ) {
*/
async function fetchPRs() {
const { items } = await GitHubFetch(
- `/search/issues?q=is:pr state:closed sort:updated label:"${ LABEL }" repo:WordPress/gutenberg`,
+ `/search/issues?q=is:pr state:closed sort:updated label:"${ LABEL }" repo:WordPress/gutenberg`
);
- const PRs = items.map( ( { id, number, title } ) => ( { id, number, title } ) );
+ const PRs = items.map( ( { id, number, title } ) => ( {
+ id,
+ number,
+ title,
+ } ) );
console.log( 'Found the following PRs to cherry-pick: ' );
- PRs.forEach( ( { number, title } ) => console.log( indent( `#${ number } – ${ title }` ) ) );
+ PRs.forEach( ( { number, title } ) =>
+ console.log( indent( `#${ number } – ${ title }` ) )
+ );
console.log( 'Fetching commit IDs...' );
const PRsWithMergeCommit = [];
for ( const PR of PRs ) {
- const { merge_commit_sha } = await GitHubFetch(
- '/repos/WordPress/Gutenberg/pulls/' + PR.number,
+ const { mergeCommitHash } = await GitHubFetch(
+ '/repos/WordPress/Gutenberg/pulls/' + PR.number
);
PRsWithMergeCommit.push( {
...PR,
- mergeCommitHash: merge_commit_sha,
+ mergeCommitHash,
} );
- if ( !merge_commit_sha ) {
- throw new Error( `Cannot fetch the merge commit sha for ${ prToString( PR ) }` );
+ if ( ! mergeCommitHash ) {
+ throw new Error(
+ `Cannot fetch the merge commit sha for ${ prToString( PR ) }`
+ );
}
}
console.log( 'Done!' );
- PRsWithMergeCommit
- .forEach( ( msg ) => console.log( indent( `${ prToString( msg ) }` ) ) );
+ PRsWithMergeCommit.forEach( ( msg ) =>
+ console.log( indent( `${ prToString( msg ) }` ) )
+ );
return PRsWithMergeCommit;
}
@@ -139,14 +155,11 @@ async function fetchPRs() {
* @return {Promise} Parsed response JSON.
*/
async function GitHubFetch( path ) {
- const response = await fetch(
- 'https://api.github.com' + path,
- {
- headers: {
- Accept: 'application/vnd.github.v3+json',
- },
+ const response = await fetch( 'https://api.github.com' + path, {
+ headers: {
+ Accept: 'application/vnd.github.v3+json',
},
- );
+ } );
return await response.json();
}
@@ -160,20 +173,22 @@ async function GitHubFetch( path ) {
* @return {Array} A two-tuple containing a list of successful cherry-picks and a list of failed ones.
*/
function cherryPickAll( PRs ) {
- let remainingPRs = [...PRs];
+ let remainingPRs = [ ...PRs ];
let i = 1;
let allSuccesses = [];
while ( remainingPRs.length ) {
- console.log( `Cherry-picking round ${ i ++ }: ` );
- const [successes, failures] = cherryPickRound( remainingPRs );
- allSuccesses = [...allSuccesses, ...successes];
+ console.log( `Cherry-picking round ${ i++ }: ` );
+ const [ successes, failures ] = cherryPickRound( remainingPRs );
+ allSuccesses = [ ...allSuccesses, ...successes ];
remainingPRs = failures;
- if ( !successes.length ) {
- console.log( 'Nothing merged cleanly in the last round, breaking.' );
+ if ( ! successes.length ) {
+ console.log(
+ 'Nothing merged cleanly in the last round, breaking.'
+ );
break;
}
}
- return [allSuccesses, remainingPRs];
+ return [ allSuccesses, remainingPRs ];
}
/**
@@ -185,7 +200,7 @@ function cherryPickAll( PRs ) {
* @return {Array} A two-tuple containing a list of successful cherry-picks and a list of failed ones.
*/
function cherryPickRound( PRs ) {
- const stack = [...PRs];
+ const stack = [ ...PRs ];
const successes = [];
const failures = [];
while ( stack.length ) {
@@ -198,7 +213,12 @@ function cherryPickRound( PRs ) {
} );
console.log(
indent(
- `✅ cherry-pick commit: ${ cherryPickHash } for PR: ${ prToString( PR, false ) }` ) );
+ `✅ cherry-pick commit: ${ cherryPickHash } for PR: ${ prToString(
+ PR,
+ false
+ ) }`
+ )
+ );
} catch ( e ) {
failures.push( {
...PR,
@@ -207,7 +227,7 @@ function cherryPickRound( PRs ) {
console.log( indent( `❌ ${ prToString( PR ) }` ) );
}
}
- return [successes, failures];
+ return [ successes, failures ];
}
/**
@@ -216,48 +236,64 @@ function cherryPickRound( PRs ) {
* @param {*} x Input.
* @return {*} Input
*/
-const identity = x => x;
+const identity = ( x ) => x;
/**
* Formats a PR object in a human readable way.
*
- * @param {Object} PR PR details.
+ * @param {Object} PR PR details.
+ * @param {number} PR.number
+ * @param {string} PR.mergeCommitHash
+ * @param {string} PR.title
* @param {boolean} withMergeCommitHash Should include the commit hash in the output?
* @return {string} Formatted text
*/
-function prToString( { number, mergeCommitHash, title }, withMergeCommitHash = true ) {
+function prToString(
+ { number, mergeCommitHash, title },
+ withMergeCommitHash = true
+) {
return [
`#${ number }`,
withMergeCommitHash ? mergeCommitHash?.substr( 0, 20 ) : '',
`${ title?.substr( 0, 30 ) }${ title?.length > 30 ? '...' : '' }`,
- ].filter( identity ).join( ' – ' );
+ ]
+ .filter( identity )
+ .join( ' – ' );
}
/**
* Indents a block of text with {width} spaces
*
- * @param {string} text The text to indent.
+ * @param {string} text The text to indent.
* @param {number} width Number of spaces to use.
* @return {string} Indented text.
*/
function indent( text, width = 3 ) {
- const indent = ' '.repeat( width );
- return text.split( "\n" ).map( line => indent + line ).join( "\n" );
+ const _indent = ' '.repeat( width );
+ return text
+ .split( '\n' )
+ .map( ( line ) => _indent + line )
+ .join( '\n' );
}
/**
* Attempts to cherry-pick a given commit into the current branch,
*
+ * @param {string} commit A commit hash.
* @return {string} Branch name.
*/
function cherryPickOne( commit ) {
- const result = spawnSync( 'git', ['cherry-pick', commit] );
+ const result = spawnSync( 'git', [ 'cherry-pick', commit ] );
const message = result.stdout.toString().trim();
- if ( result.status !== 0 || !message.includes( 'Author: ' ) ) {
- spawnSync( 'git', ['reset', '--hard'] );
+ if ( result.status !== 0 || ! message.includes( 'Author: ' ) ) {
+ spawnSync( 'git', [ 'reset', '--hard' ] );
throw new Error( result.stderr.toString().trim() );
}
- const commitHashOutput = spawnSync( 'git', ['rev-parse', '--short', 'HEAD'] );
+ const commitHashOutput = spawnSync( 'git', [
+ 'rev-parse',
+ '--short',
+ 'HEAD',
+ ] );
return commitHashOutput.stdout.toString().trim();
}
@@ -266,17 +302,24 @@ function cherryPickOne( commit ) {
* and informs about the next steps to take.
*
* @param {Array} successes Successful cherry-picks.
- * @param {Array} failures Failed cherry-picks.
+ * @param {Array} failures Failed cherry-picks.
*/
function reportSummaryNextSteps( successes, failures ) {
console.log( 'Summary:' );
- console.log( indent( `✅ ${ successes.length } PRs got cherry-picked cleanly` ) );
console.log(
- indent( `${ failures.length > 0 ? '❌' : '✅' } ${ failures.length } PRs failed` ) );
+ indent( `✅ ${ successes.length } PRs got cherry-picked cleanly` )
+ );
+ console.log(
+ indent(
+ `${ failures.length > 0 ? '❌' : '✅' } ${
+ failures.length
+ } PRs failed`
+ )
+ );
console.log( '' );
const nextSteps = [];
- if ( successes.length && !AUTO_PROPAGATE_RESULTS_TO_GITHUB ) {
+ if ( successes.length && ! AUTO_PROPAGATE_RESULTS_TO_GITHUB ) {
nextSteps.push( 'Push this branch' );
nextSteps.push( 'Go to each of the cherry-picked Pull Requests' );
nextSteps.push( `Remove the ${ LABEL } label` );
@@ -287,8 +330,8 @@ function reportSummaryNextSteps( successes, failures ) {
nextSteps.push( 'Manually cherry-pick the PRs that failed' );
}
if ( nextSteps.length ) {
- console.log( "Next steps:" );
- for ( let i = 0; i < nextSteps.length; i ++ ) {
+ console.log( 'Next steps:' );
+ for ( let i = 0; i < nextSteps.length; i++ ) {
console.log( indent( `${ i + 1 }. ${ nextSteps[ i ] }` ) );
}
console.log( '' );
@@ -307,8 +350,8 @@ function GHcommentAndRemoveLabel( pr ) {
const { number, cherryPickHash } = pr;
const comment = prComment( cherryPickHash );
try {
- cli( 'gh', ['pr', 'comment', number, '--body', comment] );
- cli( 'gh', ['pr', 'edit', number, '--remove-label', LABEL] );
+ cli( 'gh', [ 'pr', 'comment', number, '--body', comment ] );
+ cli( 'gh', [ 'pr', 'edit', number, '--remove-label', LABEL ] );
console.log( `✅ ${ number }: ${ comment }` );
} catch ( e ) {
console.log( `❌ ${ number }. ${ comment } ` );
@@ -322,7 +365,10 @@ function GHcommentAndRemoveLabel( pr ) {
/**
* When cherry-pick succeeds, this function outputs the manual next steps to take.
*
- * @param {Object} PR PR details.
+ * @param {Object} PR PR details.
+ * @param {number} PR.number
+ * @param {string} PR.title
+ * @param {string} PR.cherryPickHash
*/
function reportSuccessManual( { number, title, cherryPickHash } ) {
console.log( indent( prUrl( number ) ) );
@@ -334,7 +380,11 @@ function reportSuccessManual( { number, title, cherryPickHash } ) {
/**
* When cherry-pick fails, this function outputs the details.
*
- * @param {Object} PR PR details.
+ * @param {Object} PR PR details.
+ * @param {number} PR.number
+ * @param {string} PR.title
+ * @param {string} PR.error
+ * @param {string} PR.mergeCommitHash
*/
function reportFailure( { number, title, error, mergeCommitHash } ) {
console.log( indent( prUrl( number ) ) );
@@ -348,6 +398,7 @@ function reportFailure( { number, title, error, mergeCommitHash } ) {
/**
* Returns the URL of the Gutenberg PR given its number.
*
+ * @param {number} number
* @return {string} PR URL.
*/
function prUrl( number ) {
@@ -371,7 +422,9 @@ function prComment( cherryPickHash ) {
* @return {string} Branch name.
*/
function getCurrentBranch() {
- return spawnSync( 'git', ['rev-parse', '--abbrev-ref', 'HEAD'] ).stdout.toString().trim();
+ return spawnSync( 'git', [ 'rev-parse', '--abbrev-ref', 'HEAD' ] )
+ .stdout.toString()
+ .trim();
}
/**
@@ -381,12 +434,19 @@ function getCurrentBranch() {
* @return {Promise}
*/
async function reportGhUnavailable() {
- console.log( 'Github CLI is not setup. This script will not be able to automatically' );
- console.log( 'comment on the processed PRs and remove the backport label from them.' );
- console.log( 'Instead, you will see a detailed list of next steps to perform manually.' );
+ console.log(
+ 'Github CLI is not setup. This script will not be able to automatically'
+ );
+ console.log(
+ 'comment on the processed PRs and remove the backport label from them.'
+ );
+ console.log(
+ 'Instead, you will see a detailed list of next steps to perform manually.'
+ );
console.log( '' );
console.log(
- 'To enable automatic handling, install the `gh` utility from https://cli.github.com/' );
+ 'To enable automatic handling, install the `gh` utility from https://cli.github.com/'
+ );
console.log( '' );
await promptDoYouWantToProceed();
}
@@ -403,10 +463,11 @@ async function promptDoYouWantToProceed() {
output: process.stdout,
} );
- const question = ( prompt ) => new Promise( ( resolve ) => rl.question( prompt, resolve ) );
+ const question = ( prompt ) =>
+ new Promise( ( resolve ) => rl.question( prompt, resolve ) );
do {
const answer = await question( 'Do you want to proceed? (Y/n)' );
- if ( !answer || answer === 'Y' ) {
+ if ( ! answer || answer === 'Y' ) {
break;
}
if ( answer === 'n' ) {
diff --git a/bin/plugin/commands/changelog.js b/bin/plugin/commands/changelog.js
index 7c8ad778d3cbf4..e6fb8c7054b16e 100644
--- a/bin/plugin/commands/changelog.js
+++ b/bin/plugin/commands/changelog.js
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-const { groupBy, flow } = require( 'lodash' );
+const { groupBy } = require( 'lodash' );
const Octokit = require( '@octokit/rest' );
const { sprintf } = require( 'sprintf-js' );
const semver = require( 'semver' );
@@ -185,6 +185,21 @@ const REWORD_TERMS = {
docs: 'documentation',
};
+/**
+ * Creates a pipe function. Performs left-to-right function composition, where
+ * each successive invocation is supplied the return value of the previous.
+ *
+ * @param {Function[]} functions Functions to pipe.
+ */
+function pipe( functions ) {
+ return ( /** @type {unknown[]} */ ...args ) => {
+ return functions.reduce(
+ ( prev, func ) => [ func( ...prev ) ],
+ args
+ )[ 0 ];
+ };
+}
+
/**
* Escapes the RegExp special characters.
*
@@ -880,7 +895,7 @@ function skipCreatedByBots( pullRequests ) {
* @return {string} The formatted props section.
*/
function getContributorProps( pullRequests ) {
- const contributorsList = flow( [
+ const contributorsList = pipe( [
skipCreatedByBots,
getFirstTimeContributorPRs,
getUniqueByUsername,
@@ -920,7 +935,7 @@ function getContributorsMarkdownList( pullRequests ) {
* @return {string} The formatted contributors section.
*/
function getContributorsList( pullRequests ) {
- const contributorsList = flow( [
+ const contributorsList = pipe( [
skipCreatedByBots,
getUniqueByUsername,
sortByUsername,
diff --git a/changelog.txt b/changelog.txt
index c3638cd1a13d75..4399018de22861 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,202 @@
== Changelog ==
+= 14.2.0 =
+
+## Changelog
+
+### Deprecations
+
+- Officially deprecate the `children` and `node` block attribute sources. ([44265](https://github.com/WordPress/gutenberg/pull/44265))
+
+### Enhancements
+
+#### Components
+
+- Link/Unlink buttons: Add more polished styling and UX. ([43802](https://github.com/WordPress/gutenberg/pull/43802))
+
+#### Global Styles
+
+- Allow setting Letter case and Decoration to 'None' and add Letter case to Global Styles. ([44067](https://github.com/WordPress/gutenberg/pull/44067))
+- Block supports: Allow overriding prettify options for enqueued CSS. ([44248](https://github.com/WordPress/gutenberg/pull/44248))
+- Show Letter Spacing in Global Styles -> Typography -> Headings. ([44142](https://github.com/WordPress/gutenberg/pull/44142))
+- Spacing presets: Switch to using numbers instead of t-shirt sizes for labels. ([44247](https://github.com/WordPress/gutenberg/pull/44247))
+
+#### Block Editor
+
+- Hide all floating block UI when typing. ([44083](https://github.com/WordPress/gutenberg/pull/44083))
+- Update animation for line and sibling inserter. ([44269](https://github.com/WordPress/gutenberg/pull/44269))
+- Warning component: Align the action buttons. ([44328](https://github.com/WordPress/gutenberg/pull/44328))
+
+#### Block Library
+
+- Calendar block: Add color supports and polish styles. ([42029](https://github.com/WordPress/gutenberg/pull/42029))
+- Embed block: Mark which attributes should be considered content. ([44039](https://github.com/WordPress/gutenberg/pull/44039))
+- List Item block: Improve writing flow. ([43954](https://github.com/WordPress/gutenberg/pull/43954))
+- Post Navigation Link block: Add arrows. ([40684](https://github.com/WordPress/gutenberg/pull/40684))
+- Query Loop block: Suggest active variation patterns.
+ ([44197](https://github.com/WordPress/gutenberg/pull/44197))
+
+#### Patterns
+
+- Add a new category for block patterns called "Banners". ([44203](https://github.com/WordPress/gutenberg/pull/44203))
+- Add a new category for block patterns called "Footers".
+ ([44200](https://github.com/WordPress/gutenberg/pull/44200))
+
+### Bug Fixes
+
+#### Components
+
+- BlockMover: Clean up focus styles. ([44241](https://github.com/WordPress/gutenberg/pull/44241))
+- Fix animation running in loop while dragging an image on a dropzone. ([44264](https://github.com/WordPress/gutenberg/pull/44264))
+- Fix popover stacking in the customize widgets editor. ([44282](https://github.com/WordPress/gutenberg/pull/44282))
+- Link autocompleter: Enable for all blocks. ([44078](https://github.com/WordPress/gutenberg/pull/44078))
+- Remove unexpected `has-text` class when empty children are passed to `Button`. ([44198](https://github.com/WordPress/gutenberg/pull/44198))
+
+#### Block Library
+
+##### Bugfixes to blocks:
+
+- Cover block: Fix preview. ([44321](https://github.com/WordPress/gutenberg/pull/44321))
+- Freeform block: Hide "Convert to blocks" when the block locked.
+ ([44288](https://github.com/WordPress/gutenberg/pull/44288))
+- Group block: Change default variation in inserter. ([44176](https://github.com/WordPress/gutenberg/pull/44176))
+- Missing block: Fix HTML block check. ([44327](https://github.com/WordPress/gutenberg/pull/44327))
+- Navigation block: Fix submenu colors for imported classic menus.
+ ([44283](https://github.com/WordPress/gutenberg/pull/44283))
+- Navigation block: Remove ellipses as menu icon options for now. ([44222](https://github.com/WordPress/gutenberg/pull/44222))
+- Pullquote block: Fix transform to quote crash.
+ ([44315](https://github.com/WordPress/gutenberg/pull/44315))
+- Post Featured Image block: Fix height/scale overwriting `img` inline styles. ([44213](https://github.com/WordPress/gutenberg/pull/44213))
+- Query Loop block: Fix broken preview in specific category template. ([44294](https://github.com/WordPress/gutenberg/pull/44294))
+- Query Loop block: Fix variation with declared`icon` object with `src`.
+ ([44270](https://github.com/WordPress/gutenberg/pull/44270))
+
+##### Other bugfixes not related to a specific block:
+
+- Avoid showing the recursion warning in previews when replacing template parts. ([44256](https://github.com/WordPress/gutenberg/pull/44256))
+- Ensure replacing a template part using a pattern doesn't update the existing
+- Fix demo content cover block text color. ([44174](https://github.com/WordPress/gutenberg/pull/44174))
+ entity. ([44221](https://github.com/WordPress/gutenberg/pull/44221))
+- Add style-engine to Gutenberg's `tsconfig.json` references. ([44516](https://github.com/WordPress/gutenberg/pull/44516))
+
+#### Block Editor
+
+- Block Toolbar: Update position when moving blocks. ([44301](https://github.com/WordPress/gutenberg/pull/44301))
+- Capture state changes scheduled between render and effect. ([38509](https://github.com/WordPress/gutenberg/pull/38509))
+- Writing flow: Fix partial selection when dragging in between blocks. ([44230](https://github.com/WordPress/gutenberg/pull/44230))
+
+#### Accessibility
+
+- Add `role=application` to List View to prevent browse mode triggering in NVDA. ([44291](https://github.com/WordPress/gutenberg/pull/44291))
+- Block label and title don't consider variations. ([44250](https://github.com/WordPress/gutenberg/pull/44250))
+- Make inline toolbar navigable by arrow keys. ([43645](https://github.com/WordPress/gutenberg/pull/43645))
+- Text Selection in Safari: Try new fix for recent version. ([44148](https://github.com/WordPress/gutenberg/pull/44148))
+
+#### Global Styles
+
+- Add: Frontend section presets output. ([42124](https://github.com/WordPress/gutenberg/pull/42124))
+- Block supports: Prioritize prettify options over `SCRIPT_DEBUG`. ([44254](https://github.com/WordPress/gutenberg/pull/44254))
+- Fix padding on the post editor when `RootPaddingAwareAlignments` setting is enabled. ([44209](https://github.com/WordPress/gutenberg/pull/44209))
+- Remove the beta label from global styles header. ([44251](https://github.com/WordPress/gutenberg/pull/44251))
+- Theme.json: Fix some outline properties that don't work properly in the editor. ([44504](https://github.com/WordPress/gutenberg/pull/44504))
+
+#### Site Editor
+
+- Make template names and descriptions dynamic. ([43862](https://github.com/WordPress/gutenberg/pull/43862))
+- Prevent editor from creating multiple templates when multi-clicking the
+ "create" button. ([44146](https://github.com/WordPress/gutenberg/pull/44146))
+
+#### Keycodes
+
+- Keyboard Shortcuts: Fix settings sidebar toggle shortcut. ([43428](https://github.com/WordPress/gutenberg/pull/43428))
+
+### Performance
+
+- Avoid calling redux actions constantly when moving the mouse or scrolling. ([44325](https://github.com/WordPress/gutenberg/pull/44325))
+- Batch container block settings action calls. ([43958](https://github.com/WordPress/gutenberg/pull/43958))
+- Prevent resize observer loops in BlockPreview. ([44319](https://github.com/WordPress/gutenberg/pull/44319))
+
+### Documentation
+
+- Include information about multiple scripts support added in WP 6.1. ([44155](https://github.com/WordPress/gutenberg/pull/44155))
+- Popover: Write better documentation regarding the recent API changes. ([44195](https://github.com/WordPress/gutenberg/pull/44195))
+- RangeControl component: Clarify rail vs track difference. ([44057](https://github.com/WordPress/gutenberg/pull/44057))
+- Update links in the Development Platform document. ([44181](https://github.com/WordPress/gutenberg/pull/44181))
+- Updating versions in WP for 6.0.2. ([43826](https://github.com/WordPress/gutenberg/pull/43826))
+
+### Code Quality
+
+- Backport template creation changes from Core.
+- Enforce coding guideline regarding the usage of quotation marks. ([44305](https://github.com/WordPress/gutenberg/pull/44305))
+- Fix missing TS types for a11y in `packages/components`. ([44277](https://github.com/WordPress/gutenberg/pull/44277))
+- Preferences-persistence: Remove `@wordpress/compose` dependency. ([44202](https://github.com/WordPress/gutenberg/pull/44202))
+- Refactor style engine border styles. ([43594](https://github.com/WordPress/gutenberg/pull/43594))
+- Removes whitespace from l18n-strings. ([44314](https://github.com/WordPress/gutenberg/pull/44314))
+- Renaming functions to match their naming in Core. ([44266](https://github.com/WordPress/gutenberg/pull/44266))
+ ([44299](https://github.com/WordPress/gutenberg/pull/44299))
+- `useInstanceId`: Convert to typescript. ([43790](https://github.com/WordPress/gutenberg/pull/43790))
+
+#### Updating dependencies
+
+- Update `fast-average-color` library to latest version. ([44175](https://github.com/WordPress/gutenberg/pull/44175))
+- Update `json2php` to `v0.0.5`. ([44313](https://github.com/WordPress/gutenberg/pull/44313))
+- Remove `wp-editor` from `wp-edit-blocks` dependencies. ([33496](https://github.com/WordPress/gutenberg/pull/33496))
+
+#### Block Library
+
+- Comments Pagination blocks: Rename for consistency. ([44287](https://github.com/WordPress/gutenberg/pull/44287))
+- Embed block: Remove incorrect comments about block variations. ([43834](https://github.com/WordPress/gutenberg/pull/43834))
+
+#### Components
+
+- Refactor `NavigationMenu` to ignore `exhaustive-deps`. ([44090](https://github.com/WordPress/gutenberg/pull/44090))
+- Refactor `RangeControl` to pass `exhaustive-deps`.
+ ([44271](https://github.com/WordPress/gutenberg/pull/44271))
+- Popover: Add `anchor` prop which supersedes all previous anchor-related props. ([43691](https://github.com/WordPress/gutenberg/pull/43691))
+- UnitControl: Fix exhaustive-deps warnings. ([44161](https://github.com/WordPress/gutenberg/pull/44161))
+- UnitControl: Use `hideHTMLArrows` prop to hide spin buttons. ([43985](https://github.com/WordPress/gutenberg/pull/43985))
+- `useSetting`: Minor refactor. ([44267](https://github.com/WordPress/gutenberg/pull/44267))
+
+#### Refactoring tests to use `@testing-library/react`
+
+- Refactor `BlockControls` tests to `@testing-library/react`. ([44122](https://github.com/WordPress/gutenberg/pull/44122))
+- Refactor `ColorPalette` tests to `@testing-library/react`. ([44108](https://github.com/WordPress/gutenberg/pull/44108))
+- Refactor `KeyboardShortcutHelpModal` tests to `@testing-library/react`.
+ ([44077](https://github.com/WordPress/gutenberg/pull/44077))
+
+#### Work to remove dependency on `lodash`
+
+- Compose: Introduce in-house `compose` and `pipe` utils. ([44112](https://github.com/WordPress/gutenberg/pull/44112))
+- Compose: Introduce in-house `debounce()` utility, deprecate Lodash version. ([43943](https://github.com/WordPress/gutenberg/pull/43943))
+- Lodash: Remove dependency from `@wordpress/widgets` package. ([44201](https://github.com/WordPress/gutenberg/pull/44201))
+- Lodash: Refactor away from `_.flowRight()`.
+ ([44188](https://github.com/WordPress/gutenberg/pull/44188))
+
+#### Testing
+
+- Storybook: Set up local visual regression testing.
+ ([43393](https://github.com/WordPress/gutenberg/pull/43393))
+
+#### Tooling
+
+- Ensure all packages get minor/major version bump when requested. ([44317](https://github.com/WordPress/gutenberg/pull/44317))
+
+## First time contributors
+
+The following PRs were merged by first time contributors:
+
+- @kkoppenhaver: Update RangeControl documentation to clarify rail vs track. ([44057](https://github.com/WordPress/gutenberg/pull/44057))
+- @pagelab: Enforce coding guideline regarding the usage of quotation marks. ([44305](https://github.com/WordPress/gutenberg/pull/44305))
+
+## Contributors
+
+The following contributors merged PRs in this release:
+
+@aaronrobertshaw @ajlende @annezazu @apmatthews @aristath @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @dcalhoun @draganescu @ellatrix @geriux @glendaviesnz @gziolo @jasmussen @jorgefilipecosta @kebbet @kkoppenhaver @Mamaduka @matiasbenedetto @mcsf @michalczaplinski @mirka @mtias @noisysocks @ntsekouras @pagelab @ramonjd @t-hamano @talldan @tellthemachines @tyxla @walbo @youknowriad
+
+
+
+
= 14.1.1 =
diff --git a/composer.json b/composer.json
index b91bb973ade417..3f16ba495a94ca 100644
--- a/composer.json
+++ b/composer.json
@@ -28,7 +28,7 @@
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"squizlabs/php_codesniffer": "^3.5",
- "phpcompatibility/php-compatibility": "^9.3",
+ "phpcompatibility/phpcompatibility-wp": "^2.1.3",
"wp-coding-standards/wpcs": "^2.2",
"sirbrillig/phpcs-variable-analysis": "^2.8",
"spatie/phpunit-watcher": "^1.23",
diff --git a/docs/contributors/code/testing-overview.md b/docs/contributors/code/testing-overview.md
index 85e4ff082e92af..fa17909b4cd376 100644
--- a/docs/contributors/code/testing-overview.md
+++ b/docs/contributors/code/testing-overview.md
@@ -21,7 +21,7 @@ When writing tests consider the following:
Tests for JavaScript use [Jest](https://jestjs.io/) as the test runner and its API for [globals](https://jestjs.io/docs/en/api.html) (`describe`, `test`, `beforeEach` and so on) [assertions](https://jestjs.io/docs/en/expect.html), [mocks](https://jestjs.io/docs/en/mock-functions.html), [spies](https://jestjs.io/docs/en/jest-object.html#jestspyonobject-methodname) and [mock functions](https://jestjs.io/docs/en/mock-function-api.html). If needed, you can also use [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) for React component testing.
-_It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, React Testing Library (RTL) should be used for new tests instead, and over time old tests should be refactored to use RTL too (typically when working on code that touches an old test)._
+_It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, React Testing Library (RTL) is now used for all existing and new tests instead._
Assuming you've followed the [instructions](/docs/contributors/code/getting-started-with-code-contribution.md) to install Node and project dependencies, tests can be run from the command-line with NPM:
diff --git a/docs/getting-started/create-block/author-experience.md b/docs/getting-started/create-block/author-experience.md
index 140238eaff0f99..a52ea808f69658 100644
--- a/docs/getting-started/create-block/author-experience.md
+++ b/docs/getting-started/create-block/author-experience.md
@@ -79,6 +79,7 @@ All of this combined together, here's what the edit function looks like:
```jsx
import { Placeholder, TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
+import { useBlockProps } from "@wordpress/block-editor";
export default function Edit( { attributes, isSelected, setAttributes } ) {
return (
diff --git a/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md
new file mode 100644
index 00000000000000..dbe21ff35aa339
--- /dev/null
+++ b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md
@@ -0,0 +1,263 @@
+# Extending the Query Loop block
+
+The Query Loop block is a powerful tool that allows users to cycle through a determined list of posts and display a certain set of blocks that will inherit the context of each of the posts in the list. For example, it can be set to cycle through all the posts of a certain category and for each of those posts display their featured image. And much more, of course!
+
+But precisely because the Query Loop block is so powerful and allows for great customization, it can also be daunting. Most users wouldn't want to be presented with the full capabilities of the Query Loop block, as most users wouldn't be familiar with the concept of a “query” and its associated technical terms. Instead, most users will likely appreciate a pre-set version of the block, with fewer settings to adjust and clearer naming. The Post List variation offered by default is a good example of this practice: the user will be using the Query Loop block without being exposed to its technicalities, and will also be more likely to discover and understand the purpose of the block.
+
+In the same manner, a lot of extenders might need a way to present bespoke versions of the block, with their own presets, additional settings and without customization options which are irrelevant to their use-case (often, for example, their custom post type). The Query Loop block offers very powerful ways to create such variations.
+
+## Extending the block with variations
+
+By registering your own block variation with some specific Query Loop block settings, you can have finer control over how it is presented, while still being able to use the full capabilities which the Query Loop block offers underneath. If you are not familiar with block variations, learn more about them [here](/docs/reference-guides/block-api/block-variations.md).
+
+With the block variations API you can provide the default settings that make the most sense for your use-case.
+
+Let's go on a journey, for example, of setting up a variation for a plugin which registers a `book` [custom post type](https://developer.wordpress.org/plugins/post-types/).
+
+### Offer sensible defaults
+
+Your first step would be to create a variation which will be set up in such a way to provide a block variation which will display by default a list of books instead of blog posts. The full variation code will look something like this:
+
+```js
+const MY_VARIATION_NAME = 'my-plugin/books-list';
+
+registerBlockVariation( 'core/query', {
+ name: MY_VARIATION_NAME,
+ title: 'Books List',
+ description: 'Displays a list of books',
+ isActive: ( { namespace, query } ) => {
+ return (
+ namespace === MY_VARIATION_NAME
+ && query.postType === 'book'
+ );
+ },
+ icon: /** An SVG icon can go here*/,
+ attributes: {
+ namespace: MY_VARIATION_NAME,
+ query: {
+ perPage: 6,
+ pages: 0,
+ offset: 0,
+ postType: 'book',
+ order: 'desc',
+ orderBy: 'date',
+ author: '',
+ search: '',
+ exclude: [],
+ sticky: '',
+ inherit: false,
+ },
+ },
+ scope: [ 'inserter' ],
+ }
+);
+```
+
+If that sounds like a lot, don't fret, let's go through each of the properties here and see why they are there and what they are doing.
+
+Essentially, you would start with something like this:
+
+```js
+registerBlockVariation( 'core/query', {
+ name: 'my-plugin/books-list',
+ attributes: {
+ query: {
+ /** ...more query settings if needed */
+ postType: 'book',
+ },
+ },
+} );
+```
+
+In this way, the users won't have to choose the custom `postType` from the dropdown, and be already presented with the correct configuration. However, you might ask, how is a user going to find and insert this variation? Good question! To enable this, you should add:
+
+```js
+{
+ /** ...variation properties */
+ scope: [ 'inserter' ],
+}
+```
+
+In this way, your block will show up just like any other block while the user is in the editor and searching for it. At this point you might also want to add a custom icon, title and description to your variation, just like so:
+
+```js
+{
+ /** ...variation properties */
+ title: 'Books List',
+ description: 'Displays a list of books',
+ icon: /* Your svg icon here */,
+}
+```
+
+At this point, your custom variation will be virtually indistinguishable from a stand-alone block. Completely branded to your plugin, easy to discover and directly available to the user as a drop in.
+
+### Customize your variation layout
+
+Please note that the Query Loop block supports `'block'` as a string in the `scope` property. In theory, that's to allow the variation to be picked up after inserting the block itself. Read more about the Block Variation Picker [here](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md).
+
+However, it is unadvisable to use this currently, this is due to the Query Loop setup with patterns and `scope: [ 'block' ]` variations, all of the selected pattern's attributes will be used except for `postType` and `inherit` query properties, which will likely lead to conflicts and non-functional variations.
+
+To circumvent this, there two routes, the first one is to add your default `innerBlocks`, like so:
+
+```js
+innerBlocks: [
+ [
+ 'core/post-template',
+ {},
+ [ [ 'core/post-title' ], [ 'core/post-excerpt' ] ],
+ ],
+ [ 'core/query-pagination' ],
+ [ 'core/query-no-results' ],
+],
+```
+
+The other would be to register patterns specific to your variation, we can cover that in another guide.
+
+### Making Gutenberg recognize your variation
+
+There is one slight problem you might have realized after implementing this variation: while it is transparent to the user as they are inserting it, Gutenberg will still recognize the variation as a Query Loop block at its core and so, after its insertion, it will show up as a Query Loop block in the tree view of the editor, for instance.
+
+We need a way to tell the editor that this block is indeed your specific variation. This is what the `isActive` property is made for: it's a way to determine whether a certain variation is active based on the block's attributes. You could use it like this:
+
+```js
+{
+ /** ...variation properties */
+ isActive: ( { namespace, query } ) => {
+ return (
+ namespace === MY_VARIATION_NAME
+ && query.postType === 'book'
+ );
+ },
+}
+```
+
+You might have been tempted to only compare the `postType`: in this way, Gutenberg will recognize the block as your variation any time the `postType` matches `book`! That's awesome, but the problem is that now Gutenberg will recognize the block as your specific variation any time the `postType` is set to `book`, which is not what we want: other plugins might want to publish variations based on the `book` post type, or we might just not want the variation to be recognized every time the user sets the type to `book` manually through the editor settings.
+
+That's why the Query Loop block exposes a special attribute called `namespace`: it really doesn't do anything inside the block implementation, and it's used as an easy way for extenders to recognize and scope their own variation. In addition, `isActive` also accepts just an array of strings with the attributes to compare. Often, `namespace` would be sufficient, so you would use it like so:
+
+```js
+{
+ /** ...variation properties */
+ attributes: {
+ /** ...variation attributes */
+ namespace: 'my-plugin/books-list',
+ },
+ isActive: [ 'namespace' ],
+}
+```
+
+Like so, Gutenberg will know that it is your specific variation only in the case it matches your custom namespace! So convenient!
+
+## Extending the query
+
+Even with all of this, your custom post type might have unique requirements: it might support certain custom attributes that you might want to filter and query for, or some other query parameters might be irrelevant or even completely unsupported! We have build the Query Loop block with such use-cases in mind, so let's see how you can solve this problem.
+
+### Disabling irrelevant or unsupported query controls
+
+Let's say you don't use at all the `sticky` attribute in your books, so that would be totally irrelevant to the customization of your block. In order to not confuse the users as to what a setting might do, and only exposing a clear UX to them, we want this control to be unavailable. Furthermore, let's say that you don't use the `author` field at all, which generally indicates the person who has added that post to the database, instead you use a custom `bookAuthor` field. As such, not only keeping the `author` filter would be confusing, it would outright break your query.
+
+For this reason, the Query Loop block supports a property called `allowedControls` which accepts an array of keys of the controls we want to display on the inspector sidebar. By default, we accept all the controls, but as soon as we provide an array to this property, we want to be specific and specify only the controls which are going to be relevant for us!
+
+As of version 13.9, the following controls are available:
+
+- `inherit` - Shows the toggle switch for allowing the query to be inherited directly from the template.
+- `postType` - Shows a dropdown of available post types.
+- `order` - Shows a dropdown to select the order of the query.
+- `sticky` - Shows a checkbox to only display sticky posts.
+- `taxQuery` - Shows available taxonomies filters for the currently selected post type.
+- `author` - Shows an input field to filter the query by author.
+- `search` - Shows an input filed to filter the query by keywords.
+
+In our case, the property would look like this:
+
+```js
+{
+ /** ...variation properties */
+ allowedControls: [ 'inherit', 'order', 'taxQuery', 'search' ],
+}
+```
+
+Notice that we have also disabled the `postType` control: when the user selects our variation, why show them a confusing dropdown to change the post type? On top of that it might break the block as we can implement custom controls, as we'll see shortly.
+
+### Adding additional controls
+
+Because our plugin uses custom attributes that we need to query, we want to add our own controls to allow the users to select those instead of the ones we have just disabled from the core inspector controls. We can do this via a [React HOC](https://reactjs.org/docs/higher-order-components.html) hooked into a [block filter](https://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/), like so:
+
+```jsx
+export const withBookQueryControls = ( BlockEdit ) => ( props ) => {
+ // We only want to add these controls if it is our variation,
+ // so here we can implement a custom logic to check for that, similiar
+ // to the `isActive` function described above.
+ // The following assumes that you wrote a custom `isMyBooksVariation`
+ // function to handle that.
+ return isMyBooksVariation( props ) ? (
+ <>
+
+
+ { /** Our custom component */ }
+
+ >
+ ) : (
+
+ );
+};
+
+addFilter( 'editor.BlockEdit', 'core/query', withBookQueryControls );
+```
+
+Of course, you'll be responsible for implementing the logic of your control (you might want to take a look at [`@wordpress/components`](https://www.npmjs.com/package/@wordpress/components) to make your controls fit seamlessly within the Gutenberg UI). Any extra parameter you assign within the `query` object inside the blocks attributes can be used to create a custom query according to your needs, with a little extra effort.
+
+Currently, you'll likely have to implement slightly different paths to make the query behave correctly both on the front-end side (i.e. on the end user's side) and to show the correct preview on the editor side.
+
+```js
+{
+ /** ...variation properties */
+ attributes: {
+ /** ...variation attributes */
+ query: {
+ /** ...more query settings if needed */
+ postType: 'book',
+ /** Our custom query parameter */
+ bookAuthor: 'J. R. R. Tolkien'
+ }
+ }
+}
+```
+
+### Making your custom query work on the front-end side
+
+The Query Loop block functions mainly through the Post Template block which receives the attributes and builds the query from there. Other first-class children of the Query Loop block (such as the Pagination block) behave in the same way. They build their query and then expose the result via the filter [`query_loop_block_query_vars`](https://developer.wordpress.org/reference/hooks/query_loop_block_query_vars/).
+
+You can hook into that filter and modify your query accordingly. Just make sure you don't cause side-effects to other Query Loop blocks by at least checking that you apply the filter only to your variation!
+
+```php
+if( 'my-plugin/books-list' === $block[ 'attrs' ][ 'namespace' ] ) {
+ add_filter(
+ 'query_loop_block_query_vars',
+ function( $query ) {
+ /** You can read your block custom query parameters here and build your query */
+ },
+ );
+}
+```
+
+(In the code above, we assume you have some way to access the block, for example within a [`pre_render_block`](https://developer.wordpress.org/reference/hooks/pre_render_block/) filter, but the specific solution can be different depending on the use-case, so this is not a firm recommendation).
+
+### Making your custom query work on the editor side
+
+To finish up our custom variation, we might want the editor to react to changes in our custom query and display an appropriate preview accordingly. This is not required for a functioning block, but it enables a fully integrated user experience for the consumers of your block.
+
+The Query Loop block fetches its posts to show the preview using the [WordPress REST API](https://developer.wordpress.org/rest-api/). Any extra parameter added to the `query` object will be passed as a query argument to the API. This means that these extra parameters should be either supported by the REST API, or be handled by custom filters such as the [`rest_{$this->post_type}_query`](https://developer.wordpress.org/reference/hooks/rest_this-post_type_query/) filter which allows you to hook into any API request for your custom post type. Like so:
+
+```php
+add_filter(
+ 'rest_book_query',
+ function( $args, $request ) {
+ /** We can access our custom parameters from here */
+ $book_author = $request->get_param( 'bookAuthor' );
+ /** ...your custom query logic */
+ }
+);
+```
+
+And, just like that, you'll have created a fully functional variation of the Query Loop block!
diff --git a/docs/manifest.json b/docs/manifest.json
index 69d991c65d3da5..fa66c97044e1c4 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -1482,7 +1482,7 @@
"parent": "packages"
},
{
- "title": "@wordpress/create-block External Template",
+ "title": "External Project Templates",
"slug": "packages-create-block-external-template",
"markdown_source": "../packages/create-block/docs/external-template.md",
"parent": "packages-create-block"
@@ -1607,6 +1607,12 @@
"markdown_source": "../packages/eslint-plugin/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/experiments",
+ "slug": "packages-experiments",
+ "markdown_source": "../packages/experiments/README.md",
+ "parent": "packages"
+ },
{
"title": "@wordpress/format-library",
"slug": "packages-format-library",
@@ -1829,6 +1835,12 @@
"markdown_source": "../packages/style-engine/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/style-engine Using the Style Engine to generate block supports styles",
+ "slug": "using-the-style-engine-with-block-supports",
+ "markdown_source": "../packages/style-engine/docs/using-the-style-engine-with-block-supports.md",
+ "parent": "packages-style-engine"
+ },
{
"title": "@wordpress/stylelint-config",
"slug": "packages-stylelint-config",
diff --git a/docs/reference-guides/block-api/block-metadata.md b/docs/reference-guides/block-api/block-metadata.md
index e835db50c5e286..6ce54d8009dd75 100644
--- a/docs/reference-guides/block-api/block-metadata.md
+++ b/docs/reference-guides/block-api/block-metadata.md
@@ -473,7 +473,9 @@ See the [the variations documentation](/docs/reference-guides/block-api/block-va
{ "editorScript": "file:./index.js" }
```
-Block type editor script definition. It will only be enqueued in the context of the editor.
+Block type editor scripts definition. They will only be enqueued in the context of the editor.
+
+It's possible to pass a script handle registered with the [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) function, a path to a JavaScript file relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).
_Note: An option to pass also an array of editor scripts exists since WordPress `6.1.0`._
@@ -488,7 +490,9 @@ _Note: An option to pass also an array of editor scripts exists since WordPress
{ "script": "file:./script.js" }
```
-Block type frontend and editor script definition. It will be enqueued both in the editor and when viewing the content on the front of the site.
+Block type frontend and editor scripts definition. They will be enqueued both in the editor and when viewing the content on the front of the site.
+
+It's possible to pass a script handle registered with the [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) function, a path to a JavaScript file relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).
_Note: An option to pass also an array of scripts exists since WordPress `6.1.0`._
@@ -504,7 +508,9 @@ _Note: An option to pass also an array of scripts exists since WordPress `6.1.0`
{ "viewScript": [ "file:./view.js", "example-shared-view-script" ] }
```
-Block type frontend script definition. It will be enqueued only when viewing the content on the front of the site.
+Block type frontend scripts definition. They will be enqueued only when viewing the content on the front of the site.
+
+It's possible to pass a script handle registered with the [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) function, a path to a JavaScript file relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).
_Note: An option to pass also an array of view scripts exists since WordPress `6.1.0`._
@@ -519,7 +525,9 @@ _Note: An option to pass also an array of view scripts exists since WordPress `6
{ "editorStyle": "file:./index.css" }
```
-Block type editor style definition. It will only be enqueued in the context of the editor.
+Block type editor styles definition. They will only be enqueued in the context of the editor.
+
+It's possible to pass a style handle registered with the [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) function, a path to a CSS file relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).
_Note: An option to pass also an array of editor styles exists since WordPress `5.9.0`._
@@ -534,7 +542,9 @@ _Note: An option to pass also an array of editor styles exists since WordPress `
{ "style": [ "file:./style.css", "example-shared-style" ] }
```
-Block type frontend and editor style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.
+Block type frontend and editor styles definition. They will be enqueued both in the editor and when viewing the content on the front of the site.
+
+It's possible to pass a style handle registered with the [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) function, a path to a CSS file relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).
_Note: An option to pass also an array of styles exists since WordPress `5.9.0`._
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index 745bd600aa7ff0..148988bbfcc3e8 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -203,7 +203,7 @@ Displays a list of page numbers for comments pagination. ([Source](https://githu
- **Name:** core/comments-pagination-numbers
- **Category:** theme
-- **Supports:** typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Supports:** color (background, gradients, ~~text~~), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
- **Attributes:**
## Comments Previous Page
@@ -456,7 +456,7 @@ Display post author details such as name, avatar, and bio. ([Source](https://git
- **Name:** core/post-author
- **Category:** theme
- **Supports:** color (background, gradients, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** avatarSize, byline, showAvatar, showBio, textAlign
+- **Attributes:** avatarSize, byline, isLink, linkTarget, showAvatar, showBio, textAlign
## Post Author Biography
@@ -572,7 +572,7 @@ Post terms. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages
- **Name:** core/post-terms
- **Category:** theme
-- **Supports:** color (background, gradients, link, text), typography (fontSize, lineHeight), ~~html~~
+- **Supports:** color (background, gradients, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** prefix, separator, suffix, term, textAlign
## Post Title
diff --git a/docs/reference-guides/data/data-core-annotations.md b/docs/reference-guides/data/data-core-annotations.md
index f1d1d6918e5c5d..da86bf4b0dcf56 100644
--- a/docs/reference-guides/data/data-core-annotations.md
+++ b/docs/reference-guides/data/data-core-annotations.md
@@ -2,6 +2,10 @@
Namespace: `core/annotations`.
+
+This package is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
+
+
## Selectors
diff --git a/docs/reference-guides/data/data-core-reusable-blocks.md b/docs/reference-guides/data/data-core-reusable-blocks.md
index 3eeea29bd1f182..728281d0e48f3b 100644
--- a/docs/reference-guides/data/data-core-reusable-blocks.md
+++ b/docs/reference-guides/data/data-core-reusable-blocks.md
@@ -2,6 +2,9 @@
Namespace: `core/reusable-blocks`.
+
+This package is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
+
## Selectors
diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md
index 3b3d40ffd73359..8f18ed7631b826 100644
--- a/docs/reference-guides/theme-json-reference/theme-json-living.md
+++ b/docs/reference-guides/theme-json-reference/theme-json-living.md
@@ -139,10 +139,10 @@ Border styles.
| radius | undefined | |
| style | string | |
| width | string | |
-| top | undefined | |
-| right | undefined | |
-| bottom | undefined | |
-| left | undefined | |
+| top | object | color, style, width |
+| right | object | color, style, width |
+| bottom | object | color, style, width |
+| left | object | color, style, width |
---
diff --git a/gutenberg.php b/gutenberg.php
index 167705186e72b3..503a7b249ae8cb 100644
--- a/gutenberg.php
+++ b/gutenberg.php
@@ -5,7 +5,7 @@
* Description: Printing since 1440. This is the development plugin for the new block editor in core.
* Requires at least: 5.9
* Requires PHP: 5.6
- * Version: 14.2.0-rc.1
+ * Version: 14.3.0-rc.1
* Author: Gutenberg Team
* Text Domain: gutenberg
*
diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php
index 5cb7fb7cfc5ac6..4a9a23d7b5af3f 100644
--- a/lib/block-supports/duotone.php
+++ b/lib/block-supports/duotone.php
@@ -83,10 +83,10 @@ function gutenberg_tinycolor_rgb_to_rgb( $rgb_color ) {
*/
function gutenberg_tinycolor_hue_to_rgb( $p, $q, $t ) {
if ( $t < 0 ) {
- $t += 1;
+ ++$t;
}
if ( $t > 1 ) {
- $t -= 1;
+ --$t;
}
if ( $t < 1 / 6 ) {
return $p + ( $q - $p ) * 6 * $t;
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index eaca6d4c70cc8c..15a7a131f8a9b0 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -28,25 +28,33 @@ function gutenberg_register_layout_support( $block_type ) {
/**
* Generates the CSS corresponding to the provided layout.
*
- * @param string $selector CSS selector.
- * @param array $layout Layout object. The one that is passed has already checked the existence of default block layout.
- * @param boolean $has_block_gap_support Whether the theme has support for the block gap.
- * @param string $gap_value The block gap value to apply.
- * @param boolean $should_skip_gap_serialization Whether to skip applying the user-defined value set in the editor.
- * @param string $fallback_gap_value The block gap value to apply.
- * @param array $block_spacing Custom spacing set on the block.
- *
- * @return string CSS style.
+ * @param string $selector CSS selector.
+ * @param array $layout Layout object. The one that is passed has already checked
+ * the existence of default block layout.
+ * @param bool $has_block_gap_support Optional. Whether the theme has support for the block gap. Default false.
+ * @param string|string[]|null $gap_value Optional. The block gap value to apply. Default null.
+ * @param bool $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
+ * @param string $fallback_gap_value Optional. The block gap value to apply. Default '0.5em'.
+ * @param array|null $block_spacing Optional. Custom spacing set on the block. Default null.
+ * @return string CSS styles on success. Else, empty string.
*/
function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
$layout_styles = array();
+
if ( 'default' === $layout_type ) {
if ( $has_block_gap_support ) {
if ( is_array( $gap_value ) ) {
$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
}
if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
+ // Get spacing CSS variable from preset value if provided.
+ if ( is_string( $gap_value ) && str_contains( $gap_value, 'var:preset|spacing|' ) ) {
+ $index_to_splice = strrpos( $gap_value, '|' ) + 1;
+ $slug = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
+ $gap_value = "var(--wp--preset--spacing--$slug)";
+ }
+
array_push(
$layout_styles,
array(
@@ -110,8 +118,10 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
)
);
- // Handle negative margins for alignfull children of blocks with custom padding set.
- // They're added separately because padding might only be set on one side.
+ /*
+ * Handle negative margins for alignfull children of blocks with custom padding set.
+ * They're added separately because padding might only be set on one side.
+ */
if ( isset( $block_spacing_values['declarations']['padding-right'] ) ) {
$padding_right = $block_spacing_values['declarations']['padding-right'];
$layout_styles[] = array(
@@ -225,7 +235,7 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
}
if ( 'horizontal' === $layout_orientation ) {
- /**
+ /*
* Add this style only if is not empty for backwards compatibility,
* since we intend to convert blocks that had flex layout implemented
* by custom css.
@@ -263,13 +273,17 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
}
if ( ! empty( $layout_styles ) ) {
- // Add to the style engine store to enqueue and render layout styles.
- // Return compiled layout styles to retain backwards compatibility.
- // Since https://github.com/WordPress/gutenberg/pull/42452 we no longer call wp_enqueue_block_support_styles in this block supports file.
+ /*
+ * Add to the style engine store to enqueue and render layout styles.
+ * Return compiled layout styles to retain backwards compatibility.
+ * Since https://github.com/WordPress/gutenberg/pull/42452,
+ * wp_enqueue_block_support_styles is no longer called in this block supports file.
+ */
return gutenberg_style_engine_get_stylesheet_from_css_rules(
$layout_styles,
array(
- 'context' => 'block-supports',
+ 'context' => 'block-supports',
+ 'prettify' => false,
)
);
}
@@ -323,10 +337,12 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$class_names[] = 'has-global-padding';
}
- // The following section was added to reintroduce a small set of layout classnames that were
- // removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
- // not intended to provide an extended set of classes to match all block layout attributes
- // here.
+ /*
+ * The following section was added to reintroduce a small set of layout classnames that were
+ * removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
+ * not intended to provide an extended set of classes to match all block layout attributes
+ * here.
+ */
if ( ! empty( $block['attrs']['layout']['orientation'] ) ) {
$class_names[] = 'is-' . sanitize_title( $block['attrs']['layout']['orientation'] );
}
@@ -350,14 +366,19 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$class_names[] = sanitize_title( $layout_classname );
}
- // Only generate Layout styles if the theme has not opted-out.
- // Attribute-based Layout classnames are output in all cases.
+ /*
+ * Only generate Layout styles if the theme has not opted-out.
+ * Attribute-based Layout classnames are output in all cases.
+ */
if ( ! current_theme_supports( 'disable-layout-styles' ) ) {
$gap_value = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'blockGap' ) );
- // Skip if gap value contains unsupported characters.
- // Regex for CSS value borrowed from `safecss_filter_attr`, and used here
- // because we only want to match against the value, not the CSS attribute.
+
+ /*
+ * Skip if gap value contains unsupported characters.
+ * Regex for CSS value borrowed from `safecss_filter_attr`, and used here
+ * to only match against the value, not the CSS attribute.
+ */
if ( is_array( $gap_value ) ) {
foreach ( $gap_value as $key => $value ) {
$gap_value[ $key ] = $value && preg_match( '%[\\\(&=}]|/\*%', $value ) ? null : $value;
@@ -369,10 +390,21 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$fallback_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), '0.5em' );
$block_spacing = _wp_array_get( $block, array( 'attrs', 'style', 'spacing' ), null );
- // If a block's block.json skips serialization for spacing or spacing.blockGap,
- // don't apply the user-defined value to the styles.
+ /*
+ * If a block's block.json skips serialization for spacing or spacing.blockGap,
+ * don't apply the user-defined value to the styles.
+ */
$should_skip_gap_serialization = gutenberg_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );
- $style = gutenberg_get_layout_style( ".$block_classname.$container_class", $used_layout, $has_block_gap_support, $gap_value, $should_skip_gap_serialization, $fallback_gap_value, $block_spacing );
+
+ $style = gutenberg_get_layout_style(
+ ".$block_classname.$container_class",
+ $used_layout,
+ $has_block_gap_support,
+ $gap_value,
+ $should_skip_gap_serialization,
+ $fallback_gap_value,
+ $block_spacing
+ );
// Only add container class and enqueue block support styles if unique styles were generated.
if ( ! empty( $style ) ) {
@@ -380,8 +412,10 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
}
}
- // This assumes the hook only applies to blocks with a single wrapper.
- // I think this is a reasonable limitation for that particular hook.
+ /*
+ * This assumes the hook only applies to blocks with a single wrapper.
+ * A limitation of this hook is that nested inner blocks wrappers are not yet supported.
+ */
$content = preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="' . esc_attr( implode( ' ', $class_names ) ) . ' ',
@@ -422,7 +456,7 @@ function gutenberg_restore_group_inner_container( $block_content, $block ) {
if (
WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ||
1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
- ( isset( $block['attrs']['layout']['type'] ) && 'default' !== $block['attrs']['layout']['type'] )
+ ( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] )
) {
return $block_content;
}
diff --git a/lib/block-supports/settings.php b/lib/block-supports/settings.php
new file mode 100644
index 00000000000000..60900629c04cf1
--- /dev/null
+++ b/lib/block-supports/settings.php
@@ -0,0 +1,151 @@
+get_registered( $block['blockName'] );
+ if ( ! block_has_support( $block_type, array( '__experimentalSettings' ), false ) ) {
+ return $block_content;
+ }
+
+ // return early if no settings are found on the block attributes.
+ $block_settings = _wp_array_get( $block, array( 'attrs', 'settings' ), null );
+ if ( empty( $block_settings ) ) {
+ return $block_content;
+ }
+
+ $class_name = _gutenberg_get_presets_class_name( $block );
+
+ // Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
+ // Retrieve the opening tag of the first HTML element.
+ $html_element_matches = array();
+ preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
+ $first_element = $html_element_matches[0][0];
+ // If the first HTML element has a class attribute just add the new class
+ // as we do on layout and duotone.
+ if ( strpos( $first_element, 'class="' ) !== false ) {
+ $content = preg_replace(
+ '/' . preg_quote( 'class="', '/' ) . '/',
+ 'class="' . $class_name . ' ',
+ $block_content,
+ 1
+ );
+ } else {
+ // If the first HTML element has no class attribute we should inject the attribute before the attribute at the end.
+ $first_element_offset = $html_element_matches[0][1];
+ $content = substr_replace( $block_content, ' class="' . $class_name . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
+ }
+
+ return $content;
+}
+
+/**
+ * Render the block level presets stylesheet.
+ *
+ * @access private
+ *
+ * @param string|null $pre_render The pre-rendered content. Default null.
+ * @param array $block The block being rendered.
+ *
+ * @return null
+ */
+function _gutenberg_add_block_level_preset_styles( $pre_render, $block ) {
+ // Return early if the block has not support for descendent block styles.
+ $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
+ if ( ! block_has_support( $block_type, array( '__experimentalSettings' ), false ) ) {
+ return null;
+ }
+
+ // return early if no settings are found on the block attributes.
+ $block_settings = _wp_array_get( $block, array( 'attrs', 'settings' ), null );
+ if ( empty( $block_settings ) ) {
+ return null;
+ }
+
+ $class_name = '.' . _gutenberg_get_presets_class_name( $block );
+
+ // the root selector for preset variables needs to target every possible block selector
+ // in order for the general setting to override any bock specific setting of a parent block or
+ // the site root.
+ $variables_root_selector = '*,[class*="wp-block"]';
+ $registry = WP_Block_Type_Registry::get_instance();
+ $blocks = $registry->get_all_registered();
+ foreach ( $blocks as $block_type ) {
+ if (
+ isset( $block_type->supports['__experimentalSelector'] ) &&
+ is_string( $block_type->supports['__experimentalSelector'] )
+ ) {
+ $variables_root_selector .= ',' . $block_type->supports['__experimentalSelector'];
+ }
+ }
+ $variables_root_selector = WP_Theme_JSON_6_1::scope_selector( $class_name, $variables_root_selector );
+
+ // Remove any potentially unsafe styles.
+ $theme_json_shape = WP_Theme_JSON_Gutenberg::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'settings' => $block_settings,
+ )
+ );
+ $theme_json_object = new WP_Theme_JSON_Gutenberg( $theme_json_shape );
+
+ $styles = '';
+
+ // include preset css variables declaration on the stylesheet.
+ $styles .= $theme_json_object->get_stylesheet(
+ array( 'variables' ),
+ null,
+ array(
+ 'root_selector' => $variables_root_selector,
+ 'scope' => $class_name,
+ )
+ );
+
+ // include preset css classes on the the stylesheet.
+ $styles .= $theme_json_object->get_stylesheet(
+ array( 'presets' ),
+ null,
+ array(
+ 'root_selector' => $class_name . ',' . $class_name . ' *',
+ 'scope' => $class_name,
+ )
+ );
+
+ if ( ! empty( $styles ) ) {
+ gutenberg_enqueue_block_support_styles( $styles );
+ }
+
+ return null;
+}
+
+add_filter( 'render_block', '_gutenberg_add_block_level_presets_class', 10, 2 );
+add_filter( 'pre_render_block', '_gutenberg_add_block_level_preset_styles', 10, 2 );
diff --git a/lib/client-assets.php b/lib/client-assets.php
index b2e9fea929c5d2..905aef70cb4d29 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -203,7 +203,7 @@ function gutenberg_register_packages_scripts( $scripts ) {
// Replace extension with `.asset.php` to find the generated dependencies file.
$asset_file = substr( $path, 0, -( strlen( '.js' ) ) ) . '.asset.php';
$asset = file_exists( $asset_file )
- ? require( $asset_file )
+ ? require $asset_file
: null;
$dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : array();
$version = isset( $asset['version'] ) ? $asset['version'] : $default_version;
@@ -445,3 +445,96 @@ function gutenberg_register_packages_styles( $styles ) {
$styles->add_data( 'wp-widgets', 'rtl', 'replace' );
}
add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );
+
+/**
+ * Fetches, processes and compiles stored core styles, then combines and renders them to the page.
+ * Styles are stored via the Style Engine API.
+ *
+ * This hook also exists, and should be backported to Core in future versions.
+ * However, it is envisaged that Gutenberg will continue to use the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes to aid continuous development.
+ *
+ * See: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/
+ *
+ * @param array $options {
+ * Optional. An array of options to pass to gutenberg_style_engine_get_stylesheet_from_context(). Default empty array.
+ *
+ * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
+ * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
+ * }
+ *
+ * @since 6.1
+ *
+ * @return void
+ */
+function gutenberg_enqueue_stored_styles( $options = array() ) {
+ $is_block_theme = wp_is_block_theme();
+ $is_classic_theme = ! $is_block_theme;
+
+ /*
+ * For block themes, print stored styles in the header.
+ * For classic themes, in the footer.
+ */
+ if (
+ ( $is_block_theme && doing_action( 'wp_footer' ) ) ||
+ ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) )
+ ) {
+ return;
+ }
+
+ $core_styles_keys = array( 'block-supports' );
+ $compiled_core_stylesheet = '';
+ $style_tag_id = 'core';
+ foreach ( $core_styles_keys as $style_key ) {
+ // Adds comment if code is prettified to identify core styles sections in debugging.
+ $should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
+ if ( $should_prettify ) {
+ $compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n";
+ }
+ // Chains core store ids to signify what the styles contain.
+ $style_tag_id .= '-' . $style_key;
+ $compiled_core_stylesheet .= gutenberg_style_engine_get_stylesheet_from_context( $style_key, $options );
+ }
+
+ // Combines Core styles.
+ if ( ! empty( $compiled_core_stylesheet ) ) {
+ wp_register_style( $style_tag_id, false, array(), true, true );
+ wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet );
+ wp_enqueue_style( $style_tag_id );
+ }
+
+ // If there are any other stores registered by themes etc., print them out.
+ $additional_stores = WP_Style_Engine_CSS_Rules_Store_Gutenberg::get_stores();
+
+ /*
+ * Since the corresponding action hook in Core is removed below,
+ * this function should still honour any styles stored using the Core Style Engine store.
+ */
+ if ( class_exists( 'WP_Style_Engine_CSS_Rules_Store' ) ) {
+ $additional_stores = array_merge( $additional_stores, WP_Style_Engine_CSS_Rules_Store::get_stores() );
+ }
+
+ foreach ( array_keys( $additional_stores ) as $store_name ) {
+ if ( in_array( $store_name, $core_styles_keys, true ) ) {
+ continue;
+ }
+ $styles = gutenberg_style_engine_get_stylesheet_from_context( $store_name, $options );
+ if ( ! empty( $styles ) ) {
+ $key = "wp-style-engine-$store_name";
+ wp_register_style( $key, false, array(), true, true );
+ wp_add_inline_style( $key, $styles );
+ wp_enqueue_style( $key );
+ }
+ }
+}
+
+/*
+ * Always remove the Core action hook while gutenberg_enqueue_stored_styles() exists to avoid styles being printed twice.
+ * This is also because gutenberg_enqueue_stored_styles uses the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes,
+ * which are in continuous development and generally ahead of Core.
+ */
+remove_action( 'wp_enqueue_scripts', 'wp_enqueue_stored_styles' );
+remove_action( 'wp_footer', 'wp_enqueue_stored_styles', 1 );
+
+// Enqueue stored styles.
+add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_stored_styles' );
+add_action( 'wp_footer', 'gutenberg_enqueue_stored_styles', 1 );
diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
index 878ac30c1b2c7d..07820ccbd1dbe2 100644
--- a/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
+++ b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
@@ -592,7 +592,7 @@ public function get_data() {
}
$flattened_preset = array();
foreach ( $items as $slug => $value ) {
- $flattened_preset[] = array_merge( array( 'slug' => $slug ), $value );
+ $flattened_preset[] = array_merge( array( 'slug' => (string) $slug ), $value );
}
_wp_array_set( $output, $path, $flattened_preset );
}
diff --git a/lib/compat/wordpress-6.1/blocks.php b/lib/compat/wordpress-6.1/blocks.php
index a33515632099b3..b22fb1fe18aee8 100644
--- a/lib/compat/wordpress-6.1/blocks.php
+++ b/lib/compat/wordpress-6.1/blocks.php
@@ -81,7 +81,7 @@ function gutenberg_block_type_metadata_view_script( $settings, $metadata ) {
// Replace suffix and extension with `.asset.php` to find the generated dependencies file.
$view_asset_file = substr( $view_script_path, 0, -( strlen( '.js' ) ) ) . '.asset.php';
- $view_asset = file_exists( $view_asset_file ) ? require( $view_asset_file ) : null;
+ $view_asset = file_exists( $view_asset_file ) ? require $view_asset_file : null;
$view_script_dependencies = isset( $view_asset['dependencies'] ) ? $view_asset['dependencies'] : array();
$view_script_version = isset( $view_asset['version'] ) ? $view_asset['version'] : false;
$result = wp_register_script(
@@ -102,79 +102,6 @@ function gutenberg_block_type_metadata_view_script( $settings, $metadata ) {
}
add_filter( 'block_type_metadata_settings', 'gutenberg_block_type_metadata_view_script', 10, 2 );
-if ( ! function_exists( 'wp_enqueue_block_view_script' ) ) {
- /**
- * Enqueues a frontend script for a specific block.
- *
- * Scripts enqueued using this function will only get printed
- * when the block gets rendered on the frontend.
- *
- * @since 6.1.0
- *
- * @param string $block_name The block name, including namespace.
- * @param array $args An array of arguments [handle,src,deps,ver,media,textdomain].
- *
- * @return void
- */
- function wp_enqueue_block_view_script( $block_name, $args ) {
- $args = wp_parse_args(
- $args,
- array(
- 'handle' => '',
- 'src' => '',
- 'deps' => array(),
- 'ver' => false,
- 'in_footer' => false,
-
- // Additional args to allow translations for the script's textdomain.
- 'textdomain' => '',
- )
- );
-
- /**
- * Callback function to register and enqueue scripts.
- *
- * @param string $content When the callback is used for the render_block filter,
- * the content needs to be returned so the function parameter
- * is to ensure the content exists.
- * @return string Block content.
- */
- $callback = static function( $content, $block ) use ( $args, $block_name ) {
-
- // Sanity check.
- if ( empty( $block['blockName'] ) || $block_name !== $block['blockName'] ) {
- return $content;
- }
-
- // Register the stylesheet.
- if ( ! empty( $args['src'] ) ) {
- wp_register_script( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['in_footer'] );
- }
-
- // Enqueue the stylesheet.
- wp_enqueue_script( $args['handle'] );
-
- // If a textdomain is defined, use it to set the script translations.
- if ( ! empty( $args['textdomain'] ) && in_array( 'wp-i18n', $args['deps'], true ) ) {
- wp_set_script_translations( $args['handle'], $args['textdomain'], $args['domainpath'] );
- }
-
- return $content;
- };
-
- /*
- * The filter's callback here is an anonymous function because
- * using a named function in this case is not possible.
- *
- * The function cannot be unhooked, however, users are still able
- * to dequeue the script registered/enqueued by the callback
- * which is why in this case, using an anonymous function
- * was deemed acceptable.
- */
- add_filter( 'render_block', $callback, 10, 2 );
- }
-}
-
/**
* Allow multiple view scripts per block.
*
diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
index 5c1639d3d2ce6b..bdce96e8ccf5db 100644
--- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
+++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
@@ -25,6 +25,18 @@ class WP_Theme_JSON_6_1 extends WP_Theme_JSON_6_0 {
'button' => array( ':hover', ':focus', ':active', ':visited' ),
);
+ /**
+ * The sources of data this object can represent.
+ *
+ * @var string[]
+ */
+ const VALID_ORIGINS = array(
+ 'default',
+ 'blocks',
+ 'theme',
+ 'custom',
+ );
+
/**
* Metadata for style properties.
*
@@ -119,6 +131,43 @@ class WP_Theme_JSON_6_1 extends WP_Theme_JSON_6_0 {
'typography' => 'typography',
);
+ /**
+ * Constructor.
+ *
+ * @since 5.8.0
+ *
+ * @param array $theme_json A structure that follows the theme.json schema.
+ * @param string $origin Optional. What source of data this object represents.
+ * One of 'default', 'theme', or 'custom'. Default 'theme'.
+ */
+ public function __construct( $theme_json = array(), $origin = 'theme' ) {
+ if ( ! in_array( $origin, static::VALID_ORIGINS, true ) ) {
+ $origin = 'theme';
+ }
+
+ $this->theme_json = WP_Theme_JSON_Schema::migrate( $theme_json );
+ $registry = WP_Block_Type_Registry::get_instance();
+ $valid_block_names = array_keys( $registry->get_all_registered() );
+ $valid_element_names = array_keys( static::ELEMENTS );
+ $theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names );
+ $this->theme_json = static::maybe_opt_in_into_settings( $theme_json );
+
+ // Internally, presets are keyed by origin.
+ $nodes = static::get_setting_nodes( $this->theme_json );
+ foreach ( $nodes as $node ) {
+ foreach ( static::PRESETS_METADATA as $preset_metadata ) {
+ $path = array_merge( $node['path'], $preset_metadata['path'] );
+ $preset = _wp_array_get( $this->theme_json, $path, null );
+ if ( null !== $preset ) {
+ // If the preset is not already keyed by origin.
+ if ( isset( $preset[0] ) || empty( $preset ) ) {
+ _wp_array_set( $this->theme_json, $path, array( $origin => $preset ) );
+ }
+ }
+ }
+ }
+ }
+
/**
* Given an element name, returns a class name.
*
@@ -445,7 +494,7 @@ protected static function get_blocks_metadata() {
static::$blocks_metadata[ $block_name ]['features'] = $features;
}
- // Assign defaults, then overwrite those that the block sets by itself.
+ // Assign defaults, then override those that the block sets by itself.
// If the block selector is compounded, will append the element to each
// individual block selector.
$block_selectors = explode( ',', static::$blocks_metadata[ $block_name ]['selector'] );
@@ -625,9 +674,12 @@ private static function get_block_nodes( $theme_json, $selectors = array() ) {
* 'styles': only the styles section in theme.json.
* 'presets': only the classes for the presets.
* @param array $origins A list of origins to include. By default it includes VALID_ORIGINS.
+ * @param array $options An array of options for now used for internal purposes only (may change without notice).
+ * The options currently supported are 'scope' that makes sure all style are scoped to a given selector,
+ * and root_selector which overwrites and forces a given selector to be used on the root node.
* @return string Stylesheet.
*/
- public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null ) {
+ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null, $options = array() ) {
if ( null === $origins ) {
$origins = static::VALID_ORIGINS;
}
@@ -648,6 +700,27 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
$style_nodes = static::get_style_nodes( $this->theme_json, $blocks_metadata );
$setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata );
+ $root_style_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true );
+ $root_settings_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $setting_nodes, 'selector' ), true );
+
+ if ( ! empty( $options['scope'] ) ) {
+ foreach ( $setting_nodes as &$node ) {
+ $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] );
+ }
+ foreach ( $style_nodes as &$node ) {
+ $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] );
+ }
+ }
+
+ if ( ! empty( $options['root_selector'] ) ) {
+ if ( false !== $root_settings_key ) {
+ $setting_nodes[ $root_settings_key ]['selector'] = $options['root_selector'];
+ }
+ if ( false !== $root_style_key ) {
+ $setting_nodes[ $root_style_key ]['selector'] = $options['root_selector'];
+ }
+ }
+
$stylesheet = '';
if ( in_array( 'variables', $types, true ) ) {
@@ -655,23 +728,30 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
}
if ( in_array( 'styles', $types, true ) ) {
- $root_block_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true );
-
- if ( false !== $root_block_key ) {
- $stylesheet .= $this->get_root_layout_rules( static::ROOT_BLOCK_SELECTOR, $style_nodes[ $root_block_key ] );
+ if ( false !== $root_style_key ) {
+ $stylesheet .= $this->get_root_layout_rules( $style_nodes[ $root_style_key ]['selector'], $style_nodes[ $root_style_key ] );
}
$stylesheet .= $this->get_block_classes( $style_nodes );
} elseif ( in_array( 'base-layout-styles', $types, true ) ) {
+ $root_selector = static::ROOT_BLOCK_SELECTOR;
+ $columns_selector = '.wp-block-columns';
+ if ( ! empty( $options['scope'] ) ) {
+ $root_selector = static::scope_selector( $options['scope'], $root_selector );
+ $columns_selector = static::scope_selector( $options['scope'], $columns_selector );
+ }
+ if ( ! empty( $options['root_selector'] ) ) {
+ $root_selector = $options['root_selector'];
+ }
// Base layout styles are provided as part of `styles`, so only output separately if explicitly requested.
// For backwards compatibility, the Columns block is explicitly included, to support a different default gap value.
$base_styles_nodes = array(
array(
'path' => array( 'styles' ),
- 'selector' => static::ROOT_BLOCK_SELECTOR,
+ 'selector' => $root_selector,
),
array(
'path' => array( 'styles', 'blocks', 'core/columns' ),
- 'selector' => '.wp-block-columns',
+ 'selector' => $columns_selector,
'name' => 'core/columns',
),
);
@@ -1017,7 +1097,7 @@ protected static function get_property_value( $styles, $path, $theme_json = null
if ( is_array( $ref_value ) && array_key_exists( 'ref', $ref_value ) ) {
$path_string = json_encode( $path );
$ref_value_string = json_encode( $ref_value );
- _doing_it_wrong( 'get_property_value', "Your theme.json file uses a dynamic value (${ref_value_string}) for the path at ${path_string}. However, the value at ${path_string} is also a dynamic value (pointing to ${ref_value['ref']}) and pointing to another dynamic value is not supported. Please update ${path_string} to point directly to ${ref_value['ref']}.", '6.1.0' );
+ _doing_it_wrong( 'get_property_value', "Your theme.json file uses a dynamic value ({$ref_value_string}) for the path at {$path_string}. However, the value at {$path_string} is also a dynamic value (pointing to {$ref_value['ref']}) and pointing to another dynamic value is not supported. Please update {$path_string} to point directly to {$ref_value['ref']}.", '6.1.0' );
}
}
@@ -1151,15 +1231,6 @@ protected static function get_property_value( $styles, $path, $theme_json = null
'classes' => array(),
'properties' => array( 'padding', 'margin' ),
),
- array(
- 'path' => array( 'spacing', 'spacingScale' ),
- 'prevent_override' => false,
- 'use_default_names' => true,
- 'value_key' => 'size',
- 'css_vars' => '--wp--preset--spacing--$slug',
- 'classes' => array(),
- 'properties' => array( 'padding', 'margin' ),
- ),
);
/**
@@ -1280,7 +1351,7 @@ public function set_spacing_sizes() {
}
if ( $below_midpoint_count < $steps_mid_point - 2 ) {
- $x_small_count++;
+ ++$x_small_count;
}
$slug -= 10;
@@ -1317,7 +1388,7 @@ public function set_spacing_sizes() {
}
if ( $above_midpoint_count > 1 ) {
- $x_large_count++;
+ ++$x_large_count;
}
$slug += 10;
@@ -1516,4 +1587,45 @@ protected function get_layout_styles( $block_metadata ) {
}
return $block_rules;
}
+
+ /**
+ * Function that scopes a selector with another one. This works a bit like
+ * SCSS nesting except the `&` operator isn't supported.
+ *
+ *
+ * $scope = '.a, .b .c';
+ * $selector = '> .x, .y';
+ * $merged = scope_selector( $scope, $selector );
+ * // $merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
+ *
+ *
+ * @since 5.9.0
+ *
+ * @param string $scope Selector to scope to.
+ * @param string $selector Original selector.
+ * @return string Scoped selector.
+ */
+ public static function scope_selector( $scope, $selector ) {
+ $scopes = explode( ',', $scope );
+ $selectors = explode( ',', $selector );
+
+ $selectors_scoped = array();
+ foreach ( $scopes as $outer ) {
+ foreach ( $selectors as $inner ) {
+ $outer = trim( $outer );
+ $inner = trim( $inner );
+ if ( ! empty( $outer ) && ! empty( $inner ) ) {
+ $selectors_scoped[] = $outer . ' ' . $inner;
+ } elseif ( empty( $outer ) ) {
+ $selectors_scoped[] = $inner;
+ } elseif ( empty( $inner ) ) {
+ $selectors_scoped[] = $outer;
+ }
+ }
+ }
+
+ $result = implode( ', ', $selectors_scoped );
+ return $result;
+ }
+
}
diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php
index ccccdad9a814b9..1837aa04dbb20d 100644
--- a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php
+++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php
@@ -92,14 +92,22 @@ function gutenberg_get_global_stylesheet( $types = array() ) {
/*
* If variables are part of the stylesheet,
- * we add them for all origins (default, theme, user).
+ * we add them.
+ *
* This is so themes without a theme.json still work as before 5.9:
* they can override the default presets.
* See https://core.trac.wordpress.org/ticket/54782
*/
$styles_variables = '';
if ( in_array( 'variables', $types, true ) ) {
- $styles_variables = $tree->get_stylesheet( array( 'variables' ) );
+ /*
+ * We only use the default, theme, and custom origins.
+ * This is because styles for blocks origin are added
+ * at a later phase (render cycle) so we only render the ones in use.
+ * @see wp_add_global_styles_for_blocks
+ */
+ $origins = array( 'default', 'theme', 'custom' );
+ $styles_variables = $tree->get_stylesheet( array( 'variables' ), $origins );
$types = array_diff( $types, array( 'variables' ) );
}
@@ -111,6 +119,12 @@ function gutenberg_get_global_stylesheet( $types = array() ) {
*/
$styles_rest = '';
if ( ! empty( $types ) ) {
+ /*
+ * We only use the default, theme, and custom origins.
+ * This is because styles for blocks origin are added
+ * at a later phase (render cycle) so we only render the ones in use.
+ * @see wp_add_global_styles_for_blocks
+ */
$origins = array( 'default', 'theme', 'custom' );
if ( ! $supports_theme_json ) {
$origins = array( 'default' );
diff --git a/lib/compat/wordpress-6.1/persisted-preferences.php b/lib/compat/wordpress-6.1/persisted-preferences.php
index 2a5211e12596ac..2263820e9911b4 100644
--- a/lib/compat/wordpress-6.1/persisted-preferences.php
+++ b/lib/compat/wordpress-6.1/persisted-preferences.php
@@ -21,11 +21,11 @@ function gutenberg_register_persisted_preferences_meta() {
'type' => 'object',
'single' => true,
'show_in_rest' => array(
- 'name' => 'persisted_preferences',
- 'type' => 'object',
- 'context' => array( 'edit' ),
- 'schema' => array(
+ 'name' => 'persisted_preferences',
+ 'type' => 'object',
+ 'schema' => array(
'type' => 'object',
+ 'context' => array( 'edit' ),
'properties' => array(
'_modified' => array(
'description' => __( 'The date and time the preferences were updated.', 'default' ),
@@ -72,7 +72,6 @@ function gutenberg_configure_persisted_preferences() {
),
'after'
);
-
}
add_action( 'admin_init', 'gutenberg_configure_persisted_preferences' );
diff --git a/lib/compat/wordpress-6.1/script-loader.php b/lib/compat/wordpress-6.1/script-loader.php
index 1d7b12c8fe8352..dc0d7e7dfe0f32 100644
--- a/lib/compat/wordpress-6.1/script-loader.php
+++ b/lib/compat/wordpress-6.1/script-loader.php
@@ -36,73 +36,6 @@ static function () use ( $style ) {
);
}
-/**
- * Fetches, processes and compiles stored core styles, then combines and renders them to the page.
- * Styles are stored via the style engine API.
- *
- * See: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/
- *
- * @param array $options {
- * Optional. An array of options to pass to gutenberg_style_engine_get_stylesheet_from_context(). Default empty array.
- *
- * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
- * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
- * }
- *
- * @return void
- */
-function gutenberg_enqueue_stored_styles( $options = array() ) {
- $is_block_theme = wp_is_block_theme();
- $is_classic_theme = ! $is_block_theme;
-
- /*
- * For block themes, print stored styles in the header.
- * For classic themes, in the footer.
- */
- if (
- ( $is_block_theme && doing_action( 'wp_footer' ) ) ||
- ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) )
- ) {
- return;
- }
-
- $core_styles_keys = array( 'block-supports' );
- $compiled_core_stylesheet = '';
- $style_tag_id = 'core';
- foreach ( $core_styles_keys as $style_key ) {
- // Adds comment if code is prettified to identify core styles sections in debugging.
- $should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
- if ( $should_prettify ) {
- $compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n";
- }
- // Chains core store ids to signify what the styles contain.
- $style_tag_id .= '-' . $style_key;
- $compiled_core_stylesheet .= gutenberg_style_engine_get_stylesheet_from_context( $style_key, $options );
- }
-
- // Combines Core styles.
- if ( ! empty( $compiled_core_stylesheet ) ) {
- wp_register_style( $style_tag_id, false, array(), true, true );
- wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet );
- wp_enqueue_style( $style_tag_id );
- }
-
- // If there are any other stores registered by themes etc, print them out.
- $additional_stores = WP_Style_Engine_CSS_Rules_Store_Gutenberg::get_stores();
- foreach ( array_keys( $additional_stores ) as $store_name ) {
- if ( in_array( $store_name, $core_styles_keys, true ) ) {
- continue;
- }
- $styles = gutenberg_style_engine_get_stylesheet_from_context( $store_name, $options );
- if ( ! empty( $styles ) ) {
- $key = "wp-style-engine-$store_name";
- wp_register_style( $key, false, array(), true, true );
- wp_add_inline_style( $key, $styles );
- wp_enqueue_style( $key );
- }
- }
-}
-
/**
* This applies a filter to the list of style nodes that comes from `get_style_nodes` in WP_Theme_JSON.
* This particular filter removes all of the blocks from the array.
@@ -179,5 +112,19 @@ function gutenberg_enqueue_global_styles() {
// Enqueue global styles, and then block supports styles.
add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles' );
add_action( 'wp_footer', 'gutenberg_enqueue_global_styles', 1 );
-add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_stored_styles' );
-add_action( 'wp_footer', 'gutenberg_enqueue_stored_styles', 1 );
+
+/**
+ * Loads classic theme styles on classic themes.
+ *
+ * This is needed for backwards compatibility for button blocks specifically.
+ */
+function gutenberg_enqueue_classic_theme_styles() {
+ if ( ! wp_is_block_theme() ) {
+ wp_register_style( 'classic-theme-styles', gutenberg_url( 'build/block-library/classic.css' ), array(), true );
+ wp_enqueue_style( 'classic-theme-styles' );
+ }
+}
+// To load classic theme styles on the frontend.
+add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_classic_theme_styles' );
+// To load classic theme styles in the the editor.
+add_action( 'admin_enqueue_scripts', 'gutenberg_enqueue_classic_theme_styles' );
diff --git a/lib/experimental/blocks.php b/lib/experimental/blocks.php
new file mode 100644
index 00000000000000..b789deaba6ed57
--- /dev/null
+++ b/lib/experimental/blocks.php
@@ -0,0 +1,79 @@
+ '',
+ 'src' => '',
+ 'deps' => array(),
+ 'ver' => false,
+ 'in_footer' => false,
+
+ // Additional args to allow translations for the script's textdomain.
+ 'textdomain' => '',
+ )
+ );
+
+ /**
+ * Callback function to register and enqueue scripts.
+ *
+ * @param string $content When the callback is used for the render_block filter,
+ * the content needs to be returned so the function parameter
+ * is to ensure the content exists.
+ * @return string Block content.
+ */
+ $callback = static function( $content, $block ) use ( $args, $block_name ) {
+
+ // Sanity check.
+ if ( empty( $block['blockName'] ) || $block_name !== $block['blockName'] ) {
+ return $content;
+ }
+
+ // Register the stylesheet.
+ if ( ! empty( $args['src'] ) ) {
+ wp_register_script( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['in_footer'] );
+ }
+
+ // Enqueue the stylesheet.
+ wp_enqueue_script( $args['handle'] );
+
+ // If a textdomain is defined, use it to set the script translations.
+ if ( ! empty( $args['textdomain'] ) && in_array( 'wp-i18n', $args['deps'], true ) ) {
+ wp_set_script_translations( $args['handle'], $args['textdomain'], $args['domainpath'] );
+ }
+
+ return $content;
+ };
+
+ /*
+ * The filter's callback here is an anonymous function because
+ * using a named function in this case is not possible.
+ *
+ * The function cannot be unhooked, however, users are still able
+ * to dequeue the script registered/enqueued by the callback
+ * which is why in this case, using an anonymous function
+ * was deemed acceptable.
+ */
+ add_filter( 'render_block', $callback, 10, 2 );
+ }
+}
diff --git a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php
index 643e7e5df9b321..ed36c236228d96 100644
--- a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php
@@ -141,12 +141,10 @@ public static function get_block_data() {
*
* @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data.
*/
- $theme_json = apply_filters( 'theme_json_blocks', new WP_Theme_JSON_Data_Gutenberg( $config, 'core' ) );
+ $theme_json = apply_filters( 'theme_json_blocks', new WP_Theme_JSON_Data_Gutenberg( $config, 'blocks' ) );
$config = $theme_json->get_data();
- // Core here means it's the lower level part of the styles chain.
- // It can be a core or a third-party block.
- return new WP_Theme_JSON_Gutenberg( $config, 'core' );
+ return new WP_Theme_JSON_Gutenberg( $config, 'blocks' );
}
/**
diff --git a/lib/experimental/class-wp-webfonts.php b/lib/experimental/class-wp-webfonts.php
index e422f51658befb..02083d50cabc15 100644
--- a/lib/experimental/class-wp-webfonts.php
+++ b/lib/experimental/class-wp-webfonts.php
@@ -244,7 +244,7 @@ public function validate_webfont( $webfont ) {
}
// Check the font-display.
- if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'swap' ), true ) ) {
+ if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'swap', 'optional' ), true ) ) {
$webfont['font-display'] = 'fallback';
}
diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php
index c93214385752b9..2b46a401d4b0e9 100644
--- a/lib/experimental/editor-settings.php
+++ b/lib/experimental/editor-settings.php
@@ -70,7 +70,6 @@ function gutenberg_initialize_editor( $editor_name, $editor_script_handle, $sett
'wp-blocks',
'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
);
-
}
/**
diff --git a/lib/experimental/html/class-wp-html-attribute-token.php b/lib/experimental/html/class-wp-html-attribute-token.php
new file mode 100644
index 00000000000000..7b3d5718723581
--- /dev/null
+++ b/lib/experimental/html/class-wp-html-attribute-token.php
@@ -0,0 +1,89 @@
+name = $name;
+ $this->value_starts_at = $value_start;
+ $this->value_length = $value_length;
+ $this->start = $start;
+ $this->end = $end;
+ $this->is_true = $is_true;
+ }
+}
diff --git a/lib/experimental/html/class-wp-html-tag-processor.php b/lib/experimental/html/class-wp-html-tag-processor.php
new file mode 100644
index 00000000000000..e66b5dd415cb11
--- /dev/null
+++ b/lib/experimental/html/class-wp-html-tag-processor.php
@@ -0,0 +1,1466 @@
+ "c" not " c"
+ * @TODO: Skip over `/` in attributes area, split attribute names by `/`
+ * @TODO: Decode HTML references/entities in class names when matching.
+ * E.g. match having class `1<"2` needs to recognize `class="1<"2"`.
+ * @TODO: Decode character references in `get_attribute()`
+ * @TODO: Properly escape attribute value in `set_attribute()`
+ * @TODO: Add slow mode to escape character entities in CSS class names?
+ * (This requires a custom decoder since `html_entity_decode()`
+ * doesn't handle attribute character reference decoding rules.
+ *
+ * @package WordPress
+ * @subpackage HTML
+ * @since 6.2.0
+ */
+
+/**
+ * Processes an input HTML document by applying a specified set
+ * of patches to that input. Tokenizes HTML but does not fully
+ * parse the input document.
+ *
+ * ## Usage
+ *
+ * Use of this class requires three steps:
+ *
+ * 1. Create a new class instance with your input HTML document.
+ * 2. Find the tag(s) you are looking for.
+ * 3. Request changes to the attributes in those tag(s).
+ *
+ * Example:
+ * ```php
+ * $tags = new WP_HTML_Tag_Processor( $html );
+ * if ( $tags->next_tag( [ 'tag_name' => 'option' ] ) ) {
+ * $tags->set_attribute( 'selected', true );
+ * }
+ * ```
+ *
+ * ### Finding tags
+ *
+ * The `next_tag()` function moves the internal cursor through
+ * your input HTML document until it finds a tag meeting any of
+ * the supplied restrictions in the optional query argument. If
+ * no argument is provided then it will find the next HTML tag,
+ * regardless of what kind it is.
+ *
+ * If you want to _find whatever the next tag is_:
+ * ```php
+ * $tags->next_tag();
+ * ```
+ *
+ * | Goal | Query |
+ * |-----------------------------------------------------------|----------------------------------------------------------------------------|
+ * | Find any tag. | `$tags->next_tag();` |
+ * | Find next image tag. | `$tags->next_tag( [ 'tag_name' => 'img' ] );` |
+ * | Find next tag containing the `fullwidth` CSS class. | `$tags->next_tag( [ 'class_name' => 'fullwidth' ] );` |
+ * | Find next image tag containing the `fullwidth` CSS class. | `$tags->next_tag( [ 'tag_name' => 'img', 'class_name' => 'fullwidth' ] );` |
+ *
+ * If a tag was found meeting your criteria then `next_tag()`
+ * will return `true` and you can proceed to modify it. If it
+ * returns `false`, however, it failed to find the tag and
+ * moved the cursor to the end of the file.
+ *
+ * Once the cursor reaches the end of the file the processor
+ * is done and if you want to reach an earlier tag you will
+ * need to recreate the processor and start over. The internal
+ * cursor can only proceed forward, never backing up.
+ *
+ * #### Custom queries
+ *
+ * Sometimes it's necessary to further inspect an HTML tag than
+ * the query syntax here permits. In these cases one may further
+ * inspect the search results using the read-only functions
+ * provided by the processor or external state or variables.
+ *
+ * Example:
+ * ```php
+ * // Paint up to the first five DIV or SPAN tags marked with the "jazzy" style.
+ * $remaining_count = 5;
+ * while ( $remaining_count > 0 && $tags->next_tag() ) {
+ * if (
+ * ( 'DIV' === $tags->get_tag() || 'SPAN' === $tags->get_tag() ) &&
+ * 'jazzy' === $tags->get_attribute( 'data-style' )
+ * ) {
+ * $tags->add_class( 'theme-style-everest-jazz' );
+ * $remaining_count--;
+ * }
+ * }
+ * ```
+ *
+ * `get_attribute()` will return `null` if the attribute wasn't present
+ * on the tag when it was called. It may return `""` (the empty string)
+ * in cases where the attribute was present but its value was empty.
+ * For boolean attributes, those whose name is present but no value is
+ * given, it will return `true` (the only way to set `false` for an
+ * attribute is to remove it).
+ *
+ * ### Modifying HTML attributes for a found tag
+ *
+ * Once you've found the start of an opening tag you can modify
+ * any number of the attributes on that tag. You can set a new
+ * value for an attribute, remove the entire attribute, or do
+ * nothing and move on to the next opening tag.
+ *
+ * Example:
+ * ```php
+ * if ( $tags->next_tag( [ 'class' => 'wp-group-block' ] ) ) {
+ * $tags->set_attribute( 'title', 'This groups the contained content.' );
+ * $tags->remove_attribute( 'data-test-id' );
+ * }
+ * ```
+ *
+ * If `set_attribute()` is called for an existing attribute it will
+ * overwrite the existing value. Similarly, calling `remove_attribute()`
+ * for a non-existing attribute has no effect on the document. Both
+ * of these methods are safe to call without knowing if a given attribute
+ * exists beforehand.
+ *
+ * ### Modifying CSS classes for a found tag
+ *
+ * The tag processor treats the `class` attribute as a special case.
+ * Because it's a common operation to add or remove CSS classes you
+ * can do so using this interface.
+ *
+ * As with attribute values, adding or removing CSS classes is a safe
+ * operation that doesn't require checking if the attribute or class
+ * exists before making changes. If removing the only class then the
+ * entire `class` attribute will be removed.
+ *
+ * Example:
+ * ```php
+ * // from `Yippee! `
+ * // to `Yippee! `
+ * $tags->add_class( 'is-active' );
+ *
+ * // from `Yippee! `
+ * // to `Yippee! `
+ * $tags->add_class( 'is-active' );
+ *
+ * // from `Yippee! `
+ * // to `Yippee! `
+ * $tags->add_class( 'is-active' );
+ *
+ * // from ` `
+ * // to `
+ * $tags->remove_class( 'rugby' );
+ *
+ * // from ` `
+ * // to `
+ * $tags->remove_class( 'rugby' );
+ *
+ * // from ` `
+ * // to `
+ * $tags->remove_class( 'rugby' );
+ * ```
+ *
+ * ## Design limitations
+ *
+ * @TODO: Expand this section
+ *
+ * - no nesting: cannot match open and close tag
+ * - only move forward, never backward
+ * - class names not decoded if they contain character references
+ * - only secures against HTML escaping issues; requires
+ * manually sanitizing or escaping values based on the needs of
+ * each individual attribute, since different attributes have
+ * different needs.
+ *
+ * @since 6.2.0
+ */
+class WP_HTML_Tag_Processor {
+
+ /**
+ * The HTML document to parse.
+ *
+ * @since 6.2.0
+ * @var string
+ */
+ private $html;
+
+ /**
+ * The last query passed to next_tag().
+ *
+ * @since 6.2.0
+ * @var array|null
+ */
+ private $last_query;
+
+ /**
+ * The tag name this processor currently scans for.
+ *
+ * @since 6.2.0
+ * @var string|null
+ */
+ private $sought_tag_name;
+
+ /**
+ * The CSS class name this processor currently scans for.
+ *
+ * @since 6.2.0
+ * @var string|null
+ */
+ private $sought_class_name;
+
+ /**
+ * The match offset this processor currently scans for.
+ *
+ * @since 6.2.0
+ * @var int|null
+ */
+ private $sought_match_offset;
+
+ /**
+ * The updated HTML document.
+ *
+ * @since 6.2.0
+ * @var string
+ */
+ private $updated_html = '';
+
+ /**
+ * How many bytes from the original HTML document were already read.
+ *
+ * @since 6.2.0
+ * @var int
+ */
+ private $parsed_bytes = 0;
+
+ /**
+ * How many bytes from the original HTML document were already treated
+ * with the requested replacements.
+ *
+ * @since 6.2.0
+ * @var int
+ */
+ private $updated_bytes = 0;
+
+ /**
+ * Byte offset in input document where current tag name starts.
+ *
+ * Example:
+ * ```
+ * ...
+ * 01234
+ * - tag name starts at 1
+ * ```
+ *
+ * @since 6.2.0
+ * @var ?int
+ */
+ private $tag_name_starts_at;
+
+ /**
+ * Byte length of current tag name.
+ *
+ * Example:
+ * ```
+ *
...
+ * 01234
+ * --- tag name length is 3
+ * ```
+ *
+ * @since 6.2.0
+ * @var ?int
+ */
+ private $tag_name_length;
+
+ /**
+ * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name.
+ *
+ * Example:
+ *
+ * // supposing the parser is working through this content
+ * // and stops after recognizing the `id` attribute
+ * //
+ * // ^ parsing will continue from this point
+ * $this->attributes = [
+ * 'id' => new WP_HTML_Attribute_Match( 'id', null, 6, 17 )
+ * ];
+ *
+ * // when picking up parsing again, or when asking to find the
+ * // `class` attribute we will continue and add to this array
+ * $this->attributes = [
+ * 'id' => new WP_HTML_Attribute_Match( 'id', null, 6, 17 ),
+ * 'class' => new WP_HTML_Attribute_Match( 'class', 'outline', 18, 32 )
+ * ];
+ *
+ * // Note that only the `class` attribute value is stored in the index.
+ * // That's because it is the only value used by this class at the moment.
+ *
+ *
+ * @since 6.2.0
+ * @var WP_HTML_Attribute_Token[]
+ */
+ private $attributes = array();
+
+ /**
+ * Which class names to add or remove from a tag.
+ *
+ * These are tracked separately from attribute updates because they are
+ * semantically distinct, whereas this interface exists for the common
+ * case of adding and removing class names while other attributes are
+ * generally modified as with DOM `setAttribute` calls.
+ *
+ * When modifying an HTML document these will eventually be collapsed
+ * into a single lexical update to replace the `class` attribute.
+ *
+ * Example:
+ *
+ * // Add the `WP-block-group` class, remove the `WP-group` class.
+ * $class_changes = [
+ * // Indexed by a comparable class name
+ * 'wp-block-group' => new WP_Class_Name_Operation( 'WP-block-group', WP_Class_Name_Operation::ADD ),
+ * 'wp-group' => new WP_Class_Name_Operation( 'WP-group', WP_Class_Name_Operation::REMOVE )
+ * ];
+ *
+ *
+ * @since 6.2.0
+ * @var bool[]
+ */
+ private $classname_updates = array();
+
+ const ADD_CLASS = true;
+ const REMOVE_CLASS = false;
+ const SKIP_CLASS = null;
+
+ /**
+ * Lexical replacements to apply to input HTML document.
+ *
+ * HTML modifications collapse into lexical replacements in order to
+ * provide an efficient mechanism to update documents lazily and in
+ * order to support a variety of semantic modifications without
+ * building a complicated parsing machinery. That is, it's up to
+ * the calling class to generate the lexical modification from the
+ * semantic change requested.
+ *
+ * Example:
+ *
+ * // Replace an attribute stored with a new value, indices
+ * // sourced from the lazily-parsed HTML recognizer.
+ * $start = $attributes['src']->start;
+ * $end = $attributes['src']->end;
+ * $modifications[] = new WP_HTML_Text_Replacement( $start, $end, get_the_post_thumbnail_url() );
+ *
+ * // Correspondingly, something like this
+ * // will appear in the replacements array.
+ * $replacements = [
+ * WP_HTML_Text_Replacement( 14, 28, 'https://my-site.my-domain/wp-content/uploads/2014/08/kittens.jpg' )
+ * ];
+ *
+ *
+ * @since 6.2.0
+ * @var WP_HTML_Text_Replacement[]
+ */
+ private $attribute_updates = array();
+
+ /**
+ * Constructor.
+ *
+ * @since 6.2.0
+ *
+ * @param string $html HTML to process.
+ */
+ public function __construct( $html ) {
+ $this->html = $html;
+ }
+
+ /**
+ * Finds the next tag matching the $query.
+ *
+ * @since 6.2.0
+ *
+ * @param array|string $query {
+ * Which tag name to find, having which class, etc.
+ *
+ * @type string|null $tag_name Which tag to find, or `null` for "any tag."
+ * @type int|null $match_offset Find the Nth tag matching all search criteria.
+ * 0 for "first" tag, 2 for "third," etc.
+ * Defaults to first tag.
+ * @type string|null $class_name Tag must contain this whole class name to match.
+ * }
+ * @return boolean Whether a tag was matched.
+ */
+ public function next_tag( $query = null ) {
+ $this->parse_query( $query );
+ $already_found = 0;
+
+ do {
+ /*
+ * Unfortunately we can't try to search for only the tag name we want because that might
+ * lead us to skip over other tags and lose track of our place. So we need to search for
+ * _every_ tag and then check after we find one if it's the one we are looking for.
+ */
+ if ( false === $this->parse_next_tag() ) {
+ $this->parsed_bytes = strlen( $this->html );
+
+ return false;
+ }
+
+ $this->parse_tag_opener_attributes();
+
+ if ( $this->matches() ) {
+ ++$already_found;
+ }
+
+ // Avoid copying the tag name string when possible.
+ $t = $this->html[ $this->tag_name_starts_at ];
+ if ( 's' === $t || 'S' === $t || 't' === $t || 'T' === $t ) {
+ $tag_name = $this->get_tag();
+
+ if ( 'SCRIPT' === $tag_name ) {
+ $this->skip_script_data();
+ } elseif ( 'TEXTAREA' === $tag_name || 'TITLE' === $tag_name ) {
+ $this->skip_rcdata( $tag_name );
+ }
+ }
+ } while ( $already_found < $this->sought_match_offset );
+
+ return true;
+ }
+
+ /**
+ * Skips the contents of the title and textarea tags until an appropriate
+ * tag closer is found.
+ *
+ * @see https://html.spec.whatwg.org/multipage/parsing.html#rcdata-state
+ * @param string $tag_name – the lowercase tag name which will close the RCDATA region.
+ * @since 6.2.0
+ */
+ private function skip_rcdata( $tag_name ) {
+ $html = $this->html;
+ $doc_length = strlen( $html );
+ $tag_length = strlen( $tag_name );
+
+ $at = $this->parsed_bytes;
+
+ while ( true ) {
+ $at = strpos( $this->html, '', $at );
+
+ // If we have no possible tag closer then fail.
+ if ( false === $at || ( $at + $tag_length ) > $doc_length ) {
+ $this->parsed_bytes = $doc_length;
+ return;
+ }
+
+ $at += 2;
+
+ /*
+ * We have to find a case-insensitive match to the tag name.
+ * Note also that since tag names are limited to US-ASCII
+ * characters we can ignore any kind of Unicode normalizing
+ * forms when comparing. If we get a non-ASCII character it
+ * will never be a match.
+ */
+ for ( $i = 0; $i < $tag_length; $i++ ) {
+ $tag_char = $tag_name[ $i ];
+ $html_char = $html[ $at + $i ];
+
+ if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) {
+ $at += $i;
+ continue 2;
+ }
+ }
+
+ $at += $tag_length;
+ $this->parsed_bytes = $at;
+
+ /*
+ * Ensure we terminate the tag name, otherwise we might,
+ * for example, accidentally match the sequence
+ * "" for "".
+ */
+ $c = $html[ $at ];
+ if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) {
+ continue;
+ }
+
+ $this->skip_tag_closer_attributes();
+ $at = $this->parsed_bytes;
+
+ if ( '>' === $html[ $at ] || '/' === $html[ $at ] ) {
+ ++$this->parsed_bytes;
+ return;
+ }
+ }
+ }
+
+ /**
+ * Skips the contents of tags, so if we're not seeing the
+ * start of one of these tokens we can proceed to the next
+ * potential match in the text.
+ */
+ if ( ! (
+ $at + 6 < $doc_length &&
+ ( 's' === $html[ $at ] || 'S' === $html[ $at ] ) &&
+ ( 'c' === $html[ $at + 1 ] || 'C' === $html[ $at + 1 ] ) &&
+ ( 'r' === $html[ $at + 2 ] || 'R' === $html[ $at + 2 ] ) &&
+ ( 'i' === $html[ $at + 3 ] || 'I' === $html[ $at + 3 ] ) &&
+ ( 'p' === $html[ $at + 4 ] || 'P' === $html[ $at + 4 ] ) &&
+ ( 't' === $html[ $at + 5 ] || 'T' === $html[ $at + 5 ] )
+ ) ) {
+ ++$at;
+ continue;
+ }
+
+ /*
+ * We also have to make sure we terminate the script tag opener/closer
+ * to avoid making partial matches on strings like `
' !== $c ) {
+ ++$at;
+ continue;
+ }
+
+ if ( 'escaped' === $state && ! $is_closing ) {
+ $state = 'double-escaped';
+ continue;
+ }
+
+ if ( 'double-escaped' === $state && $is_closing ) {
+ $state = 'escaped';
+ continue;
+ }
+
+ if ( $is_closing ) {
+ $this->parsed_bytes = $at;
+ $this->skip_tag_closer_attributes();
+
+ if ( '>' === $html[ $this->parsed_bytes ] ) {
+ ++$this->parsed_bytes;
+ return;
+ }
+ }
+
+ ++$at;
+ }
+ }
+
+ /**
+ * Parses the next tag.
+ *
+ * @since 6.2.0
+ */
+ private function parse_next_tag() {
+ $this->after_tag();
+
+ $html = $this->html;
+ $at = $this->parsed_bytes;
+
+ while ( true ) {
+ $at = strpos( $html, '<', $at );
+ if ( false === $at ) {
+ return false;
+ }
+
+ /*
+ * HTML tag names must start with [a-zA-Z] otherwise they are not tags.
+ * For example, "<3" is rendered as text, not a tag opener. This means
+ * if we have at least one letter following the "<" then we _do_ have
+ * a tag opener and can process it as such. This is more common than
+ * HTML comments, DOCTYPE tags, and other structure starting with "<"
+ * so it's good to check first for the presence of the tag.
+ *
+ * Reference:
+ * * https://html.spec.whatwg.org/multipage/parsing.html#data-state
+ * * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
+ */
+ $tag_name_prefix_length = strspn( $html, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $at + 1 );
+ if ( $tag_name_prefix_length > 0 ) {
+ ++$at;
+ $this->tag_name_length = $tag_name_prefix_length + strcspn( $html, " \t\f\r\n/>", $at + $tag_name_prefix_length );
+ $this->tag_name_starts_at = $at;
+ $this->parsed_bytes = $at + $this->tag_name_length;
+ return true;
+ }
+
+ //
+ // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
+ if (
+ strlen( $html ) > $at + 3 &&
+ '-' === $html[ $at + 2 ] &&
+ '-' === $html[ $at + 3 ]
+ ) {
+ $at = strpos( $html, '-->', $at + 4 ) + 3;
+ continue;
+ }
+
+ //
+ // The CDATA is case-sensitive.
+ // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
+ if (
+ strlen( $html ) > $at + 8 &&
+ '[' === $html[ $at + 2 ] &&
+ 'C' === $html[ $at + 3 ] &&
+ 'D' === $html[ $at + 4 ] &&
+ 'A' === $html[ $at + 5 ] &&
+ 'T' === $html[ $at + 6 ] &&
+ 'A' === $html[ $at + 7 ] &&
+ '[' === $html[ $at + 8 ]
+ ) {
+ $at = strpos( $html, ']]>', $at + 9 ) + 3;
+ continue;
+ }
+
+ /*
+ *
+ * These are ASCII-case-insensitive.
+ * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
+ */
+ if (
+ strlen( $html ) > $at + 8 &&
+ 'D' === strtoupper( $html[ $at + 2 ] ) &&
+ 'O' === strtoupper( $html[ $at + 3 ] ) &&
+ 'C' === strtoupper( $html[ $at + 4 ] ) &&
+ 'T' === strtoupper( $html[ $at + 5 ] ) &&
+ 'Y' === strtoupper( $html[ $at + 6 ] ) &&
+ 'P' === strtoupper( $html[ $at + 7 ] ) &&
+ 'E' === strtoupper( $html[ $at + 8 ] )
+ ) {
+ $at = strpos( $html, '>', $at + 9 ) + 1;
+ continue;
+ }
+
+ /*
+ * Anything else here is an incorrectly-opened comment and transitions
+ * to the bogus comment state - we can skip to the nearest >.
+ */
+ $at = strpos( $html, '>', $at + 1 );
+ continue;
+ }
+
+ /*
+ * transitions to a bogus comment state – we can skip to the nearest >
+ * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
+ */
+ if ( '?' === $html[ $at + 1 ] ) {
+ $at = strpos( $html, '>', $at + 2 ) + 1;
+ continue;
+ }
+
+ ++$at;
+ }
+ }
+
+ /**
+ * Parses all attributes of the current tag.
+ *
+ * @since 6.2.0
+ */
+ private function parse_tag_opener_attributes() {
+ while ( $this->parse_next_attribute() ) {
+ continue;
+ }
+ }
+
+ /**
+ * Skips all attributes of the current tag.
+ *
+ * @since 6.2.0
+ */
+ private function skip_tag_closer_attributes() {
+ while ( $this->parse_next_attribute( 'tag-closer' ) ) {
+ continue;
+ }
+ }
+
+ /**
+ * Parses the next attribute.
+ *
+ * @param string $context tag-opener or tag-closer.
+ * @since 6.2.0
+ */
+ private function parse_next_attribute( $context = 'tag-opener' ) {
+ // Skip whitespace and slashes.
+ $this->parsed_bytes += strspn( $this->html, " \t\f\r\n/", $this->parsed_bytes );
+
+ /*
+ * Treat the equal sign ("=") as a part of the attribute name if it is the
+ * first encountered byte:
+ * https://html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state
+ */
+ $name_length = '=' === $this->html[ $this->parsed_bytes ]
+ ? 1 + strcspn( $this->html, "=/> \t\f\r\n", $this->parsed_bytes + 1 )
+ : strcspn( $this->html, "=/> \t\f\r\n", $this->parsed_bytes );
+
+ // No attribute, just tag closer.
+ if ( 0 === $name_length ) {
+ return false;
+ }
+
+ $attribute_start = $this->parsed_bytes;
+ $attribute_name = substr( $this->html, $attribute_start, $name_length );
+ $this->parsed_bytes += $name_length;
+
+ $this->skip_whitespace();
+
+ $has_value = '=' === $this->html[ $this->parsed_bytes ];
+ if ( $has_value ) {
+ ++$this->parsed_bytes;
+ $this->skip_whitespace();
+
+ switch ( $this->html[ $this->parsed_bytes ] ) {
+ case "'":
+ case '"':
+ $quote = $this->html[ $this->parsed_bytes ];
+ $value_start = $this->parsed_bytes + 1;
+ $value_length = strcspn( $this->html, $quote, $value_start );
+ $attribute_end = $value_start + $value_length + 1;
+ $this->parsed_bytes = $attribute_end;
+ break;
+
+ default:
+ $value_start = $this->parsed_bytes;
+ $value_length = strcspn( $this->html, "> \t\f\r\n", $value_start );
+ $attribute_end = $value_start + $value_length;
+ $this->parsed_bytes = $attribute_end;
+ }
+ } else {
+ $value_start = $this->parsed_bytes;
+ $value_length = 0;
+ $attribute_end = $attribute_start + $name_length;
+ }
+
+ if ( 'tag-opener' !== $context ) {
+ return true;
+ }
+
+ // If an attribute is listed many times, only use the first declaration and ignore the rest.
+ if ( ! array_key_exists( $attribute_name, $this->attributes ) ) {
+ $this->attributes[ $attribute_name ] = new WP_HTML_Attribute_Token(
+ $attribute_name,
+ $value_start,
+ $value_length,
+ $attribute_start,
+ $attribute_end,
+ ! $has_value
+ );
+ }
+
+ return $this->attributes[ $attribute_name ];
+ }
+
+ /**
+ * Move the pointer past any immediate successive whitespace.
+ *
+ * @since 6.2.0
+ *
+ * @return void
+ */
+ private function skip_whitespace() {
+ $this->parsed_bytes += strspn( $this->html, " \t\f\r\n", $this->parsed_bytes );
+ }
+
+ /**
+ * Applies attribute updates and cleans up once a tag is fully parsed.
+ *
+ * @since 6.2.0
+ *
+ * @return void
+ */
+ private function after_tag() {
+ $this->class_name_updates_to_attributes_updates();
+ $this->apply_attributes_updates();
+ $this->tag_name_starts_at = null;
+ $this->tag_name_length = null;
+ $this->attributes = array();
+ }
+
+ /**
+ * Converts class name updates into tag attributes updates
+ * (they are accumulated in different data formats for performance).
+ *
+ * This method is only meant to run right before the attribute updates are applied.
+ * The behavior in all other cases is undefined.
+ *
+ * @return void
+ * @since 6.2.0
+ *
+ * @see $classname_updates
+ * @see $attribute_updates
+ */
+ private function class_name_updates_to_attributes_updates() {
+ if ( count( $this->classname_updates ) === 0 || isset( $this->attribute_updates['class'] ) ) {
+ $this->classname_updates = array();
+ return;
+ }
+
+ $existing_class = isset( $this->attributes['class'] )
+ ? substr( $this->html, $this->attributes['class']->value_starts_at, $this->attributes['class']->value_length )
+ : '';
+
+ /**
+ * Updated "class" attribute value.
+ *
+ * This is incrementally built as we scan through the existing class
+ * attribute, omitting removed classes as we do so, and then appending
+ * added classes at the end. Only when we're done processing will the
+ * value contain the final new value.
+
+ * @var string
+ */
+ $class = '';
+
+ /**
+ * Tracks the cursor position in the existing class
+ * attribute value where we're currently parsing.
+ *
+ * @var integer
+ */
+ $at = 0;
+
+ /**
+ * Indicates if we have made any actual modifications to the existing
+ * class attribute value, used to short-circuit string copying.
+ *
+ * It's possible that we are intending to remove certain classes and
+ * add others in such a way that we don't modify the existing value
+ * because calls to `add_class()` and `remove_class()` occur
+ * independent of the input values sent to the WP_HTML_Tag_Processor. That is, we
+ * might call `remove_class()` for a class that isn't already present
+ * and we might call `add_class()` for one that is, in which case we
+ * wouldn't need to break apart the string and rebuild it.
+ *
+ * This flag is set upon the first change that requires a string update.
+ *
+ * @var boolean
+ */
+ $modified = false;
+
+ // Remove unwanted classes by only copying the new ones.
+ while ( $at < strlen( $existing_class ) ) {
+ // Skip to the first non-whitespace character.
+ $ws_at = $at;
+ $ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at );
+ $at += $ws_length;
+
+ // Capture the class name – it's everything until the next whitespace.
+ $name_length = strcspn( $existing_class, " \t\f\r\n", $at );
+ if ( 0 === $name_length ) {
+ // We're done, no more class names.
+ break;
+ }
+
+ $name = substr( $existing_class, $at, $name_length );
+ $at += $name_length;
+
+ // If this class is marked for removal, start processing the next one.
+ $remove_class = (
+ isset( $this->classname_updates[ $name ] ) &&
+ self::REMOVE_CLASS === $this->classname_updates[ $name ]
+ );
+
+ // Once we've seen a class, we should never add it again.
+ if ( ! $remove_class ) {
+ $this->classname_updates[ $name ] = self::SKIP_CLASS;
+ }
+
+ if ( $remove_class ) {
+ $modified = true;
+ continue;
+ }
+
+ /*
+ * Otherwise, append it to the new "class" attribute value.
+ *
+ * By preserving the existing whitespace instead of only adding a single
+ * space (which is a valid transformation we can make) we'll introduce
+ * fewer changes to the HTML content and hopefully make comparing
+ * before/after easier for people trying to debug the modified output.
+ */
+ $class .= substr( $existing_class, $ws_at, $ws_length );
+ $class .= $name;
+ }
+
+ // Add new classes by appending the ones we haven't already seen.
+ foreach ( $this->classname_updates as $name => $operation ) {
+ if ( self::ADD_CLASS === $operation ) {
+ $modified = true;
+
+ $class .= strlen( $class ) > 0 ? ' ' : '';
+ $class .= $name;
+ }
+ }
+
+ $this->classname_updates = array();
+ if ( ! $modified ) {
+ return;
+ }
+
+ if ( strlen( $class ) > 0 ) {
+ $this->set_attribute( 'class', $class );
+ } else {
+ $this->remove_attribute( 'class' );
+ }
+ }
+
+ /**
+ * Applies updates to attributes.
+ *
+ * @since 6.2.0
+ */
+ private function apply_attributes_updates() {
+ if ( ! count( $this->attribute_updates ) ) {
+ return;
+ }
+
+ /**
+ * Attribute updates can be enqueued in any order but as we
+ * progress through the document to replace them we have to
+ * make our replacements in the order in which they are found
+ * in that document.
+ *
+ * Sorting the updates ensures we don't make our replacements
+ * out of order, which could otherwise lead to mangled output,
+ * partially-duplicate attributes, and overwritten attributes.
+ */
+ usort( $this->attribute_updates, array( self::class, 'sort_start_ascending' ) );
+
+ foreach ( $this->attribute_updates as $diff ) {
+ $this->updated_html .= substr( $this->html, $this->updated_bytes, $diff->start - $this->updated_bytes );
+ $this->updated_html .= $diff->text;
+ $this->updated_bytes = $diff->end;
+ }
+
+ $this->attribute_updates = array();
+ }
+
+ /**
+ * Sort function to arrange objects with a start property in ascending order.
+ *
+ * @since 6.2.0
+ *
+ * @param object $a First attribute update.
+ * @param object $b Second attribute update.
+ * @return integer
+ */
+ private static function sort_start_ascending( $a, $b ) {
+ return $a->start - $b->start;
+ }
+
+ /**
+ * Returns the value of the parsed attribute in the currently-opened tag.
+ *
+ * Example:
+ *
+ * $p = new WP_HTML_Tag_Processor( 'Test
' );
+ * $p->next_tag( [ 'class_name' => 'test' ] ) === true;
+ * $p->get_attribute( 'data-test-id' ) === '14';
+ * $p->get_attribute( 'enabled' ) === true;
+ * $p->get_attribute( 'aria-label' ) === null;
+ *
+ * $p->next_tag( [] ) === false;
+ * $p->get_attribute( 'class' ) === null;
+ *
+ *
+ * @since 6.2.0
+ *
+ * @param string $name Name of attribute whose value is requested.
+ * @return string|true|null Value of attribute or `null` if not available.
+ * Boolean attributes return `true`.
+ */
+ public function get_attribute( $name ) {
+ if ( null === $this->tag_name_starts_at ) {
+ return null;
+ }
+
+ $comparable = strtolower( $name );
+ if ( ! isset( $this->attributes[ $comparable ] ) ) {
+ return null;
+ }
+
+ $attribute = $this->attributes[ $comparable ];
+
+ if ( true === $attribute->is_true ) {
+ return true;
+ }
+
+ $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length );
+
+ return html_entity_decode( $raw_value );
+ }
+
+ /**
+ * Returns the lowercase name of the currently-opened tag.
+ *
+ * Example:
+ *
+ * $p = new WP_HTML_Tag_Processor( 'Test
' );
+ * $p->next_tag( [] ) === true;
+ * $p->get_tag() === 'DIV';
+ *
+ * $p->next_tag( [] ) === false;
+ * $p->get_tag() === null;
+ *
+ *
+ * @since 6.2.0
+ *
+ * @return string|null Name of current tag in input HTML, or `null` if none currently open.
+ */
+ public function get_tag() {
+ if ( null === $this->tag_name_starts_at ) {
+ return null;
+ }
+
+ $tag_name = substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length );
+
+ return strtoupper( $tag_name );
+ }
+
+ /**
+ * Updates or creates a new attribute on the currently matched tag with the value passed.
+ *
+ * For boolean attributes special handling is provided:
+ * - When `true` is passed as the value, then only the attribute name is added to the tag.
+ * - When `false` is passed, the attribute gets removed if it existed before.
+ *
+ * For string attributes, the value is escaped using the `esc_attr` function.
+ *
+ * @since 6.2.0
+ *
+ * @param string $name The attribute name to target.
+ * @param string|boolean $value The new attribute value.
+ * @throws Exception When WP_DEBUG is true and the attribute name is invalid.
+ */
+ public function set_attribute( $name, $value ) {
+ if ( null === $this->tag_name_starts_at ) {
+ return;
+ }
+
+ /*
+ * Verify that the attribute name is allowable. In WP_DEBUG
+ * environments we want to crash quickly to alert developers
+ * of typos and issues; but in production we don't want to
+ * interrupt a normal page view, so we'll silently avoid
+ * updating the attribute in those cases.
+ *
+ * Of note, we're disallowing more characters than are strictly
+ * forbidden in HTML5. This is to prevent additional security
+ * risks deeper in the WordPress and plugin stack. Specifically
+ * we reject the less-than (<) greater-than (>) and ampersand (&).
+ *
+ * The use of a PCRE match allows us to look for specific Unicode
+ * code points without writing a UTF-8 decoder. Whereas scanning
+ * for one-byte characters is trivial (with `strcspn`), scanning
+ * for the longer byte sequences would be more complicated, and
+ * this shouldn't be in the hot path for execution so we can
+ * compromise on the efficiency at this point.
+ *
+ * @see https://html.spec.whatwg.org/#attributes-2
+ */
+ if ( preg_match(
+ '~[' .
+ // Syntax-like characters.
+ '"\'>& =' .
+ // Control characters.
+ '\x{00}-\x{1F}' .
+ // HTML noncharacters.
+ '\x{FDD0}-\x{FDEF}' .
+ '\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}' .
+ '\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}' .
+ '\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}' .
+ '\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}' .
+ '\x{10FFFE}\x{10FFFF}' .
+ ']~Ssu',
+ $name
+ ) ) {
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
+ throw new Exception( 'Invalid attribute name' );
+ }
+
+ return;
+ }
+
+ /*
+ * > The values "true" and "false" are not allowed on boolean attributes.
+ * > To represent a false value, the attribute has to be omitted altogether.
+ * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes
+ */
+ if ( false === $value ) {
+ $this->remove_attribute( $name );
+ return;
+ }
+
+ if ( true === $value ) {
+ $updated_attribute = $name;
+ } else {
+ $escaped_new_value = esc_attr( $value );
+ $updated_attribute = "{$name}=\"{$escaped_new_value}\"";
+ }
+
+ if ( isset( $this->attributes[ $name ] ) ) {
+ /*
+ * Update an existing attribute.
+ *
+ * Example – set attribute id to "new" in
:
+ *
+ * ^-------------^
+ * start end
+ * replacement: `id="new"`
+ *
+ * Result:
+ */
+ $existing_attribute = $this->attributes[ $name ];
+ $this->attribute_updates[ $name ] = new WP_HTML_Text_Replacement(
+ $existing_attribute->start,
+ $existing_attribute->end,
+ $updated_attribute
+ );
+ } else {
+ /*
+ * Create a new attribute at the tag's name end.
+ *
+ * Example – add attribute id="new" to
:
+ *
+ * ^
+ * start and end
+ * replacement: ` id="new"`
+ *
+ * Result:
+ */
+ $this->attribute_updates[ $name ] = new WP_HTML_Text_Replacement(
+ $this->tag_name_starts_at + $this->tag_name_length,
+ $this->tag_name_starts_at + $this->tag_name_length,
+ ' ' . $updated_attribute
+ );
+ }
+ }
+
+ /**
+ * Removes an attribute of the currently matched tag.
+ *
+ * @since 6.2.0
+ *
+ * @param string $name The attribute name to remove.
+ */
+ public function remove_attribute( $name ) {
+ if ( ! isset( $this->attributes[ $name ] ) ) {
+ return;
+ }
+
+ /*
+ * Removes an existing tag attribute.
+ *
+ * Example – remove the attribute id from
:
+ *
+ * ^-------------^
+ * start end
+ * replacement: ``
+ *
+ * Result:
+ */
+ $this->attribute_updates[ $name ] = new WP_HTML_Text_Replacement(
+ $this->attributes[ $name ]->start,
+ $this->attributes[ $name ]->end,
+ ''
+ );
+ }
+
+ /**
+ * Adds a new class name to the currently matched tag.
+ *
+ * @since 6.2.0
+ *
+ * @param string $class_name The class name to add.
+ */
+ public function add_class( $class_name ) {
+ if ( null !== $this->tag_name_starts_at ) {
+ $this->classname_updates[ $class_name ] = self::ADD_CLASS;
+ }
+ }
+
+ /**
+ * Removes a class name from the currently matched tag.
+ *
+ * @since 6.2.0
+ *
+ * @param string $class_name The class name to remove.
+ */
+ public function remove_class( $class_name ) {
+ if ( null !== $this->tag_name_starts_at ) {
+ $this->classname_updates[ $class_name ] = self::REMOVE_CLASS;
+ }
+ }
+
+ /**
+ * Returns the string representation of the HTML Tag Processor.
+ * It closes the HTML Tag Processor and prevents further lookups and modifications.
+ *
+ * @since 6.2.0
+ *
+ * @return string The processed HTML.
+ */
+ public function __toString() {
+ // Short-circuit if there are no updates to apply.
+ if ( ! count( $this->classname_updates ) && ! count( $this->attribute_updates ) ) {
+ return $this->updated_html . substr( $this->html, $this->updated_bytes );
+ }
+
+ /*
+ * Parsing is in progress – let's apply the attribute updates without moving on to the next tag.
+ *
+ * In practice:
+ * 1. Apply the attributes updates to the original HTML
+ * 2. Replace the original HTML with the updated HTML
+ * 3. Point this tag processor to the current tag name's end in that updated HTML
+ */
+
+ // Find tag name's end in the updated markup.
+ $markup_updated_up_to_a_tag_name_end = $this->updated_html . substr( $this->html, $this->updated_bytes, $this->tag_name_starts_at + $this->tag_name_length - $this->updated_bytes );
+ $updated_tag_name_ends_at = strlen( $markup_updated_up_to_a_tag_name_end );
+ $updated_tag_name_starts_at = $updated_tag_name_ends_at - $this->tag_name_length;
+
+ // Apply attributes updates.
+ $this->updated_html = $markup_updated_up_to_a_tag_name_end;
+ $this->updated_bytes = $this->tag_name_starts_at + $this->tag_name_length;
+ $this->class_name_updates_to_attributes_updates();
+ $this->apply_attributes_updates();
+
+ // Replace $this->html with the updated markup.
+ $this->html = $this->updated_html . substr( $this->html, $this->updated_bytes );
+
+ // Rewind this processor to the tag name's end.
+ $this->tag_name_starts_at = $updated_tag_name_starts_at;
+ $this->parsed_bytes = $updated_tag_name_ends_at;
+
+ // Restore the previous version of the updated_html as we are not finished with the current_tag yet.
+ $this->updated_html = $markup_updated_up_to_a_tag_name_end;
+ $this->updated_bytes = $updated_tag_name_ends_at;
+
+ // Parse the attributes in the updated markup.
+ $this->attributes = array();
+ $this->parse_tag_opener_attributes();
+
+ return $this->html;
+ }
+
+ /**
+ * Prepares tag search criteria from input interface.
+ *
+ * @since 6.2.0
+ *
+ * @param array|string $query {
+ * Which tag name to find, having which class.
+ *
+ * @type string|null $tag_name Which tag to find, or `null` for "any tag."
+ * @type string|null $class_name Tag must contain this class name to match.
+ * }
+ */
+ private function parse_query( $query ) {
+ if ( null !== $query && $query === $this->last_query ) {
+ return;
+ }
+
+ $this->last_query = $query;
+ $this->sought_tag_name = null;
+ $this->sought_class_name = null;
+ $this->sought_match_offset = 1;
+
+ // A single string value means "find the tag of this name".
+ if ( is_string( $query ) ) {
+ $this->sought_tag_name = $query;
+ return;
+ }
+
+ // If not using the string interface we have to pass an associative array.
+ if ( ! is_array( $query ) ) {
+ return;
+ }
+
+ if ( isset( $query['tag_name'] ) && is_string( $query['tag_name'] ) ) {
+ $this->sought_tag_name = $query['tag_name'];
+ }
+
+ if ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) {
+ $this->sought_class_name = $query['class_name'];
+ }
+
+ if ( isset( $query['match_offset'] ) && is_int( $query['match_offset'] ) && 0 < $query['match_offset'] ) {
+ $this->sought_match_offset = $query['match_offset'];
+ }
+ }
+
+
+ /**
+ * Checks whether a given tag and its attributes match the search criteria.
+ *
+ * @since 6.2.0
+ *
+ * @return boolean
+ */
+ private function matches() {
+ // Do we match a case-insensitive HTML tag name?
+ if ( null !== $this->sought_tag_name ) {
+ /*
+ * String (byte) length lookup is fast. If they aren't the
+ * same length then they can't be the same string values.
+ */
+ if ( strlen( $this->sought_tag_name ) !== $this->tag_name_length ) {
+ return false;
+ }
+
+ /*
+ * Otherwise we have to check for each character if they
+ * are the same, and only `strtoupper()` if we have to.
+ * Presuming that most people will supply lowercase tag
+ * names and most HTML will contain lowercase tag names,
+ * most of the time this runs we shouldn't expect to
+ * actually run the case-folding comparison.
+ */
+ for ( $i = 0; $i < $this->tag_name_length; $i++ ) {
+ $html_char = $this->html[ $this->tag_name_starts_at + $i ];
+ $tag_char = $this->sought_tag_name[ $i ];
+
+ if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) {
+ return false;
+ }
+ }
+ }
+
+ $needs_class_name = null !== $this->sought_class_name;
+
+ if ( $needs_class_name && ! isset( $this->attributes['class'] ) ) {
+ return false;
+ }
+
+ // Do we match a byte-for-byte (case-sensitive and encoding-form-sensitive) class name?
+ if ( $needs_class_name ) {
+ $class_start = $this->attributes['class']->value_starts_at;
+ $class_end = $class_start + $this->attributes['class']->value_length;
+ $class_at = $class_start;
+
+ /*
+ * We're going to have to jump through potential matches here because
+ * it's possible that we have classes containing the class name we're
+ * looking for. For instance, if we are looking for "even" we don't
+ * want to be confused when we come to the class "not-even." This is
+ * secured by ensuring that we find our sought-after class and that
+ * it's surrounded on both sides by proper boundaries.
+ *
+ * See https://html.spec.whatwg.org/#attributes-3
+ * See https://html.spec.whatwg.org/#space-separated-tokens
+ */
+ while (
+ // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
+ false !== ( $class_at = strpos( $this->html, $this->sought_class_name, $class_at ) ) &&
+ $class_at < $class_end
+ ) {
+ /*
+ * Verify this class starts at a boundary. If it were at 0 we'd be at
+ * the start of the string and that would be fine, otherwise we have
+ * to start at a place where the preceding character is whitespace.
+ */
+ if ( $class_at > $class_start ) {
+ $character = $this->html[ $class_at - 1 ];
+
+ if ( ' ' !== $character && "\t" !== $character && "\f" !== $character && "\r" !== $character && "\n" !== $character ) {
+ $class_at += strlen( $this->sought_class_name );
+ continue;
+ }
+ }
+
+ /*
+ * Similarly, verify this class ends at a boundary as well. Here we
+ * can end at the very end of the string value, otherwise we have
+ * to end at a place where the next character is whitespace.
+ */
+ if ( $class_at + strlen( $this->sought_class_name ) < $class_end ) {
+ $character = $this->html[ $class_at + strlen( $this->sought_class_name ) ];
+
+ if ( ' ' !== $character && "\t" !== $character && "\f" !== $character && "\r" !== $character && "\n" !== $character ) {
+ $class_at += strlen( $this->sought_class_name );
+ continue;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/lib/experimental/html/class-wp-html-text-replacement.php b/lib/experimental/html/class-wp-html-text-replacement.php
new file mode 100644
index 00000000000000..e3ada169d76efa
--- /dev/null
+++ b/lib/experimental/html/class-wp-html-text-replacement.php
@@ -0,0 +1,59 @@
+start = $start;
+ $this->end = $end;
+ $this->text = $text;
+ }
+}
diff --git a/lib/experimental/html/index.php b/lib/experimental/html/index.php
new file mode 100644
index 00000000000000..e7d41f8cdf4863
--- /dev/null
+++ b/lib/experimental/html/index.php
@@ -0,0 +1,11 @@
+= 8"
- }
- }
}
},
"@octokit/rest": {
- "version": "16.43.2",
- "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz",
- "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==",
- "dev": true,
- "requires": {
- "@octokit/auth-token": "^2.4.0",
- "@octokit/plugin-paginate-rest": "^1.1.1",
- "@octokit/plugin-request-log": "^1.0.0",
- "@octokit/plugin-rest-endpoint-methods": "2.4.0",
- "@octokit/request": "^5.2.0",
- "@octokit/request-error": "^1.0.2",
- "atob-lite": "^2.0.0",
- "before-after-hook": "^2.0.0",
- "btoa-lite": "^1.0.0",
- "deprecation": "^2.0.0",
- "lodash.get": "^4.4.2",
- "lodash.set": "^4.3.2",
- "lodash.uniq": "^4.5.0",
- "octokit-pagination-methods": "^1.1.0",
- "once": "^1.4.0",
- "universal-user-agent": "^4.0.0"
+ "version": "19.0.4",
+ "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.4.tgz",
+ "integrity": "sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==",
+ "dev": true,
+ "requires": {
+ "@octokit/core": "^4.0.0",
+ "@octokit/plugin-paginate-rest": "^4.0.0",
+ "@octokit/plugin-request-log": "^1.0.4",
+ "@octokit/plugin-rest-endpoint-methods": "^6.0.0"
}
},
- "before-after-hook": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz",
- "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==",
- "dev": true
+ "@octokit/types": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.5.0.tgz",
+ "integrity": "sha512-aHm+olfIZjQpzoODpl+RCZzchKOrdSLJs+yfI7pMMcmB19Li6vidgx0DwUDO/Ic4Q3fq/lOjJORVCcLZefcrJw==",
+ "dev": true,
+ "requires": {
+ "@octokit/openapi-types": "^13.11.0"
+ }
},
- "is-plain-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
- "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "before-after-hook": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
+ "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==",
"dev": true
},
- "universal-user-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz",
- "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==",
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dev": true,
"requires": {
- "os-name": "^3.1.0"
+ "whatwg-url": "^5.0.0"
}
+ },
+ "universal-user-agent": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
+ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==",
+ "dev": true
}
}
},
"@lerna/gitlab-client": {
- "version": "3.15.0",
- "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz",
- "integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-5.5.2.tgz",
+ "integrity": "sha512-iSNk8ktwRXL5JgTYvKdEQASHLgo8Vq4RLX1hOFhOMszxKeT2kjCXLqefto3TlJ5xOGQb/kaGBm++jp+uZxhdog==",
"dev": true,
"requires": {
- "node-fetch": "^2.5.0",
- "npmlog": "^4.1.2",
- "whatwg-url": "^7.0.0"
+ "node-fetch": "^2.6.1",
+ "npmlog": "^6.0.2"
}
},
"@lerna/global-options": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz",
- "integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-5.5.2.tgz",
+ "integrity": "sha512-YaFCLMm7oThPpmRvrDX/VuoihrWCqBVm3zG+c8OM7sjs1MXDKycbdhtjzIwysWocEpf0NjUtdQS7v6gUhfNiFQ==",
"dev": true
},
"@lerna/has-npm-version": {
- "version": "3.16.5",
- "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz",
- "integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-5.5.2.tgz",
+ "integrity": "sha512-8BHJCVPy5o0vERm0jjcwYSCNOK+EclbufR05kqorsYzCu0xWPOc3SDlo5mXuWsG61SlT3RdV9SJ3Rab15fOLAg==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "semver": "^6.2.0"
- },
- "dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- }
+ "@lerna/child-process": "5.5.2",
+ "semver": "^7.3.4"
}
},
"@lerna/import": {
- "version": "3.22.0",
- "resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.22.0.tgz",
- "integrity": "sha512-uWOlexasM5XR6tXi4YehODtH9Y3OZrFht3mGUFFT3OIl2s+V85xIGFfqFGMTipMPAGb2oF1UBLL48kR43hRsOg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/import/-/import-5.5.2.tgz",
+ "integrity": "sha512-QtHJEo/9RRO9oILzSK45k5apsAyUEgwpGj4Ys3gZ7rFuXQ4+xHi9R6YC0IjwyiSfoN/i3Qbsku+PByxhhzkxHQ==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "@lerna/command": "3.21.0",
- "@lerna/prompt": "3.18.5",
- "@lerna/pulse-till-done": "3.13.0",
- "@lerna/validation-error": "3.13.0",
+ "@lerna/child-process": "5.5.2",
+ "@lerna/command": "5.5.2",
+ "@lerna/prompt": "5.5.2",
+ "@lerna/pulse-till-done": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
"dedent": "^0.7.0",
- "fs-extra": "^8.1.0",
- "p-map-series": "^1.0.0"
- }
+ "fs-extra": "^9.1.0",
+ "p-map-series": "^2.1.0"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
+ }
},
"@lerna/info": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/info/-/info-3.21.0.tgz",
- "integrity": "sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/info/-/info-5.5.2.tgz",
+ "integrity": "sha512-Ek+bCooAfng+K4Fgy9i6jKBMpZZQ3lQpv6SWg8TbrwGR/el8FYBJod3+I5khJ2RJqHAmjLBz6wiSyVPMjwvptw==",
"dev": true,
"requires": {
- "@lerna/command": "3.21.0",
- "@lerna/output": "3.13.0",
- "envinfo": "^7.3.1"
+ "@lerna/command": "5.5.2",
+ "@lerna/output": "5.5.2",
+ "envinfo": "^7.7.4"
}
},
"@lerna/init": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.21.0.tgz",
- "integrity": "sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/init/-/init-5.5.2.tgz",
+ "integrity": "sha512-CKHrcOlm2XXXF384FeCKK+CjKBW22HkJ5CcLlU1gnTFD2QarrBwTOGjpRaREXP8T/k3q7h0W0FK8B77opqLwDg==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "@lerna/command": "3.21.0",
- "fs-extra": "^8.1.0",
- "p-map": "^2.1.0",
- "write-json-file": "^3.2.0"
+ "@lerna/child-process": "5.5.2",
+ "@lerna/command": "5.5.2",
+ "@lerna/project": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "p-map": "^4.0.0",
+ "write-json-file": "^4.3.0"
},
"dependencies": {
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "detect-indent": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+ "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "sort-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz",
+ "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "write-json-file": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz",
+ "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==",
+ "dev": true,
+ "requires": {
+ "detect-indent": "^6.0.0",
+ "graceful-fs": "^4.1.15",
+ "is-plain-obj": "^2.0.0",
+ "make-dir": "^3.0.0",
+ "sort-keys": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ }
}
}
},
"@lerna/link": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.21.0.tgz",
- "integrity": "sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/link/-/link-5.5.2.tgz",
+ "integrity": "sha512-B/0a+biXO2uMSbNw1Vv9YMrfse0i8HU9mrrWQbXIHws3j0i5Wxuxvd7B/r0xzYN5LF5AFDxrPjPNTgC49U/58Q==",
"dev": true,
"requires": {
- "@lerna/command": "3.21.0",
- "@lerna/package-graph": "3.18.5",
- "@lerna/symlink-dependencies": "3.17.0",
- "p-map": "^2.1.0",
- "slash": "^2.0.0"
- },
- "dependencies": {
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
- "dev": true
- },
- "slash": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
- "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
- "dev": true
- }
+ "@lerna/command": "5.5.2",
+ "@lerna/package-graph": "5.5.2",
+ "@lerna/symlink-dependencies": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "p-map": "^4.0.0",
+ "slash": "^3.0.0"
}
},
"@lerna/list": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.21.0.tgz",
- "integrity": "sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/list/-/list-5.5.2.tgz",
+ "integrity": "sha512-uC/LRq9zcOM33vV6l4Nmx18vXNNIcaxFHVCBOC3IxZJb0MTPzKFqlu/YIVQaJMWeHpiIo6OfbK4mbH1h8yXmHw==",
"dev": true,
"requires": {
- "@lerna/command": "3.21.0",
- "@lerna/filter-options": "3.20.0",
- "@lerna/listable": "3.18.5",
- "@lerna/output": "3.13.0"
+ "@lerna/command": "5.5.2",
+ "@lerna/filter-options": "5.5.2",
+ "@lerna/listable": "5.5.2",
+ "@lerna/output": "5.5.2"
}
},
"@lerna/listable": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.5.tgz",
- "integrity": "sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-5.5.2.tgz",
+ "integrity": "sha512-CEDTaLB8V7faSSTgB1II1USpda5PQWUkfsvDJekJ4yZ4dql3XnzqdVZ48zLqPArl/30e0g1gWGOBkdKqswY+Yg==",
"dev": true,
"requires": {
- "@lerna/query-graph": "3.18.5",
- "chalk": "^2.3.1",
- "columnify": "^1.5.4"
- },
- "dependencies": {
- "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,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- }
+ "@lerna/query-graph": "5.5.2",
+ "chalk": "^4.1.0",
+ "columnify": "^1.6.0"
}
},
"@lerna/log-packed": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz",
- "integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-5.5.2.tgz",
+ "integrity": "sha512-k1tKZdNuAIj9t7ZJBSzua5zEnPoweKLpuXYzuiBE8CALBfl2Zf9szsbDQDsERDOxQ365+FEgK+GfkmvxtYx4tw==",
"dev": true,
"requires": {
- "byte-size": "^5.0.1",
- "columnify": "^1.5.4",
+ "byte-size": "^7.0.0",
+ "columnify": "^1.6.0",
"has-unicode": "^2.0.1",
- "npmlog": "^4.1.2"
+ "npmlog": "^6.0.2"
}
},
"@lerna/npm-conf": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz",
- "integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-5.5.2.tgz",
+ "integrity": "sha512-X2EE1TCSfsYy2XTUUN0+QXXEPvecuGk3mpTXR5KP+ScAs0WmTisRLyJ9lofh/9e0SIIGdVYmh2PykhgduyOKsg==",
"dev": true,
"requires": {
- "config-chain": "^1.1.11",
- "pify": "^4.0.1"
+ "config-chain": "^1.1.12",
+ "pify": "^5.0.0"
},
"dependencies": {
"pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
+ "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==",
"dev": true
}
}
},
"@lerna/npm-dist-tag": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz",
- "integrity": "sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-5.5.2.tgz",
+ "integrity": "sha512-Od4liA0ISunwatHxArHdaxFc/m9dXMI0fAFqbScgeqVkY8OeoHEY/AlINjglYChtGcbKdHm1ml8qvlK9Tr2EXg==",
"dev": true,
"requires": {
- "@evocateur/npm-registry-fetch": "^4.0.0",
- "@lerna/otplease": "3.18.5",
- "figgy-pudding": "^3.5.1",
- "npm-package-arg": "^6.1.0",
- "npmlog": "^4.1.2"
+ "@lerna/otplease": "5.5.2",
+ "npm-package-arg": "8.1.1",
+ "npm-registry-fetch": "^13.3.0",
+ "npmlog": "^6.0.2"
},
"dependencies": {
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
"validate-npm-package-name": "^3.0.0"
}
},
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@lerna/npm-install": {
- "version": "3.16.5",
- "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz",
- "integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-5.5.2.tgz",
+ "integrity": "sha512-aDIDRS9C9uWheuc6JEntNqTcaTcSFyTx4FgUw5FDHrwsTZ9TiEAB9O+XyDKIlcGHlNviuQt270boUHjsvOoMcg==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "@lerna/get-npm-exec-opts": "3.13.0",
- "fs-extra": "^8.1.0",
- "npm-package-arg": "^6.1.0",
- "npmlog": "^4.1.2",
- "signal-exit": "^3.0.2",
- "write-pkg": "^3.1.0"
+ "@lerna/child-process": "5.5.2",
+ "@lerna/get-npm-exec-opts": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "npm-package-arg": "8.1.1",
+ "npmlog": "^6.0.2",
+ "signal-exit": "^3.0.3",
+ "write-pkg": "^4.0.0"
},
"dependencies": {
- "make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"requires": {
- "pify": "^3.0.0"
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
}
},
- "npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
- "validate-npm-package-name": "^3.0.0"
+ "lru-cache": "^6.0.0"
}
},
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
},
- "write-json-file": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz",
- "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=",
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
- "detect-indent": "^5.0.0",
- "graceful-fs": "^4.1.2",
- "make-dir": "^1.0.0",
- "pify": "^3.0.0",
- "sort-keys": "^2.0.0",
- "write-file-atomic": "^2.0.0"
+ "yallist": "^4.0.0"
}
},
- "write-pkg": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz",
- "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==",
+ "npm-package-arg": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "sort-keys": "^2.0.0",
- "write-json-file": "^2.2.0"
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
+ "validate-npm-package-name": "^3.0.0"
}
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
},
"@lerna/npm-publish": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.18.5.tgz",
- "integrity": "sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-5.5.2.tgz",
+ "integrity": "sha512-TRYkkocg/VFy9MwWtfIa2gNXFkMwkDfaS1exgJK4DKbjH3hiBo/cDG3Zx/jMBGvetv4CLsC2n+phRhozgCezTA==",
"dev": true,
"requires": {
- "@evocateur/libnpmpublish": "^1.2.2",
- "@lerna/otplease": "3.18.5",
- "@lerna/run-lifecycle": "3.16.2",
- "figgy-pudding": "^3.5.1",
- "fs-extra": "^8.1.0",
- "npm-package-arg": "^6.1.0",
- "npmlog": "^4.1.2",
- "pify": "^4.0.1",
- "read-package-json": "^2.0.13"
+ "@lerna/otplease": "5.5.2",
+ "@lerna/run-lifecycle": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "libnpmpublish": "^6.0.4",
+ "npm-package-arg": "8.1.1",
+ "npmlog": "^6.0.2",
+ "pify": "^5.0.0",
+ "read-package-json": "^5.0.1"
},
"dependencies": {
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
"validate-npm-package-name": "^3.0.0"
}
},
"pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
+ "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==",
"dev": true
},
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@lerna/npm-run-script": {
- "version": "3.16.5",
- "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz",
- "integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-5.5.2.tgz",
+ "integrity": "sha512-lKn4ybw/97SMR/0j5UcJraL+gpfXv2HWKmlrG47JuAMJaEFkQQyCh4EdP3cGPCnSzrI5zXsil8SS/JelkhQpkg==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "@lerna/get-npm-exec-opts": "3.13.0",
- "npmlog": "^4.1.2"
+ "@lerna/child-process": "5.5.2",
+ "@lerna/get-npm-exec-opts": "5.5.2",
+ "npmlog": "^6.0.2"
}
},
"@lerna/otplease": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.18.5.tgz",
- "integrity": "sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-5.5.2.tgz",
+ "integrity": "sha512-kZwSWTLGFWLoFX0p6RJ8AARIo6P/wkIcUyAFrVU3YTesN7KqbujpzaVTf5bAWsDdeiRWizCGM1TVw2IDUtStQg==",
"dev": true,
"requires": {
- "@lerna/prompt": "3.18.5",
- "figgy-pudding": "^3.5.1"
+ "@lerna/prompt": "5.5.2"
}
},
"@lerna/output": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz",
- "integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/output/-/output-5.5.2.tgz",
+ "integrity": "sha512-Sv5qMvwnY7RGUw3JHyNUHNlQ4f/167kK1tczCaHUXa1SmOq5adMBbiMNApa2y5s8B+v9OahkU2nnOOaIuVy0HQ==",
"dev": true,
"requires": {
- "npmlog": "^4.1.2"
+ "npmlog": "^6.0.2"
}
},
"@lerna/pack-directory": {
- "version": "3.16.4",
- "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz",
- "integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-5.5.2.tgz",
+ "integrity": "sha512-LvBbOeSwbpHPL7w9cI0Jtpa6r61N3KboD4nutNlWaT9LRv0dLlex2k10Pfc8u15agQ62leLhHa6UmjFt16msEA==",
"dev": true,
"requires": {
- "@lerna/get-packed": "3.16.0",
- "@lerna/package": "3.16.0",
- "@lerna/run-lifecycle": "3.16.2",
- "figgy-pudding": "^3.5.1",
- "npm-packlist": "^1.4.4",
- "npmlog": "^4.1.2",
- "tar": "^4.4.10",
- "temp-write": "^3.4.0"
+ "@lerna/get-packed": "5.5.2",
+ "@lerna/package": "5.5.2",
+ "@lerna/run-lifecycle": "5.5.2",
+ "@lerna/temp-write": "5.5.2",
+ "npm-packlist": "^5.1.1",
+ "npmlog": "^6.0.2",
+ "tar": "^6.1.0"
},
"dependencies": {
- "fs-minipass": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
- "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
- "dev": true,
- "requires": {
- "minipass": "^2.6.0"
- }
- },
- "ignore-walk": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
- "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==",
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"requires": {
- "minimatch": "^3.0.4"
+ "balanced-match": "^1.0.0"
}
},
- "minipass": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
- "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"dev": true,
"requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
}
},
- "minizlib": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
- "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+ "ignore-walk": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz",
+ "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==",
"dev": true,
"requires": {
- "minipass": "^2.9.0"
+ "minimatch": "^5.0.1"
}
},
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
"dev": true,
"requires": {
- "minimist": "^1.2.5"
+ "brace-expansion": "^2.0.1"
}
},
- "npm-packlist": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
- "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+ "npm-bundled": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz",
+ "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==",
"dev": true,
"requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1",
- "npm-normalize-package-bin": "^1.0.1"
+ "npm-normalize-package-bin": "^2.0.0"
}
},
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "npm-normalize-package-bin": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
+ "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
"dev": true
},
- "tar": {
- "version": "4.4.19",
- "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz",
- "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==",
+ "npm-packlist": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz",
+ "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==",
"dev": true,
"requires": {
- "chownr": "^1.1.4",
- "fs-minipass": "^1.2.7",
- "minipass": "^2.9.0",
- "minizlib": "^1.3.3",
- "mkdirp": "^0.5.5",
- "safe-buffer": "^5.2.1",
- "yallist": "^3.1.1"
+ "glob": "^8.0.1",
+ "ignore-walk": "^5.0.1",
+ "npm-bundled": "^2.0.0",
+ "npm-normalize-package-bin": "^2.0.0"
}
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
}
}
},
"@lerna/package": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz",
- "integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/package/-/package-5.5.2.tgz",
+ "integrity": "sha512-/36+oq5Q63EYSyjW5mHPR3aMrXDo6Wn8zKcl9Dfd4bn+w0AfK/EbId7iB/TrFaNdGtw8CrhK+e5CmgiMBeXMPw==",
"dev": true,
"requires": {
- "load-json-file": "^5.3.0",
- "npm-package-arg": "^6.1.0",
- "write-pkg": "^3.1.0"
+ "load-json-file": "^6.2.0",
+ "npm-package-arg": "8.1.1",
+ "write-pkg": "^4.0.0"
},
"dependencies": {
"graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
"load-json-file": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
- "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz",
+ "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.15",
- "parse-json": "^4.0.0",
- "pify": "^4.0.1",
- "strip-bom": "^3.0.0",
- "type-fest": "^0.3.0"
+ "parse-json": "^5.0.0",
+ "strip-bom": "^4.0.0",
+ "type-fest": "^0.6.0"
}
},
- "make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
- "pify": "^3.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- }
+ "yallist": "^4.0.0"
}
},
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
"validate-npm-package-name": "^3.0.0"
}
},
- "parse-json": {
+ "strip-bom": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true
},
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
- },
- "write-json-file": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz",
- "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=",
- "dev": true,
- "requires": {
- "detect-indent": "^5.0.0",
- "graceful-fs": "^4.1.2",
- "make-dir": "^1.0.0",
- "pify": "^3.0.0",
- "sort-keys": "^2.0.0",
- "write-file-atomic": "^2.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- }
- }
- },
- "write-pkg": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz",
- "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==",
- "dev": true,
- "requires": {
- "sort-keys": "^2.0.0",
- "write-json-file": "^2.2.0"
- }
}
}
},
"@lerna/package-graph": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.5.tgz",
- "integrity": "sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-5.5.2.tgz",
+ "integrity": "sha512-tyMokkrktvohhU3PE3nZLdjrmozcrV8ql37u0l/axHXrfNiV3RDn9ENVvYXnLnP2BCHV572RRpbI5kYto4wtRg==",
"dev": true,
"requires": {
- "@lerna/prerelease-id-from-version": "3.16.0",
- "@lerna/validation-error": "3.13.0",
- "npm-package-arg": "^6.1.0",
- "npmlog": "^4.1.2",
- "semver": "^6.2.0"
+ "@lerna/prerelease-id-from-version": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "npm-package-arg": "8.1.1",
+ "npmlog": "^6.0.2",
+ "semver": "^7.3.4"
},
"dependencies": {
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
"validate-npm-package-name": "^3.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- }
}
},
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@lerna/prerelease-id-from-version": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz",
- "integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-5.5.2.tgz",
+ "integrity": "sha512-FokuA8PFH+YMlbVvPsrTWgfZzaeXDmSmXGKzF8yEM7008UOFx9a3ivDzPnRK7IDaO9nUmt++Snb3QLey1ldYlQ==",
"dev": true,
"requires": {
- "semver": "^6.2.0"
+ "semver": "^7.3.4"
+ }
+ },
+ "@lerna/profiler": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-5.5.2.tgz",
+ "integrity": "sha512-030TM1sG0h/vSJ+49e8K1HtVIt94i6lOIRILTF4zkx+O00Fcg91wBtdIduKhZZt1ziWRi1v2soijKR26IDC+Tg==",
+ "dev": true,
+ "requires": {
+ "fs-extra": "^9.1.0",
+ "npmlog": "^6.0.2",
+ "upath": "^2.0.1"
},
"dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "upath": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz",
+ "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==",
"dev": true
}
}
},
- "@lerna/profiler": {
- "version": "3.20.0",
- "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-3.20.0.tgz",
- "integrity": "sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg==",
+ "@lerna/project": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/project/-/project-5.5.2.tgz",
+ "integrity": "sha512-NtHov7CCM3DHbj6xaD9lTErOnEmz0s+piJP/nVw6aIvfkhvUl1fB6SnttM+0GHZrT6WSIXFWsb0pkRMTBn55Bw==",
"dev": true,
"requires": {
- "figgy-pudding": "^3.5.1",
- "fs-extra": "^8.1.0",
- "npmlog": "^4.1.2",
- "upath": "^1.2.0"
+ "@lerna/package": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "cosmiconfig": "^7.0.0",
+ "dedent": "^0.7.0",
+ "dot-prop": "^6.0.1",
+ "glob-parent": "^5.1.1",
+ "globby": "^11.0.2",
+ "js-yaml": "^4.1.0",
+ "load-json-file": "^6.2.0",
+ "npmlog": "^6.0.2",
+ "p-map": "^4.0.0",
+ "resolve-from": "^5.0.0",
+ "write-json-file": "^4.3.0"
+ },
+ "dependencies": {
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "detect-indent": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+ "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "load-json-file": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz",
+ "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.15",
+ "parse-json": "^5.0.0",
+ "strip-bom": "^4.0.0",
+ "type-fest": "^0.6.0"
+ }
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ },
+ "sort-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz",
+ "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "write-json-file": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz",
+ "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==",
+ "dev": true,
+ "requires": {
+ "detect-indent": "^6.0.0",
+ "graceful-fs": "^4.1.15",
+ "is-plain-obj": "^2.0.0",
+ "make-dir": "^3.0.0",
+ "sort-keys": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ }
+ }
}
},
- "@lerna/project": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.21.0.tgz",
- "integrity": "sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A==",
+ "@lerna/prompt": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-5.5.2.tgz",
+ "integrity": "sha512-flV5SOu9CZrTf2YxGgMPwiAsv2jkUzyIs3cTTdFhFtKoZV7YPVZkGyMhqhEMIuUCOeITFY+emar9iPS6d7U4Jg==",
"dev": true,
"requires": {
- "@lerna/package": "3.16.0",
- "@lerna/validation-error": "3.13.0",
- "cosmiconfig": "^5.1.0",
- "dedent": "^0.7.0",
- "dot-prop": "^4.2.0",
- "glob-parent": "^5.0.0",
- "globby": "^9.2.0",
- "load-json-file": "^5.3.0",
- "npmlog": "^4.1.2",
- "p-map": "^2.1.0",
- "resolve-from": "^4.0.0",
- "write-json-file": "^3.2.0"
+ "inquirer": "^8.2.4",
+ "npmlog": "^6.0.2"
},
"dependencies": {
- "cosmiconfig": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
- "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
"dev": true,
"requires": {
- "import-fresh": "^2.0.0",
- "is-directory": "^0.3.1",
- "js-yaml": "^3.13.1",
- "parse-json": "^4.0.0"
+ "type-fest": "^0.21.3"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz",
+ "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==",
+ "dev": true
+ },
+ "cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "inquirer": {
+ "version": "8.2.4",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz",
+ "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^7.0.0"
}
},
- "glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
"requires": {
- "is-glob": "^4.0.1"
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
}
},
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
- "import-fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
- "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
"requires": {
- "caller-path": "^2.0.0",
- "resolve-from": "^3.0.0"
- },
- "dependencies": {
- "resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
- "dev": true
- }
+ "mimic-fn": "^2.1.0"
}
},
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "requires": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dev": true,
"requires": {
- "is-extglob": "^2.1.1"
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
}
},
- "load-json-file": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
- "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+ "rxjs": {
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
+ "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
"dev": true,
"requires": {
- "graceful-fs": "^4.1.15",
- "parse-json": "^4.0.0",
- "pify": "^4.0.1",
- "strip-bom": "^3.0.0",
- "type-fest": "^0.3.0"
+ "tslib": "^2.1.0"
}
},
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
- "dev": true
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
}
},
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
},
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
"dev": true
},
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
}
}
},
- "@lerna/prompt": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.18.5.tgz",
- "integrity": "sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==",
- "dev": true,
- "requires": {
- "inquirer": "^6.2.0",
- "npmlog": "^4.1.2"
+ "@lerna/publish": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-5.5.2.tgz",
+ "integrity": "sha512-ZC8LP4I3nLcVIcyqiRAVvGRaCkHHBdYVcqtF7S9KA8w2VvuAeqHRFUTIhKBziVbYnwI2uzJXGIRWP50U+p/wAA==",
+ "dev": true,
+ "requires": {
+ "@lerna/check-working-tree": "5.5.2",
+ "@lerna/child-process": "5.5.2",
+ "@lerna/collect-updates": "5.5.2",
+ "@lerna/command": "5.5.2",
+ "@lerna/describe-ref": "5.5.2",
+ "@lerna/log-packed": "5.5.2",
+ "@lerna/npm-conf": "5.5.2",
+ "@lerna/npm-dist-tag": "5.5.2",
+ "@lerna/npm-publish": "5.5.2",
+ "@lerna/otplease": "5.5.2",
+ "@lerna/output": "5.5.2",
+ "@lerna/pack-directory": "5.5.2",
+ "@lerna/prerelease-id-from-version": "5.5.2",
+ "@lerna/prompt": "5.5.2",
+ "@lerna/pulse-till-done": "5.5.2",
+ "@lerna/run-lifecycle": "5.5.2",
+ "@lerna/run-topologically": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "@lerna/version": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "libnpmaccess": "^6.0.3",
+ "npm-package-arg": "8.1.1",
+ "npm-registry-fetch": "^13.3.0",
+ "npmlog": "^6.0.2",
+ "p-map": "^4.0.0",
+ "p-pipe": "^3.1.0",
+ "pacote": "^13.6.1",
+ "semver": "^7.3.4"
},
"dependencies": {
- "ansi-escapes": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
- "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
- "dev": true
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
},
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "hosted-git-info": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
+ "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
"dev": true,
"requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "lru-cache": "^6.0.0"
}
},
- "inquirer": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
- "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": {
- "ansi-escapes": "^3.2.0",
- "chalk": "^2.4.2",
- "cli-cursor": "^2.1.0",
- "cli-width": "^2.0.0",
- "external-editor": "^3.0.3",
- "figures": "^2.0.0",
- "lodash": "^4.17.12",
- "mute-stream": "0.0.7",
- "run-async": "^2.2.0",
- "rxjs": "^6.4.0",
- "string-width": "^2.1.0",
- "strip-ansi": "^5.1.0",
- "through": "^2.3.6"
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
}
},
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
- "ansi-regex": "^4.1.0"
+ "yallist": "^4.0.0"
}
- }
- }
- },
- "@lerna/publish": {
- "version": "3.22.1",
- "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.22.1.tgz",
- "integrity": "sha512-PG9CM9HUYDreb1FbJwFg90TCBQooGjj+n/pb3gw/eH5mEDq0p8wKdLFe0qkiqUkm/Ub5C8DbVFertIo0Vd0zcw==",
- "dev": true,
- "requires": {
- "@evocateur/libnpmaccess": "^3.1.2",
- "@evocateur/npm-registry-fetch": "^4.0.0",
- "@evocateur/pacote": "^9.6.3",
- "@lerna/check-working-tree": "3.16.5",
- "@lerna/child-process": "3.16.5",
- "@lerna/collect-updates": "3.20.0",
- "@lerna/command": "3.21.0",
- "@lerna/describe-ref": "3.16.5",
- "@lerna/log-packed": "3.16.0",
- "@lerna/npm-conf": "3.16.0",
- "@lerna/npm-dist-tag": "3.18.5",
- "@lerna/npm-publish": "3.18.5",
- "@lerna/otplease": "3.18.5",
- "@lerna/output": "3.13.0",
- "@lerna/pack-directory": "3.16.4",
- "@lerna/prerelease-id-from-version": "3.16.0",
- "@lerna/prompt": "3.18.5",
- "@lerna/pulse-till-done": "3.13.0",
- "@lerna/run-lifecycle": "3.16.2",
- "@lerna/run-topologically": "3.18.5",
- "@lerna/validation-error": "3.13.0",
- "@lerna/version": "3.22.1",
- "figgy-pudding": "^3.5.1",
- "fs-extra": "^8.1.0",
- "npm-package-arg": "^6.1.0",
- "npmlog": "^4.1.2",
- "p-finally": "^1.0.0",
- "p-map": "^2.1.0",
- "p-pipe": "^1.2.0",
- "semver": "^6.2.0"
- },
- "dependencies": {
+ },
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz",
+ "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
+ "hosted-git-info": "^3.0.6",
+ "semver": "^7.0.0",
"validate-npm-package-name": "^3.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- }
}
},
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
},
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@lerna/pulse-till-done": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz",
- "integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-5.5.2.tgz",
+ "integrity": "sha512-e8sRby4FxSU9QjdRYXvHQtb5GMVO5XDnSH83RWdSxAVFGVEVWKqI3qg3otGH1JlD/kOu195d+ZzndF9qqMvveQ==",
"dev": true,
"requires": {
- "npmlog": "^4.1.2"
+ "npmlog": "^6.0.2"
}
},
"@lerna/query-graph": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.5.tgz",
- "integrity": "sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-5.5.2.tgz",
+ "integrity": "sha512-krKt+mvGm+9fp71ZGUO1MiUZsL+W6dAKx5kBPNWkrw5TFZCasZJHRSIqby9iXpjma+MYohjFjLVvg1PIYKt/kg==",
"dev": true,
"requires": {
- "@lerna/package-graph": "3.18.5",
- "figgy-pudding": "^3.5.1"
+ "@lerna/package-graph": "5.5.2"
}
},
"@lerna/resolve-symlink": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz",
- "integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==",
- "dev": true,
- "requires": {
- "fs-extra": "^8.1.0",
- "npmlog": "^4.1.2",
- "read-cmd-shim": "^1.0.1"
- }
- },
- "@lerna/rimraf-dir": {
- "version": "3.16.5",
- "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz",
- "integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-5.5.2.tgz",
+ "integrity": "sha512-JLJg6/IFqpmGjFfKvj+lntcsGGWbIxF2uAcrVKldqwcPTmlMvolg51lL+wqII3s8N3gZIGdxhjXfhDdKuKtEzQ==",
"dev": true,
"requires": {
- "@lerna/child-process": "3.16.5",
- "npmlog": "^4.1.2",
- "path-exists": "^3.0.0",
- "rimraf": "^2.6.2"
+ "fs-extra": "^9.1.0",
+ "npmlog": "^6.0.2",
+ "read-cmd-shim": "^3.0.0"
},
"dependencies": {
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
}
},
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": {
- "glob": "^7.1.3"
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
}
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
+ }
+ },
+ "@lerna/rimraf-dir": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-5.5.2.tgz",
+ "integrity": "sha512-siE1RpEpSLFlnnbAJZz+CuBIcOqXrhR/SXVBnPDpIg4tGgHns+Q99m6K29ltuh+vZMBLMYnnyfPYitJFYTC3MQ==",
+ "dev": true,
+ "requires": {
+ "@lerna/child-process": "5.5.2",
+ "npmlog": "^6.0.2",
+ "path-exists": "^4.0.0",
+ "rimraf": "^3.0.2"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
}
}
},
"@lerna/run": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.21.0.tgz",
- "integrity": "sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/run/-/run-5.5.2.tgz",
+ "integrity": "sha512-KVMkjL2ehW+/6VAwTTLgq82Rgw4W6vOz1I9XwwO/bk9h7DoY1HlE8leaaYRNqT+Cv437A9AwggR+LswhoK3alA==",
"dev": true,
"requires": {
- "@lerna/command": "3.21.0",
- "@lerna/filter-options": "3.20.0",
- "@lerna/npm-run-script": "3.16.5",
- "@lerna/output": "3.13.0",
- "@lerna/profiler": "3.20.0",
- "@lerna/run-topologically": "3.18.5",
- "@lerna/timer": "3.13.0",
- "@lerna/validation-error": "3.13.0",
- "p-map": "^2.1.0"
+ "@lerna/command": "5.5.2",
+ "@lerna/filter-options": "5.5.2",
+ "@lerna/npm-run-script": "5.5.2",
+ "@lerna/output": "5.5.2",
+ "@lerna/profiler": "5.5.2",
+ "@lerna/run-topologically": "5.5.2",
+ "@lerna/timer": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "p-map": "^4.0.0"
},
"dependencies": {
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
}
}
},
"@lerna/run-lifecycle": {
- "version": "3.16.2",
- "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz",
- "integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-5.5.2.tgz",
+ "integrity": "sha512-d5pF0abAv6MVNG3xhG1BakHZtr93vIn27aqgBvu9XK1CW6GdbpBpCv1kc8RjHyOpjjFDt4+uK2TG7s7T0oCZPw==",
"dev": true,
"requires": {
- "@lerna/npm-conf": "3.16.0",
- "figgy-pudding": "^3.5.1",
- "npm-lifecycle": "^3.1.2",
- "npmlog": "^4.1.2"
+ "@lerna/npm-conf": "5.5.2",
+ "@npmcli/run-script": "^4.1.7",
+ "npmlog": "^6.0.2",
+ "p-queue": "^6.6.2"
}
},
"@lerna/run-topologically": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.5.tgz",
- "integrity": "sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-5.5.2.tgz",
+ "integrity": "sha512-o3XYXk7hG8ijUjejgXoa7fuQvzEohMUm4AB5SPBbvq1BhoqIZfW50KlBNjud1zVD4OsA8jJOfjItcY9KfxowuA==",
"dev": true,
"requires": {
- "@lerna/query-graph": "3.18.5",
- "figgy-pudding": "^3.5.1",
- "p-queue": "^4.0.0"
+ "@lerna/query-graph": "5.5.2",
+ "p-queue": "^6.6.2"
}
},
"@lerna/symlink-binary": {
- "version": "3.17.0",
- "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz",
- "integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-5.5.2.tgz",
+ "integrity": "sha512-fQAN0ClwlVLThqm+m9d4lIfa2TuONocdNQocmou8UBDI/C/VVW6dvD+tSL3I4jYIYJWsXJe1hBBjil4ZYXpQrQ==",
"dev": true,
"requires": {
- "@lerna/create-symlink": "3.16.2",
- "@lerna/package": "3.16.0",
- "fs-extra": "^8.1.0",
- "p-map": "^2.1.0"
+ "@lerna/create-symlink": "5.5.2",
+ "@lerna/package": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "p-map": "^4.0.0"
},
"dependencies": {
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
}
}
},
"@lerna/symlink-dependencies": {
- "version": "3.17.0",
- "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz",
- "integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-5.5.2.tgz",
+ "integrity": "sha512-eNIICnlUD1YCiIY50O2TKHkxXCF4rYAFOCVWTiUS098tNKLssTPnIQrK3ASKxK9t7srmfcm49LFxNRPjVKjSBw==",
"dev": true,
"requires": {
- "@lerna/create-symlink": "3.16.2",
- "@lerna/resolve-symlink": "3.16.0",
- "@lerna/symlink-binary": "3.17.0",
- "fs-extra": "^8.1.0",
- "p-finally": "^1.0.0",
- "p-map": "^2.1.0",
- "p-map-series": "^1.0.0"
+ "@lerna/create-symlink": "5.5.2",
+ "@lerna/resolve-symlink": "5.5.2",
+ "@lerna/symlink-binary": "5.5.2",
+ "fs-extra": "^9.1.0",
+ "p-map": "^4.0.0",
+ "p-map-series": "^2.1.0"
},
"dependencies": {
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
+ }
+ },
+ "@lerna/temp-write": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/temp-write/-/temp-write-5.5.2.tgz",
+ "integrity": "sha512-K/9L+25qIw4qw/SSLxwfAWzaUE3luqGTusd3x934Hg2sBQVX28xddwaZlasQ6qen7ETp6Ec9vSVWF2ffWTxKJg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.15",
+ "is-stream": "^2.0.0",
+ "make-dir": "^3.0.0",
+ "temp-dir": "^1.0.0",
+ "uuid": "^8.3.2"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ },
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true
}
}
},
"@lerna/timer": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz",
- "integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-5.5.2.tgz",
+ "integrity": "sha512-QcnMFwcP7xlT9DH4oGVuDYuSOfpAghG4wj7D8vN1GhJFd9ueDCzTFJpFRd6INacIbESBNMjq5WuTeNdxcDo8Fg==",
"dev": true
},
"@lerna/validation-error": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz",
- "integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-5.5.2.tgz",
+ "integrity": "sha512-ZffmtrgOkihUxpho529rDI0llDV9YFNJqh0qF2+doFePeTtFKkFVFHZvxP9hPZPMOLypX9OHwCVfMaTlIpIjjA==",
"dev": true,
"requires": {
- "npmlog": "^4.1.2"
+ "npmlog": "^6.0.2"
}
},
"@lerna/version": {
- "version": "3.22.1",
- "resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.22.1.tgz",
- "integrity": "sha512-PSGt/K1hVqreAFoi3zjD0VEDupQ2WZVlVIwesrE5GbrL2BjXowjCsTDPqblahDUPy0hp6h7E2kG855yLTp62+g==",
- "dev": true,
- "requires": {
- "@lerna/check-working-tree": "3.16.5",
- "@lerna/child-process": "3.16.5",
- "@lerna/collect-updates": "3.20.0",
- "@lerna/command": "3.21.0",
- "@lerna/conventional-commits": "3.22.0",
- "@lerna/github-client": "3.22.0",
- "@lerna/gitlab-client": "3.15.0",
- "@lerna/output": "3.13.0",
- "@lerna/prerelease-id-from-version": "3.16.0",
- "@lerna/prompt": "3.18.5",
- "@lerna/run-lifecycle": "3.16.2",
- "@lerna/run-topologically": "3.18.5",
- "@lerna/validation-error": "3.13.0",
- "chalk": "^2.3.1",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/version/-/version-5.5.2.tgz",
+ "integrity": "sha512-MMO0rnC9Y8JQEl6+XJMu0JM/bWpe6mGNhQJ8C9W1hkpMwxrizhcoEFb9Vq/q/tw7DjCVc3inrb/5s50cRmrmtg==",
+ "dev": true,
+ "requires": {
+ "@lerna/check-working-tree": "5.5.2",
+ "@lerna/child-process": "5.5.2",
+ "@lerna/collect-updates": "5.5.2",
+ "@lerna/command": "5.5.2",
+ "@lerna/conventional-commits": "5.5.2",
+ "@lerna/github-client": "5.5.2",
+ "@lerna/gitlab-client": "5.5.2",
+ "@lerna/output": "5.5.2",
+ "@lerna/prerelease-id-from-version": "5.5.2",
+ "@lerna/prompt": "5.5.2",
+ "@lerna/run-lifecycle": "5.5.2",
+ "@lerna/run-topologically": "5.5.2",
+ "@lerna/temp-write": "5.5.2",
+ "@lerna/validation-error": "5.5.2",
+ "chalk": "^4.1.0",
"dedent": "^0.7.0",
- "load-json-file": "^5.3.0",
+ "load-json-file": "^6.2.0",
"minimatch": "^3.0.4",
- "npmlog": "^4.1.2",
- "p-map": "^2.1.0",
- "p-pipe": "^1.2.0",
- "p-reduce": "^1.0.0",
- "p-waterfall": "^1.0.0",
- "semver": "^6.2.0",
- "slash": "^2.0.0",
- "temp-write": "^3.4.0",
- "write-json-file": "^3.2.0"
+ "npmlog": "^6.0.2",
+ "p-map": "^4.0.0",
+ "p-pipe": "^3.1.0",
+ "p-reduce": "^2.1.0",
+ "p-waterfall": "^2.1.1",
+ "semver": "^7.3.4",
+ "slash": "^3.0.0",
+ "write-json-file": "^4.3.0"
},
"dependencies": {
- "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,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
+ "detect-indent": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+ "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+ "dev": true
},
"graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
"load-json-file": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
- "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz",
+ "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.15",
- "parse-json": "^4.0.0",
- "pify": "^4.0.1",
- "strip-bom": "^3.0.0",
- "type-fest": "^0.3.0"
+ "parse-json": "^5.0.0",
+ "strip-bom": "^4.0.0",
+ "type-fest": "^0.6.0"
}
},
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
- "dev": true
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "sort-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz",
+ "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==",
"dev": true,
"requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
+ "is-plain-obj": "^2.0.0"
}
},
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true
},
- "slash": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
- "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
- "dev": true
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
},
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
+ "write-json-file": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz",
+ "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==",
+ "dev": true,
+ "requires": {
+ "detect-indent": "^6.0.0",
+ "graceful-fs": "^4.1.15",
+ "is-plain-obj": "^2.0.0",
+ "make-dir": "^3.0.0",
+ "sort-keys": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ }
}
}
},
"@lerna/write-log-file": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz",
- "integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==",
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-5.5.2.tgz",
+ "integrity": "sha512-eeW10lriUl3w6WXtYk30z4rZB77QXeQCkLgSMv6Rqa7AMCTZNPhIBJQ0Nkmxo8LaFSWMhin1pLhHTYdqcsaFLA==",
"dev": true,
"requires": {
- "npmlog": "^4.1.2",
- "write-file-atomic": "^2.3.0"
+ "npmlog": "^6.0.2",
+ "write-file-atomic": "^4.0.1"
+ },
+ "dependencies": {
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ }
+ }
}
},
"@mdx-js/mdx": {
@@ -6723,6 +6979,237 @@
"fastq": "^1.6.0"
}
},
+ "@npmcli/arborist": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz",
+ "integrity": "sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==",
+ "dev": true,
+ "requires": {
+ "@isaacs/string-locale-compare": "^1.1.0",
+ "@npmcli/installed-package-contents": "^1.0.7",
+ "@npmcli/map-workspaces": "^2.0.3",
+ "@npmcli/metavuln-calculator": "^3.0.1",
+ "@npmcli/move-file": "^2.0.0",
+ "@npmcli/name-from-folder": "^1.0.1",
+ "@npmcli/node-gyp": "^2.0.0",
+ "@npmcli/package-json": "^2.0.0",
+ "@npmcli/run-script": "^4.1.3",
+ "bin-links": "^3.0.0",
+ "cacache": "^16.0.6",
+ "common-ancestor-path": "^1.0.1",
+ "json-parse-even-better-errors": "^2.3.1",
+ "json-stringify-nice": "^1.1.4",
+ "mkdirp": "^1.0.4",
+ "mkdirp-infer-owner": "^2.0.0",
+ "nopt": "^5.0.0",
+ "npm-install-checks": "^5.0.0",
+ "npm-package-arg": "^9.0.0",
+ "npm-pick-manifest": "^7.0.0",
+ "npm-registry-fetch": "^13.0.0",
+ "npmlog": "^6.0.2",
+ "pacote": "^13.6.1",
+ "parse-conflict-json": "^2.0.1",
+ "proc-log": "^2.0.0",
+ "promise-all-reject-late": "^1.0.0",
+ "promise-call-limit": "^1.0.1",
+ "read-package-json-fast": "^2.0.2",
+ "readdir-scoped-modules": "^1.1.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.7",
+ "ssri": "^9.0.0",
+ "treeverse": "^2.0.0",
+ "walk-up-path": "^1.0.0"
+ },
+ "dependencies": {
+ "@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dev": true,
+ "requires": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ }
+ },
+ "@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dev": true,
+ "requires": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ }
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.1.1"
+ }
+ },
+ "unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^3.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
"@npmcli/fs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
@@ -6733,6 +7220,237 @@
"semver": "^7.3.5"
}
},
+ "@npmcli/git": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz",
+ "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==",
+ "dev": true,
+ "requires": {
+ "@npmcli/promise-spawn": "^3.0.0",
+ "lru-cache": "^7.4.4",
+ "mkdirp": "^1.0.4",
+ "npm-pick-manifest": "^7.0.0",
+ "proc-log": "^2.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@npmcli/installed-package-contents": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz",
+ "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==",
+ "dev": true,
+ "requires": {
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "@npmcli/map-workspaces": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz",
+ "integrity": "sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg==",
+ "dev": true,
+ "requires": {
+ "@npmcli/name-from-folder": "^1.0.1",
+ "glob": "^8.0.1",
+ "minimatch": "^5.0.1",
+ "read-package-json-fast": "^2.0.3"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "@npmcli/metavuln-calculator": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz",
+ "integrity": "sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^16.0.0",
+ "json-parse-even-better-errors": "^2.3.1",
+ "pacote": "^13.0.3",
+ "semver": "^7.3.5"
+ },
+ "dependencies": {
+ "@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dev": true,
+ "requires": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ }
+ },
+ "@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dev": true,
+ "requires": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ }
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.1.1"
+ }
+ },
+ "unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^3.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ }
+ }
+ },
"@npmcli/move-file": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
@@ -6751,6 +7469,78 @@
}
}
},
+ "@npmcli/name-from-folder": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz",
+ "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==",
+ "dev": true
+ },
+ "@npmcli/node-gyp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz",
+ "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==",
+ "dev": true
+ },
+ "@npmcli/package-json": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz",
+ "integrity": "sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==",
+ "dev": true,
+ "requires": {
+ "json-parse-even-better-errors": "^2.3.1"
+ }
+ },
+ "@npmcli/promise-spawn": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz",
+ "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==",
+ "dev": true,
+ "requires": {
+ "infer-owner": "^1.0.4"
+ }
+ },
+ "@npmcli/run-script": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz",
+ "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==",
+ "dev": true,
+ "requires": {
+ "@npmcli/node-gyp": "^2.0.0",
+ "@npmcli/promise-spawn": "^3.0.0",
+ "node-gyp": "^9.0.0",
+ "read-package-json-fast": "^2.0.3",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@nrwl/cli": {
+ "version": "14.7.13",
+ "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-14.7.13.tgz",
+ "integrity": "sha512-roEowDw1TxNsfL/pv752pO/gZrxhfpO1BUQ47madKn/ujupzVe/ropufrT7taDntwQMcHWLrHG3lJyqOexUJIA==",
+ "dev": true,
+ "requires": {
+ "nx": "14.7.13"
+ }
+ },
+ "@nrwl/tao": {
+ "version": "14.7.13",
+ "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-14.7.13.tgz",
+ "integrity": "sha512-nZzbMCNC5UK/Tf7kRbAqdLF5PSqom6aGd3q9m1TKbpxu9ufE5jvK0mF4EDvVJO7LCBnWaLgpZOINRfRPBLGueA==",
+ "dev": true,
+ "requires": {
+ "nx": "14.7.13"
+ }
+ },
"@octokit/auth-token": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.4.tgz",
@@ -6952,48 +7742,60 @@
"dev": true
},
"@octokit/plugin-paginate-rest": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz",
- "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.3.1.tgz",
+ "integrity": "sha512-h8KKxESmSFTcXX409CAxlaOYscEDvN2KGQRsLCGT1NSqRW+D6EXLVQ8vuHhFznS9MuH9QYw1GfsUN30bg8hjVA==",
"dev": true,
"requires": {
- "@octokit/types": "^2.0.1"
+ "@octokit/types": "^7.5.0"
},
"dependencies": {
+ "@octokit/openapi-types": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.12.0.tgz",
+ "integrity": "sha512-1QYzZrwnn3rTQE7ZoSxXrO8lhu0aIbac1c+qIPOPEaVXBWSaUyLV1x9yt4uDQOwmu6u5ywVS8OJgs+ErDLf6vQ==",
+ "dev": true
+ },
"@octokit/types": {
- "version": "2.16.2",
- "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz",
- "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.5.0.tgz",
+ "integrity": "sha512-aHm+olfIZjQpzoODpl+RCZzchKOrdSLJs+yfI7pMMcmB19Li6vidgx0DwUDO/Ic4Q3fq/lOjJORVCcLZefcrJw==",
"dev": true,
"requires": {
- "@types/node": ">= 8"
+ "@octokit/openapi-types": "^13.11.0"
}
}
}
},
"@octokit/plugin-request-log": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz",
- "integrity": "sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
+ "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"dev": true
},
"@octokit/plugin-rest-endpoint-methods": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz",
- "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==",
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.6.2.tgz",
+ "integrity": "sha512-n9dL5KMpz9qVFSNdcVWC8ZPbl68QbTk7+CMPXCXqaMZOLn1n1YuoSFFCy84Ge0fx333fUqpnBHv8BFjwGtUQkA==",
"dev": true,
"requires": {
- "@octokit/types": "^2.0.1",
+ "@octokit/types": "^7.5.0",
"deprecation": "^2.3.1"
},
"dependencies": {
+ "@octokit/openapi-types": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.12.0.tgz",
+ "integrity": "sha512-1QYzZrwnn3rTQE7ZoSxXrO8lhu0aIbac1c+qIPOPEaVXBWSaUyLV1x9yt4uDQOwmu6u5ywVS8OJgs+ErDLf6vQ==",
+ "dev": true
+ },
"@octokit/types": {
- "version": "2.16.2",
- "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz",
- "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.5.0.tgz",
+ "integrity": "sha512-aHm+olfIZjQpzoODpl+RCZzchKOrdSLJs+yfI7pMMcmB19Li6vidgx0DwUDO/Ic4Q3fq/lOjJORVCcLZefcrJw==",
"dev": true,
"requires": {
- "@types/node": ">= 8"
+ "@octokit/openapi-types": "^13.11.0"
}
},
"deprecation": {
@@ -7157,6 +7959,16 @@
"integrity": "sha512-y3MqE6N6Ksg1+YV0sXVpW2WP7Y24h7rUp2hDJuzoqWdKGr7owmRDyHC72INwfCYNzura/vsNPXvc6Xbfp4wGGw==",
"dev": true
},
+ "@parcel/watcher": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz",
+ "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==",
+ "dev": true,
+ "requires": {
+ "node-addon-api": "^3.2.1",
+ "node-gyp-build": "^4.3.0"
+ }
+ },
"@playwright/test": {
"version": "1.25.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.25.1.tgz",
@@ -8151,9 +8963,9 @@
}
},
"@react-native-community/cli-tools": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-6.2.0.tgz",
- "integrity": "sha512-08ssz4GMEnRxC/1FgTTN/Ud7mExQi5xMphItPjfHiTxpZPhrFn+IMx6mya0ncFEhhxQ207wYlJMRLPRRdBZ8oA==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-6.2.1.tgz",
+ "integrity": "sha512-7RbOkZLT/3YG8CAYYM70ajRKIOgVxK/b4t9KNsPq+2uen99MGezfeglC8s1cs3vBNVVxCo0a2JbXg18bUd8eqA==",
"requires": {
"appdirsjs": "^1.2.4",
"chalk": "^4.1.2",
@@ -8162,7 +8974,7 @@
"node-fetch": "^2.6.0",
"open": "^6.2.0",
"semver": "^6.3.0",
- "shell-quote": "1.6.1"
+ "shell-quote": "^1.7.3"
},
"dependencies": {
"ansi-styles": {
@@ -8200,6 +9012,11 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
+ "mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
+ },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -8336,6 +9153,56 @@
"react-native-iphone-x-helper": "^1.2.1"
}
},
+ "@react-spring/animated": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.5.5.tgz",
+ "integrity": "sha512-glzViz7syQ3CE6BQOwAyr75cgh0qsihm5lkaf24I0DfU63cMm/3+br299UEYkuaHNmfDfM414uktiPlZCNJbQA==",
+ "requires": {
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/core": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.5.5.tgz",
+ "integrity": "sha512-shaJYb3iX18Au6gkk8ahaF0qx0LpS0Yd+ajb4asBaAQf6WPGuEdJsbsNSgei1/O13JyEATsJl20lkjeslJPMYA==",
+ "requires": {
+ "@react-spring/animated": "~9.5.5",
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/rafz": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.5.5.tgz",
+ "integrity": "sha512-F/CLwB0d10jL6My5vgzRQxCNY2RNyDJZedRBK7FsngdCmzoq3V4OqqNc/9voJb9qRC2wd55oGXUeXv2eIaFmsw=="
+ },
+ "@react-spring/shared": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.5.5.tgz",
+ "integrity": "sha512-YwW70Pa/YXPOwTutExHZmMQSHcNC90kJOnNR4G4mCDNV99hE98jWkIPDOsgqbYx3amIglcFPiYKMaQuGdr8dyQ==",
+ "requires": {
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/types": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.5.5.tgz",
+ "integrity": "sha512-7I/qY8H7Enwasxr4jU6WmtNK+RZ4Z/XvSlDvjXFVe7ii1x0MoSlkw6pD7xuac8qrHQRm9BTcbZNyeeKApYsvCg=="
+ },
+ "@react-spring/web": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.5.5.tgz",
+ "integrity": "sha512-+moT8aDX/ho/XAhU+HRY9m0LVV9y9CK6NjSRaI+30Re150pB3iEip6QfnF4qnhSCQ5drpMF0XRXHgOTY/xbtFw==",
+ "requires": {
+ "@react-spring/animated": "~9.5.5",
+ "@react-spring/core": "~9.5.5",
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
"@samverschueren/stream-to-observable": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz",
@@ -8361,6 +9228,12 @@
"integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==",
"dev": true
},
+ "@sindresorhus/is": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
+ "dev": true
+ },
"@sinonjs/commons": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
@@ -9793,6 +10666,12 @@
}
}
},
+ "mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true
+ },
"minipass": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
@@ -10136,9 +11015,9 @@
}
},
"terser": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
- "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
+ "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
@@ -12761,6 +13640,12 @@
"semver": "^6.0.0"
}
},
+ "mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true
+ },
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -13131,9 +14016,9 @@
}
},
"terser": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
- "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
+ "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
@@ -14916,9 +15801,9 @@
}
},
"@szmarczak/http-timer": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
- "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==",
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
+ "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"dev": true,
"requires": {
"defer-to-connect": "^2.0.0"
@@ -15265,9 +16150,9 @@
}
},
"@types/cacheable-request": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz",
- "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
+ "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
"dev": true,
"requires": {
"@types/http-cache-semantics": "*",
@@ -15276,15 +16161,6 @@
"@types/responselike": "*"
}
},
- "@types/cheerio": {
- "version": "0.22.29",
- "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.29.tgz",
- "integrity": "sha512-rNX1PsrDPxiNiyLnRKiW2NXHJFHqx0Fl3J2WsZq0MTBspa/FgwlqhXJE2crIcc+/2IglLHtSWw7g053oUR8fOg==",
- "dev": true,
- "requires": {
- "@types/node": "*"
- }
- },
"@types/classnames": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
@@ -15387,9 +16263,9 @@
"dev": true
},
"@types/http-cache-semantics": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
- "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
+ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==",
"dev": true
},
"@types/http-proxy": {
@@ -15487,9 +16363,9 @@
"dev": true
},
"@types/keyv": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz",
- "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -15498,7 +16374,8 @@
"@types/lodash": {
"version": "4.14.172",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz",
- "integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw=="
+ "integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==",
+ "dev": true
},
"@types/mdast": {
"version": "3.0.10",
@@ -15509,6 +16386,12 @@
"@types/unist": "*"
}
},
+ "@types/mime": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
+ "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
+ "dev": true
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -16343,43 +17226,6 @@
"integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==",
"dev": true
},
- "@wojtekmaj/enzyme-adapter-react-17": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.6.3.tgz",
- "integrity": "sha512-Kp1ZJxtHkKEnUksaWrcMABNTOgL4wOt8VI6k2xOek2aH9PtZcWRXJNUEgnKrdJrqg5UqIjRslbVF9uUqwQJtFg==",
- "dev": true,
- "requires": {
- "@wojtekmaj/enzyme-adapter-utils": "^0.1.1",
- "enzyme-shallow-equal": "^1.0.0",
- "has": "^1.0.0",
- "object.assign": "^4.1.0",
- "object.values": "^1.1.0",
- "prop-types": "^15.7.0",
- "react-is": "^17.0.2",
- "react-test-renderer": "^17.0.0"
- },
- "dependencies": {
- "react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true
- }
- }
- },
- "@wojtekmaj/enzyme-adapter-utils": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.1.1.tgz",
- "integrity": "sha512-bNPWtN/d8huKOkC6j1E3EkSamnRrHHT7YuR6f9JppAQqtoAm3v4/vERe4J14jQKmHLCyEBHXrlgb7H6l817hVg==",
- "dev": true,
- "requires": {
- "function.prototype.name": "^1.1.0",
- "has": "^1.0.0",
- "object.assign": "^4.1.0",
- "object.fromentries": "^2.0.0",
- "prop-types": "^15.7.0"
- }
- },
"@wordpress/a11y": {
"version": "file:packages/a11y",
"requires": {
@@ -16476,8 +17322,7 @@
"@wordpress/notices": "file:packages/notices",
"@wordpress/plugins": "file:packages/plugins",
"@wordpress/url": "file:packages/url",
- "change-case": "^4.1.2",
- "lodash": "^4.17.21"
+ "change-case": "^4.1.2"
}
},
"@wordpress/block-editor": {
@@ -16511,7 +17356,6 @@
"@wordpress/url": "file:packages/url",
"@wordpress/warning": "file:packages/warning",
"@wordpress/wordcount": "file:packages/wordcount",
- "change-case": "^4.1.2",
"classnames": "^2.3.1",
"colord": "^2.7.0",
"diff": "^4.0.2",
@@ -16519,67 +17363,10 @@
"inherits": "^2.0.3",
"lodash": "^4.17.21",
"react-autosize-textarea": "^7.1.0",
- "react-easy-crop": "^3.0.0",
+ "react-easy-crop": "^4.5.1",
"rememo": "^4.0.0",
"remove-accents": "^0.4.2",
"traverse": "^0.6.6"
- },
- "dependencies": {
- "@react-spring/animated": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.4.5.tgz",
- "integrity": "sha512-KWqrtvJSMx6Fj9nMJkhTwM9r6LIriExDRV6YHZV9HKQsaolUFppgkOXpC+rsL1JEtEvKv6EkLLmSqHTnuYjiIA==",
- "requires": {
- "@react-spring/shared": "~9.4.5",
- "@react-spring/types": "~9.4.5"
- }
- },
- "@react-spring/core": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.4.5.tgz",
- "integrity": "sha512-83u3FzfQmGMJFwZLAJSwF24/ZJctwUkWtyPD7KYtNagrFeQKUH1I05ZuhmCmqW+2w1KDW1SFWQ43RawqfXKiiQ==",
- "requires": {
- "@react-spring/animated": "~9.4.5",
- "@react-spring/rafz": "~9.4.5",
- "@react-spring/shared": "~9.4.5",
- "@react-spring/types": "~9.4.5"
- }
- },
- "@react-spring/rafz": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.4.5.tgz",
- "integrity": "sha512-swGsutMwvnoyTRxvqhfJBtGM8Ipx6ks0RkIpNX9F/U7XmyPvBMGd3GgX/mqxZUpdlsuI1zr/jiYw+GXZxAlLcQ=="
- },
- "@react-spring/shared": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.4.5.tgz",
- "integrity": "sha512-JhMh3nFKsqyag0KM5IIM8BQANGscTdd0mMv3BXsUiMZrcjQTskyfnv5qxEeGWbJGGar52qr5kHuBHtCjQOzniA==",
- "requires": {
- "@react-spring/rafz": "~9.4.5",
- "@react-spring/types": "~9.4.5"
- }
- },
- "@react-spring/types": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.4.5.tgz",
- "integrity": "sha512-mpRIamoHwql0ogxEUh9yr4TP0xU5CWyZxVQeccGkHHF8kPMErtDXJlxyo0lj+telRF35XNihtPTWoflqtyARmg=="
- },
- "@react-spring/web": {
- "version": "9.4.5",
- "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.4.5.tgz",
- "integrity": "sha512-NGAkOtKmOzDEctL7MzRlQGv24sRce++0xAY7KlcxmeVkR7LRSGkoXHaIfm9ObzxPMcPHQYQhf3+X9jepIFNHQA==",
- "requires": {
- "@react-spring/animated": "~9.4.5",
- "@react-spring/core": "~9.4.5",
- "@react-spring/shared": "~9.4.5",
- "@react-spring/types": "~9.4.5"
- }
- },
- "colord": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.7.0.tgz",
- "integrity": "sha512-pZJBqsHz+pYyw3zpX6ZRXWoCHM1/cvFikY9TV8G3zcejCaKE0lhankoj8iScyrrePA8C7yJ5FStfA9zbcOnw7Q=="
- }
}
},
"@wordpress/block-library": {
@@ -16620,13 +17407,6 @@
"memize": "^1.1.0",
"micromodal": "^0.4.10",
"remove-accents": "^0.4.2"
- },
- "dependencies": {
- "colord": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz",
- "integrity": "sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA=="
- }
}
},
"@wordpress/block-serialization-default-parser": {
@@ -16649,6 +17429,7 @@
"@wordpress/autop": "file:packages/autop",
"@wordpress/blob": "file:packages/blob",
"@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser",
+ "@wordpress/compose": "file:packages/compose",
"@wordpress/data": "file:packages/data",
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/dom": "file:packages/dom",
@@ -16669,13 +17450,6 @@
"showdown": "^1.9.1",
"simple-html-tokenizer": "^0.5.7",
"uuid": "^8.3.0"
- },
- "dependencies": {
- "colord": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz",
- "integrity": "sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA=="
- }
}
},
"@wordpress/browserslist-config": {
@@ -16725,73 +17499,14 @@
"reakit": "^1.3.8",
"remove-accents": "^0.4.2",
"use-lilius": "^2.0.1",
- "uuid": "^8.3.0"
+ "uuid": "^8.3.0",
+ "valtio": "^1.7.0"
},
"dependencies": {
- "@emotion/serialize": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
- "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
- "requires": {
- "@emotion/hash": "^0.8.0",
- "@emotion/memoize": "^0.7.4",
- "@emotion/unitless": "^0.7.5",
- "@emotion/utils": "^1.0.0",
- "csstype": "^3.0.2"
- }
- },
- "colord": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz",
- "integrity": "sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA=="
- },
- "csstype": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
- "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
- },
"date-fns": {
- "version": "2.28.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz",
- "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw=="
- },
- "moment": {
"version": "2.29.3",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
- "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
- },
- "react-dates": {
- "version": "21.8.0",
- "resolved": "https://registry.npmjs.org/react-dates/-/react-dates-21.8.0.tgz",
- "integrity": "sha512-PPriGqi30CtzZmoHiGdhlA++YPYPYGCZrhydYmXXQ6RAvAsaONcPtYgXRTLozIOrsQ5mSo40+DiA5eOFHnZ6xw==",
- "requires": {
- "enzyme-shallow-equal": "^1.0.0",
- "lodash": "^4.1.1",
- "object.assign": "^4.1.0",
- "object.values": "^1.1.0",
- "prop-types": "^15.7.2",
- "raf": "^3.4.1",
- "react-with-styles": "^4.1.0",
- "react-with-styles-interface-css": "^6.0.0"
- }
- },
- "react-with-styles": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/react-with-styles/-/react-with-styles-4.2.0.tgz",
- "integrity": "sha512-tZCTY27KriRNhwHIbg1NkSdTTOSfXDg6Z7s+Q37mtz0Ym7Sc7IOr3PzVt4qJhJMW6Nkvfi3g34FuhtiGAJCBQA==",
- "requires": {
- "hoist-non-react-statics": "^3.2.1",
- "object.assign": "^4.1.0",
- "prop-types": "^15.7.2"
- }
- },
- "react-with-styles-interface-css": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/react-with-styles-interface-css/-/react-with-styles-interface-css-6.0.0.tgz",
- "integrity": "sha512-6khSG1Trf4L/uXOge/ZAlBnq2O2PEXlQEqAhCRbvzaQU4sksIkdwpCPEl6d+DtP3+IdhyffTWuHDO9lhe1iYvA==",
- "requires": {
- "array.prototype.flat": "^1.2.1"
- }
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
+ "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
}
}
},
@@ -16799,7 +17514,6 @@
"version": "file:packages/compose",
"requires": {
"@babel/runtime": "^7.16.0",
- "@types/lodash": "^4.14.172",
"@types/mousetrap": "^1.6.8",
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/dom": "file:packages/dom",
@@ -16809,7 +17523,6 @@
"@wordpress/priority-queue": "file:packages/priority-queue",
"change-case": "^4.1.2",
"clipboard": "^2.0.8",
- "lodash": "^4.17.21",
"mousetrap": "^1.6.5",
"use-memo-one": "^1.1.1"
}
@@ -16985,7 +17698,8 @@
"@wordpress/keycodes": "file:packages/keycodes",
"@wordpress/url": "file:packages/url",
"change-case": "^4.1.2",
- "form-data": "^4.0.0"
+ "form-data": "^4.0.0",
+ "mime": "^3.0.0"
}
},
"@wordpress/e2e-tests": {
@@ -17210,12 +17924,6 @@
"yargs": "^17.3.0"
},
"dependencies": {
- "@sindresorhus/is": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
- "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
- "dev": true
- },
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -17231,27 +17939,6 @@
"color-convert": "^2.0.1"
}
},
- "cacheable-lookup": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
- "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
- "dev": true
- },
- "cacheable-request": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
- "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
- "dev": true,
- "requires": {
- "clone-response": "^1.0.2",
- "get-stream": "^5.1.0",
- "http-cache-semantics": "^4.0.0",
- "keyv": "^4.0.0",
- "lowercase-keys": "^2.0.0",
- "normalize-url": "^6.0.1",
- "responselike": "^2.0.0"
- }
- },
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -17278,64 +17965,18 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dev": true,
- "requires": {
- "mimic-response": "^3.1.0"
- }
- },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
- "got": {
- "version": "11.8.5",
- "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz",
- "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==",
- "dev": true,
- "requires": {
- "@sindresorhus/is": "^4.0.0",
- "@szmarczak/http-timer": "^4.0.5",
- "@types/cacheable-request": "^6.0.1",
- "@types/responselike": "^1.0.0",
- "cacheable-lookup": "^5.0.3",
- "cacheable-request": "^7.0.2",
- "decompress-response": "^6.0.0",
- "http2-wrapper": "^1.0.0-beta.5.2",
- "lowercase-keys": "^2.0.0",
- "p-cancelable": "^2.0.0",
- "responselike": "^2.0.0"
- }
- },
- "http-cache-semantics": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
- "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
- "dev": true
- },
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
- "mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "dev": true
- },
- "normalize-url": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
- "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
- "dev": true
- },
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -17374,9 +18015,9 @@
"dev": true
},
"yargs": {
- "version": "17.3.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
- "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
+ "version": "17.5.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
+ "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
@@ -17389,9 +18030,9 @@
}
},
"yargs-parser": {
- "version": "21.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
- "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true
}
}
@@ -17424,6 +18065,12 @@
"requireindex": "^1.2.0"
}
},
+ "@wordpress/experiments": {
+ "version": "file:packages/experiments",
+ "requires": {
+ "@babel/runtime": "^7.16.0"
+ }
+ },
"@wordpress/format-library": {
"version": "file:packages/format-library",
"requires": {
@@ -17508,11 +18155,8 @@
"version": "file:packages/jest-preset-default",
"dev": true,
"requires": {
- "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"@wordpress/jest-console": "file:packages/jest-console",
- "babel-jest": "^27.4.5",
- "enzyme": "^3.11.0",
- "enzyme-to-json": "^3.4.4"
+ "babel-jest": "^27.4.5"
}
},
"@wordpress/jest-puppeteer-axe": {
@@ -17560,7 +18204,7 @@
"@wordpress/compose": "file:packages/compose",
"@wordpress/element": "file:packages/element",
"@wordpress/i18n": "file:packages/i18n",
- "lodash": "^4.17.21"
+ "change-case": "^4.1.2"
}
},
"@wordpress/media-utils": {
@@ -18102,7 +18746,6 @@
"@wordpress/escape-html": "file:packages/escape-html",
"@wordpress/i18n": "file:packages/i18n",
"@wordpress/keycodes": "file:packages/keycodes",
- "lodash": "^4.17.21",
"memize": "^1.1.0",
"rememo": "^4.0.0"
}
@@ -18166,13 +18809,6 @@
"webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
- },
- "dependencies": {
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
- }
}
},
"@wordpress/server-side-render": {
@@ -18280,15 +18916,22 @@
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"dev": true
},
- "@zkochan/cmd-shim": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz",
- "integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==",
+ "@yarnpkg/parsers": {
+ "version": "3.0.0-rc.21",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.21.tgz",
+ "integrity": "sha512-aM82UlEU12+grklXCyGnMXMqChrW8BDI6DZuw2JjijLyErEqZ/9MjEyYhcn+oz8bKSvudEAe8ygRzkt1cVMOtQ==",
"dev": true,
"requires": {
- "is-windows": "^1.0.0",
- "mkdirp-promise": "^5.0.1",
- "mz": "^2.5.0"
+ "js-yaml": "^3.10.0",
+ "tslib": "^2.4.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ }
}
},
"JSONStream": {
@@ -18392,6 +19035,12 @@
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
"dev": true
},
+ "add-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz",
+ "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==",
+ "dev": true
+ },
"address": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/address/-/address-1.2.0.tgz",
@@ -18405,21 +19054,57 @@
"dev": true
},
"agent-base": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
- "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dev": true,
"requires": {
- "es6-promisify": "^5.0.0"
+ "debug": "4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"agentkeepalive": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
- "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
+ "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
"dev": true,
"requires": {
+ "debug": "^4.1.0",
+ "depd": "^1.1.2",
"humanize-ms": "^1.2.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"aggregate-error": {
@@ -18654,12 +19339,6 @@
"integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
"dev": true
},
- "any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
- "dev": true
- },
"anymatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
@@ -24266,12 +24945,6 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
- "shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
- "dev": true
- },
"shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
@@ -25142,13 +25815,26 @@
}
},
"are-we-there-yet": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
- "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
"dev": true,
"requires": {
"delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
+ "readable-stream": "^3.6.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
}
},
"argparse": {
@@ -25192,22 +25878,17 @@
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
},
"array-differ": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz",
- "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==",
- "dev": true
- },
- "array-filter": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
- "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
"dev": true
},
"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
+ "dev": true,
+ "optional": true
},
"array-flatten": {
"version": "1.1.1",
@@ -25466,16 +26147,6 @@
"integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==",
"dev": true
},
- "array-map": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz",
- "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI="
- },
- "array-reduce": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz",
- "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys="
- },
"array-union": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
@@ -25500,6 +26171,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
"integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
+ "dev": true,
"requires": {
"define-properties": "^1.1.2",
"es-abstract": "^1.10.0",
@@ -27344,6 +28016,44 @@
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
},
+ "bin-links": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz",
+ "integrity": "sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA==",
+ "dev": true,
+ "requires": {
+ "cmd-shim": "^5.0.0",
+ "mkdirp-infer-owner": "^2.0.0",
+ "npm-normalize-package-bin": "^2.0.0",
+ "read-cmd-shim": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "write-file-atomic": "^4.0.0"
+ },
+ "dependencies": {
+ "npm-normalize-package-bin": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
+ "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ }
+ }
+ }
+ },
"binary": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
@@ -27422,12 +28132,6 @@
}
}
},
- "bluebird": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
- "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
- "dev": true
- },
"bn.js": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
@@ -27646,14 +28350,6 @@
"stream-buffers": "2.2.x"
}
},
- "bplist-parser": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.0.tgz",
- "integrity": "sha512-zgmaRvT6AN1JpPPV+S0a1/FAtoxSreYDccZGIqEMSvZl9DMe70mJ7MFzpxa1X+gHVdkToE2haRUHHMiW1OdejA==",
- "requires": {
- "big-integer": "1.6.x"
- }
- },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -27908,16 +28604,10 @@
"integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
"dev": true
},
- "byline": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
- "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=",
- "dev": true
- },
"byte-size": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz",
- "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz",
+ "integrity": "sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==",
"dev": true
},
"bytes": {
@@ -28124,10 +28814,32 @@
"unset-value": "^1.0.0"
}
},
+ "cacheable-lookup": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
+ "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
+ "dev": true
+ },
+ "cacheable-request": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
+ "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
+ "dev": true,
+ "requires": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^4.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^6.0.1",
+ "responselike": "^2.0.0"
+ }
+ },
"call-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz",
"integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==",
+ "dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.0"
@@ -28183,9 +28895,9 @@
}
},
"camelcase": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
- "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"camelcase-css": {
@@ -28199,6 +28911,7 @@
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"dev": true,
+ "optional": true,
"requires": {
"camelcase": "^2.0.0",
"map-obj": "^1.0.0"
@@ -28208,7 +28921,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -28464,32 +29178,6 @@
}
}
},
- "cheerio": {
- "version": "1.0.0-rc.3",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
- "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
- "dev": true,
- "requires": {
- "css-select": "~1.2.0",
- "dom-serializer": "~0.1.1",
- "entities": "~1.1.1",
- "htmlparser2": "^3.9.1",
- "lodash": "^4.15.0",
- "parse5": "^3.0.1"
- },
- "dependencies": {
- "dom-serializer": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
- "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
- "dev": true,
- "requires": {
- "domelementtype": "^1.3.0",
- "entities": "^1.1.1"
- }
- }
- }
- },
"chokidar": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
@@ -28962,20 +29650,21 @@
}
},
"clone-response": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
- "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
"dev": true,
"requires": {
"mimic-response": "^1.0.0"
- },
- "dependencies": {
- "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
- }
+ }
+ },
+ "cmd-shim": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz",
+ "integrity": "sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==",
+ "dev": true,
+ "requires": {
+ "mkdirp-infer-owner": "^2.0.0"
}
},
"co": {
@@ -29064,45 +29753,38 @@
"dev": true
},
"colord": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.4.0.tgz",
- "integrity": "sha512-2306/NeTDOykDwvFQK0ctnP+9I5KQdqVm+IJAM6MsAr4vvy1llAdJyax4YmZoqTxdJ/lvRBwR8MqyJi/tupBAw==",
- "dev": true
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
},
"colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w=="
},
- "colors": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
- "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=",
- "dev": true
- },
"columnify": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz",
- "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz",
+ "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==",
"dev": true,
"requires": {
- "strip-ansi": "^3.0.0",
+ "strip-ansi": "^6.0.1",
"wcwidth": "^1.0.0"
},
"dependencies": {
"ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "ansi-regex": "^5.0.1"
}
}
}
@@ -29139,6 +29821,12 @@
"integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==",
"dev": true
},
+ "common-ancestor-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
+ "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==",
+ "dev": true
+ },
"common-path-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
@@ -29364,9 +30052,9 @@
}
},
"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==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"dev": true,
"requires": {
"ini": "^1.3.4",
@@ -29444,9 +30132,9 @@
"dev": true
},
"conventional-changelog-angular": {
- "version": "5.0.12",
- "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz",
- "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==",
+ "version": "5.0.13",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz",
+ "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==",
"dev": true,
"requires": {
"compare-func": "^2.0.0",
@@ -29454,36 +30142,49 @@
}
},
"conventional-changelog-core": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz",
- "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==",
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz",
+ "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==",
"dev": true,
"requires": {
- "conventional-changelog-writer": "^4.0.6",
- "conventional-commits-parser": "^3.0.3",
+ "add-stream": "^1.0.0",
+ "conventional-changelog-writer": "^5.0.0",
+ "conventional-commits-parser": "^3.2.0",
"dateformat": "^3.0.0",
- "get-pkg-repo": "^1.0.0",
- "git-raw-commits": "2.0.0",
+ "get-pkg-repo": "^4.0.0",
+ "git-raw-commits": "^2.0.8",
"git-remote-origin-url": "^2.0.0",
- "git-semver-tags": "^2.0.3",
- "lodash": "^4.2.1",
- "normalize-package-data": "^2.3.5",
+ "git-semver-tags": "^4.1.1",
+ "lodash": "^4.17.15",
+ "normalize-package-data": "^3.0.0",
"q": "^1.5.1",
"read-pkg": "^3.0.0",
"read-pkg-up": "^3.0.0",
- "through2": "^3.0.0"
+ "through2": "^4.0.0"
},
"dependencies": {
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
},
"load-json-file": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
@@ -29492,10 +30193,31 @@
"strip-bom": "^3.0.0"
}
},
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "normalize-package-data": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
"dev": true,
"requires": {
"error-ex": "^1.3.1",
@@ -29505,45 +30227,87 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
"dev": true
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
"dev": true,
"requires": {
"load-json-file": "^4.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^3.0.0"
+ },
+ "dependencies": {
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"read-pkg-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
+ "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==",
"dev": true,
"requires": {
"find-up": "^2.0.0",
"read-pkg": "^3.0.0"
}
},
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true
},
"through2": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
- "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
"dev": true,
"requires": {
- "inherits": "^2.0.4",
- "readable-stream": "2 || 3"
+ "readable-stream": "3"
}
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
},
@@ -29554,15 +30318,14 @@
"dev": true
},
"conventional-changelog-writer": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz",
- "integrity": "sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz",
+ "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==",
"dev": true,
"requires": {
- "compare-func": "^2.0.0",
"conventional-commits-filter": "^2.0.7",
"dateformat": "^3.0.0",
- "handlebars": "^4.7.6",
+ "handlebars": "^4.7.7",
"json-stringify-safe": "^5.0.1",
"lodash": "^4.17.15",
"meow": "^8.0.0",
@@ -29610,18 +30373,17 @@
}
},
"conventional-commits-parser": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz",
- "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==",
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz",
+ "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==",
"dev": true,
"requires": {
"JSONStream": "^1.0.4",
"is-text-path": "^1.0.1",
"lodash": "^4.17.15",
"meow": "^8.0.0",
- "split2": "^2.0.0",
- "through2": "^4.0.0",
- "trim-off-newlines": "^1.0.0"
+ "split2": "^3.0.0",
+ "through2": "^4.0.0"
},
"dependencies": {
"readable-stream": {
@@ -29647,32 +30409,21 @@
}
},
"conventional-recommended-bump": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz",
- "integrity": "sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz",
+ "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==",
"dev": true,
"requires": {
"concat-stream": "^2.0.0",
- "conventional-changelog-preset-loader": "^2.1.1",
- "conventional-commits-filter": "^2.0.2",
- "conventional-commits-parser": "^3.0.3",
- "git-raw-commits": "2.0.0",
- "git-semver-tags": "^2.0.3",
- "meow": "^4.0.0",
+ "conventional-changelog-preset-loader": "^2.3.4",
+ "conventional-commits-filter": "^2.0.7",
+ "conventional-commits-parser": "^3.2.0",
+ "git-raw-commits": "^2.0.8",
+ "git-semver-tags": "^4.1.1",
+ "meow": "^8.0.0",
"q": "^1.5.1"
},
"dependencies": {
- "camelcase-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
- "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
- "dev": true,
- "requires": {
- "camelcase": "^4.1.0",
- "map-obj": "^2.0.0",
- "quick-lru": "^1.0.0"
- }
- },
"concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
@@ -29685,78 +30436,6 @@
"typedarray": "^0.0.6"
}
},
- "load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- }
- },
- "map-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
- "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
- "dev": true
- },
- "meow": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz",
- "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==",
- "dev": true,
- "requires": {
- "camelcase-keys": "^4.0.0",
- "decamelize-keys": "^1.0.0",
- "loud-rejection": "^1.0.0",
- "minimist": "^1.1.3",
- "minimist-options": "^3.0.1",
- "normalize-package-data": "^2.3.4",
- "read-pkg-up": "^3.0.0",
- "redent": "^2.0.0",
- "trim-newlines": "^2.0.0"
- }
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
- "requires": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- }
- },
- "read-pkg-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
- "dev": true,
- "requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^3.0.0"
- }
- },
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@@ -29767,34 +30446,6 @@
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
- },
- "redent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
- "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
- "dev": true,
- "requires": {
- "indent-string": "^3.0.0",
- "strip-indent": "^2.0.0"
- }
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- },
- "strip-indent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
- "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
- "dev": true
- },
- "trim-newlines": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
- "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=",
- "dev": true
}
}
},
@@ -30507,18 +31158,6 @@
"resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
"integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA="
},
- "css-select": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
- "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
- "dev": true,
- "requires": {
- "boolbase": "~1.0.0",
- "css-what": "2.1",
- "domutils": "1.5.1",
- "nth-check": "~1.0.1"
- }
- },
"css-to-react-native": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz",
@@ -30555,12 +31194,6 @@
}
}
},
- "css-what": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
- "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
- "dev": true
- },
"css.escape": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
@@ -30678,6 +31311,7 @@
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
"dev": true,
+ "optional": true,
"requires": {
"array-find-index": "^1.0.1"
}
@@ -30705,13 +31339,10 @@
"dev": true
},
"dargs": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
- "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true
},
"dashdash": {
"version": "1.14.1",
@@ -30836,6 +31467,23 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
+ "decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^3.1.0"
+ },
+ "dependencies": {
+ "mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true
+ }
+ }
+ },
"dedent": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
@@ -31119,9 +31767,9 @@
}
},
"defer-to-connect": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz",
- "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
"dev": true
},
"define-lazy-prop": {
@@ -31396,9 +32044,9 @@
"dev": true
},
"dezalgo": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
- "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dev": true,
"requires": {
"asap": "^2.0.0",
@@ -31452,12 +32100,6 @@
}
}
},
- "discontinuous-range": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
- "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
- "dev": true
- },
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -31613,12 +32255,20 @@
}
},
"dot-prop": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
- "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
"dev": true,
"requires": {
- "is-obj": "^1.0.0"
+ "is-obj": "^2.0.0"
+ },
+ "dependencies": {
+ "is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true
+ }
}
},
"dotenv": {
@@ -31657,9 +32307,9 @@
}
},
"duplexer": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
- "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
+ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
"dev": true
},
"duplexer2": {
@@ -31840,408 +32490,26 @@
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
},
"env-paths": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
- "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true
},
"envinfo": {
- "version": "7.5.0",
- "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.0.tgz",
- "integrity": "sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
"dev": true
},
- "enzyme": {
- "version": "3.11.0",
- "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz",
- "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==",
- "dev": true,
- "requires": {
- "array.prototype.flat": "^1.2.3",
- "cheerio": "^1.0.0-rc.3",
- "enzyme-shallow-equal": "^1.0.1",
- "function.prototype.name": "^1.1.2",
- "has": "^1.0.3",
- "html-element-map": "^1.2.0",
- "is-boolean-object": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-number-object": "^1.0.4",
- "is-regex": "^1.0.5",
- "is-string": "^1.0.5",
- "is-subset": "^0.1.1",
- "lodash.escape": "^4.0.1",
- "lodash.isequal": "^4.5.0",
- "object-inspect": "^1.7.0",
- "object-is": "^1.0.2",
- "object.assign": "^4.1.0",
- "object.entries": "^1.1.1",
- "object.values": "^1.1.1",
- "raf": "^3.4.1",
- "rst-selector-parser": "^2.2.3",
- "string.prototype.trim": "^1.2.1"
- },
- "dependencies": {
- "array.prototype.flat": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
- "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "dom-serializer": {
- "version": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
- "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
- "requires": {
- "domelementtype": "^1.3.0",
- "entities": "^1.1.1"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "function.prototype.name": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz",
- "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "functions-have-names": "^1.2.0"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
- "is-callable": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
- "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
- "dev": true
- },
- "is-regex": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
- "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "is-string": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
- "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
- "dev": true
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "object-inspect": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
- "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
- "dev": true
- },
- "object-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz",
- "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==",
- "dev": true
- },
- "object.entries": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz",
- "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "object.values": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
- "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "react-is": {
- "version": "16.8.6",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
- "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
- },
- "semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
- },
- "string.prototype.trimleft": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
- "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimstart": "^1.0.0"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "string.prototype.trimright": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
- "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimend": "^1.0.0"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- }
- }
- },
- "enzyme-shallow-equal": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz",
- "integrity": "sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ==",
- "requires": {
- "has": "^1.0.3",
- "object-is": "^1.0.2"
- },
- "dependencies": {
- "object-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz",
- "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ=="
- }
- }
- },
- "enzyme-to-json": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.6.2.tgz",
- "integrity": "sha512-Ynm6Z6R6iwQ0g2g1YToz6DWhxVnt8Dy1ijR2zynRKxTyBGA8rCDXU3rs2Qc4OKvUvc2Qoe1bcFK6bnPs20TrTg==",
- "dev": true,
- "requires": {
- "@types/cheerio": "^0.22.22",
- "lodash": "^4.17.21",
- "react-is": "^16.12.0"
- },
- "dependencies": {
- "react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
- }
- }
- },
"equivalent-key-map": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz",
"integrity": "sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew=="
},
"err-code": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz",
- "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
"dev": true
},
"errno": {
@@ -32282,6 +32550,7 @@
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
"integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+ "dev": true,
"requires": {
"es-to-primitive": "^1.1.1",
"function-bind": "^1.1.1",
@@ -32360,6 +32629,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
"integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+ "dev": true,
"requires": {
"is-callable": "^1.1.1",
"is-date-object": "^1.0.1",
@@ -32372,21 +32642,6 @@
"integrity": "sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==",
"dev": true
},
- "es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
- "dev": true
- },
- "es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
- "dev": true,
- "requires": {
- "es6-promise": "^4.0.3"
- }
- },
"es6-shim": {
"version": "0.35.6",
"resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz",
@@ -33856,9 +34111,9 @@
"integrity": "sha1-+YNhBRexc3wLncZDvsqTiTwE3xg="
},
"eventemitter3": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
- "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"events": {
@@ -35156,6 +35411,12 @@
}
}
},
+ "flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
+ },
"flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -35188,9 +35449,9 @@
}
},
"follow-redirects": {
- "version": "1.14.8",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
- "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true
},
"for-in": {
@@ -35787,71 +36048,77 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
- "functions-have-names": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.1.tgz",
- "integrity": "sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==",
- "dev": true
- },
"gauge": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
- "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
"dev": true,
"requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
},
"dependencies": {
"ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
- "number-is-nan": "^1.0.0"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
}
},
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
+ "ansi-regex": "^5.0.1"
}
},
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"dev": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "string-width": "^1.0.2 || 2 || 3 || 4"
}
}
}
},
- "genfun": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz",
- "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==",
- "dev": true
- },
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -35866,6 +36133,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
"integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
+ "dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -35875,7 +36143,8 @@
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true
}
}
},
@@ -35886,102 +36155,55 @@
"dev": true
},
"get-pkg-repo": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz",
- "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz",
+ "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.1.4",
- "meow": "^3.3.0",
- "normalize-package-data": "^2.3.0",
- "parse-github-repo-url": "^1.3.0",
- "through2": "^2.0.0"
+ "@hutson/parse-repository-url": "^3.0.0",
+ "hosted-git-info": "^4.0.0",
+ "through2": "^2.0.0",
+ "yargs": "^16.2.0"
},
"dependencies": {
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "meow": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
- "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
- "dev": true,
- "requires": {
- "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"
- },
- "dependencies": {
- "read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
- "dev": true,
- "requires": {
- "find-up": "^1.0.0",
- "read-pkg": "^1.0.0"
- }
- }
- }
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
"dev": true,
"requires": {
- "pinkie-promise": "^2.0.0"
+ "lru-cache": "^6.0.0"
}
},
- "path-type": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
- "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
- "graceful-fs": "^4.1.2",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
+ "yallist": "^4.0.0"
}
},
- "read-pkg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
- "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
- "dev": true,
- "requires": {
- "load-json-file": "^1.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^1.0.0"
- }
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
},
"get-port": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz",
- "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
+ "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
"dev": true
},
"get-stdin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"get-stream": {
"version": "5.2.0",
@@ -36067,128 +36289,37 @@
}
},
"git-raw-commits": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz",
- "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==",
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz",
+ "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==",
"dev": true,
"requires": {
- "dargs": "^4.0.1",
- "lodash.template": "^4.0.2",
- "meow": "^4.0.0",
- "split2": "^2.0.0",
- "through2": "^2.0.0"
+ "dargs": "^7.0.0",
+ "lodash": "^4.17.15",
+ "meow": "^8.0.0",
+ "split2": "^3.0.0",
+ "through2": "^4.0.0"
},
"dependencies": {
- "camelcase-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
- "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
- "dev": true,
- "requires": {
- "camelcase": "^4.1.0",
- "map-obj": "^2.0.0",
- "quick-lru": "^1.0.0"
- }
- },
- "load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- }
- },
- "map-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
- "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
- "dev": true
- },
- "meow": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz",
- "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==",
- "dev": true,
- "requires": {
- "camelcase-keys": "^4.0.0",
- "decamelize-keys": "^1.0.0",
- "loud-rejection": "^1.0.0",
- "minimist": "^1.1.3",
- "minimist-options": "^3.0.1",
- "normalize-package-data": "^2.3.4",
- "read-pkg-up": "^3.0.0",
- "redent": "^2.0.0",
- "trim-newlines": "^2.0.0"
- }
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
- "requires": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- }
- },
- "read-pkg-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^3.0.0"
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
}
},
- "redent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
- "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
+ "through2": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
"dev": true,
"requires": {
- "indent-string": "^3.0.0",
- "strip-indent": "^2.0.0"
+ "readable-stream": "3"
}
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- },
- "strip-indent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
- "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
- "dev": true
- },
- "trim-newlines": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
- "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=",
- "dev": true
}
}
},
@@ -36203,151 +36334,40 @@
}
},
"git-semver-tags": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz",
- "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz",
+ "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==",
"dev": true,
"requires": {
- "meow": "^4.0.0",
+ "meow": "^8.0.0",
"semver": "^6.0.0"
},
"dependencies": {
- "camelcase-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
- "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
- "dev": true,
- "requires": {
- "camelcase": "^4.1.0",
- "map-obj": "^2.0.0",
- "quick-lru": "^1.0.0"
- }
- },
- "load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- }
- },
- "map-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
- "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
- "dev": true
- },
- "meow": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz",
- "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==",
- "dev": true,
- "requires": {
- "camelcase-keys": "^4.0.0",
- "decamelize-keys": "^1.0.0",
- "loud-rejection": "^1.0.0",
- "minimist": "^1.1.3",
- "minimist-options": "^3.0.1",
- "normalize-package-data": "^2.3.4",
- "read-pkg-up": "^3.0.0",
- "redent": "^2.0.0",
- "trim-newlines": "^2.0.0"
- }
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
- "requires": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- }
- },
- "read-pkg-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
- "dev": true,
- "requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^3.0.0"
- }
- },
- "redent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
- "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
- "dev": true,
- "requires": {
- "indent-string": "^3.0.0",
- "strip-indent": "^2.0.0"
- }
- },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- },
- "strip-indent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
- "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
- "dev": true
- },
- "trim-newlines": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
- "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=",
- "dev": true
}
}
},
"git-up": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.2.tgz",
- "integrity": "sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz",
+ "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==",
"dev": true,
"requires": {
- "is-ssh": "^1.3.0",
- "parse-url": "^5.0.0"
+ "is-ssh": "^1.4.0",
+ "parse-url": "^8.1.0"
}
},
"git-url-parse": {
- "version": "11.4.3",
- "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.4.3.tgz",
- "integrity": "sha512-LZTTk0nqJnKN48YRtOpR8H5SEfp1oM2tls90NuZmBxN95PnCvmuXGzqQ4QmVirBgKx2KPYfPGteX3/raWjKenQ==",
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz",
+ "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==",
"dev": true,
"requires": {
- "git-up": "^4.0.0"
+ "git-up": "^7.0.0"
}
},
"gitconfiglocal": {
@@ -36570,6 +36590,25 @@
"delegate": "^3.1.2"
}
},
+ "got": {
+ "version": "11.8.5",
+ "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz",
+ "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "^4.0.0",
+ "@szmarczak/http-timer": "^4.0.5",
+ "@types/cacheable-request": "^6.0.1",
+ "@types/responselike": "^1.0.0",
+ "cacheable-lookup": "^5.0.3",
+ "cacheable-request": "^7.0.2",
+ "decompress-response": "^6.0.0",
+ "http2-wrapper": "^1.0.0-beta.5.2",
+ "lowercase-keys": "^2.0.0",
+ "p-cancelable": "^2.0.0",
+ "responselike": "^2.0.0"
+ }
+ },
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
@@ -37146,15 +37185,6 @@
"integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
"dev": true
},
- "html-element-map": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.2.0.tgz",
- "integrity": "sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==",
- "dev": true,
- "requires": {
- "array-filter": "^1.0.0"
- }
- },
"html-encoding-sniffer": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -37220,9 +37250,9 @@
}
},
"terser": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
- "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
+ "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
@@ -37274,20 +37304,6 @@
}
}
},
- "htmlparser2": {
- "version": "3.9.2",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
- "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
- "dev": true,
- "requires": {
- "domelementtype": "^1.3.0",
- "domhandler": "^2.3.0",
- "domutils": "^1.5.1",
- "entities": "^1.1.1",
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.2"
- }
- },
"htmlparser2-without-node-native": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/htmlparser2-without-node-native/-/htmlparser2-without-node-native-3.9.2.tgz",
@@ -37303,9 +37319,9 @@
}
},
"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==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
"dev": true
},
"http-deceiver": {
@@ -37364,13 +37380,37 @@
}
},
"http-proxy-agent": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
- "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
"dev": true,
"requires": {
- "agent-base": "4",
- "debug": "3.1.0"
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "dependencies": {
+ "@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"http-proxy-middleware": {
@@ -37488,13 +37528,30 @@
"dev": true
},
"https-proxy-agent": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
- "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"requires": {
- "agent-base": "^4.3.0",
- "debug": "^3.1.0"
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"human-signals": {
@@ -37586,50 +37643,50 @@
"dev": true
},
"import-local": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
- "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
"dev": true,
"requires": {
- "pkg-dir": "^3.0.0",
- "resolve-cwd": "^2.0.0"
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
},
"dependencies": {
"find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
- "locate-path": "^3.0.0"
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
}
},
"locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
+ "p-locate": "^4.1.0"
}
},
"p-limit": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
- "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
- "p-limit": "^2.0.0"
+ "p-limit": "^2.2.0"
}
},
"p-try": {
@@ -37638,13 +37695,19 @@
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
"pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
"requires": {
- "find-up": "^3.0.0"
+ "find-up": "^4.0.0"
}
}
}
@@ -37693,38 +37756,74 @@
"dev": true
},
"init-package-json": {
- "version": "1.10.3",
- "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz",
- "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz",
+ "integrity": "sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==",
"dev": true,
"requires": {
- "glob": "^7.1.1",
- "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0",
+ "npm-package-arg": "^9.0.1",
"promzard": "^0.3.0",
- "read": "~1.0.1",
- "read-package-json": "1 || 2",
- "semver": "2.x || 3.x || 4 || 5",
- "validate-npm-package-license": "^3.0.1",
- "validate-npm-package-name": "^3.0.0"
+ "read": "^1.0.7",
+ "read-package-json": "^5.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4",
+ "validate-npm-package-name": "^4.0.0"
},
"dependencies": {
- "npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
- "validate-npm-package-name": "^3.0.0"
+ "semver": "^7.0.0"
}
},
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
"dev": true
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
}
}
},
@@ -38109,12 +38208,6 @@
"binary-extensions": "^2.0.0"
}
},
- "is-boolean-object": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz",
- "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==",
- "dev": true
- },
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -38132,7 +38225,8 @@
"is-callable": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
- "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
},
"is-ci": {
"version": "2.0.0",
@@ -38193,7 +38287,8 @@
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
- "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
},
"is-decimal": {
"version": "1.0.2",
@@ -38254,7 +38349,8 @@
"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
+ "dev": true,
+ "optional": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
@@ -38311,6 +38407,12 @@
}
}
},
+ "is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "dev": true
+ },
"is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@@ -38320,7 +38422,8 @@
"is-negative-zero": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
- "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "dev": true
},
"is-number": {
"version": "3.0.0",
@@ -38393,6 +38496,12 @@
}
}
},
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
@@ -38413,6 +38522,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
"requires": {
"has": "^1.0.1"
}
@@ -38442,12 +38552,12 @@
"dev": true
},
"is-ssh": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.2.tgz",
- "integrity": "sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz",
+ "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==",
"dev": true,
"requires": {
- "protocols": "^1.1.0"
+ "protocols": "^2.0.1"
}
},
"is-stream": {
@@ -38461,16 +38571,11 @@
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
"dev": true
},
- "is-subset": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
- "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
- "dev": true
- },
"is-symbol": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
- "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI="
+ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+ "dev": true
},
"is-text-path": {
"version": "1.0.1",
@@ -38487,11 +38592,18 @@
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-weakref": {
"version": "1.0.1",
@@ -42171,6 +42283,12 @@
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
+ "json-stringify-nice": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz",
+ "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==",
+ "dev": true
+ },
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -42205,11 +42323,6 @@
"graceful-fs": "^4.1.6"
}
},
- "jsonify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
- "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
- },
"jsonparse": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
@@ -42373,10 +42486,22 @@
"integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==",
"dev": true
},
+ "just-diff": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-5.1.1.tgz",
+ "integrity": "sha512-u8HXJ3HlNrTzY7zrYYKjNEfBlyjqhdBkoyTVdjtn7p02RJD5NvR8rIClzeGA7t+UYP1/7eAkWNLU0+P3QrEqKQ==",
+ "dev": true
+ },
+ "just-diff-apply": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.4.1.tgz",
+ "integrity": "sha512-AAV5Jw7tsniWwih8Ly3fXxEZ06y+6p5TwQMsw0dzZ/wPKilzyDgdAnL0Ug4NNIquPUOh1vfFWEHbmXUqM5+o8g==",
+ "dev": true
+ },
"keyv": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.0.tgz",
- "integrity": "sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog==",
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.0.tgz",
+ "integrity": "sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==",
"dev": true,
"requires": {
"json-buffer": "3.0.1"
@@ -42465,29 +42590,31 @@
}
},
"lerna": {
- "version": "3.22.1",
- "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.22.1.tgz",
- "integrity": "sha512-vk1lfVRFm+UuEFA7wkLKeSF7Iz13W+N/vFd48aW2yuS7Kv0RbNm2/qcDPV863056LMfkRlsEe+QYOw3palj5Lg==",
- "dev": true,
- "requires": {
- "@lerna/add": "3.21.0",
- "@lerna/bootstrap": "3.21.0",
- "@lerna/changed": "3.21.0",
- "@lerna/clean": "3.21.0",
- "@lerna/cli": "3.18.5",
- "@lerna/create": "3.22.0",
- "@lerna/diff": "3.21.0",
- "@lerna/exec": "3.21.0",
- "@lerna/import": "3.22.0",
- "@lerna/info": "3.21.0",
- "@lerna/init": "3.21.0",
- "@lerna/link": "3.21.0",
- "@lerna/list": "3.21.0",
- "@lerna/publish": "3.22.1",
- "@lerna/run": "3.21.0",
- "@lerna/version": "3.22.1",
- "import-local": "^2.0.0",
- "npmlog": "^4.1.2"
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/lerna/-/lerna-5.5.2.tgz",
+ "integrity": "sha512-P0ThZMfWJ4BP9xRbXaLyoOCYjlPN615FRV2ZBnTBA12lw32IlcREIgvF0N1zZX7wXtsmN56rU3CABoJ5lU8xuw==",
+ "dev": true,
+ "requires": {
+ "@lerna/add": "5.5.2",
+ "@lerna/bootstrap": "5.5.2",
+ "@lerna/changed": "5.5.2",
+ "@lerna/clean": "5.5.2",
+ "@lerna/cli": "5.5.2",
+ "@lerna/create": "5.5.2",
+ "@lerna/diff": "5.5.2",
+ "@lerna/exec": "5.5.2",
+ "@lerna/import": "5.5.2",
+ "@lerna/info": "5.5.2",
+ "@lerna/init": "5.5.2",
+ "@lerna/link": "5.5.2",
+ "@lerna/list": "5.5.2",
+ "@lerna/publish": "5.5.2",
+ "@lerna/run": "5.5.2",
+ "@lerna/version": "5.5.2",
+ "import-local": "^3.0.2",
+ "npmlog": "^6.0.2",
+ "nx": ">=14.6.1 < 16",
+ "typescript": "^3 || ^4"
}
},
"leven": {
@@ -42505,6 +42632,197 @@
"type-check": "~0.3.2"
}
},
+ "libnpmaccess": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.4.tgz",
+ "integrity": "sha512-qZ3wcfIyUoW0+qSFkMBovcTrSGJ3ZeyvpR7d5N9pEYv/kXs8sHP2wiqEIXBKLFrZlmM0kR0RJD7mtfLngtlLag==",
+ "dev": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "minipass": "^3.1.1",
+ "npm-package-arg": "^9.0.1",
+ "npm-registry-fetch": "^13.0.0"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+ "dev": true
+ },
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ }
+ }
+ },
+ "libnpmpublish": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-6.0.5.tgz",
+ "integrity": "sha512-LUR08JKSviZiqrYTDfywvtnsnxr+tOvBU0BF8H+9frt7HMvc6Qn6F8Ubm72g5hDTHbq8qupKfDvDAln2TVPvFg==",
+ "dev": true,
+ "requires": {
+ "normalize-package-data": "^4.0.0",
+ "npm-package-arg": "^9.0.1",
+ "npm-registry-fetch": "^13.0.0",
+ "semver": "^7.3.7",
+ "ssri": "^9.0.0"
+ },
+ "dependencies": {
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz",
+ "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ }
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.1.1"
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
"lilconfig": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz",
@@ -43005,6 +43323,7 @@
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
+ "optional": true,
"requires": {
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
@@ -43018,6 +43337,7 @@
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"dev": true,
+ "optional": true,
"requires": {
"error-ex": "^1.2.0"
}
@@ -43056,18 +43376,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
- "lodash._reinterpolate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
- "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
- "dev": true
- },
- "lodash.clonedeep": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
- "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
- "dev": true
- },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -43085,24 +43393,12 @@
"integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=",
"dev": true
},
- "lodash.escape": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
- "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=",
- "dev": true
- },
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
"dev": true
},
- "lodash.flattendeep": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
- "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
- "dev": true
- },
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -43144,31 +43440,6 @@
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=",
"dev": true
},
- "lodash.sortby": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
- "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
- "dev": true
- },
- "lodash.template": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
- "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
- "dev": true,
- "requires": {
- "lodash._reinterpolate": "^3.0.0",
- "lodash.templatesettings": "^4.0.0"
- }
- },
- "lodash.templatesettings": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
- "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
- "dev": true,
- "requires": {
- "lodash._reinterpolate": "^3.0.0"
- }
- },
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
@@ -43374,6 +43645,7 @@
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
"dev": true,
+ "optional": true,
"requires": {
"currently-unhandled": "^0.4.1",
"signal-exit": "^3.0.0"
@@ -43443,139 +43715,156 @@
}
},
"make-fetch-happen": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz",
- "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==",
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz",
+ "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==",
"dev": true,
"requires": {
- "agentkeepalive": "^3.4.1",
- "cacache": "^12.0.0",
- "http-cache-semantics": "^3.8.1",
- "http-proxy-agent": "^2.1.0",
- "https-proxy-agent": "^2.2.3",
- "lru-cache": "^5.1.1",
- "mississippi": "^3.0.0",
- "node-fetch-npm": "^2.0.2",
- "promise-retry": "^1.1.1",
- "socks-proxy-agent": "^4.0.0",
- "ssri": "^6.0.0"
- },
- "dependencies": {
- "bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "dev": true
+ "agentkeepalive": "^4.2.1",
+ "cacache": "^16.1.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^2.0.3",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.3",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^7.0.0",
+ "ssri": "^9.0.0"
+ },
+ "dependencies": {
+ "@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dev": true,
+ "requires": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ }
+ },
+ "@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
},
"cacache": {
- "version": "12.0.4",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
- "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
"dev": true,
"requires": {
- "bluebird": "^3.5.5",
- "chownr": "^1.1.1",
- "figgy-pudding": "^3.5.1",
- "glob": "^7.1.4",
- "graceful-fs": "^4.1.15",
- "infer-owner": "^1.0.3",
- "lru-cache": "^5.1.1",
- "mississippi": "^3.0.0",
- "mkdirp": "^0.5.1",
- "move-concurrently": "^1.0.1",
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
"promise-inflight": "^1.0.1",
- "rimraf": "^2.6.3",
- "ssri": "^6.0.1",
- "unique-filename": "^1.1.1",
- "y18n": "^4.0.0"
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
}
},
"chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"dev": true
},
"glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
}
},
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
"dev": true
},
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
"dev": true,
"requires": {
- "yallist": "^3.0.2"
+ "brace-expansion": "^2.0.1"
}
},
- "mississippi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
- "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
- "dev": true,
- "requires": {
- "concat-stream": "^1.5.0",
- "duplexify": "^3.4.2",
- "end-of-stream": "^1.1.0",
- "flush-write-stream": "^1.0.0",
- "from2": "^2.1.0",
- "parallel-transform": "^1.1.0",
- "pump": "^3.0.0",
- "pumpify": "^1.3.3",
- "stream-each": "^1.1.0",
- "through2": "^2.0.0"
- }
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
},
- "pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
"dev": true,
"requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
+ "minipass": "^3.1.1"
}
},
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
"dev": true,
"requires": {
- "glob": "^7.1.3"
+ "unique-slug": "^3.0.0"
}
},
- "unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
"dev": true,
"requires": {
- "unique-slug": "^2.0.0"
+ "imurmurhash": "^0.1.4"
}
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
}
}
},
@@ -43605,7 +43894,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"map-or-similar": {
"version": "1.5.0",
@@ -43978,9 +44268,9 @@
"dev": true
},
"meow": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.0.tgz",
- "integrity": "sha512-fNWkgM1UVMey2kf24yLiccxLihc5W+6zVus3/N0b+VfnJgxV99E9u04X6NAiKdg6ED7DAQBX5sy36NM0QJZkWA==",
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
+ "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
"dev": true,
"requires": {
"@types/minimist": "^1.2.0",
@@ -43996,12 +44286,6 @@
"yargs-parser": "^20.2.3"
},
"dependencies": {
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
- },
"camelcase-keys": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
@@ -44013,20 +44297,10 @@
"quick-lru": "^4.0.1"
}
},
- "find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "requires": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- }
- },
"hosted-git-info": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
- "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
@@ -44038,13 +44312,13 @@
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
"dev": true
},
- "locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
"dev": true,
"requires": {
- "p-locate": "^4.1.0"
+ "has": "^1.0.3"
}
},
"lru-cache": {
@@ -44057,153 +44331,23 @@
}
},
"map-obj": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz",
- "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
"dev": true
},
- "minimist-options": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
- "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
- "dev": true,
- "requires": {
- "arrify": "^1.0.1",
- "is-plain-obj": "^1.1.0",
- "kind-of": "^6.0.3"
- },
- "dependencies": {
- "is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "dev": true
- }
- }
- },
"normalize-package-data": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz",
- "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
"dev": true,
"requires": {
- "hosted-git-info": "^3.0.6",
- "resolve": "^1.17.0",
- "semver": "^7.3.2",
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
"validate-npm-package-license": "^3.0.1"
}
},
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "requires": {
- "p-limit": "^2.2.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- },
- "parse-json": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
- "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- }
- },
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
- },
- "quick-lru": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
- "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
- "dev": true
- },
- "read-pkg": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
- "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
- "dev": true,
- "requires": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^2.5.0",
- "parse-json": "^5.0.0",
- "type-fest": "^0.6.0"
- },
- "dependencies": {
- "hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true
- },
- "normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- },
- "type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
- "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
- "dev": true
- }
- }
- },
- "read-pkg-up": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
- "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
- "dev": true,
- "requires": {
- "find-up": "^4.1.0",
- "read-pkg": "^5.2.0",
- "type-fest": "^0.8.1"
- },
- "dependencies": {
- "type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "dev": true
- }
- }
- },
"redent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -44214,16 +44358,6 @@
"strip-indent": "^3.0.0"
}
},
- "resolve": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
- "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
- "dev": true,
- "requires": {
- "is-core-module": "^2.1.0",
- "path-parse": "^1.0.6"
- }
- },
"strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -44234,9 +44368,9 @@
}
},
"trim-newlines": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
- "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
"dev": true
},
"type-fest": {
@@ -44250,12 +44384,6 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
- },
- "yargs-parser": {
- "version": "20.2.4",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
- "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
- "dev": true
}
}
},
@@ -45305,9 +45433,10 @@
}
},
"mime": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
- "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true
},
"mime-db": {
"version": "1.33.0",
@@ -45329,6 +45458,12 @@
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
},
+ "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
+ },
"min-document": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
@@ -45426,13 +45561,14 @@
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"minimist-options": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz",
- "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
"dev": true,
"requires": {
"arrify": "^1.0.1",
- "is-plain-obj": "^1.1.0"
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
},
"dependencies": {
"is-plain-obj": {
@@ -45444,19 +45580,18 @@
}
},
"minipass": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
- "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
+ "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==",
"dev": true,
"requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
+ "yallist": "^4.0.0"
},
"dependencies": {
"yallist": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
- "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
@@ -45487,6 +45622,40 @@
}
}
},
+ "minipass-fetch": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz",
+ "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.13",
+ "minipass": "^3.1.6",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.1.2"
+ },
+ "dependencies": {
+ "encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ }
+ }
+ }
+ },
"minipass-flush": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
@@ -45513,6 +45682,16 @@
}
}
},
+ "minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ }
+ },
"minipass-pipeline": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
@@ -45539,6 +45718,15 @@
}
}
},
+ "minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
"minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
@@ -45664,13 +45852,29 @@
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"dev": true
},
- "mkdirp-promise": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz",
- "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=",
+ "mkdirp-infer-owner": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz",
+ "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==",
"dev": true,
"requires": {
- "mkdirp": "*"
+ "chownr": "^2.0.0",
+ "infer-owner": "^1.0.4",
+ "mkdirp": "^1.0.3"
+ },
+ "dependencies": {
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ }
}
},
"mockdate": {
@@ -45697,12 +45901,6 @@
"moment": ">= 2.9.0"
}
},
- "moo": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
- "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
- "dev": true
- },
"mousetrap": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
@@ -45769,15 +45967,30 @@
"dev": true
},
"multimatch": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz",
- "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
+ "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
"dev": true,
"requires": {
- "array-differ": "^2.0.3",
- "array-union": "^1.0.2",
- "arrify": "^1.0.1",
+ "@types/minimatch": "^3.0.3",
+ "array-differ": "^3.0.0",
+ "array-union": "^2.1.0",
+ "arrify": "^2.0.1",
"minimatch": "^3.0.4"
+ },
+ "dependencies": {
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "dev": true
+ }
}
},
"mustache": {
@@ -45787,22 +46000,11 @@
"dev": true
},
"mute-stream": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
- "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
- "mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
- "requires": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
"nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
@@ -45839,27 +46041,6 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
- "nearley": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz",
- "integrity": "sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw==",
- "dev": true,
- "requires": {
- "moo": "^0.4.3",
- "nomnom": "~1.6.2",
- "railroad-diagrams": "^1.0.0",
- "randexp": "0.4.6",
- "semver": "^5.4.1"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
- "dev": true
- }
- }
- },
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -45924,6 +46105,12 @@
}
}
},
+ "node-addon-api": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
+ "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
+ "dev": true
+ },
"node-dir": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
@@ -45937,23 +46124,76 @@
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
- "node-fetch-npm": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz",
- "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==",
- "dev": true,
- "requires": {
- "encoding": "^0.1.11",
- "json-parse-better-errors": "^1.0.0",
- "safe-buffer": "^5.1.1"
- }
- },
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"dev": true
},
+ "node-gyp": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.1.0.tgz",
+ "integrity": "sha512-HkmN0ZpQJU7FLbJauJTHkHlSVAXlNGDAzH/VYFZGDOnFyn/Na3GlNJfkudmufOdS6/jNFhy88ObzL7ERz9es1g==",
+ "dev": true,
+ "requires": {
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^10.0.3",
+ "nopt": "^5.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "node-gyp-build": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
+ "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
+ "dev": true
+ },
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -46014,14 +46254,13 @@
"integrity": "sha512-OOBiglke5SlRQT5WYfwXTmYqTfXjcTNBHpalyHLtLxDpQYVpVRkJqabcch1kmwJsjV/J4OZuzEafeb4soqtFZA==",
"dev": true
},
- "nomnom": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz",
- "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=",
+ "nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"dev": true,
"requires": {
- "colors": "0.5.x",
- "underscore": "~1.4.4"
+ "abbrev": "1"
}
},
"normalize-package-data": {
@@ -46065,11 +46304,16 @@
"dev": true
},
"normalize-url": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
- "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"dev": true
},
+ "normalize-wheel": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+ "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
+ },
"npm-bundled": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz",
@@ -46079,158 +46323,13 @@
"npm-normalize-package-bin": "^1.0.1"
}
},
- "npm-lifecycle": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz",
- "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==",
+ "npm-install-checks": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz",
+ "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==",
"dev": true,
"requires": {
- "byline": "^5.0.0",
- "graceful-fs": "^4.1.15",
- "node-gyp": "^5.0.2",
- "resolve-from": "^4.0.0",
- "slide": "^1.1.6",
- "uid-number": "0.0.6",
- "umask": "^1.1.0",
- "which": "^1.3.1"
- },
- "dependencies": {
- "fs-minipass": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
- "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
- "dev": true,
- "requires": {
- "minipass": "^2.6.0"
- }
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
- "dev": true
- },
- "minipass": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
- "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
- "dev": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
- "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
- "dev": true,
- "requires": {
- "minipass": "^2.9.0"
- }
- },
- "node-gyp": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz",
- "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==",
- "dev": true,
- "requires": {
- "env-paths": "^2.2.0",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.2",
- "mkdirp": "^0.5.1",
- "nopt": "^4.0.1",
- "npmlog": "^4.1.2",
- "request": "^2.88.0",
- "rimraf": "^2.6.3",
- "semver": "^5.7.1",
- "tar": "^4.4.12",
- "which": "^1.3.1"
- }
- },
- "nopt": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
- "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
- "dev": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- },
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- },
- "tar": {
- "version": "4.4.19",
- "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz",
- "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==",
- "dev": true,
- "requires": {
- "chownr": "^1.1.4",
- "fs-minipass": "^1.2.7",
- "minipass": "^2.9.0",
- "minizlib": "^1.3.3",
- "mkdirp": "^0.5.5",
- "safe-buffer": "^5.2.1",
- "yallist": "^3.1.1"
- },
- "dependencies": {
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- }
- }
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- }
+ "semver": "^7.1.1"
}
},
"npm-normalize-package-bin": {
@@ -46586,33 +46685,129 @@
}
},
"npm-pick-manifest": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz",
- "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==",
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz",
+ "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==",
"dev": true,
"requires": {
- "figgy-pudding": "^3.5.1",
- "npm-package-arg": "^6.0.0",
- "semver": "^5.4.1"
+ "npm-install-checks": "^5.0.0",
+ "npm-normalize-package-bin": "^2.0.0",
+ "npm-package-arg": "^9.0.0",
+ "semver": "^7.3.5"
},
"dependencies": {
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "npm-normalize-package-bin": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
+ "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
+ "dev": true
+ },
"npm-package-arg": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
- "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
"dev": true,
"requires": {
- "hosted-git-info": "^2.7.1",
- "osenv": "^0.1.5",
- "semver": "^5.6.0",
- "validate-npm-package-name": "^3.0.0"
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
}
},
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ }
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "13.3.1",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz",
+ "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==",
+ "dev": true,
+ "requires": {
+ "make-fetch-happen": "^10.0.6",
+ "minipass": "^3.1.6",
+ "minipass-fetch": "^2.0.3",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.1.2",
+ "npm-package-arg": "^9.0.1",
+ "proc-log": "^2.0.0"
+ },
+ "dependencies": {
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
"dev": true
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
}
}
},
@@ -46719,24 +46914,15 @@
}
},
"npmlog": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
- "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
- "dev": true,
- "requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "nth-check": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
- "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
"dev": true,
"requires": {
- "boolbase": "~1.0.0"
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
}
},
"nullthrows": {
@@ -46762,6 +46948,401 @@
"integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
"dev": true
},
+ "nx": {
+ "version": "14.7.13",
+ "resolved": "https://registry.npmjs.org/nx/-/nx-14.7.13.tgz",
+ "integrity": "sha512-NWeZ2fDjx6rkueA/lbu6tK4qfSvp6xrvQtv81Cpyae8BhhkoI36QoxkySJVBetIY/MypDPSl9JHqJwkBju4PQw==",
+ "dev": true,
+ "requires": {
+ "@nrwl/cli": "14.7.13",
+ "@nrwl/tao": "14.7.13",
+ "@parcel/watcher": "2.0.4",
+ "@yarnpkg/lockfile": "^1.1.0",
+ "@yarnpkg/parsers": "^3.0.0-rc.18",
+ "@zkochan/js-yaml": "0.0.6",
+ "chalk": "4.1.0",
+ "chokidar": "^3.5.1",
+ "cli-cursor": "3.1.0",
+ "cli-spinners": "2.6.1",
+ "cliui": "^7.0.2",
+ "dotenv": "~10.0.0",
+ "enquirer": "~2.3.6",
+ "fast-glob": "3.2.7",
+ "figures": "3.2.0",
+ "flat": "^5.0.2",
+ "fs-extra": "^10.1.0",
+ "glob": "7.1.4",
+ "ignore": "^5.0.4",
+ "js-yaml": "4.1.0",
+ "jsonc-parser": "3.2.0",
+ "minimatch": "3.0.5",
+ "npm-run-path": "^4.0.1",
+ "open": "^8.4.0",
+ "semver": "7.3.4",
+ "string-width": "^4.2.3",
+ "strong-log-transformer": "^2.1.0",
+ "tar-stream": "~2.2.0",
+ "tmp": "~0.2.1",
+ "tsconfig-paths": "^3.9.0",
+ "tslib": "^2.3.0",
+ "v8-compile-cache": "2.3.0",
+ "yargs": "^17.4.0",
+ "yargs-parser": "21.0.1"
+ },
+ "dependencies": {
+ "@zkochan/js-yaml": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz",
+ "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
+ "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "jsonc-parser": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
+ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
+ "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
+ "dev": true,
+ "requires": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ }
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "requires": {
+ "rimraf": "^3.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "17.5.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
+ "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.0.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz",
+ "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==",
+ "dev": true
+ }
+ }
+ },
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@@ -47469,6 +48050,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz",
"integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==",
+ "dev": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
@@ -47480,6 +48062,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
"requires": {
"object-keys": "^1.0.12"
}
@@ -47488,6 +48071,7 @@
"version": "1.18.0-next.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
"integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
+ "dev": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@@ -47509,6 +48093,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@@ -47517,7 +48102,8 @@
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
}
}
},
@@ -47525,6 +48111,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@@ -47534,17 +48121,20 @@
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true
},
"is-callable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
- "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
+ "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==",
+ "dev": true
},
"is-regex": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "dev": true,
"requires": {
"has-symbols": "^1.0.1"
}
@@ -47553,6 +48143,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "dev": true,
"requires": {
"has-symbols": "^1.0.1"
}
@@ -47560,12 +48151,14 @@
"object-inspect": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
- "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
+ "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==",
+ "dev": true
},
"object.assign": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
@@ -47576,7 +48169,8 @@
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
}
}
},
@@ -47584,6 +48178,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
"integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==",
+ "dev": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
@@ -47784,16 +48379,6 @@
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
- "osenv": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
- "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
- "dev": true,
- "requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
- },
"overlayscrollbars": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz",
@@ -47818,9 +48403,9 @@
}
},
"p-cancelable": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz",
- "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
+ "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
"dev": true
},
"p-defer": {
@@ -47888,33 +48473,42 @@
}
},
"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,
- "requires": {
- "p-reduce": "^1.0.0"
- }
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz",
+ "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==",
+ "dev": true
},
"p-pipe": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz",
- "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz",
+ "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==",
"dev": true
},
"p-queue": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-4.0.0.tgz",
- "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==",
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
+ "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
"dev": true,
"requires": {
- "eventemitter3": "^3.1.0"
+ "eventemitter3": "^4.0.4",
+ "p-timeout": "^3.2.0"
+ },
+ "dependencies": {
+ "p-timeout": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
+ "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0"
+ }
+ }
}
},
"p-reduce": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz",
- "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz",
+ "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==",
"dev": true
},
"p-retry": {
@@ -47951,12 +48545,240 @@
"dev": true
},
"p-waterfall": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-1.0.0.tgz",
- "integrity": "sha1-ftlLPOszMngjU69qrhGqn8I1uwA=",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz",
+ "integrity": "sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==",
"dev": true,
"requires": {
- "p-reduce": "^1.0.0"
+ "p-reduce": "^2.0.0"
+ }
+ },
+ "pacote": {
+ "version": "13.6.2",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz",
+ "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==",
+ "dev": true,
+ "requires": {
+ "@npmcli/git": "^3.0.0",
+ "@npmcli/installed-package-contents": "^1.0.7",
+ "@npmcli/promise-spawn": "^3.0.0",
+ "@npmcli/run-script": "^4.1.0",
+ "cacache": "^16.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "infer-owner": "^1.0.4",
+ "minipass": "^3.1.6",
+ "mkdirp": "^1.0.4",
+ "npm-package-arg": "^9.0.0",
+ "npm-packlist": "^5.1.0",
+ "npm-pick-manifest": "^7.0.0",
+ "npm-registry-fetch": "^13.0.1",
+ "proc-log": "^2.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json": "^5.0.0",
+ "read-package-json-fast": "^2.0.3",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11"
+ },
+ "dependencies": {
+ "@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dev": true,
+ "requires": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ }
+ },
+ "@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dev": true,
+ "requires": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ }
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "ignore-walk": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz",
+ "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "npm-bundled": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz",
+ "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==",
+ "dev": true,
+ "requires": {
+ "npm-normalize-package-bin": "^2.0.0"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
+ "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz",
+ "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "proc-log": "^2.0.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^4.0.0"
+ }
+ },
+ "npm-packlist": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz",
+ "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==",
+ "dev": true,
+ "requires": {
+ "glob": "^8.0.1",
+ "ignore-walk": "^5.0.1",
+ "npm-bundled": "^2.0.0",
+ "npm-normalize-package-bin": "^2.0.0"
+ }
+ },
+ "ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.1.1"
+ }
+ },
+ "unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^3.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz",
+ "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ }
}
},
"pako": {
@@ -48006,6 +48828,17 @@
"safe-buffer": "^5.1.1"
}
},
+ "parse-conflict-json": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz",
+ "integrity": "sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==",
+ "dev": true,
+ "requires": {
+ "json-parse-even-better-errors": "^2.3.1",
+ "just-diff": "^5.0.1",
+ "just-diff-apply": "^5.2.0"
+ }
+ },
"parse-entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz",
@@ -48020,12 +48853,6 @@
"is-hexadecimal": "^1.0.0"
}
},
- "parse-github-repo-url": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz",
- "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=",
- "dev": true
- },
"parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -48045,34 +48872,21 @@
"dev": true
},
"parse-path": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.2.tgz",
- "integrity": "sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz",
+ "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==",
"dev": true,
"requires": {
- "is-ssh": "^1.3.0",
- "protocols": "^1.4.0"
+ "protocols": "^2.0.0"
}
},
"parse-url": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.2.tgz",
- "integrity": "sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA==",
- "dev": true,
- "requires": {
- "is-ssh": "^1.3.0",
- "normalize-url": "^3.3.0",
- "parse-path": "^4.0.0",
- "protocols": "^1.4.0"
- }
- },
- "parse5": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
- "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz",
+ "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==",
"dev": true,
"requires": {
- "@types/node": "*"
+ "parse-path": "^7.0.0"
}
},
"parseurl": {
@@ -48283,7 +49097,8 @@
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
},
"phpegjs": {
"version": "1.0.0-beta7",
@@ -48484,14 +49299,6 @@
"nanoid": "^3.1.30",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.1"
- },
- "dependencies": {
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true
- }
}
},
"postcss-calc": {
@@ -49179,6 +49986,12 @@
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
},
+ "proc-log": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz",
+ "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==",
+ "dev": true
+ },
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -49196,6 +50009,18 @@
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
+ "promise-all-reject-late": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "dev": true
+ },
+ "promise-call-limit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz",
+ "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==",
+ "dev": true
+ },
"promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@@ -49203,13 +50028,13 @@
"dev": true
},
"promise-retry": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
- "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
"dev": true,
"requires": {
- "err-code": "^1.0.0",
- "retry": "^0.10.0"
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
}
},
"promise.allsettled": {
@@ -49742,20 +50567,11 @@
"dev": true
},
"protocols": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz",
- "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz",
+ "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==",
"dev": true
},
- "protoduck": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
- "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
- "dev": true,
- "requires": {
- "genfun": "^5.0.0"
- }
- },
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@@ -49766,6 +50582,11 @@
"ipaddr.js": "1.9.1"
}
},
+ "proxy-compare": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz",
+ "integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ=="
+ },
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -50065,23 +50886,9 @@
"dev": true
},
"quick-lru": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
- "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
- "dev": true
- },
- "raf": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
- "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
- "requires": {
- "performance-now": "^2.1.0"
- }
- },
- "railroad-diagrams": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
- "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
"dev": true
},
"ramda": {
@@ -50090,16 +50897,6 @@
"integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==",
"dev": true
},
- "randexp": {
- "version": "0.4.6",
- "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
- "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
- "dev": true,
- "requires": {
- "discontinuous-range": "1.0.0",
- "ret": "~0.1.10"
- }
- },
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -50321,17 +51118,18 @@
}
},
"react-easy-crop": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-3.0.0.tgz",
- "integrity": "sha512-aP+G2W4WNE4IPRX/YPXna4gsoR+usLilGX/hepzzntZkD+rD1XaziPNOQH6z26NZKdQRDT4Avh37R5cnGmyRHQ==",
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-4.5.1.tgz",
+ "integrity": "sha512-MVzCWmKXTwZTK0iYqlF/gPLdLqvUGrLGX7SQ4g+DO3b/lCiVAwxZKLeZ1wjDfG+r/yEWUoL7At5a0kkDJeU+rQ==",
"requires": {
- "tslib": "1.11.2"
+ "normalize-wheel": "^1.0.1",
+ "tslib": "2.0.1"
},
"dependencies": {
"tslib": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.2.tgz",
- "integrity": "sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg=="
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
+ "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
}
}
},
@@ -50896,35 +51694,116 @@
}
},
"read-cmd-shim": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz",
- "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2"
- }
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz",
+ "integrity": "sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g==",
+ "dev": true
},
"read-package-json": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz",
- "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz",
+ "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==",
"dev": true,
"requires": {
- "glob": "^7.1.1",
- "json-parse-even-better-errors": "^2.3.0",
- "normalize-package-data": "^2.0.0",
- "npm-normalize-package-bin": "^1.0.0"
+ "glob": "^8.0.1",
+ "json-parse-even-better-errors": "^2.3.1",
+ "normalize-package-data": "^4.0.0",
+ "npm-normalize-package-bin": "^2.0.0"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz",
+ "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ }
+ },
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "lru-cache": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz",
+ "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz",
+ "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^5.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
+ "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ }
}
},
- "read-package-tree": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz",
- "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==",
+ "read-package-json-fast": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz",
+ "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==",
"dev": true,
"requires": {
- "read-package-json": "^2.0.0",
- "readdir-scoped-modules": "^1.0.0",
- "util-promisify": "^2.1.0"
+ "json-parse-even-better-errors": "^2.3.0",
+ "npm-normalize-package-bin": "^1.0.1"
}
},
"read-pkg": {
@@ -51147,6 +52026,7 @@
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
"dev": true,
+ "optional": true,
"requires": {
"indent-string": "^2.1.0",
"strip-indent": "^1.0.1"
@@ -51157,6 +52037,7 @@
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
"dev": true,
+ "optional": true,
"requires": {
"repeating": "^2.0.0"
}
@@ -51937,6 +52818,7 @@
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
"dev": true,
+ "optional": true,
"requires": {
"is-finite": "^1.0.0"
}
@@ -52086,12 +52968,20 @@
}
},
"resolve-cwd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
- "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
"dev": true,
"requires": {
- "resolve-from": "^3.0.0"
+ "resolve-from": "^5.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ }
}
},
"resolve-dir": {
@@ -52151,9 +53041,9 @@
"dev": true
},
"responselike": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
- "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
+ "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
"dev": true,
"requires": {
"lowercase-keys": "^2.0.0"
@@ -52174,9 +53064,9 @@
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
},
"retry": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
- "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
"dev": true
},
"reusify": {
@@ -52232,16 +53122,6 @@
"inherits": "^2.0.1"
}
},
- "rst-selector-parser": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
- "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
- "dev": true,
- "requires": {
- "lodash.flattendeep": "^4.4.0",
- "nearley": "^2.7.10"
- }
- },
"rsvp": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz",
@@ -52291,21 +53171,10 @@
}
},
"run-async": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
- "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
- "dev": true,
- "requires": {
- "is-promise": "^2.1.0"
- },
- "dependencies": {
- "is-promise": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
- "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
- "dev": true
- }
- }
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true
},
"run-con": {
"version": "1.2.10",
@@ -52934,22 +53803,9 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
},
"shell-quote": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz",
- "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=",
- "requires": {
- "array-filter": "~0.0.0",
- "array-map": "~0.0.0",
- "array-reduce": "~0.0.0",
- "jsonify": "~0.0.0"
- },
- "dependencies": {
- "array-filter": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz",
- "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw="
- }
- }
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw=="
},
"showdown": {
"version": "1.9.1",
@@ -53134,13 +53990,23 @@
"integrity": "sha512-APW9iYbkJ5cijjX4Ljhf3VG8SwYPUJT5gZrwci/wieMabQxWFiV5VwsrP5c6GMRvXKEQMGkAB1d9dvW66dTqpg=="
},
"simple-plist": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.0.tgz",
- "integrity": "sha512-uYWpeGFtZtVt2NhG4AHgpwx323zxD85x42heMJBan1qAiqqozIlaGrwrEt6kRjXWRWIXsuV1VLCvVmZan2B5dg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz",
+ "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==",
"requires": {
"bplist-creator": "0.1.0",
- "bplist-parser": "0.3.0",
- "plist": "^3.0.4"
+ "bplist-parser": "0.3.1",
+ "plist": "^3.0.5"
+ },
+ "dependencies": {
+ "bplist-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
+ "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "requires": {
+ "big-integer": "1.6.x"
+ }
+ }
}
},
"simple-swizzle": {
@@ -53167,6 +54033,14 @@
"@polka/url": "^1.0.0-next.15",
"mime": "^2.3.1",
"totalist": "^1.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true
+ }
}
},
"sisteransi": {
@@ -53186,16 +54060,10 @@
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
"dev": true
},
- "slide": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
- "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
- "dev": true
- },
"smart-buffer": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz",
- "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"dev": true
},
"snake-case": {
@@ -53679,33 +54547,48 @@
}
},
"socks": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz",
- "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
+ "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==",
"dev": true,
"requires": {
- "ip": "1.1.5",
- "smart-buffer": "^4.1.0"
+ "ip": "^2.0.0",
+ "smart-buffer": "^4.2.0"
+ },
+ "dependencies": {
+ "ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+ "dev": true
+ }
}
},
"socks-proxy-agent": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz",
- "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
"dev": true,
"requires": {
- "agent-base": "~4.2.1",
- "socks": "~2.3.2"
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
},
"dependencies": {
- "agent-base": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
- "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": {
- "es6-promisify": "^5.0.0"
+ "ms": "2.1.2"
}
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
}
}
},
@@ -53738,9 +54621,9 @@
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-js": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
- "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true
},
"source-map-loader": {
@@ -53762,6 +54645,12 @@
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
+ },
+ "source-map-js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
+ "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
+ "dev": true
}
}
},
@@ -53962,12 +54851,25 @@
}
},
"split2": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
- "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
+ "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
"dev": true,
"requires": {
- "through2": "^2.0.2"
+ "readable-stream": "^3.0.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
}
},
"sprintf-js": {
@@ -54828,245 +55730,11 @@
}
}
},
- "string.prototype.trim": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz",
- "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1"
- },
- "dependencies": {
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- },
- "dependencies": {
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
- "is-callable": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
- "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
- "dev": true
- },
- "is-regex": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
- "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "object-inspect": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
- "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
- "dev": true
- },
- "string.prototype.trimleft": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
- "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimstart": "^1.0.0"
- }
- },
- "string.prototype.trimright": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
- "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimend": "^1.0.0"
- }
- }
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz",
- "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- },
- "dependencies": {
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
- },
- "dependencies": {
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- }
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
- "is-callable": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
- "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
- "dev": true
- },
- "is-regex": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
- "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "object-inspect": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
- "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
- "dev": true
- },
- "string.prototype.trimleft": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
- "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimstart": "^1.0.0"
- }
- },
- "string.prototype.trimright": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
- "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimend": "^1.0.0"
- }
- }
- }
- },
"string.prototype.trimstart": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz",
"integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==",
+ "dev": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
@@ -55076,6 +55744,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
"requires": {
"object-keys": "^1.0.12"
}
@@ -55127,6 +55796,7 @@
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
"dev": true,
+ "optional": true,
"requires": {
"is-utf8": "^0.2.0"
}
@@ -55147,6 +55817,7 @@
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
"dev": true,
+ "optional": true,
"requires": {
"get-stdin": "^4.0.1"
}
@@ -55314,12 +55985,6 @@
"quick-lru": "^4.0.1"
}
},
- "colord": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz",
- "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==",
- "dev": true
- },
"cosmiconfig": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
@@ -55620,11 +56285,6 @@
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true
},
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
- },
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -56472,43 +57132,6 @@
"integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=",
"dev": true
},
- "temp-write": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz",
- "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "is-stream": "^1.1.0",
- "make-dir": "^1.0.0",
- "pify": "^3.0.0",
- "temp-dir": "^1.0.0",
- "uuid": "^3.0.1"
- },
- "dependencies": {
- "make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
- "dev": true,
- "requires": {
- "pify": "^3.0.0"
- }
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "dev": true
- }
- }
- },
"terminal-link": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz",
@@ -56537,9 +57160,9 @@
}
},
"terser": {
- "version": "4.6.3",
- "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
- "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz",
+ "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@@ -56581,6 +57204,12 @@
"integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==",
"dev": true
},
+ "acorn": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+ "dev": true
+ },
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -56660,14 +57289,12 @@
"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
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
- "dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -56683,21 +57310,26 @@
}
},
"terser": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz",
- "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
+ "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
+ "@jridgewell/source-map": "^0.3.2",
+ "acorn": "^8.5.0",
"commander": "^2.20.0",
- "source-map": "~0.7.2",
- "source-map-support": "~0.5.19"
+ "source-map-support": "~0.5.20"
},
"dependencies": {
- "source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
- "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
- "dev": true
+ "source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
}
}
}
@@ -56742,24 +57374,6 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
- "thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
- "requires": {
- "any-promise": "^1.0.0"
- }
- },
- "thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
- "dev": true,
- "requires": {
- "thenify": ">= 3.1.0 < 4"
- }
- },
"throat": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
@@ -56917,13 +57531,10 @@
}
},
"tr46": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
- "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
},
"traverse": {
"version": "0.6.6",
@@ -56936,6 +57547,12 @@
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
+ "treeverse": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz",
+ "integrity": "sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==",
+ "dev": true
+ },
"trim": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
@@ -56946,13 +57563,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
- "dev": true
- },
- "trim-off-newlines": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.3.tgz",
- "integrity": "sha512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"trim-repeated": {
"version": "1.0.0",
@@ -57093,9 +57705,9 @@
"dev": true
},
"type-fest": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
- "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
"dev": true
},
"type-is": {
@@ -57158,23 +57770,11 @@
"integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==",
"dev": true
},
- "uid-number": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
- "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=",
- "dev": true
- },
"ultron": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
},
- "umask": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz",
- "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=",
- "dev": true
- },
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -57229,12 +57829,6 @@
}
}
},
- "underscore": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
- "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=",
- "dev": true
- },
"unfetch": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz",
@@ -57524,7 +58118,8 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"upper-case": {
"version": "2.0.2",
@@ -57738,6 +58333,11 @@
"object-assign": "^4.1.1"
}
},
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
+ },
"util": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
@@ -57752,15 +58352,6 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
- "util-promisify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz",
- "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=",
- "dev": true,
- "requires": {
- "object.getownpropertydescriptors": "^2.0.3"
- }
- },
"util.promisify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
@@ -57851,6 +58442,15 @@
"builtins": "^1.0.3"
}
},
+ "valtio": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.7.0.tgz",
+ "integrity": "sha512-3Tnix66EERwMcrl1rfB3ylcewOcL5L/GiPmC3FlVNreQzqf2jufEeqlNmgnLgSGchkEmH3WYVtS+x6Qw4r+yzQ==",
+ "requires": {
+ "proxy-compare": "2.3.0",
+ "use-sync-external-store": "1.2.0"
+ }
+ },
"vargs": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz",
@@ -57990,6 +58590,12 @@
}
}
},
+ "walk-up-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz",
+ "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==",
+ "dev": true
+ },
"walker": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
@@ -58154,9 +58760,9 @@
"dev": true
},
"webidl-conversions": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
- "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true
},
"webpack": {
@@ -59252,14 +59858,13 @@
"dev": true
},
"whatwg-url": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
- "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"requires": {
- "lodash.sortby": "^4.7.0",
- "tr46": "^1.0.1",
- "webidl-conversions": "^4.0.2"
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
}
},
"whatwg-url-without-unicode": {
diff --git a/package.json b/package.json
index 07ab29258c7a66..694058c486f007 100755
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gutenberg",
- "version": "14.2.0-rc.1",
+ "version": "14.3.0-rc.1",
"private": true,
"description": "A new WordPress editor experience.",
"author": "The WordPress Contributors",
@@ -50,6 +50,7 @@
"@wordpress/editor": "file:packages/editor",
"@wordpress/element": "file:packages/element",
"@wordpress/escape-html": "file:packages/escape-html",
+ "@wordpress/experiments": "file:packages/experiments",
"@wordpress/format-library": "file:packages/format-library",
"@wordpress/hooks": "file:packages/hooks",
"@wordpress/html-entities": "file:packages/html-entities",
@@ -121,6 +122,7 @@
"@types/highlight-words-core": "1.2.1",
"@types/istanbul-lib-report": "3.0.0",
"@types/lodash": "4.14.172",
+ "@types/mime": "2.0.3",
"@types/npm-package-arg": "6.1.1",
"@types/prettier": "2.4.4",
"@types/qs": "6.9.7",
@@ -178,7 +180,6 @@
"css-loader": "6.2.0",
"cssnano": "5.0.7",
"deep-freeze": "0.0.1",
- "enzyme": "3.11.0",
"equivalent-key-map": "0.2.2",
"eslint-import-resolver-node": "0.3.4",
"eslint-plugin-eslint-comments": "3.1.2",
@@ -196,7 +197,7 @@
"jest-message-util": "27.4.2",
"jest-watch-typeahead": "1.0.0",
"jsdom": "16.7.0",
- "lerna": "3.22.1",
+ "lerna": "5.5.2",
"lint-staged": "10.0.1",
"lodash": "4.17.21",
"make-dir": "3.0.0",
diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss
index 95373ddd92b1f9..50af0938bccdb8 100644
--- a/packages/base-styles/_mixins.scss
+++ b/packages/base-styles/_mixins.scss
@@ -203,8 +203,19 @@
}
@mixin placeholder-style() {
- border: $border-width dashed currentColor;
border-radius: $radius-block-ui;
+
+ &::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ pointer-events: none;
+ background: currentColor;
+ opacity: 0.1;
+ }
}
/**
diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json
index 49fb91781a0c2c..d80cdd371a1959 100644
--- a/packages/block-directory/package.json
+++ b/packages/block-directory/package.json
@@ -44,8 +44,7 @@
"@wordpress/notices": "file:../notices",
"@wordpress/plugins": "file:../plugins",
"@wordpress/url": "file:../url",
- "change-case": "^4.1.2",
- "lodash": "^4.17.21"
+ "change-case": "^4.1.2"
},
"peerDependencies": {
"react": "^17.0.0",
diff --git a/packages/block-directory/src/plugins/get-install-missing/index.js b/packages/block-directory/src/plugins/get-install-missing/index.js
index 1d1eb9e0bbdd2b..58d6cdb1a188cb 100644
--- a/packages/block-directory/src/plugins/get-install-missing/index.js
+++ b/packages/block-directory/src/plugins/get-install-missing/index.js
@@ -100,7 +100,7 @@ const ModifiedWarning = ( { originalBlock, ...props } ) => {
originalBlock.title || originalName
);
actions.push(
-
+
{ __( 'Keep as HTML' ) }
);
diff --git a/packages/block-directory/src/store/actions.js b/packages/block-directory/src/store/actions.js
index a7f39c8c430615..6e8ec13002acb4 100644
--- a/packages/block-directory/src/store/actions.js
+++ b/packages/block-directory/src/store/actions.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { pick } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -119,7 +114,11 @@ export const installBlockType =
return;
}
unstable__bootstrapServerSideBlockDefinitions( {
- [ name ]: pick( response, metadataFields ),
+ [ name ]: Object.fromEntries(
+ Object.entries( response ).filter( ( [ key ] ) =>
+ metadataFields.includes( key )
+ )
+ ),
} );
} );
diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json
index b50a049ef267a0..0e8b9668ed49c0 100644
--- a/packages/block-editor/package.json
+++ b/packages/block-editor/package.json
@@ -59,7 +59,6 @@
"@wordpress/url": "file:../url",
"@wordpress/warning": "file:../warning",
"@wordpress/wordcount": "file:../wordcount",
- "change-case": "^4.1.2",
"classnames": "^2.3.1",
"colord": "^2.7.0",
"diff": "^4.0.2",
@@ -67,7 +66,7 @@
"inherits": "^2.0.3",
"lodash": "^4.17.21",
"react-autosize-textarea": "^7.1.0",
- "react-easy-crop": "^3.0.0",
+ "react-easy-crop": "^4.5.1",
"rememo": "^4.0.0",
"remove-accents": "^0.4.2",
"traverse": "^0.6.6"
diff --git a/packages/block-editor/src/components/block-controls/slot.js b/packages/block-editor/src/components/block-controls/slot.js
index 72621eb21c7358..c8cb65848e9f77 100644
--- a/packages/block-editor/src/components/block-controls/slot.js
+++ b/packages/block-editor/src/components/block-controls/slot.js
@@ -5,7 +5,7 @@ import { useContext } from '@wordpress/element';
import {
__experimentalToolbarContext as ToolbarContext,
ToolbarGroup,
- __experimentalUseSlot as useSlot,
+ __experimentalUseSlotFills as useSlotFills,
} from '@wordpress/components';
/**
@@ -16,8 +16,8 @@ import groups from './groups';
export default function BlockControlsSlot( { group = 'default', ...props } ) {
const accessibleToolbarState = useContext( ToolbarContext );
const Slot = groups[ group ].Slot;
- const slot = useSlot( Slot.__unstableName );
- const hasFills = Boolean( slot.fills && slot.fills.length );
+ const fills = useSlotFills( Slot.__unstableName );
+ const hasFills = Boolean( fills && fills.length );
if ( ! hasFills ) {
return null;
diff --git a/packages/block-editor/src/components/block-draggable/index.js b/packages/block-editor/src/components/block-draggable/index.js
index ef19fc6116aaa5..40f61bfc79ce4d 100644
--- a/packages/block-editor/src/components/block-draggable/index.js
+++ b/packages/block-editor/src/components/block-draggable/index.js
@@ -52,7 +52,7 @@ const BlockDraggable = ( {
}, [] );
if ( ! isDraggable ) {
- return children( { isDraggable: false } );
+ return children( { draggable: false } );
}
const transferData = {
diff --git a/packages/block-editor/src/components/block-draggable/test/index.native.js b/packages/block-editor/src/components/block-draggable/test/index.native.js
index 1023d3405d2bba..4f5ba758a283a0 100644
--- a/packages/block-editor/src/components/block-draggable/test/index.native.js
+++ b/packages/block-editor/src/components/block-draggable/test/index.native.js
@@ -29,15 +29,6 @@ import {
getDraggableChip,
} from './helpers';
-// Mock throttle to allow updating the dragging position on every "onDragOver" event.
-jest.mock( 'lodash', () => ( {
- ...jest.requireActual( 'lodash' ),
- throttle: ( fn ) => {
- fn.cancel = jest.fn();
- return fn;
- },
-} ) );
-
beforeAll( () => {
// Register all core blocks
registerCoreBlocks();
diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js
index 3accd8ee6babd3..6b92e92ed6efe9 100644
--- a/packages/block-editor/src/components/block-inspector/index.js
+++ b/packages/block-editor/src/components/block-inspector/index.js
@@ -10,7 +10,7 @@ import {
} from '@wordpress/blocks';
import {
PanelBody,
- __experimentalUseSlot as useSlot,
+ __experimentalUseSlotFills as useSlotFills,
FlexItem,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
@@ -143,7 +143,6 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => {
getSelectedBlockCount,
getBlockName,
__unstableGetContentLockingParent,
- getTemplateLock,
} = select( blockEditorStore );
const _selectedBlockClientId = getSelectedBlockClientId();
@@ -157,12 +156,9 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => {
selectedBlockClientId: _selectedBlockClientId,
selectedBlockName: _selectedBlockName,
blockType: _blockType,
- topLevelLockedBlock:
- getTemplateLock( _selectedBlockClientId ) === 'contentOnly'
- ? _selectedBlockClientId
- : __unstableGetContentLockingParent(
- _selectedBlockClientId
- ),
+ topLevelLockedBlock: __unstableGetContentLockingParent(
+ _selectedBlockClientId
+ ),
};
}, [] );
@@ -284,8 +280,8 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => {
};
const AdvancedControls = () => {
- const slot = useSlot( InspectorAdvancedControls.slotName );
- const hasFills = Boolean( slot.fills && slot.fills.length );
+ const fills = useSlotFills( InspectorAdvancedControls.slotName );
+ const hasFills = Boolean( fills && fills.length );
if ( ! hasFills ) {
return null;
diff --git a/packages/block-editor/src/components/block-list/use-in-between-inserter.js b/packages/block-editor/src/components/block-list/use-in-between-inserter.js
index 82dcffeaa4dde1..cbd31279e8a451 100644
--- a/packages/block-editor/src/components/block-list/use-in-between-inserter.js
+++ b/packages/block-editor/src/components/block-list/use-in-between-inserter.js
@@ -83,19 +83,19 @@ export function useInBetweenInserter() {
const orientation =
getBlockListSettings( rootClientId )?.orientation ||
'vertical';
- const rect = event.target.getBoundingClientRect();
- const offsetTop = event.clientY - rect.top;
- const offsetLeft = event.clientX - rect.left;
+ const offsetTop = event.clientY;
+ const offsetLeft = event.clientX;
const children = Array.from( event.target.children );
let element = children.find( ( blockEl ) => {
+ const blockElRect = blockEl.getBoundingClientRect();
return (
( blockEl.classList.contains( 'wp-block' ) &&
orientation === 'vertical' &&
- blockEl.offsetTop > offsetTop ) ||
+ blockElRect.top > offsetTop ) ||
( blockEl.classList.contains( 'wp-block' ) &&
orientation === 'horizontal' &&
- blockEl.offsetLeft > offsetLeft )
+ blockElRect.left > offsetLeft )
);
} );
diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js
index 8d24ba26794d53..caf488ac06ec6f 100644
--- a/packages/block-editor/src/components/block-parent-selector/index.js
+++ b/packages/block-editor/src/components/block-parent-selector/index.js
@@ -83,10 +83,10 @@ export default function BlockParentSelector() {
label={ sprintf(
/* translators: %s: Name of the block's parent. */
__( 'Select %s' ),
- blockInformation.title
+ blockInformation?.title
) }
showTooltip
- icon={ }
+ icon={ }
/>
);
diff --git a/packages/block-editor/src/components/block-popover/inbetween.js b/packages/block-editor/src/components/block-popover/inbetween.js
index e7e207cb733f1f..ae8a3b32038000 100644
--- a/packages/block-editor/src/components/block-popover/inbetween.js
+++ b/packages/block-editor/src/components/block-popover/inbetween.js
@@ -226,7 +226,7 @@ function BlockPopoverInbetween( {
forcePopoverRecompute
);
return () => {
- previousElement.ownerDocument.defaultView.removeEventListener(
+ previousElement.ownerDocument.defaultView?.removeEventListener(
'resize',
forcePopoverRecompute
);
diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js
index 03913faa26e421..36a4017c226c07 100644
--- a/packages/block-editor/src/components/block-popover/index.js
+++ b/packages/block-editor/src/components/block-popover/index.js
@@ -42,24 +42,15 @@ function BlockPopover(
ref,
usePopoverScroll( __unstableContentRef ),
] );
- const style = useMemo( () => {
- if ( ! selectedElement || lastSelectedElement !== selectedElement ) {
- return {};
- }
-
- return {
- position: 'absolute',
- width: selectedElement.offsetWidth,
- height: selectedElement.offsetHeight,
- };
- }, [ selectedElement, lastSelectedElement, __unstableRefreshSize ] );
- const [ popoverAnchorRecomputeCounter, forceRecomputePopoverAnchor ] =
- useReducer(
- // Module is there to make sure that the counter doesn't overflow.
- ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER,
- 0
- );
+ const [
+ popoverDimensionsRecomputeCounter,
+ forceRecomputePopoverDimensions,
+ ] = useReducer(
+ // Module is there to make sure that the counter doesn't overflow.
+ ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER,
+ 0
+ );
// When blocks are moved up/down, they are animated to their new position by
// updating the `transform` property manually (i.e. without using CSS
@@ -74,7 +65,7 @@ function BlockPopover(
}
const observer = new window.MutationObserver(
- forceRecomputePopoverAnchor
+ forceRecomputePopoverDimensions
);
observer.observe( selectedElement, { attributes: true } );
@@ -83,12 +74,36 @@ function BlockPopover(
};
}, [ selectedElement ] );
+ const style = useMemo( () => {
+ if (
+ // popoverDimensionsRecomputeCounter is by definition always equal or greater
+ // than 0. This check is only there to satisfy the correctness of the
+ // exhaustive-deps rule for the `useMemo` hook.
+ popoverDimensionsRecomputeCounter < 0 ||
+ ! selectedElement ||
+ lastSelectedElement !== selectedElement
+ ) {
+ return {};
+ }
+
+ return {
+ position: 'absolute',
+ width: selectedElement.offsetWidth,
+ height: selectedElement.offsetHeight,
+ };
+ }, [
+ selectedElement,
+ lastSelectedElement,
+ __unstableRefreshSize,
+ popoverDimensionsRecomputeCounter,
+ ] );
+
const popoverAnchor = useMemo( () => {
if (
- // popoverAnchorRecomputeCounter is by definition always equal or greater
+ // popoverDimensionsRecomputeCounter is by definition always equal or greater
// than 0. This check is only there to satisfy the correctness of the
// exhaustive-deps rule for the `useMemo` hook.
- popoverAnchorRecomputeCounter < 0 ||
+ popoverDimensionsRecomputeCounter < 0 ||
! selectedElement ||
( bottomClientId && ! lastSelectedElement )
) {
@@ -132,7 +147,7 @@ function BlockPopover(
bottomClientId,
lastSelectedElement,
selectedElement,
- popoverAnchorRecomputeCounter,
+ popoverDimensionsRecomputeCounter,
] );
if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) {
@@ -143,12 +158,12 @@ function BlockPopover(
{ canDuplicate && (
{ __( 'Move to' ) }
@@ -302,7 +302,7 @@ export function BlockSettingsDropdown( {
{ canRemove && (
-
-
-
-
- }
- showColors={true}
- />
-
- }
- />
-
+
`;
exports[`BlockSwitcherDropdownMenu should render enabled block switcher with multi block when transforms exist 1`] = `
-
-
-
-
-
+
`;
exports[`BlockSwitcherDropdownMenu should render switcher with blocks 1`] = `
-
-
-
-
-
+
`;
diff --git a/packages/block-editor/src/components/block-switcher/test/index.js b/packages/block-editor/src/components/block-switcher/test/index.js
index ae073d74d07a66..2e8190a466b364 100644
--- a/packages/block-editor/src/components/block-switcher/test/index.js
+++ b/packages/block-editor/src/components/block-switcher/test/index.js
@@ -1,14 +1,14 @@
/**
* External dependencies
*/
-import { shallow, mount } from 'enzyme';
+import { render, screen, within } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
-import { Button } from '@wordpress/components';
import { copy } from '@wordpress/icons';
/**
@@ -17,23 +17,25 @@ import { copy } from '@wordpress/icons';
import { BlockSwitcher, BlockSwitcherDropdownMenu } from '../';
jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() );
-jest.mock( '../../block-title/use-block-display-title', () => jest.fn() );
+jest.mock( '../../block-title/use-block-display-title', () =>
+ jest.fn().mockReturnValue( 'Block Name' )
+);
describe( 'BlockSwitcher', () => {
test( 'should not render block switcher without blocks', () => {
useSelect.mockImplementation( () => ( {} ) );
- const wrapper = shallow( );
- expect( wrapper.html() ).toBeNull();
+ const { container } = render( );
+ expect( container ).toBeEmptyDOMElement();
} );
test( 'should not render block switcher with null blocks', () => {
useSelect.mockImplementation( () => ( { blocks: [ null ] } ) );
- const wrapper = shallow(
+ const { container } = render(
);
- expect( wrapper.html() ).toBeNull();
+ expect( container ).toBeEmptyDOMElement();
} );
} );
describe( 'BlockSwitcherDropdownMenu', () => {
@@ -122,10 +124,10 @@ describe( 'BlockSwitcherDropdownMenu', () => {
],
canRemove: true,
} ) );
- const wrapper = shallow(
+ const { container } = render(
);
- expect( wrapper ).toMatchSnapshot();
+ expect( container ).toMatchSnapshot();
} );
test( 'should render disabled block switcher with multi block of different types when no transforms', () => {
@@ -133,12 +135,12 @@ describe( 'BlockSwitcherDropdownMenu', () => {
possibleBlockTransformations: [],
icon: copy,
} ) );
- const wrapper = shallow(
+ const { container } = render(
);
- expect( wrapper ).toMatchSnapshot();
+ expect( container ).toMatchSnapshot();
} );
test( 'should render enabled block switcher with multi block when transforms exist', () => {
@@ -149,12 +151,12 @@ describe( 'BlockSwitcherDropdownMenu', () => {
],
canRemove: true,
} ) );
- const wrapper = shallow(
+ const { container } = render(
);
- expect( wrapper ).toMatchSnapshot();
+ expect( container ).toMatchSnapshot();
} );
describe( 'Dropdown', () => {
@@ -166,70 +168,128 @@ describe( 'BlockSwitcherDropdownMenu', () => {
canRemove: true,
} ) );
} );
- const getDropdown = () =>
- mount(
-
- ).find( 'Dropdown' );
test( 'should dropdown exist', () => {
- expect( getDropdown() ).toHaveLength( 1 );
- } );
+ render(
+
+ );
- describe( '.renderToggle', () => {
- const onToggleStub = jest.fn();
- const mockKeyDown = {
- preventDefault: () => {},
- code: 'ArrowDown',
- };
+ expect(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } )
+ ).toBeVisible();
+ } );
- afterEach( () => {
- onToggleStub.mockReset();
+ test( 'should simulate a keydown event, which should open transform toggle.', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
- test( 'should simulate a keydown event, which should call onToggle and open transform toggle.', () => {
- const toggleClosed = mount(
- getDropdown().props().renderToggle( {
- onToggle: onToggleStub,
- isOpen: false,
- } )
- );
- const iconButtonClosed = toggleClosed.find( Button );
+ render(
+
+ );
+
+ expect(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } )
+ ).toBeVisible();
+ expect(
+ screen.queryByRole( 'menu', {
+ name: 'Block Name',
+ } )
+ ).not.toBeInTheDocument();
+
+ await user.type(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } ),
+ '[ArrowDown]'
+ );
- iconButtonClosed.simulate( 'keydown', mockKeyDown );
+ expect(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: true,
+ } )
+ ).toBeVisible();
- expect( onToggleStub ).toHaveBeenCalledTimes( 1 );
+ const menu = screen.getByRole( 'menu', {
+ name: 'Block Name',
} );
+ expect( menu ).toBeInTheDocument();
+ expect( menu ).not.toBeVisible();
+ } );
- test( 'should simulate a click event, which should call onToggle.', () => {
- const toggleOpen = mount(
- getDropdown().props().renderToggle( {
- onToggle: onToggleStub,
- isOpen: true,
- } )
- );
- const iconButtonOpen = toggleOpen.find( Button );
+ test( 'should simulate a click event, which should call onToggle.', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render(
+
+ );
+
+ expect(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } )
+ ).toBeVisible();
+ expect(
+ screen.queryByRole( 'menu', {
+ name: 'Block Name',
+ } )
+ ).not.toBeInTheDocument();
+
+ await user.click(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } )
+ );
- iconButtonOpen.simulate( 'keydown', mockKeyDown );
+ expect(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: true,
+ } )
+ ).toBeVisible();
- expect( onToggleStub ).toHaveBeenCalledTimes( 0 );
+ const menu = screen.getByRole( 'menu', {
+ name: 'Block Name',
} );
+ expect( menu ).toBeInTheDocument();
+ expect( menu ).not.toBeVisible();
} );
- describe( '.renderContent', () => {
- test( 'should create the transform items for the chosen block. A heading block will have 3 items', () => {
- const onCloseStub = jest.fn();
- const content = shallow(
-
- { getDropdown()
- .props()
- .renderContent( { onClose: onCloseStub } ) }
-
- );
- const blockList = content.find( 'BlockTransformationsMenu' );
- expect(
- blockList.prop( 'possibleBlockTransformations' )
- ).toHaveLength( 1 );
+ test( 'should create the transform items for the chosen block.', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
+
+ render(
+
+ );
+
+ await user.click(
+ screen.getByRole( 'button', {
+ name: 'Block Name',
+ expanded: false,
+ } )
+ );
+
+ expect(
+ within(
+ screen.getByRole( 'menu', {
+ name: 'Block Name',
+ } )
+ ).getAllByRole( 'menuitem' )
+ ).toHaveLength( 1 );
} );
} );
} );
diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js
index b4ba23ad1dd846..519d8f7d82bff9 100644
--- a/packages/block-editor/src/components/block-tools/index.js
+++ b/packages/block-editor/src/components/block-tools/index.js
@@ -124,7 +124,7 @@ export default function BlockTools( {
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
- { ! isTyping && ! isZoomOutMode && (
+ { ! isTyping && (
diff --git a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js
index bea9487e48ca11..d218b1104139cf 100644
--- a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js
+++ b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js
@@ -11,10 +11,15 @@ import { useCallback, useLayoutEffect, useState } from '@wordpress/element';
import { store as blockEditorStore } from '../../store';
import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs';
+const COMMON_PROPS = {
+ placement: 'top-start',
+};
+
// By default the toolbar sets the `shift` prop. If the user scrolls the page
// down the toolbar will stay on screen by adopting a sticky position at the
// top of the viewport.
const DEFAULT_PROPS = {
+ ...COMMON_PROPS,
flip: false,
shift: true,
};
@@ -25,6 +30,7 @@ const DEFAULT_PROPS = {
// the block. This only happens if the block is smaller than the viewport, as
// otherwise the toolbar will be off-screen.
const RESTRICTED_HEIGHT_PROPS = {
+ ...COMMON_PROPS,
flip: true,
shift: false,
};
diff --git a/packages/block-editor/src/components/button-block-appender/style.scss b/packages/block-editor/src/components/button-block-appender/style.scss
index dfeb3241c7bb70..45358b9a0f0503 100644
--- a/packages/block-editor/src/components/button-block-appender/style.scss
+++ b/packages/block-editor/src/components/button-block-appender/style.scss
@@ -35,7 +35,9 @@
// When the appender shows up in empty container blocks, such as Group and Columns, add an extra click state.
.block-list-appender:only-child {
.is-layout-constrained.block-editor-block-list__block:not(.is-selected) > &,
- .is-layout-flow.block-editor-block-list__block:not(.is-selected) > & {
+ .is-layout-flow.block-editor-block-list__block:not(.is-selected) > &,
+ .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-editor-block-list__layout > &,
+ .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-editor-block-list__layout > & {
pointer-events: none;
&::after {
diff --git a/packages/block-editor/src/components/image-editor/use-transform-image.js b/packages/block-editor/src/components/image-editor/use-transform-image.js
index d3e514d0f33f19..885ae8894c0920 100644
--- a/packages/block-editor/src/components/image-editor/use-transform-image.js
+++ b/packages/block-editor/src/components/image-editor/use-transform-image.js
@@ -41,7 +41,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) {
if ( angle === 0 ) {
setEditedUrl();
setRotation( angle );
- setAspect( 1 / aspect );
+ setAspect( naturalWidth / naturalHeight );
setPosition( {
x: -( position.y * naturalAspectRatio ),
y: position.x * naturalAspectRatio,
@@ -80,7 +80,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) {
canvas.toBlob( ( blob ) => {
setEditedUrl( URL.createObjectURL( blob ) );
setRotation( angle );
- setAspect( 1 / aspect );
+ setAspect( canvas.width / canvas.height );
setPosition( {
x: -( position.y * naturalAspectRatio ),
y: position.x * naturalAspectRatio,
diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js
index 6b7a24887b3423..0ad7de536282e2 100644
--- a/packages/block-editor/src/components/index.js
+++ b/packages/block-editor/src/components/index.js
@@ -155,6 +155,7 @@ export {
export { default as __experimentalBlockPatternsList } from './block-patterns-list';
export { default as __experimentalPublishDateTimePicker } from './publish-date-time-picker';
export { default as __experimentalInspectorPopoverHeader } from './inspector-popover-header';
+export { default as __experimentalUseOnBlockDrop } from './use-on-block-drop';
/*
* State Related Components
diff --git a/packages/block-editor/src/components/inserter/block-types-tab.js b/packages/block-editor/src/components/inserter/block-types-tab.js
index 2e8c9e0138728a..b5ecb5ad212753 100644
--- a/packages/block-editor/src/components/inserter/block-types-tab.js
+++ b/packages/block-editor/src/components/inserter/block-types-tab.js
@@ -1,14 +1,14 @@
/**
* External dependencies
*/
-import { map, flow, groupBy, orderBy } from 'lodash';
+import { map, groupBy, orderBy } from 'lodash';
/**
* WordPress dependencies
*/
import { __, _x } from '@wordpress/i18n';
import { useMemo, useEffect } from '@wordpress/element';
-import { useAsyncList } from '@wordpress/compose';
+import { pipe, useAsyncList } from '@wordpress/compose';
/**
* Internal dependencies
@@ -53,7 +53,7 @@ export function BlockTypesTab( {
}, [ items ] );
const itemsPerCategory = useMemo( () => {
- return flow(
+ return pipe(
( itemList ) =>
itemList.filter(
( item ) => item.category && item.category !== 'reusable'
diff --git a/packages/block-editor/src/components/inserter/search-items.js b/packages/block-editor/src/components/inserter/search-items.js
index c2f8da7a6001b2..f8edd14fc5ff49 100644
--- a/packages/block-editor/src/components/inserter/search-items.js
+++ b/packages/block-editor/src/components/inserter/search-items.js
@@ -1,9 +1,8 @@
/**
* External dependencies
*/
-import { noCase } from 'change-case';
import removeAccents from 'remove-accents';
-import { find } from 'lodash';
+import { find, words } from 'lodash';
// Default search helpers.
const defaultGetName = ( item ) => item.name || '';
@@ -36,17 +35,6 @@ function normalizeSearchInput( input = '' ) {
return input;
}
-/**
- * Extracts words from an input string.
- *
- * @param {string} input The input string.
- *
- * @return {Array} Words, extracted from the input string.
- */
-function extractWords( input = '' ) {
- return noCase( input ).split( ' ' ).filter( Boolean );
-}
-
/**
* Converts the search term into a list of normalized terms.
*
@@ -55,7 +43,7 @@ function extractWords( input = '' ) {
* @return {string[]} The normalized list of search terms.
*/
export const getNormalizedSearchTerms = ( input = '' ) => {
- return extractWords( normalizeSearchInput( input ) );
+ return words( normalizeSearchInput( input ) );
};
const removeMatchingTerms = ( unmatchedTerms, unprocessedTerms ) => {
@@ -162,7 +150,7 @@ export function getItemSearchRank( item, searchTerm, config = {} ) {
category,
collection,
].join( ' ' );
- const normalizedSearchTerms = extractWords( normalizedSearchInput );
+ const normalizedSearchTerms = words( normalizedSearchInput );
const unmatchedTerms = removeMatchingTerms(
normalizedSearchTerms,
terms
diff --git a/packages/block-editor/src/components/inserter/test/search-items.js b/packages/block-editor/src/components/inserter/test/search-items.js
index 96402392d36f4d..a33da9d580230e 100644
--- a/packages/block-editor/src/components/inserter/test/search-items.js
+++ b/packages/block-editor/src/components/inserter/test/search-items.js
@@ -42,6 +42,10 @@ describe( 'getNormalizedSearchTerms', () => {
getNormalizedSearchTerms( ' Média & Text Tag-Cloud > 123' )
).toEqual( [ 'media', 'text', 'tag', 'cloud', '123' ] );
} );
+
+ it( 'should support non-latin letters', () => {
+ expect( getNormalizedSearchTerms( 'მედია' ) ).toEqual( [ 'მედია' ] );
+ } );
} );
describe( 'getItemSearchRank', () => {
diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js
index 1f30357cf7815e..010332c0a3112d 100644
--- a/packages/block-editor/src/components/inspector-controls/slot.js
+++ b/packages/block-editor/src/components/inspector-controls/slot.js
@@ -1,7 +1,10 @@
/**
* WordPress dependencies
*/
-import { __experimentalUseSlot as useSlot } from '@wordpress/components';
+import {
+ __experimentalUseSlot as useSlot,
+ __experimentalUseSlotFills as useSlotFills,
+} from '@wordpress/components';
import warning from '@wordpress/warning';
/**
@@ -18,12 +21,13 @@ export default function InspectorControlsSlot( {
} ) {
const Slot = groups[ group ]?.Slot;
const slot = useSlot( Slot?.__unstableName );
+ const fills = useSlotFills( Slot?.__unstableName );
if ( ! Slot || ! slot ) {
warning( `Unknown InspectorControl group "${ group }" provided.` );
return null;
}
- const hasFills = Boolean( slot.fills && slot.fills.length );
+ const hasFills = Boolean( fills && fills.length );
if ( ! hasFills ) {
return null;
}
diff --git a/packages/block-editor/src/components/responsive-block-control/test/index.js b/packages/block-editor/src/components/responsive-block-control/test/index.js
index e47e22c3b3c616..a53c414f99fc0b 100644
--- a/packages/block-editor/src/components/responsive-block-control/test/index.js
+++ b/packages/block-editor/src/components/responsive-block-control/test/index.js
@@ -1,14 +1,13 @@
/**
* External dependencies
*/
-import { render, unmountComponentAtNode } from 'react-dom';
-import { act, Simulate } from 'react-dom/test-utils';
+import { render } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
/**
* WordPress dependencies
*/
import { Fragment, useState } from '@wordpress/element';
-
import { SelectControl } from '@wordpress/components';
/**
@@ -16,20 +15,6 @@ import { SelectControl } from '@wordpress/components';
*/
import ResponsiveBlockControl from '../index';
-let container = null;
-beforeEach( () => {
- // Setup a DOM element as a render target.
- container = document.createElement( 'div' );
- document.body.appendChild( container );
-} );
-
-afterEach( () => {
- // Cleanup on exiting.
- unmountComponentAtNode( container );
- container.remove();
- container = null;
-} );
-
const inputId = 'input-12345678';
const sizeOptions = [
@@ -65,16 +50,13 @@ const renderTestDefaultControlComponent = ( labelComponent, device ) => {
describe( 'Basic rendering', () => {
it( 'should render with required props', () => {
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
const activePropertyLabel = Array.from(
container.querySelectorAll( 'legend' )
@@ -121,40 +103,31 @@ describe( 'Basic rendering', () => {
} );
it( 'should not render without valid legend', () => {
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
expect( container.innerHTML ).toBe( '' );
} );
it( 'should not render without valid property', () => {
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
expect( container.innerHTML ).toBe( '' );
} );
it( 'should not render without valid default control render prop', () => {
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
expect( container.innerHTML ).toBe( '' );
} );
@@ -162,17 +135,14 @@ describe( 'Basic rendering', () => {
it( 'should render with custom label for toggle control when provided', () => {
const customToggleLabel =
'Utilise a matching padding value on all viewports';
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
const actualToggleLabel = container.querySelector(
'label.components-toggle-control__label'
@@ -184,17 +154,14 @@ describe( 'Basic rendering', () => {
it( 'should pass custom label for default control group to the renderDefaultControl function when provided', () => {
const customDefaultControlGroupLabel = 'Everything';
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
const defaultControlLabel = Array.from(
container.querySelectorAll( 'label' )
@@ -206,17 +173,14 @@ describe( 'Basic rendering', () => {
describe( 'Default and Responsive modes', () => {
it( 'should render in responsive mode when isResponsive prop is set to true', () => {
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
const defaultControlGroup = container.querySelector(
'.block-editor-responsive-block-control__group:not(.is-responsive)'
@@ -253,18 +217,15 @@ describe( 'Default and Responsive modes', () => {
renderTestDefaultControlComponent
);
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
const defaultRenderControlCall = 1;
@@ -287,7 +248,10 @@ describe( 'Default and Responsive modes', () => {
);
} );
- it( 'should switch between default and responsive modes when interacting with toggle control', () => {
+ it( 'should switch between default and responsive modes when interacting with toggle control', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
const ResponsiveBlockControlConsumer = () => {
const [ isResponsive, setIsResponsive ] = useState( false );
@@ -304,9 +268,7 @@ describe( 'Default and Responsive modes', () => {
);
};
- act( () => {
- render( , container );
- } );
+ const { container } = render( );
let defaultControlGroup = container.querySelector(
'.block-editor-responsive-block-control__group:not(.is-responsive)'
@@ -332,9 +294,7 @@ describe( 'Default and Responsive modes', () => {
expect( responsiveControlGroup ).toBeNull();
// Toggle to "responsive" mode.
- act( () => {
- Simulate.change( toggleInput, { target: { checked: false } } );
- } );
+ await user.click( toggleInput );
defaultControlGroup = container.querySelector(
'.block-editor-responsive-block-control__group:not(.is-responsive)'
@@ -347,9 +307,7 @@ describe( 'Default and Responsive modes', () => {
expect( responsiveControlGroup ).not.toBeNull();
// Toggle back to "default" mode.
- act( () => {
- Simulate.change( toggleInput, { target: { checked: true } } );
- } );
+ await user.click( toggleInput );
defaultControlGroup = container.querySelector(
'.block-editor-responsive-block-control__group:not(.is-responsive)'
@@ -382,18 +340,15 @@ describe( 'Default and Responsive modes', () => {
} );
} );
- act( () => {
- render(
- ,
- container
- );
- } );
+ const { container } = render(
+
+ );
// The user should see "range" controls so we can legitimately query for them here.
const customControls = Array.from(
diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js
index 53b3d85e5dbd6e..ee364e8c3beaeb 100644
--- a/packages/block-editor/src/components/rich-text/index.js
+++ b/packages/block-editor/src/components/rich-text/index.js
@@ -159,6 +159,8 @@ function RichTextWrapper(
// retreived from the store on merge.
// To do: fix this somehow.
const { selectionStart, selectionEnd, isSelected } = useSelect( selector );
+ const { getSelectionStart, getSelectionEnd, getBlockRootClientId } =
+ useSelect( blockEditorStore );
const { selectionChange } = useDispatch( blockEditorStore );
const multilineTag = getMultilineTag( multiline );
const adjustedAllowedFormats = getAllowedFormats( {
@@ -195,6 +197,18 @@ function RichTextWrapper(
const unset = start === undefined && end === undefined;
if ( typeof start === 'number' || unset ) {
+ // If we are only setting the start (or the end below), which
+ // means a partial selection, and we're not updating a selection
+ // with the same client ID, abort. This means the selected block
+ // is a parent block.
+ if (
+ end === undefined &&
+ getBlockRootClientId( clientId ) !==
+ getBlockRootClientId( getSelectionEnd().clientId )
+ ) {
+ return;
+ }
+
selection.start = {
clientId,
attributeKey: identifier,
@@ -203,6 +217,14 @@ function RichTextWrapper(
}
if ( typeof end === 'number' || unset ) {
+ if (
+ start === undefined &&
+ getBlockRootClientId( clientId ) !==
+ getBlockRootClientId( getSelectionStart().clientId )
+ ) {
+ return;
+ }
+
selection.end = {
clientId,
attributeKey: identifier,
diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js
index ba379713b4bcc5..7b016e7a08ee72 100644
--- a/packages/block-editor/src/components/spacing-sizes-control/index.js
+++ b/packages/block-editor/src/components/spacing-sizes-control/index.js
@@ -1,9 +1,14 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
-import { __experimentalText as Text } from '@wordpress/components';
+import { BaseControl } from '@wordpress/components';
/**
* Internal dependencies
@@ -68,8 +73,15 @@ export default function SpacingSizesControl( {
};
return (
-
- { label }
+
+
+ { label }
+
{ ! hasOneSide && (
) }
diff --git a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js
index c0d2573b42e807..cf9a663fe1fa1e 100644
--- a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js
+++ b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js
@@ -9,12 +9,12 @@ import classnames from 'classnames';
import { useState, useMemo } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import {
+ BaseControl,
Button,
RangeControl,
CustomSelectControl,
__experimentalUnitControl as UnitControl,
__experimentalHStack as HStack,
- __experimentalText as Text,
__experimentalUseCustomUnits as useCustomUnits,
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
} from '@wordpress/components';
@@ -167,21 +167,21 @@ export default function SpacingInputControl( {
<>
{ side !== 'all' && (
-
+
{ LABELS[ side ] }
-
+
{ showHint && (
-
+
{ currentValueHint }
-
+
) }
) }
{ side === 'all' && showHint && (
-
+
{ currentValueHint }
-
+
) }
{ ! disableCustomSpacingSizes && (
@@ -256,6 +256,7 @@ export default function SpacingInputControl( {
marks={ marks }
label={ ariaLabel }
hideLabelFromVision={ true }
+ __nextHasNoMarginBottom={ true }
/>
) }
{ ! showRangeControl && ! showCustomValueControl && (
diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss
index 448a21cc0ac1ba..27b83a9ba5ca81 100644
--- a/packages/block-editor/src/components/spacing-sizes-control/style.scss
+++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss
@@ -1,7 +1,8 @@
.tools-panel-item-spacing {
display: grid;
grid-template-columns: auto 1fr auto;
- grid-row-gap: $grid-unit-05;
+ align-items: center;
+ grid-template-rows: 25px auto;
}
.component-spacing-sizes-control {
@@ -17,21 +18,34 @@
align-self: center;
}
+ .components-base-control__label {
+ margin-bottom: 0;
+ height: $grid-unit-20;
+ }
+
.components-spacing-sizes-control__side-labels {
grid-column: 1 / 1;
- min-height: 30px;
justify-content: left;
+ height: $grid-unit-20;
+ margin-top: $grid-unit-15;
+ }
+
+ .components-spacing-sizes-control__side-label {
+ grid-column: 1 / 1;
+ justify-self: left;
+ margin-bottom: 0;
}
- .components-spacing-sizes-control__hint-single {
- margin-top: 0;
- margin-left: 0;
+ &.is-unlinked {
+ .components-range-control.components-spacing-sizes-control__range-control {
+ margin-top: $grid-unit-15;
+ }
}
.components-spacing-sizes-control__hint-single,
.components-spacing-sizes-control__hint-all {
color: $gray-700;
- font-size: 12px;
+ margin-bottom: 0;
}
.components-spacing-sizes-control__hint-all {
@@ -47,6 +61,11 @@
grid-row: 1 / 1;
justify-self: end;
padding: 0;
+ &.is-small.has-icon {
+ padding: 0;
+ min-width: $icon-size;
+ height: $grid-unit-20;
+ }
}
.component-spacing-sizes-control__linked-button ~ .components-spacing-sizes-control__custom-toggle-all {
@@ -56,13 +75,11 @@
.components-spacing-sizes-control__custom-toggle-single {
grid-column: 3 / 3;
justify-self: end;
- }
-
- .components-spacing-sizes-control__custom-toggle-all,
- .components-spacing-sizes-control__custom-toggle-single {
&.is-small.has-icon {
padding: 0;
min-width: $icon-size;
+ height: $grid-unit-20;
+ margin-top: $grid-unit-15;
}
}
@@ -75,7 +92,6 @@
.components-spacing-sizes-control__custom-value-range {
grid-column: span 2;
margin-left: $grid-unit-10;
- padding-right: $grid-unit-10;
height: 30px;
}
@@ -85,12 +101,7 @@
.components-spacing-sizes-control__range-control {
grid-column: span 3;
- padding-right: $grid-unit-10;
- height: 30px;
- }
-
- .components-range-control__wrapper {
- margin-bottom: 0;
+ height: 40px;
}
.components-range-control__mark {
@@ -112,13 +123,6 @@
z-index: 3;
}
- .components-spacing-sizes-control__side-label {
- margin-right: $grid-unit-05;
- grid-column: 1 / 1;
- justify-self: left;
- font-size: 12px;
- }
-
.components-spacing-sizes-control__custom-select-control {
grid-column: span 3;
}
diff --git a/packages/block-editor/src/components/url-popover/image-url-input-ui.js b/packages/block-editor/src/components/url-popover/image-url-input-ui.js
index 99a0d27bb91fd3..ea3b6fbbe0a199 100644
--- a/packages/block-editor/src/components/url-popover/image-url-input-ui.js
+++ b/packages/block-editor/src/components/url-popover/image-url-input-ui.js
@@ -221,7 +221,7 @@ const ImageURLInputUI = ( {
checked={ linkTarget === '_blank' }
/>
diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.js b/packages/block-editor/src/components/use-block-drop-zone/index.js
index ac6a0ea3d1f670..3bef31546c711e 100644
--- a/packages/block-editor/src/components/use-block-drop-zone/index.js
+++ b/packages/block-editor/src/components/use-block-drop-zone/index.js
@@ -73,6 +73,20 @@ export function getNearestBlockIndex( elements, position, orientation ) {
return candidateIndex;
}
+/**
+ * Determine if the element is an empty paragraph block.
+ *
+ * @param {?HTMLElement} element The element being tested.
+ * @return {boolean} True or False.
+ */
+function isEmptyParagraph( element ) {
+ return (
+ !! element &&
+ element.dataset.type === 'core/paragraph' &&
+ element.dataset.empty === 'true'
+ );
+}
+
/**
* @typedef {Object} WPBlockDropZoneConfig
* @property {string} rootClientId The root client id for the block list.
@@ -130,7 +144,18 @@ export default function useBlockDropZone( {
setTargetBlockIndex( targetIndex === undefined ? 0 : targetIndex );
- if ( targetIndex !== null ) {
+ if ( targetIndex !== undefined ) {
+ const nextBlock = blockElements[ targetIndex ];
+ const previousBlock = blockElements[ targetIndex - 1 ];
+
+ // Don't show the insertion point when it's near an empty paragraph block.
+ if (
+ isEmptyParagraph( nextBlock ) ||
+ isEmptyParagraph( previousBlock )
+ ) {
+ return;
+ }
+
showInsertionPoint( targetRootClientId, targetIndex );
}
}, [] ),
diff --git a/packages/block-editor/src/components/use-on-block-drop/index.js b/packages/block-editor/src/components/use-on-block-drop/index.js
index 449a9fc5dc2a9c..245f912bcf4da7 100644
--- a/packages/block-editor/src/components/use-on-block-drop/index.js
+++ b/packages/block-editor/src/components/use-on-block-drop/index.js
@@ -1,13 +1,14 @@
/**
* WordPress dependencies
*/
+import { useCallback } from '@wordpress/element';
import {
cloneBlock,
findTransform,
getBlockTransforms,
pasteHandler,
} from '@wordpress/blocks';
-import { useDispatch, useSelect } from '@wordpress/data';
+import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
import { getFilesFromDataTransfer } from '@wordpress/dom';
/**
@@ -56,8 +57,8 @@ export function parseDropEvent( event ) {
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
* @param {Function} getBlockIndex A function that gets the index of a block.
* @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.
- * @param {Function} moveBlocksToPosition A function that moves blocks.
- * @param {Function} insertBlocks A function that inserts blocks.
+ * @param {Function} moveBlocks A function that moves blocks.
+ * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
* @param {Function} clearSelectedBlock A function that clears block selection.
* @return {Function} The event handler for a block drop event.
*/
@@ -66,8 +67,8 @@ export function onBlockDrop(
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition,
- insertBlocks,
+ moveBlocks,
+ insertOrReplaceBlocks,
clearSelectedBlock
) {
return ( event ) => {
@@ -84,13 +85,7 @@ export function onBlockDrop(
const blocksToInsert = blocks.map( ( block ) =>
cloneBlock( block )
);
- insertBlocks(
- blocksToInsert,
- targetBlockIndex,
- targetRootClientId,
- true,
- null
- );
+ insertOrReplaceBlocks( blocksToInsert, true, null );
}
// If the user is moving a block.
@@ -128,12 +123,7 @@ export function onBlockDrop(
? targetBlockIndex - draggedBlockCount
: targetBlockIndex;
- moveBlocksToPosition(
- sourceClientIds,
- sourceRootClientId,
- targetRootClientId,
- insertIndex
- );
+ moveBlocks( sourceClientIds, sourceRootClientId, insertIndex );
}
};
}
@@ -146,7 +136,7 @@ export function onBlockDrop(
* @param {boolean} hasUploadPermissions Whether the user has upload permissions.
* @param {Function} updateBlockAttributes A function that updates a block's attributes.
* @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.
- * @param {Function} insertBlocks A function that inserts blocks.
+ * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
*
* @return {Function} The event handler for a block-related file drop event.
*/
@@ -156,7 +146,7 @@ export function onFilesDrop(
hasUploadPermissions,
updateBlockAttributes,
canInsertBlockType,
- insertBlocks
+ insertOrReplaceBlocks
) {
return ( files ) => {
if ( ! hasUploadPermissions ) {
@@ -176,7 +166,7 @@ export function onFilesDrop(
files,
updateBlockAttributes
);
- insertBlocks( blocks, targetBlockIndex, targetRootClientId );
+ insertOrReplaceBlocks( blocks );
}
};
}
@@ -184,22 +174,22 @@ export function onFilesDrop(
/**
* A function that returns an event handler function for block-related HTML drop events.
*
- * @param {string} targetRootClientId The root client id where the block(s) will be inserted.
- * @param {number} targetBlockIndex The index where the block(s) will be inserted.
- * @param {Function} insertBlocks A function that inserts blocks.
+ * @param {string} targetRootClientId The root client id where the block(s) will be inserted.
+ * @param {number} targetBlockIndex The index where the block(s) will be inserted.
+ * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
*
* @return {Function} The event handler for a block-related HTML drop event.
*/
export function onHTMLDrop(
targetRootClientId,
targetBlockIndex,
- insertBlocks
+ insertOrReplaceBlocks
) {
return ( HTML ) => {
const blocks = pasteHandler( { HTML, mode: 'BLOCKS' } );
if ( blocks.length ) {
- insertBlocks( blocks, targetBlockIndex, targetRootClientId );
+ insertOrReplaceBlocks( blocks );
}
};
}
@@ -207,32 +197,117 @@ export function onHTMLDrop(
/**
* A React hook for handling block drop events.
*
- * @param {string} targetRootClientId The root client id where the block(s) will be inserted.
- * @param {number} targetBlockIndex The index where the block(s) will be inserted.
+ * @typedef {'insert'|'replace'} DropAction The type of action to perform on drop.
+ *
+ * @param {string} targetRootClientId The root client id where the block(s) will be inserted.
+ * @param {number} targetBlockIndex The index where the block(s) will be inserted.
+ * @param {Object} options The optional options.
+ * @param {DropAction} options.action The type of action to perform on drop. Could be `insert` or `replace` for now.
*
* @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.
*/
-export default function useOnBlockDrop( targetRootClientId, targetBlockIndex ) {
+export default function useOnBlockDrop(
+ targetRootClientId,
+ targetBlockIndex,
+ options = {}
+) {
+ const { action = 'insert' } = options;
const hasUploadPermissions = useSelect(
( select ) => select( blockEditorStore ).getSettings().mediaUpload,
[]
);
- const { canInsertBlockType, getBlockIndex, getClientIdsOfDescendants } =
- useSelect( blockEditorStore );
+ const {
+ canInsertBlockType,
+ getBlockIndex,
+ getClientIdsOfDescendants,
+ getBlockOrder,
+ getBlocksByClientId,
+ } = useSelect( blockEditorStore );
const {
insertBlocks,
moveBlocksToPosition,
updateBlockAttributes,
clearSelectedBlock,
+ replaceBlocks,
+ removeBlocks,
} = useDispatch( blockEditorStore );
+ const registry = useRegistry();
+
+ const insertOrReplaceBlocks = useCallback(
+ ( blocks, updateSelection = true, initialPosition = 0 ) => {
+ if ( action === 'replace' ) {
+ const clientIds = getBlockOrder( targetRootClientId );
+ const clientId = clientIds[ targetBlockIndex ];
+
+ replaceBlocks( clientId, blocks, undefined, initialPosition );
+ } else {
+ insertBlocks(
+ blocks,
+ targetBlockIndex,
+ targetRootClientId,
+ updateSelection,
+ initialPosition
+ );
+ }
+ },
+ [
+ action,
+ getBlockOrder,
+ insertBlocks,
+ replaceBlocks,
+ targetBlockIndex,
+ targetRootClientId,
+ ]
+ );
+
+ const moveBlocks = useCallback(
+ ( sourceClientIds, sourceRootClientId, insertIndex ) => {
+ if ( action === 'replace' ) {
+ const sourceBlocks = getBlocksByClientId( sourceClientIds );
+ const targetBlockClientIds =
+ getBlockOrder( targetRootClientId );
+ const targetBlockClientId =
+ targetBlockClientIds[ targetBlockIndex ];
+
+ registry.batch( () => {
+ // Remove the source blocks.
+ removeBlocks( sourceClientIds, false );
+ // Replace the target block with the source blocks.
+ replaceBlocks(
+ targetBlockClientId,
+ sourceBlocks,
+ undefined,
+ 0
+ );
+ } );
+ } else {
+ moveBlocksToPosition(
+ sourceClientIds,
+ sourceRootClientId,
+ targetRootClientId,
+ insertIndex
+ );
+ }
+ },
+ [
+ action,
+ getBlockOrder,
+ getBlocksByClientId,
+ insertBlocks,
+ moveBlocksToPosition,
+ removeBlocks,
+ targetBlockIndex,
+ targetRootClientId,
+ ]
+ );
const _onDrop = onBlockDrop(
targetRootClientId,
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition,
- insertBlocks,
+ moveBlocks,
+ insertOrReplaceBlocks,
clearSelectedBlock
);
const _onFilesDrop = onFilesDrop(
@@ -241,12 +316,12 @@ export default function useOnBlockDrop( targetRootClientId, targetBlockIndex ) {
hasUploadPermissions,
updateBlockAttributes,
canInsertBlockType,
- insertBlocks
+ insertOrReplaceBlocks
);
const _onHTMLDrop = onHTMLDrop(
targetRootClientId,
targetBlockIndex,
- insertBlocks
+ insertOrReplaceBlocks
);
return ( event ) => {
diff --git a/packages/block-editor/src/components/use-on-block-drop/test/index.js b/packages/block-editor/src/components/use-on-block-drop/test/index.js
index e2789bb879473e..1b95cc0085a79e 100644
--- a/packages/block-editor/src/components/use-on-block-drop/test/index.js
+++ b/packages/block-editor/src/components/use-on-block-drop/test/index.js
@@ -98,7 +98,7 @@ describe( 'onBlockDrop', () => {
const targetBlockIndex = 0;
const getBlockIndex = noop;
const getClientIdsOfDescendants = noop;
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -115,11 +115,11 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).not.toHaveBeenCalled();
+ expect( moveBlocks ).not.toHaveBeenCalled();
} );
it( 'does nothing if the block is dropped to the same place it was dragged from', () => {
@@ -128,7 +128,7 @@ describe( 'onBlockDrop', () => {
// Target and source block index is the same.
const getBlockIndex = jest.fn( () => targetBlockIndex );
const getClientIdsOfDescendants = noop;
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -148,11 +148,11 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).not.toHaveBeenCalled();
+ expect( moveBlocks ).not.toHaveBeenCalled();
} );
it( 'does nothing if the block is dropped as a child of itself', () => {
@@ -160,7 +160,7 @@ describe( 'onBlockDrop', () => {
const targetBlockIndex = 0;
const getBlockIndex = jest.fn( () => 6 );
const getClientIdsOfDescendants = noop;
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -180,11 +180,11 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).not.toHaveBeenCalled();
+ expect( moveBlocks ).not.toHaveBeenCalled();
} );
it( 'does nothing if the block is dropped as a descendant of itself', () => {
@@ -195,7 +195,7 @@ describe( 'onBlockDrop', () => {
const getClientIdsOfDescendants = jest.fn( () => [
targetRootClientId,
] );
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -214,11 +214,11 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).not.toHaveBeenCalled();
+ expect( moveBlocks ).not.toHaveBeenCalled();
} );
it( 'inserts blocks if the drop is valid', () => {
@@ -228,7 +228,7 @@ describe( 'onBlockDrop', () => {
const targetBlockIndex = 0;
const getBlockIndex = jest.fn( () => 1 );
const getClientIdsOfDescendants = () => [];
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -247,14 +247,13 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).toHaveBeenCalledWith(
+ expect( moveBlocks ).toHaveBeenCalledWith(
sourceClientIds,
sourceRootClientId,
- targetRootClientId,
targetBlockIndex
);
} );
@@ -267,7 +266,7 @@ describe( 'onBlockDrop', () => {
const getBlockIndex = jest.fn( () => 1 );
// Dragged block is being dropped as a descendant of itself.
const getClientIdsOfDescendants = () => [];
- const moveBlocksToPosition = jest.fn();
+ const moveBlocks = jest.fn();
const event = {
dataTransfer: {
@@ -289,14 +288,13 @@ describe( 'onBlockDrop', () => {
targetBlockIndex,
getBlockIndex,
getClientIdsOfDescendants,
- moveBlocksToPosition
+ moveBlocks
);
eventHandler( event );
- expect( moveBlocksToPosition ).toHaveBeenCalledWith(
+ expect( moveBlocks ).toHaveBeenCalledWith(
sourceClientIds,
sourceRootClientId,
- targetRootClientId,
insertIndex
);
} );
@@ -306,7 +304,7 @@ describe( 'onFilesDrop', () => {
it( 'does nothing if hasUploadPermissions is false', () => {
const updateBlockAttributes = jest.fn();
const canInsertBlockType = noop;
- const insertBlocks = jest.fn();
+ const insertOrReplaceBlocks = jest.fn();
const targetRootClientId = '1';
const targetBlockIndex = 0;
const uploadPermissions = false;
@@ -317,12 +315,12 @@ describe( 'onFilesDrop', () => {
uploadPermissions,
updateBlockAttributes,
canInsertBlockType,
- insertBlocks
+ insertOrReplaceBlocks
);
onFileDropHandler();
expect( findTransform ).not.toHaveBeenCalled();
- expect( insertBlocks ).not.toHaveBeenCalled();
+ expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
} );
it( 'does nothing if the block has no matching file transforms', () => {
@@ -330,7 +328,7 @@ describe( 'onFilesDrop', () => {
// to have no return value.
findTransform.mockImplementation( noop );
const updateBlockAttributes = noop;
- const insertBlocks = jest.fn();
+ const insertOrReplaceBlocks = jest.fn();
const canInsertBlockType = noop;
const targetRootClientId = '1';
const targetBlockIndex = 0;
@@ -342,12 +340,12 @@ describe( 'onFilesDrop', () => {
uploadPermissions,
updateBlockAttributes,
canInsertBlockType,
- insertBlocks
+ insertOrReplaceBlocks
);
onFileDropHandler();
expect( findTransform ).toHaveBeenCalled();
- expect( insertBlocks ).not.toHaveBeenCalled();
+ expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
} );
it( 'inserts blocks if a valid transform can be found', () => {
@@ -359,7 +357,7 @@ describe( 'onFilesDrop', () => {
findTransform.mockImplementation( () => transformation );
const updateBlockAttributes = noop;
const canInsertBlockType = noop;
- const insertBlocks = jest.fn();
+ const insertOrReplaceBlocks = jest.fn();
const targetRootClientId = '1';
const targetBlockIndex = 0;
const uploadPermissions = true;
@@ -370,7 +368,7 @@ describe( 'onFilesDrop', () => {
uploadPermissions,
updateBlockAttributes,
canInsertBlockType,
- insertBlocks
+ insertOrReplaceBlocks
);
const files = 'test';
onFileDropHandler( files );
@@ -380,11 +378,7 @@ describe( 'onFilesDrop', () => {
files,
updateBlockAttributes
);
- expect( insertBlocks ).toHaveBeenCalledWith(
- blocks,
- targetBlockIndex,
- targetRootClientId
- );
+ expect( insertOrReplaceBlocks ).toHaveBeenCalledWith( blocks );
} );
} );
@@ -393,16 +387,16 @@ describe( 'onHTMLDrop', () => {
pasteHandler.mockImplementation( () => [] );
const targetRootClientId = '1';
const targetBlockIndex = 0;
- const insertBlocks = jest.fn();
+ const insertOrReplaceBlocks = jest.fn();
const eventHandler = onHTMLDrop(
targetRootClientId,
targetBlockIndex,
- insertBlocks
+ insertOrReplaceBlocks
);
eventHandler();
- expect( insertBlocks ).not.toHaveBeenCalled();
+ expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
} );
it( 'inserts blocks if the HTML can be converted into blocks', () => {
@@ -410,19 +404,15 @@ describe( 'onHTMLDrop', () => {
pasteHandler.mockImplementation( () => blocks );
const targetRootClientId = '1';
const targetBlockIndex = 0;
- const insertBlocks = jest.fn();
+ const insertOrReplaceBlocks = jest.fn();
const eventHandler = onHTMLDrop(
targetRootClientId,
targetBlockIndex,
- insertBlocks
+ insertOrReplaceBlocks
);
eventHandler();
- expect( insertBlocks ).toHaveBeenCalledWith(
- blocks,
- targetBlockIndex,
- targetRootClientId
- );
+ expect( insertOrReplaceBlocks ).toHaveBeenCalledWith( blocks );
} );
} );
diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js
index 2734ba69a65bb9..f0da074d196a2b 100644
--- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js
+++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js
@@ -167,7 +167,8 @@ export default function useArrowNav() {
}
function onKeyDown( event ) {
- const { keyCode, target } = event;
+ const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } =
+ event;
const isUp = keyCode === UP;
const isDown = keyCode === DOWN;
const isLeft = keyCode === LEFT;
@@ -176,9 +177,7 @@ export default function useArrowNav() {
const isHorizontal = isLeft || isRight;
const isVertical = isUp || isDown;
const isNav = isHorizontal || isVertical;
- const isShift = event.shiftKey;
- const hasModifier =
- isShift || event.ctrlKey || event.altKey || event.metaKey;
+ const hasModifier = shiftKey || ctrlKey || altKey || metaKey;
const isNavEdge = isVertical ? isVerticalEdge : isHorizontalEdge;
const { ownerDocument } = node;
const { defaultView } = ownerDocument;
@@ -200,7 +199,7 @@ export default function useArrowNav() {
return;
}
- if ( isShift ) {
+ if ( shiftKey ) {
return;
}
@@ -249,7 +248,7 @@ export default function useArrowNav() {
const isReverseDir = isRTL( target ) ? ! isReverse : isReverse;
const { keepCaretInsideBlock } = getSettings();
- if ( isShift ) {
+ if ( shiftKey ) {
if (
isClosestTabbableABlock( target, isReverse ) &&
isNavEdge( target, isReverse )
@@ -261,6 +260,9 @@ export default function useArrowNav() {
} else if (
isVertical &&
isVerticalEdge( target, isReverse ) &&
+ // When Alt is pressed, only intercept if the caret is also at
+ // the horizontal edge.
+ ( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) &&
! keepCaretInsideBlock
) {
const closestTabbable = getClosestTabbable(
@@ -273,8 +275,10 @@ export default function useArrowNav() {
if ( closestTabbable ) {
placeCaretAtVerticalEdge(
closestTabbable,
- isReverse,
- verticalRect
+ // When Alt is pressed, place the caret at the furthest
+ // horizontal edge and the furthest vertical edge.
+ altKey ? ! isReverse : isReverse,
+ altKey ? undefined : verticalRect
);
event.preventDefault();
}
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index 60a34f6ea55fb0..f6fa73a053ac58 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -20,6 +20,7 @@ import './metadata';
import './metadata-name';
export { useCustomSides } from './dimensions';
+export { useLayoutClasses, useLayoutStyles } from './layout';
export { getBorderClassesAndStyles, useBorderProps } from './use-border-props';
export { getColorClassesAndStyles, useColorProps } from './use-color-props';
export { getSpacingClassesAndStyles } from './use-spacing-props';
diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js
index ac24fa6f4e232a..73d655c57c2acb 100644
--- a/packages/block-editor/src/hooks/layout.js
+++ b/packages/block-editor/src/hooks/layout.js
@@ -37,58 +37,101 @@ import { getLayoutType, getLayoutTypes } from '../layouts';
const layoutBlockSupportKey = '__experimentalLayout';
/**
- * Generates the utility classnames for the given blocks layout attributes.
- * This method was primarily added to reintroduce classnames that were removed
- * in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719), rather
- * than providing an extensive list of all possible layout classes. The plan is to
- * have the style engine generate a more extensive list of utility classnames which
- * will then replace this method.
+ * Generates the utility classnames for the given block's layout attributes.
*
- * @param { Object } layout Layout object.
- * @param { Object } layoutDefinitions An object containing layout definitions, stored in theme.json.
+ * @param { Object } block Block object.
*
* @return { Array } Array of CSS classname strings.
*/
-function useLayoutClasses( layout, layoutDefinitions ) {
+export function useLayoutClasses( block = {} ) {
const rootPaddingAlignment = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return getSettings().__experimentalFeatures
?.useRootPaddingAwareAlignments;
}, [] );
+ const globalLayoutSettings = useSetting( 'layout' ) || {};
+
+ const { attributes = {}, name } = block;
+ const { layout } = attributes;
+
+ const { default: defaultBlockLayout } =
+ getBlockSupport( name, layoutBlockSupportKey ) || {};
+ const usedLayout =
+ layout?.inherit || layout?.contentSize || layout?.wideSize
+ ? { ...layout, type: 'constrained' }
+ : layout || defaultBlockLayout || {};
+
const layoutClassnames = [];
- if ( layoutDefinitions?.[ layout?.type || 'default' ]?.className ) {
+ if (
+ globalLayoutSettings?.definitions?.[ usedLayout?.type || 'default' ]
+ ?.className
+ ) {
layoutClassnames.push(
- layoutDefinitions?.[ layout?.type || 'default' ]?.className
+ globalLayoutSettings?.definitions?.[ usedLayout?.type || 'default' ]
+ ?.className
);
}
if (
- ( layout?.inherit ||
- layout?.contentSize ||
- layout?.type === 'constrained' ) &&
+ ( usedLayout?.inherit ||
+ usedLayout?.contentSize ||
+ usedLayout?.type === 'constrained' ) &&
rootPaddingAlignment
) {
layoutClassnames.push( 'has-global-padding' );
}
- if ( layout?.orientation ) {
- layoutClassnames.push( `is-${ kebabCase( layout.orientation ) }` );
+ if ( usedLayout?.orientation ) {
+ layoutClassnames.push( `is-${ kebabCase( usedLayout.orientation ) }` );
}
- if ( layout?.justifyContent ) {
+ if ( usedLayout?.justifyContent ) {
layoutClassnames.push(
- `is-content-justification-${ kebabCase( layout.justifyContent ) }`
+ `is-content-justification-${ kebabCase(
+ usedLayout.justifyContent
+ ) }`
);
}
- if ( layout?.flexWrap && layout.flexWrap === 'nowrap' ) {
+ if ( usedLayout?.flexWrap && usedLayout.flexWrap === 'nowrap' ) {
layoutClassnames.push( 'is-nowrap' );
}
return layoutClassnames;
}
+/**
+ * Generates a CSS rule with the given block's layout styles.
+ *
+ * @param { Object } block Block object.
+ * @param { string } selector A selector to use in generating the CSS rule.
+ *
+ * @return { string } CSS rule.
+ */
+export function useLayoutStyles( block = {}, selector ) {
+ const { attributes = {}, name } = block;
+ const { layout = {}, style = {} } = attributes;
+ // Update type for blocks using legacy layouts.
+ const usedLayout =
+ layout?.inherit || layout?.contentSize || layout?.wideSize
+ ? { ...layout, type: 'constrained' }
+ : layout || {};
+ const fullLayoutType = getLayoutType( usedLayout?.type || 'default' );
+ const globalLayoutSettings = useSetting( 'layout' ) || {};
+ const blockGapSupport = useSetting( 'spacing.blockGap' );
+ const hasBlockGapSupport = blockGapSupport !== null;
+ const css = fullLayoutType?.getLayoutStyle?.( {
+ blockName: name,
+ selector,
+ layout,
+ layoutDefinitions: globalLayoutSettings?.definitions,
+ style,
+ hasBlockGapSupport,
+ } );
+ return css;
+}
+
function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
const { layout } = attributes;
const defaultThemeLayout = useSetting( 'layout' );
@@ -299,7 +342,7 @@ export const withInspectorControls = createHigherOrderComponent(
*/
export const withLayoutStyles = createHigherOrderComponent(
( BlockListBlock ) => ( props ) => {
- const { name, attributes } = props;
+ const { name, attributes, block } = props;
const hasLayoutBlockSupport = hasBlockSupport(
name,
layoutBlockSupportKey
@@ -321,7 +364,7 @@ export const withLayoutStyles = createHigherOrderComponent(
? { ...layout, type: 'constrained' }
: layout || defaultBlockLayout || {};
const layoutClasses = hasLayoutBlockSupport
- ? useLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
+ ? useLayoutClasses( block )
: null;
const selector = `.${ getBlockDefaultClassName(
name
diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js
index ec0f20a8f9c892..1c81c910b21e12 100644
--- a/packages/block-editor/src/index.js
+++ b/packages/block-editor/src/index.js
@@ -12,6 +12,8 @@ export {
getSpacingClassesAndStyles as __experimentalGetSpacingClassesAndStyles,
getGapCSSValue as __experimentalGetGapCSSValue,
useCachedTruthy,
+ useLayoutClasses as __experimentaluseLayoutClasses,
+ useLayoutStyles as __experimentaluseLayoutStyles,
} from './hooks';
export * from './components';
export * from './elements';
diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js
index a27a799a203347..e306829c22ed55 100644
--- a/packages/block-editor/src/store/reducer.js
+++ b/packages/block-editor/src/store/reducer.js
@@ -2,7 +2,6 @@
* External dependencies
*/
import {
- flow,
reduce,
omit,
without,
@@ -15,6 +14,7 @@ import {
/**
* WordPress dependencies
*/
+import { pipe } from '@wordpress/compose';
import { combineReducers, select } from '@wordpress/data';
import { store as blocksStore } from '@wordpress/blocks';
/**
@@ -789,7 +789,7 @@ const withResetControlledBlocks = ( reducer ) => ( state, action ) => {
*
* @return {Object} Updated state.
*/
-export const blocks = flow(
+export const blocks = pipe(
combineReducers,
withSaveReusableBlock, // Needs to be before withBlockCache.
withBlockTree, // Needs to be before withInnerBlocksRemoveCascade.
@@ -1055,7 +1055,7 @@ export const blocks = flow(
const mappedBlocks = mapBlockOrder( action.blocks );
- return flow( [
+ return pipe( [
( nextState ) =>
omit( nextState, action.replacedClientIds ),
( nextState ) => ( {
@@ -1089,7 +1089,7 @@ export const blocks = flow(
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
- return flow( [
+ return pipe( [
// Remove inner block ordering for removed blocks.
( nextState ) => omit( nextState, action.removedClientIds ),
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index 498f3f0c4e72b4..837cee4427708f 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -2720,6 +2720,7 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) {
// In zoom-out mode, the block overlay is always active for top level blocks.
if (
editorMode === 'zoom-out' &&
+ clientId &&
! getBlockRootClientId( state, clientId )
) {
return true;
diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md
index ee4b758c7b8d2e..4890663b5458e2 100644
--- a/packages/block-library/CHANGELOG.md
+++ b/packages/block-library/CHANGELOG.md
@@ -9,6 +9,7 @@
### New Feature
- Made it possible to import individual blocks ([#42258](https://github.com/WordPress/gutenberg/pull/42258)). Check [README](./README.md#loading-individual-blocks) for more information.
+- Paragraph block: You can now drop files/blocks/HTML on an empty Paragraph block to transform it into relevant blocks ([#42722](https://github.com/WordPress/gutenberg/pull/42722)).
## 7.13.0 (2022-08-24)
diff --git a/packages/block-library/src/archives/index.php b/packages/block-library/src/archives/index.php
index afbf400fedba80..695affde760a8a 100644
--- a/packages/block-library/src/archives/index.php
+++ b/packages/block-library/src/archives/index.php
@@ -17,11 +17,12 @@
function render_block_core_archives( $attributes ) {
$show_post_count = ! empty( $attributes['showPostCounts'] );
$type = isset( $attributes['type'] ) ? $attributes['type'] : 'monthly';
- $class = '';
+
+ $class = 'wp-block-archives-list';
if ( ! empty( $attributes['displayAsDropdown'] ) ) {
- $class .= ' wp-block-archives-dropdown';
+ $class = 'wp-block-archives-dropdown';
$dropdown_id = wp_unique_id( 'wp-block-archives-' );
$title = __( 'Archives' );
@@ -40,9 +41,7 @@ function render_block_core_archives( $attributes ) {
$archives = wp_get_archives( $dropdown_args );
- $classnames = esc_attr( $class );
-
- $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classnames ) );
+ $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $class ) );
switch ( $dropdown_args['type'] ) {
case 'yearly':
@@ -75,8 +74,6 @@ function render_block_core_archives( $attributes ) {
);
}
- $class .= ' wp-block-archives-list';
-
/** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */
$archives_args = apply_filters(
'widget_archives_args',
diff --git a/packages/block-library/src/categories/index.php b/packages/block-library/src/categories/index.php
index 027688152fe7f9..7e3979b7aefe2e 100644
--- a/packages/block-library/src/categories/index.php
+++ b/packages/block-library/src/categories/index.php
@@ -14,7 +14,7 @@
*/
function render_block_core_categories( $attributes ) {
static $block_id = 0;
- $block_id++;
+ ++$block_id;
$args = array(
'echo' => false,
diff --git a/packages/block-library/src/classic.scss b/packages/block-library/src/classic.scss
new file mode 100644
index 00000000000000..c12983c7d9ad93
--- /dev/null
+++ b/packages/block-library/src/classic.scss
@@ -0,0 +1,15 @@
+// These rules are needed for backwards compatibility.
+.wp-block-button__link {
+ color: $white;
+ background-color: #32373c;
+ border-radius: 9999px; // 100% causes an oval, but any explicit but really high value retains the pill shape.
+
+ // This needs a low specificity so it won't override the rules from the button element if defined in theme.json.
+ box-shadow: none;
+ text-decoration: none;
+
+ // The extra 2px are added to size solids the same as the outline versions.
+ padding: calc(0.667em + 2px) calc(1.333em + 2px);
+
+ font-size: 1.125em;
+}
diff --git a/packages/block-library/src/code/style.scss b/packages/block-library/src/code/style.scss
index e8d3b07cd034fa..670a4f7f1ef4c8 100644
--- a/packages/block-library/src/code/style.scss
+++ b/packages/block-library/src/code/style.scss
@@ -1,8 +1,13 @@
-// Provide a minimum of overflow handling and ensure the code markup inherits
-// the font-family set on pre.
-.wp-block-code code {
- display: block;
- font-family: inherit;
- overflow-wrap: break-word;
- white-space: pre-wrap;
+.wp-block-code {
+ // This block has customizable padding, border-box makes that more predictable.
+ box-sizing: border-box;
+
+ // Provide a minimum of overflow handling and ensure the code markup inherits
+ // the font-family set on pre.
+ code {
+ display: block;
+ font-family: inherit;
+ overflow-wrap: break-word;
+ white-space: pre-wrap;
+ }
}
diff --git a/packages/block-library/src/code/utils.js b/packages/block-library/src/code/utils.js
index 5cf110230f11db..0beabaa8ee1d9d 100644
--- a/packages/block-library/src/code/utils.js
+++ b/packages/block-library/src/code/utils.js
@@ -1,7 +1,7 @@
/**
- * External dependencies
+ * WordPress dependencies
*/
-import { flow } from 'lodash';
+import { pipe } from '@wordpress/compose';
/**
* Escapes ampersands, shortcodes, and links.
@@ -10,7 +10,7 @@ import { flow } from 'lodash';
* @return {string} The given content with some characters escaped.
*/
export function escape( content ) {
- return flow(
+ return pipe(
escapeOpeningSquareBrackets,
escapeProtocolInIsolatedUrls
)( content || '' );
diff --git a/packages/block-library/src/comment-author-name/index.php b/packages/block-library/src/comment-author-name/index.php
index 41ab4386069e9d..04d8e60c65e8ca 100644
--- a/packages/block-library/src/comment-author-name/index.php
+++ b/packages/block-library/src/comment-author-name/index.php
@@ -34,7 +34,7 @@ function render_block_core_comment_author_name( $attributes, $content, $block )
$comment_author = get_comment_author( $comment );
$link = get_comment_author_url( $comment );
- if ( ! empty( $attributes['isLink'] ) && ! empty( $attributes['linkTarget'] ) ) {
+ if ( ! empty( $link ) && ! empty( $attributes['isLink'] ) && ! empty( $attributes['linkTarget'] ) ) {
$comment_author = sprintf( '%3s ', esc_url( $link ), esc_attr( $attributes['linkTarget'] ), $comment_author );
}
if ( '0' === $comment->comment_approved && ! $show_pending_links ) {
diff --git a/packages/block-library/src/comment-reply-link/index.php b/packages/block-library/src/comment-reply-link/index.php
index 169b62ac24bdf0..5b9bf1068fb21a 100644
--- a/packages/block-library/src/comment-reply-link/index.php
+++ b/packages/block-library/src/comment-reply-link/index.php
@@ -34,7 +34,7 @@ function render_block_core_comment_reply_link( $attributes, $content, $block ) {
// Compute comment's depth iterating over its ancestors.
while ( ! empty( $parent_id ) ) {
- $depth++;
+ ++$depth;
$parent_id = get_comment( $parent_id )->comment_parent;
}
diff --git a/packages/block-library/src/comment-template/index.php b/packages/block-library/src/comment-template/index.php
index 49ca8561e2d47a..08620a3ea695fd 100644
--- a/packages/block-library/src/comment-template/index.php
+++ b/packages/block-library/src/comment-template/index.php
@@ -16,6 +16,8 @@
*/
function block_core_comment_template_render_comments( $comments, $block ) {
global $comment_depth;
+ $thread_comments = get_option( 'thread_comments' );
+ $thread_comments_depth = get_option( 'thread_comments_depth' );
if ( empty( $comment_depth ) ) {
$comment_depth = 1;
@@ -46,21 +48,28 @@ function block_core_comment_template_render_comments( $comments, $block ) {
// If the comment has children, recurse to create the HTML for the nested
// comments.
- if ( ! empty( $children ) ) {
- $comment_depth += 1;
- $inner_content = block_core_comment_template_render_comments(
- $children,
- $block
- );
- $block_content .= sprintf( '%1$s ', $inner_content );
- $comment_depth -= 1;
+ if ( ! empty( $children ) && ! empty( $thread_comments ) ) {
+ if ( $comment_depth < $thread_comments_depth ) {
+ ++$comment_depth;
+ $inner_content = block_core_comment_template_render_comments(
+ $children,
+ $block
+ );
+ $block_content .= sprintf( '%1$s ', $inner_content );
+ --$comment_depth;
+ } else {
+ $inner_content = block_core_comment_template_render_comments(
+ $children,
+ $block
+ );
+ $block_content .= sprintf( $inner_content );
+ }
}
$content .= sprintf( '', $comment->comment_ID, $comment_classes, $block_content );
}
return $content;
-
}
/**
diff --git a/packages/block-library/src/comments-pagination-numbers/block.json b/packages/block-library/src/comments-pagination-numbers/block.json
index 97a0649a7a4c12..479872bccf1408 100644
--- a/packages/block-library/src/comments-pagination-numbers/block.json
+++ b/packages/block-library/src/comments-pagination-numbers/block.json
@@ -11,6 +11,13 @@
"supports": {
"reusable": false,
"html": false,
+ "color": {
+ "gradients": true,
+ "text": false,
+ "__experimentalDefaultControls": {
+ "background": true
+ }
+ },
"typography": {
"fontSize": true,
"lineHeight": true,
diff --git a/packages/block-library/src/cover/index.php b/packages/block-library/src/cover/index.php
index 4168d267671f7d..e5a497fd768890 100644
--- a/packages/block-library/src/cover/index.php
+++ b/packages/block-library/src/cover/index.php
@@ -25,7 +25,7 @@ function render_block_core_cover( $attributes, $content ) {
);
if ( isset( $attributes['focalPoint'] ) ) {
- $object_position = round( $attributes['focalPoint']['x'] * 100 ) . '%' . ' ' . round( $attributes['focalPoint']['y'] * 100 ) . '%';
+ $object_position = round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%';
$attr['data-object-position'] = $object_position;
$attr['style'] = 'object-position: ' . $object_position;
}
diff --git a/packages/block-library/src/gallery/gallery.js b/packages/block-library/src/gallery/gallery.js
index b3933e2a1b7b7a..9a551b6e0d9f78 100644
--- a/packages/block-library/src/gallery/gallery.js
+++ b/packages/block-library/src/gallery/gallery.js
@@ -12,7 +12,6 @@ import {
__experimentalGetElementClassName,
} from '@wordpress/block-editor';
import { VisuallyHidden } from '@wordpress/components';
-import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { createBlock, getDefaultBlockName } from '@wordpress/blocks';
import { View } from '@wordpress/primitives';
@@ -38,26 +37,6 @@ export const Gallery = ( props ) => {
__experimentalLayout: { type: 'default', alignments: [] },
} );
- const [ captionFocused, setCaptionFocused ] = useState( false );
-
- function onFocusCaption() {
- if ( ! captionFocused ) {
- setCaptionFocused( true );
- }
- }
-
- function removeCaptionFocus() {
- if ( captionFocused ) {
- setCaptionFocused( false );
- }
- }
-
- useEffect( () => {
- if ( ! isSelected ) {
- setCaptionFocused( false );
- }
- }, [ isSelected ] );
-
return (
{
>
{ children }
{ isSelected && ! children && (
-
+
{ mediaPlaceholder }
) }
{
function RichTextVisibilityHelper( {
isHidden,
- captionFocused,
- onFocusCaption,
className,
value,
placeholder,
@@ -125,8 +97,6 @@ function RichTextVisibilityHelper( {
placeholder={ placeholder }
className={ className }
tagName={ tagName }
- isSelected={ captionFocused }
- onClick={ onFocusCaption }
{ ...richTextProps }
/>
);
diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js
index e9e318b6b10a7a..9d43c4339ba1f5 100644
--- a/packages/block-library/src/group/edit.js
+++ b/packages/block-library/src/group/edit.js
@@ -53,7 +53,7 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
? { ...defaultLayout, ...layout, type: 'default' }
: { ...defaultLayout, ...layout };
const { type = 'default' } = usedLayout;
- const layoutSupportEnabled = themeSupportsLayout || type !== 'default';
+ const layoutSupportEnabled = themeSupportsLayout || type === 'flex';
const blockProps = useBlockProps();
diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss
index d6ab8704911a07..f20f0afee5f06c 100644
--- a/packages/block-library/src/image/editor.scss
+++ b/packages/block-library/src/image/editor.scss
@@ -22,6 +22,10 @@
.components-placeholder__illustration {
display: none;
}
+
+ &::before {
+ opacity: 0;
+ }
}
// Remove the transition while we still have a legacy placeholder style.
diff --git a/packages/block-library/src/latest-posts/index.php b/packages/block-library/src/latest-posts/index.php
index cbeafb6677a137..18168ba37bce84 100644
--- a/packages/block-library/src/latest-posts/index.php
+++ b/packages/block-library/src/latest-posts/index.php
@@ -55,7 +55,7 @@ function render_block_core_latest_posts( $attributes ) {
$args['author'] = $attributes['selectedAuthor'];
}
- $query = new WP_Query;
+ $query = new WP_Query();
$recent_posts = $query->query( $args );
if ( isset( $attributes['displayFeaturedImage'] ) && $attributes['displayFeaturedImage'] ) {
diff --git a/packages/block-library/src/navigation-submenu/index.php b/packages/block-library/src/navigation-submenu/index.php
index 3c41fb340cafb6..f48254824e5cc1 100644
--- a/packages/block-library/src/navigation-submenu/index.php
+++ b/packages/block-library/src/navigation-submenu/index.php
@@ -148,7 +148,7 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) {
$css_classes = trim( implode( ' ', $classes ) );
$has_submenu = count( $block->inner_blocks ) > 0;
- $is_active = ! empty( $attributes['id'] ) && ( get_the_ID() === (int) $attributes['id'] );
+ $is_active = ! empty( $attributes['id'] ) && ( get_queried_object_id() === (int) $attributes['id'] );
$show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon'];
$open_on_click = isset( $block->context['openSubmenusOnClick'] ) && $block->context['openSubmenusOnClick'];
@@ -183,7 +183,16 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) {
if ( ! $open_on_click ) {
$item_url = isset( $attributes['url'] ) ? $attributes['url'] : '';
// Start appending HTML attributes to anchor tag.
- $html .= ' {
- element
- .querySelectorAll( '[aria-expanded="true"]' )
- .forEach( ( toggle ) => {
- toggle.setAttribute( 'aria-expanded', 'false' );
- } );
-};
-
-const toggleSubmenuOnClick = ( event ) => {
- const buttonToggle = event.target.closest( '[aria-expanded]' );
- const isSubmenuOpen = buttonToggle.getAttribute( 'aria-expanded' );
-
- if ( isSubmenuOpen === 'true' ) {
- closeSubmenus( buttonToggle.closest( '.wp-block-navigation-submenu' ) );
- } else {
- // Close all sibling submenus.
- const parentElement = buttonToggle.closest(
- '.wp-block-navigation-submenu'
- );
- const parentList =
- buttonToggle.closest( '.wp-block-navigation__submenu-container' ) ||
- buttonToggle.closest( '.wp-block-navigation__container' );
- Array.from( parentList.children ).forEach( ( child ) => {
- if ( child !== parentElement ) {
- closeSubmenus( child );
- }
- } );
- // Open submenu.
- buttonToggle.setAttribute( 'aria-expanded', 'true' );
- }
-};
-
-const submenuButtons = document.querySelectorAll(
- '.wp-block-navigation-submenu__toggle'
-);
-
-submenuButtons.forEach( ( button ) => {
- button.addEventListener( 'click', toggleSubmenuOnClick );
-} );
-
-// Close on click outside.
-document.addEventListener( 'click', function ( event ) {
- const navigationBlocks = document.querySelectorAll(
- '.wp-block-navigation'
- );
- navigationBlocks.forEach( ( block ) => {
- if ( ! block.contains( event.target ) ) {
- closeSubmenus( block );
- }
- } );
-} );
-// Close on focus outside or escape key.
-document.addEventListener( 'keyup', function ( event ) {
- const submenuBlocks = document.querySelectorAll(
- '.wp-block-navigation-submenu'
- );
- submenuBlocks.forEach( ( block ) => {
- if ( ! block.contains( event.target ) ) {
- closeSubmenus( block );
- } else if ( event.key === 'Escape' ) {
- const toggle = block.querySelector( '[aria-expanded="true"]' );
- closeSubmenus( block );
- // Focus the submenu trigger so focus does not get trapped in the closed submenu.
- toggle?.focus();
- }
- } );
-} );
diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js
index 751d33b9b501f4..6cb773e60107bd 100644
--- a/packages/block-library/src/navigation/edit/index.js
+++ b/packages/block-library/src/navigation/edit/index.js
@@ -282,16 +282,18 @@ function Navigation( {
hasResolvedNavigationMenus &&
! hasUncontrolledInnerBlocks;
- if ( isPlaceholder && ! ref ) {
- /**
- * this fallback only displays (both in editor and on front)
- * the list of pages block if no menu is available as a fallback.
- * We don't want the fallback to request a save,
- * nor to be undoable, hence we mark it non persistent.
- */
- __unstableMarkNextChangeAsNotPersistent();
- replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] );
- }
+ useEffect( () => {
+ if ( isPlaceholder && ! ref ) {
+ /**
+ * this fallback only displays (both in editor and on front)
+ * the list of pages block if no menu is available as a fallback.
+ * We don't want the fallback to request a save,
+ * nor to be undoable, hence we mark it non persistent.
+ */
+ __unstableMarkNextChangeAsNotPersistent();
+ replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] );
+ }
+ }, [ clientId, isPlaceholder, ref ] );
const isEntityAvailable =
! isNavigationMenuMissing && isNavigationMenuResolved;
diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss
index 3e554327cf0e37..2e63b25ac72e03 100644
--- a/packages/block-library/src/navigation/editor.scss
+++ b/packages/block-library/src/navigation/editor.scss
@@ -629,3 +629,9 @@ body.editor-styles-wrapper
margin-bottom: $grid-unit-20;
width: 100%;
}
+
+// Buttons inside a disabled component get semitransparent when there's a clickthrough overlay.
+// Since this navigation button is content rather than UI, however, override that.
+.wp-block-navigation__responsive-container-open.components-button {
+ opacity: 1;
+}
diff --git a/packages/block-library/src/navigation/style.scss b/packages/block-library/src/navigation/style.scss
index 9114df2e6e210a..0a00d7a779d314 100644
--- a/packages/block-library/src/navigation/style.scss
+++ b/packages/block-library/src/navigation/style.scss
@@ -47,6 +47,14 @@ $navigation-icon-size: 24px;
display: block;
}
+ // This rule needs extra specificity so that it inherits the correct color from its parent.
+ // Otherwise, a link color set by a parent group can override the value.
+ // This also fixes an issue where a navigation with an explicitly set color is overridden
+ // by link colors defined in Global Styles.
+ .wp-block-navigation-item__content.wp-block-navigation-item__content {
+ color: inherit;
+ }
+
// The following rules provide class based application of user selected text
// decoration via block supports.
&.has-text-decoration-underline .wp-block-navigation-item__content {
diff --git a/packages/block-library/src/page-list/index.php b/packages/block-library/src/page-list/index.php
index 89a8ea1b071be3..fbb83a1fd9407f 100644
--- a/packages/block-library/src/page-list/index.php
+++ b/packages/block-library/src/page-list/index.php
@@ -189,7 +189,7 @@ function block_core_page_list_render_nested_page_list( $open_submenus_on_click,
if ( isset( $page['children'] ) && $is_navigation_child && $open_submenus_on_click ) {
$markup .= '' . '';
+ '';
} else {
$markup .= ' ' . $title . ' ';
}
@@ -243,7 +243,7 @@ function block_core_page_list_nest_pages( $current_level, $children ) {
*/
function render_block_core_page_list( $attributes, $content, $block ) {
static $block_id = 0;
- $block_id++;
+ ++$block_id;
$all_pages = get_pages(
array(
@@ -264,7 +264,7 @@ function render_block_core_page_list( $attributes, $content, $block ) {
$active_page_ancestor_ids = array();
foreach ( (array) $all_pages as $page ) {
- $is_active = ! empty( $page->ID ) && ( get_the_ID() === $page->ID );
+ $is_active = ! empty( $page->ID ) && ( get_queried_object_id() === $page->ID );
if ( $is_active ) {
$active_page_ancestor_ids = get_post_ancestors( $page->ID );
diff --git a/packages/block-library/src/paragraph/deprecated.js b/packages/block-library/src/paragraph/deprecated.js
index 3d3505b9f132ec..b5b62992aab769 100644
--- a/packages/block-library/src/paragraph/deprecated.js
+++ b/packages/block-library/src/paragraph/deprecated.js
@@ -11,8 +11,11 @@ import {
getColorClassName,
getFontSizeClass,
RichText,
+ useBlockProps,
} from '@wordpress/block-editor';
+import { isRTL } from '@wordpress/i18n';
+
const supports = {
className: false,
};
@@ -90,6 +93,39 @@ const migrateCustomColorsAndFontSizes = ( attributes ) => {
const { style, ...restBlockAttributes } = blockAttributes;
const deprecated = [
+ // Version without drop cap on aligned text.
+ {
+ supports,
+ attributes: {
+ ...restBlockAttributes,
+ customTextColor: {
+ type: 'string',
+ },
+ customBackgroundColor: {
+ type: 'string',
+ },
+ customFontSize: {
+ type: 'number',
+ },
+ },
+ save( { attributes } ) {
+ const { align, content, dropCap, direction } = attributes;
+ const className = classnames( {
+ 'has-drop-cap':
+ align === ( isRTL() ? 'left' : 'right' ) ||
+ align === 'center'
+ ? false
+ : dropCap,
+ [ `has-text-align-${ align }` ]: align,
+ } );
+
+ return (
+
+
+
+ );
+ },
+ },
{
supports,
attributes: {
diff --git a/packages/block-library/src/paragraph/drop-zone.js b/packages/block-library/src/paragraph/drop-zone.js
new file mode 100644
index 00000000000000..e51fb84acf8062
--- /dev/null
+++ b/packages/block-library/src/paragraph/drop-zone.js
@@ -0,0 +1,105 @@
+/**
+ * WordPress dependencies
+ */
+import { useState } from '@wordpress/element';
+import { useSelect } from '@wordpress/data';
+import {
+ __experimentalUseOnBlockDrop as useOnBlockDrop,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+import {
+ __experimentalUseDropZone as useDropZone,
+ useReducedMotion,
+} from '@wordpress/compose';
+import {
+ Popover,
+ __unstableMotion as motion,
+ __unstableAnimatePresence as AnimatePresence,
+} from '@wordpress/components';
+
+const animateVariants = {
+ hide: { opacity: 0, scaleY: 0.75 },
+ show: { opacity: 1, scaleY: 1 },
+ exit: { opacity: 0, scaleY: 0.9 },
+};
+
+export default function DropZone( { paragraphElement, clientId } ) {
+ const { rootClientId, blockIndex } = useSelect(
+ ( select ) => {
+ const selectors = select( blockEditorStore );
+ return {
+ rootClientId: selectors.getBlockRootClientId( clientId ),
+ blockIndex: selectors.getBlockIndex( clientId ),
+ };
+ },
+ [ clientId ]
+ );
+ const onBlockDrop = useOnBlockDrop( rootClientId, blockIndex, {
+ action: 'replace',
+ } );
+ const [ isDragging, setIsDragging ] = useState( false );
+ const [ isVisible, setIsVisible ] = useState( false );
+ const popoverRef = useDropZone( {
+ onDragStart: () => {
+ setIsDragging( true );
+ },
+ onDragEnd: () => {
+ setIsDragging( false );
+ },
+ } );
+ const dropZoneRef = useDropZone( {
+ onDrop: onBlockDrop,
+ onDragEnter: () => {
+ setIsVisible( true );
+ },
+ onDragLeave: () => {
+ setIsVisible( false );
+ },
+ } );
+ const reducedMotion = useReducedMotion();
+
+ return (
+
+ { isDragging ? (
+
+
+ { isVisible ? (
+
+ ) : null }
+
+
+ ) : null }
+
+ );
+}
diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js
index dd47ae81466229..c049b0b72bd249 100644
--- a/packages/block-library/src/paragraph/edit.js
+++ b/packages/block-library/src/paragraph/edit.js
@@ -6,6 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
+import { useState } from '@wordpress/element';
import { __, _x, isRTL } from '@wordpress/i18n';
import {
ToolbarButton,
@@ -20,6 +21,7 @@ import {
useBlockProps,
useSetting,
} from '@wordpress/block-editor';
+import { useMergeRefs } from '@wordpress/compose';
import { createBlock } from '@wordpress/blocks';
import { formatLtr } from '@wordpress/icons';
@@ -27,6 +29,7 @@ import { formatLtr } from '@wordpress/icons';
* Internal dependencies
*/
import { useOnEnter } from './use-enter';
+import DropZone from './drop-zone';
const name = 'core/paragraph';
@@ -45,6 +48,10 @@ function ParagraphRTLControl( { direction, setDirection } ) {
);
}
+function hasDropCapDisabled( align ) {
+ return align === ( isRTL() ? 'left' : 'right' ) || align === 'center';
+}
+
function ParagraphBlock( {
attributes,
mergeBlocks,
@@ -55,22 +62,40 @@ function ParagraphBlock( {
} ) {
const { align, content, direction, dropCap, placeholder } = attributes;
const isDropCapFeatureEnabled = useSetting( 'typography.dropCap' );
+ const [ paragraphElement, setParagraphElement ] = useState( null );
const blockProps = useBlockProps( {
- ref: useOnEnter( { clientId, content } ),
+ ref: useMergeRefs( [
+ useOnEnter( { clientId, content } ),
+ setParagraphElement,
+ ] ),
className: classnames( {
- 'has-drop-cap': dropCap,
+ 'has-drop-cap': hasDropCapDisabled( align ) ? false : dropCap,
[ `has-text-align-${ align }` ]: align,
} ),
style: { direction },
} );
+ let helpText;
+ if ( hasDropCapDisabled( align ) ) {
+ helpText = __( 'Not available for aligned text.' );
+ } else if ( dropCap ) {
+ helpText = __( 'Showing large initial letter.' );
+ } else {
+ helpText = __( 'Toggle to show a large initial letter.' );
+ }
+
return (
<>
- setAttributes( { align: newAlign } )
+ setAttributes( {
+ align: newAlign,
+ dropCap: hasDropCapDisabled( newAlign )
+ ? false
+ : dropCap,
+ } )
}
/>
setAttributes( { dropCap: ! dropCap } )
}
- help={
- dropCap
- ? __( 'Showing large initial letter.' )
- : __(
- 'Toggle to show a large initial letter.'
- )
+ help={ helpText }
+ disabled={
+ hasDropCapDisabled( align ) ? true : false
}
/>
) }
+ { ! content && (
+
+ ) }
{
avatarSizes.push( {
@@ -118,6 +119,22 @@ function PostAuthorEdit( {
setAttributes( { showBio: ! showBio } )
}
/>
+ setAttributes( { isLink: ! isLink } ) }
+ />
+ { isLink && (
+
+ setAttributes( {
+ linkTarget: value ? '_blank' : '_self',
+ } )
+ }
+ checked={ linkTarget === '_blank' }
+ />
+ ) }
@@ -158,7 +175,16 @@ function PostAuthorEdit( {
/>
) }
- { authorDetails?.name || __( 'Post Author' ) }
+ { isLink ? (
+ event.preventDefault() }
+ >
+ { authorName }
+
+ ) : (
+ authorName
+ ) }
{ showBio && (
%2s', esc_url( $link ), esc_attr( $attributes['linkTarget'] ), $author_name );
+ }
+
$byline = ! empty( $attributes['byline'] ) ? $attributes['byline'] : false;
$classes = array_merge(
isset( $attributes['itemsJustification'] ) ? array( 'items-justified-' . $attributes['itemsJustification'] ) : array(),
@@ -41,7 +47,7 @@ function render_block_core_post_author( $attributes, $content, $block ) {
( ! empty( $attributes['showAvatar'] ) ? '
' . $avatar . '
' : '' ) .
'' .
( ! empty( $byline ) ? '
' . wp_kses_post( $byline ) . '
' : '' ) .
- '
' . get_the_author_meta( 'display_name', $author_id ) . '
' .
+ '
' . $author_name . '
' .
( ! empty( $attributes['showBio'] ) ? '
' . get_the_author_meta( 'user_description', $author_id ) . '
' : '' ) .
'
' .
' ';
diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js
index 233399a63f8d55..1949553b2540f6 100644
--- a/packages/block-library/src/post-content/edit.js
+++ b/packages/block-library/src/post-content/edit.js
@@ -46,7 +46,9 @@ function EditableContent( { layout, context = {} } ) {
return getSettings()?.supportsLayout;
}, [] );
const defaultLayout = useSetting( 'layout' ) || {};
- const usedLayout = !! layout && layout.inherit ? defaultLayout : layout;
+ const usedLayout = ! layout?.type
+ ? { ...defaultLayout, ...layout, type: 'default' }
+ : { ...defaultLayout, ...layout };
const [ blocks, onInput, onChange ] = useEntityBlockEditor(
'postType',
postType,
diff --git a/packages/block-library/src/post-featured-image/block.json b/packages/block-library/src/post-featured-image/block.json
index 1072c7576d6454..40f51cffa06e75 100644
--- a/packages/block-library/src/post-featured-image/block.json
+++ b/packages/block-library/src/post-featured-image/block.json
@@ -62,7 +62,7 @@
"color": true,
"radius": true,
"width": true,
- "__experimentalSelector": "img, .block-editor-media-placeholder",
+ "__experimentalSelector": "img, .block-editor-media-placeholder, .wp-block-post-featured-image__overlay",
"__experimentalSkipSerialization": true,
"__experimentalDefaultControls": {
"color": true,
diff --git a/packages/block-library/src/post-featured-image/editor.scss b/packages/block-library/src/post-featured-image/editor.scss
index c52d14f44f7a6c..1af6e63e1be4a2 100644
--- a/packages/block-library/src/post-featured-image/editor.scss
+++ b/packages/block-library/src/post-featured-image/editor.scss
@@ -6,87 +6,94 @@
backdrop-filter: none; // Removes background blur so the overlay's actual color is visible.
}
- &.wp-block-post-featured-image {
- // Style the placeholder.
- .wp-block-post-featured-image__placeholder,
- .components-placeholder {
- justify-content: center;
- align-items: center;
- padding: 0;
+ // Style the placeholder.
+ .wp-block-post-featured-image__placeholder,
+ .components-placeholder {
+ justify-content: center;
+ align-items: center;
+ padding: 0;
- // Hide the upload button, as it's also available in the media library.
- .components-form-file-upload {
- display: none;
- }
+ // Hide the upload button, as it's also available in the media library.
+ .components-form-file-upload {
+ display: none;
+ }
- // Style the upload button.
- .components-button.components-button {
- padding: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- width: $grid-unit-60;
- height: $grid-unit-60;
- border-radius: 50%;
- position: relative;
- background: var(--wp-admin-theme-color);
- border-color: var(--wp-admin-theme-color);
- border-style: solid;
- color: $white;
+ // Style the upload button.
+ .components-button {
+ padding: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: $grid-unit-60;
+ height: $grid-unit-60;
+ border-radius: 50%;
+ position: relative;
+ background: var(--wp-admin-theme-color);
+ border-color: var(--wp-admin-theme-color);
+ border-style: solid;
+ color: $white;
- > svg {
- color: inherit;
- }
+ > svg {
+ color: inherit;
}
+ }
- // Show default placeholder height when not resized.
- min-height: 200px;
-
- // The following override the default placeholder styles that remove
- // its border so that a user selection for border color or width displays
- // a visual border.
- &:where(.has-border-color) {
- border-style: solid;
- }
- &:where([style*="border-top-color"]) {
- border-top-style: solid;
- }
- &:where([style*="border-right-color"]) {
- border-right-style: solid;
- }
- &:where([style*="border-bottom-color"]) {
- border-bottom-style: solid;
- }
- &:where([style*="border-left-color"]) {
- border-left-style: solid;
- }
+ // Show default placeholder height when not resized.
+ min-height: 200px;
+ }
- &:where([style*="border-width"]) {
- border-style: solid;
- }
- &:where([style*="border-top-width"]) {
- border-top-style: solid;
- }
- &:where([style*="border-right-width"]) {
- border-right-style: solid;
- }
- &:where([style*="border-bottom-width"]) {
- border-bottom-style: solid;
- }
- &:where([style*="border-left-width"]) {
- border-left-style: solid;
- }
+ // The following override the default placeholder styles that remove
+ // its border so that a user selection for border color or width displays
+ // a visual border. They also override the `img { border: none; }` applied
+ // by core.
+ .wp-block-post-featured-image__placeholder,
+ .components-placeholder,
+ img {
+ // The following is required to overcome WP Core applying styles that clear
+ // img borders with a higher specificity than those added by the border
+ // block support to provide a default border-style of solid when a border
+ // color or width has been set.
+ &:where(.has-border-color) {
+ border-style: solid;
+ }
+ &:where([style*="border-top-color"]) {
+ border-top-style: solid;
+ }
+ &:where([style*="border-right-color"]) {
+ border-right-style: solid;
+ }
+ &:where([style*="border-bottom-color"]) {
+ border-bottom-style: solid;
+ }
+ &:where([style*="border-left-color"]) {
+ border-left-style: solid;
}
- // Provide a minimum size for the placeholder when resized.
- // Note, this should be as small as we can afford it, and exists only
- // to ensure there's room for the upload button.
- &[style*="height"] .components-placeholder {
- min-height: $grid-unit-60;
- min-width: $grid-unit-60;
- height: 100%;
- width: 100%;
+ &:where([style*="border-width"]) {
+ border-style: solid;
+ }
+ &:where([style*="border-top-width"]) {
+ border-top-style: solid;
+ }
+ &:where([style*="border-right-width"]) {
+ border-right-style: solid;
}
+ &:where([style*="border-bottom-width"]) {
+ border-bottom-style: solid;
+ }
+ &:where([style*="border-left-width"]) {
+ border-left-style: solid;
+ }
+ }
+
+ // Provide a minimum size for the placeholder when resized.
+ // Note, this should be as small as we can afford it, and exists only
+ // to ensure there's room for the upload button.
+ &[style*="height"] .components-placeholder {
+ min-height: $grid-unit-60;
+ min-width: $grid-unit-60;
+ height: 100%;
+ width: 100%;
}
}
diff --git a/packages/block-library/src/post-featured-image/index.php b/packages/block-library/src/post-featured-image/index.php
index 552811f6d2f21d..40a7f41cd78ac3 100644
--- a/packages/block-library/src/post-featured-image/index.php
+++ b/packages/block-library/src/post-featured-image/index.php
@@ -76,16 +76,25 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes
$has_custom_gradient = isset( $attributes['customGradient'] ) && $attributes['customGradient'];
$has_solid_overlay = isset( $attributes['overlayColor'] ) && $attributes['overlayColor'];
$has_custom_overlay = isset( $attributes['customOverlayColor'] ) && $attributes['customOverlayColor'];
- $class_names = array(
- 'wp-block-post-featured-image__overlay',
- );
- $styles_properties = array();
+ $class_names = array( 'wp-block-post-featured-image__overlay' );
+ $styles = array();
if ( ! $has_dim_background ) {
return '';
}
- // Generate required classes for the element.
+ // Apply border classes and styles.
+ $border_attributes = get_block_core_post_featured_image_border_attributes( $attributes );
+
+ if ( ! empty( $border_attributes['class'] ) ) {
+ $class_names[] = $border_attributes['class'];
+ }
+
+ if ( ! empty( $border_attributes['style'] ) ) {
+ $styles[] = $border_attributes['style'];
+ }
+
+ // Apply overlay and gradient classes.
if ( $has_dim_background ) {
$class_names[] = 'has-background-dim';
$class_names[] = "has-background-dim-{$attributes['dimRatio']}";
@@ -103,35 +112,20 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes
$class_names[] = "has-{$attributes['gradient']}-gradient-background";
}
- // Generate required CSS properties and their values.
- if ( ! empty( $attributes['style']['border']['radius'] ) ) {
- $styles_properties['border-radius'] = $attributes['style']['border']['radius'];
- }
-
- if ( ! empty( $attributes['style']['border']['width'] ) ) {
- $styles_properties['border-width'] = $attributes['style']['border']['width'];
- }
-
+ // Apply background styles.
if ( $has_custom_gradient ) {
- $styles_properties['background-image'] = $attributes['customGradient'];
+ $styles[] = sprintf( 'background-image: %s;', $attributes['customGradient'] );
}
if ( $has_custom_overlay ) {
- $styles_properties['background-color'] = $attributes['customOverlayColor'];
- }
-
- $styles = '';
-
- foreach ( $styles_properties as $style_attribute => $style_attribute_value ) {
- $styles .= "{$style_attribute}: $style_attribute_value; ";
+ $styles[] = sprintf( 'background-color: %s;', $attributes['customOverlayColor'] );
}
return sprintf(
' ',
esc_attr( implode( ' ', $class_names ) ),
- esc_attr( trim( $styles ) )
+ esc_attr( safecss_filter_attr( implode( ' ', $styles ) ) )
);
-
}
/**
diff --git a/packages/block-library/src/post-featured-image/overlay.js b/packages/block-library/src/post-featured-image/overlay.js
index 572cef64801e76..f577978b9a3c93 100644
--- a/packages/block-library/src/post-featured-image/overlay.js
+++ b/packages/block-library/src/post-featured-image/overlay.js
@@ -47,20 +47,23 @@ const Overlay = ( {
return (
<>
-
+ { !! dimRatio && (
+
+ ) }
);
}
diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js
index 2900debcd16b3d..225299123c642b 100644
--- a/packages/block-library/src/query/edit/inspector-controls/index.js
+++ b/packages/block-library/src/query/edit/inspector-controls/index.js
@@ -237,10 +237,7 @@ export default function QueryInspectorControls( {
) }
{ isPostTypeHierarchical &&
- ! isControlAllowed(
- allowedControls,
- 'parents'
- ) && (
+ isControlAllowed( allowedControls, 'parents' ) && (
!! parents?.length }
label={ __( 'Parents' ) }
diff --git a/packages/block-library/src/query/edit/inspector-controls/parent-control.js b/packages/block-library/src/query/edit/inspector-controls/parent-control.js
index 8e13cb8812f3d9..830600e47481dd 100644
--- a/packages/block-library/src/query/edit/inspector-controls/parent-control.js
+++ b/packages/block-library/src/query/edit/inspector-controls/parent-control.js
@@ -125,6 +125,7 @@ function ParentControl( { parents, postType, onChange } ) {
onInputChange={ debouncedSearch }
suggestions={ suggestions }
onChange={ onParentChange }
+ __experimentalShowHowTo={ false }
/>
);
}
diff --git a/packages/block-library/src/query/edit/inspector-controls/taxonomy-controls.js b/packages/block-library/src/query/edit/inspector-controls/taxonomy-controls.js
index a7de415371cad1..4e3c65e640dfd7 100644
--- a/packages/block-library/src/query/edit/inspector-controls/taxonomy-controls.js
+++ b/packages/block-library/src/query/edit/inspector-controls/taxonomy-controls.js
@@ -116,6 +116,7 @@ export function TaxonomyControls( { onChange, query } ) {
value={ getExistingTaxQueryValue( slug ) }
suggestions={ terms.names }
onChange={ onTermsChange( slug ) }
+ __experimentalShowHowTo={ false }
/>
);
diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js
index d6848724b82874..276d7b21638173 100644
--- a/packages/block-library/src/query/utils.js
+++ b/packages/block-library/src/query/utils.js
@@ -162,7 +162,7 @@ export function useAllowedControls( attributes ) {
select( blocksStore ).getActiveBlockVariation(
queryLoopName,
attributes
- )?.allowControls,
+ )?.allowedControls,
[ attributes ]
);
diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json
index 3ceaf0fcf3e038..adb9fddca78731 100644
--- a/packages/block-library/src/quote/block.json
+++ b/packages/block-library/src/quote/block.json
@@ -29,7 +29,6 @@
},
"supports": {
"anchor": true,
- "__experimentalSlashInserter": true,
"__experimentalOnEnter": true,
"typography": {
"fontSize": true,
diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json
index 717db27747d7f6..aeac5ee57462f3 100644
--- a/packages/block-library/src/site-title/block.json
+++ b/packages/block-library/src/site-title/block.json
@@ -60,5 +60,6 @@
}
}
},
- "editorStyle": "wp-block-site-title-editor"
+ "editorStyle": "wp-block-site-title-editor",
+ "style": "wp-block-site-title"
}
diff --git a/packages/block-library/src/site-title/editor.scss b/packages/block-library/src/site-title/editor.scss
index 372a85db2f4b13..173e4570929a51 100644
--- a/packages/block-library/src/site-title/editor.scss
+++ b/packages/block-library/src/site-title/editor.scss
@@ -2,3 +2,9 @@
padding: 1em 0;
border: 1px dashed;
}
+
+.editor-styles-wrapper .wp-block-site-title {
+ a {
+ color: inherit;
+ }
+}
diff --git a/packages/block-library/src/site-title/style.scss b/packages/block-library/src/site-title/style.scss
new file mode 100644
index 00000000000000..afc6f449f4025b
--- /dev/null
+++ b/packages/block-library/src/site-title/style.scss
@@ -0,0 +1,5 @@
+.wp-block-site-title {
+ a {
+ color: inherit;
+ }
+}
diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss
index f553df10ea17c8..a7f12e74ea2f58 100644
--- a/packages/block-library/src/style.scss
+++ b/packages/block-library/src/style.scss
@@ -44,6 +44,7 @@
@import "./search/style.scss";
@import "./separator/style.scss";
@import "./site-logo/style.scss";
+@import "./site-title/style.scss";
@import "./social-links/style.scss";
@import "./spacer/style.scss";
@import "./tag-cloud/style.scss";
diff --git a/packages/block-library/src/tag-cloud/index.php b/packages/block-library/src/tag-cloud/index.php
index a7d121f7ca632b..7ff5f78400db64 100644
--- a/packages/block-library/src/tag-cloud/index.php
+++ b/packages/block-library/src/tag-cloud/index.php
@@ -28,14 +28,7 @@ function render_block_core_tag_cloud( $attributes ) {
$tag_cloud = wp_tag_cloud( $args );
if ( ! $tag_cloud ) {
- $labels = get_taxonomy_labels( get_taxonomy( $attributes['taxonomy'] ) );
- $tag_cloud = esc_html(
- sprintf(
- /* translators: %s: taxonomy name */
- __( 'Your site doesn’t have any %s, so there’s nothing to display here at the moment.' ),
- strtolower( $labels->name )
- )
- );
+ $tag_cloud = __( 'There’s no content to show here yet.' );
}
$wrapper_attributes = get_block_wrapper_attributes();
diff --git a/packages/block-library/src/template-part/index.js b/packages/block-library/src/template-part/index.js
index 562e4f713ee1a9..c64f093427f95f 100644
--- a/packages/block-library/src/template-part/index.js
+++ b/packages/block-library/src/template-part/index.js
@@ -62,13 +62,13 @@ export const init = () => {
'blockEditor.__unstableCanInsertBlockType',
'removeTemplatePartsFromPostTemplates',
(
- can,
+ canInsert,
blockType,
rootClientId,
{ getBlock, getBlockParentsByBlockName }
) => {
if ( blockType.name !== 'core/template-part' ) {
- return can;
+ return canInsert;
}
for ( const disallowedParentType of DISALLOWED_PARENTS ) {
diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js
index 49aaaa83435fbb..540002d97565f6 100644
--- a/packages/block-library/src/video/edit.js
+++ b/packages/block-library/src/video/edit.js
@@ -13,6 +13,7 @@ import {
Disabled,
PanelBody,
Spinner,
+ Placeholder,
} from '@wordpress/components';
import {
BlockControls,
@@ -43,6 +44,23 @@ import VideoCommonSettings from './edit-common-settings';
import TracksEditor from './tracks-editor';
import Tracks from './tracks';
+// Much of this description is duplicated from MediaPlaceholder.
+const placeholder = ( content ) => {
+ return (
+
+ { content }
+
+ );
+};
+
const ALLOWED_MEDIA_TYPES = [ 'video' ];
const VIDEO_POSTER_ALLOWED_MEDIA_TYPES = [ 'image' ];
@@ -146,6 +164,7 @@ function VideoEdit( {
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ attributes }
onError={ onUploadError }
+ placeholder={ placeholder }
/>
);
diff --git a/packages/block-library/src/video/editor.scss b/packages/block-library/src/video/editor.scss
index b6d388b6d06f6d..60c68fb74d1be9 100644
--- a/packages/block-library/src/video/editor.scss
+++ b/packages/block-library/src/video/editor.scss
@@ -1,3 +1,40 @@
+// Provide special styling for the placeholder.
+// @todo: this particular minimal style of placeholder could be componentized further.
+.wp-block-video.wp-block-video {
+ // Show Placeholder style on-select.
+ &.is-selected .components-placeholder {
+ // Block UI appearance.
+ color: $gray-900;
+ background-color: $white;
+ box-shadow: inset 0 0 0 $border-width $gray-900;
+ border: none;
+
+ // @todo: this should eventually be overridden by a custom border-radius set in the inspector.
+ border-radius: $radius-block-ui;
+
+ > svg {
+ opacity: 0;
+ }
+
+ .components-placeholder__illustration {
+ display: none;
+ }
+
+ &::before {
+ opacity: 0;
+ }
+ }
+
+ // Remove the transition while we still have a legacy placeholder style.
+ // Otherwise the content jumps between the 1px placeholder border, and any inherited custom
+ // parent border that may get applied when you deselect.
+ .components-placeholder__label,
+ .components-placeholder__instructions,
+ .components-button {
+ transition: none;
+ }
+}
+
.wp-block[data-align="center"] > .wp-block-video {
text-align: center;
}
diff --git a/packages/block-serialization-default-parser/parser.php b/packages/block-serialization-default-parser/parser.php
index 95add35cbfb6f1..50337b588a37b9 100644
--- a/packages/block-serialization-default-parser/parser.php
+++ b/packages/block-serialization-default-parser/parser.php
@@ -80,7 +80,7 @@ class WP_Block_Parser_Block {
* @param string $innerHTML Resultant HTML from inside block comment delimiters after removing inner blocks.
* @param array $innerContent List of string fragments and null markers where inner blocks were found.
*/
- function __construct( $name, $attrs, $innerBlocks, $innerHTML, $innerContent ) {
+ public function __construct( $name, $attrs, $innerBlocks, $innerHTML, $innerContent ) {
$this->blockName = $name;
$this->attrs = $attrs;
$this->innerBlocks = $innerBlocks;
@@ -152,7 +152,7 @@ class WP_Block_Parser_Frame {
* @param int $prev_offset Byte offset into document for after parse token ends.
* @param int $leading_html_start Byte offset into document where leading HTML before token starts.
*/
- function __construct( $block, $token_start, $token_length, $prev_offset = null, $leading_html_start = null ) {
+ public function __construct( $block, $token_start, $token_length, $prev_offset = null, $leading_html_start = null ) {
$this->block = $block;
$this->token_start = $token_start;
$this->token_length = $token_length;
@@ -224,16 +224,16 @@ class WP_Block_Parser {
* @param string $document Input document being parsed.
* @return array[]
*/
- function parse( $document ) {
+ public function parse( $document ) {
$this->document = $document;
$this->offset = 0;
$this->output = array();
$this->stack = array();
$this->empty_attrs = json_decode( '{}', true );
- do {
- // twiddle our thumbs.
- } while ( $this->proceed() );
+ while ( $this->proceed() ) {
+ continue;
+ }
return $this->output;
}
@@ -252,7 +252,7 @@ function parse( $document ) {
* @since 5.0.0
* @return bool
*/
- function proceed() {
+ public function proceed() {
$next_token = $this->next_token();
list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token;
$stack_depth = count( $this->stack );
@@ -398,7 +398,7 @@ function proceed() {
* @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments
* @return array
*/
- function next_token() {
+ public function next_token() {
$matches = null;
/*
@@ -473,7 +473,7 @@ function next_token() {
* @param string $innerHTML HTML content of block.
* @return WP_Block_Parser_Block freeform block object.
*/
- function freeform( $innerHTML ) {
+ public function freeform( $innerHTML ) {
return new WP_Block_Parser_Block( null, $this->empty_attrs, array(), $innerHTML, array( $innerHTML ) );
}
@@ -485,7 +485,7 @@ function freeform( $innerHTML ) {
* @since 5.0.0
* @param null $length how many bytes of document text to output.
*/
- function add_freeform( $length = null ) {
+ public function add_freeform( $length = null ) {
$length = $length ? $length : strlen( $this->document ) - $this->offset;
if ( 0 === $length ) {
@@ -506,7 +506,7 @@ function add_freeform( $length = null ) {
* @param int $token_length Byte length of entire block from start of opening token to end of closing token.
* @param int|null $last_offset Last byte offset into document if continuing form earlier output.
*/
- function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
+ public function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
$parent = $this->stack[ count( $this->stack ) - 1 ];
$parent->block->innerBlocks[] = (array) $block;
$html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
@@ -527,7 +527,7 @@ function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_len
* @since 5.0.0
* @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML.
*/
- function add_block_from_stack( $end_offset = null ) {
+ public function add_block_from_stack( $end_offset = null ) {
$stack_top = array_pop( $this->stack );
$prev_offset = $stack_top->prev_offset;
diff --git a/packages/block-serialization-default-parser/src/index.js b/packages/block-serialization-default-parser/src/index.js
index fad34edc2e0d5e..9fd67cde2b1d96 100644
--- a/packages/block-serialization-default-parser/src/index.js
+++ b/packages/block-serialization-default-parser/src/index.js
@@ -38,7 +38,7 @@ let stack;
*/
/**
- * @typedef {'void-block'|'block-opener'|'block-closer'} TokenType
+ * @typedef {'no-more-tokens'|'void-block'|'block-opener'|'block-closer'} TokenType
*/
/**
@@ -238,39 +238,38 @@ export const parse = ( doc ) => {
function proceed() {
const stackDepth = stack.length;
const next = nextToken();
- if ( next === null ) {
- // If not in a block then flush output.
- if ( 0 === stackDepth ) {
- addFreeform();
- return false;
- }
-
- // Otherwise we have a problem
- // This is an error
- // we have options
- // - treat it all as freeform text
- // - assume an implicit closer (easiest when not nesting)
-
- // For the easy case we'll assume an implicit closer.
- if ( 1 === stackDepth ) {
- addBlockFromStack();
- return false;
- }
-
- // For the nested case where it's more difficult we'll
- // have to assume that multiple closers are missing
- // and so we'll collapse the whole stack piecewise.
- while ( 0 < stack.length ) {
- addBlockFromStack();
- }
- return false;
- }
const [ tokenType, blockName, attrs, startOffset, tokenLength ] = next;
// We may have some HTML soup before the next block.
const leadingHtmlStart = startOffset > offset ? offset : null;
switch ( tokenType ) {
+ case 'no-more-tokens':
+ // If not in a block then flush output.
+ if ( 0 === stackDepth ) {
+ addFreeform();
+ return false;
+ }
+
+ // Otherwise we have a problem
+ // This is an error
+ // we have options
+ // - treat it all as freeform text
+ // - assume an implicit closer (easiest when not nesting)
+
+ // For the easy case we'll assume an implicit closer.
+ if ( 1 === stackDepth ) {
+ addBlockFromStack();
+ return false;
+ }
+
+ // For the nested case where it's more difficult we'll
+ // have to assume that multiple closers are missing
+ // and so we'll collapse the whole stack piecewise.
+ while ( 0 < stack.length ) {
+ addBlockFromStack();
+ }
+ return false;
case 'void-block':
// easy case is if we stumbled upon a void block
// in the top-level of the document.
@@ -380,7 +379,7 @@ function parseJSON( input ) {
/**
* Finds the next token in the document.
*
- * @return {Token|null} The next matched token.
+ * @return {Token} The next matched token.
*/
function nextToken() {
// Aye the magic
@@ -393,7 +392,7 @@ function nextToken() {
// We have no more tokens.
if ( null === matches ) {
- return null;
+ return [ 'no-more-tokens', '', null, 0, 0 ];
}
const startedAt = matches.index;
diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md
index b8d3fed3e8b731..4036cf8ac78f8e 100644
--- a/packages/blocks/CHANGELOG.md
+++ b/packages/blocks/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Deprecations
+
+- Deprecate non-string descriptions ([#44455](https://github.com/WordPress/gutenberg/pull/44455)).
+
## 11.17.0 (2022-09-21)
- The block attribute sources `children` and `node` have been deprecated. Please use the `html` source instead. See https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/ and the core blocks for examples.
diff --git a/packages/blocks/package.json b/packages/blocks/package.json
index bd03c1b7dfd574..dc443561c017ea 100644
--- a/packages/blocks/package.json
+++ b/packages/blocks/package.json
@@ -32,6 +32,7 @@
"@wordpress/autop": "file:../autop",
"@wordpress/blob": "file:../blob",
"@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser",
+ "@wordpress/compose": "file:../compose",
"@wordpress/data": "file:../data",
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/dom": "file:../dom",
diff --git a/packages/blocks/src/api/parser/get-block-attributes.js b/packages/blocks/src/api/parser/get-block-attributes.js
index 804e7f18ddd4ca..76713a66711298 100644
--- a/packages/blocks/src/api/parser/get-block-attributes.js
+++ b/packages/blocks/src/api/parser/get-block-attributes.js
@@ -2,12 +2,13 @@
* External dependencies
*/
import { parse as hpqParse } from 'hpq';
-import { flow, mapValues, castArray } from 'lodash';
+import { mapValues, castArray } from 'lodash';
import memoize from 'memize';
/**
* WordPress dependencies
*/
+import { pipe } from '@wordpress/compose';
import { applyFilters } from '@wordpress/hooks';
/**
@@ -28,7 +29,7 @@ import { normalizeBlockType } from '../utils';
* @return {Function} Enhanced hpq matcher.
*/
export const toBooleanAttributeMatcher = ( matcher ) =>
- flow( [
+ pipe( [
matcher,
// Expected values from `attr( 'disabled' )`:
//
@@ -213,7 +214,7 @@ export const matcherFromSource = memoize( ( sourceConfig ) => {
);
return query( sourceConfig.selector, subMatchers );
case 'tag':
- return flow( [
+ return pipe( [
prop( sourceConfig.selector, 'nodeName' ),
( nodeName ) =>
nodeName ? nodeName.toLowerCase() : undefined,
diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js
index 490b547e7ef593..58bf57726a3b9b 100644
--- a/packages/blocks/src/api/test/registration.js
+++ b/packages/blocks/src/api/test/registration.js
@@ -4,6 +4,7 @@
* WordPress dependencies
*/
import { addFilter, removeAllFilters, removeFilter } from '@wordpress/hooks';
+import { logged } from '@wordpress/deprecated';
import { select } from '@wordpress/data';
/**
@@ -61,6 +62,11 @@ describe( 'blocks', () => {
setUnregisteredTypeHandlerName( undefined );
setDefaultBlockName( undefined );
unstable__bootstrapServerSideBlockDefinitions( {} );
+
+ // Reset deprecation logging to ensure we properly track warnings.
+ for ( const key in logged ) {
+ delete logged[ key ];
+ }
} );
describe( 'registerBlockType()', () => {
@@ -832,6 +838,41 @@ describe( 'blocks', () => {
// Only attributes of block1 are supposed to be edited by the filter thus it must differ from block2.
expect( block1.attributes ).not.toEqual( block2.attributes );
} );
+
+ it( 'should allow non-string descriptions at registration but warn for undesired usage.', () => {
+ const newDescription = foo bar
;
+
+ const block = registerBlockType( 'my-plugin/test-block-1', {
+ ...defaultBlockSettings,
+ description: newDescription,
+ } );
+
+ expect( block.description ).toBe( newDescription );
+ expect( console ).toHaveWarnedWith(
+ 'Declaring non-string block descriptions is deprecated since version 6.2.'
+ );
+ } );
+
+ it( 'should allow non-string descriptions through `blocks.registerBlockType` filter but warn for undesired usage.', () => {
+ const newDescription = foo bar
;
+ addFilter(
+ 'blocks.registerBlockType',
+ 'core/blocks/non-string-description',
+ ( settings ) => {
+ settings.description = newDescription;
+ return settings;
+ }
+ );
+ const block = registerBlockType(
+ 'my-plugin/test-block-2',
+ defaultBlockSettings
+ );
+
+ expect( block.description ).toBe( newDescription );
+ expect( console ).toHaveWarnedWith(
+ 'Declaring non-string block descriptions is deprecated since version 6.2.'
+ );
+ } );
} );
test( 'registers block from metadata', () => {
diff --git a/packages/blocks/src/store/actions.js b/packages/blocks/src/store/actions.js
index 7d178969615cfd..1e160175dc75ee 100644
--- a/packages/blocks/src/store/actions.js
+++ b/packages/blocks/src/store/actions.js
@@ -7,6 +7,7 @@ import { castArray, pick, some } from 'lodash';
/**
* WordPress dependencies
*/
+import deprecated from '@wordpress/deprecated';
import { applyFilters } from '@wordpress/hooks';
/**
@@ -63,6 +64,12 @@ const processBlockType = ( blockType, { select } ) => {
null
);
+ if ( settings.description && typeof settings.description !== 'string' ) {
+ deprecated( 'Declaring non-string block descriptions', {
+ since: '6.2',
+ } );
+ }
+
if ( settings.deprecated ) {
settings.deprecated = settings.deprecated.map( ( deprecation ) =>
pick(
diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js
index 4c3d8252129d36..120249654445d4 100644
--- a/packages/blocks/src/store/selectors.js
+++ b/packages/blocks/src/store/selectors.js
@@ -3,7 +3,12 @@
*/
import createSelector from 'rememo';
import removeAccents from 'remove-accents';
-import { filter, flow, get, includes, map, some } from 'lodash';
+import { filter, get, includes, map, some } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { pipe } from '@wordpress/compose';
/** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
/** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
@@ -686,7 +691,7 @@ export function hasBlockSupport( state, nameOrType, feature, defaultSupports ) {
export function isMatchingSearchTerm( state, nameOrType, searchTerm ) {
const blockType = getNormalizedBlockType( state, nameOrType );
- const getNormalizedSearchTerm = flow( [
+ const getNormalizedSearchTerm = pipe( [
// Disregard diacritics.
// Input: "média"
( term ) => removeAccents( term ?? '' ),
@@ -702,7 +707,7 @@ export function isMatchingSearchTerm( state, nameOrType, searchTerm ) {
const normalizedSearchTerm = getNormalizedSearchTerm( searchTerm );
- const isSearchMatch = flow( [
+ const isSearchMatch = pipe( [
getNormalizedSearchTerm,
( normalizedCandidate ) =>
includes( normalizedCandidate, normalizedSearchTerm ),
diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 9e287d22f123b0..e665abdddca0ee 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,6 +2,28 @@
## Unreleased
+### Enhancements
+
+- `FontSizePicker`: Updated to take up full width of its parent and have a 40px Reset button when `size` is `__unstable-large` ((44559)[https://github.com/WordPress/gutenberg/pull/44559]).
+
+### Bug Fix
+
+- `Popover`: fix limitShift logic by adding iframe offset correctly [#42950](https://github.com/WordPress/gutenberg/pull/42950)).
+- `Popover`: refine position-to-placement conversion logic, add tests ([#44377](https://github.com/WordPress/gutenberg/pull/44377)).
+- `ToggleGroupControl`: adjust icon color when inactive, from `gray-700` to `gray-900` ([#44575](https://github.com/WordPress/gutenberg/pull/44575)).
+- `TokenInput`: improve logic around the `aria-activedescendant` attribute, which was causing unintended focus behavior for some screen readers ([#44526](https://github.com/WordPress/gutenberg/pull/44526)).
+- `NavigatorScreen`: fix focus issue where back button received focus unexpectedly ([#44239](https://github.com/WordPress/gutenberg/pull/44239))
+
+### Internal
+
+- `Mobile` updated to ignore `react/exhaustive-deps` eslint rule ([#44207](https://github.com/WordPress/gutenberg/pull/44207)).
+- `Popover`: refactor unit tests to TypeScript and modern RTL assertions ([#44373](https://github.com/WordPress/gutenberg/pull/44373)).
+- `SearchControl`: updated to ignore `react/exhaustive-deps` eslint rule in native files([#44381](https://github.com/WordPress/gutenberg/pull/44381))
+- `ResizableBox` updated to pass the `react/exhaustive-deps` eslint rule ([#44370](https://github.com/WordPress/gutenberg/pull/44370)).
+- `Sandbox`: updated to satisfy `react/exhaustive-deps` eslint rule ([#44378](https://github.com/WordPress/gutenberg/pull/44378))
+- `FontSizePicker`: Convert to TypeScript ([#44449](https://github.com/WordPress/gutenberg/pull/44449)).
+- `FontSizePicker`: Replace SCSS with Emotion + components ([#44483](https://github.com/WordPress/gutenberg/pull/44483)).
+
## 21.1.0 (2022-09-21)
### Deprecations
@@ -13,11 +35,18 @@
- `Button`: Remove unexpected `has-text` class when empty children are passed ([#44198](https://github.com/WordPress/gutenberg/pull/44198)).
- The `LinkedButton` to unlink sides in `BoxControl`, `BorderBoxControl` and `BorderRadiusControl` have changed from a rectangular primary button to an icon-only button, with a sentence case tooltip, and default-size icon for better legibility. The `Button` component has been fixed so when `isSmall` and `icon` props are set, and no text is present, the button shape is square rather than rectangular.
+### New Features
+
+- `MenuItem`: Add suffix prop for injecting non-icon and non-shortcut content to menu items ([#44260](https://github.com/WordPress/gutenberg/pull/44260)).
+- `ToolsPanel`: Add subheadings to ellipsis menu and reset text to default control menu items ([#44260](https://github.com/WordPress/gutenberg/pull/44260)).
+
### Internal
- `NavigationMenu` updated to ignore `react/exhaustive-deps` eslint rule ([#44090](https://github.com/WordPress/gutenberg/pull/44090)).
- `RangeControl`: updated to pass `react/exhaustive-deps` eslint rule ([#44271](https://github.com/WordPress/gutenberg/pull/44271)).
- `UnitControl` updated to pass the `react/exhaustive-deps` eslint rule ([#44161](https://github.com/WordPress/gutenberg/pull/44161)).
+- `Notice`: updated to satisfy `react/exhaustive-deps` eslint rule ([#44157](https://github.com/WordPress/gutenberg/pull/44157))
+
## 21.0.0 (2022-09-13)
diff --git a/packages/components/package.json b/packages/components/package.json
index c03b2447814e06..4f1f622f208821 100644
--- a/packages/components/package.json
+++ b/packages/components/package.json
@@ -69,7 +69,8 @@
"reakit": "^1.3.8",
"remove-accents": "^0.4.2",
"use-lilius": "^2.0.1",
- "uuid": "^8.3.0"
+ "uuid": "^8.3.0",
+ "valtio": "^1.7.0"
},
"peerDependencies": {
"react": "^17.0.0",
diff --git a/packages/components/src/alignment-matrix-control/test/index.js b/packages/components/src/alignment-matrix-control/test/index.js
index eaa28941048c14..638d8acb96ad58 100644
--- a/packages/components/src/alignment-matrix-control/test/index.js
+++ b/packages/components/src/alignment-matrix-control/test/index.js
@@ -1,91 +1,46 @@
/**
* External dependencies
*/
-import { render, unmountComponentAtNode } from 'react-dom';
-import { act } from 'react-dom/test-utils';
+import { render, screen, within } from '@testing-library/react';
/**
* Internal dependencies
*/
import AlignmentMatrixControl from '../';
-const __windowFocus = window.focus;
-
-beforeAll( () => {
- window.focus = jest.fn();
-} );
-
-afterAll( () => {
- window.focus = __windowFocus;
-} );
-
-let container = null;
-
-beforeEach( () => {
- container = document.createElement( 'div' );
- document.body.appendChild( container );
-} );
-
-afterEach( () => {
- unmountComponentAtNode( container );
- container.remove();
- container = null;
-} );
-
const getControl = () => {
- return container.querySelector( '.component-alignment-matrix-control' );
+ return screen.getByRole( 'grid' );
};
-const getCells = () => {
- const control = getControl();
- return control.querySelectorAll( '[role="gridcell"]' );
+const getCell = ( name ) => {
+ return within( getControl() ).getByRole( 'gridcell', { name } );
};
describe( 'AlignmentMatrixControl', () => {
describe( 'Basic rendering', () => {
it( 'should render', () => {
- act( () => {
- render( , container );
- } );
- const control = getControl();
+ render( );
- expect( control ).toBeTruthy();
+ expect( getControl() ).toBeInTheDocument();
} );
} );
describe( 'Change value', () => {
- it( 'should change value on cell click', () => {
- const spy = jest.fn();
+ const alignments = [ 'center left', 'center center', 'bottom center' ];
+
+ it.each( alignments )(
+ 'should change value on %s cell click',
+ ( alignment ) => {
+ const spy = jest.fn();
- act( () => {
render(
- ,
- container
+
);
- } );
-
- const cells = getCells();
-
- act( () => {
- cells[ 3 ].focus();
- } );
- expect( spy.mock.calls[ 0 ][ 0 ] ).toBe( 'center left' );
+ getCell( alignment ).focus();
- act( () => {
- cells[ 4 ].focus();
- } );
-
- expect( spy.mock.calls[ 1 ][ 0 ] ).toBe( 'center center' );
-
- act( () => {
- cells[ 7 ].focus();
- } );
-
- expect( spy.mock.calls[ 2 ][ 0 ] ).toBe( 'bottom center' );
- } );
+ expect( spy ).toHaveBeenCalledWith( alignment );
+ }
+ );
} );
} );
diff --git a/packages/components/src/border-box-control/test/utils.js b/packages/components/src/border-box-control/test/utils.js
index f5c65ed6532831..42c23e98101745 100644
--- a/packages/components/src/border-box-control/test/utils.js
+++ b/packages/components/src/border-box-control/test/utils.js
@@ -244,6 +244,54 @@ describe( 'BorderBoxControl Utils', () => {
expect( getCommonBorder( sideBorders ) ).toEqual( commonBorder );
} );
+
+ it( 'should return most common unit selection if border widths are mixed', () => {
+ const sideBorders = {
+ top: { color: '#fff', style: 'solid', width: '10px' },
+ right: { color: '#000', style: 'solid', width: '1rem' },
+ bottom: { color: '#000', style: 'solid', width: '2em' },
+ left: { color: '#000', style: undefined, width: '2em' },
+ };
+ const commonBorder = {
+ color: undefined,
+ style: undefined,
+ width: 'em',
+ };
+
+ expect( getCommonBorder( sideBorders ) ).toEqual( commonBorder );
+ } );
+
+ it( 'should return first unit when multiple units are equal most common', () => {
+ const sideBorders = {
+ top: { color: '#fff', style: 'solid', width: '1rem' },
+ right: { color: '#000', style: 'solid', width: '0.75em' },
+ bottom: { color: '#000', style: 'solid', width: '1vw' },
+ left: { color: '#000', style: undefined, width: '2vh' },
+ };
+ const commonBorder = {
+ color: undefined,
+ style: undefined,
+ width: 'rem',
+ };
+
+ expect( getCommonBorder( sideBorders ) ).toEqual( commonBorder );
+ } );
+
+ it( 'should ignore undefined values in determining most common unit', () => {
+ const sideBorders = {
+ top: { color: '#fff', style: 'solid', width: undefined },
+ right: { color: '#000', style: 'solid', width: '5vw' },
+ bottom: { color: '#000', style: 'solid', width: undefined },
+ left: { color: '#000', style: undefined, width: '2vh' },
+ };
+ const commonBorder = {
+ color: undefined,
+ style: undefined,
+ width: 'vw',
+ };
+
+ expect( getCommonBorder( sideBorders ) ).toEqual( commonBorder );
+ } );
} );
describe( 'getShorthandBorderStyle', () => {
diff --git a/packages/components/src/border-box-control/utils.ts b/packages/components/src/border-box-control/utils.ts
index 6e8c6e35f12b7e..1e2529166974a6 100644
--- a/packages/components/src/border-box-control/utils.ts
+++ b/packages/components/src/border-box-control/utils.ts
@@ -6,6 +6,7 @@ import type { CSSProperties } from 'react';
/**
* Internal dependencies
*/
+import { parseCSSUnitValue } from '../utils/unit-values';
import type { Border } from '../border-control/types';
import type { AnyBorder, Borders, BorderProp, BorderSide } from './types';
@@ -123,7 +124,7 @@ export const getCommonBorder = ( borders?: Borders ) => {
return {
color: allColorsMatch ? colors[ 0 ] : undefined,
style: allStylesMatch ? styles[ 0 ] : undefined,
- width: allWidthsMatch ? widths[ 0 ] : undefined,
+ width: allWidthsMatch ? widths[ 0 ] : getMostCommonUnit( widths ),
};
};
@@ -152,3 +153,45 @@ export const getShorthandBorderStyle = (
return [ width, borderStyle, color ].filter( Boolean ).join( ' ' );
};
+
+export const getMostCommonUnit = (
+ values: Array< string | number | undefined >
+): string | undefined => {
+ // Collect all the CSS units.
+ const units = values.map( ( value ) =>
+ value === undefined ? undefined : parseCSSUnitValue( `${ value }` )[ 1 ]
+ );
+
+ // Return the most common unit out of only the defined CSS units.
+ const filteredUnits = units.filter( ( value ) => value !== undefined );
+ return mode( filteredUnits as string[] );
+};
+
+/**
+ * Finds the mode value out of the array passed favouring the first value
+ * as a tiebreaker.
+ *
+ * @param values Values to determine the mode from.
+ *
+ * @return The mode value.
+ */
+function mode( values: Array< string > ): string | undefined {
+ if ( values.length === 0 ) {
+ return undefined;
+ }
+
+ const map: { [ index: string ]: number } = {};
+ let maxCount = 0;
+ let currentMode;
+
+ values.forEach( ( value ) => {
+ map[ value ] = map[ value ] === undefined ? 1 : map[ value ] + 1;
+
+ if ( map[ value ] > maxCount ) {
+ currentMode = value;
+ maxCount = map[ value ];
+ }
+ } );
+
+ return currentMode;
+}
diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js
index a12b58f8eaa516..eae04e09d8cf71 100644
--- a/packages/components/src/combobox-control/index.js
+++ b/packages/components/src/combobox-control/index.js
@@ -247,11 +247,6 @@ function ComboboxControl( {
instanceId={ instanceId }
ref={ inputContainer }
value={ isExpanded ? inputValue : currentLabel }
- aria-label={
- currentLabel
- ? `${ currentLabel }, ${ label }`
- : null
- }
onFocus={ onFocus }
onBlur={ onBlur }
isExpanded={ isExpanded }
diff --git a/packages/components/src/custom-select-control/index.js b/packages/components/src/custom-select-control/index.js
index f5916849d77fe9..73aebda5d257b2 100644
--- a/packages/components/src/custom-select-control/index.js
+++ b/packages/components/src/custom-select-control/index.js
@@ -1,3 +1,4 @@
+// @ts-nocheck
/**
* External dependencies
*/
@@ -15,7 +16,7 @@ import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
-import { VisuallyHidden } from '../';
+import { VisuallyHidden } from '../visually-hidden';
import { Select as SelectControlSelect } from '../select-control/styles/select-control-styles';
import SelectControlChevronDown from '../select-control/chevron-down';
import { InputBaseWithBackCompatMinWidth } from './styles';
diff --git a/packages/components/src/draggable/index.js b/packages/components/src/draggable/index.js
index 147c96e277580c..8b9b7b3b714713 100644
--- a/packages/components/src/draggable/index.js
+++ b/packages/components/src/draggable/index.js
@@ -1,13 +1,9 @@
/**
* WordPress dependencies
*/
+import { throttle } from '@wordpress/compose';
import { useEffect, useRef } from '@wordpress/element';
-/**
- * External dependencies
- */
-import { throttle } from 'lodash';
-
const dragImageClass = 'components-draggable__invisible-drag-image';
const cloneWrapperClass = 'components-draggable__clone';
const clonePadding = 0;
@@ -180,6 +176,7 @@ export default function Draggable( {
// Aim for 60fps (16 ms per frame) for now. We can potentially use requestAnimationFrame (raf) instead,
// note that browsers may throttle raf below 60fps in certain conditions.
+ // @ts-ignore
const throttledDragOver = throttle( over, 16 );
ownerDocument.addEventListener( 'dragover', throttledDragOver );
diff --git a/packages/components/src/font-size-picker/index.js b/packages/components/src/font-size-picker/index.tsx
similarity index 67%
rename from packages/components/src/font-size-picker/index.js
rename to packages/components/src/font-size-picker/index.tsx
index 1fb266bba02b2b..bc5154801880d2 100644
--- a/packages/components/src/font-size-picker/index.js
+++ b/packages/components/src/font-size-picker/index.tsx
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import classNames from 'classnames';
+import type { ReactNode, ForwardedRef } from 'react';
/**
* WordPress dependencies
@@ -14,7 +14,6 @@ import { useState, useMemo, forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
-import { BaseControl } from '../base-control';
import Button from '../button';
import RangeControl from '../range-control';
import { Flex, FlexItem } from '../flex';
@@ -34,31 +33,50 @@ import {
} from './utils';
import { VStack } from '../v-stack';
import { HStack } from '../h-stack';
+import type {
+ FontSizePickerProps,
+ FontSizeSelectOption,
+ FontSizeToggleGroupOption,
+} from './types';
+import {
+ Container,
+ HeaderHint,
+ HeaderLabel,
+ Controls,
+ ResetButton,
+} from './styles';
+import { Spacer } from '../spacer';
// This conditional is needed to maintain the spacing before the slider in the `withSlider` case.
-const MaybeVStack = ( { __nextHasNoMarginBottom, children } ) =>
+const MaybeVStack = ( {
+ __nextHasNoMarginBottom,
+ children,
+}: {
+ __nextHasNoMarginBottom: boolean;
+ children: ReactNode;
+} ) =>
! __nextHasNoMarginBottom ? (
- children
+ <>{ children }>
) : (
);
-function FontSizePicker(
- {
+const UnforwardedFontSizePicker = (
+ props: FontSizePickerProps,
+ ref: ForwardedRef< any >
+) => {
+ const {
/** Start opting into the new margin-free styles that will become the default in a future version. */
__nextHasNoMarginBottom = false,
fallbackFontSize,
fontSizes = [],
disableCustomFontSizes = false,
onChange,
- /** @type {'default' | '__unstable-large'} */
size = 'default',
value,
withSlider = false,
withReset = true,
- },
- ref
-) {
+ } = props;
if ( ! __nextHasNoMarginBottom ) {
deprecated( 'Bottom margin styles for wp.components.FontSizePicker', {
since: '6.1',
@@ -70,7 +88,7 @@ function FontSizePicker(
const hasUnits = [ typeof value, typeof fontSizes?.[ 0 ]?.size ].includes(
'string'
);
- const noUnitsValue = ! hasUnits ? value : parseInt( value );
+ const noUnitsValue = ! hasUnits ? value : parseInt( String( value ) );
const isPixelValue = typeof value === 'number' || value?.endsWith?.( 'px' );
const units = useCustomUnits( {
availableUnits: [ 'px', 'em', 'rem' ],
@@ -106,10 +124,15 @@ function FontSizePicker(
// If we have a custom value that is not available in the font sizes,
// show it as a hint as long as it's a simple CSS value.
if ( isCustomValue ) {
- return isSimpleCssValue( value ) && `(${ value })`;
+ return (
+ value !== undefined &&
+ isSimpleCssValue( value ) &&
+ `(${ value })`
+ );
}
if ( shouldUseSelectControl ) {
return (
+ selectedOption?.size !== undefined &&
isSimpleCssValue( selectedOption?.size ) &&
`(${ selectedOption?.size })`
);
@@ -146,59 +169,65 @@ function FontSizePicker(
__( 'Currently selected font size: %s' ),
selectedOption.name
);
- const baseClassName = 'components-font-size-picker';
return (
-
+
{ __( 'Font size' ) }
-
-
- { __( 'Size' ) }
- { headerHint && (
-
- { headerHint }
-
+
+
+
+ { __( 'Size' ) }
+ { headerHint && (
+
+ { headerHint }
+
+ ) }
+
+ { ! disableCustomFontSizes && (
+ {
+ setShowCustomValueControl(
+ ! showCustomValueControl
+ );
+ } }
+ isPressed={ showCustomValueControl }
+ isSmall
+ />
) }
-
- { ! disableCustomFontSizes && (
- {
- setShowCustomValueControl(
- ! showCustomValueControl
- );
- } }
- isPressed={ showCustomValueControl }
- isSmall
- />
- ) }
-
+
+
-
{ !! fontSizes.length &&
shouldUseSelectControl &&
! showCustomValueControl && (
option.key === selectedOption.slug
) }
- onChange={ ( { selectedItem } ) => {
- onChange(
+ onChange={ ( {
+ selectedItem,
+ }: {
+ selectedItem: FontSizeSelectOption;
+ } ) => {
+ onChange?.(
hasUnits
? selectedItem.size
: Number( selectedItem.size )
@@ -219,31 +248,30 @@ function FontSizePicker(
hideLabelFromVision
value={ value }
onChange={ ( newValue ) => {
- onChange(
+ onChange?.(
hasUnits ? newValue : Number( newValue )
);
} }
isBlock
size={ size }
>
- { options.map( ( option ) => (
-
- ) ) }
+ { ( options as FontSizeToggleGroupOption[] ).map(
+ ( option ) => (
+
+ )
+ ) }
) }
{ ! withSlider &&
! disableCustomFontSizes &&
showCustomValueControl && (
-
+
{
if (
- 0 === parseFloat( nextSize ) ||
- ! nextSize
+ ! nextSize ||
+ 0 === parseFloat( nextSize )
) {
- onChange( undefined );
+ onChange?.( undefined );
} else {
- onChange(
+ onChange?.(
hasUnits
? nextSize
: parseInt(
@@ -272,40 +300,46 @@ function FontSizePicker(
/>
{ withReset && (
-
-
+ {
- onChange( undefined );
+ onChange?.( undefined );
} }
isSmall
variant="secondary"
+ size={ size }
>
{ __( 'Reset' ) }
-
+
) }
) }
-
+
{ withSlider && (
{
- onChange( hasUnits ? newValue + 'px' : newValue );
+ onChange?.( hasUnits ? newValue + 'px' : newValue );
} }
min={ 12 }
max={ 100 }
/>
) }
-
+
);
-}
+};
+
+export const FontSizePicker = forwardRef( UnforwardedFontSizePicker );
-export default forwardRef( FontSizePicker );
+export default FontSizePicker;
diff --git a/packages/components/src/font-size-picker/stories/e2e/index.js b/packages/components/src/font-size-picker/stories/e2e/index.tsx
similarity index 60%
rename from packages/components/src/font-size-picker/stories/e2e/index.js
rename to packages/components/src/font-size-picker/stories/e2e/index.tsx
index 30c0140bcefbbd..c2a038e656b55e 100644
--- a/packages/components/src/font-size-picker/stories/e2e/index.js
+++ b/packages/components/src/font-size-picker/stories/e2e/index.tsx
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import type { ComponentStory } from '@storybook/react';
+
/**
* WordPress dependencies
*/
@@ -13,8 +18,11 @@ export default {
component: FontSizePicker,
};
-const FontSizePickerWithState = ( { initialValue, ...props } ) => {
- const [ fontSize, setFontSize ] = useState( initialValue );
+const FontSizePickerWithState: ComponentStory< typeof FontSizePicker > = ( {
+ value,
+ ...props
+} ) => {
+ const [ fontSize, setFontSize ] = useState( value );
return (
{
);
};
-export const Default = FontSizePickerWithState.bind( {} );
+export const Default: ComponentStory< typeof FontSizePicker > =
+ FontSizePickerWithState.bind( {} );
Default.args = {
fontSizes: [
{
@@ -43,5 +52,5 @@ Default.args = {
size: 26,
},
],
- initialValue: 16,
+ value: 16,
};
diff --git a/packages/components/src/font-size-picker/stories/index.js b/packages/components/src/font-size-picker/stories/index.tsx
similarity index 62%
rename from packages/components/src/font-size-picker/stories/index.js
rename to packages/components/src/font-size-picker/stories/index.tsx
index 6a2e63eb8ad71b..894a619e036868 100644
--- a/packages/components/src/font-size-picker/stories/index.js
+++ b/packages/components/src/font-size-picker/stories/index.tsx
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import type { ComponentMeta, ComponentStory } from '@storybook/react';
+
/**
* WordPress dependencies
*/
@@ -8,53 +13,48 @@ import { useState } from '@wordpress/element';
*/
import FontSizePicker from '../';
-export default {
+const meta: ComponentMeta< typeof FontSizePicker > = {
title: 'Components/FontSizePicker',
component: FontSizePicker,
argTypes: {
- initialValue: { table: { disable: true } }, // hide prop because it's not actually part of FontSizePicker
- fallbackFontSize: {
- description:
- 'If no value exists, this prop defines the starting position for the font size picker slider. Only relevant if `withSlider` is `true`.',
- },
- size: {
- control: { type: 'radio' },
- options: [ 'default', '__unstable-large' ],
- },
- withReset: {
- description:
- 'If `true`, a reset button will be displayed alongside the input field when a custom font size is active. Has no effect when `disableCustomFontSizes` or `withSlider` is `true`.',
- control: { type: 'boolean' },
- table: {
- type: 'boolean',
- defaultValue: { summary: true },
- },
- },
+ value: { control: { type: null } },
},
parameters: {
+ actions: { argTypesRegex: '^on.*' },
controls: { expanded: true },
docs: { source: { state: 'open' } },
},
};
+export default meta;
-const FontSizePickerWithState = ( { initialValue, ...props } ) => {
- const [ fontSize, setFontSize ] = useState( initialValue );
+const FontSizePickerWithState: ComponentStory< typeof FontSizePicker > = ( {
+ value,
+ onChange,
+ ...props
+} ) => {
+ const [ fontSize, setFontSize ] = useState( value );
return (
{
+ setFontSize( nextValue );
+ onChange?.( nextValue );
+ } }
/>
);
};
-const TwoFontSizePickersWithState = ( { fontSizes, ...props } ) => {
+const TwoFontSizePickersWithState: ComponentStory< typeof FontSizePicker > = ( {
+ fontSizes,
+ ...props
+} ) => {
return (
<>
Fewer font sizes
More font sizes
@@ -63,7 +63,8 @@ const TwoFontSizePickersWithState = ( { fontSizes, ...props } ) => {
);
};
-export const Default = FontSizePickerWithState.bind( {} );
+export const Default: ComponentStory< typeof FontSizePicker > =
+ FontSizePickerWithState.bind( {} );
Default.args = {
__nextHasNoMarginBottom: true,
disableCustomFontSizes: false,
@@ -84,15 +85,16 @@ Default.args = {
size: 26,
},
],
- initialValue: 16,
+ value: 16,
withSlider: false,
};
-export const WithSlider = FontSizePickerWithState.bind( {} );
+export const WithSlider: ComponentStory< typeof FontSizePicker > =
+ FontSizePickerWithState.bind( {} );
WithSlider.args = {
...Default.args,
fallbackFontSize: 16,
- initialValue: undefined,
+ value: undefined,
withSlider: true,
};
@@ -100,7 +102,8 @@ WithSlider.args = {
* With custom font sizes disabled via the `disableCustomFontSizes` prop, the user will
* only be able to pick one of the predefined sizes passed in `fontSizes`.
*/
-export const WithCustomSizesDisabled = FontSizePickerWithState.bind( {} );
+export const WithCustomSizesDisabled: ComponentStory< typeof FontSizePicker > =
+ FontSizePickerWithState.bind( {} );
WithCustomSizesDisabled.args = {
...Default.args,
disableCustomFontSizes: true,
@@ -109,7 +112,8 @@ WithCustomSizesDisabled.args = {
/**
* When there are more than 5 font size options, the UI is no longer a toggle group.
*/
-export const WithMoreFontSizes = FontSizePickerWithState.bind( {} );
+export const WithMoreFontSizes: ComponentStory< typeof FontSizePicker > =
+ FontSizePickerWithState.bind( {} );
WithMoreFontSizes.args = {
...Default.args,
fontSizes: [
@@ -144,27 +148,29 @@ WithMoreFontSizes.args = {
size: 36,
},
],
- initialValue: 8,
+ value: 8,
};
/**
* When units like `px` are specified explicitly, it will be shown as a label hint.
*/
-export const WithUnits = TwoFontSizePickersWithState.bind( {} );
+export const WithUnits: ComponentStory< typeof FontSizePicker > =
+ TwoFontSizePickersWithState.bind( {} );
WithUnits.args = {
...WithMoreFontSizes.args,
- fontSizes: WithMoreFontSizes.args.fontSizes.map( ( option ) => ( {
+ fontSizes: WithMoreFontSizes.args.fontSizes?.map( ( option ) => ( {
...option,
size: `${ option.size }px`,
} ) ),
- initialValue: '8px',
+ value: '8px',
};
/**
* The label hint will not be shown if it is a complex CSS value. Some examples of complex CSS values
* in this context are CSS functions like `calc()`, `clamp()`, and `var()`.
*/
-export const WithComplexCSSValues = TwoFontSizePickersWithState.bind( {} );
+export const WithComplexCSSValues: ComponentStory< typeof FontSizePicker > =
+ TwoFontSizePickersWithState.bind( {} );
WithComplexCSSValues.args = {
...Default.args,
fontSizes: [
@@ -200,5 +206,5 @@ WithComplexCSSValues.args = {
size: '2.8rem',
},
],
- initialValue: '1.125rem',
+ value: '1.125rem',
};
diff --git a/packages/components/src/font-size-picker/style.scss b/packages/components/src/font-size-picker/style.scss
deleted file mode 100644
index e19342aabf3190..00000000000000
--- a/packages/components/src/font-size-picker/style.scss
+++ /dev/null
@@ -1,78 +0,0 @@
-.components-font-size-picker__header {
- &__hint {
- margin-left: $grid-unit-05;
- color: $gray-700;
- }
-
- .components-base-control__label {
- margin-bottom: 0;
- }
-
- // This button is inheriting padding and min-width.
- // @todo: we should refactor it to not need to unset this.
- .components-button.is-small.has-icon:not(.has-text) {
- min-width: $icon-size;
- padding: 0;
- }
-}
-
-.components-font-size-picker__controls {
- max-width: $sidebar-width - ( 2 * $grid-unit-20 );
- align-items: center;
- margin-top: $grid-unit-10;
-
- &:not(.is-next-has-no-margin-bottom) {
- margin-bottom: $grid-unit-30;
- }
-
- .components-unit-control-wrapper {
- .components-input-control__label {
- font-weight: 300;
- padding-bottom: 0 !important;
- margin-bottom: $grid-unit-10 !important;
- }
- }
-
- // Apply the same height as the isSmall Reset button.
- .components-font-size-picker__number {
- @include input-control;
- display: inline-block;
- font-weight: 500;
- height: 30px;
- margin-bottom: 0;
- margin-left: 0;
- margin-right: $grid-unit-10;
- margin-top: $grid-unit-10;
- width: 54px;
-
- // Show the reset button as disabled until a value is entered.
- &[value=""] + .components-button {
- cursor: default;
- opacity: 0.3;
- pointer-events: none;
- }
-
- &-container {
- display: flex;
- flex-direction: column;
- }
- }
-
- .components-color-palette__clear {
- height: 30px;
- }
-}
-
-.components-font-size-picker__custom-input {
- .components-range-control__slider + .dashicon {
- width: 30px;
- height: 30px;
- }
-}
-
-.components-font-size-picker {
- border: 0;
- padding: 0;
- margin: 0;
-}
-
diff --git a/packages/components/src/font-size-picker/styles.ts b/packages/components/src/font-size-picker/styles.ts
new file mode 100644
index 00000000000000..7a52d44b7b6cc3
--- /dev/null
+++ b/packages/components/src/font-size-picker/styles.ts
@@ -0,0 +1,44 @@
+/**
+ * External dependencies
+ */
+import styled from '@emotion/styled';
+
+/**
+ * Internal dependencies
+ */
+import BaseControl from '../base-control';
+import Button from '../button';
+import { space } from '../ui/utils/space';
+import { COLORS } from '../utils';
+import type { FontSizePickerProps } from './types';
+
+export const Container = styled.fieldset`
+ border: 0;
+ margin: 0;
+ padding: 0;
+`;
+
+export const HeaderLabel = styled( BaseControl.VisualLabel )`
+ margin-bottom: 0;
+`;
+
+export const HeaderHint = styled.span`
+ color: ${ COLORS.gray[ 700 ] };
+ margin-left: ${ space( 1 ) };
+`;
+
+export const Controls = styled.div< {
+ __nextHasNoMarginBottom: boolean;
+} >`
+ ${ ( props ) =>
+ ! props.__nextHasNoMarginBottom && `margin-bottom: ${ space( 6 ) };` }
+`;
+
+export const ResetButton = styled( Button )< {
+ size: FontSizePickerProps[ 'size' ];
+} >`
+ &&& {
+ height: ${ ( props ) =>
+ props.size === '__unstable-large' ? '40px' : '30px' };
+ }
+`;
diff --git a/packages/components/src/font-size-picker/test/index.js b/packages/components/src/font-size-picker/test/index.tsx
similarity index 99%
rename from packages/components/src/font-size-picker/test/index.js
rename to packages/components/src/font-size-picker/test/index.tsx
index ca6a8e1a873308..808122852e2273 100644
--- a/packages/components/src/font-size-picker/test/index.js
+++ b/packages/components/src/font-size-picker/test/index.tsx
@@ -13,7 +13,7 @@ const getUnitSelect = () =>
const getUnitLabel = () =>
document.body.querySelector( '.components-unit-control__unit-label' );
-const toggleCustomInput = ( showCustomInput ) => {
+const toggleCustomInput = ( showCustomInput: boolean ) => {
const label = showCustomInput ? 'Set custom size' : 'Use size preset';
const toggleCustom = screen.getByLabelText( label, { selector: 'button' } );
fireEvent.click( toggleCustom );
diff --git a/packages/components/src/font-size-picker/test/utils.js b/packages/components/src/font-size-picker/test/utils.ts
similarity index 95%
rename from packages/components/src/font-size-picker/test/utils.js
rename to packages/components/src/font-size-picker/test/utils.ts
index fc074514925ccb..656c6473cd8615 100644
--- a/packages/components/src/font-size-picker/test/utils.js
+++ b/packages/components/src/font-size-picker/test/utils.ts
@@ -7,7 +7,7 @@ import {
getToggleGroupOptions,
} from '../utils';
-const simpleCSSCases = [
+const simpleCSSCases: [ number | string, boolean ][] = [
// Test integers and non-integers.
[ 1, true ],
[ 1.25, true ],
@@ -41,7 +41,11 @@ describe( 'isSimpleCssValue', () => {
);
} );
-const splitValuesCases = [
+const splitValuesCases: [
+ number | string,
+ string | undefined,
+ string | undefined
+][] = [
// Test integers and non-integers.
[ 1, '1', undefined ],
[ 1.25, '1.25', undefined ],
diff --git a/packages/components/src/font-size-picker/types.ts b/packages/components/src/font-size-picker/types.ts
new file mode 100644
index 00000000000000..2c824125bb7e1c
--- /dev/null
+++ b/packages/components/src/font-size-picker/types.ts
@@ -0,0 +1,98 @@
+/**
+ * External dependencies
+ */
+import type { ReactNode } from 'react';
+
+export type FontSizePickerProps = {
+ /**
+ * If `true`, it will not be possible to choose a custom fontSize. The user
+ * will be forced to pick one of the pre-defined sizes passed in fontSizes.
+ *
+ * @default false
+ */
+ disableCustomFontSizes?: boolean;
+ /**
+ * If no value exists, this prop defines the starting position for the font
+ * size picker slider. Only relevant if `withSlider` is `true`.
+ */
+ fallbackFontSize?: number;
+ /**
+ * An array of font size objects. The object should contain properties size,
+ * name, and slug.
+ */
+ fontSizes?: FontSize[];
+ /**
+ * A function that receives the new font size value.
+ * If onChange is called without any parameter, it should reset the value,
+ * attending to what reset means in that context, e.g., set the font size to
+ * undefined or set the font size a starting value.
+ */
+ onChange?: ( value: number | string | undefined ) => void;
+ /**
+ * The current font size value.
+ */
+ value?: number | string;
+ /**
+ * If `true`, the UI will contain a slider, instead of a numeric text input
+ * field. If `false`, no slider will be present.
+ *
+ * @default false
+ */
+ withSlider?: boolean;
+ /**
+ * If `true`, a reset button will be displayed alongside the input field
+ * when a custom font size is active. Has no effect when
+ * `disableCustomFontSizes` or `withSlider` is `true`.
+ *
+ * @default true
+ */
+ withReset?: boolean;
+ /**
+ * Start opting into the new margin-free styles that will become the default
+ * in a future version, currently scheduled to be WordPress 6.4. (The prop
+ * can be safely removed once this happens.)
+ *
+ * @default false
+ */
+ __nextHasNoMarginBottom?: boolean;
+ /**
+ * Size of the control.
+ *
+ * @default default
+ */
+ size?: 'default' | '__unstable-large';
+};
+
+export type FontSize = {
+ /**
+ * The property `size` contains a number with the font size value, in `px` or
+ * a string specifying the font size CSS property that should be used eg:
+ * "13px", "1em", or "clamp(12px, 5vw, 100px)".
+ */
+ size: number | string;
+ /**
+ * The `name` property includes a label for that font size e.g.: `Small`.
+ */
+ name?: string;
+ /**
+ * The `slug` property is a string with a unique identifier for the font
+ * size. Used for the class generation process.
+ */
+ slug: string;
+};
+
+export type FontSizeOption = Omit< FontSize, 'size' > &
+ Partial< Pick< FontSize, 'size' > >;
+
+export type FontSizeSelectOption = Pick< FontSizeOption, 'size' > & {
+ key: string;
+ name?: string;
+ __experimentalHint: ReactNode;
+};
+
+export type FontSizeToggleGroupOption = {
+ key: string;
+ value: number | string;
+ label: string;
+ name: string;
+};
diff --git a/packages/components/src/font-size-picker/utils.js b/packages/components/src/font-size-picker/utils.ts
similarity index 58%
rename from packages/components/src/font-size-picker/utils.js
rename to packages/components/src/font-size-picker/utils.ts
index fff3d087cf3e64..bb3dd42d4e238f 100644
--- a/packages/components/src/font-size-picker/utils.js
+++ b/packages/components/src/font-size-picker/utils.ts
@@ -3,6 +3,17 @@
*/
import { __ } from '@wordpress/i18n';
+/**
+ * Internal dependencies
+ */
+import type {
+ FontSize,
+ FontSizeOption,
+ FontSizeSelectOption,
+ FontSizeToggleGroupOption,
+ FontSizePickerProps,
+} from './types';
+
const DEFAULT_FONT_SIZE = 'default';
const DEFAULT_FONT_SIZE_OPTION = {
slug: DEFAULT_FONT_SIZE,
@@ -36,13 +47,18 @@ const FONT_SIZES_ALIASES = [
* Helper util to split a font size to its numeric value
* and its `unit`, if exists.
*
- * @param {string|number} size Font size.
- * @return {[number, string]} An array with the numeric value and the unit if exists.
+ * @param size Font size.
+ * @return An array with the numeric value and the unit if exists.
*/
-export function splitValueAndUnitFromSize( size ) {
- const [ numericValue, unit ] = `${ size }`.match( /[\d\.]+|\D+/g );
+export function splitValueAndUnitFromSize(
+ size: NonNullable< FontSizePickerProps[ 'value' ] >
+) {
+ const [ numericValue, unit ] = `${ size }`.match( /[\d\.]+|\D+/g ) ?? [];
- if ( ! isNaN( parseFloat( numericValue ) ) && isFinite( numericValue ) ) {
+ if (
+ ! isNaN( parseFloat( numericValue ) ) &&
+ isFinite( Number( numericValue ) )
+ ) {
return [ numericValue, unit ];
}
@@ -53,28 +69,30 @@ export function splitValueAndUnitFromSize( size ) {
* Some themes use css vars for their font sizes, so until we
* have the way of calculating them don't display them.
*
- * @param {string|number} value The value that is checked.
- * @return {boolean} Whether the value is a simple css value.
+ * @param value The value that is checked.
+ * @return Whether the value is a simple css value.
*/
-export function isSimpleCssValue( value ) {
+export function isSimpleCssValue(
+ value: NonNullable< FontSizePickerProps[ 'value' ] >
+) {
const sizeRegex = /^[\d\.]+(px|em|rem|vw|vh|%)?$/i;
- return sizeRegex.test( value );
+ return sizeRegex.test( String( value ) );
}
/**
* Return font size options in the proper format depending
* on the currently used control (select, toggle group).
*
- * @param {boolean} useSelectControl Whether to use a select control.
- * @param {Object[]} optionsArray Array of available font sizes objects.
- * @param {boolean} disableCustomFontSizes Flag that indicates if custom font sizes are disabled.
- * @return {Object[]|null} Array of font sizes in proper format for the used control.
+ * @param useSelectControl Whether to use a select control.
+ * @param optionsArray Array of available font sizes objects.
+ * @param disableCustomFontSizes Flag that indicates if custom font sizes are disabled.
+ * @return Array of font sizes in proper format for the used control.
*/
export function getFontSizeOptions(
- useSelectControl,
- optionsArray,
- disableCustomFontSizes
-) {
+ useSelectControl: boolean,
+ optionsArray: FontSize[],
+ disableCustomFontSizes: boolean
+): FontSizeSelectOption[] | FontSizeToggleGroupOption[] | null {
if ( disableCustomFontSizes && ! optionsArray.length ) {
return null;
}
@@ -83,8 +101,11 @@ export function getFontSizeOptions(
: getToggleGroupOptions( optionsArray );
}
-function getSelectOptions( optionsArray, disableCustomFontSizes ) {
- const options = [
+function getSelectOptions(
+ optionsArray: FontSize[],
+ disableCustomFontSizes: boolean
+): FontSizeSelectOption[] {
+ const options: FontSizeOption[] = [
DEFAULT_FONT_SIZE_OPTION,
...optionsArray,
...( disableCustomFontSizes ? [] : [ CUSTOM_FONT_SIZE_OPTION ] ),
@@ -94,21 +115,21 @@ function getSelectOptions( optionsArray, disableCustomFontSizes ) {
name,
size,
__experimentalHint:
- size && isSimpleCssValue( size ) && parseFloat( size ),
+ size && isSimpleCssValue( size ) && parseFloat( String( size ) ),
} ) );
}
/**
* Build options for the toggle group options.
*
- * @param {Array} optionsArray An array of font size options.
- * @param {string[]} labelAliases An array of alternative labels.
- * @return {Array} Remapped optionsArray.
+ * @param optionsArray An array of font size options.
+ * @param labelAliases An array of alternative labels.
+ * @return Remapped optionsArray.
*/
export function getToggleGroupOptions(
- optionsArray,
- labelAliases = FONT_SIZES_ALIASES
-) {
+ optionsArray: FontSize[],
+ labelAliases: string[] = FONT_SIZES_ALIASES
+): FontSizeToggleGroupOption[] {
return optionsArray.map( ( { slug, size, name }, index ) => {
return {
key: slug,
@@ -119,7 +140,10 @@ export function getToggleGroupOptions(
} );
}
-export function getSelectedOption( fontSizes, value ) {
+export function getSelectedOption(
+ fontSizes: FontSize[],
+ value: FontSizePickerProps[ 'value' ]
+): FontSizeOption {
if ( ! value ) {
return DEFAULT_FONT_SIZE_OPTION;
}
diff --git a/packages/components/src/form-token-field/test/index.tsx b/packages/components/src/form-token-field/test/index.tsx
index 2dc08d02fa4f88..c0926a9a630e5c 100644
--- a/packages/components/src/form-token-field/test/index.tsx
+++ b/packages/components/src/form-token-field/test/index.tsx
@@ -2057,7 +2057,12 @@ describe( 'FormTokenField', () => {
const suggestions = [ 'Pine', 'Pistachio', 'Sage' ];
- render( );
+ render(
+ <>
+
+ Click me
+ >
+ );
// No suggestions visible
const input = screen.getByRole( 'combobox' );
@@ -2093,6 +2098,22 @@ describe( 'FormTokenField', () => {
pineSuggestion.id
);
+ // Blur the input and make sure that the `aria-activedescendant`
+ // is removed
+ const button = screen.getByRole( 'button', { name: 'Click me' } );
+
+ await user.click( button );
+
+ expect( input ).not.toHaveAttribute( 'aria-activedescendant' );
+
+ // Focus the input again, `aria-activedescendant` should be added back.
+ await user.click( input );
+
+ expect( input ).toHaveAttribute(
+ 'aria-activedescendant',
+ pineSuggestion.id
+ );
+
// Add the suggestion, which hides the list
await user.keyboard( '[Enter]' );
diff --git a/packages/components/src/form-token-field/token-input.tsx b/packages/components/src/form-token-field/token-input.tsx
index 478cce3f3733cc..196ac03c799af8 100644
--- a/packages/components/src/form-token-field/token-input.tsx
+++ b/packages/components/src/form-token-field/token-input.tsx
@@ -2,12 +2,12 @@
* External dependencies
*/
import classnames from 'classnames';
-import type { ChangeEvent, ForwardedRef } from 'react';
+import type { ChangeEvent, ForwardedRef, FocusEventHandler } from 'react';
/**
* WordPress dependencies
*/
-import { forwardRef } from '@wordpress/element';
+import { forwardRef, useState } from '@wordpress/element';
/**
* Internal dependencies
@@ -26,9 +26,13 @@ export function UnForwardedTokenInput(
selectedSuggestionIndex,
className,
onChange,
+ onFocus,
+ onBlur,
...restProps
} = props;
+ const [ hasFocus, setHasFocus ] = useState( false );
+
const size = value ? value.length + 1 : 0;
const onChangeHandler = ( event: ChangeEvent< HTMLInputElement > ) => {
@@ -39,6 +43,18 @@ export function UnForwardedTokenInput(
}
};
+ const onFocusHandler: FocusEventHandler< HTMLInputElement > = ( e ) => {
+ setHasFocus( true );
+ onFocus?.( e );
+ };
+
+ const onBlurHandler: React.FocusEventHandler< HTMLInputElement > = (
+ e
+ ) => {
+ setHasFocus( false );
+ onBlur?.( e );
+ };
+
return (
{ children }
-
- { icon && iconPosition === 'right' && }
+ { ! suffix && (
+
+ ) }
+ { ! suffix && icon && iconPosition === 'right' && (
+
+ ) }
+ { suffix }
);
}
diff --git a/packages/components/src/menu-item/style.scss b/packages/components/src/menu-item/style.scss
index 18c2666025a5db..d0d11643d7c96e 100644
--- a/packages/components/src/menu-item/style.scss
+++ b/packages/components/src/menu-item/style.scss
@@ -8,6 +8,7 @@
// Ensure unchecked items have clearance for consistency
// with checked items containing an icon or shortcut.
padding-right: $grid-unit-60;
+ box-sizing: initial;
}
}
diff --git a/packages/components/src/menu-item/test/index.js b/packages/components/src/menu-item/test/index.js
index aa815dd7e4bb7e..fd074759ee3828 100644
--- a/packages/components/src/menu-item/test/index.js
+++ b/packages/components/src/menu-item/test/index.js
@@ -107,4 +107,40 @@ describe( 'MenuItem', () => {
expect( checkboxMenuItem ).toBeChecked();
expect( checkboxMenuItem ).toHaveAttribute( 'aria-checked', 'true' );
} );
+
+ it( 'should not render shortcut or right icon if suffix provided', () => {
+ render(
+ Icon }
+ iconPosition="right"
+ role="menuitemcheckbox"
+ shortcut="Shortcut"
+ suffix="Suffix"
+ >
+ My item
+
+ );
+
+ expect( screen.getByText( 'Suffix' ) ).toBeInTheDocument();
+ expect( screen.queryByText( 'Shortcut' ) ).not.toBeInTheDocument();
+ expect( screen.queryByText( 'Icon' ) ).not.toBeInTheDocument();
+ } );
+
+ it( 'should render left icon despite suffix being provided', () => {
+ render(
+ Icon }
+ iconPosition="left"
+ role="menuitemcheckbox"
+ shortcut="Shortcut"
+ suffix="Suffix"
+ >
+ My item
+
+ );
+
+ expect( screen.getByText( 'Icon' ) ).toBeInTheDocument();
+ expect( screen.getByText( 'Suffix' ) ).toBeInTheDocument();
+ expect( screen.queryByText( 'Shortcut' ) ).not.toBeInTheDocument();
+ } );
} );
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js
index ac1814e3a83f8e..69534681dfa051 100644
--- a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js
@@ -112,6 +112,9 @@ function BottomSheetNavigationContainer( {
}
}
},
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
[ currentHeight ]
);
@@ -133,6 +136,9 @@ function BottomSheetNavigationContainer( {
/>
);
} );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ children ] );
return useMemo( () => {
@@ -158,6 +164,9 @@ function BottomSheetNavigationContainer( {
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ currentHeight, _theme ] );
}
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js
index 1df6a50f036fc0..059adb42c7089a 100644
--- a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js
@@ -41,6 +41,9 @@ const BottomSheetNavigationScreen = ( {
const { setHeight } = useContext( BottomSheetNavigationContext );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
const setHeightDebounce = useCallback( debounce( setHeight, 10 ), [
setHeight,
] );
@@ -70,6 +73,8 @@ const BottomSheetNavigationScreen = ( {
*
* Related: https://github.com/WordPress/gutenberg/pull/36328#discussion_r768897546
*/
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] )
);
@@ -83,6 +88,9 @@ const BottomSheetNavigationScreen = ( {
setHeight( heightRef.current.maxHeight );
}
return () => {};
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ setHeight ] )
);
@@ -127,6 +135,9 @@ const BottomSheetNavigationScreen = ( {
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [
children,
isFocused,
diff --git a/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js
index f51b07cffd9c14..64e3f609d167c3 100644
--- a/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js
+++ b/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js
@@ -23,6 +23,9 @@ const BottomSheetSubSheet = ( {
if ( showSheet ) {
setIsFullScreen( isFullScreen );
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ showSheet, isFullScreen ] );
return (
diff --git a/packages/components/src/mobile/color-settings/index.native.js b/packages/components/src/mobile/color-settings/index.native.js
index 86afffa5ae96f5..171c4a011a7fe2 100644
--- a/packages/components/src/mobile/color-settings/index.native.js
+++ b/packages/components/src/mobile/color-settings/index.native.js
@@ -34,6 +34,9 @@ const ColorSettingsMemo = memo(
useEffect( () => {
shouldEnableBottomSheetMaxHeight( true );
onHandleClosingBottomSheet( null );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
return (
diff --git a/packages/components/src/mobile/color-settings/picker-screen.native.js b/packages/components/src/mobile/color-settings/picker-screen.native.js
index 440abd7e8ed202..f8626a67338a42 100644
--- a/packages/components/src/mobile/color-settings/picker-screen.native.js
+++ b/packages/components/src/mobile/color-settings/picker-screen.native.js
@@ -43,6 +43,9 @@ const PickerScreen = () => {
onHandleHardwareButtonPress={ onHandleHardwareButtonPress }
/>
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [
setColor,
currentValue,
diff --git a/packages/components/src/mobile/image/index.native.js b/packages/components/src/mobile/image/index.native.js
index 34f6557e8255e1..9d365763e027dd 100644
--- a/packages/components/src/mobile/image/index.native.js
+++ b/packages/components/src/mobile/image/index.native.js
@@ -82,6 +82,9 @@ const ImageComponent = ( {
} );
}
return () => ( isCurrent = false );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ url ] );
const onContainerLayout = ( event ) => {
diff --git a/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js b/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js
index 6fd716a527ee3b..f13e7d329874fd 100644
--- a/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js
+++ b/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js
@@ -69,6 +69,9 @@ export const KeyboardAvoidingView = ( {
keyboardShowSubscription.remove();
keyboardHideSubscription.remove();
};
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
function onSafeAreaInsetsUpdate( { safeAreaInsets } ) {
diff --git a/packages/components/src/mobile/link-picker/index.native.js b/packages/components/src/mobile/link-picker/index.native.js
index bf61bcddaa6154..ffde5b28c26171 100644
--- a/packages/components/src/mobile/link-picker/index.native.js
+++ b/packages/components/src/mobile/link-picker/index.native.js
@@ -91,6 +91,9 @@ export const LinkPicker = ( {
getURLFromClipboard()
.then( ( url ) => setValue( { value, clipboardUrl: url } ) )
.catch( () => setValue( { value, clipboardUrl: '' } ) );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
// TODO: Localize the accessibility label.
diff --git a/packages/components/src/mobile/link-picker/link-picker-results.native.js b/packages/components/src/mobile/link-picker/link-picker-results.native.js
index 29e67a1827632d..a3a9c7e9e0a743 100644
--- a/packages/components/src/mobile/link-picker/link-picker-results.native.js
+++ b/packages/components/src/mobile/link-picker/link-picker-results.native.js
@@ -86,6 +86,9 @@ export default function LinkPickerResults( {
setHasAllSuggestions( false );
setLinks( [ directEntry ] );
fetchMoreSuggestions( { query, links: [ directEntry ] } );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ query ] );
const onEndReached = () => fetchMoreSuggestions( { query, links } );
diff --git a/packages/components/src/mobile/link-picker/link-picker-screen.native.js b/packages/components/src/mobile/link-picker/link-picker-screen.native.js
index f77cf4e18a1b07..7bc1dbd7009b62 100644
--- a/packages/components/src/mobile/link-picker/link-picker-screen.native.js
+++ b/packages/components/src/mobile/link-picker/link-picker-screen.native.js
@@ -53,6 +53,9 @@ const LinkPickerScreen = ( { returnScreenName } ) => {
onCancel={ onCancel }
/>
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ inputValue ] );
};
diff --git a/packages/components/src/mobile/link-settings/index.native.js b/packages/components/src/mobile/link-settings/index.native.js
index 794650adefdd79..e80672a3103fa6 100644
--- a/packages/components/src/mobile/link-settings/index.native.js
+++ b/packages/components/src/mobile/link-settings/index.native.js
@@ -101,6 +101,9 @@ function LinkSettings( {
if ( onHandleClosingBottomSheet ) {
onHandleClosingBottomSheet( onCloseSettingsSheet );
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ urlInputValue, labelInputValue, linkRelInputValue ] );
useEffect( () => {
@@ -112,6 +115,9 @@ function LinkSettings( {
if ( url !== urlInputValue ) {
setUrlInputValue( url || '' );
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ url ] );
useEffect( () => {
@@ -135,6 +141,9 @@ function LinkSettings( {
if ( prevEditorSidebarOpened && ! editorSidebarOpened ) {
onSetAttributes();
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ editorSidebarOpened, isVisible ] );
useEffect( () => {
@@ -147,6 +156,9 @@ function LinkSettings( {
url: prependHTTP( urlValue ),
} );
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ urlValue ] );
const onChangeURL = useCallback(
@@ -176,6 +188,9 @@ function LinkSettings( {
rel: linkRelInputValue,
} );
}
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ urlInputValue, labelInputValue, linkRelInputValue, setAttributes ] );
const onCloseSettingsSheet = useCallback( () => {
@@ -208,6 +223,9 @@ function LinkSettings( {
rel: updatedRel,
} );
},
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
[ linkRelInputValue ]
);
diff --git a/packages/components/src/mobile/link-settings/link-settings-screen.native.js b/packages/components/src/mobile/link-settings/link-settings-screen.native.js
index 65c95187d2fcb8..d04bd0699b7a54 100644
--- a/packages/components/src/mobile/link-settings/link-settings-screen.native.js
+++ b/packages/components/src/mobile/link-settings/link-settings-screen.native.js
@@ -37,6 +37,9 @@ const LinkSettingsScreen = ( props ) => {
urlValue={ inputValue }
/>
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ props, inputValue, navigation, route ] );
};
diff --git a/packages/components/src/mobile/segmented-control/index.native.js b/packages/components/src/mobile/segmented-control/index.native.js
index b34b8d158a0899..b3270e37120e3b 100644
--- a/packages/components/src/mobile/segmented-control/index.native.js
+++ b/packages/components/src/mobile/segmented-control/index.native.js
@@ -74,12 +74,18 @@ const SegmentedControls = ( {
useEffect( () => {
setActiveSegmentIndex( selectedSegmentIndex );
segmentHandler( segments[ selectedSegmentIndex ] );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
useEffect( () => {
positionAnimationValue.setValue(
calculateEndValue( activeSegmentIndex )
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ segmentsDimensions ] );
const containerStyle = usePreferredColorSchemeStyle(
diff --git a/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js b/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js
index 9e08b88f4f1c49..11d54f954215d4 100644
--- a/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js
+++ b/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js
@@ -78,6 +78,9 @@ const useConvertUnitToMobile = ( value, unit ) => {
return () => {
dimensionsChangeSubscription.remove();
};
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
const onDimensionsChange = useCallback( ( { window } ) => {
@@ -94,6 +97,9 @@ const useConvertUnitToMobile = ( value, unit ) => {
valueToConvert,
valueUnit
);
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ windowSizes, value, unit ] );
};
diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx
index 94b7bfee306e97..9bb8b3c2d83d22 100644
--- a/packages/components/src/navigator/navigator-screen/component.tsx
+++ b/packages/components/src/navigator/navigator-screen/component.tsx
@@ -83,6 +83,14 @@ function NavigatorScreen( props: Props, forwardedRef: ForwardedRef< any > ) {
return;
}
+ const activeElement = wrapperRef.current.ownerDocument.activeElement;
+
+ // If an element is already focused within the wrapper do not focus the
+ // element. This prevents inputs or buttons from losing focus unecessarily.
+ if ( wrapperRef.current.contains( activeElement ) ) {
+ return;
+ }
+
let elementToFocus: HTMLElement | null = null;
// When navigating back, if a selector is provided, use it to look for the
@@ -99,7 +107,6 @@ function NavigatorScreen( props: Props, forwardedRef: ForwardedRef< any > ) {
const firstTabbable = (
focus.tabbable.find( wrapperRef.current ) as HTMLElement[]
)[ 0 ];
-
elementToFocus = firstTabbable ?? wrapperRef.current;
}
diff --git a/packages/components/src/navigator/test/index.js b/packages/components/src/navigator/test/index.js
index 497e1c2612b34e..7374ede686e815 100644
--- a/packages/components/src/navigator/test/index.js
+++ b/packages/components/src/navigator/test/index.js
@@ -2,6 +2,12 @@
* External dependencies
*/
import { render, screen, fireEvent } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+/**
+ * WordPress dependencies
+ */
+import { useState } from '@wordpress/element';
/**
* Internal dependencies
@@ -86,60 +92,74 @@ function CustomNavigatorBackButton( { onClick, ...props } ) {
const MyNavigation = ( {
initialPath = PATHS.HOME,
onNavigatorButtonClick,
-} ) => (
-
-
- This is the home screen.
-
- Navigate to non-existing screen.
-
-
- Navigate to child screen.
-
-
- Navigate to screen with an invalid HTML value as a path.
-
-
-
-
- This is the child screen.
-
- Navigate to nested screen.
-
-
- Go back
-
-
-
-
- This is the nested screen.
-
- Go back
-
-
-
-
- This is the screen with an invalid HTML value as a path.
-
- Go back
-
-
-
- { /* A `NavigatorScreen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ }
-
-);
+} ) => {
+ const [ inputValue, setInputValue ] = useState( '' );
+ return (
+
+
+ This is the home screen.
+
+ Navigate to non-existing screen.
+
+
+ Navigate to child screen.
+
+
+ Navigate to screen with an invalid HTML value as a path.
+
+
+
+
+ This is the child screen.
+
+ Navigate to nested screen.
+
+
+ Go back
+
+
+ This is a test input
+ {
+ setInputValue( e.target.value );
+ } }
+ value={ inputValue }
+ />
+
+
+
+ This is the nested screen.
+
+ Go back
+
+
+
+
+ This is the screen with an invalid HTML value as a path.
+
+ Go back
+
+
+
+ { /* A `NavigatorScreen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ }
+
+ );
+};
const getNavigationScreenByText = ( text, { throwIfNotFound = true } = {} ) => {
const fnName = throwIfNotFound ? 'getByText' : 'queryByText';
@@ -194,6 +214,28 @@ const getBackButton = ( { throwIfNotFound } = {} ) =>
} );
describe( 'Navigator', () => {
+ const originalGetClientRects = window.Element.prototype.getClientRects;
+
+ // `getClientRects` needs to be mocked so that `isVisible` from the `@wordpress/dom`
+ // `focusable` module can pass, in a JSDOM env where the DOM elements have no width/height.
+ const mockedGetClientRects = jest.fn( () => [
+ {
+ x: 0,
+ y: 0,
+ width: 100,
+ height: 100,
+ },
+ ] );
+
+ beforeAll( () => {
+ window.Element.prototype.getClientRects =
+ jest.fn( mockedGetClientRects );
+ } );
+
+ afterAll( () => {
+ window.Element.prototype.getClientRects = originalGetClientRects;
+ } );
+
it( 'should render', () => {
render( );
@@ -404,4 +446,27 @@ describe( 'Navigator', () => {
expect( getHomeScreen() ).toBeInTheDocument();
expect( getToInvalidHTMLPathScreenButton() ).toHaveFocus();
} );
+
+ it( 'should keep focus on the element that is being interacted with, while re-rendering', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render( );
+
+ expect( getHomeScreen() ).toBeInTheDocument();
+ expect( getToChildScreenButton() ).toBeInTheDocument();
+
+ // Navigate to child screen.
+ await user.click( getToChildScreenButton() );
+
+ expect( getChildScreen() ).toBeInTheDocument();
+ expect( getBackButton() ).toBeInTheDocument();
+ expect( getToNestedScreenButton() ).toHaveFocus();
+
+ // Interact with the input, the focus should stay on the input element.
+ const input = screen.getByLabelText( 'This is a test input' );
+ await user.type( input, 'd' );
+ expect( input ).toHaveFocus();
+ } );
} );
diff --git a/packages/components/src/notice/index.native.js b/packages/components/src/notice/index.native.js
index 72910b17620c5f..b2f2eb75c9435a 100644
--- a/packages/components/src/notice/index.native.js
+++ b/packages/components/src/notice/index.native.js
@@ -14,7 +14,7 @@ import { BlurView } from '@react-native-community/blur';
/**
* WordPress dependencies
*/
-import { useEffect, useRef, Platform } from '@wordpress/element';
+import { useEffect, useRef, useCallback, Platform } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
/**
@@ -30,40 +30,37 @@ const Notice = ( { onNoticeHidden, content, id, status } ) => {
const timer = useRef( null );
useEffect( () => {
- startAnimation();
-
- return () => {
- clearTimeout( timer?.current );
- };
- }, [] );
-
- function onHide() {
+ // start animation
Animated.timing( animationValue, {
- toValue: 0,
- duration: 150,
+ toValue: 1,
+ duration: 300,
useNativeDriver: true,
easing: Easing.out( Easing.quad ),
} ).start( ( { finished } ) => {
if ( finished && onNoticeHidden ) {
- onNoticeHidden( id );
+ timer.current = setTimeout( () => {
+ onHide();
+ }, HIDE_TIMER );
}
} );
- }
- function startAnimation() {
+ return () => {
+ clearTimeout( timer?.current );
+ };
+ }, [ animationValue, onHide, onNoticeHidden ] );
+
+ const onHide = useCallback( () => {
Animated.timing( animationValue, {
- toValue: 1,
- duration: 300,
+ toValue: 0,
+ duration: 150,
useNativeDriver: true,
easing: Easing.out( Easing.quad ),
} ).start( ( { finished } ) => {
if ( finished && onNoticeHidden ) {
- timer.current = setTimeout( () => {
- onHide();
- }, HIDE_TIMER );
+ onNoticeHidden( id );
}
} );
- }
+ }, [ animationValue, onNoticeHidden, id ] );
const noticeSolidStyles = usePreferredColorSchemeStyle(
styles.noticeSolid,
diff --git a/packages/components/src/notice/list.native.js b/packages/components/src/notice/list.native.js
index bf067a0942fd6e..72a4c743108995 100644
--- a/packages/components/src/notice/list.native.js
+++ b/packages/components/src/notice/list.native.js
@@ -14,6 +14,7 @@ import { store as noticesStore } from '@wordpress/notices';
*/
import Notice from './';
import styles from './style.scss';
+import { useCallback } from '@wordpress/element';
function NoticeList() {
const { notices } = useSelect( ( select ) => {
@@ -25,9 +26,12 @@ function NoticeList() {
const { removeNotice } = useDispatch( noticesStore );
- function onRemoveNotice( id ) {
- removeNotice( id );
- }
+ const onRemoveNotice = useCallback(
+ ( id ) => {
+ removeNotice( id );
+ },
+ [ removeNotice ]
+ );
if ( ! notices.length ) {
return null;
diff --git a/packages/components/src/palette-edit/index.js b/packages/components/src/palette-edit/index.js
index 065302acc10865..ec38edcc72a586 100644
--- a/packages/components/src/palette-edit/index.js
+++ b/packages/components/src/palette-edit/index.js
@@ -316,7 +316,7 @@ export default function PaletteEdit( {
{ paletteLabel }
- { isEditing && (
+ { hasElements && isEditing && (
{
diff --git a/packages/components/src/placeholder/style.scss b/packages/components/src/placeholder/style.scss
index db2f0065994bea..ce38921496a7bf 100644
--- a/packages/components/src/placeholder/style.scss
+++ b/packages/components/src/placeholder/style.scss
@@ -178,9 +178,9 @@
min-width: 100px;
// Blur the background so layered dashed placeholders are still visually separate.
- // We also provide a semitransparent background so as to allow duotones to sheen through.
+ // Make the background transparent to not interfere with the background overlay in placeholder-style() pseudo element
backdrop-filter: blur(100px);
- background-color: rgba($white, 0.1);
+ background-color: transparent;
// Invert the colors in themes deemed dark.
.is-dark-theme & {
@@ -234,5 +234,5 @@
width: 100%;
height: 100%;
stroke: currentColor;
- stroke-dasharray: 3;
+ opacity: 0.25;
}
diff --git a/packages/components/src/popover/index.tsx b/packages/components/src/popover/index.tsx
index 1e9060b9a42356..25bb157247a361 100644
--- a/packages/components/src/popover/index.tsx
+++ b/packages/components/src/popover/index.tsx
@@ -10,9 +10,9 @@ import {
autoUpdate,
arrow,
offset as offsetMiddleware,
- limitShift,
size,
Middleware,
+ MiddlewareArguments,
} from '@floating-ui/react-dom';
// eslint-disable-next-line no-restricted-imports
import {
@@ -34,7 +34,6 @@ import {
useMemo,
useState,
useCallback,
- useEffect,
} from '@wordpress/element';
import {
useViewportMatch,
@@ -65,6 +64,7 @@ import type {
PopoverAnchorRefReference,
PopoverAnchorRefTopBottom,
} from './types';
+import { limitShift as customLimitShift } from './limit-shift';
/**
* Name of slot in which popover should fill.
@@ -281,42 +281,31 @@ const UnforwardedPopover = (
* https://floating-ui.com/docs/react-dom#variables-inside-middleware-functions.
*/
const frameOffsetRef = useRef( getFrameOffset( referenceOwnerDocument ) );
- /**
- * Store the offset prop in a ref, due to constraints with floating-ui:
- * https://floating-ui.com/docs/react-dom#variables-inside-middleware-functions.
- */
- const offsetRef = useRef( offsetProp );
const middleware = [
- offsetMiddleware( ( { placement: currentPlacement } ) => {
- if ( ! frameOffsetRef.current ) {
- return offsetRef.current;
- }
-
- const isTopBottomPlacement =
- currentPlacement.includes( 'top' ) ||
- currentPlacement.includes( 'bottom' );
-
- // The main axis should represent the gap between the
- // floating element and the reference element. The cross
- // axis is always perpendicular to the main axis.
- const mainAxis = isTopBottomPlacement ? 'y' : 'x';
- const crossAxis = mainAxis === 'x' ? 'y' : 'x';
-
- // When the popover is before the reference, subtract the offset,
- // of the main axis else add it.
- const hasBeforePlacement =
- currentPlacement.includes( 'top' ) ||
- currentPlacement.includes( 'left' );
- const mainAxisModifier = hasBeforePlacement ? -1 : 1;
-
- return {
- mainAxis:
- offsetRef.current +
- frameOffsetRef.current[ mainAxis ] * mainAxisModifier,
- crossAxis: frameOffsetRef.current[ crossAxis ],
- };
- } ),
+ // Custom middleware which adjusts the popover's position by taking into
+ // account the offset of the anchor's iframe (if any) compared to the page.
+ {
+ name: 'frameOffset',
+ fn( { x, y }: MiddlewareArguments ) {
+ if ( ! frameOffsetRef.current ) {
+ return {
+ x,
+ y,
+ };
+ }
+
+ return {
+ x: x + frameOffsetRef.current.x,
+ y: y + frameOffsetRef.current.y,
+ data: {
+ // This will be used in the customLimitShift() function.
+ amount: frameOffsetRef.current,
+ },
+ };
+ },
+ },
+ offsetMiddleware( offsetProp ),
computedFlipProp ? flipMiddleware() : undefined,
computedResizeProp
? size( {
@@ -339,7 +328,7 @@ const UnforwardedPopover = (
shouldShift
? shiftMiddleware( {
crossAxis: true,
- limiter: limitShift(),
+ limiter: customLimitShift(),
padding: 1, // Necessary to avoid flickering at the edge of the viewport.
} )
: undefined,
@@ -395,11 +384,6 @@ const UnforwardedPopover = (
} ),
} );
- useEffect( () => {
- offsetRef.current = offsetProp;
- update();
- }, [ offsetProp, update ] );
-
const arrowCallbackRef = useCallback(
( node ) => {
arrowRef.current = node;
diff --git a/packages/components/src/popover/limit-shift.ts b/packages/components/src/popover/limit-shift.ts
new file mode 100644
index 00000000000000..45e65a0b619098
--- /dev/null
+++ b/packages/components/src/popover/limit-shift.ts
@@ -0,0 +1,205 @@
+/**
+ * External dependencies
+ */
+import type {
+ Axis,
+ Coords,
+ Placement,
+ Side,
+ MiddlewareArguments,
+} from '@floating-ui/react-dom';
+
+/**
+ * Parts of this source were derived and modified from `floating-ui`,
+ * released under the MIT license.
+ *
+ * https://github.com/floating-ui/floating-ui
+ *
+ * Copyright (c) 2021 Floating UI contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * Custom limiter function for the `shift` middleware.
+ * This function is mostly identical default `limitShift` from ``@floating-ui`;
+ * the only difference is that, when computing the min/max shift limits, it
+ * also takes into account the iframe offset that is added by the
+ * custom "frameOffset" middleware.
+ *
+ * All unexported types and functions are also from the `@floating-ui` library,
+ * and have been copied to this file for convenience.
+ */
+
+type LimitShiftOffset =
+ | ( ( args: MiddlewareArguments ) =>
+ | number
+ | {
+ /**
+ * Offset the limiting of the axis that runs along the alignment of the
+ * floating element.
+ */
+ mainAxis?: number;
+ /**
+ * Offset the limiting of the axis that runs along the side of the
+ * floating element.
+ */
+ crossAxis?: number;
+ } )
+ | number
+ | {
+ /**
+ * Offset the limiting of the axis that runs along the alignment of the
+ * floating element.
+ */
+ mainAxis?: number;
+ /**
+ * Offset the limiting of the axis that runs along the side of the
+ * floating element.
+ */
+ crossAxis?: number;
+ };
+
+type LimitShiftOptions = {
+ /**
+ * Offset when limiting starts. `0` will limit when the opposite edges of the
+ * reference and floating elements are aligned.
+ * - positive = start limiting earlier
+ * - negative = start limiting later
+ */
+ offset: LimitShiftOffset;
+ /**
+ * Whether to limit the axis that runs along the alignment of the floating
+ * element.
+ */
+ mainAxis: boolean;
+ /**
+ * Whether to limit the axis that runs along the side of the floating element.
+ */
+ crossAxis: boolean;
+};
+
+function getSide( placement: Placement ): Side {
+ return placement.split( '-' )[ 0 ] as Side;
+}
+
+function getMainAxisFromPlacement( placement: Placement ): Axis {
+ return [ 'top', 'bottom' ].includes( getSide( placement ) ) ? 'x' : 'y';
+}
+
+function getCrossAxis( axis: Axis ): Axis {
+ return axis === 'x' ? 'y' : 'x';
+}
+
+export const limitShift = (
+ options: Partial< LimitShiftOptions > = {}
+): {
+ options: Partial< LimitShiftOffset >;
+ fn: ( middlewareArguments: MiddlewareArguments ) => Coords;
+} => ( {
+ options,
+ fn( middlewareArguments ) {
+ const { x, y, placement, rects, middlewareData } = middlewareArguments;
+ const {
+ offset = 0,
+ mainAxis: checkMainAxis = true,
+ crossAxis: checkCrossAxis = true,
+ } = options;
+
+ const coords = { x, y };
+ const mainAxis = getMainAxisFromPlacement( placement );
+ const crossAxis = getCrossAxis( mainAxis );
+
+ let mainAxisCoord = coords[ mainAxis ];
+ let crossAxisCoord = coords[ crossAxis ];
+
+ const rawOffset =
+ typeof offset === 'function'
+ ? offset( middlewareArguments )
+ : offset;
+ const computedOffset =
+ typeof rawOffset === 'number'
+ ? { mainAxis: rawOffset, crossAxis: 0 }
+ : { mainAxis: 0, crossAxis: 0, ...rawOffset };
+
+ // At the moment of writing, this is the only difference
+ // with the `limitShift` function from `@floating-ui`.
+ // This offset needs to be added to all min/max limits
+ // in order to make the shift-limiting work as expected.
+ const additionalFrameOffset = {
+ x: 0,
+ y: 0,
+ ...middlewareData.frameOffset?.amount,
+ };
+
+ if ( checkMainAxis ) {
+ const len = mainAxis === 'y' ? 'height' : 'width';
+ const limitMin =
+ rects.reference[ mainAxis ] -
+ rects.floating[ len ] +
+ computedOffset.mainAxis +
+ additionalFrameOffset[ mainAxis ];
+ const limitMax =
+ rects.reference[ mainAxis ] +
+ rects.reference[ len ] -
+ computedOffset.mainAxis +
+ additionalFrameOffset[ mainAxis ];
+
+ if ( mainAxisCoord < limitMin ) {
+ mainAxisCoord = limitMin;
+ } else if ( mainAxisCoord > limitMax ) {
+ mainAxisCoord = limitMax;
+ }
+ }
+
+ if ( checkCrossAxis ) {
+ const len = mainAxis === 'y' ? 'width' : 'height';
+ const isOriginSide = [ 'top', 'left' ].includes(
+ getSide( placement )
+ );
+ const limitMin =
+ rects.reference[ crossAxis ] -
+ rects.floating[ len ] +
+ ( isOriginSide
+ ? middlewareData.offset?.[ crossAxis ] ?? 0
+ : 0 ) +
+ ( isOriginSide ? 0 : computedOffset.crossAxis ) +
+ additionalFrameOffset[ crossAxis ];
+ const limitMax =
+ rects.reference[ crossAxis ] +
+ rects.reference[ len ] +
+ ( isOriginSide
+ ? 0
+ : middlewareData.offset?.[ crossAxis ] ?? 0 ) -
+ ( isOriginSide ? computedOffset.crossAxis : 0 ) +
+ additionalFrameOffset[ crossAxis ];
+
+ if ( crossAxisCoord < limitMin ) {
+ crossAxisCoord = limitMin;
+ } else if ( crossAxisCoord > limitMax ) {
+ crossAxisCoord = limitMax;
+ }
+ }
+
+ return {
+ [ mainAxis ]: mainAxisCoord,
+ [ crossAxis ]: crossAxisCoord,
+ } as Coords;
+ },
+} );
diff --git a/packages/components/src/popover/test/__snapshots__/index.js.snap b/packages/components/src/popover/test/__snapshots__/index.js.snap
deleted file mode 100644
index e3eb977180bf21..00000000000000
--- a/packages/components/src/popover/test/__snapshots__/index.js.snap
+++ /dev/null
@@ -1,34 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Popover Component should pass additional props to portaled element 1`] = `
-
-
-
-`;
-
-exports[`Popover Component should render content 1`] = `
-
-
-
-`;
diff --git a/packages/components/src/popover/test/index.js b/packages/components/src/popover/test/index.js
deleted file mode 100644
index dff33914659693..00000000000000
--- a/packages/components/src/popover/test/index.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * External dependencies
- */
-import { act, render, screen } from '@testing-library/react';
-
-/**
- * WordPress dependencies
- */
-import { useState } from '@wordpress/element';
-
-/**
- * Internal dependencies
- */
-import Popover from '../';
-
-import { positionToPlacement, placementToMotionAnimationProps } from '../utils';
-
-describe( 'Popover', () => {
- describe( 'Component', () => {
- afterEach( () => {
- if ( document.activeElement ) {
- document.activeElement.blur();
- }
- } );
-
- it( 'should allow focus-on-open behavior to be disabled', () => {
- expect( document.activeElement ).toBe( document.body );
-
- act( () => {
- render( );
-
- jest.advanceTimersByTime( 1 );
- } );
-
- expect( document.activeElement ).toBe( document.body );
- } );
-
- it( 'should render content', () => {
- let result;
- act( () => {
- result = render( Hello );
- } );
-
- expect(
- result.container.querySelector( 'span' )
- ).toMatchSnapshot();
- } );
-
- it( 'should pass additional props to portaled element', () => {
- let result;
- act( () => {
- result = render( Hello );
- } );
-
- expect(
- result.container.querySelector( 'span' )
- ).toMatchSnapshot();
- } );
-
- it( 'should render correctly when anchor is provided', () => {
- const PopoverWithAnchor = ( args ) => {
- // Use internal state instead of a ref to make sure that the component
- // re-renders when the popover's anchor updates.
- const [ anchor, setAnchor ] = useState( null );
-
- return (
-
- );
- };
-
- render( Popover content );
-
- expect( screen.getByText( 'Popover content' ) ).toBeInTheDocument();
- } );
- } );
-
- describe( 'positionToPlacement', () => {
- it.each( [
- [ 'top left', 'top-end' ],
- [ 'top center', 'top' ],
- [ 'top right', 'top-start' ],
- [ 'middle left', 'left' ],
- [ 'middle center', 'center' ],
- [ 'middle right', 'right' ],
- [ 'bottom left', 'bottom-end' ],
- [ 'bottom center', 'bottom' ],
- [ 'bottom right', 'bottom-start' ],
- ] )( 'converts `%s` to `%s`', ( inputPosition, expectedPlacement ) => {
- expect( positionToPlacement( inputPosition ) ).toEqual(
- expectedPlacement
- );
- } );
- } );
-
- describe( 'placementToMotionAnimationProps', () => {
- describe( 'animation origin', () => {
- it.each( [
- [ 'top', 0.5, 1 ],
- [ 'top-start', 0, 1 ],
- [ 'top-end', 1, 1 ],
- [ 'right', 0, 0.5 ],
- [ 'right-start', 0, 0 ],
- [ 'right-end', 0, 1 ],
- [ 'bottom', 0.5, 0 ],
- [ 'bottom-start', 0, 0 ],
- [ 'bottom-end', 1, 0 ],
- [ 'left', 1, 0.5 ],
- [ 'left-start', 1, 0 ],
- [ 'left-end', 1, 1 ],
- ] )(
- 'for the `%s` placement computes an animation origin of (%d, %d)',
- ( inputPlacement, expectedOriginX, expectedOriginY ) => {
- expect(
- placementToMotionAnimationProps( inputPlacement )
- ).toEqual(
- expect.objectContaining( {
- style: expect.objectContaining( {
- originX: expectedOriginX,
- originY: expectedOriginY,
- } ),
- } )
- );
- }
- );
- } );
- describe( 'initial translation', () => {
- it.each( [
- [ 'top', 'translateY', '2em' ],
- [ 'top-start', 'translateY', '2em' ],
- [ 'top-end', 'translateY', '2em' ],
- [ 'right', 'translateX', '-2em' ],
- [ 'right-start', 'translateX', '-2em' ],
- [ 'right-end', 'translateX', '-2em' ],
- [ 'bottom', 'translateY', '-2em' ],
- [ 'bottom-start', 'translateY', '-2em' ],
- [ 'bottom-end', 'translateY', '-2em' ],
- [ 'left', 'translateX', '2em' ],
- [ 'left-start', 'translateX', '2em' ],
- [ 'left-end', 'translateX', '2em' ],
- ] )(
- 'for the `%s` placement computes an initial `%s` of `%s',
- (
- inputPlacement,
- expectedTranslationProp,
- expectedTranslationValue
- ) => {
- expect(
- placementToMotionAnimationProps( inputPlacement )
- ).toEqual(
- expect.objectContaining( {
- initial: expect.objectContaining( {
- [ expectedTranslationProp ]:
- expectedTranslationValue,
- } ),
- } )
- );
- }
- );
- } );
- } );
-} );
diff --git a/packages/components/src/popover/test/index.tsx b/packages/components/src/popover/test/index.tsx
new file mode 100644
index 00000000000000..b06886e52243ef
--- /dev/null
+++ b/packages/components/src/popover/test/index.tsx
@@ -0,0 +1,230 @@
+/**
+ * External dependencies
+ */
+import { render, screen } from '@testing-library/react';
+import type { CSSProperties } from 'react';
+
+/**
+ * WordPress dependencies
+ */
+import { useState } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { positionToPlacement, placementToMotionAnimationProps } from '../utils';
+import Popover from '..';
+import type { PopoverProps } from '../types';
+
+type PositionToPlacementTuple = [
+ NonNullable< PopoverProps[ 'position' ] >,
+ NonNullable< PopoverProps[ 'placement' ] >
+];
+type PlacementToAnimationOriginTuple = [
+ NonNullable< PopoverProps[ 'placement' ] >,
+ number,
+ number
+];
+type PlacementToInitialTranslationTuple = [
+ NonNullable< PopoverProps[ 'placement' ] >,
+ 'translateY' | 'translateX',
+ CSSProperties[ 'translate' ]
+];
+
+// There's no matching `placement` for 'middle center' positions,
+// fallback to 'bottom' (same as `floating-ui`'s default.)
+const FALLBACK_FOR_MIDDLE_CENTER_POSITIONS = 'bottom';
+
+const ALL_POSITIONS_TO_EXPECTED_PLACEMENTS: PositionToPlacementTuple[] = [
+ // Format: [yAxis]
+ [ 'middle', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'bottom', 'bottom' ],
+ [ 'top', 'top' ],
+ // Format: [yAxis] [xAxis]
+ [ 'middle left', 'left' ],
+ [ 'middle center', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'middle right', 'right' ],
+ [ 'bottom left', 'bottom-end' ],
+ [ 'bottom center', 'bottom' ],
+ [ 'bottom right', 'bottom-start' ],
+ [ 'top left', 'top-end' ],
+ [ 'top center', 'top' ],
+ [ 'top right', 'top-start' ],
+ // Format: [yAxis] [xAxis] [corner]
+ [ 'middle left left', 'left' ],
+ [ 'middle left right', 'left' ],
+ [ 'middle left bottom', 'left-end' ],
+ [ 'middle left top', 'left-start' ],
+ [ 'middle center left', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'middle center right', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'middle center bottom', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'middle center top', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
+ [ 'middle right left', 'right' ],
+ [ 'middle right right', 'right' ],
+ [ 'middle right bottom', 'right-end' ],
+ [ 'middle right top', 'right-start' ],
+ [ 'bottom left left', 'bottom-end' ],
+ [ 'bottom left right', 'bottom-end' ],
+ [ 'bottom left bottom', 'bottom-end' ],
+ [ 'bottom left top', 'bottom-end' ],
+ [ 'bottom center left', 'bottom' ],
+ [ 'bottom center right', 'bottom' ],
+ [ 'bottom center bottom', 'bottom' ],
+ [ 'bottom center top', 'bottom' ],
+ [ 'bottom right left', 'bottom-start' ],
+ [ 'bottom right right', 'bottom-start' ],
+ [ 'bottom right bottom', 'bottom-start' ],
+ [ 'bottom right top', 'bottom-start' ],
+ [ 'top left left', 'top-end' ],
+ [ 'top left right', 'top-end' ],
+ [ 'top left bottom', 'top-end' ],
+ [ 'top left top', 'top-end' ],
+ [ 'top center left', 'top' ],
+ [ 'top center right', 'top' ],
+ [ 'top center bottom', 'top' ],
+ [ 'top center top', 'top' ],
+ [ 'top right left', 'top-start' ],
+ [ 'top right right', 'top-start' ],
+ [ 'top right bottom', 'top-start' ],
+ [ 'top right top', 'top-start' ],
+];
+
+describe( 'Popover', () => {
+ describe( 'Component', () => {
+ describe( 'basic behavior', () => {
+ it( 'should render content', () => {
+ render( Hello );
+
+ expect( screen.getByText( 'Hello' ) ).toBeInTheDocument();
+ } );
+
+ it( 'should forward additional props to portaled element', () => {
+ render( Hello );
+
+ expect( screen.getByRole( 'tooltip' ) ).toBeInTheDocument();
+ } );
+ } );
+
+ describe( 'anchor', () => {
+ it( 'should render correctly when anchor is provided', () => {
+ const PopoverWithAnchor = ( args: PopoverProps ) => {
+ // Use internal state instead of a ref to make sure that the component
+ // re-renders when the popover's anchor updates.
+ const [ anchor, setAnchor ] =
+ useState< HTMLParagraphElement | null >( null );
+
+ return (
+
+ );
+ };
+
+ render(
+ Popover content
+ );
+
+ expect(
+ screen.getByText( 'Popover content' )
+ ).toBeInTheDocument();
+ } );
+ } );
+
+ describe( 'focus behavior', () => {
+ it( 'should focus the popover by default when opened', () => {
+ render( Popover content );
+
+ expect(
+ screen.getByText( 'Popover content' ).parentElement
+ ).toHaveFocus();
+ } );
+
+ it( 'should allow focus-on-open behavior to be disabled', () => {
+ render(
+ Popover content
+ );
+
+ expect( document.body ).toHaveFocus();
+ } );
+ } );
+ } );
+
+ describe( 'positionToPlacement', () => {
+ it.each( ALL_POSITIONS_TO_EXPECTED_PLACEMENTS )(
+ 'converts `%s` to `%s`',
+ ( inputPosition, expectedPlacement ) => {
+ expect( positionToPlacement( inputPosition ) ).toEqual(
+ expectedPlacement
+ );
+ }
+ );
+ } );
+
+ describe( 'placementToMotionAnimationProps', () => {
+ describe( 'animation origin', () => {
+ it.each( [
+ [ 'top', 0.5, 1 ],
+ [ 'top-start', 0, 1 ],
+ [ 'top-end', 1, 1 ],
+ [ 'right', 0, 0.5 ],
+ [ 'right-start', 0, 0 ],
+ [ 'right-end', 0, 1 ],
+ [ 'bottom', 0.5, 0 ],
+ [ 'bottom-start', 0, 0 ],
+ [ 'bottom-end', 1, 0 ],
+ [ 'left', 1, 0.5 ],
+ [ 'left-start', 1, 0 ],
+ [ 'left-end', 1, 1 ],
+ ] as PlacementToAnimationOriginTuple[] )(
+ 'for the `%s` placement computes an animation origin of (%d, %d)',
+ ( inputPlacement, expectedOriginX, expectedOriginY ) => {
+ expect(
+ placementToMotionAnimationProps( inputPlacement )
+ ).toEqual(
+ expect.objectContaining( {
+ style: expect.objectContaining( {
+ originX: expectedOriginX,
+ originY: expectedOriginY,
+ } ),
+ } )
+ );
+ }
+ );
+ } );
+ describe( 'initial translation', () => {
+ it.each( [
+ [ 'top', 'translateY', '2em' ],
+ [ 'top-start', 'translateY', '2em' ],
+ [ 'top-end', 'translateY', '2em' ],
+ [ 'right', 'translateX', '-2em' ],
+ [ 'right-start', 'translateX', '-2em' ],
+ [ 'right-end', 'translateX', '-2em' ],
+ [ 'bottom', 'translateY', '-2em' ],
+ [ 'bottom-start', 'translateY', '-2em' ],
+ [ 'bottom-end', 'translateY', '-2em' ],
+ [ 'left', 'translateX', '2em' ],
+ [ 'left-start', 'translateX', '2em' ],
+ [ 'left-end', 'translateX', '2em' ],
+ ] as PlacementToInitialTranslationTuple[] )(
+ 'for the `%s` placement computes an initial `%s` of `%s',
+ (
+ inputPlacement,
+ expectedTranslationProp,
+ expectedTranslationValue
+ ) => {
+ expect(
+ placementToMotionAnimationProps( inputPlacement )
+ ).toEqual(
+ expect.objectContaining( {
+ initial: expect.objectContaining( {
+ [ expectedTranslationProp ]:
+ expectedTranslationValue,
+ } ),
+ } )
+ );
+ }
+ );
+ } );
+ } );
+} );
diff --git a/packages/components/src/popover/types.ts b/packages/components/src/popover/types.ts
index b80e266c1fe2ce..2f738ca76a3a94 100644
--- a/packages/components/src/popover/types.ts
+++ b/packages/components/src/popover/types.ts
@@ -121,6 +121,7 @@ export type PopoverProps = {
* _Note: this prop is deprecated. Use the `placement` prop instead._
*/
position?:
+ | `${ PositionYAxis }`
| `${ PositionYAxis } ${ PositionXAxis }`
| `${ PositionYAxis } ${ PositionXAxis } ${ PositionCorner }`;
/**
diff --git a/packages/components/src/popover/utils.ts b/packages/components/src/popover/utils.ts
index c5b15a076114fc..f14e2c921f1ede 100644
--- a/packages/components/src/popover/utils.ts
+++ b/packages/components/src/popover/utils.ts
@@ -14,6 +14,62 @@ import type {
PopoverAnchorRefTopBottom,
} from './types';
+const POSITION_TO_PLACEMENT: Record<
+ NonNullable< PopoverProps[ 'position' ] >,
+ NonNullable< PopoverProps[ 'placement' ] >
+> = {
+ bottom: 'bottom',
+ top: 'top',
+ 'middle left': 'left',
+ 'middle right': 'right',
+ 'bottom left': 'bottom-end',
+ 'bottom center': 'bottom',
+ 'bottom right': 'bottom-start',
+ 'top left': 'top-end',
+ 'top center': 'top',
+ 'top right': 'top-start',
+ 'middle left left': 'left',
+ 'middle left right': 'left',
+ 'middle left bottom': 'left-end',
+ 'middle left top': 'left-start',
+ 'middle right left': 'right',
+ 'middle right right': 'right',
+ 'middle right bottom': 'right-end',
+ 'middle right top': 'right-start',
+ 'bottom left left': 'bottom-end',
+ 'bottom left right': 'bottom-end',
+ 'bottom left bottom': 'bottom-end',
+ 'bottom left top': 'bottom-end',
+ 'bottom center left': 'bottom',
+ 'bottom center right': 'bottom',
+ 'bottom center bottom': 'bottom',
+ 'bottom center top': 'bottom',
+ 'bottom right left': 'bottom-start',
+ 'bottom right right': 'bottom-start',
+ 'bottom right bottom': 'bottom-start',
+ 'bottom right top': 'bottom-start',
+ 'top left left': 'top-end',
+ 'top left right': 'top-end',
+ 'top left bottom': 'top-end',
+ 'top left top': 'top-end',
+ 'top center left': 'top',
+ 'top center right': 'top',
+ 'top center bottom': 'top',
+ 'top center top': 'top',
+ 'top right left': 'top-start',
+ 'top right right': 'top-start',
+ 'top right bottom': 'top-start',
+ 'top right top': 'top-start',
+ // `middle`/`middle center [corner?]` positions are associated to a fallback
+ // `bottom` placement because there aren't any corresponding placement values.
+ middle: 'bottom',
+ 'middle center': 'bottom',
+ 'middle center bottom': 'bottom',
+ 'middle center left': 'bottom',
+ 'middle center right': 'bottom',
+ 'middle center top': 'bottom',
+};
+
/**
* Converts the `Popover`'s legacy "position" prop to the new "placement" prop
* (used by `floating-ui`).
@@ -23,22 +79,8 @@ import type {
*/
export const positionToPlacement = (
position: NonNullable< PopoverProps[ 'position' ] >
-): NonNullable< PopoverProps[ 'placement' ] > => {
- const [ x, y, z ] = position.split( ' ' );
-
- if ( [ 'top', 'bottom' ].includes( x ) ) {
- let suffix = '';
- if ( ( !! z && z === 'left' ) || y === 'right' ) {
- suffix = '-start';
- } else if ( ( !! z && z === 'right' ) || y === 'left' ) {
- suffix = '-end';
- }
-
- return ( x + suffix ) as NonNullable< PopoverProps[ 'placement' ] >;
- }
-
- return y as NonNullable< PopoverProps[ 'placement' ] >;
-};
+): NonNullable< PopoverProps[ 'placement' ] > =>
+ POSITION_TO_PLACEMENT[ position ] ?? 'bottom';
/**
* @typedef AnimationOrigin
diff --git a/packages/components/src/range-control/types.ts b/packages/components/src/range-control/types.ts
index f8ba457ab77f4d..721c5edf4c8bdb 100644
--- a/packages/components/src/range-control/types.ts
+++ b/packages/components/src/range-control/types.ts
@@ -290,39 +290,6 @@ export type UseControlledRangeValueArgs = {
value: number | null;
};
-export type UseDebouncedHoverInteractionArgs = {
- /**
- * A callback function invoked when the element is hidden.
- *
- * @default () => {}
- */
- onHide?: () => void;
- /**
- * A callback function invoked when the mouse is moved out of the element.
- *
- * @default () => {}
- */
- onMouseLeave?: MouseEventHandler< HTMLInputElement >;
- /**
- * A callback function invoked when the mouse is moved.
- *
- * @default () => {}
- */
- onMouseMove?: MouseEventHandler< HTMLInputElement >;
- /**
- * A callback function invoked when the element is shown.
- *
- * @default () => {}
- */
- onShow?: () => void;
- /**
- * Timeout before the element is shown or hidden.
- *
- * @default 300
- */
- timeout?: number;
-};
-
export type UseMarksArgs = NumericProps & {
marks: RangeMarks;
step: number;
diff --git a/packages/components/src/resizable-box/resize-tooltip/utils.ts b/packages/components/src/resizable-box/resize-tooltip/utils.ts
index 54d96a1e6d1d60..7c122c2ebd85ab 100644
--- a/packages/components/src/resizable-box/resize-tooltip/utils.ts
+++ b/packages/components/src/resizable-box/resize-tooltip/utils.ts
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { useEffect, useRef, useState } from '@wordpress/element';
+import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import { useResizeObserver } from '@wordpress/compose';
const noop = () => {};
@@ -84,23 +84,23 @@ export function useResizeLabel( {
*/
const moveTimeoutRef = useRef< number >();
- const unsetMoveXY = () => {
- /*
- * If axis is controlled, we will avoid resetting the moveX and moveY values.
- * This will allow for the preferred axis values to persist in the label.
- */
- if ( isAxisControlled ) return;
- setMoveX( false );
- setMoveY( false );
- };
+ const debounceUnsetMoveXY = useCallback( () => {
+ const unsetMoveXY = () => {
+ /*
+ * If axis is controlled, we will avoid resetting the moveX and moveY values.
+ * This will allow for the preferred axis values to persist in the label.
+ */
+ if ( isAxisControlled ) return;
+ setMoveX( false );
+ setMoveY( false );
+ };
- const debounceUnsetMoveXY = () => {
if ( moveTimeoutRef.current ) {
window.clearTimeout( moveTimeoutRef.current );
}
moveTimeoutRef.current = window.setTimeout( unsetMoveXY, fadeTimeout );
- };
+ }, [ fadeTimeout, isAxisControlled ] );
useEffect( () => {
/*
@@ -143,7 +143,7 @@ export function useResizeLabel( {
onResize( { width, height } );
debounceUnsetMoveXY();
- }, [ width, height ] );
+ }, [ width, height, onResize, debounceUnsetMoveXY ] );
const label = getSizeLabel( {
axis,
diff --git a/packages/components/src/sandbox/index.js b/packages/components/src/sandbox/index.js
index 6bf96696131146..a73df2f640673b 100644
--- a/packages/components/src/sandbox/index.js
+++ b/packages/components/src/sandbox/index.js
@@ -205,32 +205,38 @@ export default function Sandbox( {
setHeight( data.height );
}
- const { ownerDocument } = ref.current;
+ const iframe = ref.current;
+ const { ownerDocument } = iframe;
const { defaultView } = ownerDocument;
// This used to be registered using , but it made the iframe blank
// after reordering the containing block. See these two issues for more details:
// https://github.com/WordPress/gutenberg/issues/6146
// https://github.com/facebook/react/issues/18752
- ref.current.addEventListener( 'load', tryNoForceSandbox, false );
+ iframe.addEventListener( 'load', tryNoForceSandbox, false );
defaultView.addEventListener( 'message', checkMessageForResize );
return () => {
- ref.current?.removeEventListener(
- 'load',
- tryNoForceSandbox,
- false
- );
+ iframe?.removeEventListener( 'load', tryNoForceSandbox, false );
defaultView.addEventListener( 'message', checkMessageForResize );
};
+ // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
+ // See https://github.com/WordPress/gutenberg/pull/44378
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
useEffect( () => {
trySandbox();
+ // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
+ // See https://github.com/WordPress/gutenberg/pull/44378
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ title, styles, scripts ] );
useEffect( () => {
trySandbox( true );
+ // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
+ // See https://github.com/WordPress/gutenberg/pull/44378
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ html, type ] );
return (
diff --git a/packages/components/src/sandbox/index.native.js b/packages/components/src/sandbox/index.native.js
index df5f0138fb95f8..65eb87305fda10 100644
--- a/packages/components/src/sandbox/index.native.js
+++ b/packages/components/src/sandbox/index.native.js
@@ -282,6 +282,9 @@ function Sandbox( {
useEffect( () => {
updateContentHtml();
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ html, title, type, styles, scripts ] );
useEffect( () => {
diff --git a/packages/components/src/search-control/index.native.js b/packages/components/src/search-control/index.native.js
index 2bf19b8a42b54b..6f640f9960a3a4 100644
--- a/packages/components/src/search-control/index.native.js
+++ b/packages/components/src/search-control/index.native.js
@@ -115,6 +115,9 @@ function SearchControl( {
mergeFutureStyles( activeDarkStyles, [ isActive, isDark ] );
setCurrentStyles( futureStyles );
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ isActive, isDark ] );
useEffect( () => {
@@ -130,6 +133,9 @@ function SearchControl( {
clearTimeout( onCancelTimer.current );
keyboardHideSubscription.remove();
};
+ // Disable reason: deferring this refactor to the native team.
+ // see https://github.com/WordPress/gutenberg/pull/41166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
const {
diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-context.js b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-context.js
index 8ea7d2cc55b9a5..cd1576fd19c3ac 100644
--- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-context.js
+++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-context.js
@@ -1,4 +1,8 @@
// @ts-nocheck
+/**
+ * External dependencies
+ */
+import { proxyMap } from 'valtio/utils';
/**
* WordPress dependencies
*/
@@ -6,8 +10,8 @@ import { createContext } from '@wordpress/element';
import warning from '@wordpress/warning';
const SlotFillContext = createContext( {
- slots: {},
- fills: {},
+ slots: proxyMap(),
+ fills: proxyMap(),
registerSlot: () => {
warning(
'Components must be wrapped within `SlotFillProvider`. ' +
diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js
index 0468a4db0b1289..c25b524079063b 100644
--- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js
+++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js
@@ -1,8 +1,14 @@
// @ts-nocheck
+/**
+ * External dependencies
+ */
+import { ref as valRef } from 'valtio';
+import { proxyMap } from 'valtio/utils';
+
/**
* WordPress dependencies
*/
-import { useMemo, useCallback, useState } from '@wordpress/element';
+import { useMemo, useCallback, useRef } from '@wordpress/element';
import isShallowEqual from '@wordpress/is-shallow-equal';
/**
@@ -11,79 +17,68 @@ import isShallowEqual from '@wordpress/is-shallow-equal';
import SlotFillContext from './slot-fill-context';
function useSlotRegistry() {
- const [ slots, setSlots ] = useState( {} );
- const [ fills, setFills ] = useState( {} );
+ const slots = useRef( proxyMap() );
+ const fills = useRef( proxyMap() );
const registerSlot = useCallback( ( name, ref, fillProps ) => {
- setSlots( ( prevSlots ) => {
- const slot = prevSlots[ name ] || {};
- return {
- ...prevSlots,
- [ name ]: {
- ...slot,
- ref: ref || slot.ref,
- fillProps: fillProps || slot.fillProps || {},
- },
- };
- } );
+ const slot = slots.current.get( name ) || {};
+ slots.current.set(
+ name,
+ valRef( {
+ ...slot,
+ ref: ref || slot.ref,
+ fillProps: fillProps || slot.fillProps || {},
+ } )
+ );
}, [] );
const unregisterSlot = useCallback( ( name, ref ) => {
- setSlots( ( prevSlots ) => {
- const { [ name ]: slot, ...nextSlots } = prevSlots;
- // Make sure we're not unregistering a slot registered by another element
- // See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412
- if ( slot?.ref === ref ) {
- return nextSlots;
- }
- return prevSlots;
- } );
+ // Make sure we're not unregistering a slot registered by another element
+ // See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412
+ if ( slots.current.get( name )?.ref === ref ) {
+ slots.current.delete( name );
+ }
}, [] );
- const updateSlot = useCallback(
- ( name, fillProps ) => {
- const slot = slots[ name ];
- if ( ! slot ) {
- return;
- }
- if ( ! isShallowEqual( slot.fillProps, fillProps ) ) {
- slot.fillProps = fillProps;
- const slotFills = fills[ name ];
- if ( slotFills ) {
- // Force update fills.
- slotFills.map( ( fill ) => fill.current.rerender() );
- }
+ const updateSlot = useCallback( ( name, fillProps ) => {
+ const slot = slots.current.get( name );
+ if ( ! slot ) {
+ return;
+ }
+
+ if ( ! isShallowEqual( slot.fillProps, fillProps ) ) {
+ slot.fillProps = fillProps;
+ const slotFills = fills.current.get( name );
+ if ( slotFills ) {
+ // Force update fills.
+ slotFills.map( ( fill ) => fill.current.rerender() );
}
- },
- [ slots, fills ]
- );
+ }
+ }, [] );
const registerFill = useCallback( ( name, ref ) => {
- setFills( ( prevFills ) => ( {
- ...prevFills,
- [ name ]: [ ...( prevFills[ name ] || [] ), ref ],
- } ) );
+ fills.current.set(
+ name,
+ valRef( [ ...( fills.current.get( name ) || [] ), ref ] )
+ );
}, [] );
const unregisterFill = useCallback( ( name, ref ) => {
- setFills( ( prevFills ) => {
- if ( prevFills[ name ] ) {
- return {
- ...prevFills,
- [ name ]: prevFills[ name ].filter(
- ( fillRef ) => fillRef !== ref
- ),
- };
- }
- return prevFills;
- } );
+ if ( fills.current.get( name ) ) {
+ fills.current.set(
+ name,
+ fills.current
+ .get( name )
+ .filter( ( fillRef ) => fillRef !== ref )
+ );
+ }
}, [] );
// Memoizing the return value so it can be directly passed to Provider value
const registry = useMemo(
() => ( {
- slots,
- fills,
+ slots: slots.current,
+ fills: fills.current,
registerSlot,
updateSlot,
unregisterSlot,
@@ -91,8 +86,6 @@ function useSlotRegistry() {
unregisterFill,
} ),
[
- slots,
- fills,
registerSlot,
updateSlot,
unregisterSlot,
diff --git a/packages/components/src/slot-fill/bubbles-virtually/use-slot-fills.js b/packages/components/src/slot-fill/bubbles-virtually/use-slot-fills.js
new file mode 100644
index 00000000000000..29e4380ed3d43d
--- /dev/null
+++ b/packages/components/src/slot-fill/bubbles-virtually/use-slot-fills.js
@@ -0,0 +1,24 @@
+// @ts-nocheck
+/**
+ * External dependencies
+ */
+import { useSnapshot } from 'valtio';
+
+/**
+ * WordPress dependencies
+ */
+import { useContext } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import SlotFillContext from './slot-fill-context';
+
+export default function useSlotFills( name ) {
+ const registry = useContext( SlotFillContext );
+ const fills = useSnapshot( registry.fills, { sync: true } );
+ // The important bit here is that this call ensures that the hook
+ // only causes a re-render if the "fills" of a given slot name
+ // change change, not any fills.
+ return fills.get( name );
+}
diff --git a/packages/components/src/slot-fill/bubbles-virtually/use-slot.js b/packages/components/src/slot-fill/bubbles-virtually/use-slot.js
index c954ad2c7573fe..2d07a2c36ae079 100644
--- a/packages/components/src/slot-fill/bubbles-virtually/use-slot.js
+++ b/packages/components/src/slot-fill/bubbles-virtually/use-slot.js
@@ -1,8 +1,13 @@
// @ts-nocheck
+/**
+ * External dependencies
+ */
+import { useSnapshot } from 'valtio';
+
/**
* WordPress dependencies
*/
-import { useCallback, useContext, useMemo } from '@wordpress/element';
+import { useCallback, useContext } from '@wordpress/element';
/**
* Internal dependencies
@@ -11,10 +16,11 @@ import SlotFillContext from './slot-fill-context';
export default function useSlot( name ) {
const registry = useContext( SlotFillContext );
-
- const slot = registry.slots[ name ] || {};
- const slotFills = registry.fills[ name ];
- const fills = useMemo( () => slotFills || [], [ slotFills ] );
+ const slots = useSnapshot( registry.slots, { sync: true } );
+ // The important bit here is that this call ensures
+ // the hook only causes a re-render if the slot
+ // with the given name change, not any other slot.
+ const slot = slots.get( name );
const updateSlot = useCallback(
( fillProps ) => {
@@ -48,7 +54,6 @@ export default function useSlot( name ) {
...slot,
updateSlot,
unregisterSlot,
- fills,
registerFill,
unregisterFill,
};
diff --git a/packages/components/src/slot-fill/index.js b/packages/components/src/slot-fill/index.js
index 4bb323c28fad61..18aea104677012 100644
--- a/packages/components/src/slot-fill/index.js
+++ b/packages/components/src/slot-fill/index.js
@@ -14,6 +14,7 @@ import BubblesVirtuallySlot from './bubbles-virtually/slot';
import BubblesVirtuallySlotFillProvider from './bubbles-virtually/slot-fill-provider';
import SlotFillProvider from './provider';
import useSlot from './bubbles-virtually/use-slot';
+export { default as useSlotFills } from './bubbles-virtually/use-slot-fills';
export function Fill( props ) {
// We're adding both Fills here so they can register themselves before
diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss
index 2052a40b66f8f7..3c42941e0d7158 100644
--- a/packages/components/src/style.scss
+++ b/packages/components/src/style.scss
@@ -17,7 +17,6 @@
@import "./dropdown/style.scss";
@import "./dropdown-menu/style.scss";
@import "./duotone-picker/style.scss";
-@import "./font-size-picker/style.scss";
@import "./form-toggle/style.scss";
@import "./form-token-field/style.scss";
@import "./guide/style.scss";
diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap
index 519a7702985ce1..51b1f8b9100cf9 100644
--- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap
+++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap
@@ -159,6 +159,7 @@ exports[`ToggleGroupControl should render correctly with icons 1`] = `
}
.emotion-15 {
+ color: #1e1e1e;
width: 30px;
padding-left: 0;
padding-right: 0;
diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
index da2cc709f50454..885ff171eb211f 100644
--- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
+++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
@@ -55,13 +55,6 @@ export const buttonView = css`
}
`;
-export const buttonActive = css`
- color: ${ COLORS.white };
- &:active {
- background: transparent;
- }
-`;
-
export const ButtonContentView = styled.div`
font-size: ${ CONFIG.fontSize };
line-height: 1;
@@ -82,8 +75,17 @@ export const isIcon = ( {
};
return css`
+ color: ${ COLORS.gray[ 900 ] };
width: ${ iconButtonSizes[ size ] };
padding-left: 0;
padding-right: 0;
`;
};
+
+export const buttonActive = css`
+ color: ${ COLORS.white };
+
+ &:active {
+ background: transparent;
+ }
+`;
diff --git a/packages/components/src/tools-panel/stories/index.js b/packages/components/src/tools-panel/stories/index.js
index 803a01eb341d35..b9d317a0fb71f2 100644
--- a/packages/components/src/tools-panel/stories/index.js
+++ b/packages/components/src/tools-panel/stories/index.js
@@ -29,11 +29,13 @@ export const _default = () => {
const [ height, setHeight ] = useState();
const [ minHeight, setMinHeight ] = useState();
const [ width, setWidth ] = useState();
+ const [ scale, setScale ] = useState();
const resetAll = () => {
setHeight( undefined );
setWidth( undefined );
setMinHeight( undefined );
+ setScale( undefined );
};
return (
@@ -79,6 +81,31 @@ export const _default = () => {
onChange={ ( next ) => setMinHeight( next ) }
/>
+ !! scale }
+ label="Scale"
+ onDeselect={ () => setScale( undefined ) }
+ >
+ setScale( next ) }
+ isBlock
+ >
+
+
+
+
+
diff --git a/packages/components/src/tools-panel/styles.ts b/packages/components/src/tools-panel/styles.ts
index 7fe2fc0a0a1a2c..f76bf47ec18c5b 100644
--- a/packages/components/src/tools-panel/styles.ts
+++ b/packages/components/src/tools-panel/styles.ts
@@ -1,6 +1,7 @@
/**
* External dependencies
*/
+import styled from '@emotion/styled';
import { css } from '@emotion/react';
/**
@@ -12,7 +13,7 @@ import {
Wrapper as BaseControlWrapper,
} from '../base-control/styles/base-control-styles';
import { LabelWrapper } from '../input-control/styles/input-control-styles';
-import { COLORS, CONFIG } from '../utils';
+import { COLORS, CONFIG, rtl } from '../utils';
import { space } from '../ui/utils/space';
const toolsPanelGrid = {
@@ -145,3 +146,29 @@ export const ToolsPanelItemPlaceholder = css`
export const DropdownMenu = css`
min-width: 200px;
`;
+
+export const ResetLabel = styled.span`
+ color: var( --wp-admin-theme-color-darker-10 );
+ font-size: 11px;
+ font-weight: 500;
+ line-height: 1.4;
+ ${ rtl( { marginLeft: space( 3 ) } ) }
+ text-transform: uppercase;
+`;
+
+export const DefaultControlsItem = css`
+ color: ${ COLORS.gray[ 900 ] };
+
+ &&[aria-disabled='true'] {
+ color: ${ COLORS.gray[ 700 ] };
+ opacity: 1;
+
+ &:hover {
+ color: ${ COLORS.gray[ 700 ] };
+ }
+
+ ${ ResetLabel } {
+ opacity: 0.3;
+ }
+ }
+`;
diff --git a/packages/components/src/tools-panel/tools-panel-header/component.tsx b/packages/components/src/tools-panel/tools-panel-header/component.tsx
index 62a40a966dcb7d..57416d4d0c311d 100644
--- a/packages/components/src/tools-panel/tools-panel-header/component.tsx
+++ b/packages/components/src/tools-panel/tools-panel-header/component.tsx
@@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react';
* WordPress dependencies
*/
import { speak } from '@wordpress/a11y';
-import { check, reset, moreVertical, plus } from '@wordpress/icons';
+import { check, moreVertical, plus } from '@wordpress/icons';
import { __, _x, sprintf } from '@wordpress/i18n';
/**
@@ -20,12 +20,14 @@ import { HStack } from '../../h-stack';
import { Heading } from '../../heading';
import { useToolsPanelHeader } from './hook';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
+import { ResetLabel } from '../styles';
import type {
ToolsPanelControlsGroupProps,
ToolsPanelHeaderProps,
} from '../types';
const DefaultControlsGroup = ( {
+ itemClassName,
items,
toggleItem,
}: ToolsPanelControlsGroupProps ) => {
@@ -33,15 +35,17 @@ const DefaultControlsGroup = ( {
return null;
}
+ const resetSuffix = { __( 'Reset' ) } ;
+
return (
-
+
{ items.map( ( [ label, hasValue ] ) => {
if ( hasValue ) {
return (
{ label }
@@ -67,8 +72,8 @@ const DefaultControlsGroup = ( {
return (
@@ -89,7 +94,7 @@ const OptionalControlsGroup = ( {
}
return (
-
+
{ items.map( ( [ label, isSelected ] ) => {
const itemLabel = isSelected
? sprintf(
@@ -147,6 +152,7 @@ const ToolsPanelHeader = (
) => {
const {
areAllOptionalControlsHidden,
+ defaultControlsItemClassName,
dropdownMenuClassName,
hasMenuItems,
headingClassName,
@@ -197,6 +203,7 @@ const ToolsPanelHeader = (
{
+ return cx( styles.DefaultControlsItem );
+ }, [ cx ] );
+
const { menuItems, hasMenuItems, areAllOptionalControlsHidden } =
useToolsPanelContext();
return {
...otherProps,
areAllOptionalControlsHidden,
+ defaultControlsItemClassName,
dropdownMenuClassName,
hasMenuItems,
headingClassName,
diff --git a/packages/components/src/tools-panel/types.ts b/packages/components/src/tools-panel/types.ts
index 3290b9fe497fc7..b95a50a4aa9cbc 100644
--- a/packages/components/src/tools-panel/types.ts
+++ b/packages/components/src/tools-panel/types.ts
@@ -147,6 +147,7 @@ export type ToolsPanelContext = {
};
export type ToolsPanelControlsGroupProps = {
+ itemClassName?: string;
items: [ string, boolean ][];
toggleItem: ( label: string ) => void;
};
diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json
index 67c51cc136afa3..5c103f27ead053 100644
--- a/packages/components/tsconfig.json
+++ b/packages/components/tsconfig.json
@@ -47,10 +47,8 @@
"src/color-list-picker",
"src/combobox-control",
"src/custom-gradient-picker",
- "src/custom-select-control",
"src/dimension-control",
"src/duotone-picker",
- "src/font-size-picker",
"src/gradient-picker",
"src/guide",
"src/higher-order/navigate-regions",
diff --git a/packages/compose/README.md b/packages/compose/README.md
index 2c772616baef48..c11f4d76f9a369 100644
--- a/packages/compose/README.md
+++ b/packages/compose/README.md
@@ -161,6 +161,39 @@ _Related_
Given a component returns the enhanced component augmented with a component
only re-rendering when its props/state change
+### throttle
+
+A simplified and properly typed version of lodash's `throttle`, that
+always uses timers instead of sometimes using rAF.
+
+Creates a throttled function that only invokes `func` at most once per
+every `wait` milliseconds. The throttled function comes with a `cancel`
+method to cancel delayed `func` invocations and a `flush` method to
+immediately invoke them. Provide `options` to indicate whether `func`
+should be invoked on the leading and/or trailing edge of the `wait`
+timeout. The `func` is invoked with the last arguments provided to the
+throttled function. Subsequent calls to the throttled function return
+the result of the last `func` invocation.
+
+**Note:** If `leading` and `trailing` options are `true`, `func` is
+invoked on the trailing edge of the timeout only if the throttled function
+is invoked more than once during the `wait` timeout.
+
+If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+until the next tick, similar to `setTimeout` with a timeout of `0`.
+
+_Parameters_
+
+- _func_ `Function`: The function to throttle.
+- _wait_ `number`: The number of milliseconds to throttle invocations to.
+- _options_ `Partial< ThrottleOptions >`: The options object.
+- _options.leading_ `boolean`: Specify invoking on the leading edge of the timeout.
+- _options.trailing_ `boolean`: Specify invoking on the trailing edge of the timeout.
+
+_Returns_
+
+- Returns the new throttled function.
+
### useAsyncList
React hook returns an array which items get asynchronously appended from a source array.
@@ -511,7 +544,7 @@ const App = () => {
### useThrottle
-Throttles a function with Lodash's `throttle`. A new throttled function will
+Throttles a function similar to Lodash's `throttle`. A new throttled function will
be returned and any scheduled calls cancelled if any of the arguments change,
including the function to throttle, so please wrap functions created on
render in components in `useCallback`.
@@ -524,11 +557,11 @@ _Parameters_
- _fn_ `TFunc`: The function to throttle.
- _wait_ `[number]`: The number of milliseconds to throttle invocations to.
-- _options_ `[import('lodash').ThrottleSettings]`: The options object. See linked documentation for details.
+- _options_ `[import('../../utils/throttle').ThrottleOptions]`: The options object. See linked documentation for details.
_Returns_
-- `import('lodash').DebouncedFunc`: Throttled function.
+- `import('../../utils/debounce').DebouncedFunc`: Throttled function.
### useViewportMatch
diff --git a/packages/compose/package.json b/packages/compose/package.json
index 4c3c615b6fa99b..d820ef282d4d12 100644
--- a/packages/compose/package.json
+++ b/packages/compose/package.json
@@ -30,7 +30,6 @@
"sideEffects": false,
"dependencies": {
"@babel/runtime": "^7.16.0",
- "@types/lodash": "^4.14.172",
"@types/mousetrap": "^1.6.8",
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/dom": "file:../dom",
@@ -40,7 +39,6 @@
"@wordpress/priority-queue": "file:../priority-queue",
"change-case": "^4.1.2",
"clipboard": "^2.0.8",
- "lodash": "^4.17.21",
"mousetrap": "^1.6.5",
"use-memo-one": "^1.1.1"
},
diff --git a/packages/compose/src/higher-order/with-global-events/listener.js b/packages/compose/src/higher-order/with-global-events/listener.js
index 881f58bff7af98..4fdf41df3c2bf8 100644
--- a/packages/compose/src/higher-order/with-global-events/listener.js
+++ b/packages/compose/src/higher-order/with-global-events/listener.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { without } from 'lodash';
-
/**
* Class responsible for orchestrating event handling on the global window,
* binding a single event to be shared across all handling instances, and
@@ -27,9 +22,12 @@ class Listener {
}
remove( /** @type {any} */ eventType, /** @type {any} */ instance ) {
- this.listeners[ eventType ] = without(
- this.listeners[ eventType ],
- instance
+ if ( ! this.listeners[ eventType ] ) {
+ return;
+ }
+
+ this.listeners[ eventType ] = this.listeners[ eventType ].filter(
+ ( /** @type {any} */ listener ) => listener !== instance
);
if ( ! this.listeners[ eventType ].length ) {
diff --git a/packages/compose/src/higher-order/with-safe-timeout/index.tsx b/packages/compose/src/higher-order/with-safe-timeout/index.tsx
index 11362b8a410f6b..4056e64ba65e53 100644
--- a/packages/compose/src/higher-order/with-safe-timeout/index.tsx
+++ b/packages/compose/src/higher-order/with-safe-timeout/index.tsx
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { without } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -64,7 +59,7 @@ const withSafeTimeout = createHigherOrderComponent(
clearTimeout( id: number ) {
clearTimeout( id );
- this.timeouts = without( this.timeouts, id );
+ this.timeouts.filter( ( timeoutId ) => timeoutId !== id );
}
render() {
diff --git a/packages/compose/src/hooks/use-disabled/index.js b/packages/compose/src/hooks/use-disabled/index.js
index cf6fb192cf1b13..fa8848046147a7 100644
--- a/packages/compose/src/hooks/use-disabled/index.js
+++ b/packages/compose/src/hooks/use-disabled/index.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { includes } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -89,8 +84,7 @@ export default function useDisabled( {
focus.focusable.find( node ).forEach( ( focusable ) => {
if (
- includes(
- DISABLED_ELIGIBLE_NODE_NAMES,
+ DISABLED_ELIGIBLE_NODE_NAMES.includes(
focusable.nodeName
) &&
// @ts-ignore
diff --git a/packages/compose/src/hooks/use-drop-zone/index.js b/packages/compose/src/hooks/use-drop-zone/index.js
index 6eaaf859a24e66..d6388e09f0bf08 100644
--- a/packages/compose/src/hooks/use-drop-zone/index.js
+++ b/packages/compose/src/hooks/use-drop-zone/index.js
@@ -107,11 +107,6 @@ export default function useDropZone( {
isDragging = true;
- ownerDocument.removeEventListener(
- 'dragenter',
- maybeDragStart
- );
-
// Note that `dragend` doesn't fire consistently for file and
// HTML drag events where the drag origin is outside the browser
// window. In Firefox it may also not fire if the originating
@@ -202,7 +197,6 @@ export default function useDropZone( {
isDragging = false;
- ownerDocument.addEventListener( 'dragenter', maybeDragStart );
ownerDocument.removeEventListener( 'dragend', maybeDragEnd );
ownerDocument.removeEventListener( 'mousemove', maybeDragEnd );
@@ -221,12 +215,6 @@ export default function useDropZone( {
ownerDocument.addEventListener( 'dragenter', maybeDragStart );
return () => {
- onDropRef.current = null;
- onDragStartRef.current = null;
- onDragEnterRef.current = null;
- onDragLeaveRef.current = null;
- onDragEndRef.current = null;
- onDragOverRef.current = null;
delete element.dataset.isDropZone;
element.removeEventListener( 'drop', onDrop );
element.removeEventListener( 'dragenter', onDragEnter );
@@ -234,7 +222,10 @@ export default function useDropZone( {
element.removeEventListener( 'dragleave', onDragLeave );
ownerDocument.removeEventListener( 'dragend', maybeDragEnd );
ownerDocument.removeEventListener( 'mousemove', maybeDragEnd );
- ownerDocument.addEventListener( 'dragenter', maybeDragStart );
+ ownerDocument.removeEventListener(
+ 'dragenter',
+ maybeDragStart
+ );
};
},
[ isDisabled ]
diff --git a/packages/compose/src/hooks/use-focus-outside/index.js b/packages/compose/src/hooks/use-focus-outside/index.js
index a6ab04d3408255..fdccb6ea01330c 100644
--- a/packages/compose/src/hooks/use-focus-outside/index.js
+++ b/packages/compose/src/hooks/use-focus-outside/index.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { includes } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -42,8 +37,7 @@ function isFocusNormalizedButton( eventTarget ) {
return true;
case 'INPUT':
- return includes(
- INPUT_BUTTON_TYPES,
+ return INPUT_BUTTON_TYPES.includes(
/** @type {HTMLInputElement} */ ( eventTarget ).type
);
}
@@ -136,7 +130,7 @@ export default function useFocusOutside( onFocusOutside ) {
*/
const normalizeButtonFocus = useCallback( ( event ) => {
const { type, target } = event;
- const isInteractionEnd = includes( [ 'mouseup', 'touchend' ], type );
+ const isInteractionEnd = [ 'mouseup', 'touchend' ].includes( type );
if ( isInteractionEnd ) {
preventBlurCheck.current = false;
diff --git a/packages/compose/src/hooks/use-focus-outside/index.native.js b/packages/compose/src/hooks/use-focus-outside/index.native.js
index 9339a519b15251..30d3e84bfea3cf 100644
--- a/packages/compose/src/hooks/use-focus-outside/index.native.js
+++ b/packages/compose/src/hooks/use-focus-outside/index.native.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { includes } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -39,8 +34,7 @@ function isFocusNormalizedButton( eventTarget ) {
return true;
case 'INPUT':
- return includes(
- INPUT_BUTTON_TYPES,
+ return INPUT_BUTTON_TYPES.includes(
/** @type {HTMLInputElement} */ ( eventTarget ).type
);
}
@@ -133,7 +127,7 @@ export default function useFocusOutside( onFocusOutside ) {
*/
const normalizeButtonFocus = useCallback( ( event ) => {
const { type, target } = event;
- const isInteractionEnd = includes( [ 'mouseup', 'touchend' ], type );
+ const isInteractionEnd = [ 'mouseup', 'touchend' ].includes( type );
if ( isInteractionEnd ) {
preventBlurCheck.current = false;
diff --git a/packages/compose/src/hooks/use-keyboard-shortcut/index.js b/packages/compose/src/hooks/use-keyboard-shortcut/index.js
index 992f8e4fcc245b..be27d15864633a 100644
--- a/packages/compose/src/hooks/use-keyboard-shortcut/index.js
+++ b/packages/compose/src/hooks/use-keyboard-shortcut/index.js
@@ -3,7 +3,6 @@
*/
import Mousetrap from 'mousetrap';
import 'mousetrap/plugins/global-bind/mousetrap-global-bind';
-import { castArray } from 'lodash';
/**
* WordPress dependencies
@@ -60,7 +59,10 @@ function useKeyboardShortcut(
// necessary to maintain the existing behavior.
/** @type {Element} */ ( /** @type {unknown} */ ( document ) )
);
- castArray( shortcuts ).forEach( ( shortcut ) => {
+ const shortcutsArray = Array.isArray( shortcuts )
+ ? shortcuts
+ : [ shortcuts ];
+ shortcutsArray.forEach( ( shortcut ) => {
const keys = shortcut.split( '+' );
// Determines whether a key is a modifier by the length of the string.
// E.g. if I add a pass a shortcut Shift+Cmd+M, it'll determine that
diff --git a/packages/compose/src/hooks/use-merge-refs/index.js b/packages/compose/src/hooks/use-merge-refs/index.js
index 89b41371f672fe..f39160444c5229 100644
--- a/packages/compose/src/hooks/use-merge-refs/index.js
+++ b/packages/compose/src/hooks/use-merge-refs/index.js
@@ -71,6 +71,7 @@ function assignRef( ref, value ) {
*/
export default function useMergeRefs( refs ) {
const element = useRef();
+ const isAttached = useRef( false );
const didElementChange = useRef( false );
/* eslint-disable jsdoc/no-undefined-types */
/** @type {import('react').MutableRefObject} */
@@ -86,7 +87,10 @@ export default function useMergeRefs( refs ) {
// ref with the node, except when the element changes in the same cycle, in
// which case the ref callbacks will already have been called.
useLayoutEffect( () => {
- if ( didElementChange.current === false ) {
+ if (
+ didElementChange.current === false &&
+ isAttached.current === true
+ ) {
refs.forEach( ( ref, index ) => {
const previousRef = previousRefs.current[ index ];
if ( ref !== previousRef ) {
@@ -113,6 +117,7 @@ export default function useMergeRefs( refs ) {
assignRef( element, value );
didElementChange.current = true;
+ isAttached.current = value !== null;
// When an element changes, the current ref callback should be called
// with the new element and the previous one with `null`.
diff --git a/packages/compose/src/hooks/use-merge-refs/test/index.js b/packages/compose/src/hooks/use-merge-refs/test/index.js
index 6893148462583a..fe73347b8e237f 100644
--- a/packages/compose/src/hooks/use-merge-refs/test/index.js
+++ b/packages/compose/src/hooks/use-merge-refs/test/index.js
@@ -41,6 +41,7 @@ describe( 'useMergeRefs', () => {
tagName: TagName = 'div',
disable1,
disable2,
+ unused,
} ) {
function refCallback1( value ) {
refCallback1.history.push( value );
@@ -63,6 +64,10 @@ describe( 'useMergeRefs', () => {
! disable2 && ref2,
] );
+ if ( unused ) {
+ return ;
+ }
+
return ;
}
@@ -327,4 +332,43 @@ describe( 'useMergeRefs', () => {
[ [], [ originalElement, null ] ],
] );
} );
+
+ it( 'should allow the hook being unused', () => {
+ const rootElement = document.getElementById( 'root' );
+
+ ReactDOM.render( , rootElement );
+
+ const originalElement = rootElement.firstElementChild;
+
+ // Render 1: ref 1 should updated, ref 2 should not.
+ expect( renderCallback.history ).toEqual( [
+ [ [ originalElement ], [] ],
+ ] );
+
+ ReactDOM.render( , rootElement );
+
+ // Render 2: ref 2 should be updated as well.
+ expect( renderCallback.history ).toEqual( [
+ [ [ originalElement, null, originalElement ], [ originalElement ] ],
+ [ [], [] ],
+ ] );
+
+ ReactDOM.render( , rootElement );
+
+ // Render 3: ref 2 should be updated with null
+ expect( renderCallback.history ).toEqual( [
+ [
+ [
+ originalElement,
+ null,
+ originalElement,
+ null,
+ originalElement,
+ ],
+ [ originalElement, null ],
+ ],
+ [ [], [] ],
+ [ [], [] ],
+ ] );
+ } );
} );
diff --git a/packages/compose/src/hooks/use-throttle/index.js b/packages/compose/src/hooks/use-throttle/index.js
index 265669f020b34d..8cade9a8442ac8 100644
--- a/packages/compose/src/hooks/use-throttle/index.js
+++ b/packages/compose/src/hooks/use-throttle/index.js
@@ -1,7 +1,6 @@
/**
* External dependencies
*/
-import { throttle } from 'lodash';
import { useMemoOne } from 'use-memo-one';
/**
@@ -10,7 +9,12 @@ import { useMemoOne } from 'use-memo-one';
import { useEffect } from '@wordpress/element';
/**
- * Throttles a function with Lodash's `throttle`. A new throttled function will
+ * Internal dependencies
+ */
+import { throttle } from '../../utils/throttle';
+
+/**
+ * Throttles a function similar to Lodash's `throttle`. A new throttled function will
* be returned and any scheduled calls cancelled if any of the arguments change,
* including the function to throttle, so please wrap functions created on
* render in components in `useCallback`.
@@ -19,14 +23,14 @@ import { useEffect } from '@wordpress/element';
*
* @template {(...args: any[]) => void} TFunc
*
- * @param {TFunc} fn The function to throttle.
- * @param {number} [wait] The number of milliseconds to throttle invocations to.
- * @param {import('lodash').ThrottleSettings} [options] The options object. See linked documentation for details.
- * @return {import('lodash').DebouncedFunc} Throttled function.
+ * @param {TFunc} fn The function to throttle.
+ * @param {number} [wait] The number of milliseconds to throttle invocations to.
+ * @param {import('../../utils/throttle').ThrottleOptions} [options] The options object. See linked documentation for details.
+ * @return {import('../../utils/debounce').DebouncedFunc} Throttled function.
*/
export default function useThrottle( fn, wait, options ) {
const throttled = useMemoOne(
- () => throttle( fn, wait, options ),
+ () => throttle( fn, wait ?? 0, options ),
[ fn, wait, options ]
);
useEffect( () => () => throttled.cancel(), [ throttled ] );
diff --git a/packages/compose/src/index.js b/packages/compose/src/index.js
index 3bd751005d9e01..01b08000bee205 100644
--- a/packages/compose/src/index.js
+++ b/packages/compose/src/index.js
@@ -2,6 +2,8 @@
export * from './utils/create-higher-order-component';
// The `debounce` helper and its types.
export * from './utils/debounce';
+// The `throttle` helper and its types.
+export * from './utils/throttle';
// The `compose` and `pipe` helpers (inspired by `flowRight` and `flow` from Lodash).
export { default as compose } from './higher-order/compose';
diff --git a/packages/compose/src/index.native.js b/packages/compose/src/index.native.js
index 2d91e6e906137b..c495c394a6897a 100644
--- a/packages/compose/src/index.native.js
+++ b/packages/compose/src/index.native.js
@@ -2,6 +2,8 @@
export * from './utils/create-higher-order-component';
// The `debounce` helper and its types.
export * from './utils/debounce';
+// The `throttle` helper and its types.
+export * from './utils/throttle';
// The `compose` and `pipe` helpers (inspired by `flowRight` and `flow` from Lodash).
export { default as compose } from './higher-order/compose';
diff --git a/packages/compose/src/utils/throttle/index.ts b/packages/compose/src/utils/throttle/index.ts
new file mode 100644
index 00000000000000..ec8878e2385922
--- /dev/null
+++ b/packages/compose/src/utils/throttle/index.ts
@@ -0,0 +1,95 @@
+/**
+ * Parts of this source were derived and modified from lodash,
+ * released under the MIT license.
+ *
+ * https://github.com/lodash/lodash
+ *
+ * Copyright JS Foundation and other contributors
+ *
+ * Based on Underscore.js, copyright Jeremy Ashkenas,
+ * DocumentCloud and Investigative Reporters & Editors
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision history
+ * available at https://github.com/lodash/lodash
+ *
+ * The following license applies to all parts of this software except as
+ * documented below:
+ *
+ * ====
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Internal dependencies
+ */
+import { debounce } from '../debounce';
+
+export interface ThrottleOptions {
+ leading?: boolean;
+ trailing?: boolean;
+}
+
+/**
+ * A simplified and properly typed version of lodash's `throttle`, that
+ * always uses timers instead of sometimes using rAF.
+ *
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed `func` invocations and a `flush` method to
+ * immediately invoke them. Provide `options` to indicate whether `func`
+ * should be invoked on the leading and/or trailing edge of the `wait`
+ * timeout. The `func` is invoked with the last arguments provided to the
+ * throttled function. Subsequent calls to the throttled function return
+ * the result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the throttled function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * @param {Function} func The function to throttle.
+ * @param {number} wait The number of milliseconds to throttle invocations to.
+ * @param {Partial< ThrottleOptions >} options The options object.
+ * @param {boolean} options.leading Specify invoking on the leading edge of the timeout.
+ * @param {boolean} options.trailing Specify invoking on the trailing edge of the timeout.
+ * @return Returns the new throttled function.
+ */
+export const throttle = < FunctionT extends ( ...args: unknown[] ) => unknown >(
+ func: FunctionT,
+ wait: number,
+ options?: ThrottleOptions
+) => {
+ let leading = true;
+ let trailing = true;
+
+ if ( options ) {
+ leading = 'leading' in options ? !! options.leading : leading;
+ trailing = 'trailing' in options ? !! options.trailing : trailing;
+ }
+ return debounce( func, wait, {
+ leading,
+ trailing,
+ maxWait: wait,
+ } );
+};
diff --git a/packages/compose/src/utils/throttle/test/index.ts b/packages/compose/src/utils/throttle/test/index.ts
new file mode 100644
index 00000000000000..66669c1dc8dda0
--- /dev/null
+++ b/packages/compose/src/utils/throttle/test/index.ts
@@ -0,0 +1,256 @@
+/**
+ * Internal dependencies
+ */
+import { throttle } from '../index';
+
+const identity = ( value ) => value;
+
+describe( 'throttle', () => {
+ beforeEach( () => {
+ jest.useFakeTimers();
+ } );
+
+ afterEach( () => {
+ jest.useRealTimers();
+ } );
+
+ it( 'should throttle a function', () => {
+ let callCount = 0;
+ const throttled = throttle( function () {
+ callCount++;
+ }, 32 );
+
+ throttled();
+ throttled();
+ throttled();
+
+ const lastCount = callCount;
+ expect( callCount ).toBeGreaterThan( 0 );
+
+ jest.advanceTimersByTime( 64 );
+
+ expect( callCount ).toBeGreaterThan( lastCount );
+ } );
+
+ it( 'should return the result of the first call on subsequent calls', () => {
+ const throttled = throttle( identity, 32 );
+ let results = [ throttled( 'a' ), throttled( 'b' ) ];
+
+ expect( results ).toStrictEqual( [ 'a', 'a' ] );
+
+ jest.advanceTimersByTime( 64 );
+
+ results = [ throttled( 'c' ), throttled( 'd' ) ];
+ expect( results[ 0 ] ).not.toBe( 'a' );
+ expect( results[ 0 ] ).not.toBe( undefined );
+
+ expect( results[ 1 ] ).not.toBe( 'd' );
+ expect( results[ 1 ] ).not.toBe( undefined );
+ } );
+
+ it( 'should clear timeout when `func` is called', () => {
+ let callCount = 0;
+ let dateCount = 0;
+
+ const globalDateNow = global.Date.now;
+ global.Date.now = function () {
+ return ++dateCount === 5 ? Infinity : +new Date();
+ };
+
+ const throttled = throttle( () => {
+ callCount++;
+ }, 32 );
+
+ throttled();
+ throttled();
+
+ jest.advanceTimersByTime( 64 );
+
+ expect( callCount ).toBe( 2 );
+ global.Date.now = globalDateNow;
+ } );
+
+ it( 'should not trigger a trailing call when invoked once', () => {
+ let callCount = 0;
+ const throttled = throttle( () => {
+ callCount++;
+ }, 32 );
+
+ throttled();
+ expect( callCount ).toBe( 1 );
+
+ jest.advanceTimersByTime( 64 );
+
+ expect( callCount ).toBe( 1 );
+ } );
+
+ [ true, false ].forEach( ( leading ) => {
+ it(
+ 'should trigger a call when invoked repeatedly' +
+ ( ! leading ? ' and `leading` is `false`' : '' ),
+ () => {
+ let callCount = 0;
+ const limit = 320;
+ const options = leading ? {} : { leading: false };
+ const throttled = throttle(
+ () => {
+ callCount++;
+ },
+ 32,
+ options
+ );
+
+ const start = Date.now();
+ while ( Date.now() - start < limit ) {
+ throttled();
+ jest.advanceTimersByTime( 1 );
+ }
+ const actual = callCount;
+
+ jest.advanceTimersByTime( 1 );
+
+ expect( actual ).toBeGreaterThan( 1 );
+ }
+ );
+ } );
+
+ it( 'should trigger a second throttled call as soon as possible', () => {
+ let callCount = 0;
+
+ const throttled = throttle(
+ () => {
+ callCount++;
+ },
+ 128,
+ { leading: false }
+ );
+
+ throttled();
+
+ jest.advanceTimersByTime( 192 );
+
+ expect( callCount ).toBe( 1 );
+ throttled();
+
+ jest.advanceTimersByTime( 64 );
+
+ expect( callCount ).toBe( 1 );
+
+ jest.advanceTimersByTime( 130 );
+
+ expect( callCount ).toBe( 2 );
+ } );
+
+ it( 'should apply default options', () => {
+ let callCount = 0;
+ const throttled = throttle(
+ () => {
+ callCount++;
+ },
+ 32,
+ {}
+ );
+
+ throttled();
+ throttled();
+ expect( callCount ).toBe( 1 );
+
+ jest.advanceTimersByTime( 128 );
+
+ expect( callCount ).toBe( 2 );
+ } );
+
+ it( 'should support a `leading` option', () => {
+ const withLeading = throttle( identity, 32, { leading: true } );
+ expect( withLeading( 'a' ) ).toBe( 'a' );
+
+ const withoutLeading = throttle( identity, 32, { leading: false } );
+ expect( withoutLeading( 'a' ) ).toBeUndefined();
+ } );
+
+ it( 'should support a `trailing` option', () => {
+ let withCount = 0;
+ let withoutCount = 0;
+
+ const withTrailing = throttle(
+ ( value ) => {
+ withCount++;
+ return value;
+ },
+ 64,
+ { trailing: true }
+ );
+
+ const withoutTrailing = throttle(
+ ( value ) => {
+ withoutCount++;
+ return value;
+ },
+ 64,
+ { trailing: false }
+ );
+
+ expect( withTrailing( 'a' ) ).toBe( 'a' );
+ expect( withTrailing( 'b' ) ).toBe( 'a' );
+
+ expect( withoutTrailing( 'a' ) ).toBe( 'a' );
+ expect( withoutTrailing( 'b' ) ).toBe( 'a' );
+
+ jest.advanceTimersByTime( 256 );
+
+ expect( withCount ).toBe( 2 );
+ expect( withoutCount ).toBe( 1 );
+ } );
+
+ it( 'should not update `lastCalled`, at the end of the timeout, when `trailing` is `false`', () => {
+ let callCount = 0;
+
+ const throttled = throttle(
+ function () {
+ callCount++;
+ },
+ 64,
+ { trailing: false }
+ );
+
+ throttled();
+ throttled();
+
+ jest.advanceTimersByTime( 96 );
+
+ throttled();
+ throttled();
+
+ jest.advanceTimersByTime( 96 );
+
+ expect( callCount ).toBeGreaterThan( 1 );
+ } );
+
+ it( 'should work with a system time of `0`', () => {
+ let callCount = 0;
+ let dateCount = 0;
+
+ const globalDateNow = global.Date.now;
+ global.Date.now = function () {
+ return ++dateCount < 4 ? 0 : +new Date();
+ };
+
+ const throttled = throttle( ( value ) => {
+ callCount++;
+ return value;
+ }, 32 );
+
+ const results = [
+ throttled( 'a' ),
+ throttled( 'b' ),
+ throttled( 'c' ),
+ ];
+ expect( results ).toStrictEqual( [ 'a', 'a', 'a' ] );
+ expect( callCount ).toBe( 1 );
+
+ jest.advanceTimersByTime( 64 );
+
+ expect( callCount ).toBe( 2 );
+ global.Date.now = globalDateNow;
+ } );
+} );
diff --git a/packages/core-data/src/hooks/use-entity-records.ts b/packages/core-data/src/hooks/use-entity-records.ts
index c9b64bd5b4144e..b92b38e4182dbe 100644
--- a/packages/core-data/src/hooks/use-entity-records.ts
+++ b/packages/core-data/src/hooks/use-entity-records.ts
@@ -9,15 +9,26 @@ import deprecated from '@wordpress/deprecated';
*/
import useQuerySelect from './use-query-select';
import { store as coreStore } from '../';
-import type { Options, EntityRecordResolution } from './use-entity-record';
+import type { Options } from './use-entity-record';
+import type { Status } from './constants';
-type EntityRecordsResolution< RecordType > = Omit<
- EntityRecordResolution< RecordType >,
- 'record'
-> & {
+interface EntityRecordsResolution< RecordType > {
/** The requested entity record */
records: RecordType[] | null;
-};
+
+ /**
+ * Is the record still being resolved?
+ */
+ isResolving: boolean;
+
+ /**
+ * Is the record resolved by now?
+ */
+ hasResolved: boolean;
+
+ /** Resolution status */
+ status: Status;
+}
const EMPTY_ARRAY = [];
diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts
index 79309d84fb98b1..4151a94824acb5 100644
--- a/packages/core-data/src/selectors.ts
+++ b/packages/core-data/src/selectors.ts
@@ -221,6 +221,55 @@ export function getEntityConfig(
return find( state.entities.config, { kind, name } );
}
+/**
+ * GetEntityRecord is declared as a *callable interface* with
+ * two signatures to work around the fact that TypeScript doesn't
+ * allow currying generic functions:
+ *
+ * ```ts
+ * type CurriedState = F extends ( state: any, ...args: infer P ) => infer R
+ * ? ( ...args: P ) => R
+ * : F;
+ * type Selector = (
+ * state: any,
+ * kind: K,
+ * key: K extends string ? 'string value' : false
+ * ) => K;
+ * type BadlyInferredSignature = CurriedState< Selector >
+ * // BadlyInferredSignature evaluates to:
+ * // (kind: string number, key: false | "string value") => string number
+ * ```
+ *
+ * The signature without the state parameter shipped as CurriedSignature
+ * is used in the return value of `select( coreStore )`.
+ *
+ * See https://github.com/WordPress/gutenberg/pull/41578 for more details.
+ */
+export interface GetEntityRecord {
+ <
+ EntityRecord extends
+ | ET.EntityRecord< any >
+ | Partial< ET.EntityRecord< any > >
+ >(
+ state: State,
+ kind: string,
+ name: string,
+ key: EntityRecordKey,
+ query?: GetRecordsHttpQuery
+ ): EntityRecord | undefined;
+
+ CurriedSignature: <
+ EntityRecord extends
+ | ET.EntityRecord< any >
+ | Partial< ET.EntityRecord< any > >
+ >(
+ kind: string,
+ name: string,
+ key: EntityRecordKey,
+ query?: GetRecordsHttpQuery
+ ) => EntityRecord | undefined;
+}
+
/**
* Returns the Entity's record object by key. Returns `null` if the value is not
* yet received, undefined if the value entity is known to not exist, or the
@@ -236,7 +285,7 @@ export function getEntityConfig(
* @return Record.
*/
export const getEntityRecord = createSelector(
- <
+ ( <
EntityRecord extends
| ET.EntityRecord< any >
| Partial< ET.EntityRecord< any > >
@@ -279,7 +328,7 @@ export const getEntityRecord = createSelector(
}
return item;
- },
+ } ) as GetEntityRecord,
( state: State, kind, name, recordId, query ) => {
const context = query?.context ?? 'default';
return [
@@ -301,7 +350,7 @@ export const getEntityRecord = createSelector(
] ),
];
}
-);
+) as GetEntityRecord;
/**
* Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity records from the API if the entity record isn't available in the local state.
@@ -414,6 +463,37 @@ export function hasEntityRecords(
return Array.isArray( getEntityRecords( state, kind, name, query ) );
}
+/**
+ * GetEntityRecord is declared as a *callable interface* with
+ * two signatures to work around the fact that TypeScript doesn't
+ * allow currying generic functions.
+ *
+ * @see GetEntityRecord
+ * @see https://github.com/WordPress/gutenberg/pull/41578
+ */
+export interface GetEntityRecords {
+ <
+ EntityRecord extends
+ | ET.EntityRecord< any >
+ | Partial< ET.EntityRecord< any > >
+ >(
+ state: State,
+ kind: string,
+ name: string,
+ query?: GetRecordsHttpQuery
+ ): EntityRecord[] | null;
+
+ CurriedSignature: <
+ EntityRecord extends
+ | ET.EntityRecord< any >
+ | Partial< ET.EntityRecord< any > >
+ >(
+ kind: string,
+ name: string,
+ query?: GetRecordsHttpQuery
+ ) => EntityRecord[] | null;
+}
+
/**
* Returns the Entity's records.
*
@@ -425,7 +505,7 @@ export function hasEntityRecords(
*
* @return Records.
*/
-export const getEntityRecords = <
+export const getEntityRecords = ( <
EntityRecord extends
| ET.EntityRecord< any >
| Partial< ET.EntityRecord< any > >
@@ -433,7 +513,7 @@ export const getEntityRecords = <
state: State,
kind: string,
name: string,
- query?: GetRecordsHttpQuery
+ query: GetRecordsHttpQuery
): EntityRecord[] | null => {
// Queried data state is prepopulated for all known entities. If this is not
// assigned for the given parameters, then it is known to not exist.
@@ -446,7 +526,7 @@ export const getEntityRecords = <
return null;
}
return getQueriedItems( queriedState, query );
-};
+} ) as GetEntityRecords;
type DirtyEntityRecord = {
title: string;
diff --git a/packages/create-block/docs/toc.json b/packages/create-block/docs/toc.json
index ea5faab5ec63ae..185a9dd7b11c9b 100644
--- a/packages/create-block/docs/toc.json
+++ b/packages/create-block/docs/toc.json
@@ -1,6 +1,6 @@
[
{
- "title": "@wordpress/create-block External Template",
+ "title": "External Project Templates",
"slug": "packages-create-block-external-template",
"markdown_source": "../packages/create-block/docs/external-template.md",
"parent": "packages-create-block"
diff --git a/packages/data/src/types.ts b/packages/data/src/types.ts
index 0e1b9d7618957e..fe7d9061d3c5d8 100644
--- a/packages/data/src/types.ts
+++ b/packages/data/src/types.ts
@@ -77,22 +77,75 @@ export type CurriedSelectorsOf< S > = S extends StoreDescriptor<
: never;
/**
- * Removes the first argument from a function
+ * Removes the first argument from a function.
*
- * This is designed to remove the `state` parameter from
+ * By default, it removes the `state` parameter from
* registered selectors since that argument is supplied
* by the editor when calling `select(…)`.
*
* For functions with no arguments, which some selectors
* are free to define, returns the original function.
+ *
+ * It is possible to manually provide a custom curried signature
+ * and avoid the automatic inference. When the
+ * F generic argument passed to this helper extends the
+ * SelectorWithCustomCurrySignature type, the F['CurriedSignature']
+ * property is used verbatim.
+ *
+ * This is useful because TypeScript does not correctly remove
+ * arguments from complex function signatures constrained by
+ * interdependent generic parameters.
+ * For more context, see https://github.com/WordPress/gutenberg/pull/41578
*/
-export type CurriedState< F > = F extends (
- state: any,
- ...args: infer P
-) => infer R
+type CurriedState< F > = F extends SelectorWithCustomCurrySignature
+ ? F[ 'CurriedSignature' ]
+ : F extends ( state: any, ...args: infer P ) => infer R
? ( ...args: P ) => R
: F;
+/**
+ * Utility to manually specify curried selector signatures.
+ *
+ * It comes handy when TypeScript can't automatically produce the
+ * correct curried function signature. For example:
+ *
+ * ```ts
+ * type BadlyInferredSignature = CurriedState<
+ * (
+ * state: any,
+ * kind: K,
+ * key: K extends string ? 'one value' : false
+ * ) => K
+ * >
+ * // BadlyInferredSignature evaluates to:
+ * // (kind: string number, key: false "one value") => string number
+ * ```
+ *
+ * With SelectorWithCustomCurrySignature, we can provide a custom
+ * signature and avoid relying on TypeScript inference:
+ * ```ts
+ * interface MySelectorSignature extends SelectorWithCustomCurrySignature {
+ * (
+ * state: any,
+ * kind: K,
+ * key: K extends string ? 'one value' : false
+ * ): K;
+ *
+ * CurriedSignature: (
+ * kind: K,
+ * key: K extends string ? 'one value' : false
+ * ): K;
+ * }
+ * type CorrectlyInferredSignature = CurriedState
+ * // (kind: K, key: K extends string ? 'one value' : false): K;
+ *
+ * For even more context, see https://github.com/WordPress/gutenberg/pull/41578
+ * ```
+ */
+export interface SelectorWithCustomCurrySignature {
+ CurriedSignature: Function;
+}
+
export interface DataRegistry {
register: ( store: StoreDescriptor< any > ) => void;
}
diff --git a/packages/docgen/lib/get-type-annotation.js b/packages/docgen/lib/get-type-annotation.js
index c03c3104fd040c..6bf65cc27465a3 100644
--- a/packages/docgen/lib/get-type-annotation.js
+++ b/packages/docgen/lib/get-type-annotation.js
@@ -405,18 +405,24 @@ function unwrapWrappedSelectors( token ) {
return token;
}
+ if ( babelTypes.isTSAsExpression( token ) ) {
+ // ( ( state, queryId ) => state.queries[ queryId ] ) as any;
+ // \------------------------------------------------/ CallExpression.expression
+ return unwrapWrappedSelectors( token.expression );
+ }
+
if ( babelTypes.isCallExpression( token ) ) {
// createSelector( ( state, queryId ) => state.queries[ queryId ] );
// \--------------------------------------------/ CallExpression.arguments[0]
if ( token.callee.name === 'createSelector' ) {
- return token.arguments[ 0 ];
+ return unwrapWrappedSelectors( token.arguments[ 0 ] );
}
// createRegistrySelector( ( selector ) => ( state, queryId ) => select( 'core/queries' ).get( queryId ) );
// \-----------------------------------------------------------/ CallExpression.arguments[0].body
// \---------------------------------------------------------------------------/ CallExpression.arguments[0]
if ( token.callee.name === 'createRegistrySelector' ) {
- return token.arguments[ 0 ].body;
+ return unwrapWrappedSelectors( token.arguments[ 0 ].body );
}
}
}
diff --git a/packages/docgen/test/get-type-annotation.js b/packages/docgen/test/get-type-annotation.js
index 13ff923f229906..fdf114dfd1f674 100644
--- a/packages/docgen/test/get-type-annotation.js
+++ b/packages/docgen/test/get-type-annotation.js
@@ -394,46 +394,53 @@ describe( 'Type annotations', () => {
} );
describe( 'statically-wrapped function exceptions', () => {
- it( 'should find types for inner function with `createSelector`', () => {
- const { tokens } = engine(
- 'test.ts',
- `/**
- * Returns the number of things
- *
- * @param state - stores all the things
- */
- export const getCount = createSelector( ( state: string[] ) => state.length );
- `
+ const getStateArgType = ( code ) => {
+ const { tokens } = engine( 'test.ts', code );
+ return getTypeAnnotation(
+ { tag: 'param', name: 'state' },
+ tokens[ 0 ],
+ 0
);
+ };
- expect(
- getTypeAnnotation(
- { tag: 'param', name: 'state' },
- tokens[ 0 ],
- 0
- )
- ).toBe( 'string[]' );
+ const docString = `/**
+ * Returns the number of things
+ *
+ * @param state - stores all the things
+ */`;
+ it( 'should find types for a typecasted function', () => {
+ const code = `${ docString }
+ export const getCount = ( state: string[] ) => state.length;
+ `;
+ expect( getStateArgType( code ) ).toBe( 'string[]' );
} );
- it( 'should find types for inner function with `createRegistrySelector`', () => {
- const { tokens } = engine(
- 'test.ts',
- `/**
- * Returns the number of things
- *
- * @param state - stores all the things
- */
- export const getCount = createRegistrySelector( ( select ) => ( state: number ) => state );
- `
- );
+ it( 'should find types for a doubly typecasted function', () => {
+ const code = `${ docString }
+ export const getCount = ( ( state: string[] ) => state.length ) as any as any;
+ `;
+ expect( getStateArgType( code ) ).toBe( 'string[]' );
+ } );
- expect(
- getTypeAnnotation(
- { tag: 'param', name: 'state' },
- tokens[ 0 ],
- 0
- )
- ).toBe( 'number' );
+ it( 'should find types for inner function with `createSelector`', () => {
+ const code = `${ docString }
+ export const getCount = createSelector( ( state: string[] ) => state.length );
+ `;
+ expect( getStateArgType( code ) ).toBe( 'string[]' );
+ } );
+
+ it( 'should find types for inner typecasted function with `createSelector`', () => {
+ const code = `${ docString }
+ export const getCount = createSelector( (( state: string[] ) => state.length) as any );
+ `;
+ expect( getStateArgType( code ) ).toBe( 'string[]' );
+ } );
+
+ it( 'should find types for inner function with `createRegistrySelector`', () => {
+ const code = `${ docString }
+ export const getCount = createRegistrySelector( ( select ) => ( state: number ) => state );
+ `;
+ expect( getStateArgType( code ) ).toBe( 'number' );
} );
} );
} );
diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json
index 432bf50989e4d6..d168c7d70afbc4 100644
--- a/packages/e2e-test-utils-playwright/package.json
+++ b/packages/e2e-test-utils-playwright/package.json
@@ -35,7 +35,8 @@
"@wordpress/keycodes": "file:../keycodes",
"@wordpress/url": "file:../url",
"change-case": "^4.1.2",
- "form-data": "^4.0.0"
+ "form-data": "^4.0.0",
+ "mime": "^3.0.0"
},
"peerDependencies": {
"@playwright/test": ">=1"
diff --git a/packages/e2e-test-utils-playwright/src/page-utils/drag-files.ts b/packages/e2e-test-utils-playwright/src/page-utils/drag-files.ts
new file mode 100644
index 00000000000000..f8e237e7e37f1d
--- /dev/null
+++ b/packages/e2e-test-utils-playwright/src/page-utils/drag-files.ts
@@ -0,0 +1,159 @@
+/**
+ * External dependencies
+ */
+import { readFile } from 'fs/promises';
+import { basename } from 'path';
+import { getType } from 'mime';
+
+/**
+ * Internal dependencies
+ */
+import type { PageUtils } from './index';
+
+type FileObject = {
+ name: string;
+ mimeType?: string;
+ buffer: Buffer;
+};
+
+type Options = {
+ position?: { x: number; y: number };
+};
+
+/**
+ * Simulate dragging files from outside the current page.
+ *
+ * @param this
+ * @param files The files to be dragged.
+ * @return The methods of the drag operation.
+ */
+async function dragFiles(
+ this: PageUtils,
+ files: string | string[] | FileObject | FileObject[]
+) {
+ const filesList = Array.isArray( files ) ? files : [ files ];
+ const fileObjects = await Promise.all(
+ filesList.map( async ( filePathOrObject ) => {
+ if ( typeof filePathOrObject !== 'string' ) {
+ return {
+ name: filePathOrObject.name,
+ mimeType:
+ filePathOrObject.mimeType ||
+ getType( filePathOrObject.name ),
+ base64: filePathOrObject.buffer.toString( 'base64' ),
+ };
+ }
+ const base64 = await readFile( filePathOrObject, 'base64' );
+ const name = basename( filePathOrObject );
+ return {
+ name,
+ mimeType: getType( filePathOrObject ),
+ base64,
+ };
+ } )
+ );
+
+ const dataTransfer = await this.page.evaluateHandle(
+ async ( _fileObjects ) => {
+ const dt = new DataTransfer();
+ const fileInstances = await Promise.all(
+ _fileObjects.map( async ( fileObject ) => {
+ const blob = await fetch(
+ `data:${ fileObject.mimeType };base64,${ fileObject.base64 }`
+ ).then( ( res ) => res.blob() );
+ return new File( [ blob ], fileObject.name, {
+ type: fileObject.mimeType ?? undefined,
+ } );
+ } )
+ );
+
+ fileInstances.forEach( ( file ) => {
+ dt.items.add( file );
+ } );
+
+ return dt;
+ },
+ fileObjects
+ );
+
+ // CDP doesn't actually support dragging files, this is only a _good enough_
+ // dummy data so that it will correctly send the relevant events.
+ const dragData = {
+ items: fileObjects.map( ( fileObject ) => ( {
+ mimeType: fileObject.mimeType ?? 'File',
+ data: fileObject.base64,
+ } ) ),
+ files: fileObjects.map( ( fileObject ) => fileObject.name ),
+ // Copy = 1, Link = 2, Move = 16.
+ dragOperationsMask: 1,
+ };
+
+ const cdpSession = await this.context.newCDPSession( this.page );
+
+ const position = {
+ x: 0,
+ y: 0,
+ };
+
+ return {
+ /**
+ * Drag the files over an element (fires `dragenter` and `dragover` events).
+ *
+ * @param selector A selector to search for an element.
+ * @param options The optional options.
+ * @param options.position A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the element.
+ */
+ dragOver: async ( selector: string, options: Options = {} ) => {
+ const boundingBox = await this.page
+ .locator( selector )
+ .boundingBox();
+
+ if ( ! boundingBox ) {
+ throw new Error(
+ 'Cannot find the element or the element is not visible on the viewport.'
+ );
+ }
+
+ position.x =
+ boundingBox.x +
+ ( options.position?.x ?? boundingBox.width / 2 );
+ position.y =
+ boundingBox.y +
+ ( options.position?.y ?? boundingBox.height / 2 );
+
+ await cdpSession.send( 'Input.dispatchDragEvent', {
+ type: 'dragEnter',
+ ...position,
+ data: dragData,
+ } );
+ await cdpSession.send( 'Input.dispatchDragEvent', {
+ type: 'dragOver',
+ ...position,
+ data: dragData,
+ } );
+ },
+
+ /**
+ * Drop the files at the current position.
+ */
+ drop: async () => {
+ const topMostElement = await this.page.evaluateHandle(
+ ( { x, y } ) => {
+ return document.elementFromPoint( x, y );
+ },
+ position
+ );
+ const elementHandle = topMostElement.asElement();
+
+ if ( ! elementHandle ) {
+ throw new Error( 'Element not found.' );
+ }
+
+ await elementHandle.dispatchEvent( 'drop', { dataTransfer } );
+
+ await cdpSession.detach();
+ },
+ };
+}
+
+export { dragFiles };
diff --git a/packages/e2e-test-utils-playwright/src/page-utils/index.ts b/packages/e2e-test-utils-playwright/src/page-utils/index.ts
index d147365fe5e0e8..95d64a022e22e2 100644
--- a/packages/e2e-test-utils-playwright/src/page-utils/index.ts
+++ b/packages/e2e-test-utils-playwright/src/page-utils/index.ts
@@ -6,6 +6,7 @@ import type { Browser, Page, BrowserContext } from '@playwright/test';
/**
* Internal dependencies
*/
+import { dragFiles } from './drag-files';
import { isCurrentURL } from './is-current-url';
import {
setClipboardData,
@@ -29,6 +30,7 @@ class PageUtils {
this.browser = this.context.browser()!;
}
+ dragFiles = dragFiles.bind( this );
isCurrentURL = isCurrentURL.bind( this );
pressKeyTimes = pressKeyTimes.bind( this );
pressKeyWithModifier = pressKeyWithModifier.bind( this );
diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md
index 68dc23f6f02aab..5bd2d284cc342e 100644
--- a/packages/e2e-test-utils/CHANGELOG.md
+++ b/packages/e2e-test-utils/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Bug Fixes
+
+- Don't use hardcoded login credentials when requesting nonce ([#44331](https://github.com/WordPress/gutenberg/pull/44331)).
+
## 8.2.0 (2022-09-21)
## 8.0.0 (2022-08-24)
diff --git a/packages/e2e-test-utils/src/rest-api.js b/packages/e2e-test-utils/src/rest-api.js
index 60dae7745051d0..b19b332f2e6962 100644
--- a/packages/e2e-test-utils/src/rest-api.js
+++ b/packages/e2e-test-utils/src/rest-api.js
@@ -12,7 +12,7 @@ import apiFetch from '@wordpress/api-fetch';
/**
* Internal dependencies
*/
-import { WP_BASE_URL } from './shared/config';
+import { WP_BASE_URL, WP_USERNAME, WP_PASSWORD } from './shared/config';
import { createURL } from './create-url';
// `apiFetch` expects `window.fetch` to be available in its default handler.
@@ -37,8 +37,8 @@ Link header: ${ links }` );
async function login( retries = 3 ) {
const formData = new FormData();
- formData.append( 'log', 'admin' );
- formData.append( 'pwd', 'password' );
+ formData.append( 'log', WP_USERNAME );
+ formData.append( 'pwd', WP_PASSWORD );
// Login to admin using fetch.
const loginResponse = await fetch( createURL( 'wp-login.php' ), {
diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md
index 8e07a04983a73e..9a68936b6b68ea 100644
--- a/packages/e2e-tests/CHANGELOG.md
+++ b/packages/e2e-tests/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### New features
+
+- Added Autocomplete Component e2e test suite. [#42905](https://github.com/WordPress/gutenberg/pull/42905).
+
## 5.2.0 (2022-09-21)
## 5.0.0 (2022-08-24)
diff --git a/packages/e2e-tests/plugins/class-test-widget.php b/packages/e2e-tests/plugins/class-test-widget.php
index 11ce978257fe46..12b1d2f34a6fa4 100644
--- a/packages/e2e-tests/plugins/class-test-widget.php
+++ b/packages/e2e-tests/plugins/class-test-widget.php
@@ -14,7 +14,7 @@ class Test_Widget extends WP_Widget {
/**
* Sets up a new test widget instance.
*/
- function __construct() {
+ public function __construct() {
parent::__construct(
'test_widget',
'Test Widget',
diff --git a/packages/e2e-tests/plugins/test-autocompleter.php b/packages/e2e-tests/plugins/test-autocompleter.php
new file mode 100644
index 00000000000000..7b1125d44894a7
--- /dev/null
+++ b/packages/e2e-tests/plugins/test-autocompleter.php
@@ -0,0 +1,27 @@
+ `${ option.visual } ${ option.name }`,
+ // Declares that options should be matched by their name
+ getOptionKeywords: ( option ) => [ option.name ],
+ // Declares that the Grapes option is disabled
+ isOptionDisabled: ( option ) => option.name === 'Grapes',
+ // Declares completions should be inserted as abbreviations
+ getOptionCompletion: ( option ) => (
+ option.visual
+ ),
+ };
+
+ function duplicateUserMentions( completers ) {
+ const [ users ] = completers.filter(
+ ( completer ) => completer.name === 'users'
+ );
+ return {
+ ...users,
+ name: 'users-copy',
+ triggerPrefix: '+',
+ getOptionCompletion: ( user ) => `+${ user.slug }`,
+ };
+ }
+
+ function appendTestCompleters( completers, blockName ) {
+ const copiedUsers = duplicateUserMentions( completers );
+ return blockName === 'core/paragraph'
+ ? [ ...completers, fruits, copiedUsers ]
+ : completers;
+ }
+
+ // Adding the filter with a priority of 11
+ // to ensure it fires after the default user mentions are added.
+ wp.hooks.addFilter(
+ 'editor.Autocomplete.completers',
+ 'editor/autocompleters/test',
+ appendTestCompleters,
+ 11
+ );
+})()
diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/iframed-block.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/iframed-block.test.js.snap
deleted file mode 100644
index a4efcd222188ef..00000000000000
--- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/iframed-block.test.js.snap
+++ /dev/null
@@ -1,7 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`changing image size should load script and dependencies in iframe 1`] = `
-"
-Iframed Block (saved)
-"
-`;
diff --git a/packages/e2e-tests/specs/editor/plugins/iframed-block.test.js b/packages/e2e-tests/specs/editor/plugins/iframed-block.test.js
deleted file mode 100644
index 4107cbe5352f7b..00000000000000
--- a/packages/e2e-tests/specs/editor/plugins/iframed-block.test.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * WordPress dependencies
- */
-import {
- activatePlugin,
- createNewPost,
- deactivatePlugin,
- insertBlock,
- getEditedPostContent,
- canvas,
- createNewTemplate,
-} from '@wordpress/e2e-test-utils';
-
-describe( 'changing image size', () => {
- beforeEach( async () => {
- await activatePlugin( 'gutenberg-test-iframed-block' );
- await createNewPost( { postType: 'page' } );
- } );
-
- afterEach( async () => {
- await deactivatePlugin( 'gutenberg-test-iframed-block' );
- } );
-
- it( 'should load script and dependencies in iframe', async () => {
- await insertBlock( 'Iframed Block' );
-
- expect( await getEditedPostContent() ).toMatchSnapshot();
-
- const element = await page.waitForSelector(
- '.wp-block-test-iframed-block'
- );
- const text = await element.evaluate( ( el ) => el.textContent );
-
- expect( text ).toBe( 'Iframed Block (set with jQuery)' );
-
- await createNewTemplate( 'Iframed Test' );
-
- const iframeElement = await canvas().waitForSelector(
- '.wp-block-test-iframed-block'
- );
- const iframedText = await iframeElement.evaluate(
- ( el ) => el.textContent
- );
-
- // Expect the script to load in the iframe, which replaces the block
- // text.
- expect( iframedText ).toBe( 'Iframed Block (set with jQuery)' );
- } );
-} );
diff --git a/packages/e2e-tests/specs/editor/various/mentions.test.js b/packages/e2e-tests/specs/editor/various/mentions.test.js
deleted file mode 100644
index 458449a1b30d4e..00000000000000
--- a/packages/e2e-tests/specs/editor/various/mentions.test.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * WordPress dependencies
- */
-import {
- clickBlockAppender,
- createNewPost,
- createUser,
- deleteUser,
- getEditedPostContent,
- pressKeyTimes,
-} from '@wordpress/e2e-test-utils';
-
-describe( 'autocomplete mentions', () => {
- beforeAll( async () => {
- await createUser( 'testuser', { firstName: 'Jane', lastName: 'Doe' } );
- } );
-
- beforeEach( async () => {
- await createNewPost();
- } );
-
- afterAll( async () => {
- await deleteUser( 'testuser' );
- } );
-
- it( 'should insert mention', async () => {
- await clickBlockAppender();
- await page.keyboard.type( 'I am @a' );
- await page.waitForSelector( '.components-autocomplete__result' );
- await page.keyboard.press( 'Enter' );
- await page.keyboard.type( '.' );
- expect( await getEditedPostContent() ).toMatchInlineSnapshot( `
- "
- I am @admin.
- "
- ` );
- } );
-
- it( 'should insert mention between two other words', async () => {
- await clickBlockAppender();
- await page.keyboard.type( 'Stuck in the middle with you.' );
- await pressKeyTimes( 'ArrowLeft', 'you.'.length );
- await page.keyboard.type( '@j' );
- await page.waitForSelector( '.components-autocomplete__result' );
- await page.keyboard.press( 'Enter' );
- await page.keyboard.type( ' ' );
- expect( await getEditedPostContent() ).toMatchInlineSnapshot( `
- "
- Stuck in the middle with @testuser you.
- "
- ` );
- } );
-
- it( 'should insert two subsequent mentions', async () => {
- await clickBlockAppender();
- await page.keyboard.type( 'I am @j' );
- await page.waitForSelector( '.components-autocomplete__result' );
- await page.keyboard.press( 'Enter' );
- await page.keyboard.type( ' @a' );
- await page.waitForSelector( '.components-autocomplete__result' );
- await page.keyboard.press( 'Enter' );
- await page.keyboard.type( '.' );
- expect( await getEditedPostContent() ).toMatchInlineSnapshot( `
- "
- I am @testuser @admin.
- "
- ` );
- } );
-} );
diff --git a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js
index 8340d2546e778d..925d179bc2e1bd 100644
--- a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js
+++ b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js
@@ -363,9 +363,8 @@ describe( 'Reusable blocks', () => {
const quoteBlock = await page.waitForSelector(
'.block-editor-block-list__block[aria-label="Block: Quote"]'
);
- await quoteBlock.click();
// Select the quote block.
- await page.keyboard.press( 'ArrowDown' );
+ await quoteBlock.focus();
await openDocumentSettingsSidebar();
await page.waitForXPath(
'//*[@role="region"][@aria-label="Editor settings"]//button[.="Styles"]'
diff --git a/packages/edit-post/src/components/header/main-dashboard-button/index.js b/packages/edit-post/src/components/header/main-dashboard-button/index.js
index efc3bfaad19e87..0878a7cce49012 100644
--- a/packages/edit-post/src/components/header/main-dashboard-button/index.js
+++ b/packages/edit-post/src/components/header/main-dashboard-button/index.js
@@ -2,7 +2,7 @@
* WordPress dependencies
*/
import {
- __experimentalUseSlot as useSlot,
+ __experimentalUseSlotFills as useSlotFills,
createSlotFill,
} from '@wordpress/components';
@@ -13,8 +13,8 @@ const { Fill, Slot: MainDashboardButtonSlot } = createSlotFill( slotName );
const MainDashboardButton = Fill;
const Slot = ( { children } ) => {
- const slot = useSlot( slotName );
- const hasFills = Boolean( slot.fills && slot.fills.length );
+ const fills = useSlotFills( slotName );
+ const hasFills = Boolean( fills && fills.length );
if ( ! hasFills ) {
return children;
diff --git a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/__snapshots__/index.js.snap b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/__snapshots__/index.js.snap
index c74f2d35c38212..5a057456d06aca 100644
--- a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/__snapshots__/index.js.snap
+++ b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/__snapshots__/index.js.snap
@@ -1,3 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`PluginPostPublishPanel renders fill properly 1`] = `" My panel titleMy panel content
"`;
+exports[`PluginPostPublishPanel renders fill properly 1`] = `
+
+
+
+
+
+
+
+
+
+ My panel title
+
+
+ My panel content
+
+
+`;
diff --git a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/index.js b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/index.js
index d140251917559f..7f650eeff3818c 100644
--- a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/index.js
+++ b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/test/index.js
@@ -1,8 +1,12 @@
+/**
+ * External dependencies
+ */
+import { render } from '@testing-library/react';
+
/**
* WordPress dependencies
*/
import { SlotFillProvider } from '@wordpress/components';
-import { render } from '@wordpress/element';
/**
* Internal dependencies
@@ -11,8 +15,7 @@ import PluginPostPublishPanel from '../';
describe( 'PluginPostPublishPanel', () => {
test( 'renders fill properly', () => {
- const div = document.createElement( 'div' );
- render(
+ const { container } = render(
{
My panel content
- ,
- div
+
);
- expect( div.innerHTML ).toMatchSnapshot();
+ expect( container ).toMatchSnapshot();
} );
} );
diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js
index 8f6d54f064c38b..239a33ea51bcc5 100644
--- a/packages/edit-post/src/components/visual-editor/index.js
+++ b/packages/edit-post/src/components/visual-editor/index.js
@@ -28,6 +28,8 @@ import {
__unstableUseMouseMoveTypingReset as useMouseMoveTypingReset,
__unstableIframe as Iframe,
__experimentalRecursionProvider as RecursionProvider,
+ __experimentaluseLayoutClasses as useLayoutClasses,
+ __experimentaluseLayoutStyles as useLayoutStyles,
} from '@wordpress/block-editor';
import { useEffect, useRef, useMemo } from '@wordpress/element';
import { Button, __unstableMotion as motion } from '@wordpress/components';
@@ -35,6 +37,7 @@ import { useSelect, useDispatch } from '@wordpress/data';
import { useMergeRefs } from '@wordpress/compose';
import { arrowLeft } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
+import { parse } from '@wordpress/blocks';
/**
* Internal dependencies
@@ -82,11 +85,37 @@ function MaybeIframe( {
);
}
+/**
+ * Given an array of nested blocks, find the first Post Content
+ * block inside it, recursing through any nesting levels.
+ *
+ * @param {Array} blocks A list of blocks.
+ *
+ * @return {Object} The Post Content block.
+ */
+function findPostContent( blocks ) {
+ for ( let i = 0; i < blocks.length; i++ ) {
+ if ( blocks[ i ].name === 'core/post-content' ) {
+ return blocks[ i ];
+ }
+ if ( blocks[ i ].innerBlocks.length ) {
+ const nestedPostContent = findPostContent(
+ blocks[ i ].innerBlocks
+ );
+
+ if ( nestedPostContent ) {
+ return nestedPostContent;
+ }
+ }
+ }
+}
+
export default function VisualEditor( { styles } ) {
const {
deviceType,
isWelcomeGuideVisible,
isTemplateMode,
+ editedPostTemplate = {},
wrapperBlockName,
wrapperUniqueId,
} = useSelect( ( select ) => {
@@ -94,8 +123,10 @@ export default function VisualEditor( { styles } ) {
isFeatureActive,
isEditingTemplate,
__experimentalGetPreviewDeviceType,
+ getEditedPostTemplate,
} = select( editPostStore );
- const { getCurrentPostId, getCurrentPostType } = select( editorStore );
+ const { getCurrentPostId, getCurrentPostType, getEditorSettings } =
+ select( editorStore );
const _isTemplateMode = isEditingTemplate();
let _wrapperBlockName;
@@ -105,10 +136,17 @@ export default function VisualEditor( { styles } ) {
_wrapperBlockName = 'core/post-content';
}
+ const supportsTemplateMode = getEditorSettings().supportsTemplateMode;
+
return {
deviceType: __experimentalGetPreviewDeviceType(),
isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ),
isTemplateMode: _isTemplateMode,
+ // Post template fetch returns a 404 on classic themes, which
+ // messes with e2e tests, so we check it's a block theme first.
+ editedPostTemplate: supportsTemplateMode
+ ? getEditedPostTemplate()
+ : {},
wrapperBlockName: _wrapperBlockName,
wrapperUniqueId: getCurrentPostId(),
};
@@ -122,7 +160,6 @@ export default function VisualEditor( { styles } ) {
themeHasDisabledLayoutStyles,
themeSupportsLayout,
assets,
- useRootPaddingAwareAlignments,
isFocusMode,
} = useSelect( ( select ) => {
const _settings = select( blockEditorStore ).getSettings();
@@ -130,8 +167,6 @@ export default function VisualEditor( { styles } ) {
themeHasDisabledLayoutStyles: _settings.disableLayoutStyles,
themeSupportsLayout: _settings.supportsLayout,
assets: _settings.__unstableResolvedAssets,
- useRootPaddingAwareAlignments:
- _settings.__experimentalFeatures?.useRootPaddingAwareAlignments,
isFocusMode: _settings.focusMode,
};
}, [] );
@@ -154,7 +189,7 @@ export default function VisualEditor( { styles } ) {
borderBottom: 0,
};
const resizedCanvasStyles = useResizeCanvas( deviceType, isTemplateMode );
- const defaultLayout = useSetting( 'layout' );
+ const globalLayoutSettings = useSetting( 'layout' );
const previewMode = 'is-' + deviceType.toLowerCase() + '-preview';
let animatedStyles = isTemplateMode
@@ -183,7 +218,9 @@ export default function VisualEditor( { styles } ) {
const blockSelectionClearerRef = useBlockSelectionClearer();
- const layout = useMemo( () => {
+ // fallbackLayout is used if there is no Post Content,
+ // and for Post Title.
+ const fallbackLayout = useMemo( () => {
if ( isTemplateMode ) {
return { type: 'default' };
}
@@ -191,17 +228,65 @@ export default function VisualEditor( { styles } ) {
if ( themeSupportsLayout ) {
// We need to ensure support for wide and full alignments,
// so we add the constrained type.
- return { ...defaultLayout, type: 'constrained' };
+ return { ...globalLayoutSettings, type: 'constrained' };
}
// Set default layout for classic themes so all alignments are supported.
return { type: 'default' };
- }, [ isTemplateMode, themeSupportsLayout, defaultLayout ] );
+ }, [ isTemplateMode, themeSupportsLayout, globalLayoutSettings ] );
+
+ const postContentBlock = useMemo( () => {
+ // When in template editing mode, we can access the blocks directly.
+ if ( editedPostTemplate?.blocks ) {
+ return findPostContent( editedPostTemplate?.blocks );
+ }
+ // If there are no blocks, we have to parse the content string.
+ // Best double-check it's a string otherwise the parse function gets unhappy.
+ const parseableContent =
+ typeof editedPostTemplate?.content === 'string'
+ ? editedPostTemplate?.content
+ : '';
- const blockListLayoutClass = classnames( {
- 'is-layout-constrained': themeSupportsLayout,
- 'is-layout-flow': ! themeSupportsLayout,
- 'has-global-padding': useRootPaddingAwareAlignments,
- } );
+ return findPostContent( parse( parseableContent ) ) || {};
+ }, [ editedPostTemplate?.content, editedPostTemplate?.blocks ] );
+
+ const postContentLayoutClasses = useLayoutClasses( postContentBlock );
+
+ const blockListLayoutClass = classnames(
+ {
+ 'is-layout-flow': ! themeSupportsLayout,
+ },
+ themeSupportsLayout && postContentLayoutClasses
+ );
+
+ const postContentLayoutStyles = useLayoutStyles(
+ postContentBlock,
+ '.block-editor-block-list__layout.is-root-container'
+ );
+
+ const layout = postContentBlock?.attributes?.layout || {};
+
+ // Update type for blocks using legacy layouts.
+ const postContentLayout = useMemo( () => {
+ return layout &&
+ ( layout?.type === 'constrained' ||
+ layout?.inherit ||
+ layout?.contentSize ||
+ layout?.wideSize )
+ ? { ...globalLayoutSettings, ...layout, type: 'constrained' }
+ : { ...globalLayoutSettings, ...layout, type: 'default' };
+ }, [
+ layout?.type,
+ layout?.inherit,
+ layout?.contentSize,
+ layout?.wideSize,
+ globalLayoutSettings,
+ ] );
+
+ // If there is a Post Content block we use its layout for the block list;
+ // if not, this must be a classic theme, in which case we use the fallback layout.
+ const blockListLayout = postContentBlock
+ ? postContentLayout
+ : fallbackLayout;
const titleRef = useRef();
useEffect( () => {
@@ -257,13 +342,24 @@ export default function VisualEditor( { styles } ) {
{ themeSupportsLayout &&
! themeHasDisabledLayoutStyles &&
! isTemplateMode && (
-
+ <>
+
+ { postContentLayoutStyles && (
+
+ ) }
+ >
) }
{ ! isTemplateMode && (
diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js
index d489456f31b7bf..5b7c4e01ead7b1 100644
--- a/packages/edit-post/src/index.js
+++ b/packages/edit-post/src/index.js
@@ -80,22 +80,6 @@ export function initializeEditor(
settings,
initialEdits
) {
- // Prevent adding template part in the post editor.
- // Only add the filter when the post editor is initialized, not imported.
- addFilter(
- 'blockEditor.__unstableCanInsertBlockType',
- 'removeTemplatePartsFromInserter',
- ( can, blockType ) => {
- if (
- ! select( editPostStore ).isEditingTemplate() &&
- blockType.name === 'core/template-part'
- ) {
- return false;
- }
- return can;
- }
- );
-
const target = document.getElementById( id );
const reboot = reinitializeEditor.bind(
null,
@@ -137,6 +121,26 @@ export function initializeEditor(
} );
}
+ /*
+ * Prevent adding template part in the post editor.
+ * Only add the filter when the post editor is initialized, not imported.
+ * Also only add the filter(s) after registerCoreBlocks()
+ * so that common filters in the block library are not overwritten.
+ */
+ addFilter(
+ 'blockEditor.__unstableCanInsertBlockType',
+ 'removeTemplatePartsFromInserter',
+ ( canInsert, blockType ) => {
+ if (
+ ! select( editPostStore ).isEditingTemplate() &&
+ blockType.name === 'core/template-part'
+ ) {
+ return false;
+ }
+ return canInsert;
+ }
+ );
+
// Show a console log warning if the browser is not in Standards rendering mode.
const documentMode =
document.compatMode === 'CSS1Compat' ? 'Standards' : 'Quirks';
diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss
index 1c9e1d182eef21..fdb4b0c136abf0 100644
--- a/packages/edit-post/src/style.scss
+++ b/packages/edit-post/src/style.scss
@@ -98,3 +98,17 @@ body.block-editor-page {
}
@include wordpress-admin-schemes();
+
+// The edit-site package adds or removes the sidebar when it's opened or closed.
+// The edit-post package, however, always has the sidebar in the canvas.
+// These edit-post specific rules ensures there isn't a border on the right of
+// the canvas when a sidebar is visually closed.
+.interface-interface-skeleton__sidebar {
+ border-left: none;
+
+ .is-sidebar-opened & {
+ @include break-medium() {
+ border-left: $border-width solid $gray-200;
+ }
+ }
+}
diff --git a/packages/edit-site/src/components/block-editor/resizable-editor.js b/packages/edit-site/src/components/block-editor/resizable-editor.js
index c309e65a49d204..2e76b5a2a1e983 100644
--- a/packages/edit-site/src/components/block-editor/resizable-editor.js
+++ b/packages/edit-site/src/components/block-editor/resizable-editor.js
@@ -57,38 +57,14 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
useEffect(
function autoResizeIframeHeight() {
- const iframe = iframeRef.current;
-
- if ( ! iframe || ! enableResizing ) {
+ if ( ! iframeRef.current || ! enableResizing ) {
return;
}
- let timeoutId = null;
-
- function resizeHeight() {
- if ( ! timeoutId ) {
- // Throttle the updates on timeout. This code previously
- // used `requestAnimationFrame`, but that seems to not
- // always work before an iframe is ready.
- timeoutId = iframe.contentWindow.setTimeout( () => {
- const { readyState } = iframe.contentDocument;
-
- // Continue deferring the timeout until the document is ready.
- // Only then will it have a height.
- if (
- readyState !== 'interactive' &&
- readyState !== 'complete'
- ) {
- resizeHeight();
- return;
- }
-
- setHeight( iframe.contentDocument.body.scrollHeight );
- timeoutId = null;
-
- // 30 frames per second.
- }, 1000 / 30 );
- }
+ const iframe = iframeRef.current;
+
+ function setFrameHeight() {
+ setHeight( iframe.contentDocument.body.scrollHeight );
}
let resizeObserver;
@@ -97,28 +73,23 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
resizeObserver?.disconnect();
resizeObserver = new iframe.contentWindow.ResizeObserver(
- resizeHeight
+ setFrameHeight
);
// Observe the body, since the `html` element seems to always
// have a height of `100%`.
resizeObserver.observe( iframe.contentDocument.body );
-
- resizeHeight();
+ setFrameHeight();
}
- // This is only required in Firefox for some unknown reasons.
iframe.addEventListener( 'load', registerObserver );
- // This is required in Chrome and Safari.
- registerObserver();
return () => {
- iframe.contentWindow?.clearTimeout( timeoutId );
resizeObserver?.disconnect();
iframe.removeEventListener( 'load', registerObserver );
};
},
- [ enableResizing ]
+ [ enableResizing, iframeRef.current ]
);
const resizeWidthBy = useCallback( ( deltaPixels ) => {
diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js
index dd7bff6fd2ee6e..d29a04638b275a 100644
--- a/packages/edit-site/src/components/global-styles/palette.js
+++ b/packages/edit-site/src/components/global-styles/palette.js
@@ -68,11 +68,15 @@ function Palette( { name } ) {
}
>
- { colors.slice( 0, 5 ).map( ( { color } ) => (
-
-
-
- ) ) }
+ { colors
+ .slice( 0, 5 )
+ .map( ( { color }, index ) => (
+
+
+
+ ) ) }
{ paletteButtonText }
diff --git a/packages/edit-site/src/components/global-styles/preview.js b/packages/edit-site/src/components/global-styles/preview.js
index a424da638da2b5..0fd3e578cfaa0e 100644
--- a/packages/edit-site/src/components/global-styles/preview.js
+++ b/packages/edit-site/src/components/global-styles/preview.js
@@ -79,13 +79,13 @@ const StylesPreview = ( { label, isFocused } ) => {
)
.slice( 0, 2 );
- // Reset leaked styles from WP common.css and remove main content layout padding.
+ // Reset leaked styles from WP common.css and remove main content layout padding and border.
const editorStyles = useMemo( () => {
if ( styles ) {
return [
...styles,
{
- css: 'body{min-width: 0;padding: 0;}',
+ css: 'body{min-width: 0;padding: 0;border: none;}',
isGlobalStyles: true,
},
];
diff --git a/packages/edit-site/src/components/global-styles/screen-typography-element.js b/packages/edit-site/src/components/global-styles/screen-typography-element.js
index a14801c43a3b0e..76d7d6de5df90d 100644
--- a/packages/edit-site/src/components/global-styles/screen-typography-element.js
+++ b/packages/edit-site/src/components/global-styles/screen-typography-element.js
@@ -2,12 +2,19 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
+import {
+ __experimentalToggleGroupControl as ToggleGroupControl,
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
+ __experimentalSpacer as Spacer,
+} from '@wordpress/components';
+import { useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import TypographyPanel from './typography-panel';
import ScreenHeader from './header';
+import TypographyPreview from './typography-preview';
const elements = {
text: {
@@ -29,13 +36,70 @@ const elements = {
};
function ScreenTypographyElement( { name, element } ) {
+ const [ headingLevel, setHeadingLevel ] = useState( 'heading' );
+
return (
<>
-
+
+
+
+ { element === 'heading' && (
+
+
+
+
+
+
+
+
+
+
+
+ ) }
+
>
);
}
diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss
index 1f203c348b25ec..fabc0fa9b40233 100644
--- a/packages/edit-site/src/components/global-styles/style.scss
+++ b/packages/edit-site/src/components/global-styles/style.scss
@@ -11,7 +11,7 @@
display: block;
}
-.edit-site-typography-panel__preview {
+.edit-site-typography-preview {
display: flex;
align-items: center;
justify-content: center;
@@ -46,7 +46,7 @@
.component-color-indicator {
// Show a diagonal line (crossed out) for empty swatches.
- background: linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
+ background: $white linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
flex-shrink: 0;
}
}
@@ -97,7 +97,7 @@
}
&:focus .edit-site-global-styles-variations_item-preview {
- border: var(--wp-admin-theme-color) $border-width solid;
+ border: var(--wp-admin-theme-color) var(--wp-admin-border-width-focus) solid;
}
}
diff --git a/packages/edit-site/src/components/global-styles/typography-panel.js b/packages/edit-site/src/components/global-styles/typography-panel.js
index f4c77abf0fd71d..a632f532a174f4 100644
--- a/packages/edit-site/src/components/global-styles/typography-panel.js
+++ b/packages/edit-site/src/components/global-styles/typography-panel.js
@@ -9,25 +9,25 @@ import {
__experimentalTextTransformControl as TextTransformControl,
} from '@wordpress/block-editor';
import {
- PanelBody,
FontSizePicker,
- __experimentalToggleGroupControl as ToggleGroupControl,
- __experimentalToggleGroupControlOption as ToggleGroupControlOption,
- __experimentalGrid as Grid,
+ __experimentalToolsPanel as ToolsPanel,
+ __experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-import { useState } from '@wordpress/element';
+
/**
* Internal dependencies
*/
import { getSupportedGlobalStylesPanels, useSetting, useStyle } from './hooks';
export function useHasTypographyPanel( name ) {
+ const hasFontFamily = useHasFontFamilyControl( name );
const hasLineHeight = useHasLineHeightControl( name );
const hasFontAppearance = useHasAppearanceControl( name );
const hasLetterSpacing = useHasLetterSpacingControl( name );
const supports = getSupportedGlobalStylesPanels( name );
return (
+ hasFontFamily ||
hasLineHeight ||
hasFontAppearance ||
hasLetterSpacing ||
@@ -35,6 +35,12 @@ export function useHasTypographyPanel( name ) {
);
}
+function useHasFontFamilyControl( name ) {
+ const supports = getSupportedGlobalStylesPanels( name );
+ const [ fontFamilies ] = useSetting( 'typography.fontFamilies', name );
+ return supports.includes( 'fontFamily' ) && !! fontFamilies?.length;
+}
+
function useHasLineHeightControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
@@ -54,6 +60,23 @@ function useHasAppearanceControl( name ) {
return hasFontStyles || hasFontWeights;
}
+function useAppearanceControlLabel( name ) {
+ const supports = getSupportedGlobalStylesPanels( name );
+ const hasFontStyles =
+ useSetting( 'typography.fontStyle', name )[ 0 ] &&
+ supports.includes( 'fontStyle' );
+ const hasFontWeights =
+ useSetting( 'typography.fontWeight', name )[ 0 ] &&
+ supports.includes( 'fontWeight' );
+ if ( ! hasFontStyles ) {
+ return __( 'Font weight' );
+ }
+ if ( ! hasFontWeights ) {
+ return __( 'Font style' );
+ }
+ return __( 'Appearance' );
+}
+
function useHasLetterSpacingControl( name, element ) {
const setting = useSetting( 'typography.letterSpacing', name )[ 0 ];
if ( ! setting ) {
@@ -78,12 +101,53 @@ function useHasTextTransformControl( name, element ) {
return supports.includes( 'textTransform' );
}
-export default function TypographyPanel( { name, element } ) {
- const [ selectedLevel, setCurrentTab ] = useState( 'heading' );
+function useStyleWithReset( path, blockName ) {
+ const [ style, setStyle ] = useStyle( path, blockName );
+ const [ userStyle ] = useStyle( path, blockName, 'user' );
+ const hasStyle = () => !! userStyle;
+ const resetStyle = () => setStyle( undefined );
+ return [ style, setStyle, hasStyle, resetStyle ];
+}
+
+function useFontAppearance( prefix, name ) {
+ const [ fontStyle, setFontStyle ] = useStyle(
+ prefix + 'typography.fontStyle',
+ name
+ );
+ const [ userFontStyle ] = useStyle(
+ prefix + 'typography.fontStyle',
+ name,
+ 'user'
+ );
+ const [ fontWeight, setFontWeight ] = useStyle(
+ prefix + 'typography.fontWeight',
+ name
+ );
+ const [ userFontWeight ] = useStyle(
+ prefix + 'typography.fontWeight',
+ name,
+ 'user'
+ );
+ const hasFontAppearance = () => !! userFontStyle || !! userFontWeight;
+ const resetFontAppearance = () => {
+ setFontStyle( undefined );
+ setFontWeight( undefined );
+ };
+ return {
+ fontStyle,
+ setFontStyle,
+ fontWeight,
+ setFontWeight,
+ hasFontAppearance,
+ resetFontAppearance,
+ };
+}
+
+export default function TypographyPanel( { name, element, headingLevel } ) {
const supports = getSupportedGlobalStylesPanels( name );
let prefix = '';
if ( element === 'heading' ) {
- prefix = `elements.${ selectedLevel }.`;
+ prefix = `elements.${ headingLevel }.`;
} else if ( element && element !== 'text' ) {
prefix = `elements.${ element }.`;
}
@@ -99,142 +163,99 @@ export default function TypographyPanel( { name, element } ) {
const hasFontWeights =
useSetting( 'typography.fontWeight', name )[ 0 ] &&
supports.includes( 'fontWeight' );
+ const hasFontFamilyEnabled = useHasFontFamilyControl( name );
const hasLineHeightEnabled = useHasLineHeightControl( name );
const hasAppearanceControl = useHasAppearanceControl( name );
+ const appearanceControlLabel = useAppearanceControlLabel( name );
const hasLetterSpacingControl = useHasLetterSpacingControl( name, element );
const hasTextTransformControl = useHasTextTransformControl( name, element );
/* Disable font size controls when the option to style all headings is selected. */
let hasFontSizeEnabled = supports.includes( 'fontSize' );
- if ( element === 'heading' && selectedLevel === 'heading' ) {
+ if ( element === 'heading' && headingLevel === 'heading' ) {
hasFontSizeEnabled = false;
}
- const [ fontFamily, setFontFamily ] = useStyle(
- prefix + 'typography.fontFamily',
- name
- );
- const [ fontSize, setFontSize ] = useStyle(
- prefix + 'typography.fontSize',
- name
- );
+ const [ fontFamily, setFontFamily, hasFontFamily, resetFontFamily ] =
+ useStyleWithReset( prefix + 'typography.fontFamily', name );
+ const [ fontSize, setFontSize, hasFontSize, resetFontSize ] =
+ useStyleWithReset( prefix + 'typography.fontSize', name );
+ const {
+ fontStyle,
+ setFontStyle,
+ fontWeight,
+ setFontWeight,
+ hasFontAppearance,
+ resetFontAppearance,
+ } = useFontAppearance( prefix, name );
+ const [ lineHeight, setLineHeight, hasLineHeight, resetLineHeight ] =
+ useStyleWithReset( prefix + 'typography.lineHeight', name );
+ const [
+ letterSpacing,
+ setLetterSpacing,
+ hasLetterSpacing,
+ resetLetterSpacing,
+ ] = useStyleWithReset( prefix + 'typography.letterSpacing', name );
+ const [
+ textTransform,
+ setTextTransform,
+ hasTextTransform,
+ resetTextTransform,
+ ] = useStyleWithReset( prefix + 'typography.textTransform', name );
- const [ fontStyle, setFontStyle ] = useStyle(
- prefix + 'typography.fontStyle',
- name
- );
- const [ fontWeight, setFontWeight ] = useStyle(
- prefix + 'typography.fontWeight',
- name
- );
- const [ lineHeight, setLineHeight ] = useStyle(
- prefix + 'typography.lineHeight',
- name
- );
- const [ letterSpacing, setLetterSpacing ] = useStyle(
- prefix + 'typography.letterSpacing',
- name
- );
- const [ textTransform, setTextTransform ] = useStyle(
- prefix + 'typography.textTransform',
- name
- );
- const [ backgroundColor ] = useStyle( prefix + 'color.background', name );
- const [ gradientValue ] = useStyle( prefix + 'color.gradient', name );
- const [ color ] = useStyle( prefix + 'color.text', name );
- const extraStyles =
- element === 'link'
- ? {
- textDecoration: 'underline',
- }
- : {};
+ const resetAll = () => {
+ resetFontFamily();
+ resetFontSize();
+ resetFontAppearance();
+ resetLineHeight();
+ resetLetterSpacing();
+ resetTextTransform();
+ };
return (
-
-
- Aa
-
-
- { element === 'heading' && (
-
-
-
-
-
-
-
-
-
-
-
- ) }
- { supports.includes( 'fontFamily' ) && (
-
-
-
- ) }
- { hasFontSizeEnabled && (
-
-
-
- ) }
- { hasAppearanceControl && (
+
+ { hasFontFamilyEnabled && (
+
+
+
+ ) }
+ { hasFontSizeEnabled && (
+
+
+
+ ) }
+ { hasAppearanceControl && (
+
- ) }
- { hasLineHeightEnabled && (
+
+ ) }
+ { hasLineHeightEnabled && (
+
- ) }
- { hasLetterSpacingControl && (
+
+ ) }
+ { hasLetterSpacingControl && (
+
- ) }
- { hasTextTransformControl && (
-
-
-
- ) }
-
-
+
+ ) }
+ { hasTextTransformControl && (
+
+
+
+ ) }
+
);
}
diff --git a/packages/edit-site/src/components/global-styles/typography-preview.js b/packages/edit-site/src/components/global-styles/typography-preview.js
new file mode 100644
index 00000000000000..b0e134ab0cce59
--- /dev/null
+++ b/packages/edit-site/src/components/global-styles/typography-preview.js
@@ -0,0 +1,49 @@
+/**
+ * Internal dependencies
+ */
+import { useStyle } from './hooks';
+
+export default function TypographyPreview( { name, element, headingLevel } ) {
+ let prefix = '';
+ if ( element === 'heading' ) {
+ prefix = `elements.${ headingLevel }.`;
+ } else if ( element && element !== 'text' ) {
+ prefix = `elements.${ element }.`;
+ }
+
+ const [ fontFamily ] = useStyle( prefix + 'typography.fontFamily', name );
+ const [ gradientValue ] = useStyle( prefix + 'color.gradient', name );
+ const [ backgroundColor ] = useStyle( prefix + 'color.background', name );
+ const [ color ] = useStyle( prefix + 'color.text', name );
+ const [ fontSize ] = useStyle( prefix + 'typography.fontSize', name );
+ const [ fontStyle ] = useStyle( prefix + 'typography.fontStyle', name );
+ const [ fontWeight ] = useStyle( prefix + 'typography.fontWeight', name );
+ const [ letterSpacing ] = useStyle(
+ prefix + 'typography.letterSpacing',
+ name
+ );
+ const extraStyles =
+ element === 'link'
+ ? {
+ textDecoration: 'underline',
+ }
+ : {};
+
+ return (
+
+ Aa
+
+ );
+}
diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
index 189fb3ebbb2586..1e9ed77736e075 100644
--- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js
+++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
@@ -434,9 +434,15 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
const pickStyleKeys = ( treeToPickFrom ) =>
pickBy( treeToPickFrom, ( value, key ) =>
- [ 'border', 'color', 'spacing', 'typography', 'filter' ].includes(
- key
- )
+ [
+ 'border',
+ 'color',
+ 'spacing',
+ 'typography',
+ 'filter',
+ 'outline',
+ 'shadow',
+ ].includes( key )
);
// Top-level.
@@ -605,12 +611,12 @@ export const toStyles = (
}
if ( useRootPaddingAlign ) {
- ruleset += `padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) }
- .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }
- .has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }
- .has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }
- .has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }
- .has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }
+ ruleset += `padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) }
+ .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }
+ .has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }
+ .has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }
+ .has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }
+ .has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }
.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0;`;
}
diff --git a/packages/edit-site/src/components/main-dashboard-button/index.js b/packages/edit-site/src/components/main-dashboard-button/index.js
index efc3bfaad19e87..0878a7cce49012 100644
--- a/packages/edit-site/src/components/main-dashboard-button/index.js
+++ b/packages/edit-site/src/components/main-dashboard-button/index.js
@@ -2,7 +2,7 @@
* WordPress dependencies
*/
import {
- __experimentalUseSlot as useSlot,
+ __experimentalUseSlotFills as useSlotFills,
createSlotFill,
} from '@wordpress/components';
@@ -13,8 +13,8 @@ const { Fill, Slot: MainDashboardButtonSlot } = createSlotFill( slotName );
const MainDashboardButton = Fill;
const Slot = ( { children } ) => {
- const slot = useSlot( slotName );
- const hasFills = Boolean( slot.fills && slot.fills.length );
+ const fills = useSlotFills( slotName );
+ const hasFills = Boolean( fills && fills.length );
if ( ! hasFills ) {
return children;
diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss
index b4527736273e81..181740907c09a6 100644
--- a/packages/edit-site/src/components/sidebar/style.scss
+++ b/packages/edit-site/src/components/sidebar/style.scss
@@ -56,7 +56,7 @@
border: 0;
}
-.edit-site-global-styles-sidebar .components-tools-panel-item.single-column {
+.edit-site-global-styles-sidebar .single-column {
grid-column: span 1;
}
diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js
index b3c4b5dc161037..a09133c956f957 100644
--- a/packages/edit-site/src/index.js
+++ b/packages/edit-site/src/index.js
@@ -18,6 +18,7 @@ import { store as preferencesStore } from '@wordpress/preferences';
import { __ } from '@wordpress/i18n';
import { store as viewportStore } from '@wordpress/viewport';
import { getQueryArgs } from '@wordpress/url';
+import { addFilter } from '@wordpress/hooks';
/**
* Internal dependencies
@@ -51,6 +52,26 @@ export function reinitializeEditor( target, settings ) {
return;
}
+ /*
+ * Prevent adding the Clasic block in the site editor.
+ * Only add the filter when the site editor is initialized, not imported.
+ * Also only add the filter(s) after registerCoreBlocks()
+ * so that common filters in the block library are not overwritten.
+ *
+ * This usage here is inspired by previous usage of the filter in the post editor:
+ * https://github.com/WordPress/gutenberg/pull/37157
+ */
+ addFilter(
+ 'blockEditor.__unstableCanInsertBlockType',
+ 'removeClassicBlockFromInserter',
+ ( canInsert, blockType ) => {
+ if ( blockType.name === 'core/freeform' ) {
+ return false;
+ }
+ return canInsert;
+ }
+ );
+
// This will be a no-op if the target doesn't have any React nodes.
unmountComponentAtNode( target );
const reboot = reinitializeEditor.bind( null, target, settings );
diff --git a/packages/editor/src/components/autosave-monitor/test/index.js b/packages/editor/src/components/autosave-monitor/test/index.js
index fc2246c986cf0c..ab56ecf14deabc 100644
--- a/packages/editor/src/components/autosave-monitor/test/index.js
+++ b/packages/editor/src/components/autosave-monitor/test/index.js
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import { shallow } from 'enzyme';
+import { render } from '@testing-library/react';
/**
* Internal dependencies
@@ -9,7 +9,6 @@ import { shallow } from 'enzyme';
import { AutosaveMonitor } from '../';
describe( 'AutosaveMonitor', () => {
- let wrapper;
let setAutosaveTimerSpy;
beforeEach( () => {
jest.useFakeTimers( 'legacy' );
@@ -17,9 +16,6 @@ describe( 'AutosaveMonitor', () => {
AutosaveMonitor.prototype,
'setAutosaveTimer'
);
- wrapper = shallow( , {
- lifecycleExperimental: true,
- } );
} );
afterEach( () => {
@@ -29,128 +25,167 @@ describe( 'AutosaveMonitor', () => {
setAutosaveTimerSpy.mockClear();
} );
+ it( 'should render nothing', () => {
+ const { container } = render( );
+
+ expect( container ).toBeEmptyDOMElement();
+ } );
+
it( 'should start autosave timer after being mounted', () => {
+ render( );
+
expect( setAutosaveTimerSpy ).toHaveBeenCalled();
} );
it( 'should clear the autosave timer after being unmounted', () => {
- wrapper.unmount();
+ const { rerender } = render( );
+
+ rerender(
);
+
+ expect( clearTimeout ).toHaveBeenCalled();
+ } );
+
+ it( 'should clear and restart autosave timer when the interval changes', () => {
+ const { rerender } = render( );
+
+ rerender( );
+
expect( clearTimeout ).toHaveBeenCalled();
+ expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
} );
- describe( '#componentDidUpdate()', () => {
- it( 'should clear and restart autosave timer when the interval changes', () => {
- wrapper.setProps( { interval: 999 } );
- expect( clearTimeout ).toHaveBeenCalled();
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
- } );
-
- it( 'should set needsAutosave=true when editReference changes', () => {
- expect( wrapper.instance().needsAutosave ).toBe( false );
- wrapper.setProps( {
- editsReference: [],
- } );
- expect( wrapper.instance().needsAutosave ).toBe( true );
- } );
-
- it( 'should set needsAutosave=true when editReference changes and the post becomes dirty', () => {
- expect( wrapper.instance().needsAutosave ).toBe( false );
- wrapper.setProps( {
- isDirty: true,
- editsReference: [],
- } );
- expect( wrapper.instance().needsAutosave ).toBe( true );
- } );
-
- it( 'should not set needsAutosave=true when editReference changes and the post is not dirty anymore', () => {
- expect( wrapper.instance().needsAutosave ).toBe( false );
- wrapper.setProps( {
- isDirty: true,
- editsReference: [],
- } );
- wrapper.setProps( {
- isDirty: false,
- editsReference: [],
- } );
- expect( wrapper.instance().needsAutosave ).toBe( false );
- } );
-
- it( 'should set needsAutosave=true when editReference changes and the post is not autosaving', () => {
- expect( wrapper.instance().needsAutosave ).toBe( false );
- wrapper.setProps( {
- isAutosaving: false,
- editsReference: [],
- } );
- expect( wrapper.instance().needsAutosave ).toBe( true );
- } );
-
- it( 'should not set needsAutosave=true when editReference changes and the post started autosaving', () => {
- expect( wrapper.instance().needsAutosave ).toBe( false );
- wrapper.setProps( {
- isAutosaving: false,
- editsReference: [],
- } );
- wrapper.setProps( {
- isAutosaving: true,
- editsReference: [],
- } );
- expect( wrapper.instance().needsAutosave ).toBe( false );
- } );
+ it( 'should autosave when `editReference` changes', () => {
+ const autosave = jest.fn();
+ const { rerender } = render(
+
+ );
+
+ expect( autosave ).not.toHaveBeenCalled();
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( autosave ).toHaveBeenCalledTimes( 1 );
} );
- describe( '#autosaveTimerHandler()', () => {
- it( 'should schedule itself in another {interval} ms', () => {
- wrapper.setProps( {
- isAutosaveable: true,
- interval: 5,
- } );
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
- wrapper.instance().autosaveTimerHandler();
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 3 );
- expect( setTimeout ).lastCalledWith( expect.any( Function ), 5000 );
- } );
-
- it( 'should schedule itself in 1000 ms if the post is not autosaveable at a time', () => {
- wrapper.setProps( {
- isAutosaveable: false,
- interval: 5,
- } );
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
- wrapper.instance().autosaveTimerHandler();
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 3 );
- expect( setTimeout ).lastCalledWith( expect.any( Function ), 1000 );
- } );
-
- it( 'should call autosave if needsAutosave=true', () => {
- const autosave = jest.fn();
- wrapper.setProps( {
- isAutosaveable: true,
- interval: 5,
- autosave,
- } );
- wrapper.instance().needsAutosave = true;
- expect( autosave ).toHaveBeenCalledTimes( 0 );
- wrapper.instance().autosaveTimerHandler();
- expect( autosave ).toHaveBeenCalledTimes( 1 );
- } );
-
- it( 'should not call autosave if needsAutosave is not true', () => {
- const autosave = jest.fn();
- wrapper.setProps( {
- isAutosaveable: true,
- interval: 5,
- autosave,
- } );
- wrapper.instance().needsAutosave = false;
- expect( autosave ).toHaveBeenCalledTimes( 0 );
- wrapper.instance().autosaveTimerHandler();
- expect( autosave ).toHaveBeenCalledTimes( 0 );
- } );
+ it( 'should autosave when `editReference` changes and the post becomes dirty', () => {
+ const autosave = jest.fn();
+ const { rerender } = render(
+
+ );
+
+ expect( autosave ).not.toHaveBeenCalled();
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( autosave ).toHaveBeenCalledTimes( 1 );
} );
- describe( '#render()', () => {
- it( 'should render nothing', () => {
- expect( wrapper.type() ).toBe( null );
- } );
+ it( 'should not autosave when `editReference` changes and the post is not dirty anymore', () => {
+ const autosave = jest.fn();
+ const { rerender } = render(
+
+ );
+
+ expect( autosave ).not.toHaveBeenCalled();
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( autosave ).not.toHaveBeenCalled();
+ } );
+
+ it( 'should not autosave when `editReference` changes and the post is not autosaving', () => {
+ const autosave = jest.fn();
+ const { rerender } = render(
+
+ );
+
+ expect( autosave ).not.toHaveBeenCalled();
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( autosave ).not.toHaveBeenCalled();
+ } );
+
+ it( 'should not autosave when `editReference` changes and the post started autosaving', () => {
+ const autosave = jest.fn();
+ const { rerender } = render(
+
+ );
+
+ expect( autosave ).not.toHaveBeenCalled();
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( autosave ).not.toHaveBeenCalled();
+ } );
+
+ it( 'should schedule itself in another {interval} ms', () => {
+ const { rerender } = render( );
+
+ rerender( );
+
+ jest.runOnlyPendingTimers();
+
+ expect( setTimeout ).lastCalledWith( expect.any( Function ), 5000 );
+ } );
+
+ it( 'should schedule itself in 1000 ms if the post is not autosaveable at a time', () => {
+ const { rerender } = render( );
+
+ rerender(
+
+ );
+
+ jest.runOnlyPendingTimers();
+
+ expect( setTimeout ).lastCalledWith( expect.any( Function ), 1000 );
} );
} );
diff --git a/packages/editor/src/components/post-preview-button/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-preview-button/test/__snapshots__/index.js.snap
deleted file mode 100644
index 77951af0f8eff5..00000000000000
--- a/packages/editor/src/components/post-preview-button/test/__snapshots__/index.js.snap
+++ /dev/null
@@ -1,37 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PostPreviewButton render() should render currentPostLink otherwise 1`] = `
-
- Preview
-
- (opens in a new tab)
-
-
-`;
-
-exports[`PostPreviewButton render() should render previewLink if provided 1`] = `
-
- Preview
-
- (opens in a new tab)
-
-
-`;
diff --git a/packages/editor/src/components/post-preview-button/test/index.js b/packages/editor/src/components/post-preview-button/test/index.js
index 674957e0d330f3..e38f5d99f5287b 100644
--- a/packages/editor/src/components/post-preview-button/test/index.js
+++ b/packages/editor/src/components/post-preview-button/test/index.js
@@ -1,7 +1,8 @@
/**
* External dependencies
*/
-import { shallow } from 'enzyme';
+import { render, screen, within } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
/**
* Internal dependencies
@@ -9,180 +10,310 @@ import { shallow } from 'enzyme';
import { PostPreviewButton } from '../';
describe( 'PostPreviewButton', () => {
- describe( 'setPreviewWindowLink()', () => {
- it( 'should do nothing if there is no preview window', () => {
- const url = 'https://wordpress.org';
- const setter = jest.fn();
- const wrapper = shallow( );
+ const documentWrite = jest.fn();
+ const documentTitle = jest.fn();
+ const documentClose = jest.fn();
+ const setLocation = jest.fn();
- wrapper.instance().setPreviewWindowLink( url );
+ beforeEach( () => {
+ global.open = jest.fn( () => ( {
+ focus: jest.fn(),
+ document: {
+ write: documentWrite,
+ close: documentClose,
+ get title() {},
+ set title( value ) {
+ documentTitle( value );
+ },
+ },
+ get location() {},
+ set location( value ) {
+ setLocation( value );
+ },
+ } ) );
+ } );
- expect( setter ).not.toHaveBeenCalled();
- } );
+ afterEach( () => {
+ global.open.mockRestore();
+ documentWrite.mockReset();
+ documentTitle.mockReset();
+ documentClose.mockReset();
+ setLocation.mockReset();
+ } );
- it( 'set preview window location to url', () => {
- const url = 'https://wordpress.org';
- const setter = jest.fn();
- const wrapper = shallow( );
- wrapper.instance().previewWindow = {
- get location() {
- return {
- href: 'about:blank',
- };
- },
- set location( value ) {
- setter( value );
- },
- };
+ it( 'should render with `editor-post-preview` class if no `className` is specified.', () => {
+ render( );
- wrapper.instance().setPreviewWindowLink( url );
+ expect( screen.getByRole( 'button' ) ).toHaveClass(
+ 'editor-post-preview'
+ );
+ } );
- expect( setter ).toHaveBeenCalledWith( url );
- } );
+ it( 'should render with a custom class and not `editor-post-preview` if `className` is specified.', () => {
+ render( );
+
+ const button = screen.getByRole( 'button' );
+
+ expect( button ).toHaveClass( 'foo-bar' );
+ expect( button ).not.toHaveClass( 'editor-post-preview' );
} );
- describe( 'getWindowTarget()', () => {
- it( 'returns a string unique to the post id', () => {
- const instance = new PostPreviewButton( {
- postId: 1,
- } );
+ it( 'should render a tertiary button if no classname is specified.', () => {
+ render( );
- expect( instance.getWindowTarget() ).toBe( 'wp-preview-1' );
- } );
+ expect( screen.getByRole( 'button' ) ).toHaveClass( 'is-tertiary' );
} );
- describe( 'componentDidUpdate()', () => {
- it( 'should change popup location if preview link is available', () => {
- const wrapper = shallow(
-
- );
+ it( 'should render the button in its default variant if a custom classname is specified.', () => {
+ render( );
+
+ const button = screen.getByRole( 'button' );
- const previewWindow = { location: {} };
+ expect( button ).not.toHaveClass( 'is-primary' );
+ expect( button ).not.toHaveClass( 'is-secondary' );
+ expect( button ).not.toHaveClass( 'is-tertiary' );
+ expect( button ).not.toHaveClass( 'is-link' );
+ } );
- wrapper.instance().previewWindow = previewWindow;
+ it( 'should render `textContent` if specified.', () => {
+ const textContent = 'Foo bar';
- wrapper.setProps( { previewLink: 'https://wordpress.org/?p=1' } );
+ render( );
- expect( previewWindow.location ).toBe(
- 'https://wordpress.org/?p=1'
- );
- } );
+ const button = screen.getByRole( 'button' );
+
+ expect( button ).toHaveTextContent( textContent );
+ expect(
+ within( button ).queryByText( 'Preview' )
+ ).not.toBeInTheDocument();
+ expect(
+ within( button ).queryByText( '(opens in a new tab)' )
+ ).not.toBeInTheDocument();
} );
- describe( 'openPreviewWindow()', () => {
- let windowOpen;
- beforeEach( () => {
- windowOpen = window.open;
- } );
- afterEach( () => {
- window.open = windowOpen;
- } );
+ it( 'should render `Preview` with accessibility text if `textContent` not specified.', () => {
+ render( );
- it( 'behaves like a regular link if not autosaveable', () => {
- const preventDefault = jest.fn();
- const autosave = jest.fn();
- const setLocation = jest.fn();
- window.open = jest.fn( () => ( {
- focus: jest.fn(),
- set location( url ) {
- setLocation( url );
- },
- } ) );
-
- const wrapper = shallow(
-
- );
-
- wrapper.simulate( 'click', {
- preventDefault,
- target: { href: 'https://wordpress.org/?p=1' },
- } );
-
- expect( preventDefault ).toHaveBeenCalled();
- expect( window.open ).toHaveBeenCalledWith( '', 'wp-preview-1' );
- expect( wrapper.instance().previewWindow.focus ).toHaveBeenCalled();
- expect( autosave ).not.toHaveBeenCalled();
- expect( setLocation ).toHaveBeenCalledWith(
- 'https://wordpress.org/?p=1'
- );
- } );
+ const button = screen.getByRole( 'button' );
+
+ expect( within( button ).getByText( 'Preview' ) ).toBeVisible();
+ expect(
+ within( button ).getByText( '(opens in a new tab)' )
+ ).toBeInTheDocument();
+ } );
- it( 'autosaves the post if autosaveable', () => {
- const preventDefault = jest.fn();
- const autosave = jest.fn();
+ it( 'should be disabled if post is not saveable.', async () => {
+ render( );
- window.open = jest.fn( () => ( {
- focus: jest.fn(),
- document: {
- write: jest.fn(),
- close: jest.fn(),
- },
- } ) );
-
- const wrapper = shallow(
-
- );
-
- wrapper.simulate( 'click', { preventDefault } );
-
- expect( preventDefault ).toHaveBeenCalled();
- expect( window.open ).toHaveBeenCalledWith( '', 'wp-preview-1' );
- expect( wrapper.instance().previewWindow.focus ).toHaveBeenCalled();
- expect( autosave ).toHaveBeenCalled();
- expect(
- wrapper.instance().previewWindow.document.write.mock
- .calls[ 0 ][ 0 ]
- ).toContain( 'Generating preview…' );
- expect(
- wrapper.instance().previewWindow.document.close
- ).toHaveBeenCalled();
+ expect( screen.getByRole( 'button' ) ).toBeDisabled();
+ } );
+
+ it( 'should not be disabled if post is saveable.', async () => {
+ render( );
+
+ expect( screen.getByRole( 'button' ) ).not.toBeDisabled();
+ } );
+
+ it( 'should set `href` to `previewLink` if `previewLink` is specified.', async () => {
+ const url = 'https://wordpress.org';
+
+ render(
+
+ );
+
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url );
+ } );
+
+ it( 'should set `href` to `currentPostLink` if `currentPostLink` is specified.', async () => {
+ const url = 'https://wordpress.org';
+
+ render(
+
+ );
+
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url );
+ } );
+
+ it( 'should prioritize `previewLink` if both `previewLink` and `currentPostLink` are specified.', async () => {
+ const url1 = 'https://wordpress.org';
+ const url2 = 'https://wordpress.com';
+
+ render(
+
+ );
+
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url1 );
+ } );
+
+ it( 'should properly set target to `wp-preview-${ postId }`.', async () => {
+ const postId = 123;
+ const url = 'https://wordpress.org';
+
+ render(
+
+ );
+
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute(
+ 'target',
+ `wp-preview-${ postId }`
+ );
+ } );
+
+ it( 'should save post if `isDraft` is `true`', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
+ const url = 'https://wordpress.org';
+ const savePost = jest.fn();
+ const autosave = jest.fn();
+
+ render(
+
+ );
+
+ await user.click( screen.getByRole( 'link' ) );
+
+ expect( savePost ).toHaveBeenCalledWith(
+ expect.objectContaining( { isPreview: true } )
+ );
+ expect( autosave ).not.toHaveBeenCalled();
} );
- describe( 'render()', () => {
- it( 'should render previewLink if provided', () => {
- const wrapper = shallow(
-
- );
+ it( 'should autosave post if `isDraft` is `false`', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+ const url = 'https://wordpress.org';
+ const savePost = jest.fn();
+ const autosave = jest.fn();
- expect( wrapper ).toMatchSnapshot();
+ render(
+
+ );
+
+ await user.click( screen.getByRole( 'link' ) );
+
+ expect( savePost ).not.toHaveBeenCalled();
+ expect( autosave ).toHaveBeenCalledWith(
+ expect.objectContaining( { isPreview: true } )
+ );
+ } );
+
+ it( 'should open a window with the specified target', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
+ const postId = 123;
+ const url = 'https://wordpress.org';
- it( 'should render currentPostLink otherwise', () => {
- const wrapper = shallow(
-
- );
+ render(
+
+ );
- expect( wrapper ).toMatchSnapshot();
+ await user.click( screen.getByRole( 'link' ) );
+
+ expect( global.open ).toHaveBeenCalledWith(
+ '',
+ `wp-preview-${ postId }`
+ );
+ } );
+
+ it( 'should set the location in the window properly', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
+ const postId = 123;
+ const url = 'https://wordpress.org';
+
+ const { rerender } = render(
+
+ );
- it( 'should be disabled if post is not saveable', () => {
- const wrapper = shallow(
-
- );
+ await user.click( screen.getByRole( 'button' ) );
- expect( wrapper.prop( 'disabled' ) ).toBe( true );
+ expect( setLocation ).toHaveBeenCalledWith( undefined );
+
+ rerender(
+
+ );
+
+ expect( setLocation ).toHaveBeenCalledWith( url );
+ } );
+
+ it( 'should display a `Generating preview` message while waiting for autosaving', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
} );
+ const previewText = 'Generating preview…';
+ const url = 'https://wordpress.org';
+ const savePost = jest.fn();
+ const autosave = jest.fn();
+
+ render(
+
+ );
+
+ await user.click( screen.getByRole( 'link' ) );
+
+ expect( documentWrite ).toHaveBeenCalledWith(
+ expect.stringContaining( previewText )
+ );
+ expect( documentTitle ).toHaveBeenCalledWith( previewText );
+ expect( documentClose ).toHaveBeenCalled();
} );
} );
diff --git a/packages/experiments/CHANGELOG.md b/packages/experiments/CHANGELOG.md
new file mode 100644
index 00000000000000..256046894e354f
--- /dev/null
+++ b/packages/experiments/CHANGELOG.md
@@ -0,0 +1,5 @@
+
+
+## Unreleased
+
+– Package created.
diff --git a/packages/experiments/README.md b/packages/experiments/README.md
new file mode 100644
index 00000000000000..fe6221588ecc19
--- /dev/null
+++ b/packages/experiments/README.md
@@ -0,0 +1,60 @@
+# Experiments
+
+Private `__experimental` APIs that are not [exposed publicly plugin authors](https://make.wordpress.org/core/2022/08/10/proposal-stop-merging-experimental-apis-from-gutenberg-to-wordpress-core/#respond).
+
+This package acts as a "dealer" that only allows WordPress packages to use the experimental APIs.
+
+Each package needs to start by registering itself:
+
+```js
+const { register } =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ '', // See index.js, this may change without notice.
+ '@wordpress/blocks'
+ );
+```
+
+The function name communicates that plugins are not supposed to use it. To make double and triple sure, the first argument must be that exact consent string, and the second argument must be a known `@wordpress` package that hasn't opted in yet – otherwise an error is thrown.
+
+Expose a new `__experimental` API as follows:
+
+```js
+export const __experiments = register( { __unstableGetInnerBlocksProps } )
+```
+
+Consume the registered `__experimental` APIs as follows:
+
+```js
+// In the @wordpress/block-editor package:
+import { __experiments as blocksExperiments } from '@wordpress/blocks';
+const { unlock } =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ '', // See index.js
+ '@wordpress/block-editor'
+ );
+
+const { __unstableGetInnerBlocksProps } = unlock( blocksExperiments );
+```
+
+All new experimental APIs should be shipped as **private** using this method.
+
+The **public** experimental APIs that have already been shipped in a stable WordPress version should remain accessible via `window.wp`. Please do not create new ones.
+
+A determined developer who would want to use the private experimental APIs at all costs would have to:
+
+* Realize a private importing system exists
+* Read the code where the risks would be spelled out in capital letters
+* Explicitly type out he or she is aware of the consequences
+* Pretend to register a `@wordpress` package (and trigger an error as soon as the real package is loaded)
+
+Dangerously opting in to using these APIs by theme and plugin developers is not recommended. Furthermore, the WordPress Core philosophy to strive to maintain backward compatibility for third-party developers **does not apply** to experimental APIs registered via this package.
+
+The consent string for opting in to these APIs may change at any time and without notice. This change will break existing third-party code. Such a change may occur in either a major or minor release.
+
+## Contributing to this package
+
+This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
+
+To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md).
+
+
diff --git a/packages/experiments/package.json b/packages/experiments/package.json
new file mode 100644
index 00000000000000..9f27183fb1be91
--- /dev/null
+++ b/packages/experiments/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "@wordpress/experiments",
+ "version": "0.0.1",
+ "description": "Internal experimental APIs for WordPress core.",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "wordpress",
+ "gutenberg",
+ "dom",
+ "utils"
+ ],
+ "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/experiments/README.md",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/WordPress/gutenberg.git",
+ "directory": "packages/experiments"
+ },
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg/issues"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "main": "build/index.js",
+ "module": "build-module/index.js",
+ "react-native": "src/index",
+ "sideEffects": false,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/experiments/src/index.js b/packages/experiments/src/index.js
new file mode 100644
index 00000000000000..033816e4b28365
--- /dev/null
+++ b/packages/experiments/src/index.js
@@ -0,0 +1,85 @@
+const CORE_MODULES_USING_EXPERIMENTS = [
+ '@wordpress/data',
+ '@wordpress/block-editor',
+ '@wordpress/block-library',
+ '@wordpress/blocks',
+ '@wordpress/core-data',
+ '@wordpress/date',
+ '@wordpress/edit-site',
+ '@wordpress/edit-widgets',
+];
+
+const registeredExperiments = {};
+/*
+ * Warning for theme and plugin developers.
+ *
+ * The use of experimental developer APIs is intended for use by WordPress Core
+ * and the Gutenberg plugin exclusively.
+ *
+ * Dangerously opting in to using these APIs is NOT RECOMMENDED. Furthermore,
+ * the WordPress Core philosophy to strive to maintain backward compatibility
+ * for third-party developers DOES NOT APPLY to experimental APIs.
+ *
+ * THE CONSENT STRING FOR OPTING IN TO THESE APIS MAY CHANGE AT ANY TIME AND
+ * WITHOUT NOTICE. THIS CHANGE WILL BREAK EXISTING THIRD-PARTY CODE. SUCH A
+ * CHANGE MAY OCCUR IN EITHER A MAJOR OR MINOR RELEASE.
+ */
+const requiredConsent =
+ 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.';
+
+export const __dangerousOptInToUnstableAPIsOnlyForCoreModules = (
+ consent,
+ moduleName
+) => {
+ if ( ! CORE_MODULES_USING_EXPERIMENTS.includes( moduleName ) ) {
+ throw new Error(
+ `You tried to opt-in to unstable APIs as a module "${ moduleName }". ` +
+ 'This feature is only for JavaScript modules shipped with WordPress core. ' +
+ 'Please do not use it in plugins and themes as the unstable APIs will be removed ' +
+ 'without a warning. If you ignore this error and depend on unstable features, ' +
+ 'your product will inevitably break on one of the next WordPress releases.'
+ );
+ }
+ if ( moduleName in registeredExperiments ) {
+ throw new Error(
+ `You tried to opt-in to unstable APIs as a module "${ moduleName }" which is already registered. ` +
+ 'This feature is only for JavaScript modules shipped with WordPress core. ' +
+ 'Please do not use it in plugins and themes as the unstable APIs will be removed ' +
+ 'without a warning. If you ignore this error and depend on unstable features, ' +
+ 'your product will inevitably break on one of the next WordPress releases.'
+ );
+ }
+ if ( consent !== requiredConsent ) {
+ throw new Error(
+ `You tried to opt-in to unstable APIs without confirming you know the consequences. ` +
+ 'This feature is only for JavaScript modules shipped with WordPress core. ' +
+ 'Please do not use it in plugins and themes as the unstable APIs will removed ' +
+ 'without a warning. If you ignore this error and depend on unstable features, ' +
+ 'your product will inevitably break on the next WordPress release.'
+ );
+ }
+ registeredExperiments[ moduleName ] = {
+ accessKey: {},
+ apis: {},
+ };
+ return {
+ register: ( experiments ) => {
+ for ( const key in experiments ) {
+ registeredExperiments[ moduleName ].apis[ key ] =
+ experiments[ key ];
+ }
+ return registeredExperiments[ moduleName ].accessKey;
+ },
+ unlock: ( accessKey ) => {
+ for ( const experiment of Object.values( registeredExperiments ) ) {
+ if ( experiment.accessKey === accessKey ) {
+ return experiment.apis;
+ }
+ }
+
+ throw new Error(
+ 'There is no registered module matching the specified access key'
+ );
+ },
+ };
+};
diff --git a/packages/experiments/src/test/index.js b/packages/experiments/src/test/index.js
new file mode 100644
index 00000000000000..a3424ac26f7e20
--- /dev/null
+++ b/packages/experiments/src/test/index.js
@@ -0,0 +1,84 @@
+/**
+ * Internal dependencies
+ */
+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '../';
+
+const requiredConsent =
+ 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.';
+
+describe( '__dangerousOptInToUnstableAPIsOnlyForCoreModules', () => {
+ it( 'Should require a consent string', () => {
+ expect( () => {
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ '',
+ '@wordpress/data'
+ );
+ } ).toThrow( /without confirming you know the consequences/ );
+ } );
+ it( 'Should require a valid @wordpress package name', () => {
+ expect( () => {
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ 'custom_package'
+ );
+ } ).toThrow(
+ /This feature is only for JavaScript modules shipped with WordPress core/
+ );
+ } );
+ it( 'Should not register the same module twice', () => {
+ expect( () => {
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ '@wordpress/edit-widgets'
+ );
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ '@wordpress/edit-widgets'
+ );
+ } ).toThrow( /is already registered/ );
+ } );
+ it( 'Should grant access to unstable APIs when passed both a consent string and a previously unregistered package name', () => {
+ const unstableAPIs = __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ '@wordpress/edit-site'
+ );
+ expect( unstableAPIs.unlock ).toEqual( expect.any( Function ) );
+ expect( unstableAPIs.register ).toEqual( expect.any( Function ) );
+ } );
+ it( 'Should register and unlock experimental APIs', () => {
+ // This would live in @wordpress/data:
+ // Opt-in to experimental APIs
+ const dataExperiments =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ '@wordpress/data'
+ );
+
+ // Register the experimental APIs
+ const dataExperimentalFunctions = {
+ __experimentalFunction: jest.fn(),
+ };
+ const dataAccessKey = dataExperiments.register(
+ dataExperimentalFunctions
+ );
+
+ // This would live in @wordpress/core-data:
+ // Register the experimental APIs
+ const coreDataExperiments =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ requiredConsent,
+ '@wordpress/core-data'
+ );
+
+ // Get the experimental APIs registered by @wordpress/data
+ const { __experimentalFunction } =
+ coreDataExperiments.unlock( dataAccessKey );
+
+ // Call one!
+ __experimentalFunction();
+
+ expect(
+ dataExperimentalFunctions.__experimentalFunction
+ ).toHaveBeenCalled();
+ } );
+} );
diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md
index cb12e59b63e9c2..85b5acfc13d899 100644
--- a/packages/jest-preset-default/CHANGELOG.md
+++ b/packages/jest-preset-default/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Breaking Change
+
+- Testing: Remove enzyme completely ([#44494](https://github.com/WordPress/gutenberg/pull/44494)). See the [example in the README](./README.md#using-enzyme) for instructions on how to continue using `enzyme` in your project.
+
## 9.1.0 (2022-09-21)
## 9.0.0 (2022-08-24)
diff --git a/packages/jest-preset-default/README.md b/packages/jest-preset-default/README.md
index 041b9ac1613d6d..97c436bce9fc78 100644
--- a/packages/jest-preset-default/README.md
+++ b/packages/jest-preset-default/README.md
@@ -36,6 +36,64 @@ npm install @wordpress/jest-preset-default --save-dev
- `transform` - keeps the default [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) transformer.
- `verbose` - each individual test won't be reported during the run.
+#### Using enzyme
+
+Historically, this package used to use `enzyme`, but support was dropped in favor of `@testing-library/react`, primary reason being unblocking the upgrade to React 18.
+
+If you wish to use `enzyme`, you can still use it by manually providing the React 17 adapter, by following the steps below.
+
+To install the enzyme dependency, run:
+
+```bash
+npm install --save enzyme
+```
+
+To install the React 17 adapter dependency, run:
+
+```bash
+npm install --save @wojtekmaj/enzyme-adapter-react-17
+```
+
+To use the React 17 adapter, use this in your [`setupFilesAfterEnv`](https://jestjs.io/docs/configuration#setupfilesafterenv-array) configuration:
+
+```javascript
+// It "mocks" enzyme, so that we can delay loading of
+// the utility functions until enzyme is imported in tests.
+// Props to @gdborton for sharing this technique in his article:
+// https://medium.com/airbnb-engineering/unlocking-test-performance-migrating-from-mocha-to-jest-2796c508ec50.
+let mockEnzymeSetup = false;
+
+jest.mock( 'enzyme', () => {
+ const actualEnzyme = jest.requireActual( 'enzyme' );
+ if ( ! mockEnzymeSetup ) {
+ mockEnzymeSetup = true;
+
+ // Configure enzyme 3 for React, from docs: http://airbnb.io/enzyme/docs/installation/index.html
+ const Adapter = jest.requireActual(
+ '@wojtekmaj/enzyme-adapter-react-17'
+ );
+ actualEnzyme.configure( { adapter: new Adapter() } );
+ }
+ return actualEnzyme;
+} );
+```
+
+If you also use snapshot tests with `enzyme`, you might want to add support for serializing them, through the `enzyme-to-json` package.
+
+To install the dependency, run:
+
+```bash
+npm install --save enzyme-to-json
+```
+
+Finally, you should add `enzyme-to-json/serializer` to the array of [`snapshotSerializers`](https://jestjs.io/docs/configuration#snapshotserializers-arraystring):
+
+```javascript
+{
+ snapshotSerializers: [ 'enzyme-to-json/serializer' ]
+}
+```
+
## Contributing to this package
This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
diff --git a/packages/jest-preset-default/jest-preset.js b/packages/jest-preset-default/jest-preset.js
index 707118566cb8af..c6a491e9ed1d98 100644
--- a/packages/jest-preset-default/jest-preset.js
+++ b/packages/jest-preset-default/jest-preset.js
@@ -17,7 +17,6 @@ module.exports = {
'@wordpress/jest-preset-default/scripts/setup-test-framework.js'
),
],
- snapshotSerializers: [ require.resolve( 'enzyme-to-json/serializer.js' ) ],
testEnvironment: 'jsdom',
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json
index e2040352bf5dd9..d1973828983750 100644
--- a/packages/jest-preset-default/package.json
+++ b/packages/jest-preset-default/package.json
@@ -9,8 +9,7 @@
"gutenberg",
"jest",
"preset",
- "react",
- "enzyme"
+ "react"
],
"homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/jest-preset-default/README.md",
"repository": {
@@ -31,11 +30,8 @@
],
"main": "index.js",
"dependencies": {
- "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"@wordpress/jest-console": "file:../jest-console",
- "babel-jest": "^27.4.5",
- "enzyme": "^3.11.0",
- "enzyme-to-json": "^3.4.4"
+ "babel-jest": "^27.4.5"
},
"peerDependencies": {
"@babel/core": ">=7",
diff --git a/packages/jest-preset-default/scripts/setup-test-framework.js b/packages/jest-preset-default/scripts/setup-test-framework.js
index ca5e8875b2f831..80ac6fded4f5dc 100644
--- a/packages/jest-preset-default/scripts/setup-test-framework.js
+++ b/packages/jest-preset-default/scripts/setup-test-framework.js
@@ -1,21 +1 @@
require( '@wordpress/jest-console' );
-
-// It "mocks" enzyme, so that we can delay loading of
-// the utility functions until enzyme is imported in tests.
-// Props to @gdborton for sharing this technique in his article:
-// https://medium.com/airbnb-engineering/unlocking-test-performance-migrating-from-mocha-to-jest-2796c508ec50.
-let mockEnzymeSetup = false;
-
-jest.mock( 'enzyme', () => {
- const actualEnzyme = jest.requireActual( 'enzyme' );
- if ( ! mockEnzymeSetup ) {
- mockEnzymeSetup = true;
-
- // Configure enzyme 3 for React, from docs: http://airbnb.io/enzyme/docs/installation/index.html
- const Adapter = jest.requireActual(
- '@wojtekmaj/enzyme-adapter-react-17'
- );
- actualEnzyme.configure( { adapter: new Adapter() } );
- }
- return actualEnzyme;
-} );
diff --git a/packages/library-export-default-webpack-plugin/index.js b/packages/library-export-default-webpack-plugin/index.js
index 2105077d0ad480..55f0f1b92fe6a7 100644
--- a/packages/library-export-default-webpack-plugin/index.js
+++ b/packages/library-export-default-webpack-plugin/index.js
@@ -1,11 +1,10 @@
/**
* External dependencies
*/
-const { includes } = require( 'lodash' );
const { ConcatSource } = require( 'webpack-sources' );
module.exports = class LibraryExportDefaultPlugin {
- constructor( entryPointNames ) {
+ constructor( entryPointNames = [] ) {
this.entryPointNames = entryPointNames;
}
@@ -16,7 +15,7 @@ module.exports = class LibraryExportDefaultPlugin {
const { mainTemplate, chunkTemplate } = compilation;
const onRenderWithEntry = ( source, chunk ) => {
- if ( ! includes( this.entryPointNames, chunk.name ) ) {
+ if ( ! this.entryPointNames.includes( chunk.name ) ) {
return source;
}
return new ConcatSource( source, '["default"]' );
diff --git a/packages/library-export-default-webpack-plugin/package.json b/packages/library-export-default-webpack-plugin/package.json
index 7a8bc4604b71e5..6bd234574450e7 100644
--- a/packages/library-export-default-webpack-plugin/package.json
+++ b/packages/library-export-default-webpack-plugin/package.json
@@ -29,7 +29,6 @@
],
"main": "index.js",
"dependencies": {
- "lodash": "^4.17.21",
"webpack-sources": "^3.2.2"
},
"peerDependencies": {
diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json
index 878bb307e36a51..b060c4f62aee9f 100644
--- a/packages/list-reusable-blocks/package.json
+++ b/packages/list-reusable-blocks/package.json
@@ -31,7 +31,7 @@
"@wordpress/compose": "file:../compose",
"@wordpress/element": "file:../element",
"@wordpress/i18n": "file:../i18n",
- "lodash": "^4.17.21"
+ "change-case": "^4.1.2"
},
"peerDependencies": {
"react": "^17.0.0",
diff --git a/packages/list-reusable-blocks/src/components/import-dropdown/index.js b/packages/list-reusable-blocks/src/components/import-dropdown/index.js
index 74aee0df9280c7..ddeed025b42c54 100644
--- a/packages/list-reusable-blocks/src/components/import-dropdown/index.js
+++ b/packages/list-reusable-blocks/src/components/import-dropdown/index.js
@@ -1,11 +1,7 @@
-/**
- * External dependencies
- */
-import { flow } from 'lodash';
-
/**
* WordPress dependencies
*/
+import { pipe } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { Dropdown, Button } from '@wordpress/components';
@@ -29,7 +25,7 @@ function ImportDropdown( { onUpload } ) {
) }
renderContent={ ( { onClose } ) => (
-
+
) }
/>
);
diff --git a/packages/list-reusable-blocks/src/utils/export.js b/packages/list-reusable-blocks/src/utils/export.js
index a8456262779622..0f70931c500805 100644
--- a/packages/list-reusable-blocks/src/utils/export.js
+++ b/packages/list-reusable-blocks/src/utils/export.js
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import { kebabCase } from 'lodash';
+import { paramCase as kebabCase } from 'change-case';
/**
* WordPress dependencies
diff --git a/packages/react-native-aztec/package.json b/packages/react-native-aztec/package.json
index 7ed083784390fd..4bba123cff489a 100644
--- a/packages/react-native-aztec/package.json
+++ b/packages/react-native-aztec/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/react-native-aztec",
- "version": "1.82.1",
+ "version": "1.83.0",
"description": "Aztec view for react-native.",
"private": true,
"author": "The WordPress Contributors",
diff --git a/packages/react-native-bridge/package.json b/packages/react-native-bridge/package.json
index f9a4fab7459198..bd73b847ae9087 100644
--- a/packages/react-native-bridge/package.json
+++ b/packages/react-native-bridge/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/react-native-bridge",
- "version": "1.82.1",
+ "version": "1.83.0",
"description": "Native bridge library used to integrate the block editor into a native App.",
"private": true,
"author": "The WordPress Contributors",
diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md
index 72409d9ac9e0fd..f283009ba1c299 100644
--- a/packages/react-native-editor/CHANGELOG.md
+++ b/packages/react-native-editor/CHANGELOG.md
@@ -11,6 +11,9 @@ For each user feature we should also add a importance categorization label to i
## Unreleased
+## 1.83.0
+* No User facing changes *
+
## 1.82.1
- [**] List block v2: Fix issues splitting or merging paragraphs into the block [#43949]
diff --git a/packages/react-native-editor/__device-tests__/helpers/utils.js b/packages/react-native-editor/__device-tests__/helpers/utils.js
index 7c05cb2db19a43..64d802f30dbec8 100644
--- a/packages/react-native-editor/__device-tests__/helpers/utils.js
+++ b/packages/react-native-editor/__device-tests__/helpers/utils.js
@@ -12,8 +12,6 @@ const path = require( 'path' );
const serverConfigs = require( './serverConfigs' );
const { iosServer, iosLocal, android } = require( './caps' );
const AppiumLocal = require( './appium-local' );
-// eslint-disable-next-line import/no-extraneous-dependencies
-const _ = require( 'underscore' );
// Platform setup.
const defaultPlatform = 'android';
@@ -95,7 +93,7 @@ const setupDriver = async () => {
let desiredCaps;
if ( isAndroid() ) {
- desiredCaps = _.clone( android );
+ desiredCaps = { ...android };
if ( isLocalEnvironment() ) {
desiredCaps.app = path.resolve( localAndroidAppPath );
try {
@@ -117,10 +115,10 @@ const setupDriver = async () => {
desiredCaps.app = `sauce-storage:Gutenberg-${ safeBranchName }.apk`; // App should be preloaded to sauce storage, this can also be a URL.
}
} else {
- desiredCaps = _.clone( iosServer );
+ desiredCaps = { ...iosServer };
desiredCaps.app = `sauce-storage:Gutenberg-${ safeBranchName }.app.zip`; // App should be preloaded to sauce storage, this can also be a URL.
if ( isLocalEnvironment() ) {
- desiredCaps = _.clone( iosLocal );
+ desiredCaps = { ...iosLocal };
const iosPlatformVersions = getIOSPlatformVersions();
if ( iosPlatformVersions.length === 0 ) {
diff --git a/packages/react-native-editor/ios/Gemfile.lock b/packages/react-native-editor/ios/Gemfile.lock
index 030c5a4816ec88..98d409730b4bd4 100644
--- a/packages/react-native-editor/ios/Gemfile.lock
+++ b/packages/react-native-editor/ios/Gemfile.lock
@@ -74,7 +74,7 @@ GEM
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
- tzinfo (1.2.9)
+ tzinfo (1.2.10)
thread_safe (~> 0.1)
xcodeproj (1.19.0)
CFPropertyList (>= 2.3.3, < 4.0)
diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock
index 555e7b6dcb7ba6..7aa6fe0c4be61e 100644
--- a/packages/react-native-editor/ios/Podfile.lock
+++ b/packages/react-native-editor/ios/Podfile.lock
@@ -13,7 +13,7 @@ PODS:
- ReactCommon/turbomodule/core (= 0.66.2)
- fmt (6.2.1)
- glog (0.3.5)
- - Gutenberg (1.82.1):
+ - Gutenberg (1.83.0):
- React-Core (= 0.66.2)
- React-CoreModules (= 0.66.2)
- React-RCTImage (= 0.66.2)
@@ -350,7 +350,7 @@ PODS:
- React-Core
- RNSVG (9.13.6):
- React-Core
- - RNTAztecView (1.82.1):
+ - RNTAztecView (1.83.0):
- React-Core
- WordPress-Aztec-iOS (~> 1.19.8)
- SDWebImage (5.11.1):
@@ -528,7 +528,7 @@ SPEC CHECKSUMS:
FBReactNativeSpec: 18438b1c04ce502ed681cd19db3f4508964c082a
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 5337263514dd6f09803962437687240c5dc39aa4
- Gutenberg: 4c406229dfc941c04dc1923ef661bc42cdf48c42
+ Gutenberg: 031679fce5059a5f5c3ae7cc2e9952fbd1bf5d58
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
RCT-Folly: a21c126816d8025b547704b777a2ba552f3d9fa9
RCTRequired: 5e9e85f48da8dd447f5834ce14c6799ea8c7f41a
@@ -569,7 +569,7 @@ SPEC CHECKSUMS:
RNReanimated: b413cc7aa3e2a740d9804cda3a9396a68f9eea7f
RNScreens: 953633729a42e23ad0c93574d676b361e3335e8b
RNSVG: 36a7359c428dcb7c6bce1cc546fbfebe069809b0
- RNTAztecView: 8cb0bd37845a25eab416611e92d5adaf5a4931ac
+ RNTAztecView: cd8b382fee06712786e5a80a85f7069f0bd42045
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
WordPress-Aztec-iOS: 7d11d598f14c82c727c08b56bd35fbeb7dafb504
diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json
index bbed3427be5088..a031310dd7dba6 100644
--- a/packages/react-native-editor/package.json
+++ b/packages/react-native-editor/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/react-native-editor",
- "version": "1.82.1",
+ "version": "1.83.0",
"description": "Mobile WordPress gutenberg editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json
index 46d058e2a8a13c..c4f74b0b6017da 100644
--- a/packages/rich-text/package.json
+++ b/packages/rich-text/package.json
@@ -38,7 +38,6 @@
"@wordpress/escape-html": "file:../escape-html",
"@wordpress/i18n": "file:../i18n",
"@wordpress/keycodes": "file:../keycodes",
- "lodash": "^4.17.21",
"memize": "^1.1.0",
"rememo": "^4.0.0"
},
diff --git a/packages/rich-text/src/component/index.native.js b/packages/rich-text/src/component/index.native.js
index 623b243e910781..7fb9a25e1df63c 100644
--- a/packages/rich-text/src/component/index.native.js
+++ b/packages/rich-text/src/component/index.native.js
@@ -4,7 +4,6 @@
* External dependencies
*/
import { View, Platform, Dimensions } from 'react-native';
-import { get, pickBy } from 'lodash';
import memize from 'memize';
import { colord } from 'colord';
@@ -228,8 +227,10 @@ export class RichText extends Component {
onFormatChange( record ) {
const { start = 0, end = 0, activeFormats = [] } = record;
- const changeHandlers = pickBy( this.props, ( v, key ) =>
- key.startsWith( 'format_on_change_functions_' )
+ const changeHandlers = Object.fromEntries(
+ Object.entries( this.props ).filter( ( [ key ] ) =>
+ key.startsWith( 'format_on_change_functions_' )
+ )
);
Object.values( changeHandlers ).forEach( ( changeHandler ) => {
@@ -1282,10 +1283,7 @@ export default compose( [
select( 'core/block-editor' );
const parents = getBlockParents( clientId, true );
const parentBlock = parents ? getBlock( parents[ 0 ] ) : undefined;
- const parentBlockStyles = get( parentBlock, [
- 'attributes',
- 'childrenStyles',
- ] );
+ const parentBlockStyles = parentBlock?.attributes?.childrenStyles;
const settings = getSettings();
const baseGlobalStyles = settings?.__experimentalGlobalStylesBaseStyles;
diff --git a/packages/rich-text/src/get-active-format.js b/packages/rich-text/src/get-active-format.js
index 3028b327667613..783177168b60ab 100644
--- a/packages/rich-text/src/get-active-format.js
+++ b/packages/rich-text/src/get-active-format.js
@@ -1,13 +1,6 @@
-/**
- * External dependencies
- */
-
-import { find } from 'lodash';
-
/**
* Internal dependencies
*/
-
import { getActiveFormats } from './get-active-formats';
/** @typedef {import('./create').RichTextValue} RichTextValue */
@@ -26,5 +19,7 @@ import { getActiveFormats } from './get-active-formats';
* type, or undefined.
*/
export function getActiveFormat( value, formatType ) {
- return find( getActiveFormats( value ), { type: formatType } );
+ return getActiveFormats( value )?.find(
+ ( { type } ) => type === formatType
+ );
}
diff --git a/packages/rich-text/src/store/actions.js b/packages/rich-text/src/store/actions.js
index 9b14ac26bca5fc..b8abea4d0aa29b 100644
--- a/packages/rich-text/src/store/actions.js
+++ b/packages/rich-text/src/store/actions.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { castArray } from 'lodash';
-
/**
* Returns an action object used in signalling that format types have been
* added.
@@ -14,7 +9,9 @@ import { castArray } from 'lodash';
export function addFormatTypes( formatTypes ) {
return {
type: 'ADD_FORMAT_TYPES',
- formatTypes: castArray( formatTypes ),
+ formatTypes: Array.isArray( formatTypes )
+ ? formatTypes
+ : [ formatTypes ],
};
}
@@ -28,6 +25,6 @@ export function addFormatTypes( formatTypes ) {
export function removeFormatTypes( names ) {
return {
type: 'REMOVE_FORMAT_TYPES',
- names: castArray( names ),
+ names: Array.isArray( names ) ? names : [ names ],
};
}
diff --git a/packages/rich-text/src/store/reducer.js b/packages/rich-text/src/store/reducer.js
index 86148eb7f76ff9..9d299af39c4e69 100644
--- a/packages/rich-text/src/store/reducer.js
+++ b/packages/rich-text/src/store/reducer.js
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { omit } from 'lodash';
-
/**
* WordPress dependencies
*/
@@ -31,7 +26,11 @@ export function formatTypes( state = {}, action ) {
),
};
case 'REMOVE_FORMAT_TYPES':
- return omit( state, action.names );
+ return Object.fromEntries(
+ Object.entries( state ).filter(
+ ( [ key ] ) => ! action.names.includes( key )
+ )
+ );
}
return state;
diff --git a/packages/rich-text/src/store/selectors.js b/packages/rich-text/src/store/selectors.js
index d50347cf42e046..32a50cf89020d2 100644
--- a/packages/rich-text/src/store/selectors.js
+++ b/packages/rich-text/src/store/selectors.js
@@ -2,7 +2,6 @@
* External dependencies
*/
import createSelector from 'rememo';
-import { find } from 'lodash';
/**
* Returns all the available format types.
@@ -38,7 +37,7 @@ export function getFormatType( state, name ) {
* @return {?Object} Format type.
*/
export function getFormatTypeForBareElement( state, bareElementTagName ) {
- return find( getFormatTypes( state ), ( { className, tagName } ) => {
+ return getFormatTypes( state ).find( ( { className, tagName } ) => {
return className === null && bareElementTagName === tagName;
} );
}
@@ -52,7 +51,7 @@ export function getFormatTypeForBareElement( state, bareElementTagName ) {
* @return {?Object} Format type.
*/
export function getFormatTypeForClassName( state, elementClassName ) {
- return find( getFormatTypes( state ), ( { className } ) => {
+ return getFormatTypes( state ).find( ( { className } ) => {
if ( className === null ) {
return false;
}
diff --git a/packages/scripts/README.md b/packages/scripts/README.md
index 2efcd59301a194..18b89521a2e1da 100644
--- a/packages/scripts/README.md
+++ b/packages/scripts/README.md
@@ -676,7 +676,10 @@ module.exports = {
};
```
-If you follow this approach, please, be aware that future versions of this package may change what webpack and Babel plugins we bundle, default configs, etc. Should those changes be necessary, they will be registered in the [package’s CHANGELOG](https://github.com/WordPress/gutenberg/blob/HEAD/packages/scripts/CHANGELOG.md), so make sure to read it before upgrading.
+If you follow this approach, please, be aware that:
+
+- You should keep using the `wp-scripts` commands (`start` and `build`). Do not use `webpack` directly.
+- Future versions of this package may change what webpack and Babel plugins we bundle, default configs, etc. Should those changes be necessary, they will be registered in the [package’s CHANGELOG](https://github.com/WordPress/gutenberg/blob/HEAD/packages/scripts/CHANGELOG.md), so make sure to read it before upgrading.
## Contributing to this package
diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js
index 00bedfda870161..5347e126827cf7 100644
--- a/packages/scripts/config/webpack.config.js
+++ b/packages/scripts/config/webpack.config.js
@@ -25,6 +25,7 @@ const {
hasArgInCLI,
hasCssnanoConfig,
hasPostCSSConfig,
+ getWordPressSrcDirectory,
getWebpackEntryPoints,
getRenderPropPaths,
} = require( '../utils' );
@@ -233,7 +234,7 @@ const config = {
patterns: [
{
from: '**/block.json',
- context: process.env.WP_SRC_DIRECTORY,
+ context: getWordPressSrcDirectory(),
noErrorOnMissing: true,
transform( content, absoluteFrom ) {
const convertExtension = ( path ) => {
@@ -267,7 +268,7 @@ const config = {
},
{
from: '**/*.php',
- context: process.env.WP_SRC_DIRECTORY,
+ context: getWordPressSrcDirectory(),
noErrorOnMissing: true,
filter: ( filepath ) => {
return (
diff --git a/packages/scripts/utils/config.js b/packages/scripts/utils/config.js
index 6cb6eaeafe47c1..983706c98035c9 100644
--- a/packages/scripts/utils/config.js
+++ b/packages/scripts/utils/config.js
@@ -168,6 +168,16 @@ const getWebpackArgs = () => {
return webpackArgs;
};
+/**
+ * Returns the WordPress source directory. It defaults to 'src' if the
+ * `process.env.WP_SRC_DIRECTORY` variable is not set.
+ *
+ * @return {string} The WordPress source directory.
+ */
+function getWordPressSrcDirectory() {
+ return process.env.WP_SRC_DIRECTORY || 'src';
+}
+
/**
* Detects the list of entry points to use with webpack. There are three ways to do this:
* 1. Use the legacy webpack 4 format passed as CLI arguments.
@@ -185,10 +195,10 @@ function getWebpackEntryPoints() {
}
// Continue only if the source directory exists.
- if ( ! hasProjectFile( process.env.WP_SRC_DIRECTORY ) ) {
+ if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) {
log(
chalk.yellow(
- `Source directory "${ process.env.WP_SRC_DIRECTORY }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.`
+ `Source directory "${ getWordPressSrcDirectory() }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.`
)
);
return {};
@@ -197,7 +207,7 @@ function getWebpackEntryPoints() {
// 2. Checks whether any block metadata files can be detected in the defined source directory.
// It scans all discovered files looking for JavaScript assets and converts them to entry points.
const blockMetadataFiles = glob(
- `${ process.env.WP_SRC_DIRECTORY }/**/block.json`,
+ `${ getWordPressSrcDirectory() }/**/block.json`,
{
absolute: true,
}
@@ -205,7 +215,7 @@ function getWebpackEntryPoints() {
if ( blockMetadataFiles.length > 0 ) {
const srcDirectory = fromProjectRoot(
- process.env.WP_SRC_DIRECTORY + sep
+ getWordPressSrcDirectory() + sep
);
const entryPoints = blockMetadataFiles.reduce(
( accumulator, blockMetadataFile ) => {
@@ -232,9 +242,7 @@ function getWebpackEntryPoints() {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
- ) }". File is located outside of the "${
- process.env.WP_SRC_DIRECTORY
- }" directory.`
+ ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.`
)
);
return;
@@ -246,7 +254,7 @@ function getWebpackEntryPoints() {
// Detects the proper file extension used in the defined source directory.
const [ entryFilepath ] = glob(
- `${ process.env.WP_SRC_DIRECTORY }/${ entryName }.[jt]s?(x)`,
+ `${ getWordPressSrcDirectory() }/${ entryName }.[jt]s?(x)`,
{
absolute: true,
}
@@ -261,9 +269,7 @@ function getWebpackEntryPoints() {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
- ) }". File does not exist in the "${
- process.env.WP_SRC_DIRECTORY
- }" directory.`
+ ) }". File does not exist in the "${ getWordPressSrcDirectory() }" directory.`
)
);
return;
@@ -283,7 +289,7 @@ function getWebpackEntryPoints() {
// 3. Checks whether a standard file name can be detected in the defined source directory,
// and converts the discovered file to entry point.
const [ entryFile ] = glob(
- `${ process.env.WP_SRC_DIRECTORY }/index.[jt]s?(x)`,
+ `${ getWordPressSrcDirectory() }/index.[jt]s?(x)`,
{
absolute: true,
}
@@ -291,7 +297,7 @@ function getWebpackEntryPoints() {
if ( ! entryFile ) {
log(
chalk.yellow(
- `No entry file discovered in the "${ process.env.WP_SRC_DIRECTORY }" directory.`
+ `No entry file discovered in the "${ getWordPressSrcDirectory() }" directory.`
)
);
return {};
@@ -309,19 +315,19 @@ function getWebpackEntryPoints() {
*/
function getRenderPropPaths() {
// Continue only if the source directory exists.
- if ( ! hasProjectFile( process.env.WP_SRC_DIRECTORY ) ) {
+ if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) {
return [];
}
// Checks whether any block metadata files can be detected in the defined source directory.
const blockMetadataFiles = glob(
- `${ process.env.WP_SRC_DIRECTORY }/**/block.json`,
+ `${ getWordPressSrcDirectory() }/**/block.json`,
{
absolute: true,
}
);
- const srcDirectory = fromProjectRoot( process.env.WP_SRC_DIRECTORY + sep );
+ const srcDirectory = fromProjectRoot( getWordPressSrcDirectory() + sep );
const renderPaths = blockMetadataFiles.map( ( blockMetadataFile ) => {
const { render } = JSON.parse( readFileSync( blockMetadataFile ) );
@@ -342,9 +348,7 @@ function getRenderPropPaths() {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
- ) }". File is located outside of the "${
- process.env.WP_SRC_DIRECTORY
- }" directory.`
+ ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.`
)
);
return false;
@@ -360,6 +364,7 @@ function getRenderPropPaths() {
module.exports = {
getJestOverrideConfigFile,
getWebpackArgs,
+ getWordPressSrcDirectory,
getWebpackEntryPoints,
getRenderPropPaths,
hasBabelConfig,
diff --git a/packages/scripts/utils/index.js b/packages/scripts/utils/index.js
index 870d159da67335..870c2423361b53 100644
--- a/packages/scripts/utils/index.js
+++ b/packages/scripts/utils/index.js
@@ -13,6 +13,7 @@ const {
const {
getJestOverrideConfigFile,
getWebpackArgs,
+ getWordPressSrcDirectory,
getWebpackEntryPoints,
getRenderPropPaths,
hasBabelConfig,
@@ -34,6 +35,7 @@ module.exports = {
getNodeArgsFromCLI,
getPackageProp,
getWebpackArgs,
+ getWordPressSrcDirectory,
getWebpackEntryPoints,
getRenderPropPaths,
hasArgInCLI,
diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md
index 7ef6ef36c0e049..317e48e0c37c48 100644
--- a/packages/style-engine/README.md
+++ b/packages/style-engine/README.md
@@ -4,7 +4,7 @@ The Style Engine aims to provide a consistent API for rendering styling for bloc
Initially, it will offer a single, centralized agent responsible for generating block styles, and, in later phases, it will also assume the responsibility of processing and rendering optimized frontend CSS.
-## Important
+## Please note
This package is new as of WordPress 6.1 and therefore in its infancy.
@@ -23,23 +23,17 @@ For more information about the roadmap, please refer to [Block editor styles: in
### wp_style_engine_get_styles()
-Global public function to generate styles from a single style object, e.g., the value of
-a [block's attributes.style object](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/#styles)
-or
-the [top level styles in theme.json](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/).
+Global public function to generate styles from a single style object, e.g., the value of a [block's attributes.style object](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/#styles) or the [top level styles in theme.json](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/).
-See also [Using the Style Engine to generate block supports styles](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/using-the-style-engine-with-block-supports).
+See also [Using the Style Engine to generate block supports styles](https://github.com/WordPress/gutenberg/tree/HEAD/packages/style-engine/docs/using-the-style-engine-with-block-supports.md).
_Parameters_
- _$block_styles_ `array` A block's `attributes.style` object or the top level styles in theme.json
- _$options_ `array` An array of options to determine the output.
- - _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or '
- global-styles'. Default is 'block-supports'. When both `context` and `selector` are set, the style engine will store the CSS rules using the `context` as a key.
- - _convert_vars_to_classnames_ `boolean` Whether to skip converting CSS var:? values to var( --wp--preset--\* )
- values. Default is `false`.
- - _selector_ `string` When a selector is passed, `generate()` will return a full CSS rule `$selector { ...rules }`,
- otherwise a concatenated string of properties and values.
+ - _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'. When both `context` and `selector` are set, the Style Engine will store the CSS rules using the `context` as a key.
+ - _convert_vars_to_classnames_ `boolean` Whether to skip converting CSS var:? values to var( --wp--preset--\* ) values. Default is `false`.
+ - _selector_ `string` When a selector is passed, `generate()` will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values.
_Returns_
`array|null`
@@ -57,19 +51,25 @@ It will return compiled CSS declarations for inline styles, or, where a selector
To enqueue a style for rendering in the site's frontend, the `$options` array requires the following:
1. **selector (string)** - this is the CSS selector for your block style CSS declarations.
-2. **context (string)** - this tells the style engine where to store the styles. Styles in the same context will be
- stored together.
+2. **context (string)** - this tells the Style Engine where to store the styles. Styles in the same context will be stored together.
`wp_style_engine_get_styles` will return the compiled CSS and CSS declarations array.
#### Usage
+As mentioned, `wp_style_engine_get_styles()` is useful whenever you wish to generate CSS and/or classnames from a **block's style object**. A good example is [using the Style Engine to generate block supports styles](https://github.com/WordPress/gutenberg/tree/HEAD/packages/style-engine/docs/using-the-style-engine-with-block-supports.md).
+
+In the following snippet, we're taking the style object from a block's attributes and passing it to the Style Engine to get the styles. By passing a `context` in the options, the Style Engine will store the styles for later retrieval, for example, should you wish to batch enqueue a set of CSS rules.
+
```php
-$block_styles = array(
- 'spacing' => array( 'padding' => '100px' )
+$block_attributes = array(
+ 'style' => array(
+ 'spacing' => array( 'padding' => '100px' ),
+ ),
);
+
$styles = wp_style_engine_get_styles(
- $block_styles,
+ $block_attributes['style'],
array(
'selector' => '.a-selector',
'context' => 'block-supports',
@@ -79,46 +79,53 @@ print_r( $styles );
/*
array(
- 'css' => '.a-selector{padding:100px}'
- 'declarations' => array( 'padding' => '100px' )
+ 'css' => '.a-selector{padding:100px}'
+ 'declarations' => array( 'padding' => '100px' )
)
*/
```
### wp_style_engine_get_stylesheet_from_css_rules()
-Use this function to compile and return a stylesheet for any CSS rules. The style engine will automatically merge declarations and combine selectors.
+Use this function to compile and return a stylesheet for any CSS rules. The Style Engine will automatically merge declarations and combine selectors.
-This function acts as a CSS compiler, but will also enqueue styles for rendering where `enqueue` and `context` strings are passed in the options.
+This function acts as a CSS compiler, but will also register the styles in a store where a `context` string is passed in the options.
_Parameters_
- _$css_rules_ `array`
-- _$options_ `array` An array of options to determine the output.
- - _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or '
- global-styles'. When set, the style engine will store the CSS rules using the `context` value as a key.
+- _$options_ `array` An array of options to determine the output.
+ - _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'. When set, the Style Engine will attempt to store the CSS rules.
+ - _prettify_ `bool` Whether to add new lines and indents to output. Default is to inherit the value of the global constant `SCRIPT_DEBUG`, if it is defined.
+ - _optimize_ `bool` Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
_Returns_
`string` A compiled CSS string based on `$css_rules`.
#### Usage
+Useful for when you wish to compile a bespoke set of CSS rules from a series of selector + declaration items.
+
+The Style Engine will return a sanitized and optimized stylesheet. By passing a `context` identifier in the options, the Style Engine will store the styles for later retrieval, for example, should you wish to batch enqueue a set of CSS rules.
+
+You can call `wp_style_engine_get_stylesheet_from_css_rules()` multiple times, and, so long as your styles use the same `context` identifier, they will be stored together.
+
```php
$styles = array(
array(
- 'selector'. => '.wp-pumpkin',
+ 'selector' => '.wp-pumpkin',
'declarations' => array( 'color' => 'orange' )
),
array(
- 'selector'. => '.wp-tomato',
+ 'selector' => '.wp-tomato',
'declarations' => array( 'color' => 'red' )
),
array(
- 'selector'. => '.wp-tomato',
+ 'selector' => '.wp-tomato',
'declarations' => array( 'padding' => '100px' )
),
array(
- 'selector'. => '.wp-kumquat',
+ 'selector' => '.wp-kumquat',
'declarations' => array( 'color' => 'orange' )
),
);
@@ -126,7 +133,7 @@ $styles = array(
$stylesheet = wp_style_engine_get_stylesheet_from_css_rules(
$styles,
array(
- 'context' => 'block-supports', // Indicates that these styles should be stored with block supports CSS.
+ 'context' => 'block-supports', // Indicates that these styles should be stored with block supports CSS.
)
);
print_r( $stylesheet ); // .wp-pumpkin,.wp-kumquat{color:orange}.wp-tomato{color:red;padding:100px}
@@ -139,34 +146,40 @@ Returns compiled CSS from a stored context, if found.
_Parameters_
- _$store_name_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or ' global-styles'. Default is 'block-supports'.
+- _$options_ `array` An array of options to determine the output.
+ - _prettify_ `bool` Whether to add new lines and indents to output. Default is to inherit the value of the global constant `SCRIPT_DEBUG`, if it is defined.
+ - _optimize_ `bool` Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
_Returns_
`string` A compiled CSS string from the stored CSS rules.
#### Usage
-A use case would be to fetch the stylesheet, which contains all the compiled CSS rules from the store, and enqueue it for rendering on the frontend.
+Use this function to generate a stylesheet using all the styles stored under a specific context identifier.
+
+A use case would be when you wish to enqueue all stored styles for rendering to the frontend. The Style Engine will merge and deduplicate styles upon retrieval.
```php
-// First register some styles.
+// First, let's gather and register our styles.
$styles = array(
array(
- 'selector'. => '.wp-apple',
+ 'selector' => '.wp-apple',
'declarations' => array( 'color' => 'green' )
),
);
-$stylesheet = wp_style_engine_get_stylesheet_from_css_rules(
+wp_style_engine_get_stylesheet_from_css_rules(
$styles,
array(
- 'context' => 'fruit-styles',
- 'enqueue' => true,
+ 'context' => 'fruit-styles',
)
);
-// Later, fetch compiled rules from context store.
-$stylesheet = gutenberg_style_engine_get_stylesheet_from_context( 'fruit-styles' );
+// Later, we fetch compiled rules from context store.
+$stylesheet = wp_style_engine_get_stylesheet_from_context( 'fruit-styles' );
+
print_r( $stylesheet ); // .wp-apple{color:green;}
+
if ( ! empty( $stylesheet ) ) {
wp_register_style( 'my-stylesheet', false, array(), true, true );
wp_add_inline_style( 'my-stylesheet', $stylesheet );
@@ -242,7 +255,7 @@ A guide to the terms and variable names referenced by the Style Engine package.
CSS rule
A CSS selector followed by a CSS declarations block inside a set of curly braces. Usually found in a CSS stylesheet.
CSS selector (or CSS class selector)
- The first component of a CSS rule, a CSS selector is a pattern of elements, classnames or other terms that define the element to which the rule’s CSS definitions apply. E.g., p.my-cool-classname > span
. A CSS selector matches HTML elements based on the contents of the "class" attribute. See MDN CSS selectors article .
+ The first component of a CSS rule, a CSS selector is a pattern of elements, classnames or other terms that define the element to which the rule’s CSS definitions apply. E.g., p.my-cool-classname > span
. A CSS selector matches HTML elements based on the contents of the "class" attribute. See MDN CSS selectors article .
CSS stylesheet
A collection of CSS rules contained within a file or within an HTML style tag .
CSS value
diff --git a/packages/style-engine/class-wp-style-engine-css-declarations.php b/packages/style-engine/class-wp-style-engine-css-declarations.php
index 243bc2b27d6cdb..360d992c6a3b38 100644
--- a/packages/style-engine/class-wp-style-engine-css-declarations.php
+++ b/packages/style-engine/class-wp-style-engine-css-declarations.php
@@ -12,7 +12,7 @@
}
/**
- * Holds, sanitizes, processes and prints CSS declarations for the style engine.
+ * Holds, sanitizes, processes and prints CSS declarations for the Style Engine.
*
* @access private
*/
diff --git a/packages/style-engine/class-wp-style-engine-css-rule.php b/packages/style-engine/class-wp-style-engine-css-rule.php
index f0f0c80ec5d6ab..e1605517573313 100644
--- a/packages/style-engine/class-wp-style-engine-css-rule.php
+++ b/packages/style-engine/class-wp-style-engine-css-rule.php
@@ -12,7 +12,7 @@
}
/**
- * Holds, sanitizes, processes and prints CSS declarations for the style engine.
+ * Holds, sanitizes, processes and prints CSS declarations for the Style Engine.
*
* @access private
*/
diff --git a/packages/style-engine/class-wp-style-engine-css-rules-store.php b/packages/style-engine/class-wp-style-engine-css-rules-store.php
index ae657ab69de431..5d083efbd1527a 100644
--- a/packages/style-engine/class-wp-style-engine-css-rules-store.php
+++ b/packages/style-engine/class-wp-style-engine-css-rules-store.php
@@ -12,7 +12,7 @@
}
/**
- * Holds, sanitizes, processes and prints CSS declarations for the style engine.
+ * Holds, sanitizes, processes and prints CSS declarations for the Style Engine.
*
* @access private
*/
diff --git a/packages/style-engine/class-wp-style-engine-processor.php b/packages/style-engine/class-wp-style-engine-processor.php
index 6b82f31944c6c8..9030cf8e24ca27 100644
--- a/packages/style-engine/class-wp-style-engine-processor.php
+++ b/packages/style-engine/class-wp-style-engine-processor.php
@@ -85,7 +85,7 @@ public function add_rules( $css_rules ) {
* Optional. An array of options. Default empty array.
*
* @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
- * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
+ * @type bool $prettify Whether to add new lines and indents to output. Default is to inherit the value of the global constant `SCRIPT_DEBUG`, if it is defined.
* }
*
* @return string The computed CSS.
diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php
index 1d6926179f6523..54f60131a55267 100644
--- a/packages/style-engine/class-wp-style-engine.php
+++ b/packages/style-engine/class-wp-style-engine.php
@@ -17,11 +17,12 @@
* The Style Engine aims to provide a consistent API for rendering styling for blocks across both client-side and server-side applications.
*
* This class is for internal Core usage and is not supposed to be used by extenders (plugins and/or themes).
+ * This class is final and should not be extended.
* This is a low-level API that may need to do breaking changes. Please, use wp_style_engine_get_styles instead.
*
* @access private
*/
-class WP_Style_Engine {
+final class WP_Style_Engine {
/**
* Style definitions that contain the instructions to
* parse/output valid Gutenberg styles from a block's attributes.
@@ -107,28 +108,28 @@ class WP_Style_Engine {
'path' => array( 'border', 'width' ),
),
'top' => array(
- 'value_func' => 'static::get_individual_property_css_declarations',
+ 'value_func' => array( self::class, 'get_individual_property_css_declarations' ),
'path' => array( 'border', 'top' ),
'css_vars' => array(
'color' => '--wp--preset--color--$slug',
),
),
'right' => array(
- 'value_func' => 'static::get_individual_property_css_declarations',
+ 'value_func' => array( self::class, 'get_individual_property_css_declarations' ),
'path' => array( 'border', 'right' ),
'css_vars' => array(
'color' => '--wp--preset--color--$slug',
),
),
'bottom' => array(
- 'value_func' => 'static::get_individual_property_css_declarations',
+ 'value_func' => array( self::class, 'get_individual_property_css_declarations' ),
'path' => array( 'border', 'bottom' ),
'css_vars' => array(
'color' => '--wp--preset--color--$slug',
),
),
'left' => array(
- 'value_func' => 'static::get_individual_property_css_declarations',
+ 'value_func' => array( self::class, 'get_individual_property_css_declarations' ),
'path' => array( 'border', 'left' ),
'css_vars' => array(
'color' => '--wp--preset--color--$slug',
diff --git a/packages/style-engine/docs/toc.json b/packages/style-engine/docs/toc.json
new file mode 100644
index 00000000000000..9feeb5f7db5e4d
--- /dev/null
+++ b/packages/style-engine/docs/toc.json
@@ -0,0 +1,8 @@
+[
+ {
+ "title": "@wordpress/style-engine Using the Style Engine to generate block supports styles",
+ "slug": "using-the-style-engine-with-block-supports",
+ "markdown_source": "../packages/style-engine/docs/using-the-style-engine-with-block-supports.md",
+ "parent": "packages-style-engine"
+ }
+]
diff --git a/packages/style-engine/docs/using-the-style-engine-with-block-supports.md b/packages/style-engine/docs/using-the-style-engine-with-block-supports.md
index 5e7c82574f703e..3587a89388ed08 100644
--- a/packages/style-engine/docs/using-the-style-engine-with-block-supports.md
+++ b/packages/style-engine/docs/using-the-style-engine-with-block-supports.md
@@ -46,45 +46,105 @@ array(
*/
```
+## Use case
+When [registering a block support](https://developer.wordpress.org/reference/classes/wp_block_supports/register/), it is possible to pass an 'apply' callback in the block support config array to add or extend block support attributes with "class" or "style" properties.
+
+If a block has opted into the block support, the values of "class" and "style" will be applied to the block element's "class" and "style" attributes accordingly when rendered in the frontend HTML. Note, this applies only to server-side rendered blocks, for example, the [Site Title block](https://developer.wordpress.org/block-editor/reference-guides/core-blocks/#site-title).
+
+The callback receives `$block_type` and `$block_attributes` as arguments. The `style` attribute within `$block_attributes` only contains the raw style object, if any styles have been set for the block, and not any CSS or classnames to be applied to the block's HTML elements.
+
+Here is where `wp_style_engine_get_styles` comes in handy: it will generate CSS and, if appropriate, classnames to be added to the "style" and "class" HTML attributes in the final rendered block markup.
+
+Here is a _very_ simplified version of how the [color block support](https://github.com/WordPress/gutenberg/tree/HEAD/lib/block-supports/color.php) works:
+
+```php
+function gutenberg_apply_colors_support( $block_type, $block_attributes ) {
+ // Get the color styles from the style object.
+ $block_color_styles = isset( $block_attributes['style']['color'] ) ? $block_attributes['style']['color'] : null;
+
+ // Since we only want the color styles, pass the color styles only to the Style Engine.
+ $styles = wp_style_engine_get_styles( array( 'color' => $block_color_styles ) );
+
+ // Return the generated styles to be applied to the block's HTML element.
+ return array(
+ 'style' => $styles['css'],
+ 'class' => $styles['classnames']
+ );
+}
+
+// Register the block support.
+WP_Block_Supports::get_instance()->register(
+ 'colors',
+ array(
+ 'register_attribute' => 'gutenberg_register_colors_support',
+ 'apply' => 'gutenberg_apply_colors_support',
+ )
+);
+```
+
+It's important to note that, for now, the Style Engine will only generate styles for the following, core block supports:
+
+- border
+- color
+- spacing
+- typography
+
+In future releases, it will be possible to extend this list.
+
## Checking for block support and skip serialization
-Before passing the block style object to the Style Engine, it's important to take into account:
+Before passing the block style object to the Style Engine, you'll need to take into account:
1. whether the theme has elected to support a particular block style, and
2. whether a block has elected to "skip serialization" of that particular block style, that is, opt-out of automatic application of styles to the block's element (usually in order to do it via the block's internals). See the [block API documentation](https://developer.wordpress.org/block-editor/explanations/architecture/styles/#block-supports-api) for further information.
If a block either:
-- has no support for a specific style, or
+- has no support for a style, or
- skips serialization of that style
-it's likely that you'll want to remove those style values from the style object.
-
-For example:
-
-```php
-// Check if a block has support using block_has_support (https://developer.wordpress.org/reference/functions/block_has_support/)
-$has_padding_support = block_has_support( $block_type, array( 'spacing', 'padding' ), false ); // Returns true.
-$has_margin_support = block_has_support( $block_type, array( 'spacing', 'margin' ), false ); // Returns false.
-
-// Check skipping of serialization.
-$should_skip_padding = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' ); // Returns true.
-$should_skip_margin = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' ); // Returns false.
+it's likely that you'll want to remove those style values from the style object before passing it to the Style Engine with help of two functions:
-// Now build the styles object.
-$spacing_block_styles = array();
-$spacing_block_styles['padding'] = $has_padding_support && ! $skip_padding ? _wp_array_get( $block_attributes['style'], array( 'spacing', 'padding' ), null ) : null;
-$spacing_block_styles['margin'] = $has_margin_support && ! $skip_margin ? _wp_array_get( $block_attributes['style'], array( 'spacing', 'margin' ), null ) : null;
+- wp_should_skip_block_supports_serialization()
+- block_has_support()
-// Now get the styles.
-$styles = wp_style_engine_get_styles( array( 'spacing' => $spacing_block_styles ) );
+We can now update the apply callback code above so that we'll only return "style" and "class", where a block has support and it doesn't skip serialization:
-print_r( $styles );
-
-/*
-// Nothing, because there's no support for margin and the block skip's serialization for padding.
-array()
-*/
+```php
+function gutenberg_apply_colors_support( $block_type, $block_attributes ) {
+ // The return value.
+ $attributes = array();
+
+ // Return early if the block skips all serialization for block supports.
+ if ( gutenberg_should_skip_block_supports_serialization( $block_type, 'color' ) ) {
+ return $attributes;
+ }
+
+ // Checks for support and skip serialization.
+ $has_text_support = block_has_support( $block_type, array( 'color', 'text' ), false );
+ $has_background_support = block_has_support( $block_type, array( 'color', 'background' ), false );
+ $skips_serialization_of_color_text = wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' );
+ $skips_serialization_of_color_background = wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' );
+
+ // Get the color styles from the style object.
+ $block_color_styles = isset( $block_attributes['style']['color'] ) ? $block_attributes['style']['color'] : null;
+
+ // The mutated styles object we're going to pass to wp_style_engine_get_styles().
+ $color_block_styles = array();
+
+ // Set the color style values according to whether the block has support and does not skip serialization.
+ $spacing_block_styles['text'] = $has_text_support && ! $skips_serialization_of_color_text ? _wp_array_get( $block_color_styles, array( 'text' ), null ) : null;
+ $spacing_block_styles['background'] = $has_background_support && ! $skips_serialization_of_color_background ? _wp_array_get( $block_color_styles, array( 'background' ), null ) : null;
+
+ // Pass the color styles, excluding those that have no support or skip serialization, to the Style Engine.
+ $styles = wp_style_engine_get_styles( array( 'color' => $block_color_styles ) );
+
+ // Return the generated styles to be applied to the block's HTML element.
+ return array(
+ 'style' => $styles['css'],
+ 'class' => $styles['classnames']
+ );
+}
```
## Generating classnames and CSS custom selectors from presets
@@ -110,8 +170,8 @@ $preset_font_size = "var:preset|font-size|{$block_attributes['fontSize']}
$preset_background_color = "var:preset|color|{$block_attributes['backgroundColor']}";
$block_styles = array(
- 'typography' => array( 'fontSize' => $preset_font_size ),
- 'color' => array( 'background' => $preset_background_color )
+ 'typography' => array( 'fontSize' => $preset_font_size ),
+ 'color' => array( 'background' => $preset_background_color )
);
$styles = wp_style_engine_get_styles(
@@ -131,12 +191,12 @@ If you don't want the Style Engine to output the CSS custom vars as well, which
```php
$options = array(
- // Whether to skip converting CSS var:? values to var( --wp--preset--* ) values. Default is `false`.
- 'convert_vars_to_classnames' => 'true',
+ // Whether to skip converting CSS var:? values to var( --wp--preset--* ) values. Default is `false`.
+ 'convert_vars_to_classnames' => 'true',
);
$styles = wp_style_engine_get_styles(
- $block_styles,
- $options
+ $block_styles,
+ $options
);
print_r( $styles );
diff --git a/packages/style-engine/phpunit/style-engine-test.php b/packages/style-engine/phpunit/style-engine-test.php
index 98c833359474a6..2ec8205c742021 100644
--- a/packages/style-engine/phpunit/style-engine-test.php
+++ b/packages/style-engine/phpunit/style-engine-test.php
@@ -60,7 +60,7 @@ public function tear_down() {
* An array of options to pass to `wp_style_engine_get_styles()`.
*
* @type string|null $context An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is `null`.
- * When set, the style engine will attempt to store the CSS rules, where a selector is also passed.
+ * When set, the Style Engine will attempt to store the CSS rules, where a selector is also passed.
* @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset||`, to var( --wp--preset--* ) values. Default `false`.
* @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`,
* otherwise, the value will be a concatenated string of CSS declarations.
@@ -363,13 +363,13 @@ public function data_wp_style_engine_get_styles() {
'spacing' => array(
'margin' => array(
'left' => 'var:preset|spacing|10',
- 'right' => 'var:preset|spacing|20',
+ 'right' => 'var:preset|spacing|3XL',
'top' => '1rem',
'bottom' => '1rem',
),
'padding' => array(
'left' => 'var:preset|spacing|30',
- 'right' => 'var:preset|spacing|40',
+ 'right' => 'var:preset|spacing|3XL',
'top' => '14px',
'bottom' => '14px',
),
@@ -377,14 +377,14 @@ public function data_wp_style_engine_get_styles() {
),
'options' => array(),
'expected_output' => array(
- 'css' => 'padding-left:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--40);padding-top:14px;padding-bottom:14px;margin-left:var(--wp--preset--spacing--10);margin-right:var(--wp--preset--spacing--20);margin-top:1rem;margin-bottom:1rem;',
+ 'css' => 'padding-left:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--3-xl);padding-top:14px;padding-bottom:14px;margin-left:var(--wp--preset--spacing--10);margin-right:var(--wp--preset--spacing--3-xl);margin-top:1rem;margin-bottom:1rem;',
'declarations' => array(
'padding-left' => 'var(--wp--preset--spacing--30)',
- 'padding-right' => 'var(--wp--preset--spacing--40)',
+ 'padding-right' => 'var(--wp--preset--spacing--3-xl)',
'padding-top' => '14px',
'padding-bottom' => '14px',
'margin-left' => 'var(--wp--preset--spacing--10)',
- 'margin-right' => 'var(--wp--preset--spacing--20)',
+ 'margin-right' => 'var(--wp--preset--spacing--3-xl)',
'margin-top' => '1rem',
'margin-bottom' => '1rem',
),
diff --git a/packages/style-engine/src/styles/outline/index.ts b/packages/style-engine/src/styles/outline/index.ts
index c6c3101fa90272..4526b31f1fa40f 100644
--- a/packages/style-engine/src/styles/outline/index.ts
+++ b/packages/style-engine/src/styles/outline/index.ts
@@ -22,7 +22,7 @@ const offset = {
style: Style,
options: StyleOptions,
path: string[] = [ 'outline', 'offset' ],
- ruleKey: string = 'outlineColor'
+ ruleKey: string = 'outlineOffset'
): GeneratedCSSRule[] => {
return generateRule( style, options, path, ruleKey );
},
diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts
index f0c3112d230b34..71e59738995e9a 100644
--- a/packages/style-engine/src/styles/utils.ts
+++ b/packages/style-engine/src/styles/utils.ts
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import { get } from 'lodash';
+import { get, kebabCase } from 'lodash';
/**
* Internal dependencies
@@ -119,6 +119,7 @@ export function getCSSVarFromStyleValue( styleValue: string ): string {
const variable = styleValue
.slice( VARIABLE_REFERENCE_PREFIX.length )
.split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE )
+ .map( ( presetVariable ) => kebabCase( presetVariable ) )
.join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE );
return `var(--wp--${ variable })`;
}
diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js
index 871dbce08cc5ae..cbddab4d5ca8db 100644
--- a/packages/style-engine/src/test/index.js
+++ b/packages/style-engine/src/test/index.js
@@ -73,13 +73,19 @@ describe( 'generate', () => {
letterSpacing: '12px',
textTransform: 'uppercase',
},
+ outline: {
+ offset: '2px',
+ width: '4px',
+ style: 'dashed',
+ color: 'red',
+ },
},
{
selector: '.some-selector',
}
)
).toEqual(
- ".some-selector { color: #cccccc; background: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(33,32,33) 42%,rgb(65,88,208) 100%); background-color: #111111; margin-top: 11px; margin-right: 12px; margin-bottom: 13px; margin-left: 14px; padding-top: 10px; padding-bottom: 5px; font-family: 'Helvetica Neue',sans-serif; font-size: 2.2rem; font-style: italic; font-weight: 800; letter-spacing: 12px; line-height: 3.3; text-decoration: line-through; text-transform: uppercase; }"
+ ".some-selector { color: #cccccc; background: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(33,32,33) 42%,rgb(65,88,208) 100%); background-color: #111111; outline-color: red; outline-style: dashed; outline-offset: 2px; outline-width: 4px; margin-top: 11px; margin-right: 12px; margin-bottom: 13px; margin-left: 14px; padding-top: 10px; padding-bottom: 5px; font-family: 'Helvetica Neue',sans-serif; font-size: 2.2rem; font-style: italic; font-weight: 800; letter-spacing: 12px; line-height: 3.3; text-decoration: line-through; text-transform: uppercase; }"
);
} );
@@ -96,6 +102,19 @@ describe( 'generate', () => {
);
} );
+ it( 'should parse preset values and kebab-case the slug', () => {
+ expect(
+ compileCSS( {
+ color: {
+ text: 'var:preset|font-size|h1',
+ },
+ spacing: { margin: { top: 'var:preset|spacing|3XL' } },
+ } )
+ ).toEqual(
+ 'color: var(--wp--preset--font-size--h-1); margin-top: var(--wp--preset--spacing--3-xl);'
+ );
+ } );
+
it( 'should parse border rules', () => {
expect(
compileCSS( {
@@ -221,6 +240,13 @@ describe( 'getCSSRules', () => {
letterSpacing: '12px',
textTransform: 'uppercase',
},
+ outline: {
+ offset: '2px',
+ width: '4px',
+ style: 'dashed',
+ color: 'red',
+ },
+ shadow: '10px 10px red',
},
{
selector: '.some-selector',
@@ -242,6 +268,26 @@ describe( 'getCSSRules', () => {
key: 'backgroundColor',
value: '#555555',
},
+ {
+ selector: '.some-selector',
+ key: 'outlineColor',
+ value: 'red',
+ },
+ {
+ selector: '.some-selector',
+ key: 'outlineStyle',
+ value: 'dashed',
+ },
+ {
+ selector: '.some-selector',
+ key: 'outlineOffset',
+ value: '2px',
+ },
+ {
+ selector: '.some-selector',
+ key: 'outlineWidth',
+ value: '4px',
+ },
{
selector: '.some-selector',
key: 'marginRight',
@@ -263,45 +309,50 @@ describe( 'getCSSRules', () => {
value: '5px',
},
{
- key: 'fontFamily',
selector: '.some-selector',
+ key: 'fontFamily',
value: "'Helvetica Neue',sans-serif",
},
{
- key: 'fontSize',
selector: '.some-selector',
+ key: 'fontSize',
value: '2.2rem',
},
{
- key: 'fontStyle',
selector: '.some-selector',
+ key: 'fontStyle',
value: 'italic',
},
{
- key: 'fontWeight',
selector: '.some-selector',
+ key: 'fontWeight',
value: '800',
},
{
- key: 'letterSpacing',
selector: '.some-selector',
+ key: 'letterSpacing',
value: '12px',
},
{
- key: 'lineHeight',
selector: '.some-selector',
+ key: 'lineHeight',
value: '3.3',
},
{
- key: 'textDecoration',
selector: '.some-selector',
+ key: 'textDecoration',
value: 'line-through',
},
{
- key: 'textTransform',
selector: '.some-selector',
+ key: 'textTransform',
value: 'uppercase',
},
+ {
+ selector: '.some-selector',
+ key: 'boxShadow',
+ value: '10px 10px red',
+ },
] );
} );
diff --git a/packages/style-engine/src/test/utils.js b/packages/style-engine/src/test/utils.js
index 62dec772979060..a45d9256dc1c09 100644
--- a/packages/style-engine/src/test/utils.js
+++ b/packages/style-engine/src/test/utils.js
@@ -1,7 +1,11 @@
/**
* Internal dependencies
*/
-import { camelCaseJoin, upperFirst } from '../styles/utils';
+import {
+ camelCaseJoin,
+ getCSSVarFromStyleValue,
+ upperFirst,
+} from '../styles/utils';
describe( 'utils', () => {
describe( 'upperFirst()', () => {
@@ -9,9 +13,30 @@ describe( 'utils', () => {
expect( upperFirst( 'toontown' ) ).toEqual( 'Toontown' );
} );
} );
+
describe( 'camelCaseJoin()', () => {
it( 'should return a camelCase string', () => {
expect( camelCaseJoin( [ 'toon', 'town' ] ) ).toEqual( 'toonTown' );
} );
} );
+
+ describe( 'getCSSVarFromStyleValue()', () => {
+ it( 'should return a compiled CSS var', () => {
+ expect(
+ getCSSVarFromStyleValue( 'var:preset|color|yellow-bun' )
+ ).toEqual( 'var(--wp--preset--color--yellow-bun)' );
+ } );
+
+ it( 'should kebab case numbers', () => {
+ expect(
+ getCSSVarFromStyleValue( 'var:preset|font-size|h1' )
+ ).toEqual( 'var(--wp--preset--font-size--h-1)' );
+ } );
+
+ it( 'should kebab case camel case', () => {
+ expect(
+ getCSSVarFromStyleValue( 'var:preset|color|heavenlyBlue' )
+ ).toEqual( 'var(--wp--preset--color--heavenly-blue)' );
+ } );
+ } );
} );
diff --git a/packages/style-engine/style-engine.php b/packages/style-engine/style-engine.php
index c7a5d5a71428c8..4571a2fcce4ffe 100644
--- a/packages/style-engine/style-engine.php
+++ b/packages/style-engine/style-engine.php
@@ -26,7 +26,7 @@
* Optional. An array of options. Default empty array.
*
* @type string|null $context An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is `null`.
- * When set, the style engine will attempt to store the CSS rules, where a selector is also passed.
+ * When set, the Style Engine will attempt to store the CSS rules, where a selector is also passed.
* @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset||`, to var( --wp--preset--* ) values. Default `false`.
* @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`,
* otherwise, the value will be a concatenated string of CSS declarations.
@@ -91,9 +91,9 @@ function wp_style_engine_get_styles( $block_styles, $options = array() ) {
* Optional. An array of options. Default empty array.
*
* @type string|null $context An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'.
- * When set, the style engine will attempt to store the CSS rules.
+ * When set, the Style Engine will attempt to store the CSS rules.
* @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
- * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
+ * @type bool $prettify Whether to add new lines and indents to output. Default is to inherit the value of the global constant `SCRIPT_DEBUG`, if it is defined.
* }
*
* @return string A string of compiled CSS declarations, or empty string.
@@ -140,7 +140,7 @@ function wp_style_engine_get_stylesheet_from_css_rules( $css_rules, $options = a
* Optional. An array of options. Default empty array.
*
* @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
- * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
+ * @type bool $prettify Whether to add new lines and indents to output. Default is to inherit the value of the global constant `SCRIPT_DEBUG`, if it is defined.
* }
*
* @return string A compiled CSS string.
diff --git a/packages/widgets/src/blocks/legacy-widget/edit/preview.js b/packages/widgets/src/blocks/legacy-widget/edit/preview.js
index 3d731672e87435..a23e046572ce3e 100644
--- a/packages/widgets/src/blocks/legacy-widget/edit/preview.js
+++ b/packages/widgets/src/blocks/legacy-widget/edit/preview.js
@@ -61,10 +61,15 @@ export default function Preview( { idBase, instance, isVisible } ) {
function setHeight() {
// Pick the maximum of these two values to account for margin collapsing.
const height = Math.max(
- iframe.contentDocument.documentElement.offsetHeight,
- iframe.contentDocument.body.offsetHeight
+ iframe.contentDocument.documentElement?.offsetHeight ?? 0,
+ iframe.contentDocument.body?.offsetHeight ?? 0
);
- iframe.style.height = `${ height }px`;
+
+ // Fallback to a height of 100px if the height cannot be determined.
+ // This ensures the block is still selectable. 100px should hopefully
+ // be not so big that it's annoying, and not so small that nothing
+ // can be seen.
+ iframe.style.height = `${ height !== 0 ? height : 100 }px`;
}
const { IntersectionObserver } = iframe.ownerDocument.defaultView;
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 59c87341f6eb29..7473a44d819bc3 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -2,8 +2,10 @@
Sniffs for WordPress plugins, with minor modifications for Gutenberg
-
+
+ *\.php$
+
diff --git a/phpunit/block-supports/border-test.php b/phpunit/block-supports/border-test.php
index dd2b279867aeb7..7c8bd9975d35bb 100644
--- a/phpunit/block-supports/border-test.php
+++ b/phpunit/block-supports/border-test.php
@@ -12,12 +12,12 @@ class WP_Block_Supports_Border_Test extends WP_UnitTestCase {
*/
private $test_block_name;
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->test_block_name = null;
}
- function tear_down() {
+ public function tear_down() {
unregister_block_type( $this->test_block_name );
$this->test_block_name = null;
parent::tear_down();
@@ -53,7 +53,7 @@ private function register_bordered_block_with_support( $block_name, $supports =
return $registry->get_registered( $this->test_block_name );
}
- function test_border_object_with_no_styles() {
+ public function test_border_object_with_no_styles() {
$block_type = self::register_bordered_block_with_support(
'test/border-object-with-no-styles',
array(
@@ -72,7 +72,7 @@ function test_border_object_with_no_styles() {
$this->assertSame( $expected, $actual );
}
- function test_border_object_with_invalid_style_prop() {
+ public function test_border_object_with_invalid_style_prop() {
$block_type = self::register_bordered_block_with_support(
'test/border-object-with-invalid-style-prop',
array(
@@ -91,7 +91,7 @@ function test_border_object_with_invalid_style_prop() {
$this->assertSame( $expected, $actual );
}
- function test_border_color_slug_with_numbers_is_kebab_cased_properly() {
+ public function test_border_color_slug_with_numbers_is_kebab_cased_properly() {
$block_type = self::register_bordered_block_with_support(
'test/border-color-slug-with-numbers-is-kebab-cased-properly',
array(
@@ -123,7 +123,7 @@ function test_border_color_slug_with_numbers_is_kebab_cased_properly() {
$this->assertSame( $expected, $actual );
}
- function test_flat_border_with_skipped_serialization() {
+ public function test_flat_border_with_skipped_serialization() {
$block_type = self::register_bordered_block_with_support(
'test/flat-border-with-skipped-serialization',
array(
@@ -153,7 +153,7 @@ function test_flat_border_with_skipped_serialization() {
$this->assertSame( $expected, $actual );
}
- function test_flat_border_with_individual_skipped_serialization() {
+ public function test_flat_border_with_individual_skipped_serialization() {
$block_type = self::register_bordered_block_with_support(
'test/flat-border-with-individual-skipped-serialization',
array(
@@ -185,7 +185,7 @@ function test_flat_border_with_individual_skipped_serialization() {
$this->assertSame( $expected, $actual );
}
- function test_split_border_radius() {
+ public function test_split_border_radius() {
$block_type = self::register_bordered_block_with_support(
'test/split-border-radius',
array(
@@ -214,7 +214,7 @@ function test_split_border_radius() {
$this->assertSame( $expected, $actual );
}
- function test_flat_border_with_custom_color() {
+ public function test_flat_border_with_custom_color() {
$block_type = self::register_bordered_block_with_support(
'test/flat-border-with-custom-color',
array(
@@ -243,7 +243,7 @@ function test_flat_border_with_custom_color() {
$this->assertSame( $expected, $actual );
}
- function test_split_borders_with_custom_colors() {
+ public function test_split_borders_with_custom_colors() {
$block_type = self::register_bordered_block_with_support(
'test/split-borders-with-custom-colors',
array(
@@ -288,7 +288,7 @@ function test_split_borders_with_custom_colors() {
$this->assertSame( $expected, $actual );
}
- function test_split_borders_with_skipped_serialization() {
+ public function test_split_borders_with_skipped_serialization() {
$block_type = self::register_bordered_block_with_support(
'test/split-borders-with-skipped-serialization',
array(
@@ -332,7 +332,7 @@ function test_split_borders_with_skipped_serialization() {
$this->assertSame( $expected, $actual );
}
- function test_split_borders_with_skipped_individual_feature_serialization() {
+ public function test_split_borders_with_skipped_individual_feature_serialization() {
$block_type = self::register_bordered_block_with_support(
'test/split-borders-with-skipped-individual-feature-serialization',
array(
@@ -378,7 +378,7 @@ function test_split_borders_with_skipped_individual_feature_serialization() {
$this->assertSame( $expected, $actual );
}
- function test_partial_split_borders() {
+ public function test_partial_split_borders() {
$block_type = self::register_bordered_block_with_support(
'test/partial-split-borders',
array(
@@ -415,7 +415,7 @@ function test_partial_split_borders() {
$this->assertSame( $expected, $actual );
}
- function test_split_borders_with_named_colors() {
+ public function test_split_borders_with_named_colors() {
$block_type = self::register_bordered_block_with_support(
'test/split-borders-with-named-colors',
array(
diff --git a/phpunit/block-supports/colors-test.php b/phpunit/block-supports/colors-test.php
index 89b3a9192270e6..f21f6477f4162a 100644
--- a/phpunit/block-supports/colors-test.php
+++ b/phpunit/block-supports/colors-test.php
@@ -12,18 +12,18 @@ class WP_Block_Supports_Colors_Test extends WP_UnitTestCase {
*/
private $test_block_name;
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->test_block_name = null;
}
- function tear_down() {
+ public function tear_down() {
unregister_block_type( $this->test_block_name );
$this->test_block_name = null;
parent::tear_down();
}
- function test_color_slugs_with_numbers_are_kebab_cased_properly() {
+ public function test_color_slugs_with_numbers_are_kebab_cased_properly() {
$this->test_block_name = 'test/color-slug-with-numbers';
register_block_type(
$this->test_block_name,
@@ -64,7 +64,7 @@ function test_color_slugs_with_numbers_are_kebab_cased_properly() {
$this->assertSame( $expected, $actual );
}
- function test_color_with_skipped_serialization_block_supports() {
+ public function test_color_with_skipped_serialization_block_supports() {
$this->test_block_name = 'test/color-with-skipped-serialization-block-supports';
register_block_type(
$this->test_block_name,
@@ -102,7 +102,7 @@ function test_color_with_skipped_serialization_block_supports() {
$this->assertSame( $expected, $actual );
}
- function test_gradient_with_individual_skipped_serialization_block_supports() {
+ public function test_gradient_with_individual_skipped_serialization_block_supports() {
$this->test_block_name = 'test/gradient-with-individual-skipped-serialization-block-support';
register_block_type(
$this->test_block_name,
diff --git a/phpunit/block-supports/layout-test.php b/phpunit/block-supports/layout-test.php
index 5609fba1a17fbf..a22d77cf35408e 100644
--- a/phpunit/block-supports/layout-test.php
+++ b/phpunit/block-supports/layout-test.php
@@ -7,7 +7,7 @@
*/
class WP_Block_Supports_Layout_Test extends WP_UnitTestCase {
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->theme_root = realpath( __DIR__ . '/../data/themedir1' );
$this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
@@ -24,7 +24,7 @@ function set_up() {
unset( $GLOBALS['wp_themes'] );
}
- function tear_down() {
+ public function tear_down() {
$GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
wp_clean_themes_cache();
unset( $GLOBALS['wp_themes'] );
@@ -32,11 +32,11 @@ function tear_down() {
parent::tear_down();
}
- function filter_set_theme_root() {
+ public function filter_set_theme_root() {
return $this->theme_root;
}
- function test_outer_container_not_restored_for_non_aligned_image_block_with_non_themejson_theme() {
+ public function test_outer_container_not_restored_for_non_aligned_image_block_with_non_themejson_theme() {
// The "default" theme doesn't have theme.json support.
switch_theme( 'default' );
$block = array(
@@ -49,7 +49,7 @@ function test_outer_container_not_restored_for_non_aligned_image_block_with_non_
$this->assertSame( $expected, gutenberg_restore_image_outer_container( $block_content, $block ) );
}
- function test_outer_container_restored_for_aligned_image_block_with_non_themejson_theme() {
+ public function test_outer_container_restored_for_aligned_image_block_with_non_themejson_theme() {
// The "default" theme doesn't have theme.json support.
switch_theme( 'default' );
$block = array(
@@ -62,7 +62,7 @@ function test_outer_container_restored_for_aligned_image_block_with_non_themejso
$this->assertSame( $expected, gutenberg_restore_image_outer_container( $block_content, $block ) );
}
- function test_additional_styles_moved_to_restored_outer_container_for_aligned_image_block_with_non_themejson_theme() {
+ public function test_additional_styles_moved_to_restored_outer_container_for_aligned_image_block_with_non_themejson_theme() {
// The "default" theme doesn't have theme.json support.
switch_theme( 'default' );
$block = array(
@@ -89,7 +89,7 @@ function test_additional_styles_moved_to_restored_outer_container_for_aligned_im
$this->assertSame( $expected_other_attributes, gutenberg_restore_image_outer_container( $block_classes_other_attributes, $block ) );
}
- function test_outer_container_not_restored_for_aligned_image_block_with_themejson_theme() {
+ public function test_outer_container_not_restored_for_aligned_image_block_with_themejson_theme() {
switch_theme( 'block-theme' );
$block = array(
'blockName' => 'core/image',
@@ -103,6 +103,16 @@ function test_outer_container_not_restored_for_aligned_image_block_with_themejso
$this->assertSame( $expected, gutenberg_restore_image_outer_container( $block_content, $block ) );
}
+ const ARGS_DEFAULTS = array(
+ 'selector' => null,
+ 'layout' => null,
+ 'has_block_gap_support' => false,
+ 'gap_value' => null,
+ 'should_skip_gap_serialization' => false,
+ 'fallback_gap_value' => '0.5em',
+ 'block_spacing' => null,
+ );
+
/**
* Generates the CSS corresponding to the provided layout.
*
@@ -110,21 +120,21 @@ function test_outer_container_not_restored_for_aligned_image_block_with_themejso
*
* @covers ::gutenberg_get_layout_style
*
- * @param array $args {
- * Arguments for the test function.
- *
- * @type string $selector CSS selector.
- * @type array $layout Layout object. The one that is passed has already checked the existence of default block layout.
- * @type boolean $has_block_gap_support Whether the theme has support for the block gap.
- * @type string $gap_value The block gap value to apply.
- * @type boolean $should_skip_gap_serialization Whether to skip applying the user-defined value set in the editor.
- * @type string $fallback_gap_value The block gap value to apply.
- * @type array $block_spacing Custom spacing set on the block.
- * }
+ * @param array $args Dataset to test.
* @param string $expected_output The expected output.
*/
- function test_gutenberg_get_layout_style( $args, $expected_output ) {
- $layout_styles = gutenberg_get_layout_style( $args['selector'], $args['layout'], $args['has_block_gap_support'], $args['gap_value'], $args['should_skip_gap_serialization'], $args['fallback_gap_value'], $args['block_spacing'] );
+ public function test_gutenberg_get_layout_style( $args, $expected_output ) {
+ $args = array_merge( static::ARGS_DEFAULTS, $args );
+ $layout_styles = gutenberg_get_layout_style(
+ $args['selector'],
+ $args['layout'],
+ $args['has_block_gap_support'],
+ $args['gap_value'],
+ $args['should_skip_gap_serialization'],
+ $args['fallback_gap_value'],
+ $args['block_spacing']
+ );
+
$this->assertSame( $expected_output, $layout_styles );
}
@@ -135,7 +145,11 @@ function test_gutenberg_get_layout_style( $args, $expected_output ) {
*/
public function data_gutenberg_get_layout_style() {
return array(
- 'should_return_empty_value_with_no_args' => array(
+ 'no args should return empty value' => array(
+ 'args' => array(),
+ 'expected_output' => '',
+ ),
+ 'nulled args should return empty value' => array(
'args' => array(
'selector' => null,
'layout' => null,
@@ -147,83 +161,57 @@ public function data_gutenberg_get_layout_style() {
),
'expected_output' => '',
),
- 'should_return_empty_value_with_only_selector' => array(
+ 'only selector should return empty value' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => null,
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'selector' => '.wp-layout',
),
'expected_output' => '',
),
- 'should_return_default_layout_with_block_gap_support' => array(
+ 'default layout and block gap support' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => null,
- 'has_block_gap_support' => true,
- 'gap_value' => '1em',
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'selector' => '.wp-layout',
+ 'has_block_gap_support' => true,
+ 'gap_value' => '1em',
),
'expected_output' => '.wp-layout > *{margin-block-start:0;margin-block-end:0;}.wp-layout.wp-layout > * + *{margin-block-start:1em;margin-block-end:0;}',
),
- 'should_return_empty_value_with_block_gap_support_and_skip_serialization' => array(
+ 'skip serialization should return empty value' => array(
'args' => array(
'selector' => '.wp-layout',
- 'layout' => null,
'has_block_gap_support' => true,
'gap_value' => '1em',
'should_skip_gap_serialization' => true,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '',
),
- 'should_return_default_layout_with_axial_block_gap_support' => array(
+ 'default layout and axial block gap support' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => null,
- 'has_block_gap_support' => true,
- 'gap_value' => array( 'top' => '1em' ),
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'selector' => '.wp-layout',
+ 'has_block_gap_support' => true,
+ 'gap_value' => array( 'top' => '1em' ),
),
'expected_output' => '.wp-layout > *{margin-block-start:0;margin-block-end:0;}.wp-layout.wp-layout > * + *{margin-block-start:1em;margin-block-end:0;}',
),
- 'should_return_constrained_layout_with_sizes' => array(
+ 'constrained layout with sizes' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'constrained',
'contentSize' => '800px',
'wideSize' => '1200px',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '.wp-layout > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width:800px;margin-left:auto !important;margin-right:auto !important;}.wp-layout > .alignwide{max-width:1200px;}.wp-layout .alignfull{max-width:none;}',
),
- 'should_return_constrained_layout_with_sizes_and_block_spacing' => array(
+ 'constrained layout with sizes and block spacing' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'constrained',
'contentSize' => '800px',
'wideSize' => '1200px',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => array(
+ 'block_spacing' => array(
'padding' => array(
'left' => '20px',
'right' => '10px',
@@ -232,172 +220,149 @@ public function data_gutenberg_get_layout_style() {
),
'expected_output' => '.wp-layout > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width:800px;margin-left:auto !important;margin-right:auto !important;}.wp-layout > .alignwide{max-width:1200px;}.wp-layout .alignfull{max-width:none;}.wp-layout > .alignfull{margin-right:calc(10px * -1);margin-left:calc(20px * -1);}',
),
- 'should_return_constrained_layout_with_block_gap_support' => array(
+ 'constrained layout with block gap support' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'constrained',
),
- 'has_block_gap_support' => true,
- 'gap_value' => '2.5rem',
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'has_block_gap_support' => true,
+ 'gap_value' => '2.5rem',
),
'expected_output' => '.wp-layout > *{margin-block-start:0;margin-block-end:0;}.wp-layout.wp-layout > * + *{margin-block-start:2.5rem;margin-block-end:0;}',
),
- 'should_return_constrained_layout_with_axial_block_gap_support' => array(
+ 'constrained layout with axial block gap support' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'constrained',
),
- 'has_block_gap_support' => true,
- 'gap_value' => array( 'top' => '2.5rem' ),
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'has_block_gap_support' => true,
+ 'gap_value' => array( 'top' => '2.5rem' ),
),
'expected_output' => '.wp-layout > *{margin-block-start:0;margin-block-end:0;}.wp-layout.wp-layout > * + *{margin-block-start:2.5rem;margin-block-end:0;}',
),
- 'should_return_constrained_layout_with_block_gap_support_and_spacing' => array(
+ 'constrained layout with block gap support and spacing preset' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'constrained',
),
- 'has_block_gap_support' => true,
- 'gap_value' => 'var:preset|spacing|50',
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'has_block_gap_support' => true,
+ 'gap_value' => 'var:preset|spacing|50',
),
'expected_output' => '.wp-layout > *{margin-block-start:0;margin-block-end:0;}.wp-layout.wp-layout > * + *{margin-block-start:var(--wp--preset--spacing--50);margin-block-end:0;}',
),
- 'should_return_empty_value_for_flex_layout_with_no_args' => array(
+ 'flex layout with no args should return empty value' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '',
),
- 'should_return_empty_value_for_horizontal_flex_layout_with_orientation_only' => array(
+ 'horizontal flex layout should return empty value' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'horizontal',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '',
),
- 'should_return_rule_horizontal_flex_layout_with_flex_properties' => array(
+ 'flex layout with properties' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'horizontal',
'flexWrap' => 'nowrap',
'justifyContent' => 'left',
'verticalAlignment' => 'bottom',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '.wp-layout{flex-wrap:nowrap;justify-content:flex-start;align-items:flex-end;}',
),
- 'should_return_rule_for_horizontal_flex_layout_with_flex_properties_and_gap' => array(
+ 'flex layout with properties and block gap' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'horizontal',
'flexWrap' => 'nowrap',
'justifyContent' => 'left',
'verticalAlignment' => 'bottom',
),
- 'has_block_gap_support' => true,
- 'gap_value' => '29px',
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
+ 'has_block_gap_support' => true,
+ 'gap_value' => '29px',
),
'expected_output' => '.wp-layout{flex-wrap:nowrap;gap:29px;justify-content:flex-start;align-items:flex-end;}',
),
- 'should_return_rule_for_horizontal_flex_layout_with_flex_properties_and_axial_gap' => array(
+ 'flex layout with properties and axial block gap' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'horizontal',
'flexWrap' => 'nowrap',
'justifyContent' => 'left',
'verticalAlignment' => 'bottom',
),
- 'has_block_gap_support' => true,
- 'gap_value' => array(
+ 'has_block_gap_support' => true,
+ 'gap_value' => array(
'top' => '1px',
'left' => '2px',
),
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '.wp-layout{flex-wrap:nowrap;gap:1px 2px;justify-content:flex-start;align-items:flex-end;}',
),
- 'should_return_rule_for_horizontal_flex_layout_with_flex_properties_gap_fallback_and_spacing' => array(
+ 'flex layout with properties and axial block gap using spacing preset' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'horizontal',
'flexWrap' => 'nowrap',
'justifyContent' => 'left',
'verticalAlignment' => 'bottom',
),
- 'has_block_gap_support' => true,
- 'gap_value' => array(
+ 'has_block_gap_support' => true,
+ 'gap_value' => array(
'left' => 'var:preset|spacing|40',
),
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => '11px',
- 'block_spacing' => null,
+ 'fallback_gap_value' => '11px',
),
'expected_output' => '.wp-layout{flex-wrap:nowrap;gap:11px var(--wp--preset--spacing--40);justify-content:flex-start;align-items:flex-end;}',
),
- 'should_return_rule_for_vertical_flex_layout_with_flex_properties' => array(
+ 'vertical flex layout with properties' => array(
'args' => array(
- 'selector' => '.wp-layout',
- 'layout' => array(
+ 'selector' => '.wp-layout',
+ 'layout' => array(
'type' => 'flex',
'orientation' => 'vertical',
'flexWrap' => 'nowrap',
'justifyContent' => 'left',
'verticalAlignment' => 'bottom',
),
- 'has_block_gap_support' => null,
- 'gap_value' => null,
- 'should_skip_gap_serialization' => null,
- 'fallback_gap_value' => null,
- 'block_spacing' => null,
),
'expected_output' => '.wp-layout{flex-wrap:nowrap;flex-direction:column;align-items:flex-start;}',
),
+ 'default layout with blockGap to verify converting gap value into valid CSS' => array(
+ 'args' => array(
+ 'selector' => '.wp-block-group.wp-container-6',
+ 'layout' => array(
+ 'type' => 'default',
+ ),
+ 'has_block_gap_support' => true,
+ 'gap_value' => 'var:preset|spacing|70',
+ 'block_spacing' => array(
+ 'blockGap' => 'var(--wp--preset--spacing--70)',
+ ),
+ ),
+ 'expected_output' => '.wp-block-group.wp-container-6 > *{margin-block-start:0;margin-block-end:0;}.wp-block-group.wp-container-6.wp-block-group.wp-container-6 > * + *{margin-block-start:var(--wp--preset--spacing--70);margin-block-end:0;}',
+ ),
);
}
}
diff --git a/phpunit/block-supports/spacing-test.php b/phpunit/block-supports/spacing-test.php
index 4caaf12911f9ad..1ac0c86e620428 100644
--- a/phpunit/block-supports/spacing-test.php
+++ b/phpunit/block-supports/spacing-test.php
@@ -12,18 +12,18 @@ class WP_Block_Supports_Spacing_Test extends WP_UnitTestCase {
*/
private $test_block_name;
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->test_block_name = null;
}
- function tear_down() {
+ public function tear_down() {
unregister_block_type( $this->test_block_name );
$this->test_block_name = null;
parent::tear_down();
}
- function test_spacing_style_is_applied() {
+ public function test_spacing_style_is_applied() {
$this->test_block_name = 'test/spacing-style-is-applied';
register_block_type(
$this->test_block_name,
@@ -68,7 +68,7 @@ function test_spacing_style_is_applied() {
$this->assertSame( $expected, $actual );
}
- function test_spacing_with_skipped_serialization_block_supports() {
+ public function test_spacing_with_skipped_serialization_block_supports() {
$this->test_block_name = 'test/spacing-with-skipped-serialization-block-supports';
register_block_type(
$this->test_block_name,
@@ -112,7 +112,7 @@ function test_spacing_with_skipped_serialization_block_supports() {
$this->assertSame( $expected, $actual );
}
- function test_margin_with_individual_skipped_serialization_block_supports() {
+ public function test_margin_with_individual_skipped_serialization_block_supports() {
$this->test_block_name = 'test/margin-with-individual-skipped-serialization-block-supports';
register_block_type(
$this->test_block_name,
diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php
index 0d2958dcf93309..ecc37ec442135c 100644
--- a/phpunit/block-supports/typography-test.php
+++ b/phpunit/block-supports/typography-test.php
@@ -15,7 +15,7 @@ class WP_Block_Supports_Typography_Test extends WP_UnitTestCase {
/**
* Sets up tests.
*/
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->test_block_name = null;
}
@@ -23,7 +23,7 @@ function set_up() {
/**
* Tears down tests.
*/
- function tear_down() {
+ public function tear_down() {
unregister_block_type( $this->test_block_name );
$this->test_block_name = null;
parent::tear_down();
@@ -34,7 +34,7 @@ function tear_down() {
*
* @covers ::wp_apply_typography_support
*/
- function test_should_kebab_case_font_size_slug_with_numbers() {
+ public function test_should_kebab_case_font_size_slug_with_numbers() {
$this->test_block_name = 'test/font-size-slug-with-numbers';
register_block_type(
$this->test_block_name,
@@ -68,7 +68,7 @@ function test_should_kebab_case_font_size_slug_with_numbers() {
*
* @covers ::wp_apply_typography_support
*/
- function test_should_generate_font_family_with_legacy_inline_styles_using_a_value() {
+ public function test_should_generate_font_family_with_legacy_inline_styles_using_a_value() {
$this->test_block_name = 'test/font-family-with-inline-styles-using-value';
register_block_type(
$this->test_block_name,
@@ -101,7 +101,7 @@ function test_should_generate_font_family_with_legacy_inline_styles_using_a_valu
*
* @covers ::wp_apply_typography_support
*/
- function test_should_skip_serialization_for_typography_block_supports() {
+ public function test_should_skip_serialization_for_typography_block_supports() {
$this->test_block_name = 'test/typography-with-skipped-serialization-block-supports';
register_block_type(
$this->test_block_name,
@@ -147,7 +147,7 @@ function test_should_skip_serialization_for_typography_block_supports() {
*
* @covers ::wp_apply_typography_support
*/
- function test_should_skip_serialization_for_letter_spacing_block_supports() {
+ public function test_should_skip_serialization_for_letter_spacing_block_supports() {
$this->test_block_name = 'test/letter-spacing-with-individual-skipped-serialization-block-supports';
register_block_type(
$this->test_block_name,
@@ -183,7 +183,7 @@ function test_should_skip_serialization_for_letter_spacing_block_supports() {
*
* @covers ::wp_apply_typography_support
*/
- function test_should_generate_css_var_for_font_family_with_legacy_inline_styles() {
+ public function test_should_generate_css_var_for_font_family_with_legacy_inline_styles() {
$this->test_block_name = 'test/font-family-with-inline-styles-using-css-var';
register_block_type(
$this->test_block_name,
@@ -216,7 +216,7 @@ function test_should_generate_css_var_for_font_family_with_legacy_inline_styles(
*
* @covers ::wp_apply_typography_support
*/
- function test_should_generate_classname_for_font_family() {
+ public function test_should_generate_classname_for_font_family() {
$this->test_block_name = 'test/font-family-with-class';
register_block_type(
$this->test_block_name,
@@ -263,7 +263,7 @@ function test_should_generate_classname_for_font_family() {
* @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing.
* @param string $expected_output Expected output of gutenberg_get_typography_font_size_value().
*/
- function test_gutenberg_get_typography_font_size_value( $font_size_preset, $should_use_fluid_typography, $expected_output ) {
+ public function test_gutenberg_get_typography_font_size_value( $font_size_preset, $should_use_fluid_typography, $expected_output ) {
$actual = gutenberg_get_typography_font_size_value( $font_size_preset, $should_use_fluid_typography );
$this->assertSame( $expected_output, $actual );
diff --git a/phpunit/blocks/render-block-cover-test.php b/phpunit/blocks/render-block-cover-test.php
index c9da23f655494a..753aa14f2fe4db 100644
--- a/phpunit/blocks/render-block-cover-test.php
+++ b/phpunit/blocks/render-block-cover-test.php
@@ -42,7 +42,6 @@ public static function wpSetUpBeforeClass() {
);
set_post_thumbnail( self::$post, self::$attachment_id );
-
}
/**
@@ -128,6 +127,5 @@ public function test_gutenberg_render_block_core_cover_fixed_or_repeated_backgro
$this->assertStringContainsString( 'object-position', $rendered );
$this->assertStringNotContainsString( 'background-image', $rendered );
$this->assertStringNotContainsString( 'min-height', $rendered );
-
}
}
diff --git a/phpunit/blocks/render-comments-test.php b/phpunit/blocks/render-comments-test.php
index a6930c50c22266..2ce8ce77ad698e 100644
--- a/phpunit/blocks/render-comments-test.php
+++ b/phpunit/blocks/render-comments-test.php
@@ -43,4 +43,4 @@ public function test_render_block_core_comments_empty_output_if_comments_disable
$rendered = gutenberg_render_block_core_comments( $attributes, '', $block );
$this->assertEmpty( $rendered );
}
-};
+}
diff --git a/phpunit/blocks/render-last-posts-test.php b/phpunit/blocks/render-last-posts-test.php
index a20b6f717a4fa3..f26da1cfa6724b 100644
--- a/phpunit/blocks/render-last-posts-test.php
+++ b/phpunit/blocks/render-last-posts-test.php
@@ -40,7 +40,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
$file = DIR_TESTDATA . '/images/canola.jpg';
- for ( $i = 0; $i < 5; $i ++ ) {
+ for ( $i = 0; $i < 5; $i++ ) {
self::$posts[ $i ] = $factory->post->create_and_get();
self::$attachment_ids[ $i ] = $factory->attachment->create_upload_object( $file, self::$posts[ $i ]->ID );
set_post_thumbnail( self::$posts[ $i ], self::$attachment_ids[ $i ] );
diff --git a/phpunit/class-block-context-test.php b/phpunit/class-block-context-test.php
index 74f391bf479d5d..4cf30478aa5682 100644
--- a/phpunit/class-block-context-test.php
+++ b/phpunit/class-block-context-test.php
@@ -66,7 +66,7 @@ protected function register_block_type( $name, $args ) {
* Tests that a block which provides context makes that context available to
* its inner blocks.
*/
- function test_provides_block_context() {
+ public function test_provides_block_context() {
$provided_context = array();
$this->register_block_type(
@@ -133,7 +133,7 @@ function test_provides_block_context() {
* Tests that a block can receive default-provided context through
* render_block.
*/
- function test_provides_default_context() {
+ public function test_provides_default_context() {
global $post;
$provided_context = array();
@@ -166,7 +166,7 @@ function test_provides_default_context() {
/**
* Tests that default block context can be filtered.
*/
- function test_default_context_is_filterable() {
+ public function test_default_context_is_filterable() {
$provided_context = array();
$this->register_block_type(
diff --git a/phpunit/class-block-fixture-test.php b/phpunit/class-block-fixture-test.php
index 94e5c17c66ac39..a3e47cc7b28337 100644
--- a/phpunit/class-block-fixture-test.php
+++ b/phpunit/class-block-fixture-test.php
@@ -13,7 +13,7 @@ class Block_Fixture_Test extends WP_UnitTestCase {
*
* @dataProvider data_block_fixtures
*/
- function test_kses_doesnt_change_fixtures( $block, $filename ) {
+ public function test_kses_doesnt_change_fixtures( $block, $filename ) {
// KSES doesn't allow data: URLs, so we need to replace any of them in fixtures.
$block = preg_replace( "/src=['\"]data:[^'\"]+['\"]/", 'src="https://wordpress.org/foo.jpg"', $block );
@@ -31,7 +31,7 @@ function test_kses_doesnt_change_fixtures( $block, $filename ) {
$this->assertSame( $block, $kses_block, "Failed to match $filename" );
}
- function data_block_fixtures() {
+ public function data_block_fixtures() {
$data = array();
foreach ( glob( gutenberg_dir_path() . 'test/integration/fixtures/blocks/*.serialized.html' ) as $path ) {
diff --git a/phpunit/class-block-library-navigation-link-test.php b/phpunit/class-block-library-navigation-link-test.php
index 7b91742ec22724..bb6cc33fb2e8ba 100644
--- a/phpunit/class-block-library-navigation-link-test.php
+++ b/phpunit/class-block-library-navigation-link-test.php
@@ -109,7 +109,7 @@ public function tear_down() {
parent::tear_down();
}
- function test_returns_link_when_post_is_published() {
+ public function test_returns_link_when_post_is_published() {
$page_id = self::$page->ID;
$parsed_blocks = parse_blocks(
@@ -131,7 +131,7 @@ function test_returns_link_when_post_is_published() {
);
}
- function test_returns_empty_when_label_is_missing() {
+ public function test_returns_empty_when_label_is_missing() {
$page_id = self::$page->ID;
$parsed_blocks = parse_blocks(
@@ -150,7 +150,7 @@ function test_returns_empty_when_label_is_missing() {
);
}
- function test_returns_empty_when_draft() {
+ public function test_returns_empty_when_draft() {
$page_id = self::$draft->ID;
$parsed_blocks = parse_blocks(
@@ -170,7 +170,7 @@ function test_returns_empty_when_draft() {
);
}
- function test_returns_link_for_category() {
+ public function test_returns_link_for_category() {
$category_id = self::$category->term_id;
$parsed_blocks = parse_blocks(
@@ -192,7 +192,7 @@ function test_returns_link_for_category() {
);
}
- function test_returns_link_for_plain_link() {
+ public function test_returns_link_for_plain_link() {
$parsed_blocks = parse_blocks(
''
);
@@ -212,7 +212,7 @@ function test_returns_link_for_plain_link() {
);
}
- function test_returns_empty_when_custom_post_type_draft() {
+ public function test_returns_empty_when_custom_post_type_draft() {
$page_id = self::$custom_draft->ID;
$parsed_blocks = parse_blocks(
@@ -232,7 +232,7 @@ function test_returns_empty_when_custom_post_type_draft() {
);
}
- function test_returns_link_when_custom_post_is_published() {
+ public function test_returns_link_when_custom_post_is_published() {
$page_id = self::$custom_post->ID;
$parsed_blocks = parse_blocks(
diff --git a/phpunit/class-override-script-test.php b/phpunit/class-override-script-test.php
index fc0043cb735ff7..b3af1acd80f446 100644
--- a/phpunit/class-override-script-test.php
+++ b/phpunit/class-override-script-test.php
@@ -6,7 +6,7 @@
*/
class Override_Script_Test extends WP_UnitTestCase {
- function set_up() {
+ public function set_up() {
parent::set_up();
wp_register_script(
@@ -18,7 +18,7 @@ function set_up() {
);
}
- function tear_down() {
+ public function tear_down() {
parent::tear_down();
wp_deregister_script( 'gutenberg-dummy-script' );
@@ -27,7 +27,7 @@ function tear_down() {
/**
* Tests that script is localized.
*/
- function test_localizes_script() {
+ public function test_localizes_script() {
global $wp_scripts;
gutenberg_override_script(
@@ -46,7 +46,7 @@ function test_localizes_script() {
/**
* Tests that script properties are overridden.
*/
- function test_replaces_registered_properties() {
+ public function test_replaces_registered_properties() {
global $wp_scripts;
gutenberg_override_script(
@@ -68,7 +68,7 @@ function test_replaces_registered_properties() {
/**
* Tests that new script registers normally if no handle by the name.
*/
- function test_registers_new_script() {
+ public function test_registers_new_script() {
global $wp_scripts;
gutenberg_override_script(
diff --git a/phpunit/class-phpunit-environment-setup-test.php b/phpunit/class-phpunit-environment-setup-test.php
index 63ce4e84e3ebc5..6dd03a5a1f5afb 100644
--- a/phpunit/class-phpunit-environment-setup-test.php
+++ b/phpunit/class-phpunit-environment-setup-test.php
@@ -12,7 +12,7 @@ class Phpunit_Environment_Setup_Test extends WP_UnitTestCase {
* added to wp-config by the setup code. We need to know when tests are not
* actually running in a multisite environment when they should be.
*/
- function test_is_multisite_if_defined() {
+ public function test_is_multisite_if_defined() {
$is_multisite_in_env = ( '1' === getenv( 'WP_MULTISITE' ) );
$this->assertEquals( $is_multisite_in_env, is_multisite(), 'Despite WP_MULTISITE being set in the environment, the tests were not run in multisite mode. There is likely an issue with the phpunit setup.' );
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index e3704bfdc864f6..14ce71f3b4ed5b 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -8,7 +8,7 @@
class WP_Theme_JSON_Resolver_Gutenberg_Test extends WP_UnitTestCase {
- function set_up() {
+ public function set_up() {
parent::set_up();
$this->theme_root = realpath( __DIR__ . '/data/themedir1' );
@@ -26,29 +26,29 @@ function set_up() {
unset( $GLOBALS['wp_themes'] );
}
- function tear_down() {
+ public function tear_down() {
$GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
wp_clean_themes_cache();
unset( $GLOBALS['wp_themes'] );
parent::tear_down();
}
- function filter_set_theme_root() {
+ public function filter_set_theme_root() {
return $this->theme_root;
}
- function filter_set_locale_to_polish() {
+ public function filter_set_locale_to_polish() {
return 'pl_PL';
}
- function filter_db_query( $query ) {
+ public function filter_db_query( $query ) {
if ( preg_match( '#post_type = \'wp_global_styles\'#', $query ) ) {
$this->queries[] = $query;
}
return $query;
}
- function test_translations_are_applied() {
+ public function test_translations_are_applied() {
add_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) );
load_textdomain( 'block-theme', realpath( __DIR__ . '/data/languages/themes/block-theme-pl_PL.mo' ) );
@@ -125,7 +125,7 @@ function test_translations_are_applied() {
);
}
- function test_switching_themes_recalculates_data() {
+ public function test_switching_themes_recalculates_data() {
// The "default" theme doesn't have theme.json support.
switch_theme( 'default' );
$default = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();
@@ -138,7 +138,7 @@ function test_switching_themes_recalculates_data() {
$this->assertTrue( $has_theme_json_support );
}
- function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
+ public function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
switch_theme( 'default' );
$color_palette = array(
array(
@@ -182,7 +182,7 @@ private static function recursive_ksort( &$array ) {
ksort( $array );
}
- function test_merges_child_theme_json_into_parent_theme_json() {
+ public function test_merges_child_theme_json_into_parent_theme_json() {
switch_theme( 'block-theme-child' );
$actual_settings = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data()->get_settings();
@@ -268,7 +268,7 @@ function test_merges_child_theme_json_into_parent_theme_json() {
);
}
- function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries() {
+ public function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries() {
add_filter( 'query', array( $this, 'filter_db_query' ) );
$query_count = count( $this->queries );
for ( $i = 0; $i < 3; $i++ ) {
diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php
index 6c450951cb1dd4..aa92f61f888f7e 100644
--- a/phpunit/class-wp-theme-json-test.php
+++ b/phpunit/class-wp-theme-json-test.php
@@ -432,7 +432,7 @@ public function test_get_stylesheet() {
$this->assertEquals( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) );
}
- function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() {
+ public function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -475,7 +475,7 @@ function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() {
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
- function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given_property() {
+ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given_property() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -514,7 +514,7 @@ function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given_proper
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
- function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() {
+ public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -553,7 +553,7 @@ function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_element
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
- function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() {
+ public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -593,7 +593,7 @@ function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() {
$this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) );
}
- function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseudo_selectors() {
+ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseudo_selectors() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -640,7 +640,7 @@ function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseu
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
- function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_selectors() {
+ public function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_selectors() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -695,7 +695,7 @@ function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_sele
* bootstrap. After a core block adopts feature level selectors we could
* remove that filter and instead use the core block for the following test.
*/
- function test_get_stylesheet_with_block_support_feature_level_selectors() {
+ public function test_get_stylesheet_with_block_support_feature_level_selectors() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -748,7 +748,7 @@ function test_get_stylesheet_with_block_support_feature_level_selectors() {
$this->assertEquals( $expected, $theme_json->get_stylesheet() );
}
- function test_remove_invalid_element_pseudo_selectors() {
+ public function test_remove_invalid_element_pseudo_selectors() {
$actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -795,14 +795,14 @@ function test_remove_invalid_element_pseudo_selectors() {
$this->assertEqualSetsWithIndex( $expected, $actual );
}
- function test_get_element_class_name_button() {
+ public function test_get_element_class_name_button() {
$expected = 'wp-element-button';
$actual = WP_Theme_JSON_Gutenberg::get_element_class_name( 'button' );
$this->assertEquals( $expected, $actual );
}
- function test_get_element_class_name_invalid() {
+ public function test_get_element_class_name_invalid() {
$expected = '';
$actual = WP_Theme_JSON_Gutenberg::get_element_class_name( 'unknown-element' );
@@ -813,7 +813,7 @@ function test_get_element_class_name_invalid() {
* Testing that dynamic properties in theme.json return the value they reference, e.g.
* array( 'ref' => 'styles.color.background' ) => "#ffffff".
*/
- function test_get_property_value_valid() {
+ public function test_get_property_value_valid() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -845,7 +845,7 @@ function test_get_property_value_valid() {
*
* @expectedIncorrectUsage get_property_value
*/
- function test_get_property_value_loop() {
+ public function test_get_property_value_loop() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -876,7 +876,7 @@ function test_get_property_value_loop() {
*
* @expectedIncorrectUsage get_property_value
*/
- function test_get_property_value_recursion() {
+ public function test_get_property_value_recursion() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -907,7 +907,7 @@ function test_get_property_value_recursion() {
*
* @expectedIncorrectUsage get_property_value
*/
- function test_get_property_value_self() {
+ public function test_get_property_value_self() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -929,7 +929,7 @@ function test_get_property_value_self() {
*
* @dataProvider data_generate_spacing_scale_fixtures
*/
- function test_set_spacing_sizes( $spacing_scale, $expected_output ) {
+ public function test_set_spacing_sizes( $spacing_scale, $expected_output ) {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -950,7 +950,7 @@ function test_set_spacing_sizes( $spacing_scale, $expected_output ) {
*
* @return array
*/
- function data_generate_spacing_scale_fixtures() {
+ public function data_generate_spacing_scale_fixtures() {
return array(
'one_step_spacing_scale' => array(
'spacingScale' => array(
@@ -1192,7 +1192,7 @@ public function test_set_spacing_sizes_when_invalid( $spacing_scale, $expected_o
*
* @return array
*/
- function data_set_spacing_sizes_when_invalid() {
+ public function data_set_spacing_sizes_when_invalid() {
return array(
'invalid_spacing_scale_values_missing_operator' => array(
@@ -1251,7 +1251,7 @@ function data_set_spacing_sizes_when_invalid() {
);
}
- function test_get_styles_for_block_with_padding_aware_alignments() {
+ public function test_get_styles_for_block_with_padding_aware_alignments() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -1284,7 +1284,7 @@ function test_get_styles_for_block_with_padding_aware_alignments() {
$this->assertEquals( $expected, $root_rules . $style_rules );
}
- function test_get_styles_for_block_without_padding_aware_alignments() {
+ public function test_get_styles_for_block_without_padding_aware_alignments() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
@@ -1314,7 +1314,7 @@ function test_get_styles_for_block_without_padding_aware_alignments() {
$this->assertEquals( $expected, $root_rules . $style_rules );
}
- function test_get_styles_for_block_with_content_width() {
+ public function test_get_styles_for_block_with_content_width() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
diff --git a/phpunit/class-wp-webfonts-local-provider-test.php b/phpunit/class-wp-webfonts-local-provider-test.php
index c9ab3e2cd8b958..43ef4a84951c84 100644
--- a/phpunit/class-wp-webfonts-local-provider-test.php
+++ b/phpunit/class-wp-webfonts-local-provider-test.php
@@ -38,7 +38,7 @@ private function set_up_theme() {
unset( $GLOBALS['wp_themes'] );
}
- function tear_down() {
+ public function tear_down() {
// Restore the original theme directory setup.
$GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
wp_clean_themes_cache();
diff --git a/phpunit/html/WP_HTML_Tag_Processor_Isolated_Test.php b/phpunit/html/WP_HTML_Tag_Processor_Isolated_Test.php
new file mode 100644
index 00000000000000..d593c5d2f4fe92
--- /dev/null
+++ b/phpunit/html/WP_HTML_Tag_Processor_Isolated_Test.php
@@ -0,0 +1,145 @@
+' );
+
+ $this->expectException( Exception::class );
+
+ $p->next_tag();
+ $p->set_attribute( $attribute_name, 'test' );
+
+ $this->assertEquals( ' ', (string) $p );
+ }
+
+ /**
+ * Attribute names with invalid characters should be rejected.
+ *
+ * When WP_DEBUG isn't set we want to quietly fail to set the
+ * invalid attribute to avoid breaking the HTML and to do so
+ * without breaking the entire page.
+ *
+ * @dataProvider data_invalid_attribute_names
+ * @covers set_attribute
+ */
+ public function test_set_attribute_silently_fails_when_given_invalid_attribute_names_outside_of_debug_mode( $attribute_name ) {
+ $p = new WP_HTML_Tag_Processor( ' ' );
+
+ $p->next_tag();
+ $p->set_attribute( $attribute_name, 'test' );
+
+ $this->assertEquals( ' ', (string) $p );
+ }
+
+ /**
+ * Data provider with invalid HTML attribute names.
+ *
+ * @return array {
+ * @type string $attribute_name Text considered invalid for HTML attribute names.
+ * }
+ */
+ public function data_invalid_attribute_names() {
+ return array(
+ 'controls_null' => array( "i\x00d" ),
+ 'controls_newline' => array( "\nbroken-expectations" ),
+ 'space' => array( 'aria label' ),
+ 'double-quote' => array( '"id"' ),
+ 'single-quote' => array( "'id'" ),
+ 'greater-than' => array( 'sneaky>script' ),
+ 'solidus' => array( 'data/test-id' ),
+ 'equals' => array( 'checked=checked' ),
+ 'noncharacters_1' => array( html_entity_decode( 'anything' ) ),
+ 'noncharacters_2' => array( html_entity_decode( 'test' ) ),
+ 'noncharacters_3' => array( html_entity_decode( 'test' ) ),
+ 'noncharacters_4' => array( html_entity_decode( 'test' ) ),
+ 'noncharacters_5' => array( html_entity_decode( '' ) ),
+ 'wp_no_lt' => array( 'id
',
+ );
+
+ $examples['Simple uppercase script tag'] = array(
+ '
',
+ );
+
+ $examples['Script with a comment opener inside should end at the next script tag closer (dash dash escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Script with a comment opener and a script tag opener inside should end two script tag closer later (double escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Double escaped script with a tricky opener'] = array(
+ '">">
',
+ );
+
+ $examples['Double escaped script with a tricky closer'] = array(
+ '">
',
+ );
+
+ $examples['Double escaped, then escaped, then double escaped'] = array(
+ '
',
+ );
+
+ $examples['Script with a commented a script tag opener inside should at the next tag closer (dash dash escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Script closer with another script tag in closer attributes'] = array(
+ '
',
+ );
+
+ $examples['Script closer with attributes'] = array(
+ '
',
+ );
+
+ $examples['Script opener with title closer inside'] = array(
+ '
',
+ );
+
+ $examples['Complex script with many parsing states'] = array(
+ '-->
-->',
+ );
+ return $examples;
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ *
+ * @dataProvider data_rcdata_state
+ */
+ public function test_next_tag_ignores_the_contents_of_a_rcdata_tag( $rcdata_then_div, $rcdata_tag ) {
+ $p = new WP_HTML_Tag_Processor( $rcdata_then_div );
+ $p->next_tag();
+ $this->assertSame( $rcdata_tag, $p->get_tag(), "The first found tag was not '$rcdata_tag'" );
+ $p->next_tag();
+ $this->assertSame( 'div', $p->get_tag(), "The second found tag was not 'div'" );
+ }
+
+ /**
+ * Data provider for test_ignores_contents_of_a_rcdata_tag().
+ *
+ * @return array {
+ * @type array {
+ * @type string $rcdata_then_div The HTML snippet containing RCDATA and div tags.
+ * @type string $rcdata_tag The RCDATA tag.
+ * }
+ * }
+ */
+ public function data_rcdata_state() {
+ $examples = array();
+ $examples['Simple textarea'] = array(
+ '
',
+ 'textarea',
+ );
+
+ $examples['Simple title'] = array(
+ 'Back to notifications
',
+ 'title',
+ );
+
+ $examples['Comment opener inside a textarea tag should be ignored'] = array(
+ '
'
+ );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'class', 'span-class' );
+ $p->next_tag( 'p' );
+ $p->set_attribute( 'class', 'p-class' );
+ $this->assertSame(
+ '123456
789',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers remove_attribute
+ * @covers __toString
+ */
+ public function test_removing_attributes_works_even_in_malformed_html() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED );
+ $p->next_tag( 'span' );
+ $p->remove_attribute( 'Notifications<' );
+ $this->assertSame(
+ 'Back to notifications
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_Tag
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_updating_attributes_works_even_in_malformed_html_1() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'id', 'first' );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'id', 'second' );
+ $this->assertSame(
+ 'Back to notifications
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers set_attribute
+ * @covers add_class
+ * @covers __toString
+ *
+ * @dataProvider data_malformed_tag
+ */
+ public function test_updating_attributes_works_even_in_malformed_html_2( $html_input, $html_expected ) {
+ $p = new WP_HTML_Tag_Processor( $html_input );
+ $p->next_tag();
+ $p->set_attribute( 'foo', 'bar' );
+ $p->add_class( 'firstTag' );
+ $p->next_tag();
+ $p->add_class( 'secondTag' );
+ $this->assertSame(
+ $html_expected,
+ (string) $p
+ );
+ }
+
+ /**
+ * Data provider for test_updates_when_malformed_tag().
+ *
+ * @return array {
+ * @type array {
+ * @type string $html_input The input HTML snippet.
+ * @type string $html_expected The expected HTML snippet after processing.
+ * }
+ * }
+ */
+ public function data_malformed_tag() {
+ $null_byte = chr( 0 );
+ $examples = array();
+ $examples['Invalid entity inside attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['HTML tag opening inside attribute value'] = array(
+ 'This <is> a <strong is="true">thing.
test ',
+ 'This <is> a <strong is="true">thing.
test ',
+ );
+
+ $examples['HTML tag brackets in attribute values and data markup'] = array(
+ 'This <is> a <strong is="true">thing.
test ',
+ 'This <is> a <strong is="true">thing.
test ',
+ );
+
+ $examples['Single and double quotes in attribute value'] = array(
+ 'test ',
+ '
test ',
+ );
+
+ $examples['Unquoted attribute values'] = array(
+ '
test ',
+ 'test ',
+ );
+
+ $examples['Double-quotes escaped in double-quote attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Unquoted attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Unquoted attribute value with tag-like value'] = array(
+ ' >test ',
+ ' >test ',
+ );
+
+ $examples['Unquoted attribute value with tag-like value followed by tag-like data'] = array(
+ ' >test ',
+ ' >test ',
+ );
+
+ $examples['1'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['2'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['4'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['5'] = array(
+ ' code>test ',
+ ' code>test ',
+ );
+
+ $examples['6'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['7'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['8'] = array(
+ ' id="test">test ',
+ ' id="test">test ',
+ );
+
+ $examples['9'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['10'] = array(
+ '>test ',
+ '>test ',
+ );
+
+ $examples['11'] = array(
+ 'The applicative operator <* works well in Haskell; is what?test ',
+ 'The applicative operator <* works well in Haskell; is what?test ',
+ );
+
+ $examples['12'] = array(
+ '<3 is a heart but is a tag.test ',
+ '<3 is a heart but is a tag.test ',
+ );
+
+ $examples['13'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['14'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['15'] = array(
+ ' a HTML Tag ]]>test ',
+ ' a HTML Tag ]]>test ',
+ );
+
+ $examples['16'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['17'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['18'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['19'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['20'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['21'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['22'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['23'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['24'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['25'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Multiple unclosed tags treated as a single tag'] = array(
+ '
+test ',
+ '
+test ',
+ );
+
+ $examples['27'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['28'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ return $examples;
+ }
+}
diff --git a/phpunit/html/wp-html-tag-processor-standalone-test.php b/phpunit/html/wp-html-tag-processor-standalone-test.php
new file mode 100644
index 00000000000000..d0b5f8288986ad
--- /dev/null
+++ b/phpunit/html/wp-html-tag-processor-standalone-test.php
@@ -0,0 +1,1268 @@
+Text ';
+ const HTML_WITH_CLASSES = 'Text
';
+ const HTML_MALFORMED = 'Back to notifications
';
+
+ /**
+ * @ticket 56299
+ *
+ * @covers get_tag
+ */
+ public function test_get_tag_returns_null_before_finding_tags() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertNull( $p->get_tag() );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_tag
+ */
+ public function test_get_tag_returns_null_when_not_in_open_tag() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertFalse( $p->next_tag( 'p' ), 'Querying a non-existing tag did not return false' );
+ $this->assertNull( $p->get_tag(), 'Accessing a non-existing tag did not return null' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_tag
+ */
+ public function test_get_tag_returns_open_tag_name() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( 'div' ), 'Querying an existing tag did not return true' );
+ $this->assertSame( 'DIV', $p->get_tag(), 'Accessing an existing tag name did not return "div"' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_null_before_finding_tags() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertNull( $p->get_attribute( 'class' ) );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_null_when_not_in_open_tag() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertFalse( $p->next_tag( 'p' ), 'Querying a non-existing tag did not return false' );
+ $this->assertNull( $p->get_attribute( 'class' ), 'Accessing an attribute of a non-existing tag did not return null' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_null_when_attribute_missing() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( 'div' ), 'Querying an existing tag did not return true' );
+ $this->assertNull( $p->get_attribute( 'test-id' ), 'Accessing a non-existing attribute did not return null' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_attribute_value() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( 'div' ), 'Querying an existing tag did not return true' );
+ $this->assertSame( 'test', $p->get_attribute( 'class' ), 'Accessing a class="test" attribute value did not return "test"' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_true_for_boolean_attribute() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( array( 'class_name' => 'test' ) ), 'Querying an existing tag did not return true' );
+ $this->assertTrue( $p->get_attribute( 'enabled' ), 'Accessing a boolean "enabled" attribute value did not return true' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_get_attribute_returns_string_for_truthy_attributes() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( array() ), 'Querying an existing tag did not return true' );
+ $this->assertSame( 'enabled', $p->get_attribute( 'enabled' ), 'Accessing a boolean "enabled" attribute value did not return true' );
+ $this->assertSame( '1', $p->get_attribute( 'checked' ), 'Accessing a checked=1 attribute value did not return "1"' );
+ $this->assertSame( 'true', $p->get_attribute( 'hidden' ), 'Accessing a hidden="true" attribute value did not return "true"' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers WP_HTML_Tag_Processor::get_attribute
+ */
+ public function test_get_attribute_decodes_html_character_references() {
+ $p = new WP_HTML_Tag_Processor( '
' );
+ $p->next_tag();
+ $this->assertSame( 'the "grande" is < 32oz†', $p->get_attribute( 'id' ), 'HTML Attribute value was returned without decoding character references' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers get_attribute
+ */
+ public function test_attributes_parser_treats_slash_as_attribute_separator() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $this->assertTrue( $p->next_tag( array() ), 'Querying an existing tag did not return true' );
+ $this->assertTrue( $p->get_attribute( 'a' ), 'Accessing an existing attribute did not return true' );
+ $this->assertTrue( $p->get_attribute( 'b' ), 'Accessing an existing attribute did not return true' );
+ $this->assertTrue( $p->get_attribute( 'c' ), 'Accessing an existing attribute did not return true' );
+ $this->assertTrue( $p->get_attribute( 'd' ), 'Accessing an existing attribute did not return true' );
+ $this->assertSame( 'test', $p->get_attribute( 'e' ), 'Accessing an existing e="test" did not return "test"' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers __toString
+ */
+ public function test_tostring_applies_the_updates_so_far_and_keeps_the_processor_on_the_current_tag() {
+ $p = new WP_HTML_Tag_Processor( 'Test
' );
+ $p->next_tag();
+ $p->remove_attribute( 'id' );
+
+ $p->next_tag();
+ $p->set_attribute( 'id', 'div-id-1' );
+ $p->add_class( 'new_class_1' );
+ $this->assertSame(
+ 'Test
',
+ (string) $p,
+ 'Calling __toString after updating the attributes of the second tag returned different HTML than expected'
+ );
+
+ $p->set_attribute( 'id', 'div-id-2' );
+ $p->add_class( 'new_class_2' );
+ $this->assertSame(
+ 'Test
',
+ (string) $p,
+ 'Calling __toString after updating the attributes of the second tag for the second time returned different HTML than expected'
+ );
+
+ $p->next_tag();
+ $p->remove_attribute( 'id' );
+ $this->assertSame(
+ 'Test
',
+ (string) $p,
+ 'Calling __toString after removing the id attribute of the third tag returned different HTML than expected'
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers __toString
+ */
+ public function test_tostring_without_updating_any_attributes_returns_the_original_html() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $this->assertSame( self::HTML_SIMPLE, (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ */
+ public function test_next_tag_with_no_arguments_should_find_the_next_existing_tag() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $this->assertTrue( $p->next_tag(), 'Querying an existing tag did not return true' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ */
+ public function test_next_tag_should_return_false_for_a_non_existing_tag() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $this->assertFalse( $p->next_tag( 'p' ), 'Querying a non-existing tag did not return false' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers __toString
+ */
+ public function test_set_attribute_on_a_non_existing_tag_does_not_change_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $this->assertFalse( $p->next_tag( 'p' ), 'Querying a non-existing tag did not return false' );
+ $this->assertFalse( $p->next_tag( 'div' ), 'Querying a non-existing tag did not return false' );
+ $p->set_attribute( 'id', 'primary' );
+ $this->assertSame(
+ self::HTML_SIMPLE,
+ (string) $p,
+ 'Calling __toString after updating a non-existing tag returned an HTML that was different from the original HTML'
+ );
+ }
+
+ /**
+ * Passing a double quote inside of an attribute values could lead to an XSS attack as follows:
+ *
+ *
+ * $p = new WP_HTML_Tag_Processor( '' );
+ * $p->next_tag();
+ * $p->set_attribute('class', '" onclick="alert');
+ * echo $p;
+ * //
+ *
+ *
+ * To prevent it, `set_attribute` calls `esc_attr()` on its given values.
+ *
+ *
+ *
+ *
+ *
+ * @ticket 56299
+ *
+ * @dataProvider data_set_attribute_escapable_values
+ * @covers set_attribute
+ */
+ public function test_set_attribute_prevents_xss( $attribute_value ) {
+ $p = new WP_HTML_Tag_Processor( '
' );
+ $p->next_tag();
+ $p->set_attribute( 'test', $attribute_value );
+
+ /*
+ * Testing the escaping is hard using tools that properly parse
+ * HTML because they might interpret the escaped values. It's hard
+ * with tools that don't understand HTML because they might get
+ * confused by improperly-escaped values.
+ *
+ * For this test, since we control the input HTML we're going to
+ * do what looks like the opposite of what we want to be doing with
+ * this library but are only doing so because we have full control
+ * over the content and because we want to look at the raw values.
+ */
+ $match = null;
+ preg_match( '~^
$~', (string) $p, $match );
+ list( , $actual_value ) = $match;
+
+ $this->assertEquals( $actual_value, '"' . esc_attr( $attribute_value ) . '"' );
+ }
+
+ /**
+ * Data provider with HTML attribute values that might need escaping.
+ */
+ public function data_set_attribute_escapable_values() {
+ return array(
+ array( '"' ),
+ array( '"' ),
+ array( '&' ),
+ array( '&' ),
+ array( '€' ),
+ array( "'" ),
+ array( '<>' ),
+ array( '"";' ),
+ array( '" onclick="alert(\'1\');"> ' ),
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_set_attribute_with_a_non_existing_attribute_adds_a_new_attribute_to_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->set_attribute( 'test-attribute', 'test-value' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * According to HTML spec, only the first instance of an attribute counts.
+ * The other ones are ignored.
+ *
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_update_first_when_duplicated_attribute() {
+ $p = new WP_HTML_Tag_Processor( 'Text
' );
+ $p->next_tag();
+ $p->set_attribute( 'id', 'updated-id' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_set_attribute_with_an_existing_attribute_name_updates_its_value_in_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->set_attribute( 'id', 'new-id' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_next_tag_and_set_attribute_in_a_loop_update_all_tags_in_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ while ( $p->next_tag() ) {
+ $p->set_attribute( 'data-foo', 'bar' );
+ }
+
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * Removing an attribute that's listed many times, e.g. `
` should remove
+ * all its instances and output just `
`.
+ *
+ * Today, however, WP_HTML_Tag_Processor only removes the first such attribute. It seems like a corner case
+ * and introducing additional complexity to correctly handle this scenario doesn't seem to be worth it.
+ * Let's revisit if and when this becomes a problem.
+ *
+ * This test is in place to confirm this behavior, while incorrect, is well-defined.
+ *
+ * @ticket 56299
+ *
+ * @covers remove_attribute
+ * @covers __toString
+ */
+ public function test_remove_first_when_duplicated_attribute() {
+ $p = new WP_HTML_Tag_Processor( 'Text
' );
+ $p->next_tag();
+ $p->remove_attribute( 'id' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_attribute
+ * @covers __toString
+ */
+ public function test_remove_attribute_with_an_existing_attribute_name_removes_it_from_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->remove_attribute( 'id' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_attribute
+ * @covers __toString
+ */
+ public function test_remove_attribute_with_a_non_existing_attribute_name_does_not_change_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->remove_attribute( 'no-such-attribute' );
+ $this->assertSame( self::HTML_SIMPLE, (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_add_class_creates_a_class_attribute_when_there_is_none() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->add_class( 'foo-class' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_calling_add_class_twice_creates_a_class_attribute_with_both_class_names_when_there_is_no_class_attribute() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->add_class( 'foo-class' );
+ $p->add_class( 'bar-class' );
+ $this->assertSame( 'Text
', (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_remove_class_does_not_change_the_markup_when_there_is_no_class_attribute() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE );
+ $p->next_tag();
+ $p->remove_class( 'foo-class' );
+ $this->assertSame( self::HTML_SIMPLE, (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_add_class_appends_class_names_to_the_existing_class_attribute_when_one_already_exists() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->add_class( 'foo-class' );
+ $p->add_class( 'bar-class' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_remove_class_removes_a_single_class_from_the_class_attribute_when_one_exists() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->remove_class( 'main' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_calling_remove_class_with_all_listed_class_names_removes_the_existing_class_attribute_from_the_markup() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->remove_class( 'main' );
+ $p->remove_class( 'with-border' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_add_class_does_not_add_duplicate_class_names() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->add_class( 'with-border' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_add_class_preserves_class_name_order_when_a_duplicate_class_name_is_added() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->add_class( 'main' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers __toString
+ */
+ public function test_add_class_when_there_is_a_class_attribute_with_excessive_whitespaces() {
+ $p = new WP_HTML_Tag_Processor(
+ 'Text
'
+ );
+ $p->next_tag();
+ $p->add_class( 'foo-class' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_remove_class_preserves_whitespaces_when_there_is_a_class_attribute_with_excessive_whitespaces() {
+ $p = new WP_HTML_Tag_Processor(
+ 'Text
'
+ );
+ $p->next_tag();
+ $p->remove_class( 'with-border' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_removing_all_classes_removes_the_existing_class_attribute_from_the_markup_even_when_excessive_whitespaces_are_present() {
+ $p = new WP_HTML_Tag_Processor(
+ 'Text
'
+ );
+ $p->next_tag();
+ $p->remove_class( 'main' );
+ $p->remove_class( 'with-border' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * When both set_attribute('class', $value) and add_class( $different_value ) are called,
+ * the final class name should be $value. In other words, the `add_class` call should be ignored,
+ * and the `set_attribute` call should win. This holds regardless of the order in which these methods
+ * are called.
+ *
+ * @ticket 56299
+ *
+ * @covers add_class
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_set_attribute_takes_priority_over_add_class() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->add_class( 'add_class' );
+ $p->set_attribute( 'class', 'set_attribute' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p,
+ 'Calling __toString after updating first tag\'s attributes did not return the expected HTML'
+ );
+
+ $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES );
+ $p->next_tag();
+ $p->set_attribute( 'class', 'set_attribute' );
+ $p->add_class( 'add_class' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p,
+ 'Calling __toString after updating second tag\'s attributes did not return the expected HTML'
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers remove_attribute
+ * @covers add_class
+ * @covers remove_class
+ * @covers __toString
+ */
+ public function test_advanced_use_case() {
+ $input = <<
+
+
+HTML;
+
+ $expected_output = <<
+
+
+HTML;
+
+ $p = new WP_HTML_Tag_Processor( $input );
+ $this->assertTrue( $p->next_tag( 'div' ), 'Querying an existing tag did not return true' );
+ $p->set_attribute( 'data-details', '{ "key": "value" }' );
+ $p->add_class( 'is-processed' );
+ $this->assertTrue(
+ $p->next_tag(
+ array(
+ 'tag_name' => 'div',
+ 'class_name' => 'BtnGroup',
+ )
+ ),
+ 'Querying an existing tag did not return true'
+ );
+ $p->remove_class( 'BtnGroup' );
+ $p->add_class( 'button-group' );
+ $p->add_class( 'Another-Mixed-Case' );
+ $this->assertTrue(
+ $p->next_tag(
+ array(
+ 'tag_name' => 'div',
+ 'class_name' => 'BtnGroup',
+ )
+ ),
+ 'Querying an existing tag did not return true'
+ );
+ $p->remove_class( 'BtnGroup' );
+ $p->add_class( 'button-group' );
+ $p->add_class( 'Another-Mixed-Case' );
+ $this->assertTrue(
+ $p->next_tag(
+ array(
+ 'tag_name' => 'button',
+ 'class_name' => 'btn',
+ 'match_offset' => 3,
+ )
+ ),
+ 'Querying an existing tag did not return true'
+ );
+ $p->remove_attribute( 'class' );
+ $this->assertFalse( $p->next_tag( 'non-existent' ), 'Querying a non-existing tag did not return false' );
+ $p->set_attribute( 'class', 'test' );
+ $this->assertSame( $expected_output, (string) $p, 'Calling __toString after updating the attributes did not return the expected HTML' );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers remove_attribute
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_correctly_parses_html_attributes_wrapped_in_single_quotation_marks() {
+ $p = new WP_HTML_Tag_Processor(
+ 'Text
'
+ );
+ $p->next_tag(
+ array(
+ 'tag_name' => 'div',
+ 'id' => 'first',
+ )
+ );
+ $p->remove_attribute( 'id' );
+ $p->next_tag(
+ array(
+ 'tag_name' => 'span',
+ 'id' => 'second',
+ )
+ );
+ $p->set_attribute( 'id', 'single-quote' );
+ $this->assertSame(
+ 'Text
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_set_attribute_with_value_equals_to_true_adds_a_boolean_html_attribute_with_implicit_value() {
+ $p = new WP_HTML_Tag_Processor(
+ 'I have a bike '
+ );
+ $p->next_tag( 'input' );
+ $p->set_attribute( 'checked', true );
+ $this->assertSame(
+ 'I have a bike ',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_setting_a_boolean_attribute_to_false_removes_it_from_the_markup() {
+ $p = new WP_HTML_Tag_Processor(
+ 'I have a bike '
+ );
+ $p->next_tag( 'input' );
+ $p->set_attribute( 'checked', false );
+ $this->assertSame(
+ 'I have a bike ',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_setting_a_missing_attribute_to_false_does_not_change_the_markup() {
+ $html_input = 'I have a bike ';
+ $p = new WP_HTML_Tag_Processor( $html_input );
+ $p->next_tag( 'input' );
+ $p->set_attribute( 'checked', false );
+ $this->assertSame( $html_input, (string) $p );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_setting_a_boolean_attribute_to_a_string_value_adds_explicit_value_to_the_markup() {
+ $p = new WP_HTML_Tag_Processor(
+ 'I have a bike '
+ );
+ $p->next_tag( 'input' );
+ $p->set_attribute( 'checked', 'checked' );
+ $this->assertSame(
+ 'I have a bike ',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers get_tag
+ * @covers next_tag
+ */
+ public function test_unclosed_script_tag_should_not_cause_an_infinite_loop() {
+ $p = new WP_HTML_Tag_Processor( '
',
+ );
+
+ $examples['Simple uppercase script tag'] = array(
+ '
',
+ );
+
+ $examples['Script with a comment opener inside should end at the next script tag closer (dash dash escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Script with a comment opener and a script tag opener inside should end two script tag closer later (double escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Double escaped script with a tricky opener'] = array(
+ '">">
',
+ );
+
+ $examples['Double escaped script with a tricky closer'] = array(
+ '">
',
+ );
+
+ $examples['Double escaped, then escaped, then double escaped'] = array(
+ '
',
+ );
+
+ $examples['Script with a commented a script tag opener inside should at the next tag closer (dash dash escaped state)'] = array(
+ '
-->',
+ );
+
+ $examples['Script closer with another script tag in closer attributes'] = array(
+ '
',
+ );
+
+ $examples['Script closer with attributes'] = array(
+ '
',
+ );
+
+ $examples['Script opener with title closer inside'] = array(
+ '
',
+ );
+
+ $examples['Complex script with many parsing states'] = array(
+ '-->
-->',
+ );
+ return $examples;
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ *
+ * @dataProvider data_rcdata_state
+ */
+ public function test_next_tag_ignores_the_contents_of_a_rcdata_tag( $rcdata_then_div, $rcdata_tag ) {
+ $p = new WP_HTML_Tag_Processor( $rcdata_then_div );
+ $p->next_tag();
+ $this->assertSame( $rcdata_tag, $p->get_tag(), "The first found tag was not '$rcdata_tag'" );
+ $p->next_tag();
+ $this->assertSame( 'DIV', $p->get_tag(), "The second found tag was not 'div'" );
+ }
+
+ /**
+ * Data provider for test_ignores_contents_of_a_rcdata_tag().
+ *
+ * @return array {
+ * @type array {
+ * @type string $rcdata_then_div The HTML snippet containing RCDATA and div tags.
+ * @type string $rcdata_tag The RCDATA tag.
+ * }
+ * }
+ */
+ public function data_rcdata_state() {
+ $examples = array();
+ $examples['Simple textarea'] = array(
+ 'Back to notifications
',
+ 'TEXTAREA',
+ );
+
+ $examples['Simple title'] = array(
+ 'Back to notifications
',
+ 'TITLE',
+ );
+
+ $examples['Comment opener inside a textarea tag should be ignored'] = array(
+ '',
+ 'TEXTAREA',
+ );
+
+ $examples['Textarea closer with another textarea tag in closer attributes'] = array(
+ 'Back to notifications
',
+ 'TEXTAREA',
+ );
+
+ $examples['Textarea closer with attributes'] = array(
+ 'Back to notifications
',
+ 'TEXTAREA',
+ );
+
+ $examples['Textarea opener with title closer inside'] = array(
+ '
',
+ 'TEXTAREA',
+ );
+ return $examples;
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_can_query_and_update_wrongly_nested_tags() {
+ $p = new WP_HTML_Tag_Processor(
+ '123456
789'
+ );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'class', 'span-class' );
+ $p->next_tag( 'p' );
+ $p->set_attribute( 'class', 'p-class' );
+ $this->assertSame(
+ '123456
789',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers remove_attribute
+ * @covers __toString
+ */
+ public function test_removing_attributes_works_even_in_malformed_html() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED );
+ $p->next_tag( 'span' );
+ $p->remove_attribute( 'Notifications<' );
+ $this->assertSame(
+ 'Back to notifications
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_Tag
+ * @covers set_attribute
+ * @covers __toString
+ */
+ public function test_updating_attributes_works_even_in_malformed_html_1() {
+ $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'id', 'first' );
+ $p->next_tag( 'span' );
+ $p->set_attribute( 'id', 'second' );
+ $this->assertSame(
+ 'Back to notifications
',
+ (string) $p
+ );
+ }
+
+ /**
+ * @ticket 56299
+ *
+ * @covers next_tag
+ * @covers set_attribute
+ * @covers add_class
+ * @covers __toString
+ *
+ * @dataProvider data_malformed_tag
+ */
+ public function test_updating_attributes_works_even_in_malformed_html_2( $html_input, $html_expected ) {
+ $p = new WP_HTML_Tag_Processor( $html_input );
+ $p->next_tag();
+ $p->set_attribute( 'foo', 'bar' );
+ $p->add_class( 'firstTag' );
+ $p->next_tag();
+ $p->add_class( 'secondTag' );
+ $this->assertSame(
+ $html_expected,
+ (string) $p
+ );
+ }
+
+ /**
+ * Data provider for test_updates_when_malformed_tag().
+ *
+ * @return array {
+ * @type array {
+ * @type string $html_input The input HTML snippet.
+ * @type string $html_expected The expected HTML snippet after processing.
+ * }
+ * }
+ */
+ public function data_malformed_tag() {
+ $null_byte = chr( 0 );
+ $examples = array();
+ $examples['Invalid entity inside attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['HTML tag opening inside attribute value'] = array(
+ 'This <is> a <strong is="true">thing.
test ',
+ 'This <is> a <strong is="true">thing.
test ',
+ );
+
+ $examples['HTML tag brackets in attribute values and data markup'] = array(
+ 'This <is> a <strong is="true">thing.
test ',
+ 'This <is> a <strong is="true">thing.
test ',
+ );
+
+ $examples['Single and double quotes in attribute value'] = array(
+ 'test ',
+ '
test ',
+ );
+
+ $examples['Unquoted attribute values'] = array(
+ '
test ',
+ 'test ',
+ );
+
+ $examples['Double-quotes escaped in double-quote attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Unquoted attribute value'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Unquoted attribute value with tag-like value'] = array(
+ ' >test ',
+ ' >test ',
+ );
+
+ $examples['Unquoted attribute value with tag-like value followed by tag-like data'] = array(
+ ' >test ',
+ ' >test ',
+ );
+
+ $examples['1'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['2'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['4'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['5'] = array(
+ ' code>test ',
+ ' code>test ',
+ );
+
+ $examples['6'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['7'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['8'] = array(
+ ' id="test">test ',
+ ' id="test">test ',
+ );
+
+ $examples['9'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['10'] = array(
+ '>test ',
+ '>test ',
+ );
+
+ $examples['11'] = array(
+ 'The applicative operator <* works well in Haskell; is what?test ',
+ 'The applicative operator <* works well in Haskell; is what?test ',
+ );
+
+ $examples['12'] = array(
+ '<3 is a heart but is a tag.test ',
+ '<3 is a heart but is a tag.test ',
+ );
+
+ $examples['13'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['14'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['15'] = array(
+ ' a HTML Tag ]]>test ',
+ ' a HTML Tag ]]>test ',
+ );
+
+ $examples['16'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['17'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['18'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['19'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['20'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['21'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['22'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['23'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['24'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['25'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['Multiple unclosed tags treated as a single tag'] = array(
+ '
+test ',
+ '
+test ',
+ );
+
+ $examples['27'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ $examples['28'] = array(
+ 'test ',
+ 'test ',
+ );
+
+ return $examples;
+ }
+}
diff --git a/phpunit/html/wp-html-tag-processor-wp-test.php b/phpunit/html/wp-html-tag-processor-wp-test.php
new file mode 100644
index 00000000000000..6c3a30340b2677
--- /dev/null
+++ b/phpunit/html/wp-html-tag-processor-wp-test.php
@@ -0,0 +1,91 @@
+
+ * $p = new WP_HTML_Tag_Processor( '' );
+ * $p->next_tag();
+ * $p->set_attribute('class', '" onclick="alert');
+ * echo $p;
+ * //
+ *
+ *
+ * To prevent it, `set_attribute` calls `esc_attr()` on its given values.
+ *
+ *
+ *
+ *
+ *
+ * @ticket 56299
+ *
+ * @dataProvider data_set_attribute_escapable_values
+ * @covers set_attribute
+ */
+ public function test_set_attribute_prevents_xss( $value_to_set, $expected_result ) {
+ $p = new WP_HTML_Tag_Processor( '
' );
+ $p->next_tag();
+ $p->set_attribute( 'test', $value_to_set );
+
+ /*
+ * Testing the escaping is hard using tools that properly parse
+ * HTML because they might interpret the escaped values. It's hard
+ * with tools that don't understand HTML because they might get
+ * confused by improperly-escaped values.
+ *
+ * For this test, since we control the input HTML we're going to
+ * do what looks like the opposite of what we want to be doing with
+ * this library but are only doing so because we have full control
+ * over the content and because we want to look at the raw values.
+ */
+ $match = null;
+ preg_match( '~^
$~', (string) $p, $match );
+ list( , $actual_value ) = $match;
+
+ $this->assertEquals( $actual_value, '"' . $expected_result . '"' );
+ }
+
+ /**
+ * Data provider with HTML attribute values that might need escaping.
+ */
+ public function data_set_attribute_escapable_values() {
+ return array(
+ array( '"', '"' ),
+ array( '"', '"' ),
+ array( '&', '&' ),
+ array( '&', '&' ),
+ array( '€', '€' ),
+ array( "'", ''' ),
+ array( '<>', '<>' ),
+ array( '"";', '"";' ),
+ array(
+ '" onclick="alert(\'1\');"> ',
+ '" onclick="alert('1');"><span onclick=""></span><script>alert("1")</script>',
+ ),
+ );
+ }
+
+}
diff --git a/phpunit/navigation-page-test.php b/phpunit/navigation-page-test.php
index 8cfb4170663d56..3209f77d824497 100644
--- a/phpunit/navigation-page-test.php
+++ b/phpunit/navigation-page-test.php
@@ -83,7 +83,7 @@ public function test_gutenberg_navigation_editor_preload_menus_initializes_creat
$this->callback
->expects( $this->once() )
->method( 'preload_menus_rest_pre_dispatch_callback' )
- ->willReturn( new $response );
+ ->willReturn( $response );
gutenberg_navigation_editor_preload_menus();
diff --git a/schemas/json/theme.json b/schemas/json/theme.json
index 62e27ff14611d9..947509c0377749 100644
--- a/schemas/json/theme.json
+++ b/schemas/json/theme.json
@@ -8,6 +8,7 @@
"reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/"
},
"settingsPropertiesAppearanceTools": {
+ "type": "object",
"properties": {
"appearanceTools": {
"description": "Setting that enables the following UI tools:\n\n- border: color, radius, style, width\n- color: link\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
@@ -26,6 +27,7 @@
}
},
"settingsPropertiesBorder": {
+ "type": "object",
"properties": {
"border": {
"description": "Settings related to borders.",
@@ -57,6 +59,7 @@
}
},
"settingsPropertiesColor": {
+ "type": "object",
"properties": {
"color": {
"description": "Settings related to colors.",
@@ -186,6 +189,7 @@
}
},
"settingsPropertiesLayout": {
+ "type": "object",
"properties": {
"layout": {
"description": "Settings related to layout.",
@@ -205,6 +209,7 @@
}
},
"settingsPropertiesSpacing": {
+ "type": "object",
"properties": {
"spacing": {
"description": "Settings related to spacing.",
@@ -310,6 +315,7 @@
}
},
"settingsPropertiesTypography": {
+ "type": "object",
"properties": {
"typography": {
"description": "Settings related to typography.",
@@ -379,18 +385,25 @@
},
"fluid": {
"description": "Specifics the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
- "type": [ "object", "boolean" ],
- "properties": {
- "min": {
- "description": "A min font size for fluid font size calculations in px, rem or em.",
- "type": "string"
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "min": {
+ "description": "A min font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ },
+ "max": {
+ "description": "A max font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
},
- "max": {
- "description": "A max font size for fluid font size calculations in px, rem or em.",
- "type": "string"
+ {
+ "type": "boolean"
}
- },
- "additionalProperties": false
+ ]
}
},
"additionalProperties": false
@@ -432,7 +445,6 @@
},
"fontWeight": {
"description": "List of available font weights, separated by a space.",
- "type": "string",
"default": "400",
"oneOf": [
{
@@ -451,7 +463,8 @@
"auto",
"block",
"fallback",
- "swap"
+ "swap",
+ "optional"
]
},
"src": {
@@ -520,6 +533,7 @@
}
},
"settingsPropertiesCustom": {
+ "type": "object",
"properties": {
"custom": {
"description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
@@ -562,6 +576,7 @@
"type": "object",
"properties": {
"core/archives": {
+ "type": "object",
"description": "Archive block. Display a monthly archive of your posts. This block has no block-level settings",
"additionalProperties": false
},
@@ -575,11 +590,13 @@
"$ref": "#/definitions/settingsPropertiesComplete"
},
"core/button": {
+ "type": "object",
"allOf": [
{
"$ref": "#/definitions/settingsPropertiesAppearanceTools"
},
{
+ "type": "object",
"properties": {
"border": {
"description": "Settings related to borders.\nGutenberg plugin required.",
@@ -862,6 +879,7 @@
}
},
"stylesProperties": {
+ "type": "object",
"properties": {
"border": {
"description": "Border styles.",
@@ -909,60 +927,76 @@
"type": "string"
},
"top": {
- "color": {
- "description": "Sets the `border-top-color` CSS property.",
- "type": "string"
- },
- "style": {
- "description": "Sets the `border-top-style` CSS property.",
- "type": "string"
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-top-color` CSS property.",
+ "type": "string"
+ },
+ "style": {
+ "description": "Sets the `border-top-style` CSS property.",
+ "type": "string"
+ },
+ "width": {
+ "description": "Sets the `border-top-width` CSS property.",
+ "type": "string"
+ }
},
- "width": {
- "description": "Sets the `border-top-width` CSS property.",
- "type": "string"
- }
+ "additionalProperties": false
},
"right": {
- "color": {
- "description": "Sets the `border-right-color` CSS property.",
- "type": "string"
- },
- "style": {
- "description": "Sets the `border-right-style` CSS property.",
- "type": "string"
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-right-color` CSS property.",
+ "type": "string"
+ },
+ "style": {
+ "description": "Sets the `border-right-style` CSS property.",
+ "type": "string"
+ },
+ "width": {
+ "description": "Sets the `border-right-width` CSS property.",
+ "type": "string"
+ }
},
- "width": {
- "description": "Sets the `border-right-width` CSS property.",
- "type": "string"
- }
+ "additionalProperties": false
},
"bottom": {
- "color": {
- "description": "Sets the `border-bottom-color` CSS property.",
- "type": "string"
- },
- "style": {
- "description": "Sets the `border-bottom-style` CSS property.",
- "type": "string"
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-bottom-color` CSS property.",
+ "type": "string"
+ },
+ "style": {
+ "description": "Sets the `border-bottom-style` CSS property.",
+ "type": "string"
+ },
+ "width": {
+ "description": "Sets the `border-bottom-width` CSS property.",
+ "type": "string"
+ }
},
- "width": {
- "description": "Sets the `border-bottom-width` CSS property.",
- "type": "string"
- }
+ "additionalProperties": false
},
"left": {
- "color": {
- "description": "Sets the `border-left-color` CSS property.",
- "type": "string"
- },
- "style": {
- "description": "Sets the `border-left-style` CSS property.",
- "type": "string"
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-left-color` CSS property.",
+ "type": "string"
+ },
+ "style": {
+ "description": "Sets the `border-left-style` CSS property.",
+ "type": "string"
+ },
+ "width": {
+ "description": "Sets the `border-left-width` CSS property.",
+ "type": "string"
+ }
},
- "width": {
- "description": "Sets the `border-left-width` CSS property.",
- "type": "string"
- }
+ "additionalProperties": false
}
},
"additionalProperties": false
@@ -1145,7 +1179,33 @@
"type": "object",
"properties": {
"button": {
- "$ref": "#/definitions/stylesPropertiesComplete"
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "properties": {
+ "border": {},
+ "color": {},
+ "filter": {},
+ "outline": {},
+ "shadow": {},
+ "spacing": {},
+ "typography": {},
+ ":hover": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":focus": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":active": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
},
"link": {
"type": "object",
diff --git a/test/e2e/specs/editor/blocks/paragraph.spec.js b/test/e2e/specs/editor/blocks/paragraph.spec.js
index d4848234986f2b..6a043153320d83 100644
--- a/test/e2e/specs/editor/blocks/paragraph.spec.js
+++ b/test/e2e/specs/editor/blocks/paragraph.spec.js
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+const path = require( 'path' );
+
/**
* WordPress dependencies
*/
@@ -28,4 +33,160 @@ test.describe( 'Paragraph', () => {
// style.
expect( firstBlockTagName ).toBe( 'P' );
} );
+
+ test.describe( 'Empty paragraph', () => {
+ test.use( {
+ // Make the viewport large enough so that a scrollbar isn't displayed.
+ // Otherwise, the page scrolling can interfere with the test runner's
+ // ability to drop a block in the right location.
+ viewport: {
+ width: 960,
+ height: 1024,
+ },
+ } );
+
+ test.beforeAll( async ( { requestUtils } ) => {
+ await requestUtils.deleteAllMedia();
+ } );
+
+ test.afterEach( async ( { requestUtils } ) => {
+ await requestUtils.deleteAllMedia();
+ } );
+
+ test( 'should allow dropping an image on en empty paragraph block', async ( {
+ editor,
+ page,
+ pageUtils,
+ } ) => {
+ await editor.insertBlock( { name: 'core/paragraph' } );
+
+ const testImageName = '10x10_e2e_test_image_z9T8jK.png';
+ const testImagePath = path.join(
+ __dirname,
+ '../../../assets',
+ testImageName
+ );
+
+ const { dragOver, drop } = await pageUtils.dragFiles(
+ testImagePath
+ );
+
+ await dragOver( '[data-type="core/paragraph"]' );
+
+ await expect(
+ page.locator( 'data-testid=empty-paragraph-drop-zone' )
+ ).toBeVisible();
+
+ await drop();
+
+ const imageBlock = page.locator(
+ 'role=document[name="Block: Image"i]'
+ );
+ await expect( imageBlock ).toBeVisible();
+ await expect( imageBlock.locator( 'role=img' ) ).toHaveAttribute(
+ 'src',
+ new RegExp( testImageName.replace( '.', '\\.' ) )
+ );
+ } );
+
+ test( 'should allow dropping blocks on en empty paragraph block', async ( {
+ editor,
+ page,
+ } ) => {
+ await editor.insertBlock( {
+ name: 'core/heading',
+ attributes: { content: 'My Heading' },
+ } );
+ await editor.insertBlock( { name: 'core/paragraph' } );
+ await page.focus( 'text=My Heading' );
+ await editor.showBlockToolbar();
+
+ const dragHandle = page.locator(
+ 'role=toolbar[name="Block tools"i] >> role=button[name="Drag"i][include-hidden]'
+ );
+ await dragHandle.hover();
+ await page.mouse.down();
+
+ const emptyParagraph = page.locator(
+ '[data-type="core/paragraph"][data-empty="true"]'
+ );
+ const boundingBox = await emptyParagraph.boundingBox();
+ // Call the move function twice to make sure the `dragOver` event is sent.
+ // @see https://github.com/microsoft/playwright/issues/17153
+ for ( let i = 0; i < 2; i += 1 ) {
+ await page.mouse.move( boundingBox.x, boundingBox.y );
+ }
+
+ await expect(
+ page.locator( 'data-testid=empty-paragraph-drop-zone' )
+ ).toBeVisible();
+
+ await page.mouse.up();
+
+ await expect.poll( editor.getEditedPostContent )
+ .toBe( `
+My Heading
+` );
+ } );
+
+ test( 'should allow dropping HTML on en empty paragraph block', async ( {
+ editor,
+ page,
+ } ) => {
+ await editor.insertBlock( { name: 'core/paragraph' } );
+
+ // Insert a dummy draggable element on the page to simulate dragging
+ // HTML from other places.
+ await page.evaluate( () => {
+ const draggable = document.createElement( 'div' );
+ draggable.draggable = true;
+ draggable.style.width = '10px';
+ draggable.style.height = '10px';
+ // Position it at the top left corner for convenience.
+ draggable.style.position = 'fixed';
+ draggable.style.top = 0;
+ draggable.style.left = 0;
+ draggable.style.zIndex = 999999;
+
+ draggable.addEventListener(
+ 'dragstart',
+ ( event ) => {
+ // Set the data transfer to some HTML on dragstart.
+ event.dataTransfer.setData(
+ 'text/html',
+ 'My Heading '
+ );
+ },
+ { once: true }
+ );
+
+ document.body.appendChild( draggable );
+ } );
+
+ // This is where the dummy draggable element is at.
+ await page.mouse.move( 0, 0 );
+ await page.mouse.down();
+
+ const emptyParagraph = page.locator(
+ '[data-type="core/paragraph"][data-empty="true"]'
+ );
+ const boundingBox = await emptyParagraph.boundingBox();
+ // Call the move function twice to make sure the `dragOver` event is sent.
+ // @see https://github.com/microsoft/playwright/issues/17153
+ for ( let i = 0; i < 2; i += 1 ) {
+ await page.mouse.move( boundingBox.x, boundingBox.y );
+ }
+
+ await expect(
+ page.locator( 'data-testid=empty-paragraph-drop-zone' )
+ ).toBeVisible();
+
+ await page.mouse.up();
+
+ await expect.poll( editor.getEditedPostContent )
+ .toBe( `
+My Heading
+` );
+ } );
+ } );
} );
diff --git a/test/e2e/specs/editor/plugins/__snapshots__/Iframed-block-Should-save-the-changes-1-chromium.txt b/test/e2e/specs/editor/plugins/__snapshots__/Iframed-block-Should-save-the-changes-1-chromium.txt
new file mode 100644
index 00000000000000..bcc47c713c778a
--- /dev/null
+++ b/test/e2e/specs/editor/plugins/__snapshots__/Iframed-block-Should-save-the-changes-1-chromium.txt
@@ -0,0 +1,3 @@
+
+Iframed Block (saved)
+
\ No newline at end of file
diff --git a/test/e2e/specs/editor/plugins/iframed-block.spec.js b/test/e2e/specs/editor/plugins/iframed-block.spec.js
new file mode 100644
index 00000000000000..55b67cb70fe86e
--- /dev/null
+++ b/test/e2e/specs/editor/plugins/iframed-block.spec.js
@@ -0,0 +1,46 @@
+/**
+ * WordPress dependencies
+ */
+const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
+
+test.describe( 'Iframed block', () => {
+ test.beforeEach( async ( { requestUtils, admin } ) => {
+ await requestUtils.activatePlugin( 'gutenberg-test-iframed-block' );
+ await admin.createNewPost( { postType: 'page' } );
+ } );
+
+ test.afterEach( async ( { requestUtils } ) => {
+ await requestUtils.deactivatePlugin( 'gutenberg-test-iframed-block' );
+ } );
+
+ test( 'Should save the changes', async ( { editor, page } ) => {
+ await editor.insertBlock( { name: 'test/iframed-block' } );
+ expect( await editor.getEditedPostContent() ).toMatchSnapshot();
+
+ await expect(
+ page.locator( 'role=document[name="Block: Iframed Block"i]' )
+ ).toContainText( 'Iframed Block (set with jQuery)' );
+
+ // open page from sidebar settings
+ await page.click(
+ 'role=region[name="Editor settings"i] >> role=button[name="Page"i]'
+ );
+
+ // Opens the template editor with a newly created template.
+ await page.click( 'role=button[name="Select template"i]' );
+ await page.click( 'role=button[name="Add template"i]' );
+ await page.fill( 'role=textbox[name="NAME"i]', 'Test template' );
+ await page.click( 'role=button[name="Create"i]' );
+
+ // Expect iframe canvas to be visible
+ await expect(
+ page.locator( 'iframe[name="editor-canvas"]' )
+ ).toBeVisible();
+
+ // Expect the script to load in the iframe, which replaces the block text.
+ const iframedText = page.frameLocator( 'iframe' ).locator( 'body' );
+ await expect( iframedText ).toContainText(
+ 'Iframed Block (set with jQuery)'
+ );
+ } );
+} );
diff --git a/test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js b/test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js
new file mode 100644
index 00000000000000..67270fb2cc3570
--- /dev/null
+++ b/test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js
@@ -0,0 +1,412 @@
+/**
+ * WordPress dependencies
+ */
+const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
+
+const userList = [
+ {
+ username: 'testuser',
+ firstName: 'Jane',
+ lastName: 'Doe',
+ password: 'iLoVeE2EtEsTs',
+ },
+ {
+ username: 'yourfather',
+ firstName: 'Darth',
+ lastName: 'Vader',
+ password: 'padme123',
+ },
+ {
+ username: 'mockingjay',
+ firstName: 'Katniss',
+ lastName: 'Everdeen',
+ password: 'district12forlyfe',
+ },
+ {
+ username: 'ringbearer',
+ firstName: 'Frodo',
+ lastName: 'Baggins',
+ password: 'ep1cburgl@r',
+ },
+ {
+ username: 'thebetterhobbit',
+ firstName: 'Bilbo',
+ lastName: 'Baggins',
+ password: 'lostwithouts@m',
+ },
+ {
+ username: 'makeitso',
+ firstName: 'Jean-Luc',
+ lastName: 'Picard',
+ password: 'engagE!1',
+ },
+ {
+ username: 'buddytheelf',
+ firstName: 'Buddy',
+ lastName: 'Elf',
+ password: 'sm1lingsmyfavorite',
+ },
+];
+test.describe( 'Autocomplete', () => {
+ test.beforeAll( async ( { requestUtils } ) => {
+ await Promise.all(
+ userList.map( ( user ) =>
+ requestUtils.createUser( {
+ email: `${ user.username }@example.com`,
+ ...user,
+ } )
+ )
+ );
+ await requestUtils.activatePlugin( 'gutenberg-test-autocompleter' );
+ } );
+
+ test.afterAll( async ( { requestUtils } ) => {
+ await requestUtils.deleteAllUsers();
+ await requestUtils.deactivatePlugin( 'gutenberg-test-autocompleter' );
+ } );
+
+ test.beforeEach( async ( { admin } ) => {
+ await admin.createNewPost();
+ } );
+
+ test.afterEach( async ( { editor } ) => {
+ await editor.publishPost();
+ } );
+
+ [
+ [ 'User Mention', 'mention' ],
+ [ 'Custom Completer', 'option' ],
+ ].forEach( ( completerAndOptionType ) => {
+ const [ completer, type ] = completerAndOptionType;
+ test( `${ completer }: should insert ${ type }`, async ( {
+ page,
+ editor,
+ } ) => {
+ // Set up test data for each case
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.triggerString = 'I am @da';
+ testData.optionText = 'Darth Vader yourfather';
+ testData.snapshot = `
+I am @yourfather.
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = 'I like ~s';
+ testData.optionText = '🍓 Strawberry';
+ testData.snapshot = `
+I like 🍓.
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator( `role=option[name="${ testData.optionText }"i]` )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( '.' );
+
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ test( `${ completer }: should insert ${ type } between two other words`, async ( {
+ page,
+ editor,
+ pageUtils,
+ } ) => {
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.triggerString = '@j';
+ testData.optionText = 'Jane Doe testuser';
+ testData.snapshot = `
+Stuck in the middle with @testuser you.
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = 'a ~m';
+ testData.optionText = '🥭 Mango';
+ testData.snapshot = `
+Stuck in the middle with a 🥭 you.
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( 'Stuck in the middle with you.' );
+ await pageUtils.pressKeyTimes( 'ArrowLeft', 'you.'.length );
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator( `role=option[name="${ testData.optionText }"i]` )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( ' ' );
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ test( `${ completer }: should insert two subsequent ${ type }s`, async ( {
+ page,
+ editor,
+ } ) => {
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.firstTriggerString =
+ 'The two greatest hobbits, in order: @bi';
+ testData.secondTriggerString = ' @fr';
+ testData.firstOptionText = 'Bilbo Baggins thebetterhobbit';
+ testData.secondOptionText = 'Frodo Baggins ringbearer';
+ testData.snapshot = `
+The two greatest hobbits, in order: @thebetterhobbit @ringbearer.
+`;
+ } else if ( type === 'option' ) {
+ testData.firstTriggerString = 'An awesome combination: ~m';
+ testData.secondTriggerString = ' ~b';
+ testData.firstOptionText = '🥭 Mango';
+ testData.secondOptionText = '🫐 Blueberry';
+ testData.snapshot = `
+An awesome combination: 🥭 🫐.
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( testData.firstTriggerString );
+ await expect(
+ page.locator(
+ `role=option[name="${ testData.firstOptionText }"i]`
+ )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( testData.secondTriggerString );
+ await expect(
+ page.locator(
+ `role=option[name="${ testData.secondOptionText }"i]`
+ )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( '.' );
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ test( `${ completer }: should allow ${ type } selection via click event`, async ( {
+ page,
+ editor,
+ } ) => {
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.triggerString = '@';
+ testData.optionText = 'Katniss Everdeen mockingjay';
+ testData.snapshot = `
+@mockingjay
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = '~';
+ testData.optionText = '🍓 Strawberry';
+ testData.snapshot = `
+🍓
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator( `role=option[name="${ testData.optionText }"i]` )
+ ).toBeVisible();
+ await page;
+ page.locator(
+ `role=option[name="${ testData.optionText }"i]`
+ ).click();
+
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ test( `${ completer }: should allow ${ type } selection via keypress event`, async ( {
+ page,
+ editor,
+ pageUtils,
+ } ) => {
+ const testData = {};
+ // Jean-Luc is the target because user mentions will be listed alphabetically by first + last name
+ // This may seem off by one, but that's only because the test site adds an `admin` user that ends up at the top of the list
+ // 🍒 is the target because options are listed in the order they appear in the custom completer
+ if ( type === 'mention' ) {
+ testData.triggerString = '@';
+ testData.optionText = 'Jean-Luc Picard makeitso';
+ testData.snapshot = `
+@makeitso
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = '~';
+ testData.optionText = '🍒 Cherry';
+ testData.snapshot = `
+🍒
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator( `role=option[name="${ testData.optionText }"i]` )
+ ).toBeVisible();
+ await pageUtils.pressKeyTimes( 'ArrowDown', 6 );
+ await page.keyboard.press( 'Enter' );
+
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ test( `${ completer }: should cancel ${ type } selection via \`Escape\` keypress event`, async ( {
+ page,
+ editor,
+ } ) => {
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.triggerString = 'My name is @j';
+ testData.optionText = 'Jane Doe testuser';
+ testData.postCompleterInput = ' ...a secret.';
+ testData.snapshot = `
+My name is @j ...a secret.
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = 'My favorite fruit is ~a';
+ testData.optionText = '🍎 Apple';
+ testData.postCompleterInput =
+ " ...no I changed my mind. It's mango.";
+ testData.snapshot = `
+My favorite fruit is ~a ...no I changed my mind. It's mango.
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator( `role=option[name="${ testData.optionText }"i]` )
+ ).toBeVisible();
+ await page.keyboard.press( 'Escape' );
+ await page.keyboard.type( testData.postCompleterInput );
+ // The characters before `Escape` should remain (i.e. `~app`)
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+
+ // This test does not apply to user mentions, because they don't get disabled.
+ if ( type !== 'mention' ) {
+ test( `${ completer }: should not insert disabled ${ type }s`, async ( {
+ page,
+ editor,
+ } ) => {
+ await page.click( 'role=button[name="Add default block"i]' );
+ // The 'Grapes' option is disabled in our test plugin, so it should not insert the grapes emoji
+ await page.keyboard.type( 'Sorry, we are all out of ~g' );
+ await expect(
+ page.locator( 'role=option', { hasText: '🍇 Grape' } )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( ' grapes.' );
+ await expect.poll( editor.getEditedPostContent )
+ .toBe( `
+Sorry, we are all out of ~g grapes.
+` );
+ } );
+ }
+
+ test( `${ completer }: should allow newlines after multiple ${ type } completions`, async ( {
+ page,
+ editor,
+ } ) => {
+ const testData = {};
+ if ( type === 'mention' ) {
+ testData.triggerString = '@bu';
+ testData.optionText = 'Buddy Elf buddytheelf';
+ testData.snapshot = `
+@buddytheelf test
+
+
+
+@buddytheelf test
+
+
+
+@buddytheelf test
+
+
+
+@buddytheelf test
+
+
+
+
+`;
+ } else if ( type === 'option' ) {
+ testData.triggerString = '~b';
+ testData.optionText = '🫐 Blueberry';
+ testData.snapshot = `
+🫐 test
+
+
+
+🫐 test
+
+
+
+🫐 test
+
+
+
+🫐 test
+
+
+
+
+`;
+ }
+
+ await page.click( 'role=button[name="Add default block"i]' );
+
+ for ( let i = 0; i < 4; i++ ) {
+ await page.keyboard.type( testData.triggerString );
+ await expect(
+ page.locator(
+ `role=option[name="${ testData.optionText }"i]`
+ )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( ' test' );
+ await page.keyboard.press( 'Enter' );
+ }
+
+ await expect
+ .poll( editor.getEditedPostContent )
+ .toBe( testData.snapshot );
+ } );
+ } );
+
+ // The following test concerns an infinite loop regression (https://github.com/WordPress/gutenberg/issues/41709).
+ // When present, the regression will cause this test to time out.
+ test( 'should insert elements from multiple completers in a single block', async ( {
+ page,
+ editor,
+ } ) => {
+ await page.click( 'role=button[name="Add default block"i]' );
+ await page.keyboard.type( '@fr' );
+ await expect(
+ page.locator( 'role=option', { hasText: 'Frodo Baggins' } )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( ' +bi' );
+ await expect(
+ page.locator( 'role=option', { hasText: 'Bilbo Baggins' } )
+ ).toBeVisible();
+ await page.keyboard.press( 'Enter' );
+ await expect.poll( editor.getEditedPostContent )
+ .toBe( `
+@ringbearer +thebetterhobbit
+` );
+ } );
+} );
diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js
index 5e828bce2bf7da..05bca4285eb414 100644
--- a/test/e2e/specs/editor/various/writing-flow.spec.js
+++ b/test/e2e/specs/editor/various/writing-flow.spec.js
@@ -700,7 +700,7 @@ test.describe( 'Writing Flow', () => {
const x = paragraphRect.x + ( 2 * paragraphRect.width ) / 3;
const y = paragraphRect.y + paragraphRect.height + 1;
- // The typing observer requires two mouse moves to dectect and actual
+ // The typing observer requires two mouse moves to detect an actual
// move.
await page.mouse.move( x - 1, y - 1 );
await page.mouse.move( x, y );
@@ -959,6 +959,40 @@ test.describe( 'Writing Flow', () => {
page.locator( 'role=document[name="Paragraph block"i]' )
).toHaveText( /^a+\.a$/ );
} );
+
+ test( 'should vertically move the caret when pressing Alt', async ( {
+ page,
+ pageUtils,
+ } ) => {
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( 'a' );
+
+ async function getHeight() {
+ return await page.evaluate(
+ () => document.activeElement.offsetHeight
+ );
+ }
+
+ const height = await getHeight();
+
+ // Keep typing until the height of the element increases. We need two
+ // lines.
+ while ( height === ( await getHeight() ) ) {
+ await page.keyboard.type( 'a' );
+ }
+
+ // Create a new paragraph.
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.type( 'b' );
+ await page.keyboard.press( 'ArrowLeft' );
+ await pageUtils.pressKeyWithModifier( 'alt', 'ArrowUp' );
+ await page.keyboard.type( '.' );
+
+ // Expect the "." to be added at the start of the paragraph
+ await expect(
+ page.locator( 'role=document[name="Paragraph block"i] >> nth = 0' )
+ ).toHaveText( /^.a+$/ );
+ } );
} );
class WritingFlowUtils {
diff --git a/test/integration/blocks-schema.test.js b/test/integration/blocks-schema.test.js
index 8e4ee17b48ff51..1bc75555d6b880 100644
--- a/test/integration/blocks-schema.test.js
+++ b/test/integration/blocks-schema.test.js
@@ -21,6 +21,16 @@ describe( 'block.json schema', () => {
] );
const ajv = new Ajv();
+ test( 'strictly adheres to the draft-04 meta schema', () => {
+ // Use ajv.compile instead of ajv.validateSchema to validate the schema
+ // because validateSchema only checks syntax, whereas, compile checks
+ // if the schema is semantically correct with strict mode.
+ // See https://github.com/ajv-validator/ajv/issues/1434#issuecomment-822982571
+ const result = ajv.compile( blockSchema );
+
+ expect( result.errors ).toBe( null );
+ } );
+
test( 'found block folders', () => {
expect( blockFolders.length ).toBeGreaterThan( 0 );
} );
diff --git a/test/integration/fixtures/blocks/core__post-author.json b/test/integration/fixtures/blocks/core__post-author.json
index c98f6db8560061..7f7871c9fb7056 100644
--- a/test/integration/fixtures/blocks/core__post-author.json
+++ b/test/integration/fixtures/blocks/core__post-author.json
@@ -4,7 +4,9 @@
"isValid": true,
"attributes": {
"avatarSize": 48,
- "showAvatar": true
+ "showAvatar": true,
+ "isLink": false,
+ "linkTarget": "_self"
},
"innerBlocks": []
}
diff --git a/test/integration/theme-schema.test.js b/test/integration/theme-schema.test.js
new file mode 100644
index 00000000000000..0e5ed88a1441eb
--- /dev/null
+++ b/test/integration/theme-schema.test.js
@@ -0,0 +1,27 @@
+/**
+ * External dependencies
+ */
+import Ajv from 'ajv-draft-04';
+
+/**
+ * Internal dependencies
+ */
+import themeSchema from '../../schemas/json/theme.json';
+
+describe( 'theme.json schema', () => {
+ const ajv = new Ajv( {
+ // Used for matching unknown blocks without repeating core blocks names
+ // with patternProperties in settings.blocks and settings.styles
+ allowMatchingProperties: true,
+ } );
+
+ it( 'strictly adheres to the draft-04 meta schema', () => {
+ // Use ajv.compile instead of ajv.validateSchema to validate the schema
+ // because validateSchema only checks syntax, whereas, compile checks
+ // if the schema is semantically correct with strict mode.
+ // See https://github.com/ajv-validator/ajv/issues/1434#issuecomment-822982571
+ const result = ajv.compile( themeSchema );
+
+ expect( result.errors ).toBe( null );
+ } );
+} );
diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js
index c430aae0ed244c..77d7818bacc852 100644
--- a/test/unit/jest.config.js
+++ b/test/unit/jest.config.js
@@ -37,7 +37,6 @@ module.exports = {
'^.+\\.[jt]sx?$': '/test/unit/scripts/babel-transformer.js',
},
snapshotSerializers: [
- 'enzyme-to-json/serializer',
'@emotion/jest/serializer',
'snapshot-diff/serializer',
],
diff --git a/tsconfig.json b/tsconfig.json
index be2b2c31082485..7618b05fc70f7d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -33,6 +33,7 @@
{ "path": "packages/project-management-automation" },
{ "path": "packages/react-i18n" },
{ "path": "packages/report-flaky-tests" },
+ { "path": "packages/style-engine" },
{ "path": "packages/token-list" },
{ "path": "packages/url" },
{ "path": "packages/warning" },