Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Add permalinks functionality to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to replace placeholders in paths.

License

NotificationsYou must be signed in to change notification settings

permalinks/permalinks

Repository files navigation

Easily add powerful permalink or URL routing/URL rewriting capablities to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to do path or URL transformation.

Please consider following this project's author,Jon Schlinkert, and consider starring the project to show your ❤️ and support.

(TOC generated byverb usingmarkdown-toc)

Install

Install withnpm:

$ npm install --save permalinks

Quickstart

Add permalinks support to any JavaScript project using node'srequire() system with the following line of code:

constpermalink=require('permalinks');

(The main export is a function that automatically creates an instance ofPermalinks and calls thepermalinks.formt() method. As an alternative, if you need to access any internal methods, theAPI documentation shows how to create an instance ofPermalinks.)

Usage

permalink(structure,file[,options]);

Params

  • structure:{string} (required) A kind of template that determines what a permalink will look like when it's rendered.
  • file:{string|object} (required) Locals, or a file object or path (the file associated with the permalink).
  • locals:{object} (optional) Additional data to use for resolving placeholder values in the structure

Examples

console.log(permalink('/:area/:slug/index.html',{area:'blog',slug:'idiomatic-permalinks'}));//=> '/blog/idiomatic-permalinks/index.html'console.log(permalinks('/blog/:stem/index.html','src/about.hbs'));//=> '/blog/about/index.html'console.log(permalinks('/archives/:stem-:num.html','src/foo.hbs',{num:21}));//=> '/archives/foo-21.html'

API

Create an instance ofPermalinks with the givenoptions

Params

  • options{Options|String}

Example

constPermalinks=require('permalinks').Permalinks;constpermalinks=newPermalinks();console.log(permalinks.format(':stem/index.html'),{path:'src/about.hbs'});//=> 'about/index.html'

Usesparse-filepath to parse thefile.path on the given file object. This method is called by theformat method, but you can use it directly and pass the results aslocals (the last argument) to the.format method if you need to override or modify any path segments.

Params

  • file{Object}
  • returns{Object}

Example

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]}

Generate a permalink by replacing:prop placeholders in the specifiedstructure with data from the givenfile andlocals.

Params

  • structure{String}: Permalink structure or the name of a registeredpreset.
  • file{Object|String}: File object or file path string.
  • locals{Object}: Any additional data to use for resolving placeholders.
  • returns{String}

Example

constfp=permalinks.format('blog/:stem/index.html',{path:'src/about.hbs'});console.log(fp);//=> 'blog/about/index.html'

Define a permalinkpreset with the givenname andstructure.

Params

  • name{String}: If only the name is passed,
  • structure{String}
  • returns{Object}: Returns thePermalinks instance for chaining

Example

permalinks.preset('blog','blog/:stem/index.html');consturl=permalinks.format('blog',{path:'src/about.hbs'});console.log(url);//=> 'blog/about/index.html'

Define permalink helpername with the givenfn. 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.

Params

  • name{String}: Helper name
  • fn{Function}
  • returns{Object}: Returns the Permalink instance for chaining.

Example

permalinks.helper('date',function(file,format){returnmoment(file.data.date).format(format);});conststructure1=':date(file, "YYYY/MM/DD")/:stem/index.html';constfile1=permalinks.format(structure1,{data:{date:'2017-01-01'},path:'src/about.tmpl'});conststructure2=':name(upper(stem))/index.html';constfile2=permalinks.format(structure2,{data:{date:'2017-01-01'},path:'src/about.tmpl'});console.log(file1);//=> '2017/01/01/about/index.html'console.log(file2);//=> '2017/01/01/about/index.html'

Add a function for calculating the context at render time. Any number of context functions may be used, and they are called in the order in which they are defined.

Params

  • fn{Function}: Function that takes thefile being rendered and thecontext as arguments. The permalinks instance is exposed asthis inside the function.
  • returns{Object}: Returns the instance for chaining.

Example

permalinks.context(function(file,context){context.site={title:'My Blog'};});permalinks.helper('title',function(){returnthis.file.data.title||this.context.site.title;});

Normalize the givenfile to be avinyl file object.

Params

  • file{String|Object}: Iffile is a string, it will be converted to thefile.path on a file object.
  • file{Object}
  • options{Object}
  • returns{Object}: Returns the normalizevinyl file.

Example

constfile=permalinks.normalizeFile('foo.hbs');console.log(file);//=> '<File "foo.hbs">'

Docs

What is a permalink?

The word "permalink" is a portmanteau for "permanent link". A permalink is a URL to a page, post or resource on your site that is intended to stay the same as long as the site exists.

Most blogging platforms and static site generators offer some level of support or plugins for generating permalinks. To users surfing your site, a permalink represents an entire "absolute" URL, such ashttps://my-site.com/foo/index.html. However, you will probably only need to generate the relative path portion of the URL:/foo/index.html.

How are permalinks created?

A permalink is created by replacing placeholder values in a [permalink structure][] (like:slug in/blog/:slug/index.html) with actual data. This data is provided by the user in the form oflocals, and/or created by parsing the [file path][] (of the file for which we are generating a permalink):

// given this structure'/blog/:slug/index.html'// and this data{slug:'my-first-blog-post'}// the resulting (relative part of the) permalink would be'/blog/my-first-blog-post/index.html'

This is covered in greater detail in the following documentation.

Structure

A permalink structure is a template that determines how your permalink should look after it's rendered.

Structures may contain literal strings, and/or placeholder strings like:name, which will be replaced with actual data when theformat method is called.

Examples

Given a file named10-powerful-seo-tips.md, we can change the aesthetics or semantics of the resulting permalink simply by changing the structure. For example:

'/blog/:name/'//=> blog/10-powerful-seo-tips/'/blog/:name.html'//=> blog/10-powerful-seo-tips.html'/blog/:name/index.html'//=> blog/10-powerful-seo-tips/index.html

With a bit more information, provided aslocals or from thefile itself (such asfile.data, which commonly holds parsed front-matter data), we can get much more creative:

For example, iffile.data.slug was defined asmore-powerful-seo-tips, we might use it like this:

'/blog/:data.slug/index.html'//=> blog/more-powerful-seo-tips/index.html

We can get even more creative usinghelpers. We might, for example:

  • create a helper that parses a date from front-matter, such as2017-01-02, into year, month and day
  • slugifies atitle, like "Foo Bar Baz", to be dash-separated and all lower-case
  • adds the index of a file from an array of files
'/blog/:date(data.date, "YYYY/MM/DD")/index.html'//=> blog/:slugify(data.title)/index.html'blog/:slugify(data.title)/index.html'//=> blog/:slugify(data.title)/index.html'/archives/:num.html'//=> archives/23.html

Your creativity is the only limitation!

Alternative syntax

Permalinks useshandlebars to resolve templates, which means that you can also/alternatively use handlebar's native mustache syntax for defining permalink structures:

/blog/{{name}}/index.html/blog/{{foo.bar.baz}}/index.html/blog/{{year}}/{{month}}/{{day}}/{{slug}}.html

Why handlebars?

There are a few reasons we decided to use Handlebars over parsing/rendering the:params internally:

  • Excellent context handling and resolution of variables. We have a lot of experience with templating, parsing and rendering. Most libraries choose the "minimalist" route for resolving:prop strings because of all the edge cases that crop up with more advanced features, and it's fast. With Handlebars, we compromise very slightly on speed (although it's still very fast) in exchange for power and reliability.
  • Helpers! You canuse helpers to modify any of the variables in your permalink structure. You can even register helpers from great libraries liketemplate-helpers orhandlebars-helpers
  • Error handling: handlebars provides great error handling, but we especially like that handlebars allows us to choose what should happen when a missing helper is identified. We use that feature to detect dates and other similar patterns that might need to be parsed before calling other helpers (for example, let's say you define:month/:year/:day, but none of those variables exist. handlebars will call thehelperMissing helper for each param, which gives you the opportunity to, for example, parsefile.data.date into an object with those properties, and return the values instead of throwing an error)
  • Other advanced handlebars features, like subexpressions and object paths (foo.bar.baz)

Example using subexpressions

'/blog/{{lower (slugify data.title)}}/index.html'// or'/blog/:lower((slugify data.title))/index.html'

Note that:lower( is effectively converted to{{lower, thus only the outermost subexpression will result in double parentheses. This is easier to see in the following example, which has two nested subexpressions:

'/blog/:foo((bar (baz "qux")))/index.html'

If the:param syntax seems confusing, feel free to stick with the handlebars syntax.

file

Type:{String|Object} (optional iflocals is passed)

If a file object or string is passed, it will be parsed using node'spath.parse() method, and merged with locals to create the context for resolving:props in the structure.

permalinks(structure,file,locals);//                     ↑

File handling

Files may be defined as a string or an object. If defined as a string, the filepath will be converted to an object and set on thefile.path property.

In other words'a/b/c.md' becomes{ path: 'a/b/c.md' }.

locals

Type: (optional iffile is passed)

Additional data to use for resolving:props in the structure

permalinks(structure,file,locals);//                            ↑

Context

The "context" is an in-memory object that is used to resolve placeholders in permalinkstructures.

The context object is created dynamically before rendering each permalinks, by merging the following objects:

locals

If alocals object is passed as the last argument, it will be merged onto the context to be used for resolving placeholders in the permalinkstructure.

console.log(permalinks('/blog/:name/index.:ext','src/about.hbs',{ext:'.html'}));//=> '/blog/about/index.html'console.log(permalinks(':category/:name/index.html','src/about.hbs',{category:'blog'}));//=> 'blog/about/index.html'

file.data

Type:object

Default:undefined

Populate thefile.data object with additional data to use for a specific file when rendering a permalink structure.

options.data

Type:object

Default:undefined

Provide additional data to use when rendering permalinks for all files.

File path properties

Values on the providedfile object are merged onto the root of the context and are used to resolve placeholders in the permalink structure. File values can be overridden bylocals orhelpers.

A file does not need to be passed, but if a file is provided with at least afile.path property, the path will be parsed to provide as many of the following variables on the context as possible.

variabledescription
file.baseGets and sets base directory. Used for created relative paths. Whennull orundefined, it simply proxies thefile.cwd property. Will always be normalized and have trailing separators removed. Throws when set to any value other than non-empty strings ornull/undefined.
file.pathGets and sets the absolute pathname string orundefined. This value is always normalized and trailing separators are removed. Throws when set to any value other than a string.
file.relativeGets the result ofpath.relative(file.base, file.path). This is a getter and will throw if set or whenfile.path has not already been set.
file.dirnameGets and sets the dirname offile.path. Will always be normalized and have trailing separators removed. Throws whenfile.dirname is not exlicitly defined and/orfile.path is not set.
file.basenameGets and sets the basename offile.path. Throws whenfile.basename is not exlicitly defined and/orfile.path is not set.
file.stemGets and sets stem (filename without suffix) offile.path. Throws whenfile.stem is not exlicitly defined and/orfile.path is not set.
file.nameAlias forfile.stem.
file.extnameGets and sets extname property offile.path.
file.extAlias forfile.extname.

Example

┌──────────────────────────────────────────────┐│                     file.path                    │┌─────────────────────┬────────────────────────┐│      file.dirname     │        file.basename     ││                       ├──────────┬─────────────┤│                       │ file.name │              ││                       │ file.stem │ file.extname │" /home/user/foo/src    /   about        .tmpl      "└─────────────────────┴──────────┴─────────────┘

Afile.relative value can only be calculated if bothfile.base andfile.path exist:

┌──────────────────────────────────────────────┐│                     file.path                    │┌─────────────────────┬────────────────────────┐│      file.base        │        file.relative     │└─────────────────────┴────────────────────────┘

Presets

Easily store and re-use permalink structures.

(If you're familiar with the popular blogging platform, WordPress, you might also be familiar with the built-in "Permalinks Settings" that WordPress offers. This feature attempts to replicate and improve on that functionality.)

Example

Create apretty preset for automatically formatting URLs, where thefile.stem of a blog post is used as the folder name, followed by/index.html:

constpermalinks=newPermalinks();permalinks.preset('pretty','blog/:slugify(title)/index.html');console.log(permalinks.format(':pretty','foo/bar/baz.hbs',{title:'Post One'}));//=> 'blog/post-one/index.html'console.log(permalinks.format(':pretty','foo/bar/qux.hbs',{title:'Post Two'}));//=> 'blog/post-two/index.html'

Helpers

Helper functions can be used to resolve placeholders in permalink structures. For example:

// register a helper functionpermalinks.helper('foo',function(){// return the value to use to replace "foo"returnthis.file.stem;});consturl=permalinks.format('/:foo',{path:'about.hbs'});console.log(url);//=> '/about'
Helper example

Use adate helper to dynamically generate paths based on the date defined in YAML front matter of a file.

varmoment=require('moment');varPermalinks=require('permalinks');varpermalinks=newPermalinks();varfile={path:'src/about.hbs',data:{date:'2017-02-14'}};// "file.data" is merged onto "this.context"permalinks.helper('date',function(format){returnmoment(this.context.date).format(format||'YYYY/MM/DD');});console.log(permalinks.format(':date/:stem/index.html',file));//=> '2017/02/14/about/index.html'

Helpers can also take arguments:

console.log(permalinks.format(':date("YYYY")/:stem/index.html',file));//=> '2017/about/index.html'

See thehelper unit tests for more examples.

file helper

A special built-infile helper is called on every file and then removed from the context before rendering.

permalinks.helper('file',function(file,data,locals){// do stuff with file, data and locals});

You can override this helper to modify the context or set properties on files before generating permalinks.

`file` helper example

Use thefile helper to increment a value for pagination or something similar:

varfile=newFile({path:'foo/bar/baz.hbs'});varpermalinks=newPermalinks();varcount=0;permalinks.helper('file',function(file,data,locals){data.num=++count;});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

Additional resources

Here is some reading material if you're interested in learning more about permalinks.

About

Contributing

Pull requests and stars are always welcome. For bugs and feature requests,please create an issue.

Running Tests

Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

$ npm install&& npmtest
Building docs

(This project's readme.md is generated byverb, please don't edit the readme directly. Any changes to the readme must be made in the.verb.md readme template.)

To generate the readme, run the following command:

$ npm install -g verbose/verb#dev verb-generate-readme&& verb

Related projects

You might also be interested in these projects:

Author

Jon Schlinkert

License

Copyright © 2018,Jon Schlinkert.Released under theMIT License.


This file was generated byverb-generate-readme, v0.6.0, on January 11, 2018.

About

Add permalinks functionality to any node.js project. Can be used in static site generators, build systems, web applications or anywhere you need to replace placeholders in paths.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp