From 6d1d16d5a76332ec2f9f9697f0897113f4ecdb6c Mon Sep 17 00:00:00 2001 From: Nathaniel Hunter <42shadow42@gmail.com> Date: Sun, 26 Jun 2022 13:32:53 -0500 Subject: [PATCH 1/7] Expanded whitespace test case to catch more inefficiences --- index.js | 8 ++++++-- test.js | 15 +++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index b3feb5a..7677265 100644 --- a/index.js +++ b/index.js @@ -38,11 +38,15 @@ export function trimLines(value) { */ function trimLine(value, start, end) { if (!start) { - value = value.replace(/^[ \t]+/, '') + const regex = /^[ \t]+/ + value = value.replace(regex, '') } if (!end) { - value = value.replace(/[ \t]+$/, '') + const regex = /[ \t]/ + let i = value.length + while (regex.test(value.charAt(--i))); + return value.slice(0, i + 1) } return value diff --git a/test.js b/test.js index ba1dd42..7c5a4d0 100644 --- a/test.js +++ b/test.js @@ -36,21 +36,28 @@ test('efficiency', (t) => { t.test('whitespace around line', (t) => { const timeoutId = setTimeout(() => { t.fail('did not pass in 10ms') - }, 10) + }, 20) t.deepEqual( trimLines( - 'a' + + whitespace + + '\n' + + whitespace + + 'a' + whitespace + '\n' + whitespace + 'b' + whitespace + + 'c' + + whitespace + '\n' + whitespace + - 'c' + 'd' + + whitespace + + '\n' ), - 'a\nb\nc' + '\na\nb' + whitespace + 'c\nd\n' ) setTimeout(() => { From 3dc039b26b52fe1661166314b0b7cd535e507bb4 Mon Sep 17 00:00:00 2001 From: Nathaniel Hunter <42shadow42@gmail.com> Date: Sun, 26 Jun 2022 13:43:30 -0500 Subject: [PATCH 2/7] Added more time, the CI environment appears to be less efficient --- test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.js b/test.js index 7c5a4d0..1ceac24 100644 --- a/test.js +++ b/test.js @@ -35,8 +35,8 @@ test('efficiency', (t) => { t.test('whitespace around line', (t) => { const timeoutId = setTimeout(() => { - t.fail('did not pass in 10ms') - }, 20) + t.fail('did not pass in 30ms') + }, 30) t.deepEqual( trimLines( From 6ec51517ca1291f896aecd2b00d828bc3b3277ec Mon Sep 17 00:00:00 2001 From: 42shadow42 <42shadow42@gmail.com> Date: Sun, 26 Jun 2022 14:00:57 -0500 Subject: [PATCH 3/7] Inlined regex --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index 7677265..949356e 100644 --- a/index.js +++ b/index.js @@ -38,8 +38,7 @@ export function trimLines(value) { */ function trimLine(value, start, end) { if (!start) { - const regex = /^[ \t]+/ - value = value.replace(regex, '') + value = value.replace( /^[ \t]+/, '') } if (!end) { From 04db121826e0e59628d8a9e4114d56ffdc3ce2cb Mon Sep 17 00:00:00 2001 From: 42shadow42 <42shadow42@gmail.com> Date: Sun, 26 Jun 2022 14:01:38 -0500 Subject: [PATCH 4/7] Removed extraneous space --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 949356e..861ee8d 100644 --- a/index.js +++ b/index.js @@ -38,7 +38,7 @@ export function trimLines(value) { */ function trimLine(value, start, end) { if (!start) { - value = value.replace( /^[ \t]+/, '') + value = value.replace(/^[ \t]+/, '') } if (!end) { From f1feb1281614b5110c29d0d4374421743c8728d2 Mon Sep 17 00:00:00 2001 From: Nathaniel Hunter <42shadow42@gmail.com> Date: Thu, 30 Jun 2022 20:35:15 -0500 Subject: [PATCH 5/7] Implemented leading trim without regex, separated test cases to be less nebulous --- index.js | 12 ++++++++---- test.js | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index 861ee8d..1404da8 100644 --- a/index.js +++ b/index.js @@ -42,10 +42,14 @@ function trimLine(value, start, end) { } if (!end) { - const regex = /[ \t]/ - let i = value.length - while (regex.test(value.charAt(--i))); - return value.slice(0, i + 1) + let endIndex = value.length - 1 + let char = value.charAt(endIndex) + while (char === ' ' || char === '\t') { + endIndex-- + char = value.charAt(endIndex) + } + + value = value.slice(0, endIndex + 1) } return value diff --git a/test.js b/test.js index 1ceac24..9c83b6a 100644 --- a/test.js +++ b/test.js @@ -33,31 +33,53 @@ test('efficiency', (t) => { }, 0) }) - t.test('whitespace around line', (t) => { + t.test('flanking whitespace', (t) => { + const timeoutId = setTimeout(() => { + t.fail('did not pass in 10ms') + }, 10) + + t.deepEqual(trimLines(whitespace + '\na\n' + whitespace), '\na\n') + + setTimeout(() => { + clearTimeout(timeoutId) + t.end() + }, 0) + }) + + t.test('internalized whitespace ', (t) => { const timeoutId = setTimeout(() => { t.fail('did not pass in 30ms') }, 30) + t.deepEqual( + trimLines('\na' + whitespace + 'b\n'), + '\na' + whitespace + 'b\n' + ) + + setTimeout(() => { + clearTimeout(timeoutId) + t.end() + }, 0) + }) + + t.test('whitespace around line', (t) => { + const timeoutId = setTimeout(() => { + t.fail('did not pass in 10ms') + }, 10) + t.deepEqual( trimLines( - whitespace + - '\n' + - whitespace + - 'a' + + 'a' + whitespace + '\n' + whitespace + 'b' + whitespace + - 'c' + - whitespace + '\n' + whitespace + - 'd' + - whitespace + - '\n' + 'c' ), - '\na\nb' + whitespace + 'c\nd\n' + 'a\nb\nc' ) setTimeout(() => { From 6c1773329555188e8eb6d4917933c39e7573d986 Mon Sep 17 00:00:00 2001 From: Nathaniel Hunter <42shadow42@gmail.com> Date: Sat, 2 Jul 2022 18:26:21 -0500 Subject: [PATCH 6/7] Reduce use of regex, use char codes over string characters --- index.js | 29 +++++++++++++++++------------ test.js | 19 ++++++++++++------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/index.js b/index.js index 1404da8..ce86562 100644 --- a/index.js +++ b/index.js @@ -17,7 +17,7 @@ export function trimLines(value) { while (match) { lines.push( - trimLine(source.slice(last, match.index), last === 0, false), + trimLine(source.slice(last, match.index), last !== 0, true), match[0] ) @@ -25,7 +25,7 @@ export function trimLines(value) { match = search.exec(source) } - lines.push(trimLine(source.slice(last), last === 0, true)) + lines.push(trimLine(source.slice(last), last !== 0, false)) return lines.join('') } @@ -37,20 +37,25 @@ export function trimLines(value) { * @returns {string} */ function trimLine(value, start, end) { - if (!start) { - value = value.replace(/^[ \t]+/, '') + let startIndex = 0 + let endIndex = value.length + if (start) { + let code = value.codePointAt(startIndex) + + while (code === 9 || code === 32) { + startIndex++ + code = value.codePointAt(startIndex) + } } - if (!end) { - let endIndex = value.length - 1 - let char = value.charAt(endIndex) - while (char === ' ' || char === '\t') { + if (end) { + let code = value.codePointAt(endIndex - 1) + + while (code === 9 || code === 32) { endIndex-- - char = value.charAt(endIndex) + code = value.codePointAt(endIndex - 1) } - - value = value.slice(0, endIndex + 1) } - return value + return endIndex > startIndex ? value.slice(startIndex, endIndex) : '' } diff --git a/test.js b/test.js index 9c83b6a..b1a4c29 100644 --- a/test.js +++ b/test.js @@ -14,6 +14,11 @@ test('trimLines(value)', function (t) { 'a\rb\r\nc\nd', 'should preseve line endings' ) + t.equal( + trimLines(' \n \n \n '), + '\n\n\n', + 'should handle complete empty space' + ) t.end() }) @@ -22,8 +27,8 @@ test('efficiency', (t) => { t.test('whitespace in line', (t) => { const timeoutId = setTimeout(() => { - t.fail('did not pass in 10ms') - }, 10) + t.fail('did not pass in 30ms') + }, 30) t.deepEqual(trimLines('a' + whitespace + 'b'), 'a' + whitespace + 'b') @@ -35,8 +40,8 @@ test('efficiency', (t) => { t.test('flanking whitespace', (t) => { const timeoutId = setTimeout(() => { - t.fail('did not pass in 10ms') - }, 10) + t.fail('did not pass in 30ms') + }, 30) t.deepEqual(trimLines(whitespace + '\na\n' + whitespace), '\na\n') @@ -46,7 +51,7 @@ test('efficiency', (t) => { }, 0) }) - t.test('internalized whitespace ', (t) => { + t.test('internalized whitespace', (t) => { const timeoutId = setTimeout(() => { t.fail('did not pass in 30ms') }, 30) @@ -64,8 +69,8 @@ test('efficiency', (t) => { t.test('whitespace around line', (t) => { const timeoutId = setTimeout(() => { - t.fail('did not pass in 10ms') - }, 10) + t.fail('did not pass in 30ms') + }, 30) t.deepEqual( trimLines( From 66fe8856866adc3e5e566031fd6a9b946e8341b2 Mon Sep 17 00:00:00 2001 From: Nathaniel Hunter <42shadow42@gmail.com> Date: Sat, 2 Jul 2022 18:40:10 -0500 Subject: [PATCH 7/7] Use constants to clarify character codes. --- index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index ce86562..c6e1c73 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,6 @@ +const SPACE = 32 +const TAB = 9 + /** * Remove initial and final spaces and tabs at the line breaks in `value`. * Does not trim initial and final spaces and tabs of the value itself. @@ -42,7 +45,7 @@ function trimLine(value, start, end) { if (start) { let code = value.codePointAt(startIndex) - while (code === 9 || code === 32) { + while (code === SPACE || code === TAB) { startIndex++ code = value.codePointAt(startIndex) } @@ -51,7 +54,7 @@ function trimLine(value, start, end) { if (end) { let code = value.codePointAt(endIndex - 1) - while (code === 9 || code === 32) { + while (code === SPACE || code === TAB) { endIndex-- code = value.codePointAt(endIndex - 1) }