diff --git a/.eslintrc.json b/.eslintrc.json index 948dbdb..24b8984 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,8 +1,7 @@ { - "ecmaFeatures": { - "modules": true, - "experimentalObjectRestSpread": true - }, + "extends": [ + "eslint:recommended" + ], "env": { "browser": false, @@ -11,6 +10,15 @@ "mocha": true }, + "parserOptions":{ + "ecmaVersion": 9, + "sourceType": "module", + "ecmaFeatures": { + "modules": true, + "experimentalObjectRestSpread": true + } + }, + "globals": { "document": false, "navigator": false, diff --git a/.travis.yml b/.travis.yml index 3932eaa..50b2735 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ sudo: false +os: + - linux + - osx + - windows language: node_js node_js: + - 'node' + - '11' + - '10' + - '9' + - '8' + - '7' - '6' - - '5' - - '4' - - '0.12' - - '0.10' -matrix: - fast_finish: true - allow_failures: - - node_js: '4' - - node_js: '0.10' - - node_js: '0.12' diff --git a/.verb.md b/.verb.md index 9b0a64f..d296753 100644 --- a/.verb.md +++ b/.verb.md @@ -1,11 +1,9 @@ -In addition to the [related projects](#related-projects) listed below, also take a look at the [helpers org](https://github.com/helpers), there are 60+ specialized helpers that can be used individually. - ## Usage To get all helpers: ```js -var helpers = require('{%= name %}')(); +const helpers = require('{%= name %}')(); console.log(helpers); ``` @@ -13,31 +11,31 @@ console.log(helpers); ```js // get only the math helpers -var helpers = require('{%= name %}')('math'); +const helpers = require('{%= name %}')('math'); ``` **Get multiple helper categories** ```js // get only the math helpers -var helpers = require('{%= name %}')(['math', 'string']); +const helpers = require('{%= name %}')(['math', 'string']); ``` -### Use with any template engine +### Template-engine agnostic **Lo-Dash Example** ```js -var helpers = require('{%= name %}')('array'); +const helpers = require('{%= name %}')('array'); // pass helpers on `imports` -var imports = {imports: helpers}; +const imports = { imports: helpers }; // compile a template -var fn = _.template('<%= first(foo) %>', imports); +const fn = _.template('<%= first(foo) %>', imports); // render -fn({foo: ['a', 'b', 'c']}); +fn({ foo: ['a', 'b', 'c'] }); //=> 'a' ``` @@ -53,57 +51,57 @@ Handlebars and Lo-Dash both allow **dot notation** to be used for referencing he This can be used as a way of working around potential naming conflicts. -## API +## Helpers _(The following **API Table of Contents** is generated by [verb][]. See the [verbfile.js](verbfile.js) for more details.)_ -{%= include("toc.md") %} +{%= include("docs/toc.md") %} ### array -{%= increaseHeadings(apidocs("lib/array.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/array.js")) %} ### code -{%= increaseHeadings(apidocs("lib/code.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/code.js")) %} ### collection -{%= increaseHeadings(apidocs("lib/collection.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/collection.js")) %} ### conditional -{%= increaseHeadings(apidocs("lib/conditional.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/conditional.js")) %} ### fs -{%= increaseHeadings(apidocs("lib/fs.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/fs.js")) %} ### html -{%= increaseHeadings(apidocs("lib/html.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/html.js")) %} ### index -{%= increaseHeadings(apidocs("lib/index.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/index.js")) %} ### math -{%= increaseHeadings(apidocs("lib/math.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/math.js")) %} ### object -{%= increaseHeadings(apidocs("lib/object.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/object.js")) %} ### path -{%= increaseHeadings(apidocs("lib/path.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/path.js")) %} ### string -{%= increaseHeadings(apidocs("lib/string.js")) %} +{%= increaseHeadings(apidocs("lib/helpers/string.js")) %} -### Code coverage +## Coverage ``` {%= coverage("coverage/summary.txt") %} diff --git a/LICENSE b/LICENSE index 1e49edf..7cccaf9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015-2016, Jon Schlinkert. +Copyright (c) 2015-present, Jon Schlinkert. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5f5c3aa..bf296db 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ -# template-helpers [![NPM version](https://img.shields.io/npm/v/template-helpers.svg?style=flat)](https://www.npmjs.com/package/template-helpers) [![NPM downloads](https://img.shields.io/npm/dm/template-helpers.svg?style=flat)](https://npmjs.org/package/template-helpers) [![Build Status](https://img.shields.io/travis/jonschlinkert/template-helpers.svg?style=flat)](https://travis-ci.org/jonschlinkert/template-helpers) +# template-helpers [![NPM version](https://img.shields.io/npm/v/template-helpers.svg?style=flat)](https://www.npmjs.com/package/template-helpers) [![NPM monthly downloads](https://img.shields.io/npm/dm/template-helpers.svg?style=flat)](https://npmjs.org/package/template-helpers) [![NPM total downloads](https://img.shields.io/npm/dt/template-helpers.svg?style=flat)](https://npmjs.org/package/template-helpers) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/template-helpers.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/template-helpers) -Generic JavaScript helpers that can be used with any template engine. Handlebars, Lo-Dash, Underscore, or any engine that supports helper functions. +> Generic JavaScript helpers that can be used with any template engine. Handlebars, Lo-Dash, Underscore, or any engine that supports helper functions. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. - [Install](#install) - [Usage](#usage) - * [Use with any template engine](#use-with-any-template-engine) + * [Template-engine agnostic](#template-engine-agnostic) * [Namespacing](#namespacing) -- [API](#api) +- [Helpers](#helpers) * [array](#array) * [code](#code) * [collection](#collection) @@ -18,16 +20,8 @@ Generic JavaScript helpers that can be used with any template engine. Handlebars * [object](#object) * [path](#path) * [string](#string) - * [Code coverage](#code-coverage) +- [Coverage](#coverage) - [About](#about) - * [Related projects](#related-projects) - * [Contributing](#contributing) - * [Building docs](#building-docs) - * [Running tests](#running-tests) - * [Author](#author) - * [License](#license) - -_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_ ## Install @@ -37,14 +31,12 @@ Install with [npm](https://www.npmjs.com/): $ npm install --save template-helpers ``` -In addition to the [related projects](#related-projects) listed below, also take a look at the [helpers org](https://github.com/helpers), there are 60+ specialized helpers that can be used individually. - ## Usage To get all helpers: ```js -var helpers = require('template-helpers')(); +const helpers = require('template-helpers')(); console.log(helpers); ``` @@ -52,31 +44,31 @@ console.log(helpers); ```js // get only the math helpers -var helpers = require('template-helpers')('math'); +const helpers = require('template-helpers')('math'); ``` **Get multiple helper categories** ```js // get only the math helpers -var helpers = require('template-helpers')(['math', 'string']); +const helpers = require('template-helpers')(['math', 'string']); ``` -### Use with any template engine +### Template-engine agnostic **Lo-Dash Example** ```js -var helpers = require('template-helpers')('array'); +const helpers = require('template-helpers')('array'); // pass helpers on `imports` -var imports = {imports: helpers}; +const imports = { imports: helpers }; // compile a template -var fn = _.template('<%= first(foo) %>', imports); +const fn = _.template('<%= first(foo) %>', imports); // render -fn({foo: ['a', 'b', 'c']}); +fn({ foo: ['a', 'b', 'c'] }); //=> 'a' ``` @@ -92,166 +84,181 @@ Handlebars and Lo-Dash both allow **dot notation** to be used for referencing he This can be used as a way of working around potential naming conflicts. -## API +## Helpers _(The following **API Table of Contents** is generated by [verb](https://github.com/verbose/verb). See the [verbfile.js](verbfile.js) for more details.)_ ## Categories -Currently **86 helpers** in **10 categories**: +Currently **101 helpers** in **10 categories**: -* **[array](#array)** ([code](lib/array.js) | [unit tests](test/array.js)) -* **[code](#code)** ([code](lib/code.js) | [unit tests](test/code.js)) -* **[collection](#collection)** ([code](lib/collection.js) | [unit tests](test/collection.js)) -* **[conditional](#conditional)** ([code](lib/conditional.js) | [unit tests](test/conditional.js)) -* **[fs](#fs)** ([code](lib/fs.js) | [unit tests](test/fs.js)) -* **[html](#html)** ([code](lib/html.js) | [unit tests](test/html.js)) -* **[math](#math)** ([code](lib/math.js) | [unit tests](test/math.js)) -* **[object](#object)** ([code](lib/object.js) | [unit tests](test/object.js)) -* **[path](#path)** ([code](lib/path.js) | [unit tests](test/path.js)) -* **[string](#string)** ([code](lib/string.js) | [unit tests](test/string.js)) +* **[array](#array)** ([code](lib/helpers/array.js) | [unit tests](test/array.js)) +* **[code](#code)** ([code](lib/helpers/code.js) | [unit tests](test/code.js)) +* **[collection](#collection)** ([code](lib/helpers/collection.js) | [unit tests](test/collection.js)) +* **[conditional](#conditional)** ([code](lib/helpers/conditional.js) | [unit tests](test/conditional.js)) +* **[fs](#fs)** ([code](lib/helpers/fs.js) | [unit tests](test/fs.js)) +* **[html](#html)** ([code](lib/helpers/html.js) | [unit tests](test/html.js)) +* **[math](#math)** ([code](lib/helpers/math.js) | [unit tests](test/math.js)) +* **[object](#object)** ([code](lib/helpers/object.js) | [unit tests](test/object.js)) +* **[path](#path)** ([code](lib/helpers/path.js) | [unit tests](test/path.js)) +* **[string](#string)** ([code](lib/helpers/string.js) | [unit tests](test/string.js)) ## All helpers ### [array helpers](#array) -Visit the: [code](lib/array.js) | [unit tests](test/array.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+array+helpers)) - -* **[isArray](#isArray)** ([code](lib/array.js#L22) | [unit tests](test/array.js#L18)) -* **[arrayify](#arrayify)** ([code](lib/array.js#L46) | [unit tests](test/array.js#L25)) -* **[first](#first)** ([code](lib/array.js#L64) | [unit tests](test/array.js#L32)) -* **[last](#last)** ([code](lib/array.js#L87) | [unit tests](test/array.js#L48)) -* **[before](#before)** ([code](lib/array.js#L112) | [unit tests](test/array.js#L61)) -* **[after](#after)** ([code](lib/array.js#L132) | [unit tests](test/array.js#L71)) -* **[each](#each)** ([code](lib/array.js#L159) | [unit tests](test/array.js#L98)) -* **[map](#map)** ([code](lib/array.js#L201) | [unit tests](test/array.js#L122)) -* **[join](#join)** ([code](lib/array.js#L232) | [unit tests](test/array.js#L82)) -* **[sort](#sort)** ([code](lib/array.js#L257) | [unit tests](test/array.js#L137)) -* **[length](#length)** ([code](lib/array.js#L291) | [unit tests](test/array.js#L162)) -* **[compact](#compact)** ([code](lib/array.js#L309) | [unit tests](test/array.js#L178)) -* **[difference](#difference)** ([code](lib/array.js#L328) | [unit tests](test/array.js#L189)) -* **[unique](#unique)** ([code](lib/array.js#L364) | [unit tests](test/array.js#L205)) -* **[union](#union)** ([code](lib/array.js#L394) | [unit tests](test/array.js#L215)) -* **[shuffle](#shuffle)** ([code](lib/array.js#L411) | [no tests]) +Visit the: [code](lib/helpers/array.js) | [unit tests](test/array.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+array+helpers)) + +* **[isArray](#isArray)** ([code](lib/helpers/array.js#L21) | [unit tests](test/array.js#L18)) +* **[arrayify](#arrayify)** ([code](lib/helpers/array.js#L42) | [unit tests](test/array.js#L25)) +* **[first](#first)** ([code](lib/helpers/array.js#L58) | [unit tests](test/array.js#L32)) +* **[last](#last)** ([code](lib/helpers/array.js#L79) | [unit tests](test/array.js#L48)) +* **[before](#before)** ([code](lib/helpers/array.js#L102) | [unit tests](test/array.js#L61)) +* **[after](#after)** ([code](lib/helpers/array.js#L121) | [unit tests](test/array.js#L71)) +* **[each](#each)** ([code](lib/helpers/array.js#L147) | [unit tests](test/array.js#L98)) +* **[map](#map)** ([code](lib/helpers/array.js#L188) | [unit tests](test/array.js#L122)) +* **[join](#join)** ([code](lib/helpers/array.js#L218) | [unit tests](test/array.js#L82)) +* **[sort](#sort)** ([code](lib/helpers/array.js#L241) | [unit tests](test/array.js#L137)) +* **[length](#length)** ([code](lib/helpers/array.js#L272) | [unit tests](test/array.js#L162)) +* **[compact](#compact)** ([code](lib/helpers/array.js#L289) | [unit tests](test/array.js#L178)) +* **[difference](#difference)** ([code](lib/helpers/array.js#L307) | [unit tests](test/array.js#L189)) +* **[unique](#unique)** ([code](lib/helpers/array.js#L344) | [unit tests](test/array.js#L205)) +* **[union](#union)** ([code](lib/helpers/array.js#L373) | [unit tests](test/array.js#L215)) +* **[shuffle](#shuffle)** ([code](lib/helpers/array.js#L389) | [no tests]) ### [code helpers](#code) -Visit the: [code](lib/code.js) | [unit tests](test/code.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+code+helpers)) +Visit the: [code](lib/helpers/code.js) | [unit tests](test/code.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+code+helpers)) -* **[embed](#embed)** ([code](lib/code.js#L24) | [unit tests](test/code.js#L33)) -* **[jsfiddle](#jsfiddle)** ([code](lib/code.js#L48) | [unit tests](test/code.js#L24)) +* **[embed](#embed)** ([code](lib/helpers/code.js#L23) | [unit tests](test/code.js#L33)) +* **[jsfiddle](#jsfiddle)** ([code](lib/helpers/code.js#L45) | [unit tests](test/code.js#L24)) ### [collection helpers](#collection) -Visit the: [code](lib/collection.js) | [unit tests](test/collection.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+collection+helpers)) +Visit the: [code](lib/helpers/collection.js) | [unit tests](test/collection.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+collection+helpers)) -* **[any](#any)** ([code](lib/collection.js#L15) | [unit tests](test/collection.js#L17)) -* **[filter](#filter)** ([code](lib/collection.js#L32) | [unit tests](test/collection.js#L34)) +* **[any](#any)** ([code](lib/helpers/collection.js#L17) | [unit tests](test/collection.js#L17)) +* **[filter](#filter)** ([code](lib/helpers/collection.js#L32) | [unit tests](test/collection.js#L34)) ### [conditional helpers](#conditional) -Visit the: [code](lib/conditional.js) | [unit tests](test/conditional.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+conditional+helpers)) - -* **[_if](#_if)** ([code](lib/conditional.js#L13) | [no tests]) +Visit the: [code](lib/helpers/conditional.js) | [unit tests](test/conditional.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+conditional+helpers)) + +* **[and](#and)** ([code](lib/helpers/conditional.js#L13) | [no tests]) +* **[compare](#compare)** ([code](lib/helpers/conditional.js#L30) | [unit tests](test/conditional.js#L35)) +* **[find](#find)** ([code](lib/helpers/conditional.js#L72) | [no tests]) +* **[every](#every)** ([code](lib/helpers/conditional.js#L83) | [no tests]) +* **[gt](#gt)** ([code](lib/helpers/conditional.js#L98) | [no tests]) +* **[gte](#gte)** ([code](lib/helpers/conditional.js#L110) | [no tests]) +* **[_if](#_if)** ([code](lib/helpers/conditional.js#L122) | [no tests]) +* **[is](#is)** ([code](lib/helpers/conditional.js#L142) | [unit tests](test/conditional.js#L47)) +* **[eq](#eq)** ([code](lib/helpers/conditional.js#L157) | [no tests]) +* **[isnt](#isnt)** ([code](lib/helpers/conditional.js#L169) | [unit tests](test/conditional.js#L59)) +* **[notEq](#notEq)** ([code](lib/helpers/conditional.js#L183) | [no tests]) +* **[lt](#lt)** ([code](lib/helpers/conditional.js#L195) | [no tests]) +* **[lte](#lte)** ([code](lib/helpers/conditional.js#L207) | [no tests]) +* **[or](#or)** ([code](lib/helpers/conditional.js#L219) | [no tests]) +* **[some](#some)** ([code](lib/helpers/conditional.js#L230) | [no tests]) ### [fs helpers](#fs) -Visit the: [code](lib/fs.js) | [unit tests](test/fs.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+fs+helpers)) +Visit the: [code](lib/helpers/fs.js) | [unit tests](test/fs.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+fs+helpers)) -* **[exists](#exists)** ([code](lib/fs.js#L19) | [unit tests](test/fs.js#L17)) -* **[read](#read)** ([code](lib/fs.js#L35) | [unit tests](test/fs.js#L23)) +* **[exists](#exists)** ([code](lib/helpers/fs.js#L16) | [unit tests](test/fs.js#L17)) +* **[read](#read)** ([code](lib/helpers/fs.js#L29) | [unit tests](test/fs.js#L23)) ### [html helpers](#html) -Visit the: [code](lib/html.js) | [unit tests](test/html.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+html+helpers)) +Visit the: [code](lib/helpers/html.js) | [unit tests](test/html.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+html+helpers)) -* **[escapeHtml](#escapeHtml)** ([code](lib/html.js#L18) | [unit tests](test/html.js#L17)) -* **[sanitize](#sanitize)** ([code](lib/html.js#L46) | [unit tests](test/html.js#L27)) +* **[escapeHtml](#escapeHtml)** ([code](lib/helpers/html.js#L18) | [unit tests](test/html.js#L17)) +* **[sanitize](#sanitize)** ([code](lib/helpers/html.js#L46) | [unit tests](test/html.js#L27)) ### [math helpers](#math) -Visit the: [code](lib/math.js) | [unit tests](test/math.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+math+helpers)) +Visit the: [code](lib/helpers/math.js) | [unit tests](test/math.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+math+helpers)) -* **[add](#add)** ([code](lib/math.js#L18) | [unit tests](test/math.js#L17)) -* **[subtract](#subtract)** ([code](lib/math.js#L35) | [unit tests](test/math.js#L23)) -* **[divide](#divide)** ([code](lib/math.js#L53) | [unit tests](test/math.js#L29)) -* **[multiply](#multiply)** ([code](lib/math.js#L71) | [unit tests](test/math.js#L35)) -* **[floor](#floor)** ([code](lib/math.js#L89) | [unit tests](test/math.js#L41)) -* **[ceil](#ceil)** ([code](lib/math.js#L107) | [unit tests](test/math.js#L47)) -* **[round](#round)** ([code](lib/math.js#L128) | [unit tests](test/math.js#L53)) -* **[sum](#sum)** ([code](lib/math.js#L145) | [unit tests](test/math.js#L60)) +* **[add](#add)** ([code](lib/helpers/math.js#L17) | [unit tests](test/math.js#L17)) +* **[subtract](#subtract)** ([code](lib/helpers/math.js#L31) | [unit tests](test/math.js#L23)) +* **[divide](#divide)** ([code](lib/helpers/math.js#L46) | [unit tests](test/math.js#L29)) +* **[multiply](#multiply)** ([code](lib/helpers/math.js#L61) | [unit tests](test/math.js#L35)) +* **[floor](#floor)** ([code](lib/helpers/math.js#L76) | [unit tests](test/math.js#L41)) +* **[ceil](#ceil)** ([code](lib/helpers/math.js#L91) | [unit tests](test/math.js#L47)) +* **[round](#round)** ([code](lib/helpers/math.js#L109) | [unit tests](test/math.js#L53)) +* **[sum](#sum)** ([code](lib/helpers/math.js#L123) | [unit tests](test/math.js#L60)) ### [object helpers](#object) -Visit the: [code](lib/object.js) | [unit tests](test/object.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+object+helpers)) - -* **[fallback](#fallback)** ([code](lib/object.js#L22) | [unit tests](test/object.js#L18)) -* **[stringify](#stringify)** ([code](lib/object.js#L39) | [unit tests](test/object.js#L26)) -* **[parse](#parse)** ([code](lib/object.js#L56) | [unit tests](test/object.js#L33)) -* **[get](#get)** ([code](lib/object.js#L74) | [no tests]) -* **[keys](#keys)** ([code](lib/object.js#L91) | [unit tests](test/object.js#L64)) -* **[isObject](#isObject)** ([code](lib/object.js#L112) | [unit tests](test/object.js#L40)) -* **[isPlainObject](#isPlainObject)** ([code](lib/object.js#L135) | [unit tests](test/object.js#L48)) -* **[hasOwn](#hasOwn)** ([code](lib/object.js#L149) | [unit tests](test/object.js#L57)) -* **[omit](#omit)** ([code](lib/object.js#L167) | [unit tests](test/object.js#L98)) -* **[forIn](#forIn)** ([code](lib/object.js#L185) | [unit tests](test/object.js#L70)) -* **[forOwn](#forOwn)** ([code](lib/object.js#L207) | [unit tests](test/object.js#L84)) -* **[extend](#extend)** ([code](lib/object.js#L224) | [unit tests](test/object.js#L105)) -* **[merge](#merge)** ([code](lib/object.js#L257) | [unit tests](test/object.js#L132)) +Visit the: [code](lib/helpers/object.js) | [unit tests](test/object.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+object+helpers)) + +* **[fallback](#fallback)** ([code](lib/helpers/object.js#L22) | [unit tests](test/object.js#L18)) +* **[stringify](#stringify)** ([code](lib/helpers/object.js#L36) | [unit tests](test/object.js#L26)) +* **[parse](#parse)** ([code](lib/helpers/object.js#L50) | [unit tests](test/object.js#L33)) +* **[get](#get)** ([code](lib/helpers/object.js#L65) | [no tests]) +* **[keys](#keys)** ([code](lib/helpers/object.js#L79) | [unit tests](test/object.js#L64)) +* **[isObject](#isObject)** ([code](lib/helpers/object.js#L97) | [unit tests](test/object.js#L40)) +* **[isPlainObject](#isPlainObject)** ([code](lib/helpers/object.js#L117) | [unit tests](test/object.js#L48)) +* **[hasOwn](#hasOwn)** ([code](lib/helpers/object.js#L129) | [unit tests](test/object.js#L57)) +* **[omit](#omit)** ([code](lib/helpers/object.js#L144) | [unit tests](test/object.js#L98)) +* **[forIn](#forIn)** ([code](lib/helpers/object.js#L163) | [unit tests](test/object.js#L70)) +* **[forOwn](#forOwn)** ([code](lib/helpers/object.js#L188) | [unit tests](test/object.js#L84)) +* **[extend](#extend)** ([code](lib/helpers/object.js#L205) | [unit tests](test/object.js#L105)) +* **[merge](#merge)** ([code](lib/helpers/object.js#L241) | [unit tests](test/object.js#L132)) ### [path helpers](#path) -Visit the: [code](lib/path.js) | [unit tests](test/path.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+path+helpers)) - -* **[dirname](#dirname)** ([code](lib/path.js#L20) | [unit tests](test/path.js#L18)) -* **[basename](#basename)** ([code](lib/path.js#L38) | [unit tests](test/path.js#L24)) -* **[filename](#filename)** ([code](lib/path.js#L56) | [unit tests](test/path.js#L30)) -* **[extname](#extname)** ([code](lib/path.js#L74) | [unit tests](test/path.js#L36)) -* **[ext](#ext)** ([code](lib/path.js#L74) | [unit tests](test/path.js#L36)) -* **[resolve](#resolve)** ([code](lib/path.js#L110) | [unit tests](test/path.js#L48)) -* **[relative](#relative)** ([code](lib/path.js#L129) | [unit tests](test/path.js#L54)) -* **[segments](#segments)** ([code](lib/path.js#L160) | [unit tests](test/path.js#L108)) -* **[join](#join)** ([code](lib/path.js#L182) | [unit tests](test/path.js#L101)) -* **[isAbsolute](#isAbsolute)** ([code](lib/path.js#L217) | [unit tests](test/path.js#L82)) -* **[isRelative](#isRelative)** ([code](lib/path.js#L252) | [unit tests](test/path.js#L63)) +Visit the: [code](lib/helpers/path.js) | [unit tests](test/path.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+path+helpers)) + +* **[dirname](#dirname)** ([code](lib/helpers/path.js#L19) | [unit tests](test/path.js#L17)) +* **[basename](#basename)** ([code](lib/helpers/path.js#L34) | [unit tests](test/path.js#L23)) +* **[filename](#filename)** ([code](lib/helpers/path.js#L49) | [unit tests](test/path.js#L29)) +* **[stem](#stem)** ([code](lib/helpers/path.js#L65) | [no tests]) +* **[extname](#extname)** ([code](lib/helpers/path.js#L80) | [unit tests](test/path.js#L35)) +* **[ext](#ext)** ([code](lib/helpers/path.js#L80) | [unit tests](test/path.js#L35)) +* **[resolve](#resolve)** ([code](lib/helpers/path.js#L110) | [unit tests](test/path.js#L47)) +* **[relative](#relative)** ([code](lib/helpers/path.js#L126) | [unit tests](test/path.js#L53)) +* **[segments](#segments)** ([code](lib/helpers/path.js#L162) | [unit tests](test/path.js#L107)) +* **[join](#join)** ([code](lib/helpers/path.js#L183) | [unit tests](test/path.js#L100)) +* **[isAbsolute](#isAbsolute)** ([code](lib/helpers/path.js#L215) | [unit tests](test/path.js#L81)) +* **[isRelative](#isRelative)** ([code](lib/helpers/path.js#L247) | [unit tests](test/path.js#L62)) ### [string helpers](#string) -Visit the: [code](lib/string.js) | [unit tests](test/string.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+string+helpers)) - -* **[camelcase](#camelcase)** ([code](lib/string.js#L18) | [unit tests](test/string.js#L111)) -* **[centerAlign](#centerAlign)** ([code](lib/string.js#L45) | [no tests]) -* **[chop](#chop)** ([code](lib/string.js#L69) | [unit tests](test/string.js#L51)) -* **[count](#count)** ([code](lib/string.js#L90) | [unit tests](test/string.js#L290)) -* **[dotcase](#dotcase)** ([code](lib/string.js#L110) | [unit tests](test/string.js#L175)) -* **[ellipsis](#ellipsis)** ([code](lib/string.js#L135) | [unit tests](test/string.js#L381)) -* **[isString](#isString)** ([code](lib/string.js#L157) | [no tests]) -* **[lower](#lower)** ([code](lib/string.js#L174) | [unit tests](test/string.js#L17)) -* **[lowercase](#lowercase)** ([code](lib/string.js#L174) | [unit tests](test/string.js#L17)) -* **[pascalcase](#pascalcase)** ([code](lib/string.js#L191) | [unit tests](test/string.js#L132)) -* **[snakecase](#snakecase)** ([code](lib/string.js#L211) | [unit tests](test/string.js#L154)) -* **[split](#split)** ([code](lib/string.js#L233) | [no tests]) -* **[strip](#strip)** ([code](lib/string.js#L250) | [unit tests](test/string.js#L73)) -* **[stripIndent](#stripIndent)** ([code](lib/string.js#L269) | [unit tests](test/string.js#L87)) -* **[trim](#trim)** ([code](lib/string.js#L298) | [unit tests](test/string.js#L37)) -* **[dashcase](#dashcase)** ([code](lib/string.js#L317) | [unit tests](test/string.js#L196)) -* **[pathcase](#pathcase)** ([code](lib/string.js#L339) | [unit tests](test/string.js#L217)) -* **[sentencecase](#sentencecase)** ([code](lib/string.js#L361) | [unit tests](test/string.js#L238)) -* **[hyphenate](#hyphenate)** ([code](lib/string.js#L380) | [unit tests](test/string.js#L252)) -* **[slugify](#slugify)** ([code](lib/string.js#L399) | [unit tests](test/string.js#L270)) -* **[reverse](#reverse)** ([code](lib/string.js#L414) | [unit tests](test/string.js#L304)) -* **[rightAlign](#rightAlign)** ([code](lib/string.js#L432) | [no tests]) -* **[replace](#replace)** ([code](lib/string.js#L451) | [unit tests](test/string.js#L343)) -* **[titleize](#titleize)** ([code](lib/string.js#Lundefined) | [no tests]) -* **[titlecase](#titlecase)** ([code](lib/string.js#L473) | [unit tests](test/string.js#L361)) -* **[truncate](#truncate)** ([code](lib/string.js#L492) | [unit tests](test/string.js#L371)) -* **[upper](#upper)** ([code](lib/string.js#L509) | [unit tests](test/string.js#L27)) -* **[uppercase](#uppercase)** ([code](lib/string.js#L509) | [unit tests](test/string.js#L27)) -* **[wordwrap](#wordwrap)** ([code](lib/string.js#L531) | [unit tests](test/string.js#L313)) +Visit the: [code](lib/helpers/string.js) | [unit tests](test/string.js) | [issues](https://github.com/jonschlinkert/template-helpers/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+string+helpers)) + +* **[camelcase](#camelcase)** ([code](lib/helpers/string.js#L24) | [unit tests](test/string.js#L98)) +* **[centerAlign](#centerAlign)** ([code](lib/helpers/string.js#L46) | [no tests]) +* **[chop](#chop)** ([code](lib/helpers/string.js#L69) | [unit tests](test/string.js#L50)) +* **[count](#count)** ([code](lib/helpers/string.js#L88) | [unit tests](test/string.js#L277)) +* **[dotcase](#dotcase)** ([code](lib/helpers/string.js#L107) | [unit tests](test/string.js#L162)) +* **[ellipsis](#ellipsis)** ([code](lib/helpers/string.js#L128) | [unit tests](test/string.js#L368)) +* **[isString](#isString)** ([code](lib/helpers/string.js#L147) | [no tests]) +* **[lower](#lower)** ([code](lib/helpers/string.js#L161) | [unit tests](test/string.js#L16)) +* **[lowercase](#lowercase)** ([code](lib/helpers/string.js#L161) | [unit tests](test/string.js#L16)) +* **[pascalcase](#pascalcase)** ([code](lib/helpers/string.js#L177) | [unit tests](test/string.js#L119)) +* **[snakecase](#snakecase)** ([code](lib/helpers/string.js#L196) | [unit tests](test/string.js#L141)) +* **[split](#split)** ([code](lib/helpers/string.js#L214) | [no tests]) +* **[strip](#strip)** ([code](lib/helpers/string.js#L230) | [unit tests](test/string.js#L72)) +* **[stripIndent](#stripIndent)** ([code](lib/helpers/string.js#L248) | [unit tests](test/string.js#L86)) +* **[trim](#trim)** ([code](lib/helpers/string.js#L275) | [unit tests](test/string.js#L36)) +* **[dashcase](#dashcase)** ([code](lib/helpers/string.js#L291) | [unit tests](test/string.js#L183)) +* **[pathcase](#pathcase)** ([code](lib/helpers/string.js#L309) | [unit tests](test/string.js#L204)) +* **[sentencecase](#sentencecase)** ([code](lib/helpers/string.js#L327) | [unit tests](test/string.js#L225)) +* **[hyphenate](#hyphenate)** ([code](lib/helpers/string.js#L345) | [unit tests](test/string.js#L239)) +* **[slugify](#slugify)** ([code](lib/helpers/string.js#L363) | [unit tests](test/string.js#L257)) +* **[reverse](#reverse)** ([code](lib/helpers/string.js#L377) | [unit tests](test/string.js#L291)) +* **[rightAlign](#rightAlign)** ([code](lib/helpers/string.js#L394) | [no tests]) +* **[replace](#replace)** ([code](lib/helpers/string.js#L412) | [unit tests](test/string.js#L330)) +* **[titleize](#titleize)** ([code](lib/helpers/string.js#Lundefined) | [no tests]) +* **[titlecase](#titlecase)** ([code](lib/helpers/string.js#L433) | [unit tests](test/string.js#L348)) +* **[truncate](#truncate)** ([code](lib/helpers/string.js#L451) | [unit tests](test/string.js#L358)) +* **[upper](#upper)** ([code](lib/helpers/string.js#L467) | [unit tests](test/string.js#L26)) +* **[uppercase](#uppercase)** ([code](lib/helpers/string.js#L467) | [unit tests](test/string.js#L26)) +* **[wordwrap](#wordwrap)** ([code](lib/helpers/string.js#L484) | [unit tests](test/string.js#L300)) ### array -#### [isArray](lib/array.js#L22) +#### [isArray](lib/helpers/array.js#L21) Returns true if `value` is an array. @@ -270,7 +277,7 @@ Returns true if `value` is an array. //=> 'true' ``` -#### [arrayify](lib/array.js#L46) +#### [arrayify](lib/helpers/array.js#L42) Cast `val` to an array. @@ -293,7 +300,7 @@ Cast `val` to an array. //=> '["a"]' ``` -#### [first](lib/array.js#L64) +#### [first](lib/helpers/array.js#L58) Returns the first item, or first `n` items of an array. @@ -310,7 +317,7 @@ Returns the first item, or first `n` items of an array. //=> '["a", "b"]' ``` -#### [last](lib/array.js#L87) +#### [last](lib/helpers/array.js#L79) Returns the last item, or last `n` items of an array. @@ -327,7 +334,7 @@ Returns the last item, or last `n` items of an array. //=> '["d", "e"]' ``` -#### [before](lib/array.js#L112) +#### [before](lib/helpers/array.js#L102) Returns all of the items in an array up to the specified number Opposite of `<%= after() %`. @@ -344,7 +351,7 @@ Returns all of the items in an array up to the specified number Opposite of `<%= //=> '["a", "b"]' ``` -#### [after](lib/array.js#L132) +#### [after](lib/helpers/array.js#L121) Returns all of the items in an arry after the specified index. Opposite of `<%= before() %`. @@ -361,7 +368,7 @@ Returns all of the items in an arry after the specified index. Opposite of `<%= //=> '["c"]' ``` -#### [each](lib/array.js#L159) +#### [each](lib/helpers/array.js#L147) Calling `fn` on each element of the given `array` with the given `context`. @@ -386,7 +393,7 @@ function double(str) { //=> '["aa", "bb", "cc"]' ``` -#### [map](lib/array.js#L201) +#### [map](lib/helpers/array.js#L188) Returns a new array, created by calling `function` on each element of the given `array`. @@ -411,7 +418,7 @@ function double(str) { //=> '["aa", "bb", "cc"]' ``` -#### [join](lib/array.js#L232) +#### [join](lib/helpers/array.js#L218) Join all elements of array into a string, optionally using a given separator. @@ -431,7 +438,7 @@ Join all elements of array into a string, optionally using a given separator. //=> 'a-b-c' ``` -#### [sort](lib/array.js#L257) +#### [sort](lib/helpers/array.js#L241) Sort the given `array`. If an array of objects is passed, you may optionally pass a `key` to sort on as the second argument. You may alternatively pass a sorting function as the second argument. @@ -450,7 +457,7 @@ Sort the given `array`. If an array of objects is passed, you may optionally pas //=> '[{"a":"aaa"},{"a":"zzz"}]' ``` -#### [length](lib/array.js#L291) +#### [length](lib/helpers/array.js#L272) Returns the length of the given array. @@ -466,7 +473,7 @@ Returns the length of the given array. //=> 3 ``` -#### [compact](lib/array.js#L309) +#### [compact](lib/helpers/array.js#L289) Returns an array with all falsey values removed. @@ -482,7 +489,7 @@ Returns an array with all falsey values removed. //=> '["a", "b", "c"]' ``` -#### [difference](lib/array.js#L328) +#### [difference](lib/helpers/array.js#L307) Return the difference between the first array and additional arrays. @@ -499,7 +506,7 @@ Return the difference between the first array and additional arrays. //=> '["c"]' ``` -#### [unique](lib/array.js#L364) +#### [unique](lib/helpers/array.js#L344) Return an array, free of duplicate values. @@ -515,7 +522,7 @@ Return an array, free of duplicate values. => '["a", "b", "c"]' ``` -#### [union](lib/array.js#L394) +#### [union](lib/helpers/array.js#L373) Returns an array of unique values using strict equality for comparisons. @@ -531,7 +538,7 @@ Returns an array of unique values using strict equality for comparisons. //=> '["a", "b", "c"]' ``` -#### [shuffle](lib/array.js#L411) +#### [shuffle](lib/helpers/array.js#L389) Shuffle the items in an array. @@ -549,7 +556,7 @@ Shuffle the items in an array. ### code -#### [embed](lib/code.js#L24) +#### [embed](lib/helpers/code.js#L23) Embed code from an external file as preformatted text. @@ -568,7 +575,7 @@ Embed code from an external file as preformatted text. <%= embed('path/to/file.hbs', 'html') %> ``` -#### [jsfiddle](lib/code.js#L48) +#### [jsfiddle](lib/helpers/code.js#L45) Generate the HTML for a jsFiddle link with the given `params` @@ -585,7 +592,7 @@ Generate the HTML for a jsFiddle link with the given `params` ### collection -#### [any](lib/collection.js#L15) +#### [any](lib/helpers/collection.js#L17) Returns `true` if `value` exists in the given string, array or object. See [any](https://github.com/jonschlinkert/any) for documentation. @@ -596,7 +603,7 @@ or object. See [any](https://github.com/jonschlinkert/any) for documentation. * `target` **{any}** * `options` **{Object}** -#### [filter](lib/collection.js#L32) +#### [filter](lib/helpers/collection.js#L32) Filter the given array or object to contain only the matching values. @@ -614,7 +621,72 @@ Filter the given array or object to contain only the matching values. ### conditional -#### [_if](lib/conditional.js#L13) +#### [and](lib/helpers/conditional.js#L13) + +Returns true when both `valueA` and `valueB` are truthy. + +**Params** + +* `valueA` **{any}** +* `valueB` **{any}** +* `returns` **{Boolean}** + +#### [compare](lib/helpers/conditional.js#L30) + +Render a block when a comparison of the first and third arguments returns true. + +**Params** + +* `valueA` **{String}** +* `operator` **{String}**: The operator to use for the comparison (must be a quoted string). +* `valueB` **{String}** +* `returns` **{Boolean}** + +**Example** + +```js +<%= compare("foo", "!==", "bar") %> +``` + +#### [find](lib/helpers/conditional.js#L72) + +Returns the first truthy value. + +**Params** + +* `...values` **{...args}** +* `returns` **{any}** + +#### [every](lib/helpers/conditional.js#L83) + +Returns true when all provided values are truthy. + +**Params** + +* `...values` **{...any}** +* `returns` **{Boolean}** + +#### [gt](lib/helpers/conditional.js#L98) + +Returns true when `valueA` is greater than `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [gte](lib/helpers/conditional.js#L110) + +Returns true when `valueA` is greater than or equal to `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [_if](lib/helpers/conditional.js#L122) Return true if `key` is an own, enumerable property of the given `obj`. @@ -625,9 +697,90 @@ of the given `obj`. * `key` **{String}** * `returns` **{Boolean}** +#### [is](lib/helpers/conditional.js#L142) + +Returns true when `valueA` equals `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `strict` **{String}** +* `returns` **{Boolean}** + +#### [eq](lib/helpers/conditional.js#L157) + +Alias for [is](#is). + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `strict` **{String}** +* `returns` **{Boolean}** + +#### [isnt](lib/helpers/conditional.js#L169) + +Returns true when `valueA` does not equal `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [notEq](lib/helpers/conditional.js#L183) + +Alias for [isnt](#isnt). + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [lt](lib/helpers/conditional.js#L195) + +Returns true when `valueA` is less than `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [lte](lib/helpers/conditional.js#L207) + +Returns true when `valueA` is less than or equal to `valueB`. + +**Params** + +* `valueA` **{String}** +* `valueB` **{String}** +* `returns` **{Boolean}** + +#### [or](lib/helpers/conditional.js#L219) + +Returns `valueA` if thruthy, otherwise `valueB`. + +**Params** + +* `valueA` **{any}** +* `valueB` **{any}** +* `returns` **{any}** + +#### [some](lib/helpers/conditional.js#L230) + +Returns true when at least one value is truthy. + +**Params** + +* `...values` **{...any}** +* `returns` **{Boolean}** + ### fs -#### [exists](lib/fs.js#L19) +#### [exists](lib/helpers/fs.js#L16) Return true if a file exists @@ -642,7 +795,7 @@ Return true if a file exists <%= exists("foo.js") %> ``` -#### [read](lib/fs.js#L35) +#### [read](lib/helpers/fs.js#L29) Read a file from the file system and inject its content @@ -659,7 +812,7 @@ Read a file from the file system and inject its content ### html -#### [escapeHtml](lib/html.js#L18) +#### [escapeHtml](lib/helpers/html.js#L18) Escape HTML characters in a string. @@ -675,7 +828,7 @@ Escape HTML characters in a string. //=> <span>foo</span> ``` -#### [sanitize](lib/html.js#L46) +#### [sanitize](lib/helpers/html.js#L46) Strip HTML tags from a string, so that only the text nodes are preserved. @@ -693,7 +846,7 @@ Strip HTML tags from a string, so that only the text nodes are preserved. ### math -#### [add](lib/math.js#L18) +#### [add](lib/helpers/math.js#L17) Return the product of `a` plus `b`. @@ -709,7 +862,7 @@ Return the product of `a` plus `b`. //=> '3' ``` -#### [subtract](lib/math.js#L35) +#### [subtract](lib/helpers/math.js#L31) Subtract `b` from `a`. @@ -725,7 +878,7 @@ Subtract `b` from `a`. //=> '3' ``` -#### [divide](lib/math.js#L53) +#### [divide](lib/helpers/math.js#L46) Divide `a` (the numerator) by `b` (the divisor). @@ -742,7 +895,7 @@ Divide `a` (the numerator) by `b` (the divisor). //=> '5' ``` -#### [multiply](lib/math.js#L71) +#### [multiply](lib/helpers/math.js#L61) Multiply `a` by `b`. @@ -759,7 +912,7 @@ Multiply `a` by `b`. //=> '5' ``` -#### [floor](lib/math.js#L89) +#### [floor](lib/helpers/math.js#L76) Returns the largest integer less than or equal to the given `number`. @@ -775,7 +928,7 @@ Returns the largest integer less than or equal to the given `number`. //=> '10' ``` -#### [ceil](lib/math.js#L107) +#### [ceil](lib/helpers/math.js#L91) Returns the smallest integer greater than or equal to the given `number`. @@ -791,7 +944,7 @@ Returns the smallest integer greater than or equal to the given `number`. //=> '11' ``` -#### [round](lib/math.js#L128) +#### [round](lib/helpers/math.js#L109) Returns the value of the given `number` rounded to the nearest integer. @@ -810,7 +963,7 @@ Returns the value of the given `number` rounded to the nearest integer. //=> '11' ``` -#### [sum](lib/math.js#L145) +#### [sum](lib/helpers/math.js#L123) Returns the sum of all numbers in the given array. @@ -828,7 +981,7 @@ Returns the sum of all numbers in the given array. ### object -#### [fallback](lib/object.js#L22) +#### [fallback](lib/helpers/object.js#L22) Specify a fallback value to use when the desired value is undefined. Note that undefined variables that are _not object properties_ with throw an error. @@ -845,7 +998,7 @@ Specify a fallback value to use when the desired value is undefined. Note that u <%= fallback(page.title, site.title) %> ``` -#### [stringify](lib/object.js#L39) +#### [stringify](lib/helpers/object.js#L36) Stringify an object using `JSON.stringify()`. @@ -861,7 +1014,7 @@ Stringify an object using `JSON.stringify()`. //=> '{"a":"a"}' ``` -#### [parse](lib/object.js#L56) +#### [parse](lib/helpers/object.js#L50) Parse a string into an object using `JSON.parse()`. @@ -877,7 +1030,7 @@ Parse a string into an object using `JSON.parse()`. //=> 'bar' ``` -#### [get](lib/object.js#L74) +#### [get](lib/helpers/object.js#L65) Use property paths (`a.b.c`) get a nested value from an object. @@ -894,7 +1047,7 @@ Use property paths (`a.b.c`) get a nested value from an object. //=> 'c' ``` -#### [keys](lib/object.js#L91) +#### [keys](lib/helpers/object.js#L79) Returns an array of keys from the given `object`. @@ -910,7 +1063,7 @@ Returns an array of keys from the given `object`. //=> '["a", "c"]' ``` -#### [isObject](lib/object.js#L112) +#### [isObject](lib/helpers/object.js#L97) Return true if the given `value` is an object, and not `null` or an array. @@ -929,7 +1082,7 @@ Return true if the given `value` is an object, and not `null` or an array. //=> 'true' ``` -#### [isPlainObject](lib/object.js#L135) +#### [isPlainObject](lib/helpers/object.js#L117) Return true if the given `value` is a plain object. @@ -951,7 +1104,7 @@ Return true if the given `value` is a plain object. //=> 'false' ``` -#### [hasOwn](lib/object.js#L149) +#### [hasOwn](lib/helpers/object.js#L129) Return true if `key` is an own, enumerable property of the given `obj`. @@ -962,7 +1115,7 @@ of the given `obj`. * `key` **{String}** * `returns` **{Boolean}** -#### [omit](lib/object.js#L167) +#### [omit](lib/helpers/object.js#L144) Return a copy of `object` exclusing the given `keys`. @@ -979,9 +1132,9 @@ Return a copy of `object` exclusing the given `keys`. //=> '{b: "b"}' ``` -#### [forIn](lib/object.js#L185) +#### [forIn](lib/helpers/object.js#L163) -Return a copy of `object` exclusing the given `keys`. +Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. **Params** @@ -992,13 +1145,15 @@ Return a copy of `object` exclusing the given `keys`. **Example** ```js -<%= omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c']) %> -//=> '{b: "b"}' +const context = { values: { a: 'b', c: 'd' } }; +const str = '<% forIn(values, function(val, key) { %><%= val %><% }) %>'; +const fn = _.template(str, { imports: helpers }); +assert.equal(fn(context), 'bd'); ``` -#### [forOwn](lib/object.js#L207) +#### [forOwn](lib/helpers/object.js#L188) -Return a copy of `object` exclusing the given `keys`. +Iterate over the own enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false` **Params** @@ -1009,11 +1164,13 @@ Return a copy of `object` exclusing the given `keys`. **Example** ```js -<%= omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c']) %> -//=> '{b: "b"}' +const context = { values: { a: 'b', c: 'd' } }; +const str = '<% forOwn(values, function(val, key) { %><%= key %><% }) %>'; +const fn = _.template(str, { imports: helpers }); +console.log(fn(context)) //=> 'ac' ``` -#### [extend](lib/object.js#L224) +#### [extend](lib/helpers/object.js#L205) Extend `o` with properties of other `objects`. @@ -1023,7 +1180,7 @@ Extend `o` with properties of other `objects`. * `objects` **{Object}** * `returns` **{Object}** -#### [merge](lib/object.js#L257) +#### [merge](lib/helpers/object.js#L241) Recursively combine the properties of `o` with the properties of other `objects`. @@ -1036,7 +1193,7 @@ properties of other `objects`. ### path -#### [dirname](lib/path.js#L20) +#### [dirname](lib/helpers/path.js#L19) Return the dirname for the given `filepath`. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1052,7 +1209,7 @@ Return the dirname for the given `filepath`. Uses the node.js [path](https://nod //=> 'a/b/c' ``` -#### [basename](lib/path.js#L38) +#### [basename](lib/helpers/path.js#L34) Return the basename for the given `filepath`. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1068,9 +1225,9 @@ Return the basename for the given `filepath`. Uses the node.js [path](https://no //=> 'd.js' ``` -#### [filename](lib/path.js#L56) +#### [filename](lib/helpers/path.js#L49) -Return the filename for the given `filepath`, excluding extension. +Returns the filename for the given `filepath`, excluding extension. Aliased as `stem`. **Params** @@ -1080,11 +1237,27 @@ Return the filename for the given `filepath`, excluding extension. **Example** ```js -<%= basename("a/b/c/d.js") %> +<%= filename("a/b/c/d.js") %> //=> 'd' ``` -#### [extname](lib/path.js#L74) +#### [stem](lib/helpers/path.js#L65) + +Alias for [filename](#filename). + +**Params** + +* `filepath` **{String}** +* `returns` **{String}**: Returns the file name part of the file path. + +**Example** + +```js +<%= stem("a/b/c/d.js") %> +//=> 'd' +``` + +#### [extname](lib/helpers/path.js#L80) Return the file extension for the given `filepath`. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1100,7 +1273,7 @@ Return the file extension for the given `filepath`. Uses the node.js [path](http //=> '.js' ``` -#### [ext](lib/path.js#L92) +#### [ext](lib/helpers/path.js#L95) Return the file extension for the given `filepath`, excluding the `.`. @@ -1116,7 +1289,7 @@ Return the file extension for the given `filepath`, excluding the `.`. //=> 'js' ``` -#### [resolve](lib/path.js#L110) +#### [resolve](lib/helpers/path.js#L110) Resolves the given paths to an absolute path. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1132,7 +1305,7 @@ Resolves the given paths to an absolute path. Uses the node.js [path](https://no //=> '/foo/bar/baz' ``` -#### [relative](lib/path.js#L129) +#### [relative](lib/helpers/path.js#L126) Get the relative path from file `a` to file `b`. Typically `a` and `b` would be variables passed on the context. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1148,7 +1321,7 @@ Get the relative path from file `a` to file `b`. Typically `a` and `b` would be <%= relative(a, b) %> ``` -#### [segments](lib/path.js#L160) +#### [segments](lib/helpers/path.js#L162) Get specific (joined) segments of a file path by passing a range of array indices. @@ -1170,7 +1343,7 @@ Get specific (joined) segments of a file path by passing a range of array indice //=> 'b/c' ``` -#### [join](lib/path.js#L182) +#### [join](lib/helpers/path.js#L183) Join all arguments together and normalize the resulting `filepath`. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1189,7 +1362,7 @@ can be used with helpers to differentiate. Example: `<%= path.join() %>`. //=> 'a/b' ``` -#### [isAbsolute](lib/path.js#L217) +#### [isAbsolute](lib/helpers/path.js#L215) Returns true if a file path is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1220,7 +1393,7 @@ Returns true if a file path is an absolute path. An absolute path will always re //=> 'false' ``` -#### [isRelative](lib/path.js#L252) +#### [isRelative](lib/helpers/path.js#L247) Returns true if a file path is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. Uses the node.js [path](https://nodejs.org/api/path.html) module. @@ -1253,7 +1426,7 @@ Returns true if a file path is an absolute path. An absolute path will always re ### string -#### [camelcase](lib/string.js#L18) +#### [camelcase](lib/helpers/string.js#L24) camelCase the characters in `string`. @@ -1269,7 +1442,7 @@ camelCase the characters in `string`. //=> 'fooBarBaz' ``` -#### [centerAlign](lib/string.js#L45) +#### [centerAlign](lib/helpers/string.js#L46) Center align the characters in a string using non-breaking spaces. @@ -1284,7 +1457,7 @@ Center align the characters in a string using non-breaking spaces. <%= centerAlign("abc") %> ``` -#### [chop](lib/string.js#L69) +#### [chop](lib/helpers/string.js#L69) Like trim, but removes both extraneous whitespace and non-word characters from the beginning and end of a string. @@ -1306,7 +1479,7 @@ Like trim, but removes both extraneous whitespace and non-word characters from t //=> 'ABC' ``` -#### [count](lib/string.js#L90) +#### [count](lib/helpers/string.js#L88) Count the number of occurrances of a substring within a string. @@ -1323,7 +1496,7 @@ Count the number of occurrances of a substring within a string. //=> '3' ``` -#### [dotcase](lib/string.js#L110) +#### [dotcase](lib/helpers/string.js#L107) dot.case the characters in `string`. @@ -1339,7 +1512,7 @@ dot.case the characters in `string`. //=> 'a.b.c.d.e' ``` -#### [ellipsis](lib/string.js#L135) +#### [ellipsis](lib/helpers/string.js#L128) Truncate a string to the specified `length`, and append it with an elipsis, `…`. @@ -1357,7 +1530,7 @@ Truncate a string to the specified `length`, and append it with an elipsis, `… //=> 'foo bar…' ``` -#### [isString](lib/string.js#L157) +#### [isString](lib/helpers/string.js#L147) Returns true if the value is a string. @@ -1376,7 +1549,7 @@ Returns true if the value is a string. //=> 'false' ``` -#### [lowercase](lib/string.js#L174) +#### [lowercase](lib/helpers/string.js#L161) Lowercase the characters in the given `string`. @@ -1392,7 +1565,7 @@ Lowercase the characters in the given `string`. //=> 'abc' ``` -#### [pascalcase](lib/string.js#L191) +#### [pascalcase](lib/helpers/string.js#L177) PascalCase the characters in `string`. @@ -1408,7 +1581,7 @@ PascalCase the characters in `string`. //=> 'FooBarBaz' ``` -#### [snakecase](lib/string.js#L211) +#### [snakecase](lib/helpers/string.js#L196) snake_case the characters in `string`. @@ -1424,7 +1597,7 @@ snake_case the characters in `string`. //=> 'a_b_c_d_e' ``` -#### [split](lib/string.js#L233) +#### [split](lib/helpers/string.js#L214) Split `string` by the given `character`. @@ -1440,7 +1613,7 @@ Split `string` by the given `character`. //=> ['a', 'b', 'c'] ``` -#### [strip](lib/string.js#L250) +#### [strip](lib/helpers/string.js#L230) Strip `substring` from the given `string`. @@ -1456,7 +1629,7 @@ Strip `substring` from the given `string`. //=> 'bar' ``` -#### [stripIndent](lib/string.js#L269) +#### [stripIndent](lib/helpers/string.js#L248) Strip the indentation from a `string`. @@ -1472,7 +1645,7 @@ Strip the indentation from a `string`. //=> 'ABC' ``` -#### [trim](lib/string.js#L298) +#### [trim](lib/helpers/string.js#L275) Trim extraneous whitespace from the beginning and end of a string. @@ -1488,7 +1661,7 @@ Trim extraneous whitespace from the beginning and end of a string. //=> 'ABC' ``` -#### [dashcase](lib/string.js#L317) +#### [dashcase](lib/helpers/string.js#L291) dash-case the characters in `string`. This is similar to [slugify](https://github.com/simov/slugify), but [slugify](https://github.com/simov/slugify) makes the string compatible to be used as a URL slug. @@ -1504,7 +1677,7 @@ dash-case the characters in `string`. This is similar to [slugify](https://githu //=> 'a-b-c-d-e' ``` -#### [pathcase](lib/string.js#L339) +#### [pathcase](lib/helpers/string.js#L309) path/case the characters in `string`. @@ -1520,7 +1693,7 @@ path/case the characters in `string`. //=> 'a/b/c/d/e' ``` -#### [sentencecase](lib/string.js#L361) +#### [sentencecase](lib/helpers/string.js#L327) Sentence-case the characters in `string`. @@ -1536,7 +1709,7 @@ Sentence-case the characters in `string`. //=> 'Foo bar baz.' ``` -#### [hyphenate](lib/string.js#L380) +#### [hyphenate](lib/helpers/string.js#L345) Replace spaces in a string with hyphens. This @@ -1552,7 +1725,7 @@ Replace spaces in a string with hyphens. This //=> 'a-b-c' ``` -#### [reverse](lib/string.js#L414) +#### [reverse](lib/helpers/string.js#L377) Reverse the characters in a string. @@ -1568,7 +1741,7 @@ Reverse the characters in a string. //=> 'cba' ``` -#### [rightAlign](lib/string.js#L432) +#### [rightAlign](lib/helpers/string.js#L394) Right align the characters in a string using non-breaking spaces. @@ -1583,7 +1756,7 @@ Right align the characters in a string using non-breaking spaces. <%= rightAlign(str) %> ``` -#### [replace](lib/string.js#L451) +#### [replace](lib/helpers/string.js#L412) Replace occurrences of `a` with `b`. @@ -1601,7 +1774,7 @@ Replace occurrences of `a` with `b`. //=> 'zbczbc' ``` -#### [titlecase](lib/string.js#L473) +#### [titlecase](lib/helpers/string.js#L433) Truncate a string by removing all HTML tags and limiting the result to the specified `length`. @@ -1618,7 +1791,7 @@ Truncate a string by removing all HTML tags and limiting the result to the speci //=> 'foo bar' ``` -#### [truncate](lib/string.js#L492) +#### [truncate](lib/helpers/string.js#L451) Truncate a string by removing all HTML tags and limiting the result to the specified `length`. @@ -1635,7 +1808,7 @@ Truncate a string by removing all HTML tags and limiting the result to the speci //=> 'foo bar' ``` -#### [uppercase](lib/string.js#L509) +#### [uppercase](lib/helpers/string.js#L467) Uppercase the characters in a string. @@ -1651,7 +1824,7 @@ Uppercase the characters in a string. //=> 'ABC' ``` -#### [wordwrap](lib/string.js#L531) +#### [wordwrap](lib/helpers/string.js#L484) Wrap words to a specified width using [word-wrap](https://github.com/jonschlinkert/word-wrap). @@ -1668,7 +1841,7 @@ Wrap words to a specified width using [word-wrap](https://github.com/jonschlinke //=> ' a b c
d e f' ``` -### Code coverage +## Coverage ``` Statements : 94.61% ( 439/464 ) @@ -1679,49 +1852,60 @@ Lines : 94.42% ( 389/412 ) ## About -### Related projects - -* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") -* [handlebars-helpers](https://www.npmjs.com/package/handlebars-helpers): More than 130 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate… [more](https://github.com/assemble/handlebars-helpers) | [homepage](https://github.com/assemble/handlebars-helpers "More than 130 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate, Verb, Ghost, gulp-handlebars, grunt-handlebars, consolidate, or any node.js/Handlebars project.") -* [helper-cache](https://www.npmjs.com/package/helper-cache): Easily register and get helper functions to be passed to any template engine or node.js… [more](https://github.com/jonschlinkert/helper-cache) | [homepage](https://github.com/jonschlinkert/helper-cache "Easily register and get helper functions to be passed to any template engine or node.js application. Methods for both sync and async helpers.") -* [template](https://www.npmjs.com/package/template): Render templates using any engine. Supports, layouts, pages, partials and custom template types. Use template… [more](https://github.com/jonschlinkert/template) | [homepage](https://github.com/jonschlinkert/template "Render templates using any engine. Supports, layouts, pages, partials and custom template types. Use template helpers, middleware, routes, loaders, and lots more. Powers assemble, verb and other node.js apps.") -* [utils](https://www.npmjs.com/package/utils): Fast, generic JavaScript/node.js utility functions. | [homepage](https://github.com/jonschlinkert/utils "Fast, generic JavaScript/node.js utility functions.") -* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") - -### Contributing +
+Contributing Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). -### Building docs +
-_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ +
+Running Tests -To generate the readme and API documentation with [verb](https://github.com/verbose/verb): +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: ```sh -$ npm install -g verb verb-generate-readme && verb +$ npm install && npm test ``` -### Running tests +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ -Install dev dependencies: +To generate the readme, run the following command: ```sh -$ npm install -d && npm test +$ npm install -g verbose/verb#dev verb-generate-readme && verb ``` +
+ +### Related projects + +You might also be interested in the following projects (also visit the [github.com/helpers](https://github.com/helpers), where you can find 60+ additional standalone helpers!): + +* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") +* [handlebars-helpers](https://www.npmjs.com/package/handlebars-helpers): More than 130 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate… [more](https://github.com/helpers/handlebars-helpers) | [homepage](https://github.com/helpers/handlebars-helpers "More than 130 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate, Verb, Ghost, gulp-handlebars, grunt-handlebars, consolidate, or any node.js/Handlebars project.") +* [templates](https://www.npmjs.com/package/templates): System for creating and managing template collections, and rendering templates with any node.js template engine… [more](https://github.com/jonschlinkert/templates) | [homepage](https://github.com/jonschlinkert/templates "System for creating and managing template collections, and rendering templates with any node.js template engine. Can be used as the basis for creating a static site generator or blog framework.") + +### Contributors + ### Author **Jon Schlinkert** -* [github/jonschlinkert](https://github.com/jonschlinkert) -* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) ### License -Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). -Released under the [MIT license](https://github.com/jonschlinkert/template-helpers/blob/master/LICENSE). +Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). *** -_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on July 19, 2016._ \ No newline at end of file +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on November 24, 2018._ \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index a5ffec8..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -var gulp = require('gulp'); -var mocha = require('gulp-mocha'); -var istanbul = require('gulp-istanbul'); -var eslint = require('gulp-eslint'); - -gulp.task('coverage', function() { - return gulp.src(['index.js', 'lib/**/*.js']) - .pipe(istanbul({includeUntested: true})) - .pipe(istanbul.hookRequire()); -}); - -gulp.task('mocha', ['coverage'], function() { - return gulp.src('test/*.js') - .pipe(mocha()) - .pipe(istanbul.writeReports({ - reporters: ['html', 'text', 'text-summary'], - reportOpts: {dir: 'coverage', file: 'summary.txt'} - })) - .pipe(istanbul.writeReports()); -}); - -gulp.task('eslint', function() { - return gulp.src(['*.js', 'test/*.js', 'lib/**/*.js']) - .pipe(eslint()) - .pipe(eslint.format()); -}); - -gulp.task('default', ['eslint', 'mocha']); diff --git a/index.js b/index.js index 33fa5ad..0ea6f0b 100644 --- a/index.js +++ b/index.js @@ -1,46 +1,40 @@ +'use strict'; + /*! * template-helpers * - * Copyright (c) 2015, Jon Schlinkert. + * Copyright (c) 2015-present, Jon Schlinkert. * Licensed under the MIT License. */ -'use strict'; - -/** - * Expose helpers - */ +const helpers = require('./lib/helpers'); -module.exports = function(key) { - var lib = require('./lib'); - var forIn = lib.object.forIn; - var helpers = {}; +module.exports = key => { + let res = {}; if (typeof key === 'string') { - helpers = lib[key]; - helpers[key] = helpers; - return helpers; + res = helpers[key]; + res[key] = res; + return res; } if (Array.isArray(key)) { - return key.reduce(function(acc, k) { - acc[k] = lib[k]; - - forIn(acc[k], function(group, prop) { - acc[prop] = group; - }); - + return key.reduce((acc, k) => { + acc[k] = helpers[k]; + for (let prop of Object.keys(acc[k])) { + acc[prop] = acc[k][prop]; + } return acc; }, {}); } - forIn(lib, function(group, prop) { - helpers[prop] = group; + for (let prop of Object.keys(helpers)) { + let group = helpers[prop]; + res[prop] = group; - forIn(group, function(v, k) { - helpers[k] = v; - }); - }); - - return helpers; + for (let k of Object.keys(group)) { + res[k] = group[k]; + } + } + return res; }; diff --git a/lib/conditional.js b/lib/conditional.js deleted file mode 100644 index 478a8f5..0000000 --- a/lib/conditional.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -/** - * Return true if `key` is an own, enumerable property - * of the given `obj`. - * - * @param {Object} `object` - * @param {String} `key` - * @return {Boolean} - * @api public - */ - -exports._if = function if_(fn, a, b, thisArg) { - if (typeof fn !== 'function') return ''; - - thisArg = thisArg || this || null; - var res = fn.call(thisArg, a, b); - - if (res) return a; - return b; -}; - diff --git a/lib/array.js b/lib/helpers/array.js similarity index 79% rename from lib/array.js rename to lib/helpers/array.js index c7beff3..e0aa164 100644 --- a/lib/array.js +++ b/lib/helpers/array.js @@ -1,7 +1,7 @@ 'use strict'; -var object = require('./object'); -var utils = require('./utils'); +const object = require('./object'); +const utils = require('../utils'); /** * Returns true if `value` is an array. @@ -13,15 +13,12 @@ var utils = require('./utils'); * <%= isArray(['a, b, c']) %> * //=> 'true' * ``` - * * @param {*} `value` The value to test. * @return {Boolean} * @api public */ -exports.isArray = function isArray(val) { - return Array.isArray(val); -}; +exports.isArray = val => Array.isArray(val); /** * Cast `val` to an array. @@ -36,16 +33,13 @@ exports.isArray = function isArray(val) { * <%= arrayify(['a']) %> * //=> '["a"]' * ``` - * * @param {*} `val` The value to arrayify. * @return {Array} An array. * @return {Array} * @api public */ -exports.arrayify = function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -}; +exports.arrayify = val => [].concat(val != null ? val : []); /** * Returns the first item, or first `n` items of an array. @@ -54,20 +48,19 @@ exports.arrayify = function arrayify(val) { * <%= first(['a', 'b', 'c', 'd', 'e'], 2) %> * //=> '["a", "b"]' * ``` - * + * @name .first * @param {Array} `array` * @param {Number} `n` Number of items to return, starting at `0`. * @return {Array} * @api public */ -exports.first = function first(arr, n) { +exports.first = (arr, n) => { if (utils.isEmpty(arr)) return ''; if (utils.isNumber(n)) { return arr.slice(0, n); - } else { - return arr[0]; } + return arr[0]; }; /** @@ -77,20 +70,18 @@ exports.first = function first(arr, n) { * <%= last(['a', 'b', 'c', 'd', 'e'], 2) %> * //=> '["d", "e"]' * ``` - * * @param {Array} `array` * @param {Number} `n` Number of items to return, starting with the last item. * @return {Array} * @api public */ -exports.last = function last(arr, n) { +exports.last = (arr, n) => { if (utils.isEmpty(arr)) return ''; if (!utils.isNumber(n)) { return arr[arr.length - 1]; - } else { - return arr.slice(-n); } + return arr.slice(-n); }; /** @@ -101,7 +92,6 @@ exports.last = function last(arr, n) { * <%= before(['a', 'b', 'c'], 2) %> * //=> '["a", "b"]' * ``` - * * @param {Array} `array` * @param {Number} `n` * @return {Array} Array excluding items after the given number. @@ -109,7 +99,7 @@ exports.last = function last(arr, n) { * @api public */ -exports.before = function before(arr, n) { +exports.before = (arr, n) => { return !utils.isEmpty(arr) ? arr.slice(0, -n) : ''; }; @@ -121,7 +111,6 @@ exports.before = function before(arr, n) { * <%= after(['a', 'b', 'c'], 1) %> * //=> '["c"]' * ``` - * * @param {Array} `array` Collection * @param {Number} `n` Starting index (number of items to exclude) * @return {Array} Array exluding `n` items. @@ -129,7 +118,7 @@ exports.before = function before(arr, n) { * @api public */ -exports.after = function after(arr, n) { +exports.after = (arr, n) => { return !utils.isEmpty(arr) ? arr.slice(n) : ''; }; @@ -149,22 +138,21 @@ exports.after = function after(arr, n) { * <%= each(['a', 'b', 'c'], double, ctx) %> * //=> '["aa", "bb", "cc"]' * ``` - * * @param {Array} `array` * @param {String} `fn` The function to call on each element in the given array. * @return {String} * @api public */ -exports.each = function each(arr, fn, context) { +exports.each = (arr, fn, context) => { if (utils.isEmpty(arr)) { return ''; } - var len = arr.length; - var idx = -1; - var res = ''; - var val; + let len = arr.length; + let idx = -1; + let res = ''; + let val; while (++idx < len) { if ((val = fn.call(context, arr[idx], idx, arr)) === false) { @@ -191,19 +179,18 @@ exports.each = function each(arr, fn, context) { * <%= map(['a', 'b', 'c'], double) %> * //=> '["aa", "bb", "cc"]' * ``` - * * @param {Array} `array` * @param {String} `fn` The function to call on each element in the given array. * @return {String} * @api public */ -exports.map = function map(arr, fn, context) { +exports.map = (arr, fn, context) => { if (utils.isEmpty(arr)) return ''; - var len = arr.length; - var res = new Array(len); - var idx = -1; + let len = arr.length; + let res = new Array(len); + let idx = -1; while (++idx < len) { res[idx] = fn.call(context, arr[idx], idx, arr); @@ -222,17 +209,15 @@ exports.map = function map(arr, fn, context) { * <%= join(['a', 'b', 'c'], '-') %> * //=> 'a-b-c' * ``` - * * @param {Array} `array` * @param {String} `sep` The separator to use. * @return {String} * @api public */ -exports.join = function join(arr, sep) { +exports.join = (arr, sep) => { if (utils.isEmpty(arr)) return ''; - sep = typeof sep !== 'string' ? ', ' : sep; - return arr.join(sep); + return arr.join(typeof sep !== 'string' ? ', ' : sep); }; /** @@ -248,30 +233,27 @@ exports.join = function join(arr, sep) { * <%= sort([{a: "zzz"}, {a: "aaa"}], "a") %> * //=> '[{"a":"aaa"},{"a":"zzz"}]' * ``` - * * @param {Array} `array` the array to sort. * @param {String|Function} `key` The object key to sort by, or sorting function. * @api public */ -exports.sort = function sort(arr, key) { +exports.sort = (arr, key) => { if (utils.isEmpty(arr)) return ''; if (typeof key === 'function') { return arr.sort(key); } - if (typeof key !== 'string') { return arr.sort(); } - - return arr.sort(function(a, b) { + return arr.sort((a, b) => { if (object.isObject(a) && typeof a[key] === 'string') { return a[key].localeCompare(b[key]); - } else if (typeof a === 'string') { + } + if (typeof a === 'string') { return a.localeCompare(b); - } else { - return a > b; } + return a > b; }); }; @@ -282,13 +264,12 @@ exports.sort = function sort(arr, key) { * <%= length(['a', 'b', 'c']) %> * //=> 3 * ``` - * * @param {Array} `array` * @return {Number} The length of the array. * @api public */ -exports.length = function length(arr) { +exports.length = arr => { if (utils.isEmpty(arr)) return ''; return Array.isArray(arr) ? arr.length : 0; }; @@ -300,13 +281,12 @@ exports.length = function length(arr) { * <%= compact([null, a, undefined, 0, false, b, c, '']) %> * //=> '["a", "b", "c"]' * ``` - * * @param {Array} `arr` * @return {Array} * @api public */ -exports.compact = function compact(arr) { +exports.compact = arr => { return !utils.isEmpty(arr) ? arr.filter(Boolean) : ''; }; @@ -318,28 +298,29 @@ exports.compact = function compact(arr) { * <%= difference(["a", "c"], ["a", "b"]) %> * //=> '["c"]' * ``` - * * @param {Array} `array` The array to compare againts. * @param {Array} `arrays` One or more additional arrays. * @return {Array} * @api public */ -exports.difference = function difference(a, b, c) { - if (utils.isEmpty(a)) return ''; - var len = a.length; - var arr = []; - var rest; +exports.difference = (...args) => { + if (utils.isEmpty(args)) return ''; + let [ a, b, c ] = args; + let len = a.length; + let arr = []; + let rest; - if (!b) { + if (b == null) { return a; } - if (!c) { + if (c == null) { rest = b; } else { - rest = [].concat.apply([], [].slice.call(arguments, 1)); + rest = utils.flatten(args.slice(1)); } + while (len--) { if (rest.indexOf(a[len]) === -1) { arr.unshift(a[len]); @@ -355,19 +336,18 @@ exports.difference = function difference(a, b, c) { * <%= unique(['a', 'b', 'c', 'c']) % * => '["a", "b", "c"]' * ``` - * * @param {Array} `array` The array to uniquify * @return {Array} Duplicate-free array * @api public */ -exports.unique = function unique(arr) { +exports.unique = arr => { if (utils.isEmpty(arr)) return ''; - var len = arr.length; - var i = -1; + let len = arr.length; + let i = -1; while (i++ < len) { - var j = i + 1; + let j = i + 1; for (; j < arr.length; ++j) { if (arr[i] === arr[j]) { @@ -385,14 +365,13 @@ exports.unique = function unique(arr) { * <%= union(["a"], ["b"], ["c"]) %> * //=> '["a", "b", "c"]' * ``` - * * @param {Array} `arr` * @return {Array} * @api public */ -exports.union = function union(arr) { - return !utils.isEmpty(arr) ? utils.union([], [].concat.apply([], arguments)) : ''; +exports.union = (...args) => { + return !utils.isEmpty(args) ? utils.union([], [].concat.apply([], args)) : ''; }; /** @@ -402,19 +381,18 @@ exports.union = function union(arr) { * <%= shuffle(["a", "b", "c"]) %> * //=> ["c", "a", "b"] * ``` - * * @param {Array} `arr` * @return {Array} * @api public */ -exports.shuffle = function shuffle(arr) { - var len = arr.length; - var res = new Array(len); - var i = -1; +exports.shuffle = arr => { + let len = arr.length; + let res = new Array(len); + let i = -1; while (++i < len) { - var rand = utils.random(0, i); + let rand = utils.random(0, i); if (i !== rand) { res[i] = res[rand]; } diff --git a/lib/code.js b/lib/helpers/code.js similarity index 76% rename from lib/code.js rename to lib/helpers/code.js index de02cfb..84ba03e 100755 --- a/lib/code.js +++ b/lib/helpers/code.js @@ -1,9 +1,9 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var utils = require('./utils'); -var obj = require('./object'); +const fs = require('fs'); +const path = require('path'); +const utils = require('../utils'); +const object = require('./object'); /** * Embed code from an external file as preformatted text. @@ -14,23 +14,21 @@ var obj = require('./object'); * // specify the language to use * <%= embed('path/to/file.hbs', 'html') %> * ``` - * * @param {String} `fp` filepath to the file to embed. * @param {String} `language` Optionally specify the language to use for syntax highlighting. * @return {String} * @api public */ -exports.embed = function embed(fp, ext) { +exports.embed = (fp, ext) => { ext = typeof ext !== 'string' ? path.extname(fp).slice(1) : ext; - var code = fs.readFileSync(fp, 'utf8'); + let code = fs.readFileSync(fp, 'utf8'); // if the string is markdown, escape backticks if (ext === 'markdown' || ext === 'md') { code = code.split('`').join('`'); } - - return utils.block(code, ext) + '\n'; + return utils.toCodeBlock(code, ext) + '\n'; }; /** @@ -39,14 +37,13 @@ exports.embed = function embed(fp, ext) { * ```js * <%= jsfiddle({id: '0dfk10ks', {tabs: true}}) %> * ``` - * * @param {Object} `params` * @return {String} * @api public */ -exports.jsfiddle = function jsFiddle(attr) { - if (!attr || !obj.isPlainObject(attr)) return ''; +exports.jsfiddle = attr => { + if (!attr || !object.isPlainObject(attr)) return ''; attr.id = 'http://jsfiddle.net/' + (attr.id || ''); attr.width = attr.width || '100%'; attr.height = attr.height || '300'; @@ -55,7 +52,6 @@ exports.jsfiddle = function jsFiddle(attr) { attr.src = attr.id + '/embedded/' + attr.tabs; attr.allowfullscreen = attr.allowfullscreen || 'allowfullscreen'; attr.frameborder = attr.frameborder || '0'; - - attr = obj.omit(attr, ['id', 'tabs', 'skin']); + attr = object.omit(attr, ['id', 'tabs', 'skin']); return ''; }; diff --git a/lib/collection.js b/lib/helpers/collection.js similarity index 54% rename from lib/collection.js rename to lib/helpers/collection.js index 35b9c23..7f7d74e 100644 --- a/lib/collection.js +++ b/lib/helpers/collection.js @@ -1,6 +1,8 @@ 'use strict'; -var utils = require('./utils'); +const any = require('any'); +const iterator = require('../iterator'); +const utils = require('../utils'); /** * Returns `true` if `value` exists in the given string, array @@ -12,9 +14,7 @@ var utils = require('./utils'); * @api public */ -exports.any = function any(value, target) { - return utils.any.apply(utils.any, arguments); -}; +exports.any = any; /** * Filter the given array or object to contain only the matching values. @@ -29,32 +29,32 @@ exports.any = function any(value, target) { * @api public */ -exports.filter = function filter(val, fn, context) { +exports.filter = (val, fn, context) => { if (utils.isEmpty(val)) return ''; - var iterator = function() {}; + let iter = () => {}; + if (typeof fn === 'string') { - var prop = fn; - iterator = function(target) { - if (typeof target === 'string') { - return target === prop; - } - return target[prop]; + let prop = fn; + iter = target => { + return typeof target === 'string' ? target === prop : target[prop]; }; } else { - iterator = utils.makeIterator(fn, context); + iter = iterator(fn, context); } + if (typeof val === 'string') { - return iterator(val); + return iter(val); } + if (Array.isArray(val)) { - return val.filter(iterator); + return val.filter(iter); } if (utils.isObject(val)) { - var obj = val; - var res = {}; - for (var key in obj) { - if (obj.hasOwnProperty(key) && iterator(key)) { + let obj = val; + let res = {}; + for (let key in obj) { + if (obj.hasOwnProperty(key) && iter(key)) { res[key] = obj[key]; } } diff --git a/lib/helpers/conditional.js b/lib/helpers/conditional.js new file mode 100644 index 0000000..81bfe1d --- /dev/null +++ b/lib/helpers/conditional.js @@ -0,0 +1,233 @@ +'use strict'; + +/** + * Returns true when both `valueA` and `valueB` are truthy. + * + * @name .and + * @param {any} `valueA` + * @param {any} `valueB` + * @return {Boolean} + * @api public + */ + +exports.and = (valueA, valueB) => !!valueA && !!valueB; + +/** + * Render a block when a comparison of the first and third arguments + * returns true. + * + * ```js + * <%= compare("foo", "!==", "bar") %> + * ``` + * @name .compare + * @param {String} `valueA` + * @param {String} `operator` The operator to use for the comparison (must be a quoted string). + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.compare = function(a, operator, b) { + /* eslint-disable eqeqeq */ + + if (arguments.length < 3) { + throw new Error('"compare" helper - expected 3 arguments'); + } + + switch (operator) { + case '!=': + return a != b; + case '!==': + return a !== b; + case '<': + return a < b; + case '<=': + return a <= b; + case '==': + return a == b; + case '===': + return a === b; + case '>': + return a > b; + case '>=': + return a >= b; + case 'typeof': + return typeof a === b; + default: { + throw new Error(`"compare" helper - invalid operator: "${operator}"`); + } + } + return false; +}; + +/** + * Returns the first truthy value. + * + * @name .find + * @param {...args} `...values` + * @return {any} + * @api public + */ + +exports.find = (...values) => values.find(v => !!v); + +/** + * Returns true when all provided values are truthy. + * + * @name .every + * @param {...any} `...values` + * @return {Boolean} + * @api public + */ + +exports.every = (...args) => { + for (let ele of args) if (!ele) return false; + return true; +}; + +/** + * Returns true when `valueA` is greater than `valueB`. + * + * @name .gt + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.gt = (a, b) => a > b; + +/** + * Returns true when `valueA` is greater than or equal to `valueB`. + * + * @name .gte + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.gte = (a, b) => a >= b; + +/** + * Return true if `key` is an own, enumerable property + * of the given `obj`. + * + * @param {Object} `object` + * @param {String} `key` + * @return {Boolean} + * @api public + */ + +exports._if = function if_(fn, a, b, thisArg) { + if (typeof fn !== 'function') return ''; + + thisArg = thisArg || this || null; + let res = fn.call(thisArg, a, b); + if (res) return a; + return b; +}; + +/** + * Returns true when `valueA` equals `valueB`. + * + * @name .is + * @param {String} `valueA` + * @param {String} `valueB` + * @param {String} `strict` + * @return {Boolean} + * @api public + */ + +exports.is = (a, b, strict = true) => { + return strict ? a === b : a == b; +}; + +/** + * Alias for [is](#is). + * + * @name .eq + * @param {String} `valueA` + * @param {String} `valueB` + * @param {String} `strict` + * @return {Boolean} + * @api public + */ + +exports.eq = exports.is; + +/** + * Returns true when `valueA` does not equal `valueB`. + * + * @name .isnt + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.isnt = (a, b, strict = true) => { + return strict ? a !== b : a != b; +}; + +/** + * Alias for [isnt](#isnt). + * + * @name .notEq + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.notEq = exports.isnt; + +/** + * Returns true when `valueA` is less than `valueB`. + * + * @name .lt + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.lt = (a, b) => a < b; + +/** + * Returns true when `valueA` is less than or equal to `valueB`. + * + * @name .lte + * @param {String} `valueA` + * @param {String} `valueB` + * @return {Boolean} + * @api public + */ + +exports.lte = (a, b) => a <= b; + +/** + * Returns `valueA` if thruthy, otherwise `valueB`. + * + * @name .or + * @param {any} `valueA` + * @param {any} `valueB` + * @return {any} + * @api public + */ + +exports.or = (valueA, valueB) => !!valueA ? valueA : valueB; + +/** + * Returns true when at least one value is truthy. + * + * @name .some + * @param {...any} `...values` + * @return {Boolean} + * @api public + */ + +exports.some = (...args) => { + for (let ele of args) if (!!ele) return true; + return false; +}; diff --git a/lib/fs.js b/lib/helpers/fs.js similarity index 63% rename from lib/fs.js rename to lib/helpers/fs.js index 1f2a43e..fe4d05e 100644 --- a/lib/fs.js +++ b/lib/helpers/fs.js @@ -1,8 +1,6 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var exists = require('fs-exists-sync'); +const fs = require('fs'); /** * Return true if a file exists @@ -10,15 +8,12 @@ var exists = require('fs-exists-sync'); * ```js * <%= exists("foo.js") %> * ``` - * * @param {String} `filepath` Path of the file to check. * @return {Boolean} True if the file exists * @api public */ -exports.exists = function(filepath) { - return filepath && exists(filepath); -}; +exports.exists = filepath => filepath && fs.existsSync(filepath); /** * Read a file from the file system and inject its content @@ -26,14 +21,12 @@ exports.exists = function(filepath) { * ```js * <%= read("foo.js") %> * ``` - * * @param {String} `filepath` Path of the file to read. * @return {String} Contents of the given file. * @api public */ -exports.read = function read(filepath) { - filepath = path.resolve(filepath); - if (!exists(filepath)) return ''; +exports.read = filepath => { + if (!exports.exists(filepath)) return ''; return fs.readFileSync(filepath, 'utf8'); }; diff --git a/lib/html.js b/lib/helpers/html.js similarity index 82% rename from lib/html.js rename to lib/helpers/html.js index b77be33..3736e6b 100644 --- a/lib/html.js +++ b/lib/helpers/html.js @@ -1,6 +1,6 @@ 'use strict'; -var string = require('./string'); +const string = require('./string'); /** * Escape HTML characters in a string. @@ -15,9 +15,9 @@ var string = require('./string'); * @api public */ -exports.escapeHtml = function escapeHtml(str) { +exports.escapeHtml = str => { if (!string.isString(str)) return ''; - return str.replace(/[\/"'&<>]/g, function(ch) { + return str.replace(/[/"'&<>]/g, ch => { return ({ '"': '"', '&': '&', @@ -43,6 +43,6 @@ exports.escapeHtml = function escapeHtml(str) { * @api public */ -exports.sanitize = function sanitize(str) { +exports.sanitize = str => { return string.isString(str) ? str.replace(/(<([^>]+)>)/g, '').trim() : ''; }; diff --git a/lib/helpers/index.js b/lib/helpers/index.js new file mode 100644 index 0000000..cbdd7fc --- /dev/null +++ b/lib/helpers/index.js @@ -0,0 +1,19 @@ +'use strict'; + +const define = (obj, k, fn) => { + Reflect.defineProperty(obj, k, { + enumerable: true, + get: fn + }); +}; + +define(exports, 'string', () => require('./string')); +define(exports, 'path', () => require('./path')); +define(exports, 'object', () => require('./object')); +define(exports, 'math', () => require('./math')); +define(exports, 'html', () => require('./html')); +define(exports, 'fs', () => require('./fs')); +define(exports, 'conditional', () => require('./conditional')); +define(exports, 'collection', () => require('./collection')); +define(exports, 'code', () => require('./code')); +define(exports, 'array', () => require('./array')); diff --git a/lib/math.js b/lib/helpers/math.js similarity index 70% rename from lib/math.js rename to lib/helpers/math.js index 63194d9..27f4929 100644 --- a/lib/math.js +++ b/lib/helpers/math.js @@ -1,6 +1,6 @@ 'use strict'; -var utils = require('./utils'); +const utils = require('../utils'); /** * Return the product of `a` plus `b`. @@ -9,15 +9,12 @@ var utils = require('./utils'); * <%= add(1, 2) %> * //=> '3' * ``` - * * @param {Number} `a` * @param {Number} `b` * @api public */ -exports.add = function add(a, b) { - return a + b; -}; +exports.add = (a, b) => a + b; /** * Subtract `b` from `a`. @@ -26,15 +23,12 @@ exports.add = function add(a, b) { * <%= subtract(5, 2) %> * //=> '3' * ``` - * * @param {Number} `a` * @param {Number} `b` * @api public */ -exports.subtract = function subtract(a, b) { - return a - b; -}; +exports.subtract = (a, b) => Number(a) - Number(b); /** * Divide `a` (the numerator) by `b` (the divisor). @@ -43,16 +37,13 @@ exports.subtract = function subtract(a, b) { * <%= divide(10, 2) %> * //=> '5' * ``` - * * @param {Number} `a` the numerator. * @param {Number} `b` the divisor. * @return {Number} The quotient of `a` divided by `b`. * @api public */ -exports.divide = function divide(a, b) { - return (+a) / (+b); -}; +exports.divide = (a, b) => Number(a) / Number(b); /** * Multiply `a` by `b`. @@ -61,16 +52,13 @@ exports.divide = function divide(a, b) { * <%= divide(10, 2) %> * //=> '5' * ``` - * * @param {Number} `a` * @param {Number} `b` * @return {Number} The product of `a` times `b`. * @api public */ -exports.multiply = function multiply(a, b) { - return (+a) * (+b); -}; +exports.multiply = (a, b) => Number(a) * Number(b); /** * Returns the largest integer less than or equal to the @@ -80,15 +68,12 @@ exports.multiply = function multiply(a, b) { * <%= floor(10.6) %> * //=> '10' * ``` - * * @param {Number} `number` * @return {Number} * @api public */ -exports.floor = function floor(n) { - return Math.floor(+n); -}; +exports.floor = n => Math.floor(n); /** * Returns the smallest integer greater than or equal to the @@ -98,15 +83,12 @@ exports.floor = function floor(n) { * <%= ceil(10.1) %> * //=> '11' * ``` - * * @param {Number} `number` * @return {Number} * @api public */ -exports.ceil = function ceil(n) { - return Math.ceil(+n); -}; +exports.ceil = n => Math.ceil(n); /** * Returns the value of the given `number` rounded to the @@ -119,15 +101,12 @@ exports.ceil = function ceil(n) { * <%= round(10.5) %> * //=> '11' * ``` - * * @param {Number} `number` * @return {Number} * @api public */ -exports.round = function round(n) { - return Math.round(+n); -}; +exports.round = n => Math.round(n); /** * Returns the sum of all numbers in the given array. @@ -136,23 +115,22 @@ exports.round = function round(n) { * <%= sum([1, 2, 3, 4, 5]) %> * //=> '15' * ``` - * * @param {Number} `number` * @return {Number} * @api public */ -exports.sum = function sum() { - var args = utils.flatten([].concat.apply([], arguments)); - var len = args.length; - var idx = -1; - var num = 0; +exports.sum = (...args) => { + let arr = [].concat.apply([], args); + let len = arr.length; + let idx = -1; + let num = 0; while (++idx < len) { - if (!utils.isNumber(args[idx])) { + if (!utils.isNumber(arr[idx])) { continue; } - num += (+args[idx]); + num += (+arr[idx]); } return num; }; diff --git a/lib/object.js b/lib/helpers/object.js similarity index 60% rename from lib/object.js rename to lib/helpers/object.js index 2898c93..193b8cd 100644 --- a/lib/object.js +++ b/lib/helpers/object.js @@ -1,7 +1,8 @@ 'use strict'; -var hasOwn = Object.prototype.hasOwnProperty; -var utils = require('./utils'); +const hasOwn = Object.prototype.hasOwnProperty; +const get = require('get-value'); +const utils = require('../utils'); /** * Specify a fallback value to use when the desired @@ -12,16 +13,13 @@ var utils = require('./utils'); * // when `title` is undefined, use the generic `site.title` * <%= fallback(page.title, site.title) %> * ``` - * * @param {*} `a` The desired value. * @param {*} `b` The fallback ("default") value * @return {*} Either `a` or `b` * @api public */ -exports.fallback = function fallback(a, b) { - return a != null ? a : b; -}; +exports.fallback = (a, b) => a != null ? a : b; /** * Stringify an object using `JSON.stringify()`. @@ -30,15 +28,12 @@ exports.fallback = function fallback(a, b) { * <%= stringify({a: "a"}) %> * //=> '{"a":"a"}' * ``` - * * @param {Object} `object` * @return {String} * @api public */ -exports.stringify = function stringify(obj) { - return JSON.stringify(obj); -}; +exports.stringify = obj => JSON.stringify(obj); /** * Parse a string into an object using `JSON.parse()`. @@ -47,15 +42,12 @@ exports.stringify = function stringify(obj) { * <%= parse('{"foo":"bar"}')["foo"] %> * //=> 'bar' * ``` - * * @param {String} `str` The string to parse. * @return {Object} The parsed object. * @api public */ -exports.parse = function parse(str) { - return JSON.parse(str); -}; +exports.parse = str => utils.isString(str) ? JSON.parse(str) : void 0; /** * Use property paths (`a.b.c`) get a nested value from an object. @@ -64,16 +56,13 @@ exports.parse = function parse(str) { * <%= get({a: {b: 'c'}}, 'a.b') %> * //=> 'c' * ``` - * * @param {Object} `object` * @param {String} `path` Dot notation for the property to get. * @return {String} * @api public */ -exports.get = function get(obj, prop) { - return utils.get.apply(utils.get, arguments); -}; +exports.get = (obj, prop, options) => get(obj, prop, options); /** * Returns an array of keys from the given `object`. @@ -82,15 +71,12 @@ exports.get = function get(obj, prop) { * <%= keys({a: 'b', c: 'd'}) %> * //=> '["a", "c"]' * ``` - * * @param {Object} `object` * @return {Array} Keys from `object` * @api public */ -exports.keys = function keys(obj) { - return Object.keys(obj); -}; +exports.keys = obj => Object.keys(obj); /** * Return true if the given `value` is an object, and @@ -103,15 +89,12 @@ exports.keys = function keys(obj) { * <%= isObject({a: 'b'}) %> * //=> 'true' * ``` - * * @param {Object} `value` The value to check. * @return {Boolean} * @api public */ -exports.isObject = function isObject(val) { - return utils.typeOf(val) === 'object'; -}; +exports.isObject = utils.isObject; /** * Return true if the given `value` is a plain object. @@ -126,15 +109,12 @@ exports.isObject = function isObject(val) { * <%= isPlainObject(/foo/g) %> * //=> 'false' * ``` - * * @param {Object} `value` The value to check. * @return {Boolean} * @api public */ -exports.isPlainObject = function isPlainObject(val) { - return utils.isPlainObject(val); -}; +exports.isPlainObject = val => utils.isPlainObject(val); /** * Return true if `key` is an own, enumerable property @@ -146,9 +126,7 @@ exports.isPlainObject = function isPlainObject(val) { * @api public */ -exports.hasOwn = function hasOwn_(obj, key) { - return hasOwn.call(obj, key); -}; +exports.hasOwn = (obj, key) => hasOwn.call(obj, key); /** * Return a copy of `object` exclusing the given `keys`. @@ -157,33 +135,33 @@ exports.hasOwn = function hasOwn_(obj, key) { * <%= omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c']) %> * //=> '{b: "b"}' * ``` - * * @param {Object} `object` Object with keys to omit. * @param {String} `keys` Keys to omit. * @return {Boolean} * @api public */ -exports.omit = function omit(o, keys) { - return utils.omit.apply(utils.omit, arguments); -}; +exports.omit = (obj, keys) => utils.omit(obj, keys); /** - * Return a copy of `object` exclusing the given `keys`. + * Iterate over the own and inherited enumerable properties of an object, + * and return an object with properties that evaluate to true from the + * callback. Exit early by returning `false`. * * ```js - * <%= omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c']) %> - * //=> '{b: "b"}' + * const context = { values: { a: 'b', c: 'd' } }; + * const str = '<% forIn(values, function(val, key) { %><%= val %><% }) %>'; + * const fn = _.template(str, { imports: helpers }); + * assert.equal(fn(context), 'bd'); * ``` - * * @param {Object} `object` Object with keys to omit. * @param {String} `keys` Keys to omit. * @return {Boolean} * @api public */ -exports.forIn = function forIn(obj, fn, context) { - for (var key in obj) { +exports.forIn = (obj, fn, context) => { + for (let key in obj) { if (fn.call(context, obj[key], key, obj) === false) { break; } @@ -191,21 +169,24 @@ exports.forIn = function forIn(obj, fn, context) { }; /** - * Return a copy of `object` exclusing the given `keys`. + * Iterate over the own enumerable properties of an object, + * and return an object with properties that evaluate to true + * from the callback. Exit early by returning `false` * * ```js - * <%= omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c']) %> - * //=> '{b: "b"}' + * const context = { values: { a: 'b', c: 'd' } }; + * const str = '<% forOwn(values, function(val, key) { %><%= key %><% }) %>'; + * const fn = _.template(str, { imports: helpers }); + * console.log(fn(context)) //=> 'ac' * ``` - * * @param {Object} `object` Object with keys to omit. * @param {String} `keys` Keys to omit. * @return {Boolean} * @api public */ -exports.forOwn = function forOwn(obj, fn, context) { - exports.forIn(obj, function(val, key) { +exports.forOwn = (obj, fn, context) => { + exports.forIn(obj, (val, key) => { if (hasOwn.call(obj, key)) { return fn.call(context, obj[key], key, obj); } @@ -221,26 +202,29 @@ exports.forOwn = function forOwn(obj, fn, context) { * @api public */ -exports.extend = function extend(obj) { - if (utils.typeOf(obj) !== 'object') { return ''; } - var args = arguments; - var len = args.length - 1; +exports.extend = (obj, ...rest) => { + if (!utils.isObject(obj)) return ''; + let last = rest[rest.length - 1]; + if (utils.isObject(last) && last.hash) { + rest.pop(); + } + + let len = rest.length; if (len === 0) { return obj; } - for (var i = 0; i < len; i++) { - var val = args[i + 1]; - - if (utils.typeOf(val) === 'object') { - for (var key in val) { - if (exports.hasOwn(val, key)) { - obj[key] = val[key]; + for (let ele of rest) { + if (utils.isObject(ele)) { + for (let key in ele) { + if (exports.hasOwn(ele, key)) { + obj[key] = ele[key]; } } } } + return obj; }; @@ -254,27 +238,32 @@ exports.extend = function extend(obj) { * @api public */ -exports.merge = function merge(obj) { - if (utils.typeOf(obj) !== 'object') { return ''; } - var args = arguments; - var len = args.length - 1; +exports.merge = (obj, ...rest) => { + if (!utils.isObject(obj)) return ''; + let last = rest[rest.length - 1]; + if (utils.isObject(last) && last.hash) { + rest.pop(); + } + + let len = rest.length; if (len === 0) { return obj; } - for (var i = 0; i < len; i++) { - var val = args[i + 1]; - - for (var key in val) { - if (exports.hasOwn(val, key)) { - if (utils.typeOf(val[key]) === 'object') { - obj[key] = exports.merge(obj[key], val[key]); - } else { - obj[key] = val[key]; + for (let ele of rest) { + if (utils.isObject(ele)) { + for (let key in ele) { + if (exports.hasOwn(ele, key)) { + if (utils.isObject(ele[key])) { + obj[key] = exports.merge(obj[key], ele[key]); + } else { + obj[key] = ele[key]; + } } } } } + return obj; }; diff --git a/lib/path.js b/lib/helpers/path.js similarity index 76% rename from lib/path.js rename to lib/helpers/path.js index fe1f64c..d63a689 100644 --- a/lib/path.js +++ b/lib/helpers/path.js @@ -1,7 +1,7 @@ 'use strict'; -var path = require('path'); -var utils = require('./utils'); +const path = require('path'); +const relative = require('relative'); /** * Return the dirname for the given `filepath`. Uses @@ -11,15 +11,12 @@ var utils = require('./utils'); * <%= dirname("a/b/c/d") %> * //=> 'a/b/c' * ``` - * * @param {String} `filepath` * @return {String} Returns the directory part of the file path. * @api public */ -exports.dirname = function dirname(filepath) { - return path.dirname(filepath); -}; +exports.dirname = path.dirname; /** * Return the basename for the given `filepath`. Uses @@ -29,34 +26,44 @@ exports.dirname = function dirname(filepath) { * <%= basename("a/b/c/d.js") %> * //=> 'd.js' * ``` - * * @param {String} `filepath` * @return {String} Returns the basename part of the file path. * @api public */ -exports.basename = function basename(fp) { - return path.basename(fp); -}; +exports.basename = path.basename; /** - * Return the filename for the given `filepath`, excluding - * extension. + * Returns the filename for the given `filepath`, excluding + * extension. Aliased as `stem`. * * ```js - * <%= basename("a/b/c/d.js") %> + * <%= filename("a/b/c/d.js") %> * //=> 'd' * ``` - * * @param {String} `filepath` * @return {String} Returns the file name part of the file path. * @api public */ -exports.filename = function filename(filepath) { +exports.filename = filepath => { return path.basename(filepath, path.extname(filepath)); }; +/** + * Alias for [filename](#filename). + * + * ```js + * <%= stem("a/b/c/d.js") %> + * //=> 'd' + * ``` + * @param {String} `filepath` + * @return {String} Returns the file name part of the file path. + * @api public + */ + +exports.stem = exports.filename; + /** * Return the file extension for the given `filepath`. * Uses the node.js [path] module. @@ -65,15 +72,12 @@ exports.filename = function filename(filepath) { * <%= extname("foo.js") %> * //=> '.js' * ``` - * * @param {String} `filepath` * @return {String} Returns a file extension * @api public */ -exports.extname = function extname(filepath) { - return path.extname(filepath); -}; +exports.extname = path.extname; /** * Return the file extension for the given `filepath`, @@ -83,15 +87,12 @@ exports.extname = function extname(filepath) { * <%= ext("foo.js") %> * //=> 'js' * ``` - * * @param {String} `filepath` * @return {String} Returns a file extension without dot. * @api public */ -exports.ext = function ext(filepath) { - return path.extname(filepath).slice(1); -}; +exports.ext = filepath => path.extname(filepath).replace(/^\./, ''); /** * Resolves the given paths to an absolute path. Uses @@ -101,15 +102,12 @@ exports.ext = function ext(filepath) { * <%= resolve('/foo/bar', './baz') %> * //=> '/foo/bar/baz' * ``` - * * @param {String} `filepath` * @return {String} Returns a resolve * @api public */ -exports.resolve = function resolve() { - return path.resolve.apply(path, arguments); -}; +exports.resolve = path.resolve; /** * Get the relative path from file `a` to file `b`. @@ -119,21 +117,26 @@ exports.resolve = function resolve() { * ```js * <%= relative(a, b) %> * ``` - * * @param {String} `a` The "from" file path. * @param {String} `b` The "to" file path. * @return {String} Returns a relative path. * @api public */ -exports.relative = function relative(a, b) { - if (typeof b === 'undefined' && typeof process !== 'undefine' && typeof process.cwd === 'function') { +exports.relative = (a, b) => { + if (b === void 0) { b = a; - a = process.cwd(); + + if (typeof process !== 'undefined' && typeof process.cwd === 'function') { + a = process.cwd(); + } else { + a = '.'; + } } + a = a || ''; b = b || ''; - var rel = utils.relative(a, b); + let rel = relative(a, b); return rel === '.' ? './' : rel; }; @@ -151,14 +154,13 @@ exports.relative = function relative(a, b) { * <%= segments("a/b/c/d", "1", "2") %> * //=> 'b/c' * ``` - * * @param {String} `filepath` The file path to split into segments. * @return {String} Returns a single, joined file path. * @api public */ -exports.segments = function segments(filepath, a, b) { - return filepath.split(/[\\\/]+/).slice(a, b).join('/'); +exports.segments = (filepath, a, b) => { + return filepath.split(/[\\/]+/).slice(a, b).join('/'); }; /** @@ -173,15 +175,12 @@ exports.segments = function segments(filepath, a, b) { * <%= join("a", "b") %> * //=> 'a/b' * ``` - * * @param {String} `filepaths` List of file paths. * @return {String} Returns a single, joined file path. * @api public */ -exports.join = function join() { - return path.join.apply(path, arguments); -}; +exports.join = path.join; /** * Returns true if a file path is an absolute path. An @@ -208,15 +207,12 @@ exports.join = function join() { * <%= isAbsolute('.') %> * //=> 'false' * ``` - * * @param {String} `filepath` * @return {String} Returns a resolve * @api public */ -exports.isAbsolute = function isAbsolute(filepath) { - return utils.isAbsolute(filepath); -}; +exports.isAbsolute = path.isAbsolute; /** * Returns true if a file path is an absolute path. An @@ -243,12 +239,9 @@ exports.isAbsolute = function isAbsolute(filepath) { * <%= isRelative('.') %> * //=> 'true' * ``` - * * @param {String} `filepath` * @return {String} Returns a resolve * @api public */ -exports.isRelative = function isRelative(filepath) { - return !utils.isAbsolute(filepath); -}; +exports.isRelative = filepath => !path.isAbsolute(filepath); diff --git a/lib/string.js b/lib/helpers/string.js similarity index 64% rename from lib/string.js rename to lib/helpers/string.js index 22c68d7..89b4653 100644 --- a/lib/string.js +++ b/lib/helpers/string.js @@ -1,6 +1,13 @@ 'use strict'; -var utils = require('./utils'); +const wrap = require('word-wrap'); +const slugify = require('helper-slugify'); +const alignCenter = require('center-align'); +const alignRight = require('right-align'); +const titlecase = require('titlecase'); +const { isString } = require('../utils'); +const chopRe = () => /^[-_.\W\s]+|[-_.\W\s]+$/g; +const nonWordRe = () => /[-_.\W\s]+(\w|$)/g; /** * camelCase the characters in `string`. @@ -9,23 +16,18 @@ var utils = require('./utils'); * <%= camelcase("foo bar baz") %> * //=> 'fooBarBaz' * ``` - * * @param {String} `string` The string to camelcase. * @return {String} * @api public */ -exports.camelcase = function camelcase(str) { - if (!exports.isString(str)) return ''; - if (str.length === 1) { - return str.toLowerCase(); +exports.camelcase = input => { + if (!isString(input)) return ''; + if (input.length === 1) { + return input.toLowerCase(); } - - var re = /[-_.\W\s]+(\w|$)/g; - str = exports.chop(str).toLowerCase(); - return str.replace(re, function(_, ch) { - return ch.toUpperCase(); - }); + let str = exports.chop(input).toLowerCase(); + return str.replace(nonWordRe(), (_, ch) => ch.toUpperCase()); }; /** @@ -35,15 +37,14 @@ exports.camelcase = function camelcase(str) { * ```js * <%= centerAlign("abc") %> * ``` - * * @param {String} `str` The string to reverse. * @return {String} Centered string. * @related rightAlign * @api public */ -exports.centerAlign = function centerAlign(str) { - return exports.isString(str) ? utils.alignCenter(str, ' ') : ''; +exports.centerAlign = str => { + return isString(str) ? alignCenter(str, ' ') : ''; }; /** @@ -60,16 +61,14 @@ exports.centerAlign = function centerAlign(str) { * <%= chop(" ABC ") %> * //=> 'ABC' * ``` - * * @param {String} `string` The string to chop. * @return {String} * @api public */ -exports.chop = function chop(str) { - if (!exports.isString(str)) return ''; - var re = /^[-_.\W\s]+|[-_.\W\s]+$/g; - return str.trim().replace(re, ''); +exports.chop = str => { + if (!isString(str)) return ''; + return str.trim().replace(chopRe(), ''); }; /** @@ -80,15 +79,14 @@ exports.chop = function chop(str) { * <%= count("abcabcabc", "a") %> * //=> '3' * ``` - * * @param {String} `string` * @param {String} `substring` * @return {Number} The occurances of `substring` in `string` * @api public */ -exports.count = function count(str, sub) { - if (exports.isString(str)) { +exports.count = (str, sub) => { + if (isString(str)) { return (sub ? (str.split(sub).length - 1) : '0'); } return ''; @@ -101,19 +99,15 @@ exports.count = function count(str, sub) { * <%= dotcase("a-b-c d_e") %> * //=> 'a.b.c.d.e' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.dotcase = function dotcase(str) { - if (!exports.isString(str)) return ''; - if (str.length === 1) { return str.toLowerCase(); } - var re = /[-_.\W\s]+(\w|$)/g; - return exports.chop(str).replace(re, function(_, ch) { - return '.' + ch; - }); +exports.dotcase = str => { + if (!isString(str)) return ''; + if (str.length === 1) return str.toLowerCase(); + return exports.chop(str).replace(nonWordRe(), (_, ch) => '.' + ch); }; /** @@ -124,7 +118,6 @@ exports.dotcase = function dotcase(str) { * <%= ellipsis("foo bar baz", 7) %> * //=> 'foo bar…' * ``` - * * @param {String} `str` * @param {Number} `length` The desired length of the returned string. * @param {String} `ch` Optionally pass custom characters to append. Default is `…`. @@ -132,10 +125,8 @@ exports.dotcase = function dotcase(str) { * @api public */ -exports.ellipsis = function ellipsis(str, limit, ch) { - return exports.isString(str) - ? (exports.truncate(str, limit) + (ch || '…')) - : ''; +exports.ellipsis = (str, limit, ch) => { + return isString(str) ? (exports.truncate(str, limit) + (ch || '…')) : ''; }; /** @@ -148,15 +139,12 @@ exports.ellipsis = function ellipsis(str, limit, ch) { * <%= isString(null) %> * //=> 'false' * ``` - * * @param {String} `val` * @return {Boolean} True if the value is a string. * @api public */ -exports.isString = function isString(str) { - return str && typeof str === 'string'; -}; +exports.isString = isString; /** * Lowercase the characters in the given `string`. @@ -165,14 +153,13 @@ exports.isString = function isString(str) { * <%= lowercase("ABC") %> * //=> 'abc' * ``` - * * @param {String} `string` The string to lowercase. * @return {String} * @api public */ -exports.lowercase = exports.lower = function lowercase(str) { - return exports.isString(str) ? str.toLowerCase() : ''; +exports.lowercase = exports.lower = str => { + return isString(str) ? str.toLowerCase() : ''; }; /** @@ -182,16 +169,15 @@ exports.lowercase = exports.lower = function lowercase(str) { * <%= pascalcase("foo bar baz") %> * //=> 'FooBarBaz' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.pascalcase = function pascalcase(str) { - if (!exports.isString(str)) return ''; - if (str.length === 1) { return str.toUpperCase(); } - str = exports.camelcase(str); +exports.pascalcase = input => { + if (!isString(input)) return ''; + if (input.length === 1) { return input.toUpperCase(); } + let str = exports.camelcase(input); return str[0].toUpperCase() + str.slice(1); }; @@ -202,19 +188,15 @@ exports.pascalcase = function pascalcase(str) { * <%= snakecase("a-b-c d_e") %> * //=> 'a_b_c_d_e' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.snakecase = function snakecase(str) { - if (!exports.isString(str)) return ''; - if (str.length === 1) { return str.toLowerCase(); } - var re = /[-_.\W\s]+(\w|$)/g; - return exports.chop(str).replace(re, function(_, ch) { - return '_' + ch; - }); +exports.snakecase = str => { + if (!isString(str)) return ''; + if (str.length === 1) return str.toLowerCase(); + return exports.chop(str).replace(nonWordRe(), (_, ch) => '_' + ch); }; /** @@ -224,14 +206,13 @@ exports.snakecase = function snakecase(str) { * <%= split("a,b,c", ",") %> * //=> ['a', 'b', 'c'] * ``` - * * @param {String} `string` The string to split. * @return {String} `character` Default is `,` * @api public */ -exports.split = function split(str, ch) { - return exports.isString(str) ? str.split(ch || ',') : ''; +exports.split = (str, ch) => { + return isString(str) ? str.split(ch || ',') : ''; }; /** @@ -241,15 +222,14 @@ exports.split = function split(str, ch) { * <%= strip("foo-bar", "foo-") %> * //=> 'bar' * ``` - * * @param {String|RegExp} `substring` The string or regex pattern of the substring to remove. * @param {String} `string` The target string. * @api public */ -exports.strip = function strip(val, str) { - if (!exports.isString(val) && !(val instanceof RegExp)) return ''; - if (!exports.isString(str)) return ''; +exports.strip = (val, str) => { + if (!isString(val) && !(val instanceof RegExp)) return ''; + if (!isString(str)) return ''; return str.split(val).join(''); }; @@ -260,22 +240,20 @@ exports.strip = function strip(val, str) { * <%= stripIndent(" _ABC_") %> * //=> 'ABC' * ``` - * * @param {String} `string` The string to strip indentation from. * @return {String} * @api public */ -exports.stripIndent = function stripIndent(str) { - if (!exports.isString(str)) return ''; - - var matches = str.match(/^[ \t]+(?!\s)/gm); +exports.stripIndent = str => { + if (!isString(str)) return ''; + let matches = str.match(/^[ \t]+(?!\s)/gm); if (!matches) return str; - var ws = matches.reverse().pop(); - var len = ws.length; + let whitespace = matches.reverse().pop(); + let len = whitespace.length; if (len) { - var re = new RegExp('^[ \\t]{' + len + '}', 'gm'); + let re = new RegExp(`^[ \\t]{${len}}`, 'gm'); return str.replace(re, ''); } return str; @@ -289,15 +267,12 @@ exports.stripIndent = function stripIndent(str) { * <%= trim(" ABC ") %> * //=> 'ABC' * ``` - * * @param {String} `string` The string to trim. * @return {String} * @api public */ -exports.trim = function trim(str) { - return exports.isString(str) ? str.trim() : ''; -}; +exports.trim = str => isString(str) ? str.trim() : ''; /** * dash-case the characters in `string`. This is similar to [slugify], @@ -307,20 +282,16 @@ exports.trim = function trim(str) { * <%= dashcase("a b.c d_e") %> * //=> 'a-b-c-d-e' * ``` - * * @param {String} `string` * @return {String} * @tags dasherize, dashify, hyphenate, case * @api public */ -exports.dashcase = function dashcase(str) { - if (!exports.isString(str)) return ''; - if (str.length === 1) { return str.toLowerCase(); } - var re = /[-_.\W\s]+(\w|$)/g; - return exports.chop(str).replace(re, function(_, ch) { - return '-' + ch; - }); +exports.dashcase = str => { + if (!isString(str)) return ''; + if (str.length === 1) return str.toLowerCase(); + return exports.chop(str).replace(nonWordRe(), (_, ch) => '-' + ch); }; /** @@ -330,19 +301,15 @@ exports.dashcase = function dashcase(str) { * <%= pathcase("a-b-c d_e") %> * //=> 'a/b/c/d/e' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.pathcase = function pathcase(str) { - if (!exports.isString(str)) return ''; +exports.pathcase = str => { + if (!isString(str)) return ''; if (str.length === 1) { return str.toLowerCase(); } - var re = /[_.-\W\s]+(\w|$)/g; - return exports.chop(str).replace(re, function(_, ch) { - return '/' + ch; - }); + return exports.chop(str).replace(nonWordRe(), (_, ch) => '/' + ch); }; /** @@ -352,14 +319,13 @@ exports.pathcase = function pathcase(str) { * <%= sentencecase("foo bar baz.") %> * //=> 'Foo bar baz.' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.sentencecase = function sentencecase(str) { - if (!exports.isString(str)) return ''; +exports.sentencecase = str => { + if (!isString(str)) return ''; if (str.length === 1) { return str.toUpperCase(); } return str.charAt(0).toUpperCase() + str.slice(1); }; @@ -371,14 +337,13 @@ exports.sentencecase = function sentencecase(str) { * <%= hyphenate("a b c") %> * //=> 'a-b-c' * ``` - * * @param {String} `string` * @return {String} * @api public */ -exports.hyphenate = function hyphenate(str) { - return exports.isString(str) ? exports.chop(str).split(' ').join('-') : ''; +exports.hyphenate = str => { + return isString(str) ? exports.chop(str).split(' ').join('-') : ''; }; /** @@ -390,13 +355,12 @@ exports.hyphenate = function hyphenate(str) { * <%= slugify('This is a post title.') %> * //=> 'this-is-a-post-title' * ``` - * * @param {String} `string` The string to slugify. * @return {String} Slug. * @api draft */ -exports.slugify = require('helper-slugify'); +exports.slugify = slugify; /** * Reverse the characters in a string. @@ -405,14 +369,13 @@ exports.slugify = require('helper-slugify'); * <%= reverse("abc") %> * //=> 'cba' * ``` - * * @param {String} `str` The string to reverse. * @return {String} * @api public */ -exports.reverse = function reverse(str) { - return exports.isString(str) ? str.split('').reverse().join('') : ''; +exports.reverse = str => { + return isString(str) ? str.split('').reverse().join('') : ''; }; /** @@ -422,15 +385,14 @@ exports.reverse = function reverse(str) { * ```js * <%= rightAlign(str) %> * ``` - * * @param {String} `str` The string to reverse. * @return {String} Right-aligned string. * @related centerAlign * @api public */ -exports.rightAlign = function rightAlign(str) { - return exports.isString(str) ? utils.alignRight(str) : ''; +exports.rightAlign = str => { + return isString(str) ? alignRight(str) : ''; }; /** @@ -440,7 +402,6 @@ exports.rightAlign = function rightAlign(str) { * <%= replace("abcabc", /a/, "z") %> * //=> 'zbczbc' * ``` - * * @param {String} `str` * @param {String|RegExp} `a` Can be a string or regexp. * @param {String} `b` @@ -448,8 +409,8 @@ exports.rightAlign = function rightAlign(str) { * @api public */ -exports.replace = function replace(str, a, b) { - if (!exports.isString(str)) return ''; +exports.replace = (str, a, b) => { + if (!isString(str)) return ''; if (!a) { return str; } if (!b) { b = ''; } return str.split(a).join(b); @@ -463,15 +424,14 @@ exports.replace = function replace(str, a, b) { * <%= titlecase("big deal") %> * //=> 'foo bar' * ``` - * * @param {String} `str` * @param {Number} `length` The desired length of the returned string. * @return {String} The truncated string. * @api public */ -exports.titlecase = exports.titleize = function titlecase(str, length) { - return exports.isString(str) ? utils.titlecase(str) : ''; +exports.titlecase = exports.titleize = (str, length) => { + return isString(str) ? titlecase(str) : ''; }; /** @@ -482,15 +442,14 @@ exports.titlecase = exports.titleize = function titlecase(str, length) { * <%= truncate("foo bar baz", 7) %> * //=> 'foo bar' * ``` - * * @param {String} `str` * @param {Number} `length` The desired length of the returned string. * @return {String} The truncated string. * @api public */ -exports.truncate = function truncate(str, length) { - return exports.isString(str) ? str.substr(0, length) : ''; +exports.truncate = (str, length) => { + return isString(str) ? str.substr(0, length) : ''; }; /** @@ -500,18 +459,13 @@ exports.truncate = function truncate(str, length) { * <%= uppercase("abc") %> * //=> 'ABC' * ``` - * * @param {String} `string` The string to uppercase. * @return {String} * @api public */ -exports.uppercase = exports.upper = function uppercase(str) { - return exports.isString(str) ? str.toUpperCase() : ''; -}; -// ensure code conext picks up alias as a method -exports.upper = function upper(str) { - return exports.uppercase.apply(null, arguments); +exports.uppercase = exports.upper = str => { + return isString(str) ? str.toUpperCase() : ''; }; /** @@ -521,13 +475,12 @@ exports.upper = function upper(str) { * <%= wordwrap("a b c d e f", {width: 5, newline: '
'}) %> * //=> ' a b c
d e f' * ``` - * * @param {String} `string` The string with words to wrap. * @param {Options} `object` Options to pass to [word-wrap] * @return {String} Formatted string. * @api public */ -exports.wordwrap = function wordwrap(str) { - return exports.isString(str) ? utils.wrap.apply(utils.wrap, arguments) : ''; +exports.wordwrap = (str, options) => { + return isString(str) ? wrap(str, options) : ''; }; diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 23b2930..0000000 --- a/lib/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('export-files')(__dirname); diff --git a/lib/iterator.js b/lib/iterator.js new file mode 100644 index 0000000..c84dd50 --- /dev/null +++ b/lib/iterator.js @@ -0,0 +1,64 @@ +'use strict'; + +const typeOf = require('kind-of'); +const prop = name => obj => obj[name]; +const noop = val => val; + +module.exports = (target, thisArg) => { + const invoke = (val, i, arr) => target.call(thisArg, val, i, arr); + switch (typeOf(target)) { + case 'undefined': + case 'null': + return noop; + case 'function': + return (thisArg === void 0) ? target : invoke; + case 'object': + return val => isMatch(val, target); + case 'regexp': + return str => target.test(str); + case 'string': + case 'number': + default: { + return prop(target); + } + } +}; + +function containsMatch(array, value) { + for (let i = 0; i < array.length; i++) { + if (isMatch(array[i], value)) { + return true; + } + } + return false; +} + +function matchArray(array, value) { + for (let i = 0; i < array.length; i++) { + if (!containsMatch(array, value[i])) { + return false; + } + } + return true; +} + +function matchObject(obj, value) { + for (let key in value) { + if (value.hasOwnProperty(key)) { + if (isMatch(obj[key], value[key]) === false) { + return false; + } + } + } + return true; +} + +function isMatch(val, value) { + if (typeOf(val) === 'object') { + if (Array.isArray(val) && Array.isArray(value)) { + return matchArray(val, value); + } + return matchObject(val, value); + } + return val === value; +} diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000..ac68eae --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,149 @@ +'use strict'; + +const typeOf = require('kind-of'); + +exports.isEmpty = val => { + if (typeof val === 'function') { + return false; + } + if (exports.isObject(val)) { + val = Object.keys(val); + } + if (Array.isArray(val)) { + return val.length === 0; + } + if (typeof val === 'undefined') { + return true; + } + if (val === 0) { + return false; + } + if (val == null) { + return true; + } +}; + +exports.omit = (obj, keys = []) => { + let res = {}; + + for (let key of Object.keys(obj)) { + if (!keys.includes(key)) { + res[key] = obj[key]; + } + } + + return res; +}; + +/** + * Get the "title" from a markdown link + */ + +exports.getTitle = str => { + if (/^\[[^\]]+\]\(/.test(str)) { + let m = /^\[([^\]]+)\]/.exec(str); + if (m) return m[1]; + } + return str; +}; + +exports.isString = str => str !== '' && typeof str === 'string'; + +exports.isNumber = num => { + if (typeof num === 'number') { + return num - num === 0; + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; +}; + +exports.isObject = val => typeOf(val) === 'object'; + +exports.isPlainObject = val => { + return exports.isObject(val) && val.constructor === Object; +}; + +/** + * Returns true if the given `val` is an object. + * + * ```js + * utils.isObject('foo'); + * //=> false + * + * utils.isObject({}); + * //=> true + * ``` + * @param {any} `val` + * @return {Boolean} + * @api public + */ + +exports.isObject = val => { + return typeOf(val) === 'object'; +}; + +/** + * Stringify HTML tag attributes from the given `object`. + * + * @param {Object} `object` Object of attributes as key-value pairs. + * @return {String} Stringified attributes, e.g. `foo="bar"` + * @api public + */ + +exports.toAttributes = obj => { + return Object.keys(obj).map(key => `${key}="${obj[key]}"`).join(' '); +}; + +exports.toCodeBlock = (str, lang) => { + if (typeof str !== 'string') { + throw new TypeError('expected a string.'); + } + let code = ''; + code += '```' + (typeof lang === 'string' ? lang : ''); + code += '\n'; + code += str; + code += '\n'; + code += '```'; + return code; +}; + +/** + * Generate a random number + * + * @param {Number} `min` + * @param {Number} `max` + * @return {Number} + */ + +exports.random = (min, max) => { + return min + Math.floor(Math.random() * (max - min + 1)); +}; + +exports.flatten = arr => { + const flat = (a, res) => { + let len = a.length; + let i = -1; + while (len--) { + let cur = a[++i]; + if (Array.isArray(cur)) { + flat(cur, res); + } else { + res.push(cur); + } + } + return res; + }; + return flat(arr, []); +}; + +exports.union = (...args) => { + return [...new Set(exports.flatten(args))]; +}; + +/** + * Expose `exports` modules + */ + +module.exports = exports; diff --git a/lib/utils/index.js b/lib/utils/index.js deleted file mode 100644 index 60a0481..0000000 --- a/lib/utils/index.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -var utils = require('lazy-cache')(require); -var fn = require; -require = utils; - -/** - * Utils - */ - -require('any'); -require('arr-union', 'union'); -require('arr-flatten', 'flatten'); -require('center-align', 'alignCenter'); -require('get-value', 'get'); -require('is-absolute'); -require('is-number'); -require('is-plain-object'); -require('kind-of', 'typeOf'); -require('make-iterator'); -require('object.omit', 'omit'); -require('relative'); -require('right-align', 'alignRight'); -require('strip-color'); -require('titlecase'); -require('to-gfm-code-block', 'block'); -require('word-wrap', 'wrap'); -require = fn; - -utils.isEmpty = function(val) { - if (typeof val === 'function') { - return false; - } - if (utils.isObject(val)) { - val = Object.keys(val); - } - if (Array.isArray(val)) { - return val.length === 0; - } - if (typeof val === 'undefined') { - return true; - } - if (val === 0) { - return false; - } - if (val == null) { - return true; - } -}; - -/** - * Get the "title" from a markdown link - */ - -utils.getTitle = function(str) { -if (/^\[[^\]]+\]\(/.test(str)) { - var m = /^\[([^\]]+)\]/.exec(str); - if (m) return m[1]; - } - return str; -}; - -/** - * Returns true if the given `val` is an object. - * - * ```js - * utils.isObject('foo'); - * //=> false - * - * utils.isObject({}); - * //=> true - * ``` - * @param {any} `val` - * @return {Boolean} - * @api public - */ - -utils.isObject = function(val) { - return utils.typeOf(val) === 'object'; -}; - -/** - * Stringify HTML tag attributes from the given `object`. - * - * @param {Object} `object` Object of attributes as key-value pairs. - * @return {String} Stringified attributes, e.g. `foo="bar"` - * @api public - */ - -utils.toAttributes = function(obj) { - return Object.keys(obj).map(function(key) { - return key + '="' + obj[key] + '"'; - }).join(' '); -}; - -/** - * Generate a random number - * - * @param {Number} `min` - * @param {Number} `max` - * @return {Number} - */ - -utils.random = function(min, max) { - return min + Math.floor(Math.random() * (max - min + 1)); -}; - -/** - * Expose `utils` modules - */ - -module.exports = utils; diff --git a/package.json b/package.json index 43026ce..d3936fa 100644 --- a/package.json +++ b/package.json @@ -11,52 +11,34 @@ "license": "MIT", "files": [ "index.js", - "lib", - "LICENSE", - "README.md" + "lib" ], "main": "index.js", "engines": { - "node": ">=0.10.0" + "node": ">=6" }, "scripts": { "test": "mocha" }, "dependencies": { "any": "^1.0.0", - "arr-flatten": "^1.0.1", - "arr-union": "^3.1.0", - "center-align": "^0.1.3", - "export-files": "^2.1.1", - "fs-exists-sync": "^0.1.0", - "get-value": "^2.0.6", + "center-align": "^1.0.1", + "get-value": "^3.0.1", "helper-slugify": "^0.2.0", - "is-absolute": "^0.2.5", - "is-number": "^2.1.0", - "is-plain-object": "^2.0.1", - "kind-of": "^3.0.3", - "lazy-cache": "^2.0.1", - "make-iterator": "^0.3.0", - "object.omit": "^2.0.0", + "kind-of": "^6.0.2", "relative": "^3.0.2", "right-align": "^0.1.3", - "strip-color": "^0.1.0", "titlecase": "^1.1.2", - "to-gfm-code-block": "^0.1.1", - "word-wrap": "^1.1.0" + "word-wrap": "^1.2.3" }, "devDependencies": { - "gulp": "^3.9.1", - "gulp-eslint": "^3.0.1", - "gulp-format-md": "^0.1.9", - "gulp-istanbul": "^1.0.0", - "gulp-mocha": "^2.2.0", + "gulp-format-md": "^2.0.0", "helper-coverage": "^0.1.3", - "lodash.template": "^4.2.5", + "lodash.template": "^4.4.0", "markdown-link": "^0.1.1", - "mocha": "^2.5.3", - "through2": "^2.0.1", - "verb-generate-readme": "^0.1.26" + "mocha": "^5.2.0", + "through2": "^3.0.0", + "verb-generate-readme": "^0.8.0" }, "keywords": [ "compile", @@ -72,38 +54,32 @@ ], "verb": { "toc": true, - "helpers": [ - "helper-coverage" + "layout": "default", + "tasks": [ + "readme" ], "plugins": [ "gulp-format-md" ], - "reflinks": [ - "any", - "assemble", - "helper-concat", - "slugify", - "templates", - "verb", - "verb-generate-readme", - "word-wrap" + "helpers": [ + "helper-coverage" ], "related": { + "description": "You might also be interested in the following projects (also visit the [github.com/helpers](https://github.com/helpers), where you can find 60+ additional standalone helpers!):", "list": [ "assemble", "handlebars-helpers", - "helper-cache", - "template", - "utils", - "verb" + "templates" ] }, - "layout": "default", - "tasks": [ - "readme" - ], "lint": { "reflinks": true - } + }, + "reflinks": [ + "any", + "slugify", + "verb", + "word-wrap" + ] } } diff --git a/test/conditional.js b/test/conditional.js index c8990d0..1f4229c 100644 --- a/test/conditional.js +++ b/test/conditional.js @@ -31,4 +31,40 @@ describe('conditional', function() { assert.equal(template('<%= _if(fn, "foo", "bar") %>', imports)(context), 'bar'); }); }); + + describe('compare', function() { + it('should be true when values are equal', function() { + assert.equal(template('<%= compare("foo", "===", "foo") %>', imports)(context), 'true'); + assert.equal(template('<%= compare("foo", "==", "foo") %>', imports)(context), 'true'); + }); + + it('should be false when values are not equal', function() { + assert.equal(template('<%= compare("foo", "===", "bar") %>', imports)(context), 'false'); + assert.equal(template('<%= compare("foo", "==", "bar") %>', imports)(context), 'false'); + }); + }); + + describe('is / eq', function() { + it('should be true when values are equal', function() { + assert.equal(template('<%= is("foo", "foo") %>', imports)(context), 'true'); + assert.equal(template('<%= eq("foo", "foo") %>', imports)(context), 'true'); + }); + + it('should be false when values are not equal', function() { + assert.equal(template('<%= is("foo", "bar") %>', imports)(context), 'false'); + assert.equal(template('<%= eq("foo", "bar") %>', imports)(context), 'false'); + }); + }); + + describe('isnt / notEq', function() { + it('should be false when values are equal', function() { + assert.equal(template('<%= isnt("foo", "foo") %>', imports)(context), 'false'); + assert.equal(template('<%= notEq("foo", "foo") %>', imports)(context), 'false'); + }); + + it('should be true when values are not equal', function() { + assert.equal(template('<%= isnt("foo", "bar") %>', imports)(context), 'true'); + assert.equal(template('<%= notEq("foo", "bar") %>', imports)(context), 'true'); + }); + }); }); diff --git a/test/object.js b/test/object.js index 4390662..972d68d 100644 --- a/test/object.js +++ b/test/object.js @@ -83,7 +83,7 @@ describe('objects', function() { describe('forOwn', function() { it('should expose the keys on an object.', function() { - var context = {values: {a: 'b', c: 'd'}} + var context = { values: { a: 'b', c: 'd' } }; var actual = template('<% forOwn(values, function(val, key) { %><%= key %><% }) %>', imports)(context); assert.equal(actual, 'ac'); }); diff --git a/test/path.js b/test/path.js index aef1f1a..9e1d1d8 100644 --- a/test/path.js +++ b/test/path.js @@ -11,8 +11,7 @@ var path = require('path'); var assert = require('assert'); var template = require('lodash.template'); var helpers = require('..')('path'); - -var imports = {imports: helpers}; +var imports = { imports: helpers }; describe('path helpers', function() { describe('dirname', function() { diff --git a/test/string.js b/test/string.js index a20302f..f9ffa1c 100644 --- a/test/string.js +++ b/test/string.js @@ -7,11 +7,10 @@ 'use strict'; -var assert = require('assert'); -var template = require('lodash.template'); -var helpers = require('..')(['string', 'html']); - -var imports = {imports: helpers}; +const assert = require('assert'); +const template = require('lodash.template'); +const helpers = require('..')(['string', 'html']); +const imports = { imports: helpers }; describe('string helpers', function() { describe('lowercase', function() { @@ -89,22 +88,10 @@ describe('string helpers', function() { assert.equal(template('<%= stripIndent() %>', imports)(), ''); }); it('should strip indentation from a string.', function() { - var str = template('<%= stripIndent(str) %>', imports)({str: [ - ' - a', - ' - b', - ' * c', - ' * d', - ' + e', - ' + f' - ].join('\n')}); - assert.equal(str, [ - '- a', - '- b', - ' * c', - ' * d', - ' + e', - ' + f' - ].join('\n')); + var str = template('<%= stripIndent(str) %>', imports)({ + str: [' - a', ' - b', ' * c', ' * d', ' + e', ' + f'].join('\n') + }); + assert.equal(str, ['- a', '- b', ' * c', ' * d', ' + e', ' + f'].join('\n')); }); }); diff --git a/test/test.js b/test/test.js index 013694c..4db79a7 100644 --- a/test/test.js +++ b/test/test.js @@ -7,9 +7,9 @@ 'use strict'; -var assert = require('assert'); -var lib = require('..'); -var helpers; +const assert = require('assert'); +const lib = require('..'); +let helpers; describe('helpers', function() { before(function() { @@ -17,7 +17,7 @@ describe('helpers', function() { }); it('should expose all helpers on main export', function() { - var keys = Object.keys(helpers); + let keys = Object.keys(helpers); assert(keys.length > 70); }); @@ -27,7 +27,7 @@ describe('helpers', function() { }); it('should filter out array helpers when passed as an argument to lib', function() { - var array = lib('array'); + let array = lib('array'); assert(typeof array === 'object'); }); @@ -37,7 +37,7 @@ describe('helpers', function() { }); it('should filter out code helpers when passed as an argument to lib', function() { - var code = lib('code'); + let code = lib('code'); assert(typeof code === 'object'); }); @@ -47,7 +47,7 @@ describe('helpers', function() { }); it('should filter out collection helpers when passed as an argument to lib', function() { - var collection = lib('collection'); + let collection = lib('collection'); assert(typeof collection === 'object'); }); @@ -57,7 +57,7 @@ describe('helpers', function() { }); it('should filter out conditional helpers when passed as an argument to lib', function() { - var conditional = lib('conditional'); + let conditional = lib('conditional'); assert(typeof conditional === 'object'); }); @@ -67,7 +67,7 @@ describe('helpers', function() { }); it('should filter out fs helpers when passed as an argument to lib', function() { - var fs = lib('fs'); + let fs = lib('fs'); assert(typeof fs === 'object'); }); @@ -77,7 +77,7 @@ describe('helpers', function() { }); it('should filter out html helpers when passed as an argument to lib', function() { - var html = lib('html'); + let html = lib('html'); assert(typeof html === 'object'); }); @@ -87,7 +87,7 @@ describe('helpers', function() { }); it('should filter out math helpers when passed as an argument to lib', function() { - var math = lib('math'); + let math = lib('math'); assert(typeof math === 'object'); }); @@ -97,7 +97,7 @@ describe('helpers', function() { }); it('should filter out object helpers when passed as an argument to lib', function() { - var object = lib('object'); + let object = lib('object'); assert(typeof object === 'object'); }); @@ -107,7 +107,7 @@ describe('helpers', function() { }); it('should filter out path helpers when passed as an argument to lib', function() { - var path = lib('path'); + let path = lib('path'); assert(typeof path === 'object'); }); @@ -117,14 +117,14 @@ describe('helpers', function() { }); it('should filter out string helpers when passed as an argument to lib', function() { - var string = lib('string'); + let string = lib('string'); assert(typeof string === 'object'); assert(typeof string.lower === 'function'); assert(typeof string.upper === 'function'); }); it('should filter out an array of groups', function() { - var helpers = lib(['string', 'array']); + let helpers = lib(['string', 'array']); assert(typeof helpers === 'object'); assert(typeof helpers.last === 'function'); assert(typeof helpers.upper === 'function'); diff --git a/verbfile.js b/verbfile.js index f3d45cd..91b12d2 100644 --- a/verbfile.js +++ b/verbfile.js @@ -1,11 +1,10 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var exists = require('fs-exists-sync'); -var link = require('markdown-link'); -var through = require('through2'); -var cache = {}; +const fs = require('fs'); +const path = require('path'); +const link = require('markdown-link'); +const through = require('through2'); +const cache = {}; /** * TODO: externalize to `verb-generate-toc` @@ -24,13 +23,13 @@ module.exports = function(verb, base, env) { }); verb.task('toc', function(cb) { - var total = { categories: 0, helpers: 0 }; - var sections = []; - var summary = []; - var methods = {}; - var toc = []; + let total = { categories: 0, helpers: 0 }; + let sections = []; + let summary = []; + let methods = {}; + let toc = []; - return verb.src('lib/*.js') + return verb.src('lib/helpers/*.js') .pipe(through.obj(function(file, enc, next) { if (file.stem === 'index') { next(); @@ -40,8 +39,8 @@ module.exports = function(verb, base, env) { try { file.base = verb.cwd; file.code = require(file.path); - var heading = listItem(file); - var newFile = { + let heading = listItem(file); + let newFile = { methods: require(file.path), test: { path: path.join('test', file.basename), @@ -58,10 +57,10 @@ module.exports = function(verb, base, env) { } }; - var testLine = matchTest(newFile.test.path); - var codeLine = matchCode(newFile.path); + let testLine = matchTest(newFile.test.path); + let codeLine = matchCode(newFile.path); - for (var key in newFile.methods) { + for (let key in newFile.methods) { total.helpers++; if (newFile.methods.hasOwnProperty(key)) { newFile.data.methods[key] = { @@ -86,16 +85,15 @@ module.exports = function(verb, base, env) { next(err); } }, function(next) { - - verb.data({total: total}); - verb.data({methods: methods}); + verb.data({ total }); + verb.data({ methods }); next(); })); }); verb.task('sectionToc', function() { - var toc = ''; - return verb.src('lib/*.js') + let toc = ''; + return verb.src('lib/helpers/*.js') .pipe(through.obj(function(file, enc, next) { if (file.stem !== 'index') { file.base = verb.cwd; @@ -105,7 +103,7 @@ module.exports = function(verb, base, env) { next(); }, function(next) { // create an `include` from the toc - verb.include('toc.md', {content: toc}); + verb.include('toc.md', { contents: Buffer.from(toc) }); next(); })) .pipe(verb.dest('.')); @@ -114,10 +112,10 @@ module.exports = function(verb, base, env) { verb.task('fix-headings', function() { return verb.src('README.md') .pipe(through.obj(function(file, enc, next) { - var str = file.contents.toString(); + let str = file.contents.toString(); str = str.replace(/\n### index/, ''); str = str.replace(/^(#{2,}\s*\[)\./gm, '$1'); - file.contents = new Buffer(str); + file.contents = Buffer.from(str); next(null, file); })) .pipe(verb.dest('.')); @@ -126,20 +124,19 @@ module.exports = function(verb, base, env) { verb.task('default', ['toc', 'readme', 'fix-headings']); }; - function section(name) { - return `## ${name}\n{%= apidocs("lib/${name}.js") %}`; + return `## ${name}\n{%= apidocs("lib/helpers/${name}.js") %}`; } function matchTest(fp) { - if (!fp || !exists(fp)) return function() {}; - var str = fs.readFileSync(fp, 'utf8'); - var lines = str.split('\n'); + if (!fp || !fs.existsSync(fp)) return function() {}; + let str = fs.readFileSync(fp, 'utf8'); + let lines = str.split('\n'); return function(method) { - var re = new RegExp('\\s*(describe|it)\\([\'"]\\.?(' + method + ')'); - var len = lines.length, i = -1; + let re = new RegExp('\\s*(describe|it)\\([\'"]\\.?(' + method + ')'); + let len = lines.length, i = -1; while (++i < len) { - var line = lines[i]; + let line = lines[i]; if (re.test(line)) { return i + 1; } @@ -149,19 +146,18 @@ function matchTest(fp) { } function matchCode(fp) { - if (!fp || !exists(fp)) return function() {}; - var str = fs.readFileSync(fp, 'utf8'); - var lines = str.split('\n'); - return function(method) { - var re = new RegExp('^exports\\.(' + method + ')', 'gm'); - var len = lines.length, i = -1; + if (!fp || !fs.existsSync(fp)) return function() {}; + let str = fs.readFileSync(fp, 'utf8'); + let lines = str.split('\n'); + return method => { + let re = new RegExp(`^exports\\.(${method})`, 'gm'); + let len = lines.length, i = -1; while (++i < len) { - var line = lines[i]; + let line = lines[i]; if (re.test(line)) { return i + 1; } } - return; }; } @@ -171,13 +167,13 @@ function helpers(app) { }); app.helper('issue', function(name) { - var repo = app.cache.data.repository; + let repo = app.cache.data.repository; return '[create issue](https://github.com/' + repo + '/issues/new?title=' + name + '%20helper)'; }); app.helper('sectionIssue', function(section) { - var repo = app.cache.data.repository; - var url = 'https://github.com/' + repo + '/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+'; + let repo = app.cache.data.repository; + let url = 'https://github.com/' + repo + '/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+'; return '[issues](' + url + section + '+helpers)'; }); @@ -190,7 +186,7 @@ function helpers(app) { }); app.helper('testLink', function(file) { - var line = file.test.line; + let line = file.test.line; return line ? codeLink('unit tests', file.test.path, line) : '[no tests]'; }); @@ -206,3 +202,4 @@ function listItem(file) { function codeLink(title, path, start) { return link(title, path + '#L' + start); } +