Socket
Socket
Sign inDemoInstall

permalinks

Package Overview
Dependencies
55
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0 to 1.0.1

47

index.js
'use strict';
var use = require('use');
var handlebars = require('handlebars');
var convert = require('./lib/convert');

@@ -35,2 +37,4 @@ var utils = require('./lib/utils');

this.data = this.options.data || {};
this.fns = [];
use(this);
}

@@ -106,10 +110,6 @@

file = utils.formatFile(file, this.options);
file = this.normalizeFile(file, this.options);
var context = this.context(file, locals, this.options);
var pattern = utils.get(file, 'data.permalink.structure') || this.preset(structure);
return this.render(pattern, {
helpers: context.helpers,
data: context.data
});
return this.render(pattern, context);
};

@@ -181,3 +181,7 @@

Permalinks.prototype.helper = function(name, fn) {
this.helpers[name] = fn;
if (name === 'context') {
this.fns.push(fn);
} else {
this.helpers[name] = fn;
}
return this;

@@ -206,6 +210,7 @@ };

Permalinks.prototype.context = function(file, locals, options) {
var opts = utils.assign({}, this.options, options);
var fileData = utils.assign({}, file.data, file.data.permalink);
var context = utils.assign({}, this.parse(file), this.data, locals, fileData);
var helpers = utils.assign({}, this.helpers);
var ctx = utils.assign({}, {app: this}, {options: options});
var ctx = utils.assign({}, {app: this}, {options: opts});
var data = {};

@@ -229,2 +234,6 @@

for (var i = 0; i < this.fns.length; i++) {
this.fns[i].call(this, ctx.context);
}
helpers = utils.deepBind(helpers, ctx);

@@ -239,3 +248,3 @@ if (typeof helpers.file === 'function') {

return {
options: options,
options: opts,
helpers: helpers,

@@ -255,3 +264,3 @@ data: data

Permalinks.prototype.render = function(str, options) {
Permalinks.prototype.render = function(structure, options) {
if (!this.helpers.helperMissing) {

@@ -261,5 +270,7 @@ this.helper('helperMissing', helperMissing);

var hbs = utils.handlebars.create();
var hbs = handlebars.create();
hbs.registerHelper(options.helpers);
var fn = hbs.compile(convert(str));
var str = convert(structure);
var fn = hbs.compile(str);
return fn(options.data);

@@ -269,2 +280,14 @@ };

/**
*
*
* @param {String} `str`
* @param {Object} `options`
* @return {String} Returns the fully resolved permalink string.
*/
Permalinks.prototype.normalizeFile = function(file, options) {
return utils.normalizeFile(file, options);
};
/**
* Default helper for managing missing variables

@@ -271,0 +294,0 @@ */

@@ -5,4 +5,4 @@ 'use strict';

module.exports = function(filepath) {
var segs = utils.splitPath(filepath);
module.exports = function(pattern) {
var segs = utils.splitPath(pattern);
var len = segs.length;

@@ -16,3 +16,3 @@ var idx = -1;

function convert(str, last) {
function convert(str, isLast) {
var re = /\\?:(?=[!\w*$_>])(([-!\w*$_>. ]+)(?:\((.*?)\))*[!\w*$_. )]*)/g;

@@ -24,3 +24,3 @@

if (last && i !== -1) {
if (isLast && i !== -1) {
suffix = args.slice(i);

@@ -31,2 +31,4 @@ args = args.slice(0, i);

args = utils.splitArgs(args).join('');
args = args.replace(/([*>]) */, '$1 ');
var res = match[0] === '\\'

@@ -36,6 +38,5 @@ ? match.slice(1)

res = res.replace(/([*>]) */, '$1 ');
return res + suffix;
});
};
}

@@ -42,0 +43,0 @@ function parse(args) {

@@ -15,3 +15,2 @@ 'use strict';

require('get-value', 'get');
require('handlebars');
require('isobject', 'isObject');

@@ -22,3 +21,3 @@ require('parse-filepath', 'parse');

utils.formatFile = function(val, options) {
utils.normalizeFile = function(val, options) {
function format(file) {

@@ -25,0 +24,0 @@ if (!utils.isObject(file)) {

{
"name": "permalinks",
"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": "1.0.0",
"version": "1.0.1",
"homepage": "https://github.com/jonschlinkert/permalinks",

@@ -30,10 +30,15 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)",

"lazy-cache": "^2.0.2",
"lodash.template": "^4.4.0",
"parse-filepath": "^1.0.1",
"use": "^2.0.0",
"vinyl": "^2.0.1"
},
"devDependencies": {
"diacritics-map": "^0.1.0",
"gulp-format-md": "^0.1.11",
"kind-of": "^3.1.0",
"mocha": "^3.2.0",
"moment": "^2.17.1",
"randomatic": "^1.1.6"
"randomatic": "^1.1.6",
"strip-color": "^0.1.0"
},

@@ -79,2 +84,2 @@ "keywords": [

}
}
}

@@ -26,6 +26,6 @@ # permalinks [![NPM version](https://img.shields.io/npm/v/permalinks.svg?style=flat)](https://www.npmjs.com/package/permalinks) [![NPM monthly downloads](https://img.shields.io/npm/dm/permalinks.svg?style=flat)](https://npmjs.org/package/permalinks) [![NPM total downloads](https://img.shields.io/npm/dt/permalinks.svg?style=flat)](https://npmjs.org/package/permalinks) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/permalinks.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/permalinks)

var file = {path: 'src/about.hbs'};
var locals = {category: 'foo'};
var locals = {category: 'blog'};
console.log(permalinks(structure, file, locals));
//=> 'foo/about/index.html'
//=> 'blog/about/index.html'
```

@@ -35,5 +35,5 @@

<summary><strong>Constructor usage</strong></summary>
If you need to [register helpers](#helpers) or use any of the `Permalinks` methods,
main export can alternatively be used as a constructor function:
The main export can be used as a constructor function. If you need to [register helpers](#helpers) or use any of the `Permalinks` methods, you will need to first create an instance of `Permalinks`.
```js

@@ -44,4 +44,4 @@ var Permalinks = require('permalinks');

var permalinks = new Permalinks(options);
var file = {path: 'src/about.hbs'};
var file = new File({path: 'src/about.hbs'});
console.log(permalinks.format(':stem/index.html', file));

@@ -52,16 +52,21 @@ //=> 'about/index.html'

## Context
## Files
The "context" is an in-memory object that is used for resolving the placeholders in permalink [structures](#structures).
### File conventions
The context object is created by merging the following objects:
For convenience, files can be defined as a string or an object. If defined as a string, permalinks will convert the filepath to the `file.path` property of an object.
* **file** - all of the [path properties](#file-path-properties) supported by [vinyl](https://github.com/gulpjs/vinyl), and any other user-defined properties defined on the given `file` (if a file is supplied as a string, it will converted to a vinyl file object and used as the `file.path`)
* **file.data** - the `file.data` object, if it exists. This object is often used for caching parsed yaml front-matter.
* **file.data.permalink** - This property can be a string, for defining the permalink to structure to use for a file, or an object with optional `structure` and/or `options` properties, for defining permalink options and data to be used for a specific file.
* **locals** - passed to the [format](#format) method (or the main export if you're not creating an instance of Permalinks)
* **global data** - passed on `options.data` to the contstructor
In other words, both of the following paths:
```js
var file = 'a/b/c.md';
var file = {path: 'a/b/c.md'};
```
...will convert to `{path: 'a/b/c.md'}`.
### File path properties
Values on the provided `file` object are used to resolve placeholders in the permalink structure. File values can be overridden by [locals](#locals) or [helpers](#helpers).
As long as a file is provided with at least a `file.path` property, most of the following built-in `file` variables will be automatically available on the context.

@@ -81,203 +86,111 @@

### Custom data
## Data
Any of the built-in `file` variable can be overridden by setting the properties directly.
TODO
## Helpers
### locals
Helpers can be used to resolve placeholders in permalink structures.
TODO
### file helper
### file.data
A special built-in `file` helper is called on every file and then removed from the context before rendering.
TODO
```js
permalinks.helper('file', function(file, data, locals) {
// do stuff with file, data and locals
});
```
### options.data
This is useful for modifying the context or setting properties on files before generating permalinks.
TODO
<details>
<summary><strong>Example</strong></summary>
```js
var file = new File({path: 'foo/bar/baz.hbs'});
var permalinks = new Permalinks();
var count = 0;
## Helpers
permalinks.helper('file', function(file, data, locals) {
data.num = ++count;
});
Helper functions can be used to resolve placeholders in permalink structures. For example:
console.log(permalinks.format(':num-:basename', file));
//=> '1-baz.hbs'
console.log(permalinks.format(':num-:basename', file));
//=> '2-baz.hbs'
console.log(permalinks.format(':num-:basename', file));
//=> '3-baz.hbs'
console.log(count);
//=> 3
```js
var url = permalinks.format(':foo', {path: 'about.hbs'});
```
</details>
<details>
<summary><strong>SEO Recommendations</strong></summary>
### Registering helpers
Permalinks are important for SEO, but it's a good idea to spend some time thinking about the strategy you want to use before you decide on a URL structure.
Helpers are registered using the `permalinks.helper()` method.
### Use semantic relevance
```js
The most important aspect of a URL is that it makes semantic sense to humans. The more interesting the URL is to humans, the more interesting it will be to search engines.
permalinks.helper('foo', function() {
The following are all good permalink structures, in order of [my own](https://github.com/jonschlinkert) personal preference. Pick the one that makes the most sense for your site:
});
```
* `/:postname` (a semantic, descriptive, catchy post name is best permalink structure whenever possible)
* `/:category/:postname/`
* `/:author/:postname` (popular with [medium](https://medium.com)-style blogging platforms)
* `/:category/:author/:postname`
<details>
<summary><strong>Helper example</strong></summary>
It's not unusualy for big sites to use different structures for different parts of the site (blog, products, etc).
Use a `date` helper to dynamically generate paths based on the date defined in YAML front matter of a file.
### Avoid date-based permalinks
Contrary to what might seem like an idiomatic pattern, based on the widespread adoption of using dates to categorize blog posts, dates tend to, well... _date_ your content.
Date-based URL's tend to _decrease click through rates_ on older articles. Think about it, who prefers reading out of date content? Try to use a URL strategy that doesn't go out of its way to emphasize the date, and you'll keep your posts feeling like fresh content.
There are plenty of valid use cases for using date-based URL's, like for categorizing movies, albums, breaking news, and so on. But in general, if you're writing about topics that aren't more relevant to users _specifically because of the date of the material_, it's 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.
### Numeric permalinks
Numeric or `:id` based permalinks are better than date-based, but they don't really offer much usability or SEO benefit.
## Summary
The best URL structure is one that:
* provides the _highest degree of semantic relevance_ to the content, and
* is _useful to both search engines and humans_
Happy blogging!
</details>
## API
### [Permalinks](index.js#L18)
Create an instance of `Permalinks` with the given `options`
**Params**
* `options` **{Options|String}**
**Example**
```js
var moment = require('moment');
var Permalinks = require('permalinks');
var permalinks = new Permalinks();
console.log(permalinks.format(':stem/index.html'), {path: 'src/about.hbs'});
//=> 'about/index.html'
```
### [.parse](index.js#L64)
var file = {
path: 'src/about.hbs',
data: {
date: '2017-02-14'
}
};
Uses [parse-filepath](https://github.com/jonschlinkert/parse-filepath) to parse the `file.path` on the given file object. This method is called by the [format](#format) method, but you can use it directly and pass the results as `locals` (the last argument) to the `.format` method if you need to override or modify any path segments.
// "file.data" is merged onto "this.context"
permalinks.helper('date', function(format) {
return moment(this.context.date).format(format || 'YYYY/MM/DD');
});
**Params**
* `file` **{Object}**
* `returns` **{Object}**
**Example**
```js
console.log(permalinks.parse({path: 'foo/bar/baz.md'}));
// { root: '',
// dir: 'foo/bar',
// base: 'baz.md',
// ext: '.md',
// name: 'baz',
// extname: '.md',
// basename: 'baz.md',
// dirname: 'foo/bar',
// stem: 'baz',
// path: 'foo/bar/baz.md',
// absolute: [Getter/Setter],
// isAbsolute: [Getter/Setter] }
console.log(permalinks.format(':date/:stem/index.html', file));
//=> '2017/02/14/about/index.html'
```
### [.format](index.js#L94)
Helpers can also optionally take arguments:
Generate a permalink by replacing `:prop` placeholders in the specified `structure` with data from the given `file` and `locals`.
**Params**
* `structure` **{String}**: Permalink structure or the name of a registered [preset](#preset).
* `file` **{Object|String}**: File object or file path string.
* `locals` **{Object}**: Any additional data to use for resolving placeholders.
* `returns` **{String}**
**Example**
```js
var fp = permalinks.format('blog/:stem/index.html', {path: 'src/about.hbs'});
console.log(fp);
//=> 'blog/about/index.html'
console.log(permalinks.format(':date("YYYY")/:stem/index.html', file));
//=> '2017/about/index.html'
```
</details>
### [.preset](index.js#L130)
See the [helper unit tests](test) for more examples.
Define a permalink `preset` with the given `name` and `structure`.
### file helper
**Params**
A special built-in `file` helper is called on every file and then removed from the context before rendering.
* `name` **{String}**: If only the name is passed,
* `structure` **{String}**
* `returns` **{Object}**: Returns the `Permalinks` instance for chaining
**Example**
```js
permalinks.preset('blog', 'blog/:stem/index.html');
var url = permalinks.format('blog', {path: 'src/about.hbs'});
console.log(url);
//=> 'blog/about/index.html'
permalinks.helper('file', function(file, data, locals) {
// do stuff with file, data and locals
});
```
### [.helper](index.js#L178)
This is useful for modifying the context or setting properties on files before generating permalinks.
Define permalink helper `name` with the given `fn`. Helpers work like any other variable on the context, but they can optionally take any number of arguments and can be nested to build up the resulting string.
<details>
<summary><strong>`file` helper example</strong></summary>
**Params**
Use the `file` helper to increment a value for pagination or something similar:
* `name` **{String}**: Helper name
* `fn` **{Function}**
* `returns` **{Object}**: Returns the Permalink instance for chaining.
**Example**
```js
permalinks.helper('date', function(file, format) {
return moment(file.data.date).format(format);
});
var file = new File({path: 'foo/bar/baz.hbs'});
var permalinks = new Permalinks();
var count = 0;
var structure1 = ':date(file, "YYYY/MM/DD")/:stem/index.html';
var file1 = permalinks.format(structure1, {
data: {date: '2017-01-01'},
path: 'src/about.tmpl'
permalinks.helper('file', function(file, data, locals) {
data.num = ++count;
});
var structure2 = ':name(upper(stem))/index.html';
var file2 = permalinks.format(structure2, {
data: {date: '2017-01-01'},
path: 'src/about.tmpl'
});
console.log(permalinks.format(':num-:basename', file));
//=> '1-baz.hbs'
console.log(permalinks.format(':num-:basename', file));
//=> '2-baz.hbs'
console.log(permalinks.format(':num-:basename', file));
//=> '3-baz.hbs'
console.log(count);
//=> 3
```
console.log(file1);
//=> '2017/01/01/about/index.html'
</details>
console.log(file2);
//=> '2017/01/01/about/index.html'
```
## About

@@ -321,2 +234,2 @@

_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 14, 2017._
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 15, 2017._
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc