Skip to content

Commit bee26fe

Browse files
authored
Merge pull request #2692 from hey-api/copilot/fix-4811abf9-2ebf-43bc-b1cd-2fde0f579207
2 parents c8124d9 + dba81bc commit bee26fe

File tree

3 files changed

+91
-2
lines changed

3 files changed

+91
-2
lines changed

.changeset/lazy-ties-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hey-api/openapi-ts": patch
3+
---
4+
5+
fix(validators): escaping slashes in regular expressions
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { createRegularExpressionLiteral } from '../types';
4+
5+
describe('createRegularExpressionLiteral', () => {
6+
it('should escape forward slashes in regex patterns', () => {
7+
const result = createRegularExpressionLiteral({
8+
text: '^data:image/svg\\+xml;base64,[A-Za-z0-9+/]+=*$',
9+
});
10+
11+
expect(result.text).toBe(
12+
'/^data:image\\/svg\\+xml;base64,[A-Za-z0-9+\\/]+=*$/',
13+
);
14+
});
15+
16+
it('should handle patterns without forward slashes', () => {
17+
const result = createRegularExpressionLiteral({
18+
text: '^[a-zA-Z0-9_]*$',
19+
});
20+
21+
expect(result.text).toBe('/^[a-zA-Z0-9_]*$/');
22+
});
23+
24+
it('should handle patterns that already have slashes at start and end', () => {
25+
const result = createRegularExpressionLiteral({
26+
text: '/^[a-zA-Z0-9_]*$/',
27+
});
28+
29+
expect(result.text).toBe('/^[a-zA-Z0-9_]*$/');
30+
});
31+
32+
it('should handle patterns with slashes at start/end and internal slashes', () => {
33+
const result = createRegularExpressionLiteral({
34+
text: '/^data:image/svg\\+xml;base64,[A-Za-z0-9+/]+=*$/',
35+
});
36+
37+
expect(result.text).toBe(
38+
'/^data:image\\/svg\\+xml;base64,[A-Za-z0-9+\\/]+=*$/',
39+
);
40+
});
41+
42+
it('should preserve flags', () => {
43+
const result = createRegularExpressionLiteral({
44+
flags: ['g', 'i'],
45+
text: '^[a-zA-Z]*$',
46+
});
47+
48+
expect(result.text).toBe('/^[a-zA-Z]*$/gi');
49+
});
50+
51+
it('should handle patterns with multiple forward slashes', () => {
52+
const result = createRegularExpressionLiteral({
53+
text: '^path/to/file/name$',
54+
});
55+
56+
expect(result.text).toBe('/^path\\/to\\/file\\/name$/');
57+
});
58+
59+
it('should handle empty pattern', () => {
60+
const result = createRegularExpressionLiteral({
61+
text: '',
62+
});
63+
64+
expect(result.text).toBe('//');
65+
});
66+
67+
it('should handle patterns with already correctly escaped slashes', () => {
68+
const result = createRegularExpressionLiteral({
69+
text: '^data:image\\/svg\\+xml;base64,[A-Za-z0-9+\\/]+=*$',
70+
});
71+
72+
expect(result.text).toBe(
73+
'/^data:image\\/svg\\+xml;base64,[A-Za-z0-9+\\/]+=*$/',
74+
);
75+
});
76+
});

packages/openapi-ts/src/tsc/types.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,16 @@ export const createRegularExpressionLiteral = ({
10801080
flags?: ReadonlyArray<'g' | 'i' | 'm' | 's' | 'u' | 'y'>;
10811081
text: string;
10821082
}) => {
1083-
const textWithSlashes =
1084-
text.startsWith('/') && text.endsWith('/') ? text : `/${text}/`;
1083+
// Extract pattern content, removing outer slashes if present
1084+
const patternContent =
1085+
text.startsWith('/') && text.endsWith('/') ? text.slice(1, -1) : text;
1086+
1087+
// Escape forward slashes in the pattern content, but only if they're not already escaped
1088+
const escapedPattern = patternContent.replace(/(?<!\\)\//g, '\\/');
1089+
1090+
// Wrap with forward slashes
1091+
const textWithSlashes = `/${escapedPattern}/`;
1092+
10851093
return ts.factory.createRegularExpressionLiteral(
10861094
`${textWithSlashes}${flags.join('')}`,
10871095
);

0 commit comments

Comments
 (0)