From 4edd61a78e30c8bffdb33fba6198297a90180d96 Mon Sep 17 00:00:00 2001 From: sttk Date: Sat, 26 Mar 2022 17:31:20 +0900 Subject: [PATCH] Fix: Treats escaped enclosures as normal chars. --- index.js | 30 +++++++++++++++++++++++++++--- package.json | 1 + test/.gitkeep | 0 test/index.test.js | 34 +++++++++++++++++++++++++++++++--- 4 files changed, 59 insertions(+), 6 deletions(-) delete mode 100644 test/.gitkeep diff --git a/index.js b/index.js index 09dde64..a5acb73 100644 --- a/index.js +++ b/index.js @@ -53,12 +53,36 @@ function isEnclosure(str) { return false; } - var foundIndex = str.indexOf(enclosureStart); - if (foundIndex < 0) { + var enclosureIndex = str.length - 1; + var foundIndex = findLastNonBsCharFrom(str, enclosureIndex - 1); + if ((enclosureIndex - foundIndex) % 2 === 0) { + // Last enclosure is escaped. return false; } - return str.slice(foundIndex + 1, -1).includes(slash); + while (foundIndex >= 0) { + enclosureIndex = str.lastIndexOf(enclosureStart, foundIndex); + if (enclosureIndex < 0) { + return false; + } + + foundIndex = findLastNonBsCharFrom(str, enclosureIndex - 1); + if ((enclosureIndex - foundIndex) % 2 === 0) { + // Enclosure is escaped. + return false; + } + } + + return str.slice(enclosureIndex + 1, -1).includes(slash); +} + +function findLastNonBsCharFrom(str, startIndex) { + for (var i = startIndex; i >= 0; i--) { + if (str[i] !== '\\') { + return i; + } + } + return -1; } function isGlobby(str) { diff --git a/package.json b/package.json index baeab42..4705c95 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "devDependencies": { "eslint": "^7.0.0", "eslint-config-gulp": "^5.0.0", + "eslint-plugin-node": "^11.1.0", "expect": "^26.0.1", "mocha": "^7.1.2", "nyc": "^15.0.1" diff --git a/test/.gitkeep b/test/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/index.test.js b/test/index.test.js index 5889412..a16f522 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -112,12 +112,12 @@ describe('glob-parent', function () { expect(gp('/{,/,bar/baz,qux}/')).toEqual('/'); expect(gp('/\\{,/,bar/baz,qux}/')).toEqual('/{,/,bar/baz,qux}'); expect(gp('{,/,bar/baz,qux}')).toEqual('.'); - expect(gp('\\{,/,bar/baz,qux\\}')).toEqual('{,/,bar/baz,qux}'); + expect(gp('\\{,/,bar/baz,qux\\}')).toEqual('{,/,bar'); expect(gp('\\{,/,bar/baz,qux}/')).toEqual('{,/,bar/baz,qux}'); expect(gp('path/foo[a\\/]/')).toEqual('path'); expect(gp('path/foo\\[a\\/]/')).toEqual('path/foo[a\\/]'); expect(gp('foo[a\\/]')).toEqual('.'); - expect(gp('foo\\[a\\/]')).toEqual('foo[a\\/]'); + expect(gp('foo\\[a\\/]')).toEqual('foo[a\\'); expect(gp('path/(foo/bar|baz)')).toEqual('path'); expect(gp('path/(foo/bar|baz)/')).toEqual('path'); expect(gp('path/\\(foo/bar|baz)/')).toEqual('path/(foo/bar|baz)'); @@ -136,11 +136,39 @@ describe('glob-parent', function () { expect(gp('{../,./,{bar,/baz\\},qux\\}')).toEqual('.'); expect(gp('path/{,/,bar/{baz,qux\\}}/')).toEqual('path'); expect(gp('path/{,/,bar/{baz,qux}\\}/')).toEqual('path'); - // expect(gp('path/\\{../,./,{bar,/baz},qux}/')).toEqual('path'); + expect(gp('path/\\{../,./,{bar,/baz},qux}')).toEqual('path/{../,.'); + expect(gp('path/\\{../,./,{bar,/baz},qux}/')).toEqual('path/{../,.'); done(); }); + it('should treat escaped brackets as normal chars', function (done) { + if (isWin32) { + expect(gp('aaa\\}')).toEqual('aaa'); + expect(gp('\\{aaa/bbb\\}')).toEqual('{aaa'); + expect(gp('\\{\\{aaa/bbb\\}')).toEqual('{{aaa'); + expect(gp('{\\{aaa/bbb}')).toEqual('.'); + expect(gp('ccc/{\\{aaa/bbb}')).toEqual('ccc'); + expect(gp('ccc\\/\\{\\{aaa/bbb}')).toEqual('ccc\\/{{aaa'); + + var opts = { flipBackslashes: true }; + expect(gp('aaa\\}', opts)).toEqual('aaa'); + expect(gp('\\{aaa/bbb\\}', opts)).toEqual('{aaa'); + expect(gp('\\{\\{aaa/bbb\\}', opts)).toEqual('{{aaa'); + expect(gp('{\\{aaa/bbb}', opts)).toEqual('.'); + expect(gp('ccc/{\\{aaa/bbb}', opts)).toEqual('ccc'); + expect(gp('ccc\\/\\{\\{aaa/bbb}', opts)).toEqual('ccc\\/{{aaa'); + } else { + expect(gp('aaa\\}')).toEqual('.'); + expect(gp('\\{aaa/bbb\\}')).toEqual('{aaa'); + expect(gp('\\{\\{aaa/bbb\\}')).toEqual('{{aaa'); + expect(gp('{\\{aaa/bbb}')).toEqual('.'); + expect(gp('ccc/{\\{aaa/bbb}')).toEqual('ccc'); + expect(gp('ccc\\/\\{\\{aaa/bbb}')).toEqual('ccc\\/{{aaa'); + } + done(); + }); + it('should return parent dirname from non-glob paths', function (done) { expect(gp('path')).toEqual('.'); expect(gp('path/foo')).toEqual('path');