Skip to content

Commit

Permalink
Merge branch 'WordPress:trunk' into trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
miminari authored Oct 25, 2024
2 parents eb4c754 + 0466f7d commit 0ad8409
Show file tree
Hide file tree
Showing 5,649 changed files with 313,448 additions and 254,083 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
302 changes: 233 additions & 69 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ const restrictedImports = [
name: 'lodash',
message: 'Please use native functionality instead.',
},
{
name: 'reakit',
message:
'Please use Reakit API through `@wordpress/components` instead.',
},
{
name: '@ariakit/react',
message:
Expand All @@ -61,10 +56,6 @@ const restrictedImports = [
importNames: [ 'combineReducers' ],
message: 'Please use `combineReducers` from `@wordpress/data` instead.',
},
{
name: 'puppeteer-testing-library',
message: '`puppeteer-testing-library` is still experimental.',
},
{
name: '@emotion/css',
message:
Expand All @@ -85,6 +76,77 @@ const restrictedImports = [
message:
"edit-widgets is a WordPress top level package that shouldn't be imported into other packages",
},
{
name: 'classnames',
message:
"Please use `clsx` instead. It's a lighter and faster drop-in replacement for `classnames`.",
},
];

const restrictedSyntax = [
// NOTE: We can't include the forward slash in our regex or
// we'll get a `SyntaxError` (Invalid regular expression: \ at end of pattern)
// here. That's why we use \\u002F in the regexes below.
{
selector:
'ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]',
message: 'Path access on WordPress dependencies is not allowed.',
},
{
selector:
'CallExpression[callee.name="deprecated"] Property[key.name="version"][value.value=/' +
majorMinorRegExp +
'/]',
message:
'Deprecated functions must be removed before releasing this version.',
},
{
selector:
'CallExpression[callee.object.name="page"][callee.property.name="waitFor"]',
message:
'This method is deprecated. You should use the more explicit API methods available.',
},
{
selector:
'CallExpression[callee.object.name="page"][callee.property.name="waitForTimeout"]',
message: 'Prefer page.waitForSelector instead.',
},
{
selector: 'JSXAttribute[name.name="id"][value.type="Literal"]',
message:
'Do not use string literals for IDs; use withInstanceId instead.',
},
{
// Discourage the usage of `Math.random()` as it's a code smell
// for UUID generation, for which we already have a higher-order
// component: `withInstanceId`.
selector:
'CallExpression[callee.object.name="Math"][callee.property.name="random"]',
message:
'Do not use Math.random() to generate unique IDs; use withInstanceId instead. (If you’re not generating unique IDs: ignore this message.)',
},
{
selector:
'CallExpression[callee.name="withDispatch"] > :function > BlockStatement > :not(VariableDeclaration,ReturnStatement)',
message:
'withDispatch must return an object with consistent keys. Avoid performing logic in `mapDispatchToProps`.',
},
{
selector:
'LogicalExpression[operator="&&"][left.property.name="length"][right.type="JSXElement"]',
message:
'Avoid truthy checks on length property rendering, as zero length is rendered verbatim.',
},
];

/** `no-restricted-syntax` rules for components. */
const restrictedSyntaxComponents = [
{
selector:
'JSXOpeningElement[name.name="Button"]:not(:has(JSXAttribute[name.name="accessibleWhenDisabled"])) JSXAttribute[name.name="disabled"]',
message:
'`disabled` used without the `accessibleWhenDisabled` prop. Disabling a control without maintaining focusability can cause accessibility issues, by hiding their presence from screen reader users, or preventing focus from returning to a trigger element. (Ignore this error if you truly mean to disable.)',
},
];

module.exports = {
Expand All @@ -96,6 +158,7 @@ module.exports = {
],
globals: {
wp: 'off',
globalThis: 'readonly',
},
settings: {
jsdoc: {
Expand All @@ -106,9 +169,16 @@ module.exports = {
},
rules: {
'jest/expect-expect': 'off',
'react/jsx-boolean-value': 'error',
'react/jsx-curly-brace-presence': [
'error',
{ props: 'never', children: 'never' },
],
'@wordpress/dependency-group': 'error',
'@wordpress/is-gutenberg-plugin': 'error',
'@wordpress/wp-global-usage': 'error',
'@wordpress/react-no-unsafe-timeout': 'error',
'@wordpress/i18n-hyphenated-range': 'error',
'@wordpress/i18n-no-flanking-whitespace': 'error',
'@wordpress/i18n-text-domain': [
'error',
{
Expand Down Expand Up @@ -145,61 +215,11 @@ module.exports = {
disallowTypeAnnotations: false,
},
],
'no-restricted-syntax': [
'no-restricted-syntax': [ 'error', ...restrictedSyntax ],
'jsdoc/check-tag-names': [
'error',
// NOTE: We can't include the forward slash in our regex or
// we'll get a `SyntaxError` (Invalid regular expression: \ at end of pattern)
// here. That's why we use \\u002F in the regexes below.
{
selector:
'ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]',
message:
'Path access on WordPress dependencies is not allowed.',
},
{
selector:
'CallExpression[callee.name="deprecated"] Property[key.name="version"][value.value=/' +
majorMinorRegExp +
'/]',
message:
'Deprecated functions must be removed before releasing this version.',
},
{
selector:
'CallExpression[callee.object.name="page"][callee.property.name="waitFor"]',
message:
'This method is deprecated. You should use the more explicit API methods available.',
},
{
selector:
'CallExpression[callee.object.name="page"][callee.property.name="waitForTimeout"]',
message: 'Prefer page.waitForSelector instead.',
},
{
selector: 'JSXAttribute[name.name="id"][value.type="Literal"]',
message:
'Do not use string literals for IDs; use withInstanceId instead.',
},
{
// Discourage the usage of `Math.random()` as it's a code smell
// for UUID generation, for which we already have a higher-order
// component: `withInstanceId`.
selector:
'CallExpression[callee.object.name="Math"][callee.property.name="random"]',
message:
'Do not use Math.random() to generate unique IDs; use withInstanceId instead. (If you’re not generating unique IDs: ignore this message.)',
},
{
selector:
'CallExpression[callee.name="withDispatch"] > :function > BlockStatement > :not(VariableDeclaration,ReturnStatement)',
message:
'withDispatch must return an object with consistent keys. Avoid performing logic in `mapDispatchToProps`.',
},
{
selector:
'LogicalExpression[operator="&&"][left.property.name="length"][right.type="JSXElement"]',
message:
'Avoid truthy checks on length property rendering, as zero length is rendered verbatim.',
definedTags: [ 'jest-environment' ],
},
],
},
Expand Down Expand Up @@ -253,14 +273,87 @@ module.exports = {
},
{
files: [
// Components package.
'packages/components/src/**/*.[tj]s?(x)',
// Navigation block.
'packages/block-library/src/navigation/**/*.[tj]s?(x)',
'packages/*/src/**/*.[tj]s?(x)',
'storybook/stories/**/*.[tj]s?(x)',
],
excludedFiles: [ '**/*.native.js' ],
rules: {
'no-restricted-syntax': [
'error',
...restrictedSyntax,
...restrictedSyntaxComponents,
],
},
},
{
files: [ 'packages/*/src/**/*.[tj]s?(x)' ],
excludedFiles: [
'packages/*/src/**/@(test|stories)/**',
'**/*.@(native|ios|android).js',
],
excludedFiles: [ ...developmentFiles ],
rules: {
'react-hooks/exhaustive-deps': 'error',
'no-restricted-syntax': [
'error',
...restrictedSyntax,
...restrictedSyntaxComponents,
// Temporary rules until we're ready to officially deprecate the bottom margins.
...[
'BaseControl',
'CheckboxControl',
'ComboboxControl',
'DimensionControl',
'FocalPointPicker',
'RangeControl',
'SearchControl',
'SelectControl',
'TextControl',
'TextareaControl',
'ToggleControl',
'ToggleGroupControl',
'TreeSelect',
].map( ( componentName ) => ( {
selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__nextHasNoMarginBottom"]))`,
message:
componentName +
' should have the `__nextHasNoMarginBottom` prop to opt-in to the new margin-free styles.',
} ) ),
// Temporary rules until we're ready to officially default to the new size.
...[
'BorderBoxControl',
'BorderControl',
'BoxControl',
'Button',
'ComboboxControl',
'CustomSelectControl',
'DimensionControl',
'FontAppearanceControl',
'FontFamilyControl',
'FontSizePicker',
'FormTokenField',
'InputControl',
'LetterSpacingControl',
'LineHeightControl',
'NumberControl',
'RangeControl',
'SelectControl',
'TextControl',
'ToggleGroupControl',
'UnitControl',
].map( ( componentName ) => ( {
// Falsy `__next40pxDefaultSize` without a non-default `size` prop.
selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`,
message:
componentName +
' should have the `__next40pxDefaultSize` prop when using the default size.',
} ) ),
{
// Falsy `__next40pxDefaultSize` without a `render` prop.
selector:
'JSXOpeningElement[name.name="FormFileUpload"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="render"]))',
message:
'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.',
},
],
},
},
{
Expand Down Expand Up @@ -361,12 +454,59 @@ module.exports = {
'jsdoc/require-param': 'off',
},
},
{
files: [ 'packages/components/src/**' ],
excludedFiles: [
'packages/components/src/utils/colors-values.js',
'packages/components/src/theme/**',
],
rules: {
'no-restricted-syntax': [
'error',
...restrictedSyntax,
...restrictedSyntaxComponents,
{
selector:
':matches(Literal[value=/--wp-admin-theme-/],TemplateElement[value.cooked=/--wp-admin-theme-/])',
message:
'--wp-admin-theme-* variables do not support component theming. Use variables from the COLORS object in packages/components/src/utils/colors-values.js instead.',
},
{
selector:
// Allow overriding definitions, but not access with var()
':matches(Literal[value=/var\\(\\s*--wp-components-color-/],TemplateElement[value.cooked=/var\\(\\s*--wp-components-color-/])',
message:
'To ensure proper fallbacks, --wp-components-color-* variables should not be used directly. Use variables from the COLORS object in packages/components/src/utils/colors-values.js instead.',
},
],
},
},
{
files: [ 'packages/components/src/**' ],
excludedFiles: [ 'packages/components/src/**/@(test|stories)/**' ],
plugins: [ 'ssr-friendly' ],
extends: [ 'plugin:ssr-friendly/recommended' ],
},
{
files: [ 'packages/components/src/**' ],
rules: {
'no-restricted-imports': [
'error',
// The `ariakit` and `framer-motion` APIs are meant to be consumed via
// the `@wordpress/components` package, hence why importing those
// dependencies should be allowed in the components package.
{
paths: restrictedImports.filter(
( { name } ) =>
! [
'@ariakit/react',
'framer-motion',
].includes( name )
),
},
],
},
},
{
files: [ 'packages/block-editor/**' ],
rules: {
Expand All @@ -390,5 +530,29 @@ module.exports = {
],
},
},
{
files: [ 'packages/edit-post/**', 'packages/edit-site/**' ],
rules: {
'no-restricted-imports': [
'error',
{
paths: [
...restrictedImports,
{
name: '@wordpress/interface',
message:
'The edit-post and edit-site package should not directly import the interface package. They should import them from the private APIs of the editor package instead.',
},
],
},
],
},
},
{
files: [ 'packages/interactivity*/src/**' ],
rules: {
'react/react-in-jsx-scope': 'error',
},
},
],
};
9 changes: 9 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,12 @@ c56e8a1910ed74f405b74bbb12fe81dea974e5c3

# Prettier upgrade to 3.0.3.
0bee15148fe4330c20cf372cb46a33693e45cb5f

# ESLint: Enable react/jsx-boolean-value
9a34927870df80ac3b2da14d71f81d20ec23e2b6

# Autofix eslint curly rule.
0221522f253e094b277a1485b7a2d186cb172632

# ESLint: Enable react/jsx-curly-brace-presence
5d4baa9ab5f57d207cc3a048003216a8574574d9
Loading

0 comments on commit 0ad8409

Please sign in to comment.