Skip to content

Commit

Permalink
feat: joinPath()
Browse files Browse the repository at this point in the history
  • Loading branch information
curbengh committed Aug 17, 2020
1 parent b34456a commit c1295d6
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Utilities for [Hexo].
- [hash](#hashstr)
- [highlight](#highlightstr-options)
- [htmlTag](#htmltagtag-attrs-text-escape)
- [joinPath](#joinpathpaths-option)
- [isExternalLink](#isexternallinkurl-sitehost-exclude)
- [Pattern](#patternrule)
- [Permalink](#permalinkrule-options)
Expand Down Expand Up @@ -324,6 +325,51 @@ htmlTag('script', {src: '/foo.js', async: true}, '')
// <script src="/foo.js" async></script>
```

### joinPath([...paths][, option])

Join and format paths.

Option | Description | Default
--- | --- | ---
`sep` | Path separator | [`path.sep`](https://nodejs.org/api/path.html#path_path_sep)

``` js
joinPath('foo/bar\\baz')
// Windows: foo\bar\baz
// Unix: foo/bar/baz

joinPath('foo/bar/baz', 'lorem\\ipsum\\dolor')
// Windows: foo\bar\baz\lorem\ipsum\dolor
// Unix: foo/bar/baz/lorem/ipsum/dolor

joinPath('foo/bar/baz', 'lorem\\ipsum\\dolor', { sep: '/' })
// foo/bar/baz/lorem/ipsum/dolor

joinPath('foo/', '/bar', '/baz')
// Windows: foo\bar\baz
// Unix: foo/bar/baz

/* If the joined path string is a zero-length string, then '.' will be returned,
representing the current working directory. */
joinPath()
// .

joinPath('')
// .
```

Platform-specific separator also can be used:

``` js
const { sep } = require('path').win32
joinPath('foo/', '/bar', '/baz', { sep })
// foo\bar\baz

const { sep } = require('path').posix
joinPath('foo/', '/bar', '/baz', { sep })
// foo/bar/baz
```

### isExternalLink(url, sitehost, [exclude])

Option | Description | Default
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exports.HashStream = hash.HashStream;
exports.highlight = require('./highlight');
exports.htmlTag = require('./html_tag');
exports.isExternalLink = require('./is_external_link');
exports.joinPath = require('./join_path');
exports.Pattern = require('./pattern');
exports.Permalink = require('./permalink');
exports.prettyUrls = require('./pretty_urls');
Expand Down
26 changes: 26 additions & 0 deletions lib/join_path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const { sep: sepPlatform } = require('path');

const formatPath = (str, sep) => {
const rDedup = new RegExp('\\' + sep + '{2,}', 'g');
return str.replace(/\/|\\/g, sep).replace(rDedup, sep);
};

const joinPath = (...args) => {
const argsSize = args.length;

// defaults to platform-specific path separator
let sep = sepPlatform;
if (typeof args[argsSize - 1] === 'object') sep = args.pop().sep;

const result = args.join(sep);

// Similar behaviour as path.join()
// https://nodejs.org/api/path.html#path_path_join_paths
if (result.length === 0) return '.';

return formatPath(result, sep);
};

module.exports = joinPath;
64 changes: 64 additions & 0 deletions test/join_path.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict';

require('chai').should();
const { sep } = require('path');
const join = require('../lib/join_path');

describe('joinPath', () => {
it('one path', () => {
const content = 'foo/bar';
join(content).should.eql('foo' + sep + 'bar');
});

it('no argument', () => {
join().should.eql('.');
});

it('zero-length string', () => {
join('').should.eql('.');
});

it('two paths', () => {
join('foo', 'bar').should.eql('foo' + sep + 'bar');
});

it('one path - custom separator', () => {
const custom = '\\';
join('foo/bar', { sep: custom }).should.eql('foo' + custom + 'bar');
});

it('two paths - custom separator', () => {
const custom = '\\';
join('foo', 'bar', { sep: custom }).should.eql('foo' + custom + 'bar');
});

it('deduplicate separators', () => {
join('foo/', '/bar').should.eql('foo' + sep + 'bar');
});

it('starting and ending slashes', () => {
join('/foo/', '/bar/').should.eql(sep + 'foo' + sep + 'bar' + sep);
});

it('mixed slashes', () => {
join('foo/', '\\bar').should.eql('foo' + sep + 'bar');
});

it('mixed and >2 slashes', () => {
join('foo////', '\\\\bar').should.eql('foo' + sep + 'bar');
});

it('mixed and >2 slashes - custom separator', () => {
const custom = '\\';
join('foo////', '\\\\bar', { sep: custom }).should.eql('foo' + custom + 'bar');
});

it('three paths', () => {
join('foo', 'bar', 'baz').should.eql('foo' + sep + 'bar' + sep + 'baz');
});

it('three paths - custom separator', () => {
const custom = '\\';
join('foo', 'bar', 'baz', { sep: custom }).should.eql('foo' + custom + 'bar' + custom + 'baz');
});
});

0 comments on commit c1295d6

Please sign in to comment.