From 5497dcdf1a1a9883e08de595ff503ba2821e148a Mon Sep 17 00:00:00 2001 From: sreelakshmi-bruno Date: Wed, 12 Nov 2025 11:30:27 +0530 Subject: [PATCH] decode forward slash --- src/index.js | 14 +++++++++++- tests/escaped.spec.js | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index fb72f44..d64ac96 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ /** * Pretty-prints a JSON-like string without parsing. * Fast path: chunked copying, fast string scan, lookahead for empty {} / []. + * Decodes \uXXXX unicode sequences and \/ forward slash escapes for readability. * * @param {string} input * @param {string} indent @@ -45,6 +46,7 @@ function fastJsonFormat(input, indent = ' ') { // Character codes const QUOTE = 34; // " const BACKSLASH = 92; // \ + const FORWARD_SLASH = 47;// / const OPEN_BRACE = 123; // { const CLOSE_BRACE = 125; // } const OPEN_BRACKET = 91; // [ @@ -97,7 +99,7 @@ function fastJsonFormat(input, indent = ' ') { }; // Scan a JSON string starting at index of opening quote `i` (s[i] === '"'). - // Returns index just after the closing quote and decodes \uXXXX sequences. + // Returns index just after the closing quote and decodes \uXXXX and \/ sequences. const scanString = (i) => { out.push('"'); // opening quote let j = i + 1; @@ -134,6 +136,16 @@ function fastJsonFormat(input, indent = ' ') { } // If parsing failed, reset and let it be copied as-is j = backslashPos + 1; + } else if (j < n && s.charCodeAt(j) === FORWARD_SLASH) { + // Found \/ - decode to / for readability + // Copy everything up to the backslash + if (backslashPos > lastCopy) { + out.push(s.slice(lastCopy, backslashPos)); + } + out.push('/'); + j++; // skip the forward slash + lastCopy = j; + continue; } // For other escapes (or invalid \u), just skip the escaped char if (j < n) j++; diff --git a/tests/escaped.spec.js b/tests/escaped.spec.js index 6aa70c8..a97b77c 100644 --- a/tests/escaped.spec.js +++ b/tests/escaped.spec.js @@ -66,4 +66,55 @@ describe('escaped characters', () => { }`; assertEqual(input, expected); }); +}); + +describe('forward slash escape sequences', () => { + it('should decode \\/ escape sequences to forward slashes', () => { + const input = '{"url":"https:\\/\\/example.com\\/api\\/v1"}'; + const expected = `{ + "url": "https://example.com/api/v1" +}`; + assertEqual(input, expected); + }); + + it('should handle unescaped forward slashes correctly', () => { + const input = '{"url":"https://example.com/api/v1"}'; + const expected = `{ + "url": "https://example.com/api/v1" +}`; + assertEqual(input, expected); + }); + + it('should handle forward slashes mixed with other escape sequences', () => { + const input = '{"text":"line1\\npath\\/to\\/file\\ttab","unicode":"\\u4e16\\u754c\\/path"}'; + const expected = `{ + "text": "line1\\npath/to/file\\ttab", + "unicode": "世界/path" +}`; + assertEqual(input, expected); + }); + + it('should handle a single escaped forward slash', () => { + const input = '{"slash":"\\/"}'; + const expected = `{ + "slash": "/" +}`; + assertEqual(input, expected); + }); + + it('should handle multiple consecutive escaped forward slashes', () => { + const input = '{"path":"\\/\\/network\\/share"}'; + const expected = `{ + "path": "//network/share" +}`; + assertEqual(input, expected); + }); + + it('should handle escaped forward slash at end of string', () => { + const input = '{"url":"https://example.com\\/"}'; + const expected = `{ + "url": "https://example.com/" +}`; + assertEqual(input, expected); + }); }); \ No newline at end of file