Skip to content

Commit fa60b4e

Browse files
committed
Merge branch 'master' into renovate/lock-file-maintenance
2 parents 93760b2 + ac83e0c commit fa60b4e

File tree

16 files changed

+292
-35
lines changed

16 files changed

+292
-35
lines changed

.github/workflows/publish.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ on:
3030
required: false
3131
type: boolean
3232
default: true
33+
dist-tag:
34+
description: 'NPM dist tag to publish to'
35+
required: false
36+
type: string
37+
default: 'latest'
3338

3439
permissions: {}
3540

@@ -89,5 +94,8 @@ jobs:
8994
if [ "${{ inputs.github-release }}" = "true" ]; then
9095
ARGS="$ARGS --github-release"
9196
fi
97+
if [ -n "${{ inputs.dist-tag }}" ]; then
98+
ARGS="$ARGS --tag ${{ inputs.dist-tag }}"
99+
fi
92100
93101
pnpm code-infra publish $ARGS

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Versions
22

3+
## 2.0.8
4+
5+
Test release
6+
37
## 2.0.7
48

59
Test release

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mui-public",
3-
"version": "2.0.7",
3+
"version": "2.0.8",
44
"private": true,
55
"scripts": {
66
"preinstall": "npx only-allow pnpm",

packages/bundle-size-checker/src/builder.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as zlib from 'node:zlib';
44
import { promisify } from 'node:util';
55
import { build, transformWithEsbuild } from 'vite';
66
import { visualizer } from 'rollup-plugin-visualizer';
7+
import { escapeFilename } from './strings.js';
78

89
const gzipAsync = promisify(zlib.gzip);
910

@@ -48,7 +49,7 @@ function createReplacePlugin(replacements) {
4849
* @param {ObjectEntry} entry - Entry point (string or object)
4950
* @param {CommandLineArgs} args
5051
* @param {Record<string, string>} [replacements] - String replacements to apply
51-
* @returns {Promise<import('vite').InlineConfig>}
52+
* @returns {Promise<{ config:import('vite').InlineConfig, treemapPath: string }>}
5253
*/
5354
async function createViteConfig(entry, args, replacements = {}) {
5455
const entryName = entry.id;
@@ -78,13 +79,15 @@ async function createViteConfig(entry, args, replacements = {}) {
7879
const externalsArray = entry.externals || ['react', 'react-dom'];
7980

8081
// Ensure build directory exists
81-
const outDir = path.join(rootDir, 'build', entryName);
82+
const outDir = path.join(rootDir, 'build', escapeFilename(entryName));
8283
await fs.mkdir(outDir, { recursive: true });
8384

85+
const treemapPath = path.join(outDir, 'treemap.html');
86+
8487
/**
8588
* @type {import('vite').InlineConfig}
8689
*/
87-
const configuration = {
90+
const config = {
8891
configFile: false,
8992
root: rootDir,
9093

@@ -112,7 +115,7 @@ async function createViteConfig(entry, args, replacements = {}) {
112115
? [
113116
// File sizes are not accurate, use it only for relative comparison
114117
visualizer({
115-
filename: `${outDir}.html`,
118+
filename: treemapPath,
116119
title: `Bundle Size Analysis: ${entryName}`,
117120
projectRoot: rootDir,
118121
open: false,
@@ -171,7 +174,7 @@ async function createViteConfig(entry, args, replacements = {}) {
171174
],
172175
};
173176

174-
return configuration;
177+
return { config, treemapPath };
175178
}
176179

177180
/**
@@ -275,19 +278,21 @@ async function processBundleSizes(output, entryName) {
275278
* @param {ObjectEntry} entry - The entry configuration
276279
* @param {CommandLineArgs} args - Command line arguments
277280
* @param {Record<string, string>} [replacements] - String replacements to apply
278-
* @returns {Promise<Map<string, SizeSnapshotEntry>>}
281+
* @returns {Promise<{ sizes: Map<string, SizeSnapshotEntry>, treemapPath: string }>}
279282
*/
280283
export async function getBundleSizes(entry, args, replacements) {
281284
// Create vite configuration
282-
const configuration = await createViteConfig(entry, args, replacements);
285+
const { config, treemapPath } = await createViteConfig(entry, args, replacements);
283286

284287
// Run vite build
285-
const { output } = /** @type {import('vite').Rollup.RollupOutput} */ (await build(configuration));
288+
const { output } = /** @type {import('vite').Rollup.RollupOutput} */ (await build(config));
286289
const manifestChunk = output.find((chunk) => chunk.fileName === '.vite/manifest.json');
287290
if (!manifestChunk) {
288291
throw new Error(`Manifest file not found in output for entry: ${entry.id}`);
289292
}
290293

291294
// Process the output to get bundle sizes
292-
return processBundleSizes(output, entry.id);
295+
const sizes = await processBundleSizes(output, entry.id);
296+
297+
return { sizes, treemapPath };
293298
}

packages/bundle-size-checker/src/cli.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import yargs from 'yargs';
77
import { Piscina } from 'piscina';
88
import micromatch from 'micromatch';
99
import envCi from 'env-ci';
10+
import { pathToFileURL } from 'node:url';
11+
import chalk from 'chalk';
1012
import { loadConfig } from './configLoader.js';
1113
import { uploadSnapshot } from './uploadSnapshot.js';
1214
import { renderMarkdownReport } from './renderMarkdownReport.js';
@@ -229,7 +231,9 @@ async function run(argv) {
229231
await fs.writeFile(snapshotDestPath, JSON.stringify(sortedBundleSizes, null, 2));
230232

231233
// eslint-disable-next-line no-console
232-
console.log(`Bundle size snapshot written to ${snapshotDestPath}`);
234+
console.log(
235+
`Bundle size snapshot written to ${chalk.underline(pathToFileURL(snapshotDestPath))}`,
236+
);
233237

234238
// Upload the snapshot if upload configuration is provided and not null
235239
if (config && config.upload) {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const illegalRe = /[/?<>\\:*|"]/g;
2+
// eslint-disable-next-line no-control-regex
3+
const controlRe = /[\x00-\x1f\x80-\x9f]/g;
4+
const reservedRe = /^\.+$/;
5+
const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
6+
const windowsTrailingRe = /[. ]+$/;
7+
8+
/**
9+
* Inspired by https://github.com/parshap/node-sanitize-filename
10+
*
11+
* Replaces characters in strings that are illegal/unsafe for filenames.
12+
* Unsafe characters are either removed or replaced by a substitute set
13+
* in the optional `options` object.
14+
*
15+
* Illegal Characters on Various Operating Systems
16+
* / ? < > \ : * | "
17+
* https://kb.acronis.com/content/39790
18+
*
19+
* Unicode Control codes
20+
* C0 0x00-0x1f & C1 (0x80-0x9f)
21+
* http://en.wikipedia.org/wiki/C0_and_C1_control_codes
22+
*
23+
* Reserved filenames on Unix-based systems (".", "..")
24+
* Reserved filenames in Windows ("CON", "PRN", "AUX", "NUL", "COM1",
25+
* "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
26+
* "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", and
27+
* "LPT9") case-insesitively and with or without filename extensions.
28+
* @param {string} input
29+
*/
30+
export function escapeFilename(input, replacement = '_') {
31+
const sanitized = input
32+
.replace(illegalRe, replacement)
33+
.replace(controlRe, replacement)
34+
.replace(reservedRe, replacement)
35+
.replace(windowsReservedRe, replacement)
36+
.replace(windowsTrailingRe, replacement);
37+
return sanitized;
38+
}

packages/bundle-size-checker/src/worker.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { pathToFileURL } from 'node:url';
2-
import path from 'node:path';
32
import fs from 'node:fs/promises';
43
import chalk from 'chalk';
54
import * as module from 'node:module';
@@ -83,7 +82,7 @@ export default async function getSizes({ entry, args, index, total, replace }) {
8382
}
8483

8584
try {
86-
const sizeMap = await getBundleSizes(entry, args, replace);
85+
const { sizes: sizeMap, treemapPath } = await getBundleSizes(entry, args, replace);
8786

8887
// Create a concise log message showing import details
8988
let entryDetails = '';
@@ -108,7 +107,7 @@ ${chalk.green('✓')} ${chalk.green.bold(`Completed ${index + 1}/${total}: [${en
108107
${chalk.cyan('Import:')} ${entryDetails}
109108
${chalk.cyan('Externals:')} ${entry.externals.join(', ')}
110109
${chalk.cyan('Sizes:')} ${chalk.yellow(byteSizeFormatter.format(entrySize.parsed))} (${chalk.yellow(byteSizeFormatter.format(entrySize.gzip))} gzipped)
111-
${args.analyze ? ` ${chalk.cyan('Analysis:')} ${chalk.underline(pathToFileURL(path.join(rootDir, 'build', `${entry.id}.html`)).href)}` : ''}
110+
${args.analyze ? ` ${chalk.cyan('Analysis:')} ${chalk.underline(pathToFileURL(treemapPath).href)}` : ''}
112111
`.trim(),
113112
);
114113

packages/code-infra/src/cli/cmdPublish.mjs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ function getOctokit() {
2323
* @typedef {Object} Args
2424
* @property {boolean} dry-run Run in dry-run mode without publishing
2525
* @property {boolean} github-release Create a GitHub draft release after publishing
26+
* @property {string} tag NPM dist tag to publish to
2627
*/
2728

2829
/**
@@ -221,7 +222,7 @@ async function publishToNpm(packages, options) {
221222
});
222223

223224
// Use pnpm's built-in duplicate checking - no need to check versions ourselves
224-
await publishPackages(packages, 'latest', options);
225+
await publishPackages(packages, options);
225226
console.log('✅ Successfully published to npm');
226227
}
227228

@@ -268,10 +269,15 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
268269
type: 'boolean',
269270
default: false,
270271
description: 'Create a GitHub draft release after publishing',
272+
})
273+
.option('tag', {
274+
type: 'string',
275+
default: 'latest',
276+
description: 'NPM dist tag to publish to',
271277
});
272278
},
273279
handler: async (argv) => {
274-
const { dryRun = false, githubRelease = false } = argv;
280+
const { dryRun = false, githubRelease = false, tag = 'latest' } = argv;
275281

276282
if (dryRun) {
277283
console.log('🧪 Running in DRY RUN mode - no actual publishing will occur\n');
@@ -303,7 +309,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
303309

304310
// Publish to npm (pnpm handles duplicate checking automatically)
305311
// No git checks, we'll do our own
306-
await publishToNpm(allPackages, { dryRun, noGitChecks: true });
312+
await publishToNpm(allPackages, { dryRun, noGitChecks: true, tag });
307313

308314
await createGitTag(version, dryRun);
309315

packages/code-infra/src/cli/cmdPublishCanary.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ async function publishCanaryVersions(
151151
let publishSuccess = false;
152152
try {
153153
console.log(`📤 Publishing ${packagesToPublish.length} canary versions...`);
154-
await publishPackages(packagesToPublish, 'canary', { ...options, noGitChecks: true });
154+
await publishPackages(packagesToPublish, { ...options, noGitChecks: true, tag: 'canary' });
155155

156156
packagesToPublish.forEach((pkg) => {
157157
const canaryVersion = canaryVersions.get(pkg.name);

packages/code-infra/src/cli/pnpm.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import * as semver from 'semver';
3131
* @typedef {Object} PublishOptions
3232
* @property {boolean} [dryRun] - Whether to run in dry-run mode
3333
* @property {boolean} [noGitChecks] - Whether to skip git checks
34+
* @property {string} [tag] - NPM dist tag to publish to
3435
*/
3536

3637
/**
@@ -129,12 +130,12 @@ export async function getPackageVersionInfo(packageName, baseVersion) {
129130
/**
130131
* Publish packages with the given options
131132
* @param {PublicPackage[]} packages - Packages to publish
132-
* @param {string} tag - npm tag to publish with
133133
* @param {PublishOptions} [options={}] - Publishing options
134134
* @returns {Promise<void>}
135135
*/
136-
export async function publishPackages(packages, tag, options = {}) {
136+
export async function publishPackages(packages, options = {}) {
137137
const args = [];
138+
const tag = options.tag ?? 'latest';
138139

139140
// Add package filters
140141
packages.forEach((pkg) => {

0 commit comments

Comments
 (0)