Add coexistence checks to all enqueue methods to prevent loading both React and Grid.js assets simultaneously. Changes: - ReactAdmin.php: Only enqueue React assets when ?react=1 - Init.php: Skip Grid.js when React active on admin pages - Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0 - Customer.php, Product.php, License.php: Add coexistence checks Now the toggle between Classic and React versions works correctly. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
175 lines
4.4 KiB
JavaScript
175 lines
4.4 KiB
JavaScript
/**
|
|
* Traverse up through the chain of parent AST nodes returning the first parent
|
|
* the predicate returns a truthy value for.
|
|
*
|
|
* @param {Object} sourceNode The AST node to search from.
|
|
* @param {Function} predicate A predicate invoked for each parent.
|
|
*
|
|
* @return {Object | undefined} The first encountered parent node where the predicate
|
|
* returns a truthy value.
|
|
*/
|
|
function findParent( sourceNode, predicate ) {
|
|
if ( ! sourceNode.parent ) {
|
|
return;
|
|
}
|
|
|
|
if ( predicate( sourceNode.parent ) ) {
|
|
return sourceNode.parent;
|
|
}
|
|
|
|
return findParent( sourceNode.parent, predicate );
|
|
}
|
|
|
|
/**
|
|
* Tests whether the GUTENBERG_PHASE variable is accessed via
|
|
* `process.env.GUTENBERG_PHASE`.
|
|
*
|
|
* @example
|
|
* ```js
|
|
* // good
|
|
* if ( process.env.GUTENBERG_PHASE === 2 ) {
|
|
*
|
|
* // bad
|
|
* if ( GUTENBERG_PHASE === 2 ) {
|
|
* ```
|
|
*
|
|
* @param {Object} node The GUTENBERG_PHASE identifier node.
|
|
* @param {Object} context The eslint context object.
|
|
*/
|
|
function testIsAccessedViaProcessEnv( node, context ) {
|
|
const parent = node.parent;
|
|
|
|
if (
|
|
parent &&
|
|
parent.type === 'MemberExpression' &&
|
|
context.getSource( parent ) === 'process.env.GUTENBERG_PHASE'
|
|
) {
|
|
return;
|
|
}
|
|
|
|
context.report(
|
|
node,
|
|
'The `GUTENBERG_PHASE` constant should be accessed using `process.env.GUTENBERG_PHASE`.'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Tests whether the GUTENBERG_PHASE variable is used in a strict binary
|
|
* equality expression in a comparison with a number, triggering a
|
|
* violation if not.
|
|
*
|
|
* @example
|
|
* ```js
|
|
* // good
|
|
* if ( process.env.GUTENBERG_PHASE === 2 ) {
|
|
*
|
|
* // bad
|
|
* if ( process.env.GUTENBERG_PHASE >= '2' ) {
|
|
* ```
|
|
*
|
|
* @param {Object} node The GUTENBERG_PHASE identifier node.
|
|
* @param {Object} context The eslint context object.
|
|
*/
|
|
function testIsUsedInStrictBinaryExpression( node, context ) {
|
|
const parent = findParent(
|
|
node,
|
|
( candidate ) => candidate.type === 'BinaryExpression'
|
|
);
|
|
|
|
if ( parent ) {
|
|
const comparisonNode =
|
|
node.parent.type === 'MemberExpression' ? node.parent : node;
|
|
|
|
// Test for process.env.GUTENBERG_PHASE === <number> or <number> === process.env.GUTENBERG_PHASE.
|
|
const hasCorrectOperator = [ '===', '!==' ].includes( parent.operator );
|
|
const hasCorrectOperands =
|
|
( parent.left === comparisonNode &&
|
|
typeof parent.right.value === 'number' ) ||
|
|
( parent.right === comparisonNode &&
|
|
typeof parent.left.value === 'number' );
|
|
|
|
if ( hasCorrectOperator && hasCorrectOperands ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
context.report(
|
|
node,
|
|
'The `GUTENBERG_PHASE` constant should only be used in a strict equality comparison with a primitive number.'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Tests whether the GUTENBERG_PHASE variable is used as the condition for an
|
|
* if statement, triggering a violation if not.
|
|
*
|
|
* @example
|
|
* ```js
|
|
* // good
|
|
* if ( process.env.GUTENBERG_PHASE === 2 ) {
|
|
*
|
|
* // bad
|
|
* const isFeatureActive = process.env.GUTENBERG_PHASE === 2;
|
|
* ```
|
|
*
|
|
* @param {Object} node The GUTENBERG_PHASE identifier node.
|
|
* @param {Object} context The eslint context object.
|
|
*/
|
|
function testIsUsedInIfOrTernary( node, context ) {
|
|
const conditionalParent = findParent( node, ( candidate ) =>
|
|
[ 'IfStatement', 'ConditionalExpression' ].includes( candidate.type )
|
|
);
|
|
const binaryParent = findParent(
|
|
node,
|
|
( candidate ) => candidate.type === 'BinaryExpression'
|
|
);
|
|
|
|
if (
|
|
conditionalParent &&
|
|
binaryParent &&
|
|
conditionalParent.test &&
|
|
conditionalParent.test.range[ 0 ] === binaryParent.range[ 0 ] &&
|
|
conditionalParent.test.range[ 1 ] === binaryParent.range[ 1 ]
|
|
) {
|
|
return;
|
|
}
|
|
|
|
context.report(
|
|
node,
|
|
'The `GUTENBERG_PHASE` constant should only be used as part of the condition in an if statement or ternary expression.'
|
|
);
|
|
}
|
|
|
|
module.exports = {
|
|
meta: {
|
|
type: 'problem',
|
|
schema: [],
|
|
deprecated: true,
|
|
replacedBy: '@wordpress/is-gutenberg-plugin',
|
|
},
|
|
create( context ) {
|
|
return {
|
|
Identifier( node ) {
|
|
// Bypass any identifiers with a node name different to `GUTENBERG_PHASE`.
|
|
if ( node.name !== 'GUTENBERG_PHASE' ) {
|
|
return;
|
|
}
|
|
|
|
testIsAccessedViaProcessEnv( node, context );
|
|
testIsUsedInStrictBinaryExpression( node, context );
|
|
testIsUsedInIfOrTernary( node, context );
|
|
},
|
|
Literal( node ) {
|
|
// Bypass any identifiers with a node value different to `GUTENBERG_PHASE`.
|
|
if ( node.value !== 'GUTENBERG_PHASE' ) {
|
|
return;
|
|
}
|
|
|
|
if ( node.parent && node.parent.type === 'MemberExpression' ) {
|
|
testIsAccessedViaProcessEnv( node, context );
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|