diff --git a/dangerFileContent.ts b/dangerFileContent.ts index 89960978b0c16d..c69ed51d03c170 100644 --- a/dangerFileContent.ts +++ b/dangerFileContent.ts @@ -1,8 +1,7 @@ import { exec } from 'child_process'; import type * as dangerModule from 'danger'; import replaceUrl from '@mui-internal/api-docs-builder/utils/replaceUrl'; -// eslint-disable-next-line import/no-relative-packages -import { loadComparison } from './scripts/sizeSnapshot'; +import { loadComparison } from 'size-snapshot'; declare const danger: (typeof dangerModule)['danger']; declare const markdown: (typeof dangerModule)['markdown']; @@ -187,7 +186,9 @@ async function reportBundleSize() { } } -function addDeployPreviewUrls() { +async function addDeployPreviewUrls() { + const netlifyPreview = `https://deploy-preview-${danger.github.pr.number}--material-ui.netlify.app/`; + /** * The incoming path from danger does not start with `/` * e.g. ['docs/data/joy/components/button/button.md'] @@ -212,10 +213,14 @@ function addDeployPreviewUrls() { .replace('components/', 'react-'); } - return url; + return new URL(url, netlifyPreview); } - const netlifyPreview = `https://deploy-preview-${danger.github.pr.number}--material-ui.netlify.app/`; + async function formatMdLinkWithQrCode(path: string) { + const url = String(formatFileToLink(path)); + const qr = `${netlifyPreview}edge-functions/qr-code?text=${encodeURIComponent(url)}`; + return `
page ${path}QR code
`; + } const files = [...danger.git.created_files, ...danger.git.modified_files]; @@ -224,24 +229,17 @@ function addDeployPreviewUrls() { .filter((file) => file.startsWith('docs/data') && file.endsWith('.md')) .slice(0, 5); + const docsMdLines = await Promise.all(docs.map(formatMdLinkWithQrCode)); + markdown(` ## Netlify deploy preview -${ - docs.length - ? docs - .map((path) => { - const formattedUrl = formatFileToLink(path); - return `- [${path}](${netlifyPreview}${formattedUrl})`; - }) - .join('\n') - : netlifyPreview -} +${docsMdLines.length ? docsMdLines.join('\n') : await formatMdLinkWithQrCode('/')} `); } async function run() { - addDeployPreviewUrls(); + await addDeployPreviewUrls(); switch (dangerCommand) { case 'prepareBundleSizeReport': diff --git a/netlify.toml b/netlify.toml index 869ce37a1c4dfc..90ead4ac9baac4 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,3 +1,9 @@ +# run `pnpm --package netlify-cli dlx netlify dev --cwd .` to run functions locally +[dev] + command = "pnpm docs:dev" + targetPort = 3000 + port = 8888 + [build] # Directory (relative to root of your repo) that contains the deploy-ready # HTML files and assets generated by the build. If a base directory has diff --git a/netlify/edge-functions/qr-code.ts b/netlify/edge-functions/qr-code.ts new file mode 100644 index 00000000000000..106c6fe1bcc8c2 --- /dev/null +++ b/netlify/edge-functions/qr-code.ts @@ -0,0 +1,33 @@ +import qr from 'https://esm.sh/qr-image@3.2.0'; + +export default async function handler(req: Request) { + const params = new URL(req.url).searchParams; + const text = params.get('text'); + + if (!text) { + return new Response('Missing text query parameter', { status: 400 }); + } + + if (text.length > 1000) { + return new Response('Text query parameter is too long', { status: 400 }); + } + + const data = qr.imageSync(text, { type: 'png' }); + + const v = params.get('v') || ''; + + const cacheKey = new URLSearchParams(); + cacheKey.append('text', text); + cacheKey.append('v', v); + + return new Response(data, { + headers: { + 'Content-Type': 'image/png', + 'Cache-Control': 'public, max-age=31536000, immutable', // Cache for 1 year + }, + }); +} +export const config = { + cache: 'manual', + path: '/edge-functions/qr-code', +}; diff --git a/package.json b/package.json index 0819eb296f24f8..9616e8a4e12272 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,8 @@ "@netlify/functions": "^3.0.0", "@slack/bolt": "^4.2.0", "execa": "^9.5.2", - "google-auth-library": "^9.15.0" + "google-auth-library": "^9.15.0", + "qrcode": "^1.5.4" }, "devDependencies": { "@argos-ci/core": "^2.12.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea2fa53ba5813c..673a43f9c3a235 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: google-auth-library: specifier: ^9.15.0 version: 9.15.0(encoding@0.1.13) + qrcode: + specifier: ^1.5.4 + version: 1.5.4 devDependencies: '@argos-ci/core': specifier: ^2.12.0 @@ -1411,7 +1414,7 @@ importers: version: 7.26.0 '@mui/base': specifier: '*' - version: 5.0.0-beta.68(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 5.0.0-beta.69(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/internal-markdown': specifier: workspace:^ version: link:../markdown @@ -3969,6 +3972,17 @@ packages: '@types/react': optional: true + '@mui/base@5.0.0-beta.69': + resolution: {integrity: sha512-r2YyGUXpZxj8rLAlbjp1x2BnMERTZ/dMqd9cClKj2OJ7ALAuiv/9X5E9eHfRc9o/dGRuLSMq/WTjREktJVjxVA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@mui/core-downloads-tracker@5.15.14': resolution: {integrity: sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==} @@ -4139,8 +4153,8 @@ packages: '@types/react': optional: true - '@mui/utils@6.4.0': - resolution: {integrity: sha512-woOTATWNsTNR3YBh2Ixkj3l5RaxSiGoC9G8gOpYoFw1mZM77LWJeuMHFax7iIW4ahK0Cr35TF9DKtrafJmOmNQ==} + '@mui/utils@6.4.1': + resolution: {integrity: sha512-iQUDUeYh87SvR4lVojaRaYnQix8BbRV51MxaV6MBmqthecQoxwSbS5e2wnbDJUeFxY2ppV505CiqPLtd0OWkqw==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -7333,6 +7347,9 @@ packages: diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -10769,6 +10786,10 @@ packages: engines: {node: '>=18'} hasBin: true + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -11053,6 +11074,11 @@ packages: resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} engines: {node: '>=0.9'} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + qs@6.13.0: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} @@ -15056,7 +15082,21 @@ snapshots: '@babel/runtime': 7.26.0 '@floating-ui/react-dom': 2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/types': 7.2.21(@types/react@19.0.6) - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) + '@popperjs/core': 2.11.8 + clsx: 2.1.1 + prop-types: 15.8.1 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.6 + + '@mui/base@5.0.0-beta.69(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@floating-ui/react-dom': 2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@mui/types': 7.2.21(@types/react@19.0.6) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@popperjs/core': 2.11.8 clsx: 2.1.1 prop-types: 15.8.1 @@ -15091,7 +15131,7 @@ snapshots: '@mui/material': link:packages/mui-material/build '@mui/system': 6.4.0(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0) '@mui/types': 7.2.21(@types/react@19.0.6) - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) clsx: 2.1.1 prop-types: 15.8.1 react: 19.0.0 @@ -15147,7 +15187,7 @@ snapshots: '@mui/private-theming@6.4.0(@types/react@19.0.6)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) prop-types: 15.8.1 react: 19.0.0 optionalDependencies: @@ -15199,7 +15239,7 @@ snapshots: '@mui/private-theming': 6.4.0(@types/react@19.0.6)(react@19.0.0) '@mui/styled-engine': 6.4.0(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(react@19.0.0) '@mui/types': 7.2.21(@types/react@19.0.6) - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 @@ -15237,7 +15277,7 @@ snapshots: optionalDependencies: '@types/react': 19.0.6 - '@mui/utils@6.4.0(@types/react@19.0.6)(react@19.0.0)': + '@mui/utils@6.4.1(@types/react@19.0.6)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 '@mui/types': 7.2.21(@types/react@19.0.6) @@ -15272,7 +15312,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-charts-vendor': 7.20.0 '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) '@react-spring/rafz': 9.7.5 @@ -15310,7 +15350,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-data-grid': 7.23.6(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@mui/material@packages+mui-material+build)(@mui/system@packages+mui-system+build)(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/x-data-grid-pro': 7.23.6(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@mui/material@packages+mui-material+build)(@mui/system@packages+mui-system+build)(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) @@ -15333,7 +15373,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-data-grid': 7.23.6(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@mui/material@packages+mui-material+build)(@mui/system@packages+mui-system+build)(@types/react@19.0.6)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) '@mui/x-license': 7.23.6(@types/react@19.0.6)(react@19.0.0) @@ -15354,7 +15394,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) clsx: 2.1.1 prop-types: 15.8.1 @@ -15372,7 +15412,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-date-pickers': 7.23.6(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@mui/material@packages+mui-material+build)(@mui/system@packages+mui-system+build)(@types/react@19.0.6)(date-fns@2.30.0)(dayjs@1.11.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) '@mui/x-license': 7.23.6(@types/react@19.0.6)(react@19.0.0) @@ -15394,7 +15434,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) '@types/react-transition-group': 4.4.12(@types/react@19.0.6) clsx: 2.1.1 @@ -15413,7 +15453,7 @@ snapshots: '@mui/x-internals@7.23.6(@types/react@19.0.6)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) react: 19.0.0 transitivePeerDependencies: - '@types/react' @@ -15421,7 +15461,7 @@ snapshots: '@mui/x-license@7.23.6(@types/react@19.0.6)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) react: 19.0.0 transitivePeerDependencies: - '@types/react' @@ -15431,7 +15471,7 @@ snapshots: '@babel/runtime': 7.26.0 '@mui/material': link:packages/mui-material/build '@mui/system': link:packages/mui-system/build - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@mui/x-internals': 7.23.6(@types/react@19.0.6)(react@19.0.0) '@types/react-transition-group': 4.4.12(@types/react@19.0.6) clsx: 2.1.1 @@ -16016,7 +16056,7 @@ snapshots: '@emotion/serialize': 1.3.3 '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0) '@mui/system': 6.4.0(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0))(@types/react@19.0.6)(react@19.0.0) - '@mui/utils': 6.4.0(@types/react@19.0.6)(react@19.0.0) + '@mui/utils': 6.4.1(@types/react@19.0.6)(react@19.0.0) '@wyw-in-js/processor-utils': 0.5.5 '@wyw-in-js/shared': 0.5.5 '@wyw-in-js/transform': 0.5.5 @@ -19106,6 +19146,8 @@ snapshots: miller-rabin: 4.0.1 randombytes: 2.1.0 + dijkstrajs@1.0.3: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -23575,6 +23617,8 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + pngjs@5.0.0: {} + possible-typed-array-names@1.0.0: {} postcss-cli@11.0.0(jiti@1.21.6)(postcss@8.4.49)(tsx@4.19.2): @@ -23846,6 +23890,12 @@ snapshots: qjobs@1.2.0: {} + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + qs@6.13.0: dependencies: side-channel: 1.1.0