@f3liz/rescript-autogen-openapi 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -31,6 +31,65 @@ function escapeString(str) {
|
|
|
31
31
|
return str.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll("\t", "\\t");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
function escapeRegexPattern(str) {
|
|
35
|
+
return (function(s) {
|
|
36
|
+
return s.replace(/\[([^\]]+)\]/g, function(match) {
|
|
37
|
+
let content = match.slice(1, -1);
|
|
38
|
+
let chars = [];
|
|
39
|
+
let hyphenCount = 0;
|
|
40
|
+
let i = 0;
|
|
41
|
+
|
|
42
|
+
while (i < content.length) {
|
|
43
|
+
if (content[i] === '\\\\' && i + 1 < content.length) {
|
|
44
|
+
if (content[i + 1] === '-') {
|
|
45
|
+
// Escaped hyphen - count it and skip
|
|
46
|
+
hyphenCount++;
|
|
47
|
+
i += 2;
|
|
48
|
+
} else {
|
|
49
|
+
// Other escaped char - keep as is
|
|
50
|
+
chars.push(content[i]);
|
|
51
|
+
chars.push(content[i + 1]);
|
|
52
|
+
i += 2;
|
|
53
|
+
}
|
|
54
|
+
} else if (content[i] === '-' && i > 0 && i < content.length - 1) {
|
|
55
|
+
// Check if this hyphen is part of a valid range
|
|
56
|
+
let prevChar = chars[chars.length - 1];
|
|
57
|
+
let nextChar = content[i + 1];
|
|
58
|
+
// If previous char is a backslash, this can't be a range
|
|
59
|
+
if (chars.length >= 2 && chars[chars.length - 2] === '\\\\') {
|
|
60
|
+
// Previous was escaped, so this hyphen is literal
|
|
61
|
+
hyphenCount++;
|
|
62
|
+
i++;
|
|
63
|
+
} else if (nextChar === '\\\\') {
|
|
64
|
+
// Next is escape sequence, hyphen is literal
|
|
65
|
+
hyphenCount++;
|
|
66
|
+
i++;
|
|
67
|
+
} else if (prevChar && nextChar && prevChar.charCodeAt(0) < nextChar.charCodeAt(0)) {
|
|
68
|
+
// Valid range (e.g., a-z), keep the hyphen
|
|
69
|
+
chars.push('-');
|
|
70
|
+
i++;
|
|
71
|
+
} else {
|
|
72
|
+
// Invalid or ambiguous, move to end
|
|
73
|
+
hyphenCount++;
|
|
74
|
+
i++;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
// Regular character or hyphen at start/end
|
|
78
|
+
chars.push(content[i]);
|
|
79
|
+
i++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Add collected hyphens at the end
|
|
84
|
+
let result = chars.join('');
|
|
85
|
+
if (hyphenCount > 0) {
|
|
86
|
+
result += '-'.repeat(hyphenCount);
|
|
87
|
+
}
|
|
88
|
+
return '[' + result + ']';
|
|
89
|
+
});
|
|
90
|
+
})(str);
|
|
91
|
+
}
|
|
92
|
+
|
|
34
93
|
function generateFileHeader(description) {
|
|
35
94
|
return `// ` + description + `
|
|
36
95
|
// Generated by @f3liz/rescript-autogen-openapi
|
|
@@ -247,6 +306,7 @@ export {
|
|
|
247
306
|
generateTypeName,
|
|
248
307
|
generateOperationName,
|
|
249
308
|
escapeString,
|
|
309
|
+
escapeRegexPattern,
|
|
250
310
|
generateFileHeader,
|
|
251
311
|
indent,
|
|
252
312
|
trimMargin,
|
|
@@ -50,7 +50,7 @@ function generateSchemaWithContext(ctx, depthOpt, extractedTypeMap, irType) {
|
|
|
50
50
|
let s = applyConstraints("S.string", c.minLength, c.maxLength, v => v.toString());
|
|
51
51
|
let p = c.pattern;
|
|
52
52
|
if (p !== undefined) {
|
|
53
|
-
return s + `->S.pattern(
|
|
53
|
+
return s + `->S.pattern(/` + CodegenUtils.escapeRegexPattern(p) + `/)`;
|
|
54
54
|
} else {
|
|
55
55
|
return s;
|
|
56
56
|
}
|
package/package.json
CHANGED
|
@@ -48,6 +48,71 @@ let escapeString = (str: string): string =>
|
|
|
48
48
|
->String.replaceAll("\n", "\\n")->String.replaceAll("\r", "\\r")
|
|
49
49
|
->String.replaceAll("\t", "\\t")
|
|
50
50
|
|
|
51
|
+
// Escape Regex Pattern for ReScript 12 regex literals
|
|
52
|
+
// With /.../ syntax, forward slashes don't need escaping inside character classes
|
|
53
|
+
// Only fix hyphen placement in character classes for clarity
|
|
54
|
+
let escapeRegexPattern = (str: string): string => {
|
|
55
|
+
// Move escaped hyphens (\-) to the end of character classes for clarity
|
|
56
|
+
%raw(`
|
|
57
|
+
function(s) {
|
|
58
|
+
return s.replace(/\[([^\]]+)\]/g, function(match) {
|
|
59
|
+
let content = match.slice(1, -1);
|
|
60
|
+
let chars = [];
|
|
61
|
+
let hyphenCount = 0;
|
|
62
|
+
let i = 0;
|
|
63
|
+
|
|
64
|
+
while (i < content.length) {
|
|
65
|
+
if (content[i] === '\\\\' && i + 1 < content.length) {
|
|
66
|
+
if (content[i + 1] === '-') {
|
|
67
|
+
// Escaped hyphen - count it and skip
|
|
68
|
+
hyphenCount++;
|
|
69
|
+
i += 2;
|
|
70
|
+
} else {
|
|
71
|
+
// Other escaped char - keep as is
|
|
72
|
+
chars.push(content[i]);
|
|
73
|
+
chars.push(content[i + 1]);
|
|
74
|
+
i += 2;
|
|
75
|
+
}
|
|
76
|
+
} else if (content[i] === '-' && i > 0 && i < content.length - 1) {
|
|
77
|
+
// Check if this hyphen is part of a valid range
|
|
78
|
+
let prevChar = chars[chars.length - 1];
|
|
79
|
+
let nextChar = content[i + 1];
|
|
80
|
+
// If previous char is a backslash, this can't be a range
|
|
81
|
+
if (chars.length >= 2 && chars[chars.length - 2] === '\\\\') {
|
|
82
|
+
// Previous was escaped, so this hyphen is literal
|
|
83
|
+
hyphenCount++;
|
|
84
|
+
i++;
|
|
85
|
+
} else if (nextChar === '\\\\') {
|
|
86
|
+
// Next is escape sequence, hyphen is literal
|
|
87
|
+
hyphenCount++;
|
|
88
|
+
i++;
|
|
89
|
+
} else if (prevChar && nextChar && prevChar.charCodeAt(0) < nextChar.charCodeAt(0)) {
|
|
90
|
+
// Valid range (e.g., a-z), keep the hyphen
|
|
91
|
+
chars.push('-');
|
|
92
|
+
i++;
|
|
93
|
+
} else {
|
|
94
|
+
// Invalid or ambiguous, move to end
|
|
95
|
+
hyphenCount++;
|
|
96
|
+
i++;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// Regular character or hyphen at start/end
|
|
100
|
+
chars.push(content[i]);
|
|
101
|
+
i++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add collected hyphens at the end
|
|
106
|
+
let result = chars.join('');
|
|
107
|
+
if (hyphenCount > 0) {
|
|
108
|
+
result += '-'.repeat(hyphenCount);
|
|
109
|
+
}
|
|
110
|
+
return '[' + result + ']';
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
`)(str)
|
|
114
|
+
}
|
|
115
|
+
|
|
51
116
|
// Generate file header
|
|
52
117
|
let generateFileHeader = (~description: string): string =>
|
|
53
118
|
`// ${description}
|
|
@@ -42,7 +42,7 @@ let rec generateSchemaWithContext = (~ctx: GenerationContext.t, ~depth=0, ~extra
|
|
|
42
42
|
| String({constraints: c}) =>
|
|
43
43
|
let s = applyConstraints("S.string", c.minLength, c.maxLength, v => Int.toString(v))
|
|
44
44
|
switch c.pattern {
|
|
45
|
-
| Some(p) => `${s}->S.pattern(
|
|
45
|
+
| Some(p) => `${s}->S.pattern(/${CodegenUtils.escapeRegexPattern(p)}/)`
|
|
46
46
|
| None => s
|
|
47
47
|
}
|
|
48
48
|
| Number({constraints: c}) =>
|