permalinks
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -5,3 +5,3 @@ # {%= name %} {%= badge("fury") %} | ||
See Assemble's [permalinks middleware](https://github.com/assemble/assemble-middleware-permalinks) for an implementation example. | ||
For an implementation example, see Assemble's [permalinks middleware](https://github.com/assemble/assemble-middleware-permalinks). | ||
@@ -8,0 +8,0 @@ ## Table of Contents |
{ | ||
"name": "permalinks", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"main": [ | ||
@@ -5,0 +5,0 @@ "index.js" |
@@ -1,2 +0,2 @@ | ||
Adding patterns is easy, just add a `patterns: []` property to the `permalinks` option, then add any number of patterns to the array. For example, let's say we want to add the `:project` variable to our permalinks: | ||
Adding patterns is easy, just add a `replacements: []` property to the `permalinks` option, then add any number of patterns to the array. For example, let's say we want to add the `:project` variable to our permalinks: | ||
@@ -3,0 +3,0 @@ ```js |
@@ -7,3 +7,3 @@ ## Recommendations | ||
### Avoid date-based permalinks | ||
Yep, that's what I said. There are plenty of valid use cases for using date-based URL's. This plugin offers a number of date-based patterns, and we leverage [Moment.js][moment] a lot. Still, I recommend that you avoid using a date-based permalink structure for your blog or documentation, because there is a good chance it will do more harm than good over the long term. | ||
Yep, that's what I said. There are plenty of valid use cases for using date-based URL's. This plugin offers a number of date-based replacement patterns, and we leverage [Moment.js][moment] a lot. Still, I recommend that you avoid using a date-based permalink structure for your blog or documentation, because there is a good chance it will do more harm than good over the long term. | ||
@@ -35,20 +35,19 @@ Date-based URL's tend to _decrease click through rates_ on older articles. Think about it, who prefers reading out of date content? So use a URL strategy that doesn't go out of its way to emphasize the date, and you'l keep your posts feeling like fresh content. | ||
```js | ||
var pkg = require('./package.json'); | ||
var _str = require('underscore.string'); | ||
_.mixin(_.str.exports()); | ||
assemble: { | ||
options: { | ||
permalinks: { | ||
structure: ':author:ext', | ||
patterns: [ | ||
{ | ||
pattern: ':author', | ||
replacement: '<%= _str.slugify(pkg.author.name) %>' | ||
} | ||
] | ||
} | ||
}, | ||
files: {}, | ||
... | ||
options: { | ||
permalinks: { | ||
structure: ':author:ext', | ||
replacements: [ | ||
{ | ||
pattern: ':author', | ||
replacement: '<%= _str.slugify(pkg.author.name) %>' | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
[moment]: http://momentjs.com/ "Moment.js Permalinks" |
129
index.js
@@ -1,11 +0,11 @@ | ||
/** | ||
* permalinks <https://github.com/assemble/permalinks> | ||
* | ||
* Copyright (c) 2014, Jon Schlinkert, Brian Woodward, contributors. | ||
* Licensed under the MIT License | ||
* | ||
*/ | ||
/*! | ||
* permalinks <https://github.com/assemble/permalinks> | ||
* | ||
* Copyright (c) 2014, Jon Schlinkert, Brian Woodward, contributors. | ||
* Licensed under the MIT License | ||
* | ||
*/ | ||
var path = require('path'); | ||
var strings = require('strings'); | ||
var Strings = require('strings'); | ||
var digits = require('digits'); | ||
@@ -17,3 +17,9 @@ var randomatic = require('randomatic'); | ||
module.exports = function(structure, context, options) { | ||
var join = function() { | ||
var filepath = path.join.apply(path, arguments); | ||
return filepath.replace(/\\/g, '/'); | ||
}; | ||
module.exports = function Permalinks(structure, context, options) { | ||
var args = arguments; | ||
@@ -30,26 +36,39 @@ | ||
} | ||
options = options || {}; | ||
// strings middleware, normalizes patterns to return a generic key/value object | ||
var normalize = function (patterns) { | ||
return function () { | ||
return _.map(patterns, function (pattern) { | ||
return new strings.Pattern(pattern.pattern, pattern.replacement); | ||
}); | ||
}; | ||
}; | ||
var permalinks = new Strings(context); | ||
// Allow user-defined length to be provided (for array of files) | ||
var len = options.length || 3; | ||
var l = options.length || 3; | ||
var i = options.index || 0; | ||
var specialPatterns = { | ||
num: new strings.Pattern(/:\bnum\b/, digits.pad(i, {auto: len})), | ||
digits: new strings.Pattern(/:(0)+/, function (match) { | ||
var matchLen = String(match).length - 1; | ||
return digits.pad(i, {digits: matchLen}); | ||
}), | ||
random: new strings.Pattern(/:random\(([^)]+)\)/, function (a, b) { | ||
permalinks.parser('custom', options.replacements); | ||
permalinks.parser('path', [ | ||
{ | ||
pattern: /:basename/, | ||
replacement: function() { | ||
return this.basename; | ||
} | ||
}, | ||
{ | ||
pattern: /:dirname/, | ||
replacement: function() { | ||
return this.dirname; | ||
} | ||
}, | ||
{ | ||
pattern: /:extname|:ext/, | ||
replacement: function(pattern) { | ||
return this.extname || this.ext; | ||
} | ||
} | ||
]); | ||
permalinks.parser('date', require('strings-parser-date')()); | ||
permalinks.parser('random', { | ||
pattern: /:random\(([^)]+)\)/, | ||
replacement: function (a, b, c) { | ||
var len, chars; | ||
@@ -64,32 +83,44 @@ if(b.match(/,/)) { | ||
} | ||
}) | ||
}; | ||
} | ||
}); | ||
// register the replacements as middleware | ||
strings | ||
.use(specialPatterns) // specialPatterns | ||
.use(context) // expose context data to Strings | ||
.use(strings.dates(context.date, _.pick(options, 'lang'))) // date patterns | ||
.use(normalize(options.replacements || [])); // wrap any additional replacement patterns | ||
permalinks.parser('digits', { | ||
pattern: /:(0)+/, | ||
replacement: function (match) { | ||
var matchLen = String(match).length - 1; | ||
return digits.pad(i, {digits: matchLen}); | ||
} | ||
}); | ||
permalinks.parser('num', { | ||
pattern: /:\bnum\b/, | ||
replacement: digits.pad(i, {auto: l}) | ||
}); | ||
// Presets: pre-formatted permalink structures. If a preset | ||
// is defined, append it to the user-defined structure. | ||
permalinks.parser('prop', { | ||
pattern: /:(\w+)/g, | ||
replacement: function(match, prop) { | ||
return this[prop] || prop; | ||
} | ||
}); | ||
// Presets: pre-formatted permalink propstrings. If a preset is specified | ||
// in the options, append it to the user-defined propstring. | ||
permalinks.propstring('numbered', join((structure || ''), ':num-:basename:ext')); | ||
permalinks.propstring('pretty', join((structure || ''), ':basename/index:ext')); | ||
permalinks.propstring('dayname', join((structure || ''), ':YYYY/:MM/:DD/:basename/index:ext')); | ||
permalinks.propstring('monthname', join((structure || ''), ':YYYY/:MM/:basename/index:ext')); | ||
if(options.preset && String(options.preset).length !== 0) { | ||
// The preset | ||
var presets = { | ||
numbered: path.join((structure || ''), ':num-:basename:ext'), | ||
pretty: path.join((structure || ''), ':basename/index:ext'), | ||
dayname: path.join((structure || ''), ':YYYY/:MM/:DD/:basename/index:ext'), | ||
monthname: path.join((structure || ''), ':YYYY/:MM/:basename/index:ext') | ||
}; | ||
// Presets are joined to structures, so if a preset is specified | ||
// use the preset the new structure. | ||
structure = String(_.values(_.pick(presets, options.preset))); | ||
// Presets are joined to propstrings, so if a preset is | ||
// specified use the preset the new propstring. | ||
structure = permalinks.propstring(options.preset); | ||
} | ||
var parsers = Object.keys(permalinks._parsers); | ||
var permalink = strings.run(structure).replace(/\\/g, '/'); | ||
return permalink; | ||
// Process replacement patterns | ||
return permalinks.process(structure, parsers, context); | ||
} |
{ | ||
"name": "permalinks", | ||
"description": "Adds URL routing or permalinks functionality to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to do path transformation or prop-string replacements.", | ||
"version": "0.2.1", | ||
"description": "Adds permalink or URL routing/URL rewriting logic to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to do path transformation or prop-string replacements.", | ||
"version": "0.3.0", | ||
"homepage": "https://github.com/jonschlinkert/permalinks", | ||
@@ -24,12 +24,19 @@ "author": { | ||
"keywords": [ | ||
"blog entry", | ||
"blog post", | ||
"filepath", | ||
"link", | ||
"path", | ||
"permalinks", | ||
"url", | ||
"uri", | ||
"permanent link", | ||
"rewrite", | ||
"rewriting", | ||
"route", | ||
"routes", | ||
"routing", | ||
"url-routing", | ||
"path", | ||
"filepath", | ||
"path transformation" | ||
"transformation", | ||
"uri", | ||
"URL rewriting", | ||
"url", | ||
"url-routing" | ||
], | ||
@@ -51,6 +58,9 @@ "main": "index.js", | ||
"lodash": "~2.4.1", | ||
"randomatic": "~0.1.0", | ||
"strings": "~0.2.1", | ||
"parse-filepath": "^0.2.1", | ||
"randomatic": "^0.1.4", | ||
"strings": "^0.3.3", | ||
"strings-parser-date": "^0.1.0", | ||
"strings-parser-url": "^0.1.0", | ||
"underscore.string": "~2.3.3" | ||
} | ||
} |
# permalinks [![NPM version](https://badge.fury.io/js/permalinks.png)](http://badge.fury.io/js/permalinks) | ||
> Adds URL routing or permalinks functionality to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to do path transformation or prop-string replacements. | ||
> Adds permalink or URL routing/URL rewriting logic to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to do path transformation or prop-string replacements. | ||
See Assemble's [permalinks middleware](https://github.com/assemble/assemble-middleware-permalinks) for an implementation example. | ||
For an implementation example, see Assemble's [permalinks middleware](https://github.com/assemble/assemble-middleware-permalinks). | ||
@@ -141,3 +141,3 @@ ## Table of Contents | ||
### Custom replacement patterns | ||
Adding patterns is easy, just add a `patterns: []` property to the `permalinks` option, then add any number of patterns to the array. For example, let's say we want to add the `:project` variable to our permalinks: | ||
Adding patterns is easy, just add a `replacements: []` property to the `permalinks` option, then add any number of patterns to the array. For example, let's say we want to add the `:project` variable to our permalinks: | ||
@@ -144,0 +144,0 @@ ```js |
@@ -10,4 +10,66 @@ /** | ||
var expect = require('chai').expect; | ||
var Strings = require('strings'); | ||
var permalinks = require('../'); | ||
// Custom function for task assemble:filename_replacement | ||
var toPostName = function(str) { | ||
var path = require('path'); | ||
var name = path.basename(str, path.extname(str)); | ||
var re = /\d{4}-\d{2}-\d{2}-(.+)/; | ||
// $1 = yyyy, $2 = mm, $3 = dd, $4 = basename | ||
return name.replace(re, '$1'); | ||
}; | ||
// Custom function for task assemble:filename_replacement | ||
var toDateFolders = function(str) { | ||
var path = require('path'); | ||
var name = path.basename(str, path.extname(str)); | ||
var re = /(\d{4})-(\d{2})-(\d{2})-(.+)/; | ||
// $1 = yyyy, $2 = mm, $3 = dd, $4 = basename | ||
return name.replace(re, function(str, yr, mo, day, basename) { | ||
return yr + '/' + mo + '/' + day + '/' + basename; | ||
}); | ||
}; | ||
describe('custom replacement patterns:', function() { | ||
describe('paths', function() { | ||
var opts = { | ||
replacements: [{ | ||
pattern: ':post', | ||
replacement: function(src) { | ||
return toPostName(this.src); | ||
} | ||
}] | ||
}; | ||
it('should replace :basename', function() { | ||
var obj = {src: 'test/fixtures/posts/2014-12-31-last-year.md'}; | ||
var expected = 'last-year/index.html'; | ||
var actual = permalinks(':post/index.html', obj, opts); | ||
expect(actual).to.eql(expected); | ||
}); | ||
}); | ||
}); | ||
describe('custom replacement patterns:', function() { | ||
describe('paths', function() { | ||
var opts = { | ||
replacements: [{ | ||
pattern: ':post', | ||
replacement: function(src) { | ||
return toDateFolders(this.src); | ||
} | ||
}] | ||
}; | ||
it('should replace :basename', function() { | ||
var obj = {src: 'test/fixtures/posts/2014-12-31-last-year.md', destBase: 'blog'}; | ||
var expected = 'blog/2014/12/31/last-year/index.html'; | ||
var actual = permalinks(':destBase/:post/index.html', obj, opts); | ||
expect(actual).to.eql(expected); | ||
}); | ||
}); | ||
}); | ||
describe('permalinks:', function() { | ||
@@ -36,7 +98,7 @@ describe('paths', function() { | ||
it('should replace :basename', function() { | ||
var obj = {basename: 'foo', ext: '.html'}; | ||
var context = {basename: 'foo', ext: '.html'}; | ||
var options = { | ||
replacements: [ | ||
{ | ||
pattern: ':project', | ||
pattern: /:project/, | ||
replacement: require('../package.json').name | ||
@@ -47,3 +109,4 @@ } | ||
var expected = 'permalinks/foo/index.html'; | ||
var actual = permalinks(':project/:basename/index:ext', obj, options); | ||
var actual = permalinks(':project/:basename/index:ext', context, options); | ||
expect(actual).to.eql(expected); | ||
@@ -71,2 +134,3 @@ }); | ||
}); | ||
it('should foo', function() { | ||
@@ -146,3 +210,4 @@ var obj = {basename: 'foo', ext: ''}; | ||
var actual = permalinks(':YYYY/:MM/:DD/:basename/index:ext', obj); | ||
expect(actual).to.equal(expected); | ||
expect(actual.split('/')).to.have.length.above(4); | ||
expect(actual.split('/')[0]).to.equal(String(new Date().getFullYear())); | ||
}); | ||
@@ -157,9 +222,9 @@ | ||
it('should foo', function() { | ||
it('should parse the path using a date', function() { | ||
var obj = {basename: 'foo', ext: ''}; | ||
var expected = '2014/04/29'; | ||
var actual = permalinks(':YYYY/:MM/:DD', obj); | ||
expect(actual).to.equal(expected); | ||
expect(actual.split('/')).to.have.length.above(2); | ||
}); | ||
}); | ||
}); |
42242
19
303
8
+ Addedparse-filepath@^0.2.1
+ Addedstrings-parser-date@^0.1.0
+ Addedstrings-parser-url@^0.1.0
+ Addedfrep@0.2.3(transitive)
+ Addedmoment@2.30.1(transitive)
+ Addedparse-filepath@0.2.2(transitive)
+ Addedreplacements@0.1.3(transitive)
+ Addedstrings@0.3.3(transitive)
+ Addedstrings-parser-date@0.1.1(transitive)
+ Addedstrings-parser-url@0.1.0(transitive)
- Removedfrep@0.1.8(transitive)
- Removedmoment@2.5.1(transitive)
- Removedstrings@0.2.1(transitive)
Updatedrandomatic@^0.1.4
Updatedstrings@^0.3.3