From 12585486c15f844f94ee92343420348931f16fe8 Mon Sep 17 00:00:00 2001 From: Takayuki Sato Date: Tue, 20 Jul 2021 15:09:21 +0900 Subject: [PATCH] Fix: Support single character extensions (Fixes #38) (#39) --- lib/extension.js | 45 ++++++++++--- package.json | 4 +- test/fixtures/test.s | 9 +++ test/index.js | 16 +++++ test/lib/extension.test.js | 127 +++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/test.s create mode 100644 test/lib/extension.test.js diff --git a/lib/extension.js b/lib/extension.js index 1ae0bb9..cc8070d 100644 --- a/lib/extension.js +++ b/lib/extension.js @@ -1,19 +1,44 @@ +'use strict'; + var path = require('path'); -var EXTRE = /\.[^.]*/g; -var LONGEXTRE = /^[.]?[^.]+([.].+[^.])$/; +function getLongExtension(basename) { + if (basename[basename.length - 1] === '.') { + return null; + } + + var startIndex = (basename[0] === '.') ? 1 : 0; + + var dotIndex = basename.indexOf('.', startIndex); + if (dotIndex <= startIndex) { + return null; + } + + return basename.slice(dotIndex); +} + +function getPossibleExtensions(longExtension) { + var arr = [longExtension]; + var len = longExtension.length; + var startIndex = 1; + + while (startIndex < len) { + var dotIndex = longExtension.indexOf('.', startIndex); + if (dotIndex < 0) { + break; + } + arr.push(longExtension.slice(dotIndex)); + startIndex = dotIndex + 1; + } + + return arr; +} module.exports = function(input) { var basename = path.basename(input); - var longExtension = LONGEXTRE.exec(basename); + var longExtension = getLongExtension(basename); if (!longExtension) { return; } - var possibleExtensions = longExtension[1].match(EXTRE); - if (!possibleExtensions) { - return; - } - return possibleExtensions.map(function(_, idx, exts) { - return exts.slice(idx).join(''); - }); + return getPossibleExtensions(longExtension); }; diff --git a/package.json b/package.json index a314a88..fd2d50d 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ "scripts": { "lint": "eslint .", "pretest": "rm -rf tmp/ && npm run lint", - "test": "mocha --async-only", - "cover": "istanbul cover _mocha --report lcovonly", + "test": "mocha --async-only test test/lib", + "cover": "istanbul cover _mocha --report lcovonly test test/lib", "coveralls": "npm run cover && istanbul-coveralls" }, "dependencies": { diff --git a/test/fixtures/test.s b/test/fixtures/test.s new file mode 100644 index 0000000..09ad00b --- /dev/null +++ b/test/fixtures/test.s @@ -0,0 +1,9 @@ +module.exports = { + data: { + trueKey: true, + falseKey: false, + subKey: { + subProp: 1 + } + } +}; diff --git a/test/index.js b/test/index.js index c6af716..a0a0f3c 100644 --- a/test/index.js +++ b/test/index.js @@ -252,6 +252,22 @@ describe('rechoir', function() { done(); }); + + it('should register a module loader even if the extension is single character (issue #38)', function(done) { + var fpath = path.join(__dirname, 'fixtures', 'test.s'); + rechoir.prepare({ + '.s': [ + 'nothere', + '../require-stub', + ], + }, fpath); + + expect(function() { + require(fpath); + }).toNotThrow(Error); + + done(); + }); }); }); diff --git a/test/lib/extension.test.js b/test/lib/extension.test.js new file mode 100644 index 0000000..2901f72 --- /dev/null +++ b/test/lib/extension.test.js @@ -0,0 +1,127 @@ +'use strict'; + +var expect = require('expect'); +var extension = require('../../lib/extension'); + +describe('Take out possible extensions from a file path', function() { + + it('should return an extension: ".js" from "app.js"', function(done) { + expect(extension('app.js')).toEqual('.js'); + expect(extension('a/b/c/app.js')).toEqual('.js'); + done(); + }); + + it('should return extensions: ".babel.js" and ".js" from "app.babel.js"', function(done) { + expect(extension('app.babel.js')).toEqual(['.babel.js', '.js']); + expect(extension('a/b/c/app.babel.js')).toEqual(['.babel.js', '.js']); + done(); + }); + + it('should return extensions: ".aaa.bbb.ccc", ".aaa.bbb" and ".ccc" from "app.aaa.bbb.ccc"', function(done) { + expect(extension('app.aaa.bbb.ccc')).toEqual(['.aaa.bbb.ccc', '.bbb.ccc', '.ccc']); + expect(extension('a/b/c/app.aaa.bbb.ccc')).toEqual(['.aaa.bbb.ccc', '.bbb.ccc', '.ccc']); + done(); + }); + + it('should return an extension: ".j" from "app.j"', function(done) { + expect(extension('app.j')).toEqual('.j'); + expect(extension('a/b/c/app.j')).toEqual('.j'); + done(); + }); + + it('should return extensions: ".b.j" and ".j" from "app.b.j"', function(done) { + expect(extension('app.b.j')).toEqual(['.b.j', '.j']); + expect(extension('a/b/c/app.b.j')).toEqual(['.b.j', '.j']); + done(); + }); + + it('should return extensions: ".a.b.c", ".a.b" and ".c" from "app.a.b.c"', function(done) { + expect(extension('app.a.b.c')).toEqual(['.a.b.c', '.b.c', '.c']); + expect(extension('a/b/c/app.a.b.c')).toEqual(['.a.b.c', '.b.c', '.c']); + done(); + }); + + it('should return undefined from "."', function(done) { + expect(extension('.')).toBe(undefined); + expect(extension('a/b/c/.')).toBe(undefined); + done(); + }); + + it('should return undefined from ".."', function(done) { + expect(extension('..')).toBe(undefined); + expect(extension('a/b/c/..')).toBe(undefined); + done(); + }); + + it('should return undefined from "..."', function(done) { + expect(extension('...')).toBe(undefined); + expect(extension('a/b/c/...')).toBe(undefined); + done(); + }); + + it('should return undefined from "a."', function(done) { + expect(extension('a.')).toBe(undefined); + expect(extension('a/b/c/a.')).toBe(undefined); + done(); + }); + + it('should return undefined from "app."', function(done) { + expect(extension('app.')).toBe(undefined); + expect(extension('a/b/c/app.')).toBe(undefined); + done(); + }); + + it('should return undefined from "a.b.c."', function(done) { + expect(extension('a.b.c.')).toBe(undefined); + expect(extension('a/b/c/a.b.c.')).toBe(undefined); + done(); + }); + + it('should return undefined from ".a"', function(done) { + expect(extension('.a')).toBe(undefined); + expect(extension('a/b/c/.a')).toBe(undefined); + done(); + }); + + it('should return undefined from ".app"', function(done) { + expect(extension('.app')).toBe(undefined); + expect(extension('a/b/c/.app')).toBe(undefined); + done(); + }); + + it('should return undefined from ".a."', function(done) { + expect(extension('.a.')).toBe(undefined); + expect(extension('a/b/c/.a.')).toBe(undefined); + done(); + }); + + it('should return undefined from ".app."', function(done) { + expect(extension('.app.')).toBe(undefined); + expect(extension('a/b/c/.app.')).toBe(undefined); + done(); + }); + + it('should return undefined from ".a.b.c."', function(done) { + expect(extension('.a.b.c.')).toBe(undefined); + expect(extension('a/b/c/.a.b.c.')).toBe(undefined); + done(); + }); + + it('should return ".b.c" and ".c" from ".a.b.c"', function(done) { + expect(extension('.a.b.c')).toEqual(['.b.c', '.c']); + expect(extension('a/b/c/.a.b.c')).toEqual(['.b.c', '.c']); + done(); + }); + + it('should return ".bb.cc" and ".cc" from ".aa.bb.cc"', function(done) { + expect(extension('.aa.bb.cc')).toEqual(['.bb.cc', '.cc']); + expect(extension('a/b/c/.aa.bb.cc')).toEqual(['.bb.cc', '.cc']); + done(); + }); + + it('should return "..b" and ".b" from ".a..b"', function(done) { + expect(extension('.a..b')).toEqual(['..b', '.b']); + expect(extension('a/b/c/.a..b')).toEqual(['..b', '.b']); + done(); + }); +});