Only use the last value when parsing duplicate cli arguments (#19416)

## Summary

When parsing cli args, 'mri' returns an array for duplicate args, which
causes unexpected results. All current arguments assume single values
only. Tailwind v3 works the same way.

## Test plan

Updated tests.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
Adam Royle 2025-12-08 03:26:22 +10:00 • committed by GitHub
parent 1ee7bb978d
commit 563a016f96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 43 additions and 2 deletions

View file

@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Try to canonicalize any arbitrary utility to a bare value ([#19379](https://github.com/tailwindlabs/tailwindcss/pull/19379))
- Validate candidates similarly to Oxide ([#19397](https://github.com/tailwindlabs/tailwindcss/pull/19397))
- Canonicalization: combine `text-*` and `leading-*` classes ([#19396](https://github.com/tailwindlabs/tailwindcss/pull/19396))
- Correctly handle duplicate CLI arguments ([#19416](https://github.com/tailwindlabs/tailwindcss/pull/19416))
### Added

View file

@ -17,6 +17,38 @@ it('should be possible to parse a single argument', () => {
`)
})
it('should only return the last value for duplicate arguments', () => {
expect(
args(
{
'--output': { type: 'string', description: 'Output file' },
},
['--output', 'output.css', '--output', 'override.css'],
),
).toMatchInlineSnapshot(`
{
"--output": "override.css",
"_": [],
}
`)
})
it('uses last value when flag with "-" is supplied multiple times', () => {
let result = args(
{
'--output': { type: 'string', description: 'Output file', alias: '-o' },
},
['--output', 'output.css', '--output', '-'],
)
expect(result).toMatchInlineSnapshot(`
{
"--output": "-",
"_": [],
}
`)
})
it('should fallback to the default value if no flag is passed', () => {
expect(
args(

View file

@ -77,9 +77,17 @@ export function args<const T extends Arg>(options: T, argv = process.argv.slice(
let parsed = parse(argv)
for (let key in parsed) {
if (parsed[key] === '__IO_DEFAULT_VALUE__') {
parsed[key] = '-'
let value = parsed[key]
if (key !== '_' && Array.isArray(value)) {
value = value[value.length - 1]
}
if (value === '__IO_DEFAULT_VALUE__') {
value = '-'
}
parsed[key] = value
}
let result: { _: string[]; [key: string]: unknown } = {