diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 5ea361f7a9e67..5d091d1ad70c2 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,6 +1,7 @@ name: Bug Report description: Report issues with one of our products. labels: [ 'Needs triage', '[Type] Bug' ] +type: 'Bug' body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 675a89e113687..8bebf6eba1941 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -2,6 +2,7 @@ name: Enhancement Request description: Suggest a change to a feature you like! title: "Enhancement:" labels: ["[Type] Enhancement"] +type: 'Enhancement' body: - type: dropdown id: plugin-type diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 6c6dcf2a76305..8c70477eea2dd 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -2,6 +2,7 @@ name: Feature Request description: Suggest an idea for this project! title: "Feature Request:" labels: ["[Type] Feature Request"] +type: 'Enhancement' body: - type: dropdown id: plugin-type diff --git a/.github/files/e2e-tests/notification-rules.enc b/.github/files/e2e-tests/notification-rules.enc index efd553cb8b6a3..2aa0882859a42 100644 Binary files a/.github/files/e2e-tests/notification-rules.enc and b/.github/files/e2e-tests/notification-rules.enc differ diff --git a/.phan/stubs/amp-stubs.php b/.phan/stubs/amp-stubs.php index ad1cc6a107431..1d0e1033b1403 100644 --- a/.phan/stubs/amp-stubs.php +++ b/.phan/stubs/amp-stubs.php @@ -1,6 +1,6 @@ =14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/plugin-json@6.1.0': resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} @@ -6731,29 +6719,37 @@ packages: zen-observable: optional: true - '@sentry-internal/tracing@7.80.1': - resolution: {integrity: sha512-5gZ4LPIj2vpQl2/dHBM4uXMi9OI5E0VlOhJQt0foiuN6JJeiOjdpJFcfVqJk69wrc0deVENTtgKKktxqMwVeWQ==} - engines: {node: '>=8'} + '@sentry-internal/browser-utils@8.33.0': + resolution: {integrity: sha512-zwjmD+XI3pgxxiqKGLXYDGSd+zfO7az9zzbLn1le8Vv9cRL2lZyMLcwiwEaTpwz3B0pPONeDZMT8+bzMGRs8zw==} + engines: {node: '>=14.18'} - '@sentry/browser@7.80.1': - resolution: {integrity: sha512-1dPR6vPJ9vOTzgXff9HGheb178XeEv5hyjBNhCO1f6rjCgnVj99XGNZIgO1Ee1ALJbqlfPWaeV+uSWbbcmgJMA==} - engines: {node: '>=8'} + '@sentry-internal/feedback@8.33.0': + resolution: {integrity: sha512-KSW/aiNgmJc8PDl2NsM+ONvGure4tPaluj7O1Nw+947Dh8W6CJnQ9srB7xPyoYYWyQW8Hyl1vzxY9W0J+fjlhA==} + engines: {node: '>=14.18'} - '@sentry/core@7.80.1': - resolution: {integrity: sha512-3Yh+O9Q86MxwIuJFYtuSSoUCpdx99P1xDAqL0FIPTJ+ekaVMiUJq9NmyaNh9uN2myPSmxvEXW6q3z37zta9ZHg==} - engines: {node: '>=8'} + '@sentry-internal/replay-canvas@8.33.0': + resolution: {integrity: sha512-9fEhMP+gQYQrtn/SQd1Vd7U7emTSGBpLKc5h5f0iV0yDmjYAhNVbq4RgPTYAgnBEcdVo3qgboL6UIz9Dv+dYRQ==} + engines: {node: '>=14.18'} - '@sentry/replay@7.80.1': - resolution: {integrity: sha512-yjpftIyybQeWD2i0Nd7C96tZwjNbSMRW515EL9jwlNxYbQtGtMs0HavP9Y7uQvQrzwSHY0Wp+ooe9PMuvzqbHw==} - engines: {node: '>=12'} + '@sentry-internal/replay@8.33.0': + resolution: {integrity: sha512-GFBaDA4yhlEf3wTXOVXnJVG/diuKxeqZuXcuhsAwJb+YcFR0NhgsRn3wIGuYOZZF8GBXzx9PFnb9yIuFgx5Nbw==} + engines: {node: '>=14.18'} - '@sentry/types@7.80.1': - resolution: {integrity: sha512-CVu4uPVTOI3U9kYiOdA085R7jX5H1oVODbs9y+A8opJ0dtJTMueCXgZyE8oXQ0NjGVs6HEeaLkOuiV0mj8X3yw==} - engines: {node: '>=8'} + '@sentry/browser@8.33.0': + resolution: {integrity: sha512-qu/g20ZskywEU8BWc4Fts1kXFFBtw1vS+XvPq7Ta9zCeRG5dlXhhYDVQ4/v4nAL/cs0o6aLCq73m109CFF0Kig==} + engines: {node: '>=14.18'} - '@sentry/utils@7.80.1': - resolution: {integrity: sha512-bfFm2e/nEn+b9++QwjNEYCbS7EqmteT8uf0XUs7PljusSimIqqxDtK1pfD9zjynPgC8kW/fVBKv0pe2LufomeA==} - engines: {node: '>=8'} + '@sentry/core@8.33.0': + resolution: {integrity: sha512-618PQGHQLBVCpAq1s+e/rpIUaLUnj19IPUgn97rUGXLLna8ETIAoyQoG70wz4q9niw4Z4GlS5kZNrael2O3+2w==} + engines: {node: '>=14.18'} + + '@sentry/types@8.33.0': + resolution: {integrity: sha512-V/A+72ZdnfGtXeXIpz1kUo3LRdq3WKEYYFUR2RKpCdPh9yeOrHq6u/rmzTWx49+om0yhZN+JhVoxDzt75UoFRg==} + engines: {node: '>=14.18'} + + '@sentry/utils@8.33.0': + resolution: {integrity: sha512-TdwtGdevJij2wq2x/hDUr+x5TXt47ZhWxZ8zluai/lnIDTUB3Xs/L9yHtj1J+H9hr8obkMASE9IanUrWXzrP6Q==} + engines: {node: '>=14.18'} '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -7478,6 +7474,9 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/seed-random@2.2.4': + resolution: {integrity: sha512-M4wSiHb23w6oRFo69SrjWiYMXocfhRyzX5kuGkAJmLrYJDD//8zmhsY+9t6t87RLYhyIcE4h3feYwqOFdaslHw==} + '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -10479,10 +10478,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - install@0.13.0: - resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==} - engines: {node: '>= 0.10'} - internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -10955,12 +10950,8 @@ packages: node-notifier: optional: true - jetpack-boost-critical-css-gen@https://codeload.github.com/automattic/jetpack-boost-critical-css-gen/tar.gz/56adf5a550475fd30962cd4e8f8bfcaf71f84177: - resolution: {tarball: https://codeload.github.com/automattic/jetpack-boost-critical-css-gen/tar.gz/56adf5a550475fd30962cd4e8f8bfcaf71f84177} - version: 0.0.11 - - jiti@2.0.0: - resolution: {integrity: sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==} + jiti@2.1.0: + resolution: {integrity: sha512-Nftp80J8poC3u+93ZxpjstsgfQ5d0o5qyD6yStv32sgnWr74xRxBppEwsUoA/GIdrJpgGRkC1930YkLcAsFdSw==} hasBin: true joi@17.13.3: @@ -11688,85 +11679,6 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - npm@8.19.4: - resolution: {integrity: sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true - bundledDependencies: - - '@isaacs/string-locale-compare' - - '@npmcli/arborist' - - '@npmcli/ci-detect' - - '@npmcli/config' - - '@npmcli/fs' - - '@npmcli/map-workspaces' - - '@npmcli/package-json' - - '@npmcli/run-script' - - abbrev - - archy - - cacache - - chalk - - chownr - - cli-columns - - cli-table3 - - columnify - - fastest-levenshtein - - fs-minipass - - glob - - graceful-fs - - hosted-git-info - - ini - - init-package-json - - is-cidr - - json-parse-even-better-errors - - libnpmaccess - - libnpmdiff - - libnpmexec - - libnpmfund - - libnpmhook - - libnpmorg - - libnpmpack - - libnpmpublish - - libnpmsearch - - libnpmteam - - libnpmversion - - make-fetch-happen - - minimatch - - minipass - - minipass-pipeline - - mkdirp - - mkdirp-infer-owner - - ms - - node-gyp - - nopt - - npm-audit-report - - npm-install-checks - - npm-package-arg - - npm-pick-manifest - - npm-profile - - npm-registry-fetch - - npm-user-validate - - npmlog - - opener - - p-map - - pacote - - parse-conflict-json - - proc-log - - qrcode-terminal - - read - - read-package-json - - read-package-json-fast - - readdir-scoped-modules - - rimraf - - semver - - ssri - - tar - - text-table - - tiny-relative-date - - treeverse - - validate-npm-package-name - - which - - write-file-atomic - nspell@2.1.5: resolution: {integrity: sha512-PSStyugKMiD9mHmqI/CR5xXrSIGejUXPlo88FBRq5Og1kO5QwQ5Ilu8D8O5I/SHpoS+mibpw6uKA8rd3vXd2Sg==} @@ -12067,8 +11979,8 @@ packages: periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - photon@4.0.0: - resolution: {integrity: sha512-RD3buB17jW9B+OOPjIqv/cE9imCyR+WJ4ALWtb1Q1mVg8OfYnHAyvdVTxa/+bZFNI2FWaQBKry3i1mItmW3H3A==} + photon@4.1.1: + resolution: {integrity: sha512-YPsf1/tpjc8IjaOmDOLOY3fe4ajvLjsYY6Vlwn4SsoeI9U022u+U0skzB/Tk6jX6rtmNpoc6wj72de0oB267JQ==} picocolors@1.1.0: resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} @@ -12989,11 +12901,6 @@ packages: resolution: {integrity: sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==} engines: {node: '>=8.3'} - rollup-plugin-polyfill-node@0.13.0: - resolution: {integrity: sha512-FYEvpCaD5jGtyBuBFcQImEGmTxDTPbiHjJdrYIp+mFIwgXiXabxvKUK7ZT9P31ozu2Tqm9llYQMRWsfvTMTAOw==} - peerDependencies: - rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup-plugin-postcss@4.0.2: resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} engines: {node: '>=10'} @@ -13731,8 +13638,8 @@ packages: tinycolor2@1.4.2: resolution: {integrity: sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==} - tinyglobby@0.2.8: - resolution: {integrity: sha512-AMLZywN0vbhiZi2neFEaj9VIIxC+PjDMsp0nAK6tpR86LJavZgHqGz0S/FOONwBygC+mu7R0/TyAQw0gx0Mu9Q==} + tinyglobby@0.2.9: + resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} engines: {node: '>=12.0.0'} tinyqueue@2.0.3: @@ -14528,7 +14435,7 @@ snapshots: '@automattic/calypso-url@1.1.0': dependencies: - photon: 4.0.0 + photon: 4.1.1 transitivePeerDependencies: - supports-color @@ -16673,14 +16580,6 @@ snapshots: optionalDependencies: rollup: 3.29.5 - '@rollup/plugin-inject@5.0.5(rollup@3.29.5)': - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@3.29.5) - estree-walker: 2.0.2 - magic-string: 0.30.11 - optionalDependencies: - rollup: 3.29.5 - '@rollup/plugin-json@6.1.0(rollup@3.29.5)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@3.29.5) @@ -16744,37 +16643,52 @@ snapshots: transitivePeerDependencies: - zenObservable - '@sentry-internal/tracing@7.80.1': + '@sentry-internal/browser-utils@8.33.0': + dependencies: + '@sentry/core': 8.33.0 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 + + '@sentry-internal/feedback@8.33.0': + dependencies: + '@sentry/core': 8.33.0 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 + + '@sentry-internal/replay-canvas@8.33.0': dependencies: - '@sentry/core': 7.80.1 - '@sentry/types': 7.80.1 - '@sentry/utils': 7.80.1 + '@sentry-internal/replay': 8.33.0 + '@sentry/core': 8.33.0 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 - '@sentry/browser@7.80.1': + '@sentry-internal/replay@8.33.0': dependencies: - '@sentry-internal/tracing': 7.80.1 - '@sentry/core': 7.80.1 - '@sentry/replay': 7.80.1 - '@sentry/types': 7.80.1 - '@sentry/utils': 7.80.1 + '@sentry-internal/browser-utils': 8.33.0 + '@sentry/core': 8.33.0 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 - '@sentry/core@7.80.1': + '@sentry/browser@8.33.0': dependencies: - '@sentry/types': 7.80.1 - '@sentry/utils': 7.80.1 + '@sentry-internal/browser-utils': 8.33.0 + '@sentry-internal/feedback': 8.33.0 + '@sentry-internal/replay': 8.33.0 + '@sentry-internal/replay-canvas': 8.33.0 + '@sentry/core': 8.33.0 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 - '@sentry/replay@7.80.1': + '@sentry/core@8.33.0': dependencies: - '@sentry-internal/tracing': 7.80.1 - '@sentry/core': 7.80.1 - '@sentry/types': 7.80.1 - '@sentry/utils': 7.80.1 + '@sentry/types': 8.33.0 + '@sentry/utils': 8.33.0 - '@sentry/types@7.80.1': {} + '@sentry/types@8.33.0': {} - '@sentry/utils@7.80.1': + '@sentry/utils@8.33.0': dependencies: - '@sentry/types': 7.80.1 + '@sentry/types': 8.33.0 '@sideway/address@4.1.5': dependencies: @@ -17783,6 +17697,8 @@ snapshots: '@types/retry@0.12.0': {} + '@types/seed-random@2.2.4': {} + '@types/semver@7.5.8': {} '@types/send@0.17.4': @@ -22790,8 +22706,6 @@ snapshots: ini@1.3.8: {} - install@0.13.0: {} - internal-slot@1.0.7: dependencies: es-errors: 1.3.0 @@ -23523,14 +23437,7 @@ snapshots: - supports-color - ts-node - jetpack-boost-critical-css-gen@https://codeload.github.com/automattic/jetpack-boost-critical-css-gen/tar.gz/56adf5a550475fd30962cd4e8f8bfcaf71f84177: - dependencies: - clean-css: 5.3.3 - css-tree: 2.3.1 - install: 0.13.0 - npm: 8.19.4 - - jiti@2.0.0: {} + jiti@2.1.0: {} joi@17.13.3: dependencies: @@ -24461,8 +24368,6 @@ snapshots: dependencies: path-key: 4.0.0 - npm@8.19.4: {} - nspell@2.1.5: dependencies: is-buffer: 2.0.5 @@ -24809,12 +24714,13 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 - photon@4.0.0: + photon@4.1.1: dependencies: - '@babel/runtime': 7.24.7 + '@types/seed-random': 2.2.4 crc32: 0.2.2 debug: 4.3.4 seed-random: 2.2.0 + tslib: 2.5.0 transitivePeerDependencies: - supports-color @@ -25807,11 +25713,6 @@ snapshots: - bufferutil - utf-8-validate - rollup-plugin-polyfill-node@0.13.0(rollup@3.29.5): - dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@3.29.5) - rollup: 3.29.5 - rollup-plugin-postcss@4.0.2(postcss@8.4.31): dependencies: chalk: 4.1.2 @@ -26079,11 +25980,11 @@ snapshots: dependencies: bytes-iec: 3.1.1 chokidar: 4.0.1 - jiti: 2.0.0 + jiti: 2.1.0 lilconfig: 3.1.2 nanospinner: 1.1.0 picocolors: 1.1.0 - tinyglobby: 0.2.8 + tinyglobby: 0.2.9 optionalDependencies: '@size-limit/preset-app': 11.1.6(size-limit@11.1.6) @@ -26644,15 +26545,6 @@ snapshots: terser: 5.32.0 webpack: 5.94.0(webpack-cli@4.9.1) - terser-webpack-plugin@5.3.10(webpack@5.94.0): - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.32.0 - webpack: 5.94.0 - terser-webpack-plugin@5.3.3(webpack@5.94.0(webpack-cli@4.9.1)): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -26704,7 +26596,7 @@ snapshots: tinycolor2@1.4.2: {} - tinyglobby@0.2.8: + tinyglobby@0.2.9: dependencies: fdir: 6.4.0(picomatch@4.0.2) picomatch: 4.0.2 @@ -27168,14 +27060,14 @@ snapshots: webpack: 5.94.0(webpack-cli@4.9.1) webpack-merge: 5.10.0 - webpack-dev-middleware@5.3.4(webpack@5.94.0): + webpack-dev-middleware@5.3.4(webpack@5.94.0(webpack-cli@4.9.1)): dependencies: colorette: 2.0.20 memfs: 3.5.3 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.94.0 + webpack: 5.94.0(webpack-cli@4.9.1) webpack-dev-middleware@6.1.3(webpack@5.94.0(webpack-cli@4.9.1)): dependencies: @@ -27208,36 +27100,6 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webpack@5.94.0: - dependencies: - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.12.1 - acorn-import-attributes: 1.9.5(acorn@8.12.1) - browserslist: 4.23.1 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.17.1 - es-module-lexer: 1.5.4 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.94.0) - watchpack: 2.4.2 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - webpack@5.94.0(webpack-cli@4.9.1): dependencies: '@types/estree': 1.0.5 diff --git a/projects/js-packages/critical-css-gen/.gitignore b/projects/js-packages/critical-css-gen/.gitignore index 3c55ef1574d22..18c63403d3131 100644 --- a/projects/js-packages/critical-css-gen/.gitignore +++ b/projects/js-packages/critical-css-gen/.gitignore @@ -1,4 +1,4 @@ /vendor /node_modules -/build-node -/build-browser +/build +/tests/build diff --git a/projects/js-packages/critical-css-gen/changelog/add-playwright-endpoint b/projects/js-packages/critical-css-gen/changelog/add-playwright-endpoint new file mode 100644 index 0000000000000..6d610624f1ac8 --- /dev/null +++ b/projects/js-packages/critical-css-gen/changelog/add-playwright-endpoint @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Add /playwright entry point for BrowserInterfacePlaywright. diff --git a/projects/js-packages/critical-css-gen/changelog/update-default-entry-point b/projects/js-packages/critical-css-gen/changelog/update-default-entry-point new file mode 100644 index 0000000000000..e8a166bfd75be --- /dev/null +++ b/projects/js-packages/critical-css-gen/changelog/update-default-entry-point @@ -0,0 +1,4 @@ +Significance: major +Type: changed + +Change default entry point of package to include BrowserInterfaceIframe instead of BrowserInterfacePlaywright. diff --git a/projects/js-packages/critical-css-gen/package.json b/projects/js-packages/critical-css-gen/package.json index feb13394492ae..3c4b979158dc8 100644 --- a/projects/js-packages/critical-css-gen/package.json +++ b/projects/js-packages/critical-css-gen/package.json @@ -15,48 +15,46 @@ "license": "GPL-2.0-or-later", "author": "Automattic", "scripts": { - "build:browser": "rollup -c", - "build:node": "tsc", - "build": "pnpm run clean && pnpm run build:browser && pnpm run build:node", - "clean": "rm -rf build-node/ && rm -rf build-browser/", - "test": "pnpm build && NODE_ENV=test NODE_PATH=./node_modules jest --forceExit --config=tests/config/jest.config.js" + "build": "pnpm run clean && tsc", + "build:test": "pnpm run clean:test && webpack --config tests/data/webpack.config.cjs", + "clean": "rm -rf build/", + "clean:test": "rm -rf tests/build/", + "test": "pnpm build && pnpm build:test && NODE_ENV=test NODE_PATH=./node_modules jest --forceExit --config=tests/config/jest.config.js" }, - "main": "./build-node/node.js", - "browser": "./build-browser/bundle.js", + "main": "./build/browser.js", "devDependencies": { + "@automattic/jetpack-webpack-config": "workspace:*", "@babel/core": "7.24.7", "@babel/preset-env": "7.24.7", "@babel/preset-typescript": "7.24.7", - "@rollup/plugin-commonjs": "26.0.1", - "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "15.3.0", - "@rollup/plugin-terser": "0.4.3", - "@rollup/plugin-typescript": "12.1.0", "@types/clean-css": "4.2.11", "@types/css-tree": "2.3.8", "@types/node": "^20.4.2", "express": "4.20.0", "jest": "29.7.0", + "path-browserify": "1.0.1", "playwright": "1.45.1", "playwright-core": "^1.45.1", "prettier": "npm:wp-prettier@3.0.3", - "rollup": "3.29.5", - "rollup-plugin-polyfill-node": "0.13.0", + "process": "0.11.10", "source-map": "0.7.4", "source-map-js": "1.2.0", "tslib": "2.5.0", "typescript": "5.0.4", "webpack": "5.94.0", + "webpack-cli": "4.9.1", "webpack-dev-middleware": "5.3.4" }, "exports": { ".": { - "jetpack:src": "./src/node.ts", - "types": "./build-node/node.d.ts", - "browser": "./build-browser/bundle.js", - "import": "./build-node/node.js", - "require": "./build-node/node.js", - "default": "./build-node/node.js" + "jetpack:src": "./src/browser.ts", + "types": "./build/browser.d.ts", + "default": "./build/browser.js" + }, + "./playwright": { + "jetpack:src": "./src/playwright.ts", + "types": "./build/playwright.d.ts", + "default": "./build/playwright.js" } }, "dependencies": { diff --git a/projects/js-packages/critical-css-gen/rollup.config.js b/projects/js-packages/critical-css-gen/rollup.config.js deleted file mode 100644 index 25f20558cafd1..0000000000000 --- a/projects/js-packages/critical-css-gen/rollup.config.js +++ /dev/null @@ -1,47 +0,0 @@ -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import resolve from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; -import typescript from '@rollup/plugin-typescript'; -import nodePolyfills from 'rollup-plugin-polyfill-node'; - -const sharedPlugins = [ - resolve( { - browser: true, - preferBuiltins: false, - modulesOnly: false, - } ), - typescript( { - tsconfig: 'tsconfig.browser.json', - sourceMap: true, - inlineSources: false, - declaration: false, - } ), - commonjs(), - nodePolyfills(), - json(), -]; - -export default { - input: 'src/browser.ts', - output: [ - { - sourcemap: true, - format: 'iife', - name: 'CriticalCSSGenerator', - file: 'build-browser/bundle.full.js', - }, - { - sourcemap: true, - format: 'iife', - name: 'CriticalCSSGenerator', - file: 'build-browser/bundle.js', - plugins: [ terser() ], - }, - ], - plugins: sharedPlugins, - preserveSymlinks: true, - watch: { - clearScreen: false, - }, -}; diff --git a/projects/js-packages/critical-css-gen/src/node.ts b/projects/js-packages/critical-css-gen/src/playwright.ts similarity index 100% rename from projects/js-packages/critical-css-gen/src/node.ts rename to projects/js-packages/critical-css-gen/src/playwright.ts diff --git a/projects/js-packages/critical-css-gen/tests/data/webpack.config.cjs b/projects/js-packages/critical-css-gen/tests/data/webpack.config.cjs new file mode 100644 index 0000000000000..170020dd2a080 --- /dev/null +++ b/projects/js-packages/critical-css-gen/tests/data/webpack.config.cjs @@ -0,0 +1,50 @@ +const path = require( 'path' ); +const jetpackWebpackConfig = require( '@automattic/jetpack-webpack-config/webpack' ); +const webpack = require( 'webpack' ); + +module.exports = { + entry: path.join( __dirname, '../../src/browser.ts' ), + mode: 'development', + devtool: false, + output: { + ...jetpackWebpackConfig.output, + path: path.join( __dirname, '../build' ), + filename: 'bundle.js', + library: 'CriticalCSSGenerator', + }, + resolve: { + ...jetpackWebpackConfig.resolve, + // These are needed for the build to work, + // otherwise it errors out because of the clean-css dependency. + fallback: { + ...jetpackWebpackConfig.resolve.fallback, + path: require.resolve( 'path-browserify' ), + process: require.resolve( 'process/browser' ), + url: false, + https: false, + http: false, + fs: false, + os: false, + }, + }, + node: false, + plugins: [ + new webpack.ProvidePlugin( { + process: require.resolve( 'process/browser' ), + } ), + ], + module: { + strictExportPresence: true, + rules: [ + // Transpile JavaScript + jetpackWebpackConfig.TranspileRule( { + exclude: /node_modules\//, + } ), + + // Transpile @automattic/jetpack-* in node_modules too. + jetpackWebpackConfig.TranspileRule( { + includeNodeModules: [ '@automattic/jetpack-' ], + } ), + ], + }, +}; diff --git a/projects/js-packages/critical-css-gen/tests/lib/test-server.js b/projects/js-packages/critical-css-gen/tests/lib/test-server.js index 253dc69477b07..580a1d44806ac 100644 --- a/projects/js-packages/critical-css-gen/tests/lib/test-server.js +++ b/projects/js-packages/critical-css-gen/tests/lib/test-server.js @@ -23,10 +23,7 @@ class TestServer { async start() { this.app = express(); - this.app.use( - '/bundle.js', - express.static( require.resolve( '../../build-browser/bundle.full.js' ) ) - ); + this.app.use( '/bundle.js', express.static( require.resolve( '../build/bundle.js' ) ) ); for ( const [ virtualPath, realDirectory ] of Object.entries( this.staticPaths ) ) { this.app.use( '/' + virtualPath, express.static( realDirectory ) ); diff --git a/projects/js-packages/critical-css-gen/tests/unit/generate-critical-css.test.js b/projects/js-packages/critical-css-gen/tests/unit/generate-critical-css.test.js index af4dfddaa15f0..6d5ae48735af6 100644 --- a/projects/js-packages/critical-css-gen/tests/unit/generate-critical-css.test.js +++ b/projects/js-packages/critical-css-gen/tests/unit/generate-critical-css.test.js @@ -1,6 +1,6 @@ const path = require( 'path' ); const { chromium } = require( 'playwright' ); -const { generateCriticalCSS, BrowserInterfacePlaywright } = require( '../../build-node/node.js' ); +const { generateCriticalCSS, BrowserInterfacePlaywright } = require( '../../build/playwright.js' ); const { dataDirectory } = require( '../lib/data-directory.js' ); const mockFetch = require( '../lib/mock-fetch.js' ); const TestServer = require( '../lib/test-server.js' ); diff --git a/projects/js-packages/critical-css-gen/tsconfig.browser.json b/projects/js-packages/critical-css-gen/tsconfig.browser.json deleted file mode 100644 index c9e55e8858add..0000000000000 --- a/projects/js-packages/critical-css-gen/tsconfig.browser.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": [ "src/browser.ts" ], - "compilerOptions": { - "outDir": "./build-browser" - } -} diff --git a/projects/js-packages/critical-css-gen/tsconfig.json b/projects/js-packages/critical-css-gen/tsconfig.json index 42e5c2a17fbde..5acf505050177 100644 --- a/projects/js-packages/critical-css-gen/tsconfig.json +++ b/projects/js-packages/critical-css-gen/tsconfig.json @@ -1,9 +1,9 @@ { "extends": "jetpack-js-tools/tsconfig.tsc.json", - "include": [ "src/node.ts" ], + "include": [ "src/browser.ts", "src/playwright.ts" ], "exclude": [ "node_modules/**/*" ], "compilerOptions": { - "outDir": "./build-node", + "outDir": "./build", "target": "es2019", "sourceMap": true, "allowJs": false, diff --git a/projects/js-packages/publicize-components/changelog/fix-social-share-status-tooltip-text-overflow b/projects/js-packages/publicize-components/changelog/fix-social-share-status-tooltip-text-overflow new file mode 100644 index 0000000000000..9a6eda0cf22bb --- /dev/null +++ b/projects/js-packages/publicize-components/changelog/fix-social-share-status-tooltip-text-overflow @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Social: Fixed share status tooltip text overflow diff --git a/projects/js-packages/publicize-components/src/components/share-status/share-status-label.tsx b/projects/js-packages/publicize-components/src/components/share-status/share-status-label.tsx index 86cab5ffc97e0..bf2384e4dc0fe 100644 --- a/projects/js-packages/publicize-components/src/components/share-status/share-status-label.tsx +++ b/projects/js-packages/publicize-components/src/components/share-status/share-status-label.tsx @@ -26,7 +26,9 @@ export function ShareStatusLabel( { status, message } ) { title={ __( 'Sharing failed with the following message:', 'jetpack' ) } className={ styles[ 'share-status-icon-tooltip' ] } > - { message } + + { message } + ); diff --git a/projects/js-packages/publicize-components/src/components/share-status/styles.module.scss b/projects/js-packages/publicize-components/src/components/share-status/styles.module.scss index 0cd241f349d0d..37ae6871549f4 100644 --- a/projects/js-packages/publicize-components/src/components/share-status/styles.module.scss +++ b/projects/js-packages/publicize-components/src/components/share-status/styles.module.scss @@ -56,6 +56,10 @@ } } +.tooltip-text { + word-break: break-word; +} + .share-status-icon { fill: var(--jp-green-50); } diff --git a/projects/packages/image-cdn/changelog/add-photon-url-check-method b/projects/packages/image-cdn/changelog/add-photon-url-check-method new file mode 100644 index 0000000000000..5242de078c618 --- /dev/null +++ b/projects/packages/image-cdn/changelog/add-photon-url-check-method @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Added a public method to check if a URL is CDN url diff --git a/projects/packages/image-cdn/src/class-image-cdn-core.php b/projects/packages/image-cdn/src/class-image-cdn-core.php index d577eeb68dfe2..377a92682976c 100644 --- a/projects/packages/image-cdn/src/class-image-cdn-core.php +++ b/projects/packages/image-cdn/src/class-image-cdn-core.php @@ -156,17 +156,12 @@ public static function cdn_url( $image_url, $args = array(), $scheme = null ) { } } - /** This filter is documented below. */ - $custom_photon_url = apply_filters( 'jetpack_photon_domain', '', $image_url ); - $custom_photon_url = esc_url( $custom_photon_url ); - // You can't run a Photon URL through Photon again because query strings are stripped. // So if the image is already a Photon URL, append the new arguments to the existing URL. // Alternately, if it's a *.files.wordpress.com url or an image on a private WordPress.com Simple site, // then keep the domain as is. if ( - in_array( $image_url_parts['host'], array( 'i0.wp.com', 'i1.wp.com', 'i2.wp.com' ), true ) - || wp_parse_url( $custom_photon_url, PHP_URL_HOST ) === $image_url_parts['host'] + self::is_cdn_url( $image_url ) || $is_wpcom_image || $is_wpcom_private_site ) { @@ -245,6 +240,28 @@ public static function cdn_url( $image_url, $args = array(), $scheme = null ) { return self::cdn_url_scheme( $photon_url, $scheme ); } + /** + * Checks if a given URL is a Photon URL. + * + * @since $$next-version$$ + * @param string $url The URL to check. + * @return bool True if the URL is a Photon URL, false otherwise. + */ + public static function is_cdn_url( $url ) { + $parsed_url = wp_parse_url( $url ); + + if ( ! $parsed_url ) { + return false; + } + + // See usage in ::cdn_url for documentation of this filter + $custom_photon_url = apply_filters( 'jetpack_photon_domain', '', $url ); + $custom_photon_url = esc_url( $custom_photon_url ); + + return in_array( $parsed_url['host'], array( 'i0.wp.com', 'i1.wp.com', 'i2.wp.com' ), true ) + || wp_parse_url( $custom_photon_url, PHP_URL_HOST ) === $parsed_url['host']; + } + /** * Parses WP.com-hosted image args to replicate the crop. * diff --git a/projects/packages/image-cdn/tests/php/test_class.image_cdn_core.php b/projects/packages/image-cdn/tests/php/test_class.image_cdn_core.php index 204075146cd8c..66490b1d9854f 100644 --- a/projects/packages/image-cdn/tests/php/test_class.image_cdn_core.php +++ b/projects/packages/image-cdn/tests/php/test_class.image_cdn_core.php @@ -265,6 +265,24 @@ public function test_photon_url_filter_network_path_photonized_to_https() { $this->assertEquals( 'https://photon.test/example.com/img.jpg', $url ); } + /** + * @covers ::Image_CDN_Core::is_cdn_url + * @since $$next-version$$ + * @group jetpack_photon_filter_network_path + */ + public function test_is_cdn_url_method() { + $this->apply_custom_domain( '//photon.test' ); + $this->assertTrue( Image_CDN_Core::is_cdn_url( '//photon.test/example.com/img.jpg' ) ); + + $this->assertTrue( Image_CDN_Core::is_cdn_url( 'https://i0.wp.com/example.com/img.jpg' ) ); + $this->assertTrue( Image_CDN_Core::is_cdn_url( 'http://i1.wp.com/example.com/img.jpg' ) ); + $this->assertTrue( Image_CDN_Core::is_cdn_url( '//i2.wp.com/example.com/img.jpg' ) ); + $this->assertFalse( Image_CDN_Core::is_cdn_url( '//i3.wp.com/example.com/img.jpg' ) ); + $this->assertFalse( Image_CDN_Core::is_cdn_url( 'http://example.com/img.jpg' ) ); + $this->assertFalse( Image_CDN_Core::is_cdn_url( 'https://example.com/img.jpg' ) ); + $this->assertFalse( Image_CDN_Core::is_cdn_url( '//example.com/img.jpg' ) ); + } + /** * @author aduth * @covers ::Image_CDN_Core::cdn_url_scheme diff --git a/projects/packages/jetpack-mu-wpcom/changelog/add-review-site-task b/projects/packages/jetpack-mu-wpcom/changelog/add-review-site-task new file mode 100644 index 0000000000000..bbf00ab57fc59 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/add-review-site-task @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add the Review site task diff --git a/projects/packages/jetpack-mu-wpcom/changelog/edit-profile-link b/projects/packages/jetpack-mu-wpcom/changelog/edit-profile-link new file mode 100644 index 0000000000000..8de81cd40f31f --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/edit-profile-link @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Admin bar: replace 'Edit Profile' and 'My Account' with 'My Profile' diff --git a/projects/packages/jetpack-mu-wpcom/changelog/profile-link-improvements b/projects/packages/jetpack-mu-wpcom/changelog/profile-link-improvements new file mode 100644 index 0000000000000..8b2f6f13f30ef --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/profile-link-improvements @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +profile.php: Make wpcom links more concise diff --git a/projects/packages/jetpack-mu-wpcom/changelog/renovate-npm-sentry-browser-vulnerability b/projects/packages/jetpack-mu-wpcom/changelog/renovate-npm-sentry-browser-vulnerability new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/renovate-npm-sentry-browser-vulnerability @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/packages/jetpack-mu-wpcom/package.json b/projects/packages/jetpack-mu-wpcom/package.json index 6ff8c9e6286c6..25fc971b66496 100644 --- a/projects/packages/jetpack-mu-wpcom/package.json +++ b/projects/packages/jetpack-mu-wpcom/package.json @@ -56,7 +56,7 @@ "@automattic/typography": "1.0.0", "@popperjs/core": "^2.11.8", "@preact/signals": "^1.2.2", - "@sentry/browser": "7.80.1", + "@sentry/browser": "8.33.0", "@tanstack/react-query": "^5.15.5", "@wordpress/api-fetch": "7.8.2", "@wordpress/base-styles": "5.8.1", diff --git a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php index e2f1216493f01..6e6f181dfd897 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php @@ -809,6 +809,13 @@ function wpcom_launchpad_get_task_definitions() { 'is_complete_callback' => 'wpcom_launchpad_is_task_option_completed', 'is_visible_callback' => '__return_true', ), + 'review_site' => array( + 'get_title' => function () { + return __( "Review the site's content", 'jetpack-mu-wpcom' ); + }, + 'is_complete_callback' => 'wpcom_launchpad_is_task_option_completed', + 'is_visible_callback' => '__return_true', + ), ); $extended_task_definitions = apply_filters( 'wpcom_launchpad_extended_task_definitions', array() ); diff --git a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad.php b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad.php index 4ff9f06c7b1d1..e313808a59b9f 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad.php @@ -321,6 +321,7 @@ function wpcom_launchpad_get_task_list_definitions() { }, 'task_ids' => array( 'migrating_site', + 'review_site', ), ), ); diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-admin-bar/wpcom-admin-bar.php b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-admin-bar/wpcom-admin-bar.php index 7109d817c4c3f..6bd50652ab522 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-admin-bar/wpcom-admin-bar.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-admin-bar/wpcom-admin-bar.php @@ -236,52 +236,25 @@ function wpcom_add_reader_menu( $wp_admin_bar ) { add_action( 'admin_bar_menu', 'wpcom_add_reader_menu', 11 ); /** - * Points the "Edit Profile" and "Howdy,..." to /me when appropriate. + * Points the "Edit Profile" and "Howdy,..." to /me. * * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar core object. */ -function wpcom_maybe_replace_edit_profile_menu_to_me( $wp_admin_bar ) { +function wpcom_replace_edit_profile_menu_to_me( $wp_admin_bar ) { $edit_profile_node = $wp_admin_bar->get_node( 'user-info' ); if ( $edit_profile_node ) { - /** - * The Edit Profile menu should point to /me, instead of the site's profile.php - * if the user is not a member of the current site - */ - if ( ! is_user_member_of_blog() ) { - $edit_profile_node->href = maybe_add_origin_site_id_to_url( 'https://wordpress.com/me' ); - $wp_admin_bar->add_node( (array) $edit_profile_node ); - } - } -} -// Run this function later than Core: https://github.com/WordPress/wordpress-develop/blob/5a30482419f1b0bcc713a7fdee3a14afd67a1bca/src/wp-includes/class-wp-admin-bar.php#L651 -add_action( 'admin_bar_menu', 'wpcom_maybe_replace_edit_profile_menu_to_me', 9999 ); - -/** - * Adds (Profile) -> My Account menu pointing to /me. - * - * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar core object. - */ -function wpcom_add_my_account_item_to_profile_menu( $wp_admin_bar ) { - $logout_node = $wp_admin_bar->get_node( 'logout' ); - if ( $logout_node ) { - // Adds the 'My Account' menu item before 'Log Out'. - $wp_admin_bar->remove_node( 'logout' ); + $edit_profile_node->href = maybe_add_origin_site_id_to_url( 'https://wordpress.com/me' ); + $edit_profile_node->title = preg_replace( "/()(.*?)(<\/span>)/", '$1' . __( 'My Profile', 'jetpack-mu-wpcom' ) . '$3', $edit_profile_node->title ); + $wp_admin_bar->add_node( (array) $edit_profile_node ); } - - $wp_admin_bar->add_node( - array( - 'id' => 'wpcom-profile', - 'parent' => 'user-actions', - 'title' => __( 'My Account', 'jetpack-mu-wpcom' ), - 'href' => maybe_add_origin_site_id_to_url( 'https://wordpress.com/me' ), - ) - ); - - if ( $logout_node ) { - $wp_admin_bar->add_node( (array) $logout_node ); + $my_account_node = $wp_admin_bar->get_node( 'my-account' ); + if ( $my_account_node ) { + $my_account_node->href = maybe_add_origin_site_id_to_url( 'https://wordpress.com/me' ); + $wp_admin_bar->add_node( (array) $my_account_node ); } } -add_action( 'admin_bar_menu', 'wpcom_add_my_account_item_to_profile_menu' ); +// Run this function later than Core: https://github.com/WordPress/wordpress-develop/blob/5a30482419f1b0bcc713a7fdee3a14afd67a1bca/src/wp-includes/class-wp-admin-bar.php#L651 +add_action( 'admin_bar_menu', 'wpcom_replace_edit_profile_menu_to_me', 9999 ); /** * Replaces the default admin bar class with our own. diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php index 32c1b96dcfdba..81acaabe0df9f 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php @@ -41,19 +41,27 @@ function wpcom_profile_settings_add_links_to_wpcom() { array( 'language' => array( 'link' => esc_url( 'https://wordpress.com/me/account' ), - 'text' => __( 'Your admin interface language is managed on WordPress.com Account settings', 'jetpack-mu-wpcom' ), + 'text' => __( 'Manage your WordPress.com account language ↗', 'jetpack-mu-wpcom' ), ), - 'synced' => array( + 'name' => array( 'link' => esc_url( 'https://wordpress.com/me' ), - 'text' => __( 'You can manage your profile on WordPress.com Profile settings (First / Last / Display Names, Website, and Biographical Info)', 'jetpack-mu-wpcom' ), + 'text' => __( 'Manage your WordPress.com profile ↗', 'jetpack-mu-wpcom' ), + ), + 'website' => array( + 'link' => esc_url( 'https://wordpress.com/me' ), + 'text' => __( 'Manage your WordPress.com profile website ↗', 'jetpack-mu-wpcom' ), + ), + 'bio' => array( + 'link' => esc_url( 'https://wordpress.com/me' ), + 'text' => __( 'Manage your WordPress.com profile bio ↗', 'jetpack-mu-wpcom' ), ), 'email' => array( 'link' => esc_url( 'https://wordpress.com/me/account' ), - 'text' => __( 'Your WordPress.com email is managed on WordPress.com Account settings', 'jetpack-mu-wpcom' ), + 'text' => __( 'Manage your WordPress.com account email ↗', 'jetpack-mu-wpcom' ), ), 'password' => array( 'link' => esc_url( 'https://wordpress.com/me/security' ), - 'text' => __( 'Your WordPress.com password is managed on WordPress.com Security settings', 'jetpack-mu-wpcom' ), + 'text' => __( 'Manage your WordPress.com password ↗', 'jetpack-mu-wpcom' ), ), 'isWpcomAtomicClassic' => $is_wpcom_atomic_classic, ) diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.ts b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.ts index 621c213633e06..cd09ea23fa1b0 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.ts +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-profile-settings/profile-settings-link-to-wpcom.ts @@ -1,95 +1,140 @@ -/** - * Disable the email field except on Atomic Classic sites. - */ -const wpcom_profile_settings_disable_email_field = () => { - if ( window.wpcomProfileSettingsLinkToWpcom?.isWpcomAtomicClassic ) { - return; +const wpcom_profile_settings_modify_language_section = () => { + const section = document.querySelector( '.user-language-wrap' )?.querySelector( 'td' ); + const select = document.getElementById( 'locale' ); + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.language?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.language?.text; + if ( settingsLink && settingsLinkText ) { + const notice = document.createElement( 'p' ); + notice.className = 'description'; + notice.innerHTML = `${ settingsLinkText }`; + section?.appendChild( notice ); + select?.remove(); } - const emailField = document.getElementById( 'email' ) as HTMLInputElement; - if ( emailField ) { - emailField.readOnly = true; +}; + +const wpcom_profile_settings_modify_name_section = () => { + const table = document.querySelector( '.user-user-login-wrap' )?.parentElement; + + const tr = document.createElement( 'tr' ); + const th = document.createElement( 'th' ); + const td = document.createElement( 'td' ); + + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.name?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.name?.text; + if ( table && settingsLink && settingsLinkText ) { + const h2 = document.createElement( 'h2' ); + h2.innerHTML = 'Name'; + h2.style = 'font-size: 1.2em'; + th.appendChild( h2 ); + + const notice = document.createElement( 'p' ); + notice.className = 'description'; + notice.innerHTML = `${ settingsLinkText }`; + td.appendChild( notice ); + + tr.appendChild( th ); + tr.appendChild( td ); + table?.appendChild( tr ); + table?.parentElement?.previousElementSibling?.remove(); } - const emailDescription = document.getElementById( 'email-description' ) as HTMLInputElement; - emailDescription?.remove(); + [ + '.user-user-login-wrap', + '.user-first-name-wrap', + '.user-last-name-wrap', + '.user-nickname-wrap', + '.user-display-name-wrap', + ].forEach( selector => { + const field = document.querySelector( selector ); + if ( field ) { + field.classList.add( 'hidden' ); + } + } ); }; -/** - * Add a link to the WordPress.com profile settings page. - */ -const wpcom_profile_settings_add_links_to_wpcom = () => { - const userSessionSection = document.querySelector( '.user-sessions-wrap' ); - userSessionSection?.remove(); +const wpcom_profile_settings_modify_email_section = () => { + // Hide the email field except on Atomic Classic sites. + if ( ! window.wpcomProfileSettingsLinkToWpcom?.isWpcomAtomicClassic ) { + const field = document.getElementById( 'email' ) as HTMLInputElement; + if ( field ) { + field.classList.add( 'hidden' ); + } - // We cannot set a password in wp-admin except on Atomic Classic sites. - const newPasswordSection = document.getElementById( 'password' )?.querySelector( 'td' ); - if ( ! window.wpcomProfileSettingsLinkToWpcom?.isWpcomAtomicClassic && newPasswordSection ) { - newPasswordSection.innerHTML = ''; + const description = document.getElementById( 'email-description' ) as HTMLInputElement; + description?.remove(); } - const languageSection = document.querySelector( '.user-language-wrap' )?.querySelector( 'td' ); - const languageSelect = document.getElementById( 'locale' ); - const languageSettingsLink = window.wpcomProfileSettingsLinkToWpcom?.language?.link; - const languageSettingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.language?.text; - if ( languageSettingsLink && languageSettingsLinkText ) { + const section = document.querySelector( '.user-email-wrap' )?.querySelector( 'td' ); + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.email?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.email?.text; + if ( section && settingsLink && settingsLinkText ) { const notice = document.createElement( 'p' ); notice.className = 'description'; - notice.innerHTML = `${ languageSettingsLinkText }.`; - languageSection?.appendChild( notice ); - languageSelect?.remove(); + notice.innerHTML = `${ settingsLinkText }`; + section.appendChild( notice ); } +}; - const emailSection = document.querySelector( '.user-email-wrap' )?.querySelector( 'td' ); - const emailSettingsLink = window.wpcomProfileSettingsLinkToWpcom?.email?.link; - const emailSettingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.email?.text; - if ( emailSection && emailSettingsLink && emailSettingsLinkText ) { +const wpcom_profile_settings_modify_website_section = () => { + const section = document.querySelector( '.user-url-wrap' )?.querySelector( 'td' ); + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.website?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.website?.text; + if ( section && settingsLink && settingsLinkText ) { const notice = document.createElement( 'p' ); notice.className = 'description'; - notice.innerHTML = `${ emailSettingsLinkText }.`; - emailSection.appendChild( notice ); + notice.innerHTML = `${ settingsLinkText }`; + section.appendChild( notice ); } - const passwordSettingsLink = window.wpcomProfileSettingsLinkToWpcom?.password?.link; - const passwordSettingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.password?.text; - if ( newPasswordSection && passwordSettingsLink && passwordSettingsLinkText ) { - const notice = document.createElement( 'p' ); - notice.className = 'description'; - notice.innerHTML = `${ passwordSettingsLinkText }.`; - newPasswordSection.appendChild( notice ); + const field = section?.querySelector( 'input' ); + if ( field ) { + field.classList.add( 'hidden' ); } +}; - const usernameSection = document.querySelector( '.user-user-login-wrap' )?.querySelector( 'td' ); - const syncedSettingsLink = window.wpcomProfileSettingsLinkToWpcom?.synced?.link; - const syncedSettingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.synced?.text; - if ( usernameSection && syncedSettingsLink && syncedSettingsLinkText ) { +const wpcom_profile_settings_modify_bio_section = () => { + const section = document.querySelector( '.user-description-wrap' )?.querySelector( 'td' ); + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.bio?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.bio?.text; + if ( section && settingsLink && settingsLinkText ) { const notice = document.createElement( 'p' ); notice.className = 'description'; - notice.innerHTML = `${ syncedSettingsLinkText }.`; - usernameSection.appendChild( notice ); + notice.innerHTML = `${ settingsLinkText }`; + section.appendChild( notice ); } + + const field = section?.querySelector( 'textarea' ); + if ( field ) { + field.classList.add( 'hidden' ); + } + section?.querySelector( 'p' )?.remove(); }; -/** - * Hide the fields that are synced from /me. - */ -const wpcom_profile_settings_hide_synced_fields = () => { - [ - '.user-first-name-wrap', - '.user-last-name-wrap', - '.user-nickname-wrap', - '.user-display-name-wrap', - '.user-url-wrap', - '.user-description-wrap', - ].forEach( selector => { - const field = document.querySelector( selector ); - if ( field ) { - field.classList.add( 'hidden' ); - } - } ); +const wpcom_profile_settings_modify_password_section = () => { + const userSessionSection = document.querySelector( '.user-sessions-wrap' ); + userSessionSection?.remove(); + + // We cannot set a password in wp-admin except on Atomic Classic sites. + const newPasswordSection = document.getElementById( 'password' )?.querySelector( 'td' ); + if ( ! window.wpcomProfileSettingsLinkToWpcom?.isWpcomAtomicClassic && newPasswordSection ) { + newPasswordSection.innerHTML = ''; + } + + const settingsLink = window.wpcomProfileSettingsLinkToWpcom?.password?.link; + const settingsLinkText = window.wpcomProfileSettingsLinkToWpcom?.password?.text; + if ( newPasswordSection && settingsLink && settingsLinkText ) { + const notice = document.createElement( 'p' ); + notice.className = 'description'; + notice.innerHTML = `${ settingsLinkText }`; + newPasswordSection.appendChild( notice ); + } }; document.addEventListener( 'DOMContentLoaded', () => { - wpcom_profile_settings_add_links_to_wpcom(); - wpcom_profile_settings_disable_email_field(); - wpcom_profile_settings_hide_synced_fields(); + wpcom_profile_settings_modify_language_section(); + wpcom_profile_settings_modify_name_section(); + wpcom_profile_settings_modify_email_section(); + wpcom_profile_settings_modify_website_section(); + wpcom_profile_settings_modify_bio_section(); + wpcom_profile_settings_modify_password_section(); } ); diff --git a/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements b/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements new file mode 100644 index 0000000000000..cd89bbb31e2bb --- /dev/null +++ b/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements @@ -0,0 +1,5 @@ +Significance: patch +Type: fixed +Comment: Disable controls that require user connection. + + diff --git a/projects/packages/search/changelog/renovate-photon-4.x b/projects/packages/search/changelog/renovate-photon-4.x new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/packages/search/changelog/renovate-photon-4.x @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/packages/search/package.json b/projects/packages/search/package.json index 8ce5c382cc53e..5e3deb0485c7f 100644 --- a/projects/packages/search/package.json +++ b/projects/packages/search/package.json @@ -49,7 +49,7 @@ "clsx": "2.1.1", "fast-json-stable-stringify": "2.1.0", "lodash": "4.17.21", - "photon": "4.0.0", + "photon": "4.1.1", "preact": "10.22.1", "prop-types": "15.7.2", "q-flat": "1.0.7", diff --git a/projects/packages/videopress/changelog/update-jetpack-blocks-confusing-connection-nudges b/projects/packages/videopress/changelog/update-jetpack-blocks-confusing-connection-nudges new file mode 100644 index 0000000000000..0a41d686ca108 --- /dev/null +++ b/projects/packages/videopress/changelog/update-jetpack-blocks-confusing-connection-nudges @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Update connection nudge for VideoPress connection banner in blocks diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/connect-banner.tsx b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/connect-banner.tsx index a4ec01bab7afd..3e3422c1c563e 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/connect-banner.tsx +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/connect-banner.tsx @@ -31,15 +31,22 @@ export default function ConnectBanner( { isConnected, isConnecting, }: ConnectBannerProps ): React.ReactElement { - if ( isConnected ) { + if ( isConnected && isModuleActive ) { return null; } - let connectButtonText = __( 'Connect', 'jetpack-videopress-pkg' ); + const needsActivation = isConnected && ! isModuleActive; + + let connectButtonText = __( 'Connect Jetpack', 'jetpack-videopress-pkg' ); if ( isConnecting ) { connectButtonText = __( 'Redirecting…', 'jetpack-videopress-pkg' ); } + let activateButtonText = __( 'Activate VideoPress', 'jetpack-videopress-pkg' ); + if ( isConnecting ) { + activateButtonText = __( 'Activating…', 'jetpack-videopress-pkg' ); + } + const connectYourAccountMessage = __( 'Connect your account to continue using VideoPress', 'jetpack-videopress-pkg' @@ -58,11 +65,12 @@ export default function ConnectBanner( { disabled={ isConnecting } isBusy={ isConnecting } > - { connectButtonText } + { needsActivation ? activateButtonText : connectButtonText } } + icon={ '' } > - { isModuleActive ? connectYourAccountMessage : connectJetpackModuleMessage } + { needsActivation ? connectJetpackModuleMessage : connectYourAccountMessage } ); } diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/index.tsx b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/index.tsx index e6501db60bd1b..1676198043f76 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/index.tsx +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/index.tsx @@ -34,7 +34,7 @@ export default function BlockBanner( { }: BlockBannerProps ): React.ReactElement { return (
- + { icon && }
{ children }
{ isLoading && } { action &&
{ action }
} diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/style.scss b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/style.scss index 3cf78ee0e8ce9..8964f84b82a95 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/style.scss +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/style.scss @@ -1,15 +1,39 @@ .block-banner { display: flex; - height: 48px; + justify-content: space-between; font-size: 14px; align-self: center; align-items: center; - background: #F6F7F7; - padding: 0 16px; + background: black; + border-radius: 2px; + padding: 0 20px; + box-shadow: 0 0 1px inset white; .block-banner__content { - color: #01283d; - flex-grow: 2; - margin: 0 8px; + color: white; + margin: 10px 10px 10px 0; + } + + .block-banner__action { + padding: 0; + + .components-button.is-primary { + background: white; + color: black; + font-weight: 600; + font-size: 14px; + padding: 4px 8px; + height: 28px; + margin: 8px 0 8px auto; + + &:hover:not(:disabled) { + background: #F6F7F7; + } + } + + .components-button.is-primary.is-busy { + background-size: 100px 100%; + background-image: linear-gradient(-45deg, #e34c84 28%, #ab235a 28%, #ab235a 72%, #e34c84 72%); + } } } diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/components/videopress-uploader/index.js b/projects/packages/videopress/src/client/block-editor/blocks/video/components/videopress-uploader/index.js index e7c2b99039535..660e7833e7721 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/components/videopress-uploader/index.js +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/components/videopress-uploader/index.js @@ -10,6 +10,7 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ +import { usePermission } from '../../../../../admin/hooks/use-permission'; import useResumableUploader from '../../../../../hooks/use-resumable-uploader'; import { uploadFromLibrary } from '../../../../../hooks/use-uploader'; import { buildVideoPressURL, pickVideoBlockAttributesFromUrl } from '../../../../../lib/url'; @@ -29,12 +30,15 @@ const VideoPressUploader = ( { fileToUpload, isReplacing, onReplaceCancel, + isActive, } ) => { const [ uploadPaused, setUploadPaused ] = useState( false ); const [ uploadedVideoData, setUploadedVideoData ] = useState( false ); const [ isUploadingInProgress, setIsUploadingInProgress ] = useState( false ); const [ isVerifyingLocalMedia, setIsVerifyingLocalMedia ] = useState( false ); + const { hasConnectedOwner } = usePermission(); + /* * When the file to upload is set, start the upload process * just after the component is mounted. @@ -314,6 +318,24 @@ const VideoPressUploader = ( { ); } + if ( ! isActive ) { + const needsConnectionText = __( + 'Connect your WordPress.com account to enable high-quality, ad-free video.', + 'jetpack-videopress-pkg' + ); + + const needsActivationText = __( + 'Activate the VideoPress module to enable high-quality, ad-free video.', + 'jetpack-videopress-pkg' + ); + + return ( + + { ! hasConnectedOwner ? needsConnectionText : needsActivationText } + + ); + } + // Default view to select file to upload return ( { if ( ! errorMessage ) { @@ -87,6 +89,7 @@ export const PlaceholderWrapper = withNotices( function ( { label={ title } instructions={ disableInstructions ? null : instructions } notices={ noticeUI } + className={ className } > { children } @@ -148,6 +151,7 @@ export default function VideoPressEdit( { // Get the redirect URI for the connection flow. const [ isRedirectingToMyJetpack, setIsRedirectingToMyJetpack ] = useState( false ); + const { hasConnectedOwner } = usePermission(); // Detect if the chapter file is auto-generated. const chapter = tracks?.filter( track => track.kind === 'chapters' )?.[ 0 ]; @@ -395,15 +399,15 @@ export default function VideoPressEdit( {
<> { setIsRedirectingToMyJetpack( true ); - if ( ! isStandalonePluginActive ) { - return ( window.location.href = jetpackVideoPressSettingUrl ); + if ( ! hasConnectedOwner ) { + return ( window.location.href = myJetpackConnectUrl ); } - window.location.href = myJetpackConnectUrl; + window.location.href = jetpackVideoPressSettingUrl; } } /> @@ -414,6 +418,7 @@ export default function VideoPressEdit( { fileToUpload={ fileToUpload } isReplacing={ isReplacingFile?.isReplacing } onReplaceCancel={ cancelReplacingVideoFile } + isActive={ isActive } />
@@ -592,15 +597,15 @@ export default function VideoPressEdit( { { setIsRedirectingToMyJetpack( true ); - if ( ! isStandalonePluginActive ) { - return ( window.location.href = jetpackVideoPressSettingUrl ); + if ( ! hasConnectedOwner ) { + return ( window.location.href = myJetpackConnectUrl ); } - window.location.href = myJetpackConnectUrl; + window.location.href = jetpackVideoPressSettingUrl; } } /> diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/editor.scss b/projects/packages/videopress/src/client/block-editor/blocks/video/editor.scss index 6dfbaa03c6fb1..a75c2c96c1592 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/editor.scss +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/editor.scss @@ -52,6 +52,10 @@ } } +.components-placeholder.disabled { + min-height: 0; +} + .loading-wrapper { display: flex; width: 100%; diff --git a/projects/packages/waf/changelog/add-waf-body-processor b/projects/packages/waf/changelog/add-waf-body-processor new file mode 100644 index 0000000000000..df675355a4f53 --- /dev/null +++ b/projects/packages/waf/changelog/add-waf-body-processor @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Firewall Runtime: Added support for rule files to specify body parser type. diff --git a/projects/packages/waf/src/class-waf-request.php b/projects/packages/waf/src/class-waf-request.php index 5017a2e25f46c..bbb8bcf3e17f9 100644 --- a/projects/packages/waf/src/class-waf-request.php +++ b/projects/packages/waf/src/class-waf-request.php @@ -328,28 +328,59 @@ public function get_get_vars() { return flatten_array( $_GET ); } + /** + * Returns the POST variables from a JSON body + * + * @return array{string, scalar}[] + */ + private function get_json_post_vars() { + $decoded_json = json_decode( $this->get_body(), true ) ?? array(); + return flatten_array( $decoded_json, 'json', true ); + } + + /** + * Returns the POST variables from a urlencoded body + * + * @return array{string, scalar}[] + */ + private function get_urlencoded_post_vars() { + parse_str( $this->get_body(), $params ); + return flatten_array( $params ); + } + /** * Returns the POST variables * + * @param string $body_processor Manually specifiy the method to use to process the body. Options are 'URLENCODED' and 'JSON'. + * * @return array{string, scalar}[] */ - public function get_post_vars() { + public function get_post_vars( string $body_processor = '' ) { $content_type = $this->get_header( 'content-type' ); + + // If the body processor is specified by the rules file, trust it. + if ( 'URLENCODED' === $body_processor ) { + return $this->get_urlencoded_post_vars(); + } + if ( 'JSON' === $body_processor ) { + return $this->get_json_post_vars(); + } + + // Otherwise, use $_POST if it's not empty. if ( ! empty( $_POST ) ) { - // If $_POST is populated, use it. return flatten_array( $_POST ); - } elseif ( strpos( $content_type, 'application/json' ) !== false ) { - // Attempt to decode JSON requests. - $decoded_json = json_decode( $this->get_body(), true ) ?? array(); - return flatten_array( $decoded_json, 'json', true ); - } elseif ( strpos( $content_type, 'application/x-www-form-urlencoded' ) !== false ) { - // Attempt to decode url-encoded data - parse_str( $this->get_body(), $params ); - return flatten_array( $params ); - } else { - // Don't try to parse any other content types - return array(); } + + // Lastly, try to parse the body based on the content type. + if ( strpos( $content_type, 'application/json' ) !== false ) { + return $this->get_json_post_vars(); + } + if ( strpos( $content_type, 'application/x-www-form-urlencoded' ) !== false ) { + return $this->get_urlencoded_post_vars(); + } + + // Don't try to parse any other content types. + return array(); } /** diff --git a/projects/packages/waf/src/class-waf-runtime.php b/projects/packages/waf/src/class-waf-runtime.php index 394d46aa5a6f1..19300ea804582 100644 --- a/projects/packages/waf/src/class-waf-runtime.php +++ b/projects/packages/waf/src/class-waf-runtime.php @@ -38,6 +38,14 @@ class Waf_Runtime { */ const NORMALIZE_ARRAY_MATCH_VALUES = 2; + /** + * The version of this runtime class. Used by rule files to ensure compatibility. + * + * @since $$next-version$$ + * + * @var int + */ + public $version = 1; /** * Last rule. * @@ -68,6 +76,12 @@ class Waf_Runtime { * @var string */ public $matched_var_name = ''; + /** + * Body Processor. + * + * @var string 'URLENCODED' | 'JSON' | '' + */ + private $body_processor = ''; /** * State. @@ -438,7 +452,7 @@ public function meta( $key ) { $value = $this->args_names( $this->meta( 'args_get' ) ); break; case 'args_post': - $value = $this->request->get_post_vars(); + $value = $this->request->get_post_vars( $this->get_body_processor() ); break; case 'args_post_names': $value = $this->args_names( $this->meta( 'args_post' ) ); @@ -488,6 +502,28 @@ private function state_values( $prefix ) { return $output; } + /** + * Get the body processor. + * + * @return string + */ + private function get_body_processor() { + return $this->body_processor; + } + + /** + * Set the body processor. + * + * @param string $processor Processor to set. Either 'URLENCODED' or 'JSON'. + * + * @return void + */ + public function set_body_processor( $processor ) { + if ( $processor === 'URLENCODED' || $processor === 'JSON' ) { + $this->body_processor = $processor; + } + } + /** * Change a string to all lowercase and replace spaces and underscores with dashes. * diff --git a/projects/packages/waf/tests/php/unit/test-waf-request.php b/projects/packages/waf/tests/php/unit/test-waf-request.php index ce409a4b9e5ac..01c68e5aa5bea 100644 --- a/projects/packages/waf/tests/php/unit/test-waf-request.php +++ b/projects/packages/waf/tests/php/unit/test-waf-request.php @@ -301,6 +301,64 @@ public function testGetVarsPost() { $_POST = array(); } + /** + * Test that the Waf_Request class returns POST-ed data correctly decoded from JSON via Waf_Request::get_post_vars(). + */ + public function testGetVarsPostWithJsonBodyProcessor() { + $_SERVER['CONTENT_TYPE'] = 'irrelevant'; + + $request = $this->mock_request( + array( + 'body' => json_encode( + array( + 'str' => 'value', + 'arr' => array( 'a', 'b', 'c' ), + 'obj' => (object) array( 'foo' => 'bar' ), + ) + ), + ) + ); + $value = $request->get_post_vars( 'JSON' ); + $this->assertIsArray( $value ); + $this->assertContains( array( 'json.str', 'value' ), $value ); + $this->assertContains( array( 'json.arr.0', 'a' ), $value ); + $this->assertContains( array( 'json.arr.1', 'b' ), $value ); + $this->assertContains( array( 'json.arr.2', 'c' ), $value ); + $this->assertContains( array( 'json.obj.foo', 'bar' ), $value ); + + unset( $_SERVER['CONTENT_TYPE'] ); + } + + /** + * Test that the Waf_Request class returns POST-ed data correctly decoded from URLENCODED body via Waf_Request::get_post_vars(). + */ + public function testGetVarsPostWithUrlencodedBodyProcessor() { + $_SERVER['CONTENT_TYPE'] = 'irrelevant'; + + $request = $this->mock_request( + array( + 'body' => ( + http_build_query( + array( + 'str' => 'value', + 'arr' => array( 'a', 'b', 'c' ), + 'obj' => (object) array( 'foo' => 'bar' ), + ) + ) + ), + ) + ); + $value = $request->get_post_vars( 'URLENCODED' ); + $this->assertIsArray( $value ); + $this->assertContains( array( 'str', 'value' ), $value ); + $this->assertContains( array( 'arr[0]', 'a' ), $value ); + $this->assertContains( array( 'arr[1]', 'b' ), $value ); + $this->assertContains( array( 'arr[2]', 'c' ), $value ); + $this->assertContains( array( 'obj[foo]', 'bar' ), $value ); + + unset( $_SERVER['CONTENT_TYPE'] ); + } + /** * Test that the Waf_Request class returns POST-ed data correctly decoded from JSON via Waf_Request::get_post_vars(). */ diff --git a/projects/packages/wordads/changelog/renovate-photon-4.x b/projects/packages/wordads/changelog/renovate-photon-4.x new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/packages/wordads/changelog/renovate-photon-4.x @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/packages/wordads/package.json b/projects/packages/wordads/package.json index b83d2ab4bfaac..1182205ae4698 100644 --- a/projects/packages/wordads/package.json +++ b/projects/packages/wordads/package.json @@ -45,7 +45,7 @@ "clsx": "2.1.1", "fast-json-stable-stringify": "2.1.0", "lodash": "4.17.21", - "photon": "4.0.0", + "photon": "4.1.1", "preact": "10.22.1", "prop-types": "15.7.2", "q-flat": "1.0.7", diff --git a/projects/plugins/boost/app/admin/class-admin.php b/projects/plugins/boost/app/admin/class-admin.php index 81175df6157ec..522692c7f9513 100644 --- a/projects/plugins/boost/app/admin/class-admin.php +++ b/projects/plugins/boost/app/admin/class-admin.php @@ -14,9 +14,7 @@ use Automattic\Jetpack_Boost\Lib\Analytics; use Automattic\Jetpack_Boost\Lib\Environment_Change_Detector; use Automattic\Jetpack_Boost\Lib\Premium_Features; -use Automattic\Jetpack_Boost\Modules\Modules_Index; use Automattic\Jetpack_Boost\Modules\Modules_Setup; -use Automattic\Jetpack_Boost\Modules\Optimizations\Critical_CSS\Critical_CSS; class Admin { /** @@ -83,17 +81,6 @@ public function enqueue_scripts() { */ $internal_path = apply_filters( 'jetpack_boost_asset_internal_path', 'app/assets/dist/' ); - $critical_css_gen_handle = 'jetpack-boost-critical-css-gen'; - - Assets::register_script( - $critical_css_gen_handle, - $internal_path . 'critical-css-gen.js', - JETPACK_BOOST_PATH, - array( - 'in_footer' => true, - ) - ); - $admin_js_handle = 'jetpack-boost-admin'; $admin_js_dependencies = array( @@ -101,11 +88,6 @@ public function enqueue_scripts() { 'wp-components', ); - // Enqueue the critical CSS generator script if Critical CSS is available. - if ( ( new Modules_Index() )->is_module_available( Critical_CSS::get_slug() ) ) { - $admin_js_dependencies[] = $critical_css_gen_handle; - } - Assets::register_script( $admin_js_handle, $internal_path . 'jetpack-boost.js', diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/generate-critical-css.ts b/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/generate-critical-css.ts index 94bddd77edbd9..d53a5d93d3453 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/generate-critical-css.ts +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/generate-critical-css.ts @@ -6,7 +6,6 @@ import { logPreCriticalCSSGeneration } from '$lib/utils/console'; import { isSameOrigin } from '$lib/utils/is-same-origin'; import { prepareAdminAjaxRequest } from '$lib/utils/make-admin-ajax-request'; import { standardizeError } from '$lib/utils/standardize-error'; -import { SuccessTargetError } from 'jetpack-boost-critical-css-gen'; type Viewport = { width: number; @@ -47,6 +46,12 @@ interface GeneratorCallbacks extends ProviderCallbacks { onFinished: () => void; // Called when the generator is finished, regardless of success or failure. } +async function criticalCssGenerator() { + return await import( + /* webpackChunkName: "jetpack-critical-css-gen" */ '@automattic/jetpack-critical-css-gen' + ); +} + /** * Run the local Critical CSS Generator for a set of providers, if it is not already running. * The result of generation will not be returned to the caller; it will be sent to the given @@ -137,10 +142,11 @@ async function generateCriticalCss( * @param {Object} requestGetParameters - GET parameters to include with each request. * @param {string} proxyNonce - Nonce to use when proxying CSS requests. */ -function createBrowserInterface( +async function createBrowserInterface( requestGetParameters: Record< string, string >, proxyNonce: string ) { + const CriticalCSSGenerator = await criticalCssGenerator(); return new ( class extends CriticalCSSGenerator.BrowserInterfaceIframe { constructor() { super( { @@ -164,10 +170,6 @@ function createBrowserInterface( } )(); } -function isSuccessTargetError( err: unknown ): err is SuccessTargetError { - return err instanceof Error && 'isSuccessTargetError' in err; -} - /** * Generate Critical CSS for the specified Provider Keys, sending each block * to the server. Throws on error or cancellation. @@ -187,6 +189,7 @@ async function generateForKeys( callbacks: ProviderCallbacks, signal: AbortSignal ): Promise< void > { + const CriticalCSSGenerator = await criticalCssGenerator(); try { CriticalCSSGeneratorSchema.parse( CriticalCSSGenerator ); } catch ( err ) { @@ -194,6 +197,12 @@ async function generateForKeys( throw new Error( 'css-gen-library-failure' ); } + function isSuccessTargetError( + err: unknown + ): err is InstanceType< typeof CriticalCSSGenerator.SuccessTargetError > { + return err instanceof CriticalCSSGenerator.SuccessTargetError; + } + // eslint-disable-next-line @wordpress/no-unused-vars-before-return const startTime = Date.now(); let totalSize = 0; @@ -209,7 +218,7 @@ async function generateForKeys( try { const [ css ] = await CriticalCSSGenerator.generateCriticalCSS( { - browserInterface: createBrowserInterface( requestGetParameters, proxyNonce ), + browserInterface: await createBrowserInterface( requestGetParameters, proxyNonce ), urls, viewports, progressCallback: ( step: number, total: number ) => { @@ -336,7 +345,7 @@ function keepAtRule( name: string ): boolean { /** * Helper method to filter out properties that we don't want. * Note this function is used as a filter in the generateCriticalCSS function - * in the jetpack-boost-critical-css-gen library (https://github.com/Automattic/jetpack-boost-critical-css-gen). + * in the @automattic/jetpack-critical-css-gen library (https://github.com/Automattic/jetpack-critical-css-gen). * * This function has a value parameter which is not being used here but other implementations of this * helper function for the library may require the value parameter for filtering. @@ -355,7 +364,7 @@ function keepProperty( name: string, _value: string ): boolean { * Function to verify that a specific page is valid to run the Critical CSS process on it. * * Note that this function is used as a callback in the generateCriticalCSS function - * in the jetpack-boost-critical-css-gen library (https://github.com/Automattic/jetpack-boost-critical-css-gen). + * in the @automattic/jetpack-critical-css-gen library (https://github.com/Automattic/jetpack-critical-css-gen). * * This function has a url and innerWindow parameters which are not being used here but this method * is called with URL and InnerWindow in that library to offer flexibility of the verification for other implementation. diff --git a/projects/plugins/boost/app/assets/src/js/global.d.ts b/projects/plugins/boost/app/assets/src/js/global.d.ts index 2aecfb42192d7..b2f267885c8da 100644 --- a/projects/plugins/boost/app/assets/src/js/global.d.ts +++ b/projects/plugins/boost/app/assets/src/js/global.d.ts @@ -2,8 +2,6 @@ * Type definitions for the global namespace. i.e.: things we expect to find in window. */ -import type { BrowserInterfaceIframe, generateCriticalCSS } from 'jetpack-boost-critical-css-gen'; - // declare global { @@ -38,12 +36,6 @@ declare global { }; }; - // Critical CSS Generator library. - const CriticalCSSGenerator: { - generateCriticalCSS: typeof generateCriticalCSS; - BrowserInterfaceIframe: typeof BrowserInterfaceIframe; - }; - const jpTracksAJAX: { record_ajax_event: ( eventName: string, diff --git a/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php b/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php index 4d6ef31835cb7..8b08c45ca41b3 100644 --- a/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php +++ b/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php @@ -36,10 +36,8 @@ public static function handle_proxy() { wp_send_json_error( 'Invalid URL', 400 ); } - $photon_url = Image_CDN_Core::cdn_url( $proxy_url ); - $photon_url_domain = wp_parse_url( $photon_url, PHP_URL_HOST ); - $photon_domain = wp_parse_url( apply_filters( 'jetpack_photon_domain', 'https://i0.wp.com' ), PHP_URL_HOST ); - if ( $photon_url_domain !== $photon_domain ) { + $photon_url = Image_CDN_Core::cdn_url( $proxy_url ); + if ( ! Image_CDN_Core::is_cdn_url( $proxy_url ) ) { wp_send_json_error( 'Failed to proxy the image.', 400 ); } diff --git a/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php b/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php index 75ef96c69a6f1..169ce01ee91c9 100644 --- a/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php +++ b/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php @@ -68,6 +68,11 @@ public function setup() { $this->ignore_attribute = apply_filters( 'jetpack_boost_render_blocking_js_ignore_attribute', 'data-jetpack-boost' ); add_action( 'template_redirect', array( $this, 'start_output_filtering' ), -999999 ); + + /** + * Shortcodes can sometimes output script to embed widget. It's safer to ignore them. + */ + add_filter( 'do_shortcode_tag', array( $this, 'add_ignore_attribute' ) ); } /** @@ -256,7 +261,7 @@ protected function ignore_exclusion_scripts( $buffer ) { return preg_replace_callback( $exclusions, function ( $script_match ) { - return str_replace( 'ignore_attribute ), esc_attr( $this->ignore_value ) ), $script_match[0] ); + return $this->add_ignore_attribute( $script_match[0] ); }, $buffer ); @@ -324,7 +329,18 @@ public function handle_exclusions( $tag, $handle ) { return $tag; } - return str_replace( 'ignore_attribute ), esc_attr( $this->ignore_value ) ), $tag ); + return $this->add_ignore_attribute( $tag ); + } + + /** + * Add the ignore attribute to the script tags + * + * @param string $html HTML code possibly containing a