Skip to content

Commit c1784c4

Browse files
fix format option splitter problems (#2315)
Co-authored-by: David Goss <[email protected]>
1 parent 8a10f4c commit c1784c4

File tree

3 files changed

+196
-22
lines changed

3 files changed

+196
-22
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
Please see [CONTRIBUTING.md](./CONTRIBUTING.md) on how to contribute to Cucumber.
99

1010
## [Unreleased]
11+
### Fixed
12+
- Improve handling of formatter paths ([#2315](https://github.com/cucumber/cucumber-js/pull/2315))
1113

1214
## [9.5.1] - 2023-09-06
1315
### Fixed

src/configuration/option_splitter.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,57 @@
11
export const OptionSplitter = {
22
split(option: string): string[] {
3-
option = option.replace(/"/g, '')
3+
let result: string[]
4+
let match1, match2
45

5-
const parts = option.split(/((?:file){0}):(?!\\|\/\/)/)
6-
7-
const result = parts.reduce((memo: string[], part: string, i: number) => {
8-
if (partNeedsRecombined(i)) {
9-
memo.push(parts.slice(i, i + 2).join(''))
6+
// "foo":"bar" or "foo":bar
7+
if ((match1 = option.match(/^"([^"]*)":(.*)$/)) !== null) {
8+
// "foo":"bar"
9+
if ((match2 = match1[2].match(/^"([^"]*)"$/)) !== null) {
10+
result = [match1[1], match2[1]]
1011
}
11-
12-
return memo
13-
}, [])
14-
15-
if (result.length === 1) {
16-
result.push('')
12+
// "foo":bar
13+
else {
14+
result = [match1[1], match1[2]]
15+
}
16+
}
17+
// foo:"bar"
18+
else if ((match1 = option.match(/^(.*):"([^"]*)"$/)) !== null) {
19+
result = [match1[1], match1[2]]
20+
}
21+
// "foo"
22+
else if ((match1 = option.match(/^"([^"]*)"$/)) !== null) {
23+
result = [match1[1], '']
24+
}
25+
// file://foo or file:///foo or file://C:/foo or file://C:\foo or file:///C:/foo or file:///C:\foo
26+
else if (
27+
(match1 = option.match(/^(file:\/{2,3}(?:[a-zA-Z]:[/\\])?)(.*)$/)) !==
28+
null
29+
) {
30+
// file://foo:bar
31+
if ((match2 = match1[2].match(/^([^:]*):(.*)$/)) !== null) {
32+
result = [match1[1] + match2[1], match2[2]]
33+
} else {
34+
result = [option, '']
35+
}
36+
}
37+
// C:\foo or C:/foo
38+
else if ((match1 = option.match(/^([a-zA-Z]:[/\\])(.*)$/)) !== null) {
39+
// C:\foo:bar or C:/foo:bar
40+
if ((match2 = match1[2].match(/^([^:]*):(.*)$/)) !== null) {
41+
result = [match1[1] + match2[1], match2[2]]
42+
} else {
43+
result = [option, '']
44+
}
45+
}
46+
// foo:bar
47+
else if ((match1 = option.match(/^([^:]*):(.*)$/)) !== null) {
48+
result = [match1[1], match1[2]]
49+
}
50+
// foo
51+
else {
52+
result = [option, '']
1753
}
1854

1955
return result
2056
},
2157
}
22-
23-
function partNeedsRecombined(i: number): boolean {
24-
return i % 2 === 0
25-
}

src/configuration/option_splitter_spec.ts

Lines changed: 146 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,26 @@ describe('OptionSplitter', () => {
1515
output: ['../custom/formatter', '../formatter/output.txt'],
1616
},
1717
{
18-
description: 'splits absolute unix paths',
18+
description: 'splits relative windows paths',
19+
input: '..\\custom\\formatter:..\\formatter\\output.txt',
20+
output: ['..\\custom\\formatter', '..\\formatter\\output.txt'],
21+
},
22+
{
23+
description: 'splits file URLs for absolute unix path',
1924
input: 'file:///custom/formatter:file:///formatter/output.txt',
2025
output: ['file:///custom/formatter', 'file:///formatter/output.txt'],
2126
},
2227
{
23-
description: 'splits paths with quotes around them',
24-
input: '/custom/formatter:"/formatter directory/output.txt"',
25-
output: ['/custom/formatter', '/formatter directory/output.txt'],
28+
description: 'splits file URLs for UNC path',
29+
input:
30+
'file://hostname/custom/formatter:file://hostname/formatter/output.txt',
31+
output: [
32+
'file://hostname/custom/formatter',
33+
'file://hostname/formatter/output.txt',
34+
],
2635
},
2736
{
28-
description: 'splits absolute windows paths',
37+
description: 'splits file URLs for absolute windows path',
2938
input: 'file://C:\\custom\\formatter:file://C:\\formatter\\output.txt',
3039
output: [
3140
'file://C:\\custom\\formatter',
@@ -34,10 +43,141 @@ describe('OptionSplitter', () => {
3443
},
3544
{
3645
description:
37-
'does not split a single absolute windows paths, adds empty string',
46+
'splits file URLs for absolute windows path with "/" as directory separator',
47+
input: 'file:///C:/custom/formatter:file:///C:/formatter/output.txt',
48+
output: [
49+
'file:///C:/custom/formatter',
50+
'file:///C:/formatter/output.txt',
51+
],
52+
},
53+
{
54+
description: 'splits valid file URLs for absolute windows path',
55+
input: 'file:///C:\\custom\\formatter:file:///C:\\formatter\\output.txt',
56+
output: [
57+
'file:///C:\\custom\\formatter',
58+
'file:///C:\\formatter\\output.txt',
59+
],
60+
},
61+
{
62+
description:
63+
'splits valid file URLs for absolute windows path with "/" as directory separator',
64+
input: 'file:///C:/custom/formatter:file:///C:/formatter/output.txt',
65+
output: [
66+
'file:///C:/custom/formatter',
67+
'file:///C:/formatter/output.txt',
68+
],
69+
},
70+
{
71+
description: 'splits absolute unix paths',
72+
input: '/custom/formatter:/formatter/output.txt',
73+
output: ['/custom/formatter', '/formatter/output.txt'],
74+
},
75+
{
76+
description: 'splits absolute windows paths',
77+
input: 'C:\\custom\\formatter:C:\\formatter\\output.txt',
78+
output: ['C:\\custom\\formatter', 'C:\\formatter\\output.txt'],
79+
},
80+
{
81+
description:
82+
'splits absolute windows paths with "/" as directory separator',
83+
input: 'C:/custom/formatter:C:/formatter/output.txt',
84+
output: ['C:/custom/formatter', 'C:/formatter/output.txt'],
85+
},
86+
{
87+
description: 'splits UNC paths',
88+
input:
89+
'\\\\hostname\\custom\\formatter:\\\\hostname\\formatter\\output.txt',
90+
output: [
91+
'\\\\hostname\\custom\\formatter',
92+
'\\\\hostname\\formatter\\output.txt',
93+
],
94+
},
95+
{
96+
description: 'splits UNC paths with "/" as directory separator',
97+
input: '//hostname/custom/formatter://hostname/formatter/output.txt',
98+
output: [
99+
'//hostname/custom/formatter',
100+
'//hostname/formatter/output.txt',
101+
],
102+
},
103+
{
104+
description: 'splits paths with quotes around them',
105+
input: '/custom/formatter:"/formatter directory/output.txt"',
106+
output: ['/custom/formatter', '/formatter directory/output.txt'],
107+
},
108+
{
109+
description:
110+
'does not split a single file URL for absolute unix path, adds empty string',
111+
input: 'file:///custom/formatter',
112+
output: ['file:///custom/formatter', ''],
113+
},
114+
{
115+
description:
116+
'does not split a single file URL for UNC path, adds empty string',
117+
input: 'file://hostname/custom/formatter',
118+
output: ['file://hostname/custom/formatter', ''],
119+
},
120+
{
121+
description:
122+
'does not split a single file URL for absolute windows path, adds empty string',
38123
input: 'file://C:\\custom\\formatter',
39124
output: ['file://C:\\custom\\formatter', ''],
40125
},
126+
{
127+
description:
128+
'does not split a single file URL for absolute windows path with "/" as directory separator, adds empty string',
129+
input: 'file://C:/custom/formatter',
130+
output: ['file://C:/custom/formatter', ''],
131+
},
132+
{
133+
description:
134+
'does not split a valid single file URL for absolute windows path, adds empty string',
135+
input: 'file:///C:\\custom\\formatter',
136+
output: ['file:///C:\\custom\\formatter', ''],
137+
},
138+
{
139+
description:
140+
'does not split a valid single file URL for absolute windows path with "/" as directory separator, adds empty string',
141+
input: 'file:///C:/custom/formatter',
142+
output: ['file:///C:/custom/formatter', ''],
143+
},
144+
{
145+
description:
146+
'does not split a single absolute windows path, adds empty string',
147+
input: 'C:\\custom\\formatter',
148+
output: ['C:\\custom\\formatter', ''],
149+
},
150+
{
151+
description:
152+
'does not split a single absolute windows path with "/" as directory separator, adds empty string',
153+
input: 'C:/custom/formatter',
154+
output: ['C:/custom/formatter', ''],
155+
},
156+
{
157+
description: 'does not split quoted values: case 1',
158+
input: '"foo:bar":"baz:qux"',
159+
output: ['foo:bar', 'baz:qux'],
160+
},
161+
{
162+
description: 'does not split quoted values: case 2',
163+
input: '"foo:bar":baz:qux',
164+
output: ['foo:bar', 'baz:qux'],
165+
},
166+
{
167+
description: 'does not split quoted values: case 3',
168+
input: 'foo:bar:"baz:qux"',
169+
output: ['foo:bar', 'baz:qux'],
170+
},
171+
{
172+
description: 'does not split quoted values: case 4',
173+
input: '"foo:bar:baz:qux"',
174+
output: ['foo:bar:baz:qux', ''],
175+
},
176+
{
177+
description: 'splits string contains multiple ":"',
178+
input: 'foo:bar:baz:qux',
179+
output: ['foo', 'bar:baz:qux'],
180+
},
41181
]
42182

43183
examples.forEach(({ description, input, output }) => {

0 commit comments

Comments
 (0)