Skip to content

Commit 30ce238

Browse files
committed
Enhance path handling in SnapshotBuilder: protect JSON escape sequences before replacing backslashes and restore them afterward.
1 parent 7943149 commit 30ce238

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

src/Confix.Tool/test/Confix.Tool.Tests/TestHelpers/SnapshotBuilder.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,17 @@ public void MatchSnapshot()
5050
.Aggregate(content, (current, processor) => processor(current));
5151

5252
// Normalize Windows path separators to forward slashes for consistent cross-platform snapshots.
53-
// Use regex to replace backslashes that are NOT JSON escape sequences.
54-
// JSON escapes are: \", \/, \b, \f, \n, \r, \t, \uXXXX
55-
// We replace any \ that is NOT followed by one of: " / b f n r t u
56-
// Note: We intentionally don't exclude \\ because double backslashes in paths should become /
57-
content = BackslashNotJsonEscapeRegex().Replace(content, "/");
53+
// Use regex to protect JSON escape sequences (which are NOT followed by word characters),
54+
// then replace all backslashes, then restore the protected sequences.
55+
56+
// Protect JSON escapes that are NOT followed by word characters (to distinguish \t from \test)
57+
content = JsonEscapeNotInPathRegex().Replace(content, "\x00$1");
58+
59+
// Replace all remaining backslashes with forward slashes
60+
content = content.Replace("\\", "/");
61+
62+
// Restore protected JSON escapes
63+
content = content.Replace("\x00", "\\");
5864

5965
// Collapse multiple forward slashes to single (but preserve :// for URLs)
6066
content = MultipleSlashesRegex().Replace(content, "/");
@@ -63,12 +69,11 @@ public void MatchSnapshot()
6369
}
6470

6571
/// <summary>
66-
/// Matches a backslash that is NOT followed by a JSON escape character (excluding \\).
67-
/// This allows us to replace path separators while preserving JSON escapes.
68-
/// Double backslashes (\\) are treated as path separators and will be converted.
72+
/// Matches JSON escape sequences that are NOT followed by word characters.
73+
/// This distinguishes real JSON escapes (\t, \n, etc.) from paths (\test, \new, etc.)
6974
/// </summary>
70-
[GeneratedRegex(@"\\(?![""\/bfnrtu])")]
71-
private static partial Regex BackslashNotJsonEscapeRegex();
75+
[GeneratedRegex(@"\\([""\/bfnrt](?![a-zA-Z0-9_])|u[0-9a-fA-F]{4})")]
76+
private static partial Regex JsonEscapeNotInPathRegex();
7277

7378
/// <summary>
7479
/// Matches two or more consecutive forward slashes that are NOT preceded by a colon (to preserve URLs like https://).

0 commit comments

Comments
 (0)