Skip to content

Commit

Permalink
Merge pull request #3 from dailyrandomphoto/custom-function
Browse files Browse the repository at this point in the history
feat: provide a custom function for path generation. (#1)(#2)
  • Loading branch information
dailyrandomphoto authored Oct 29, 2019
2 parents c38583d + 8c3cbd7 commit 6eaf457
Show file tree
Hide file tree
Showing 20 changed files with 416 additions and 42 deletions.
67 changes: 61 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,46 @@ INFO Created: ./source/_posts/ck20kqmij0001ieyn4es62xh7.md

The `title` argument can be omitted and its default value is `' '`.

You can define the default value of `title` via `unique_post_path` options in the `_config.yml` file.
You can define the default value of `title` in the `_config.yml` file.

```diff
#_cofig.yml

+ unique_post_path:
+ title_default: "new post"
```

You can define the path generating algorithm in the `_config.yml` file.
```diff
#_cofig.yml

unique_post_path:
title_default: "new post"
+ unique_post_path:
+ path_type: nanoid
+ size: 20
```

Available `path_type`:

path_type | length | character set |options | default | description
--- | --- | --- | --- | --- | ---
cuid (default) | 25 | `a-z0-9`, start with `c` | | | use [cuid()](https://github.com/ericelliott/cuid) generated string. <br>e.g. `ck2bi7fxf00013ryng5jr1rer`
cuid-slug | 7-10 | `a-z0-9` | | | use [cuid.slug()](https://github.com/ericelliott/cuid) generated string. <br>e.g. `xh23npi`
nanoid | 21 | `A-Za-z0-9_-` | size | 21 | use [nanoid()](https://github.com/ai/nanoid) generated string. <br>e.g. `EwUTt2eoka-oEV5kf-o0O`
nanoid-simple | 24 | `a-z0-9` | size | 24 | use [nanoid/generate](https://github.com/ai/nanoid) generated string. <br>e.g. `pfldm3gg8h9psydphotqe71d`
nanoid-lowercase | 26 | `a-z` | size | 26 | use [nanoid/generate](https://github.com/ai/nanoid) generated string. <br>e.g. `jsjxoibprplrdoitjmppotjrnm`

You can add your own path generating algorithm by define [Custom functions](#define-custom-functions).

If the layout is `page`, or if `--path, -p` or `--slug, -s` option is provided, `hexo new2` works same as `hexo new`.

### 2. Use `hexo new` command with `unique_post_path` configuration

Add `unique_post_path` options to the `_config.yml` file.
```
```diff
#_cofig.yml

unique_post_path:
auto: true
+ unique_post_path:
+ auto: true
```

Then use `new` command as before.
Expand All @@ -60,6 +83,38 @@ $ hexo new "My New Post"
INFO Created: ./source/_posts/ck20kqmij0001ieyn4es62xh7.md
```

## Define Custom Functions
Add a script file into the `scripts` folder of your hexo base directory.
e.g. scripts/my_custom_path.js

Then register a generator function.
The generator function should return a function that returns a string.
e.g.
```js
const register = require('hexo-unique-post-path').register;

register('my_custom_path', function(option) {
let size = option.size || 8;
let prefix = option.prefix || 'items-';
return function(title) {
return prefix + title.toLowerCase().replace(/[^\w]/g, '').substring(0, size);
};
});
```

```diff
#_cofig.yml

+ unique_post_path:
+ path_type: my_custom_path
+ prefix: articles-
```
```sh
$ hexo new2 "Hello World!"
=> articles-hellowor.md
```

## License
Copyright (c) 2019 dailyrandomphoto. Licensed under the [MIT license][license-url].

Expand Down
7 changes: 7 additions & 0 deletions lib/id-generators/cuid-slug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

const cuid = require('cuid');

module.exports = function(option) {
return () => cuid.slug();
};
7 changes: 7 additions & 0 deletions lib/id-generators/cuid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

const cuid = require('cuid');

module.exports = function(option) {
return cuid;
};
24 changes: 24 additions & 0 deletions lib/id-generators/id-generators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

const store = {};

function register(type, fn) {
if (typeof fn !== 'function') throw new TypeError('fn must be a function');
if (typeof store[type] === 'function') throw new TypeError('already registered as type: ' + type);
store[type] = fn;
}

function get(type) {
return store[type] || defaultFn(type);
}

function defaultFn(type) {
return function() {
throw new TypeError('can\'t find generator with type: ' + type);
};
}

module.exports = {
register,
get
};
15 changes: 15 additions & 0 deletions lib/id-generators/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

const generators = require('./id-generators');
const cuid = require('./cuid');

generators.register('default', cuid);
generators.register('cuid', cuid);
generators.register('cuid-slug', require('./cuid-slug'));
generators.register('nanoid', require('./nanoid'));
generators.register('nanoid-simple', require('./nanoid-simple'));
generators.register('nanoid-lowercase', require('./nanoid-lowercase'));
generators.register('seq', require('./seq'));
generators.register('prefix-seq', require('./prefix-seq'));

module.exports = generators;
12 changes: 12 additions & 0 deletions lib/id-generators/nanoid-lowercase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

/**
* https://github.com/ai/nanoid
*/
const generate = require('nanoid/generate');
const alphabet = 'abcdefghijklmnopqrstuvwxyz';

module.exports = function(option) {
let size = option.size || 26;
return () => generate(alphabet, size);
};
12 changes: 12 additions & 0 deletions lib/id-generators/nanoid-simple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

/**
* https://github.com/ai/nanoid
*/
const generate = require('nanoid/generate');
const alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';

module.exports = function(option) {
let size = option.size || 24;
return () => generate(alphabet, size);
};
11 changes: 11 additions & 0 deletions lib/id-generators/nanoid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

/**
* https://github.com/ai/nanoid
*/
const nanoid = require('nanoid');

module.exports = function(option) {
let size = option.size || 21;
return () => nanoid(size);
};
8 changes: 8 additions & 0 deletions lib/id-generators/prefix-seq.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

module.exports = function(option) {
option = option || {};
let start = typeof option.start !== 'undefined' ? option.start : 1;
let prefix = typeof option.prefix !== 'undefined' ? option.prefix : 'prefix-';
return () => prefix + start++;
};
7 changes: 7 additions & 0 deletions lib/id-generators/seq.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = function(option) {
option = option || {};
let start = typeof option.start !== 'undefined' ? option.start : 1;
return () => '' + start++;
};
54 changes: 31 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
'use strict';
const generators = require('./id-generators');

(function(ctx) {
const { config, extend } = ctx;
const { console, filter } = extend;
const myconfig = Object.assign({
auto: false,
title_default: ' '
}, config.unique_post_path);
if (typeof hexo !== 'undefined') {
(function(ctx) {
const { config, extend } = ctx;
const { console, filter } = extend;
const myconfig = Object.assign({
auto: false,
title_default: ' ',
path_type: 'default'
}, config.unique_post_path);

console.register('new2', 'Create a new post with a auto generated unique path.', {
usage: '[layout] [title]',
arguments: [
{name: 'layout', desc: 'Post layout. Use post, page, draft or whatever you want.'},
{name: 'title', desc: 'Post title. Wrap it with quotations to escape.'}
],
options: [
{name: '-r, --replace', desc: 'Replace the current post if existed.'},
{name: '-s, --slug', desc: 'Post slug. Customize the URL of the post.'}
]
}, require('./new2')(myconfig));
console.register('new2', 'Create a new post with a auto generated unique path.', {
usage: '[layout] [title]',
arguments: [
{name: 'layout', desc: 'Post layout. Use post, page, draft or whatever you want.'},
{name: 'title', desc: 'Post title. Wrap it with quotations to escape.'}
],
options: [
{name: '-r, --replace', desc: 'Replace the current post if existed.'},
{name: '-s, --slug', desc: 'Post slug. Customize the URL of the post.'}
]
}, require('./new2')(myconfig));

if (myconfig.auto) {
// register a filter with highest priority.
filter.register('new_post_path', require('./unique_post_path_filter'), 1);
}
if (myconfig.auto) {
// register a filter with highest priority.
filter.register('new_post_path', require('./unique_post_path_filter')(myconfig), 1);
}

}(hexo));
}(hexo));
}

module.exports = {
register: generators.register
};
19 changes: 12 additions & 7 deletions lib/new2.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const tildify = require('tildify'); // eslint-disable-line node/no-missing-require,node/no-extraneous-require
const chalk = require('chalk'); // eslint-disable-line node/no-missing-require,node/no-extraneous-require
const cuid = require('cuid');
const generators = require('./id-generators');

const reservedKeys = {
_: true,
Expand All @@ -19,20 +19,25 @@ const reservedKeys = {
};

module.exports = function(config) {

return function newConsole(args) {
// Display help message if user didn't input any arguments
// if (!args._.length) {
// return this.call('help', {_: ['new2']});
// }
const generator = generators.get(config.path_type || 'default');
const generate = generator(config);
// Display help message if user didn't input any arguments
// if (!args._.length) {
// return this.call('help', {_: ['new2']});
// }

const data = {
title: args._.pop() || config.title_default,
layout: args._.length ? args._[0] : this.config.default_layout,
slug: args.s || args.slug,
path: cuid()
path: args.p || args.path
};

if (data.layout !== 'page' && (!data.slug || !data.slug.trim())) {
data.slug = generate(data.title);
}

const keys = Object.keys(args);

for (let i = 0, len = keys.length; i < len; i++) {
Expand Down
16 changes: 11 additions & 5 deletions lib/unique_post_path_filter.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
'use strict';

const cuid = require('cuid');
const generators = require('./id-generators');

module.exports = function(data, replace) {
// set path value as a value of cuid.
data.path = cuid();
return data;
module.exports = function(config) {
return function(data, replace) {
const generator = generators.get(config.path_type || 'default');
const generate = generator(config);
// generate a unique path.
if (data.layout !== 'page') {
data.slug = generate(data.title);
}
return data;
};
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hexo-unique-post-path",
"version": "0.0.1",
"version": "0.0.2",
"description": "This plug-in helps Hexo create new posts with unique auto-generated paths.",
"main": "lib/index.js",
"scripts": {
Expand All @@ -11,6 +11,7 @@
"dependencies": {
"chalk": "^2.4.2",
"cuid": "^2.1.6",
"nanoid": "^2.1.6",
"tildify": "^2.0.0"
},
"devDependencies": {
Expand Down
14 changes: 14 additions & 0 deletions test/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "hexo/test",
"env": {
"es6": true
},
"globals": {
"should": true
},
"rules": {
"node/no-unpublished-require": ["error", {
"allowModules": ["cheerio", "hexo"]
}]
}
}
Loading

0 comments on commit 6eaf457

Please sign in to comment.