Skip to content

Commit 7aad407

Browse files
committed
Merge branch 'release/2.1.0'
2 parents 2f8dd9d + abe3c37 commit 7aad407

File tree

13 files changed

+173
-82
lines changed

13 files changed

+173
-82
lines changed

.babelrc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
{
2-
"presets": ["es2015"]
3-
}
2+
"presets": [
3+
["env", {
4+
"targets": {
5+
"node": 4
6+
}
7+
}]
8+
]
9+
}

.eslintrc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"extends": "eslint:recommended",
3+
"env": {
4+
"node": true,
5+
"es6": true
6+
},
7+
"parserOptions": {
8+
"ecmaVersion": 6,
9+
"sourceType": "module"
10+
},
11+
"rules": {
12+
"semi": 2
13+
}
14+
}

.jscsrc

Lines changed: 0 additions & 18 deletions
This file was deleted.

.jshintrc

Lines changed: 0 additions & 7 deletions
This file was deleted.

.travis.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ language: node_js
22
node_js:
33
- '4.2'
44
- '5'
5+
- '6'
6+
- '7'
57
env:
68
- CXX=g++-4.8
79
addons:
@@ -10,3 +12,13 @@ addons:
1012
- ubuntu-toolchain-r-test
1113
packages:
1214
- g++-4.8
15+
- unicode-data
16+
deploy:
17+
provider: npm
18+
email: jledentu@gmail.com
19+
api_key:
20+
secure: HaUooYs1t9OSYUD7sRkFm3uR307r+Ze0qx59E3tlBCp3Cm86yt1k3dRR7FqexDt6Gspn5wR1m59JfYtJ3a3137CryTCDjEGmBfpFBWb7+e7wg/NiSNVbyH+R8vk3kxEhv7Llzv8dKk/ZOiMyEMGyynd6GmUtAanmh2N/I/bEpq+KfVySdxFKBN+6iL0ppjB0Kq7TkYZ3IrGTkHH2BsAXZPinMFapeG1WVUkM3yrNmRZiaBRb5Kvxn74dz2BfoRybY9Am9oIgOZCjqmhio/rdTLSQ03/Hgs4zEkUKHbbDkNi9amqF1LR9TmA7a3Z9cnPtMX7kTo0N8iOml0G5qBdmdMJrqaeHU3n4DHV6PjUq18qJaJngdbAmPnr5YaUzZzzp3ESK/NlWv76O50WkLN2t5SzaS39a4kRzJfPKbJRjfrmak/AGUpYxKilhnbeGKWIEWhyQjUlA2ekUqChCDpsn8SHBZnZTvYf4tioYhN1kVNYY9EroygUAGgw3HigIgGK982hY55TVdTQO+3pl2LPwarqbQMqNHdAVnbiODKtr7wukieyuRo/lBMFj+aANqZdbw9VDdve1iTChvhDEHZyBl7IUJTWOp6ajzrKFmYSpNyFw5rSi9ur3k3knqAr3NqQlNHp6iBR+JwlGQPs/cqtUpyz5ZDFb5Asm1DEzms/uTlU=
21+
on:
22+
branch: master
23+
tags: true
24+
repo: jledentu/sails-hook-slugs

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Change Log
2+
3+
## [2.1.0] - 2017-03-29
4+
### Added
5+
Add property `blacklist` in `sails.config.slugs` and model attributes to exclude names from slugs.
6+
### Changed
7+
- Replace node-uuid by uuid
8+
- Remove require-all and Lodash dependencies
9+
- Replace JSCS + JSHint linters by ESLint
10+
11+
## [2.0.0] - 2017-03-19
12+
### Changed
13+
When a slug already exists, a dash is added between the slug and the UUID (thanks @thibaultboursier).
14+
15+
## [1.0.0] - 2015-12-06
16+
### Added
17+
Add configuration in `sails.config.slugs`:
18+
- `lowercase` (`boolean`) to lowercase slugs (defaults to `true`)
19+
### Changed
20+
Slugs are lowercased and not capitalized anymore by default.
21+
22+
## [0.2.6] - 2015-12-04
23+
### Fixed
24+
- Add `.npmignore`
25+
- Fix missing dependencies
26+
- Fix an issue with attribute property `from`
27+
28+
## [0.2.0] - 2015-12-03
29+
### Added
30+
Resolve slug conflicts by adding a UUID after a new slug if already exists
31+
32+
## [0.1.0] - 2015-11-30
33+
Initial version
34+
### Added
35+
- Slug generation
36+
- Base configuration

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# sails-hook-slugs
22

3-
[![Build Status](https://travis-ci.org/jledentu/sails-hook-slugs.svg?branch=master)](https://travis-ci.org/jledentu/sails-hook-slugs)
3+
[![Build Status](https://travis-ci.org/jledentu/sails-hook-slugs.svg?branch=master)](https://travis-ci.org/jledentu/sails-hook-slugs) [![dependencies Status](https://david-dm.org/jledentu/sails-hook-slugs/status.svg)](https://david-dm.org/jledentu/sails-hook-slugs) [![npm](https://img.shields.io/npm/v/sails-hook-slugs.svg)](https://www.npmjs.com/package/sails-hook-slugs)
44

55
This [Sails.js](https://github.com/balderdashy/sails) hook generates URL-friendly slugs in your models.
66

7+
```
8+
http://www.myblog.com/post/233987
9+
-> http://www.myblog.com/post/title-of-my-blog-post
10+
```
11+
712
## Installation
813

914
Add this hook to your Sails app:
@@ -32,7 +37,8 @@ module.exports = {
3237
},
3338
slug: {
3439
type: 'slug',
35-
from: 'title'
40+
from: 'title',
41+
blacklist: ['search']
3642
}
3743
}
3844
};
@@ -41,6 +47,7 @@ module.exports = {
4147
Configure your slug attribute:
4248

4349
* `from`: name of the attribute from which the slug will be defined (required)
50+
* `blacklist`: A list of reserved words to not use as this slug (optional)
4451

4552

4653
A `slug` attribute is automatically set when you create a record:
@@ -86,7 +93,8 @@ These parameters can be changed in `sails.config.slugs`:
8693
Parameter | Type | Details
8794
-------------- | ------------------- |:---------------------------------
8895
lowercase | `boolean` | Whether or not the generated slugs are lowercased. Defaults to `true`.
96+
blacklist | `Array<string>` | A list of reserved words to not use as slugs in your application. Defaults to `[]`.
8997

9098
## License
9199

92-
MIT © 2015 Jérémie Ledentu
100+
MIT © 2017 Jérémie Ledentu

api/models/Post.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ module.exports = {
2525
},
2626
slugAuthor: {
2727
type: 'slug',
28-
from: 'author'
28+
from: 'author',
29+
blacklist: ['profile']
2930
}
3031
}
3132
};

lib/index.js

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,61 @@
1-
import requireAll from 'require-all';
21
import slug from 'slug';
3-
import _ from 'lodash';
4-
import * as uuid from 'node-uuid';
2+
import uuid from 'uuid/v4';
53

64
function SlugsHook(sails) {
75

8-
function transformModels(models) {
9-
return _.chain(models)
10-
.mapValues((model, key) => {
11-
return _.defaults(model, {
12-
globalId: key,
13-
identity: key.toLowerCase()
14-
});
15-
})
16-
.mapKeys((model, key) => key.toLowerCase())
17-
.value();
18-
}
6+
/**
7+
* Indicate whether a given slug can be used as it is or not.
8+
*
9+
* @param {string} slugName Slug to check
10+
* @param {string} modelName Name of the model
11+
* @param {string} attributeName Attribute on which the slug is defined
12+
* @param {Array} blacklist List of names to not use
13+
* @returns {Promise}
14+
*/
15+
function slugCanBeUsed(slugName, modelName, attributeName, blacklist) {
16+
17+
return new Promise((resolve, reject) => {
18+
19+
if (sails.config.slugs.blacklist.indexOf(slugName) !== -1 ||
20+
(Array.isArray(blacklist) && blacklist.indexOf(slugName) !== -1)) {
21+
return resolve(false);
22+
}
1923

20-
function loadModels() {
21-
console.log('Loading Models...');
22-
try {
23-
let models = requireAll({
24-
dirname: __dirname + '/models',
25-
filter: /(.+)\.js$/
24+
let criteria = {};
25+
criteria[attributeName] = slugName;
26+
27+
sails.models[modelName].count(criteria)
28+
.then((found) => {
29+
resolve(!found);
30+
})
31+
.catch((err) => {
32+
reject(err);
2633
});
27-
28-
_.merge(sails.models || {}, transformModels(models));
29-
}
30-
catch (e) {
31-
console.log('No Models found');
32-
}
34+
});
3335
}
3436

3537
function patchModels() {
36-
_.forOwn(sails.models, function(model, modelName) {
3738

38-
_.forOwn(model.attributes, function(attr, name) {
39+
for (let modelName of Object.keys(sails.models)) {
40+
let model = sails.models[modelName];
41+
42+
for (let name of Object.keys(model.attributes)) {
43+
let attr = model.attributes[name];
3944
if (attr.type === 'slug' && attr.from) {
4045
attr.type = 'string';
4146

42-
model.beforeCreate = ((previousBeforeCreate, from) => function(values, cb) {
47+
model.beforeCreate = ((previousBeforeCreate, from, blacklist) => function(values, cb) {
4348

4449
let slugName = slug(values[from], {lower: sails.config.slugs.lowercase});
4550

46-
let criteria = {};
47-
criteria[name] = slugName;
48-
4951
// Check that slug is not already used
50-
sails.models[modelName].count(criteria)
51-
.then(function (found) {
52-
if (found) {
53-
values[name] = slugName + '-' + uuid.v4();
52+
slugCanBeUsed(slugName, modelName, name, blacklist)
53+
.then((ok) => {
54+
if (ok) {
55+
values[name] = slugName;
5456
}
5557
else {
56-
values[name] = slugName;
58+
values[name] = slugName + '-' + uuid();
5759
}
5860

5961
if (typeof previousBeforeCreate === 'function') {
@@ -65,26 +67,25 @@ function SlugsHook(sails) {
6567
})
6668
.catch(cb);
6769

68-
})(model.beforeCreate, attr.from);
70+
})(model.beforeCreate, attr.from, attr.blacklist);
6971

7072
delete attr.from;
7173
}
72-
});
73-
});
74+
}
75+
}
7476
}
7577

7678
return {
7779

7880
defaults: {
7981
__configKey__: {
80-
lowercase: true
82+
lowercase: true,
83+
blacklist: []
8184
}
8285
},
8386

8487
initialize: function(next) {
8588

86-
//loadModels();
87-
8889
sails.after(['hook:moduleloader:loaded'], function() {
8990

9091
patchModels();

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"name": "sails-hook-slugs",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"description": "A hook for Sails to handle slugs in your models.",
55
"main": "dist/lib/index.js",
66
"scripts": {
77
"babel": "babel lib --out-dir dist/lib",
88
"pretest": "npm run babel",
99
"test": "mocha test/bootstrap.test.js test/unit/*.test.js test/unit/**/*.test.js --compilers js:babel-core/register",
10-
"prepublish": "npm run babel"
10+
"prepublish": "npm run babel",
11+
"lint": "eslint lib"
1112
},
1213
"keywords": [
1314
"sails",
@@ -22,16 +23,15 @@
2223
"devDependencies": {
2324
"babel-cli": "^6.2.0",
2425
"babel-core": "^6.2.1",
25-
"babel-preset-es2015": "^6.1.18",
26+
"babel-preset-env": "^1.2.2",
27+
"eslint": "^3.18.0",
2628
"mocha": "^2.3.4",
2729
"sails": "^0.11.3",
2830
"sails-disk": "^0.10.8",
2931
"should": "^7.1.1"
3032
},
3133
"dependencies": {
32-
"lodash": "^3.10.1",
33-
"require-all": "^2.0.0",
3434
"slug": "^0.9.1",
35-
"node-uuid": "^1.4.7"
35+
"uuid": "^3.0.1"
3636
}
3737
}

0 commit comments

Comments
 (0)