| Pass an object: | ||
| ```js | ||
| strings.parser('prop', { | ||
| pattern: /:([\\w]+)/, | ||
| replacement: function(match) { | ||
| return match.toUpperCase(); | ||
| } | ||
| ); | ||
| ``` | ||
| Or an array | ||
| ```js | ||
| strings.parser('prop', [ | ||
| { | ||
| pattern: 'a', | ||
| replacement: 'b' | ||
| }, | ||
| { | ||
| pattern: 'c', | ||
| replacement: 'd' | ||
| } | ||
| ]); | ||
| ``` |
| Using `parsers` like this: | ||
| ```js | ||
| strings.parsers([ | ||
| 'jumbotron', | ||
| 'labels', | ||
| 'progress', | ||
| 'glyphicons', | ||
| 'badges', | ||
| 'alerts', | ||
| 'newlines' | ||
| ]); | ||
| ``` | ||
| is just sugar for: | ||
| ```js | ||
| var parsers = [ | ||
| strings.parser('jumbotron'), | ||
| strings.parser('labels'), | ||
| strings.parser('progress'), | ||
| strings.parser('glyphicons'), | ||
| strings.parser('badges'), | ||
| strings.parser('alerts'), | ||
| strings.parser('newlines'), | ||
| ]; | ||
| ``` | ||
| For an example, see [markdown-symbols](https://github.com/jonschlinkert/markdown-symbols), which uses this to store replacement patterns for custom markdown symbols. |
| **Examples:** | ||
| Pass a propstring and the parsers to use: | ||
| ```js | ||
| // define some parsers to do simple key-value replacements | ||
| strings.parser('a', {'{foo}': 'AAA'}); | ||
| strings.parser('b', {'{bar}': 'BBB'}); | ||
| strings.parser('c', {'{baz}': 'CCC'}); | ||
| console.log(strings.process('{foo}/{bar}/{baz}', ['a', 'b', 'c'])); | ||
| // => 'AAA/BBB/CCC' | ||
| ``` |
| /** | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.extendParser()', function() { | ||
| var strings = new Strings(); | ||
| strings.parser('a', {pattern: 'a', replacement: 'b'}); | ||
| describe('when a named parser is extended', function() { | ||
| it('should have all values', function () { | ||
| strings.extendParser('a', {pattern: 'c', replacement: 'd'}); | ||
| var actual = strings.parser('a'); | ||
| expect(actual[0].pattern).to.equal('a'); | ||
| expect(actual[1].pattern).to.equal('c'); | ||
| }); | ||
| }); | ||
| }); |
| /** | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.template()', function () { | ||
| var strings; | ||
| before(function () { | ||
| strings = new Strings(); | ||
| }); | ||
| it('when a template is passed', function () { | ||
| var actual = strings.replace(':a/:b/:c:ext', { | ||
| a: 'foo', | ||
| b: 'bar', | ||
| c: 'baz', | ||
| ext: '.js' | ||
| }); | ||
| expect(actual).to.eql('foo/bar/baz.js'); | ||
| }); | ||
| it('when a template is passed', function () { | ||
| var actual = strings.replace('{a}/{b}/{c}:ext', { | ||
| a: 'foo', | ||
| b: 'bar', | ||
| c: 'baz', | ||
| ext: '.js' | ||
| }); | ||
| expect(actual).to.eql('foo/bar/baz.js'); | ||
| }); | ||
| it('when a template and parser object are passed', function () { | ||
| var actual = strings.replace(':basename/index:ext', { | ||
| basename: 'file', | ||
| ext: '.html' | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| }); |
+83
| /** | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var path = require('path'); | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.run', function () { | ||
| var strings; | ||
| beforeEach(function () { | ||
| strings = new Strings(); | ||
| }); | ||
| it('when a template with a parser object are passed', function () { | ||
| strings.propstring('pretty', ':base/index:ext'); | ||
| // Set the `blog` template | ||
| strings.template('blog', 'pretty', { | ||
| ':base': 'post', | ||
| ':ext': '.html' | ||
| }); | ||
| expect(strings.run('blog')).to.eql('post/index.html'); | ||
| }); | ||
| it('when a template with a parser object and context are passed', function () { | ||
| strings.propstring('pretty', ':basename/index:ext'); | ||
| strings.template('blog', 'pretty', { | ||
| ':basename': function () { | ||
| return path.basename(this.foo, path.extname(this.foo)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.foo); | ||
| } | ||
| }); | ||
| var actual = strings.run('blog', {foo: 'path/to/my/file.html'}); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| it('when a template with a named parser, and context are passed', function () { | ||
| strings.propstring('a', ':aaa/:bbb:ext'); | ||
| strings.propstring('c', ':ccc/:ddd:ext'); | ||
| strings.parser('foo', { | ||
| ':aaa': function () { | ||
| return path.basename(this.nonsense, path.extname(this.nonsense)); | ||
| }, | ||
| ':bbb': 'index', | ||
| ':ext': function () { | ||
| return path.extname(this.nonsense); | ||
| } | ||
| }); | ||
| strings.parser('bar', { | ||
| ':ccc': function () { | ||
| return path.basename(this.nonsense, path.extname(this.nonsense)); | ||
| }, | ||
| ':ddd': 'index', | ||
| ':ext': function () { | ||
| return path.extname(this.nonsense); | ||
| } | ||
| }); | ||
| strings.template('alpha', 'a', 'foo'); | ||
| strings.template('beta', 'c', 'bar'); | ||
| var actual1 = strings.run('alpha', { | ||
| nonsense: 'path/to/my/file.html' | ||
| }); | ||
| var actual2 = strings.run('beta', { | ||
| nonsense: 'path/to/my/file.html' | ||
| }); | ||
| expect(actual1).to.eql('file/index.html'); | ||
| expect(actual2).to.eql('file/index.html'); | ||
| }); | ||
| }); |
+14
-4
| --- | ||
| tags: ['docs/verbfile.js'] | ||
| tags: ['verb-tag-jscomments'] | ||
| --- | ||
@@ -27,8 +27,18 @@ # {%= name %} {%= badge("fury") %} | ||
| ## API | ||
| {%= extract("index.js") %} | ||
| {%= jscomments("index.js") %} | ||
| ## Authors | ||
| {%= contrib("brian") %} | ||
| {%= contrib("jon") %} | ||
| {%= include("authors", { | ||
| authors: [ | ||
| { | ||
| name: 'Jon Schlinkert', | ||
| username: 'jonschlinkert' | ||
| }, | ||
| { | ||
| name: 'Brian Woodward', | ||
| username: 'doowb' | ||
| } | ||
| ] | ||
| }) %} | ||
@@ -35,0 +45,0 @@ ## License |
+1
-1
| { | ||
| "name": "strings", | ||
| "version": "0.3.1", | ||
| "version": "0.4.0", | ||
| "main": [ | ||
@@ -5,0 +5,0 @@ "index.js" |
+184
-237
@@ -10,13 +10,14 @@ /** | ||
| var frep = require('frep'); | ||
| var replace = require('frep'); | ||
| var _ = require('lodash'); | ||
| var utils = require('./lib/utils.js'); | ||
| var utils = require('./lib/utils'); | ||
| /** | ||
| * ## new Strings() | ||
| * ## Strings | ||
| * | ||
| * > Strings constructor method | ||
| * | ||
| * Instantiate a new instance of Strings, optionally passing a default context to use. | ||
| * Create a new instance of `Strings`, optionally passing a default context to use. | ||
| * | ||
@@ -29,6 +30,8 @@ * **Example** | ||
| * | ||
| * @class `Strings` | ||
| * @constructor | ||
| * @return {Object} Instance of a Strings object | ||
| */ | ||
| function Strings(context) { | ||
| function Strings(context, options) { | ||
| if (!(this instanceof Strings)) { | ||
@@ -38,3 +41,7 @@ return new Strings(context); | ||
| this._context = context || {}; | ||
| this.options = options || {}; | ||
| this.options.nonull = false; | ||
| this.context = context || {}; | ||
| this._replacements = {}; | ||
@@ -50,10 +57,14 @@ this._propstrings = {}; | ||
| /** | ||
| * ## .propstring (name, propstring) | ||
| * ## .propstring | ||
| * | ||
| * Get or set a propstring. | ||
| * Set or get a named propstring. | ||
| * | ||
| * ```js | ||
| * strings.propstring(name, propstring) | ||
| * ``` | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.propstring('permalinks', ':destBase/:dirname/:basename/index.:ext'); | ||
| * strings.propstring('url', ':base/blog/posts/:basename:ext'); | ||
| * ``` | ||
@@ -63,10 +74,24 @@ * | ||
| * @param {String} `propstring` | ||
| * @return {Object} Instance of the current Strings object | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
| */ | ||
| Strings.prototype.propstring = function (name, str) { | ||
| if (_.isUndefined(str)) { | ||
| return this._propstrings[name]; | ||
| var isPropstring = function(str) { | ||
| return /:/.test(str) ? 'null' : str; | ||
| }; | ||
| Strings.prototype.propstring = function (name, str, options) { | ||
| options = _.extend({}, this.options, options); | ||
| if (!str) { | ||
| // if `nonull:false` return the propstring or `'__null__'` | ||
| if (options.nonull === false) { | ||
| return this._propstrings[name] || isPropstring(name); | ||
| } | ||
| // if only one argument is passed, lookup the name | ||
| // and return the propstring. Or just return the | ||
| // name if it isn't set already. | ||
| return this._propstrings[name] || name; | ||
| } | ||
| this._propstrings[name] = str; | ||
@@ -78,15 +103,20 @@ return this; | ||
| /** | ||
| * ## .pattern (name, pattern) | ||
| * ## .pattern | ||
| * | ||
| * Get or set regular expression or string. | ||
| * Set or get a string or regex pattern to be used for matching. | ||
| * | ||
| * ```js | ||
| * strings.pattern(name, pattern, flags); | ||
| * ``` | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.pattern('prop', ':([\\w]+)'); | ||
| * strings.pattern('anyProp', ':([\\w]+)'); | ||
| * ``` | ||
| * | ||
| * @param {String} `name` | ||
| * @param {String} `pattern` | ||
| * @return {Object} Instance of the current Strings object | ||
| * @param {String} `name` The name of the stored pattern. | ||
| * @param {String|RegExp|Function} `pattern` The pattern to use for matching. | ||
| * @param {String} `flags` Optionally pass RegExp flags to use. | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
@@ -96,5 +126,3 @@ */ | ||
| Strings.prototype.pattern = function (name, pattern, flags) { | ||
| if (_.isUndefined(pattern)) { | ||
| return this._patterns[name]; | ||
| } | ||
| if (!pattern) {return this._patterns[name];} | ||
| if (!(pattern instanceof RegExp)) { | ||
@@ -109,6 +137,11 @@ pattern = new RegExp(pattern, flags || ''); | ||
| /** | ||
| * ## .replacement (name, replacement) | ||
| * ## .replacement | ||
| * | ||
| * Get or set a replacement string or function. | ||
| * Set or get a replacement pattern. Replacement patterns can be a | ||
| * regular expression, string or function. | ||
| * | ||
| * ```js | ||
| * strings.replacement(name, replacement) | ||
| * ``` | ||
| * | ||
| * **Example** | ||
@@ -123,4 +156,4 @@ * | ||
| * @param {String} `name` | ||
| * @param {String} `replacement` | ||
| * @return {Object} Instance of the current Strings object | ||
| * @param {String|Function} `replacement` The replacement to use when patterns are matched. | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
@@ -130,5 +163,3 @@ */ | ||
| Strings.prototype.replacement = function (name, replacement) { | ||
| if (_.isUndefined(replacement)) { | ||
| return this._replacements[name]; | ||
| } | ||
| if (!replacement) {return this._replacements[name];} | ||
| this._replacements[name] = replacement; | ||
@@ -140,40 +171,19 @@ return this; | ||
| /** | ||
| * ## .parser ( name, replacement-patterns ) | ||
| * ## .parser | ||
| * | ||
| * Define a named parser to be used against any given string. | ||
| * Set a parser that can later be used to parse any given string. | ||
| * | ||
| * **Example** | ||
| * | ||
| * Pass an object: | ||
| * | ||
| * ```js | ||
| * strings.parser('prop', { | ||
| * pattern: /:([\\w]+)/, | ||
| * replacement: function(match) { | ||
| * return match.toUpperCase(); | ||
| * } | ||
| * ); | ||
| * strings.parser (name, replacements) | ||
| * ``` | ||
| * | ||
| * Or an array | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.parser('prop', [ | ||
| * { | ||
| * pattern: 'a', | ||
| * replacement: 'b' | ||
| * }, | ||
| * { | ||
| * pattern: 'c', | ||
| * replacement: 'd' | ||
| * } | ||
| * ]); | ||
| * ``` | ||
| * {%= docs("example-parser.md") %} | ||
| * | ||
| * @param {String} `name` name of the parser. | ||
| * @param {Object|Array} `pairings` array of replacement patterns to store with the given name. | ||
| * @param {String|RegExp} `pattern` | ||
| * @param {String|Function} `replacement` | ||
| * @return {Object} Instance of the current Strings object | ||
| * | ||
| * @param {String} `name` | ||
| * @param {Object|Array} `arr` Object or array of replacement patterns to associate. | ||
| * @property {String|RegExp} `pattern` | ||
| * @property {String|Function} `replacement` | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
@@ -183,6 +193,4 @@ */ | ||
| Strings.prototype.parser = function (name, arr) { | ||
| if (_.isUndefined(arr)) { | ||
| return this._parsers[name]; | ||
| } | ||
| this._parsers[name] = !Array.isArray(arr) ? [arr] : arr; | ||
| if (!arr) {return this._parsers[name];} | ||
| this._parsers[name] = utils.arrayify(arr); | ||
| return this; | ||
@@ -193,7 +201,10 @@ }; | ||
| /** | ||
| * ## .parsers ( parsers ) | ||
| * ## .parsers | ||
| * | ||
| * Return a list of parsers based on the given list of named | ||
| * parsers or parser objects. | ||
| * Get an array of stored parsers by passing a parser name or array of parser names. | ||
| * | ||
| * ```js | ||
| * strings.parsers(array) | ||
| * ``` | ||
| * | ||
| * **Example** | ||
@@ -209,5 +220,5 @@ * | ||
| * | ||
| * {%= docs("parsers-example.md") %} | ||
| * {%= docs("example-parsers.md") %} | ||
| * | ||
| * @param {String|Array} `parsers` named parsers or parser objects to use. | ||
| * @param {String|Array} `parsers` string or array of parsers to get. | ||
| * @return {Array} | ||
@@ -222,7 +233,6 @@ * @api public | ||
| } | ||
| parsers = utils.arrayify(parsers); | ||
| parsers = Array.isArray(parsers) ? parsers : [parsers]; | ||
| // find the specified parsers | ||
| var _parsers = _.map(parsers, function (parser) { | ||
| var arr = _.flatten(_.map(parsers, function (parser) { | ||
| // if this is an actual parser object, just return it | ||
@@ -232,3 +242,2 @@ if (_.isObject(parser)) { | ||
| } | ||
| // find the parser and return it | ||
@@ -238,6 +247,6 @@ if (this._parsers.hasOwnProperty(parser)) { | ||
| } | ||
| }, this); | ||
| }, this)); | ||
| // finally normalize and return parsers | ||
| return utils._normalize(_.flatten(_parsers)); | ||
| return utils._normalizePatterns(arr); | ||
| }; | ||
@@ -247,13 +256,18 @@ | ||
| /** | ||
| * ## .extend ( parser, replacement-patterns ) | ||
| * ## .extendParser | ||
| * | ||
| * Extend a parser. | ||
| * Extend a parser with additional replacement patterns. Useful if you're using | ||
| * an external module for replacement patterns and you need to extend it. | ||
| * | ||
| * ```js | ||
| * strings.extendParser(parser, replacements) | ||
| * ``` | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.extend('prop', { | ||
| * strings.extendParser('prop', { | ||
| * pattern: /:([\\w]+)/, | ||
| * replacement: function(match) { | ||
| * return match.toUpperCase(); | ||
| * replacement: function(str) { | ||
| * return str.toUpperCase(); | ||
| * } | ||
@@ -267,9 +281,9 @@ * ); | ||
| * @param {String|Function} `replacement` | ||
| * @return {Object} Instance of the current Strings object | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
| */ | ||
| Strings.prototype.extend = function (name, arr) { | ||
| arr = !Array.isArray(arr) ? [arr] : arr; | ||
| var parser = _.union(this._parsers[name], arr); | ||
| Strings.prototype.extendParser = function (name, arr) { | ||
| arr = utils.arrayify(arr); | ||
| var parser = _.union([], this._parsers[name], arr); | ||
| this._parsers[name] = parser; | ||
@@ -281,21 +295,27 @@ return this; | ||
| /** | ||
| * ## .template( name, propstring, parsers ) | ||
| * ## .template | ||
| * | ||
| * Store, by name, a named propstring and an array of parsers. | ||
| * Set or get a reusable Strings template, consisting of a propstring | ||
| * and an array of parsers. | ||
| * | ||
| * Templates are useful since they can be stored and then later used | ||
| * with any context. | ||
| * | ||
| * ```js | ||
| * strings.template(name, propstring, parsers); | ||
| * ``` | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * // strings.template(name string, array); | ||
| * strings.template('prop', ['prop'], { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * }); | ||
| * strings.template('abc', ':a/:b/:c', ['a', 'b', 'c']); | ||
| * // or use a named propstring | ||
| * strings.template('abc', 'foo', ['a', 'b', 'c']); | ||
| * here ^ | ||
| * ``` | ||
| * | ||
| * @param {String} `name` The name of the template to store | ||
| * @param {String} `name` Name of replacement group to use for building the final string | ||
| * @param {Object} `context` Optional Object to bind to replacement function as `this` | ||
| * @return {String} | ||
| * @param {String} `name` | ||
| * @param {String} `propstring` | ||
| * @param {Array} `parsers` Names of the parsers to use with the template. | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
@@ -305,18 +325,15 @@ */ | ||
| Strings.prototype.template = function (name, propstring, parsers) { | ||
| if (_.isUndefined(propstring) && _.isUndefined(parsers)) { | ||
| // Get the stored template only the name is passed | ||
| if (arguments.length === 1) { | ||
| return this._templates[name]; | ||
| } | ||
| if (arguments.length === 2 && typeof propstring === 'object') { | ||
| this._templates[name] = { | ||
| propstring: this.propstring(propstring.propstring), | ||
| parsers: propstring.parsers | ||
| }; | ||
| } else { | ||
| this._templates[name] = { | ||
| propstring: this.propstring(propstring), | ||
| parsers: parsers | ||
| }; | ||
| var opts = propstring; | ||
| propstring = opts.propstring, | ||
| parsers = opts.parsers | ||
| } else if (arguments.length === 2 && typeof propstring === 'string') { | ||
| throw new Error('Templates must be defined with an object or array of parsers.'); | ||
| } | ||
| propstring = this.propstring(propstring); | ||
| this._templates[name] = {propstring: propstring, parsers: parsers}; | ||
| return this; | ||
@@ -327,87 +344,43 @@ }; | ||
| /** | ||
| * ## .transform( named-propstring, named-parsers, context) | ||
| * ## .replace | ||
| * | ||
| * Similar to `.process`, except that the first parameter is the name | ||
| * of the stored `propstring` to use, rather than any given string. | ||
| * Replace `:propstrings` with the real values. | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.transform('propstring', ['parser'], { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * }); | ||
| * strings.replace(str, context) | ||
| * ``` | ||
| * | ||
| * Or pass an object, `strings.transform({})`: | ||
| * | ||
| * ```js | ||
| * strings.transform({ | ||
| * propstring: 'prop', | ||
| * parsers: ['prop'], | ||
| * context: { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * } | ||
| * }); | ||
| * ``` | ||
| * | ||
| * @param {String} `name` The name of the stored template to use | ||
| * @param {Object} `context` The optional context object to bind to replacement functions as `this` | ||
| * @return {String} | ||
| * @api public | ||
| */ | ||
| Strings.prototype.transform = function (propstring, parsers, context) { | ||
| if (arguments.length === 1) { | ||
| propstring = propstring.propstring; | ||
| parsers = propstring.parsers; | ||
| context = propstring.context; | ||
| } | ||
| return this.process(this.propstring(propstring), parsers, context); | ||
| }; | ||
| /** | ||
| * ## .use( named-propstring, named-parsers, context) | ||
| * | ||
| * Similar to `.process`, except that the first parameter is the name | ||
| * of the stored `propstring` to use, rather than any given string. | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.use('propstring', ['parser'], { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * strings.replace(':a/:b/:c', { | ||
| * a: 'foo', | ||
| * b: 'bar', | ||
| * c: 'baz' | ||
| * }); | ||
| * //=> foo/bar/baz | ||
| * ``` | ||
| * | ||
| * Or pass an object, `strings.use({})`: | ||
| * | ||
| * ```js | ||
| * strings.use({ | ||
| * propstring: 'prop', | ||
| * parsers: ['prop'], | ||
| * context: { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * } | ||
| * }); | ||
| * ``` | ||
| * | ||
| * @param {String} `name` The name of the stored template to use | ||
| * @param {Object} `context` The optional context object to bind to replacement functions as `this` | ||
| * @return {String} | ||
| * @param {String} `str` The string with `:propstrings` to replace. | ||
| * @param {String} `context` The object with replacement properties. | ||
| * @return {Strings} to allow chaining | ||
| * @api public | ||
| */ | ||
| Strings.prototype.use = function (template, context) { | ||
| var tmpl = this.template(template); | ||
| return this.process(tmpl.propstring, tmpl.parsers, context); | ||
| Strings.prototype.replace = function (str, context) { | ||
| var ctx = _.extend({}, this.context, context); | ||
| return replace.strWithArr(str, utils._bind([ | ||
| { | ||
| pattern: /:([\w-]+)/g, | ||
| replacement: function(match, prop) { | ||
| return this[prop] || prop; | ||
| } | ||
| }, | ||
| { | ||
| pattern: /\{([^}]+)}/g, | ||
| replacement: function(match, prop) { | ||
| return this[prop] || prop; | ||
| } | ||
| } | ||
| ], ctx)); | ||
| }; | ||
@@ -417,18 +390,14 @@ | ||
| /** | ||
| * ## .process (str, parsers, context) | ||
| * ## .process | ||
| * | ||
| * Directly process the given string, using a named replacement | ||
| * Directly process the given prop-string, using a named replacement | ||
| * pattern or array of named replacement patterns, with the given | ||
| * context. | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.process(':foo/:bar/:baz', ['a', 'b', 'c'], { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * }); | ||
| * strings.process(str, parsers, context) | ||
| * ``` | ||
| * | ||
| * {%= docs("example-process") %} | ||
| * | ||
| * @param {String} `str` the string to process | ||
@@ -442,5 +411,16 @@ * @param {String|Object|Array} `parsers` named parsers or parser objects to use when processing. | ||
| Strings.prototype.process = function (str, arr, context) { | ||
| var parsers = this.parsers(arr); | ||
| var ctx = _.extend({}, this._context, context); | ||
| return frep.strWithArr(str, utils._bind(parsers, ctx)); | ||
| if (arguments.length === 1) { | ||
| throw new Error('`strings.process()` expects at least two arguments.'); | ||
| } | ||
| if (this._templates.hasOwnProperty(str)) { | ||
| context = arr; | ||
| var template = this._templates[str]; | ||
| str = template.propstring; | ||
| arr = template.parsers; | ||
| } | ||
| arr = this.parsers(arr); | ||
| var ctx = _.extend({}, this.context, context); | ||
| return replace.strWithArr(str, utils._bind(arr, ctx)); | ||
| }; | ||
@@ -450,56 +430,21 @@ | ||
| /** | ||
| * ## .group ( name, propstring, parsers ) | ||
| * ## .run | ||
| * | ||
| * Define a named group of propstring/parser mappings, or get a | ||
| * group if only the name is passed. | ||
| * Process a template with the given context. | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * strings.group('my-group-name', ':foo/:bar/:baz', ['a', 'b', 'c']); | ||
| * strings.run(template, context) | ||
| * ``` | ||
| * | ||
| * To get a group: | ||
| * | ||
| * ```js | ||
| * strings.group( name ); | ||
| * ``` | ||
| * | ||
| * @param {String} `name` | ||
| * @param {String} `propstring` the name of the propstring to use | ||
| * @param {String|Array} `parsers` name or array of names of parsers to use | ||
| * @return {Object} Instance of the current Strings object | ||
| * @api public | ||
| */ | ||
| Strings.prototype.group = function (groupName, propstring, parsers) { | ||
| if (_.isUndefined(propstring) && _.isUndefined(parsers)) { | ||
| return this._groups[groupName]; | ||
| } | ||
| this._groups[groupName] = { | ||
| propstring: propstring, | ||
| parsers: parsers | ||
| }; | ||
| return this; | ||
| }; | ||
| /** | ||
| * ## .run ( groupname, context ) | ||
| * | ||
| * Process the specified group using the given context. | ||
| * | ||
| * **Example** | ||
| * | ||
| * Set: (`strings.run( string, object )`) | ||
| * | ||
| * ```js | ||
| * strings.run('my-group-name', { | ||
| * foo: 'aaa', | ||
| * bar: 'bbb', | ||
| * baz: 'ccc' | ||
| * strings.run('blogTemplate', { | ||
| * dest: '_gh_pages', | ||
| * basename: '2014-07-01-post', | ||
| * ext: '.html' | ||
| * }); | ||
| * ``` | ||
| * | ||
| * @param {String} `group` The group to run. | ||
| * @param {String} `template` The template to process. | ||
| * @param {Object} `context` Optional context object, to bind to replacement function as `this` | ||
@@ -510,5 +455,7 @@ * @return {String} | ||
| Strings.prototype.run = function (group, context) { | ||
| var namedGroup = this.group(group); | ||
| return this.transform(namedGroup.propstring, namedGroup.parsers, context); | ||
| Strings.prototype.run = function (name, context) { | ||
| var template = this._templates[name]; | ||
| var propstring = template.propstring; | ||
| var parsers = template.parsers; | ||
| return this.process(propstring, parsers, context); | ||
| }; | ||
@@ -515,0 +462,0 @@ |
+80
-21
| /** | ||
| * Strings <https://github.com/sellside/strings> | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
@@ -11,16 +11,61 @@ * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| var _ = require('lodash'); | ||
| var utils = {}; | ||
| utils._normalize = function (parsers) { | ||
| /** | ||
| * Export `utils` | ||
| */ | ||
| var utils = module.exports = {}; | ||
| /** | ||
| * ## .arrayify | ||
| * | ||
| * Ensure that values are returned as an array. | ||
| * | ||
| * @param {Object|Array} `value` | ||
| * @return {Array} | ||
| */ | ||
| utils.arrayify = function(value) { | ||
| return !Array.isArray(value) ? [value] : value; | ||
| }; | ||
| /** | ||
| * ## ._normalizePatterns | ||
| * | ||
| * Normalize `key: value` replacement patterns into an array | ||
| * of objects with `pattern` and `replacement` keys. | ||
| * | ||
| * **Example** | ||
| * | ||
| * ```js | ||
| * [ | ||
| * {key: value}, | ||
| * {key: value} | ||
| * ] | ||
| * ``` | ||
| * converts to: | ||
| * | ||
| * ```js | ||
| * [ | ||
| * { pattern: key, replacement: value }, | ||
| * { pattern: key, replacement: value } | ||
| * ] | ||
| * ``` | ||
| * | ||
| * @param {Object|Array} parsers | ||
| * @return {Object} | ||
| * @api private | ||
| */ | ||
| utils._normalizePatterns = function (replacementPatterns) { | ||
| var arr = []; | ||
| if (Array.isArray(parsers)) { | ||
| // [{key: value}, {key, value}] => [{pattern: key, replacement: value], {pattern:key, replacement: value}] | ||
| var i; | ||
| for (i = 0; i < parsers.length; i++) { | ||
| arr = arr.concat(utils._normalizeObject(parsers[i])); | ||
| if (Array.isArray(replacementPatterns)) { | ||
| for (var i = 0; i < replacementPatterns.length; i++) { | ||
| arr = arr.concat(utils._normalizeObj(replacementPatterns[i])); | ||
| } | ||
| } else { | ||
| // {key: value} => [{pattern: key, replacement: value}]; | ||
| arr = arr.concat(utils._normalizeObject(parsers)); | ||
| arr = arr.concat(utils._normalizeObj(replacementPatterns)); | ||
| } | ||
@@ -31,12 +76,18 @@ return arr; | ||
| utils._normalizeObject = function (obj) { | ||
| /** | ||
| * ## ._normalizeObj | ||
| * | ||
| * Normalize the `key: value` pairs in a single replacement | ||
| * pattern object. | ||
| * | ||
| * @param {Object} `obj` | ||
| * @return {Array} | ||
| */ | ||
| if (_.isUndefined(obj)) { | ||
| return []; | ||
| } | ||
| if (obj.hasOwnProperty('pattern') && obj.hasOwnProperty('replacement')) { | ||
| utils._normalizeObj = function (obj) { | ||
| if (_.isUndefined(obj)) return []; | ||
| if (obj.hasOwnProperty('pattern') | ||
| && obj.hasOwnProperty('replacement')) { | ||
| return [obj]; | ||
| } | ||
| var arr = []; | ||
@@ -46,3 +97,2 @@ _.forOwn(obj, function (value, key) { | ||
| }); | ||
| return arr; | ||
@@ -52,4 +102,15 @@ }; | ||
| /** | ||
| * ## ._bind | ||
| * | ||
| * Bind the current `Strings` object, enabling `this` to | ||
| * be used in replacement functions. | ||
| * | ||
| * @param {Object|Array} `replacements` | ||
| * @param {Object} `context` | ||
| * @return {Array} | ||
| */ | ||
| utils._bind = function (replacements, context) { | ||
| replacements = _.cloneDeep(replacements); | ||
| replacements = _.cloneDeep(utils.arrayify(replacements)); | ||
| context = context || {}; | ||
@@ -67,3 +128,1 @@ | ||
| }; | ||
| module.exports = utils; |
+5
-2
| { | ||
| "name": "strings", | ||
| "version": "0.3.3", | ||
| "version": "0.4.0", | ||
| "description": "Easily replace and transform :props in strings.", | ||
@@ -63,5 +63,8 @@ "homepage": "https://github.com/doowb/strings", | ||
| "mocha": "^1.19.0", | ||
| "parse-filepath": "^0.3.0", | ||
| "relative": "^0.1.4", | ||
| "verb": "^0.2.11" | ||
| "verb": "^0.2.11", | ||
| "verb-tag-jscomments": "^0.1.4", | ||
| "verbalize": "^0.1.2" | ||
| } | ||
| } |
+127
-155
@@ -24,7 +24,7 @@ # strings [](http://badge.fury.io/js/strings) | ||
| ## API | ||
| ### new Strings() | ||
| ### Strings | ||
| > Strings constructor method | ||
| Instantiate a new instance of Strings, optionally passing a default context to use. | ||
| Create a new instance of `Strings`, optionally passing a default context to use. | ||
@@ -36,9 +36,13 @@ **Example** | ||
| ``` | ||
| * `return`{Object} Instance of a Strings object | ||
| * `return` {Object} Instance of a Strings object | ||
| ### .propstring | ||
| ### .propstring ( name, propstring ) | ||
| Set or get a named propstring. | ||
| Get or set a propstring. | ||
| ```js | ||
| strings.propstring(name, propstring) | ||
| ``` | ||
@@ -48,29 +52,39 @@ **Example** | ||
| ```js | ||
| strings.propstring('permalinks', ':destBase/:dirname/:basename/index.:ext'); | ||
| strings.propstring('url', ':base/blog/posts/:basename:ext'); | ||
| ``` | ||
| * `name` {String}: | ||
| * `propstring` {String}: | ||
| * `return` {Object} Instance of the current Strings object | ||
| * `name` {String} | ||
| * `propstring` {String} | ||
| * `return`{Strings} to allow chaining | ||
| ### .pattern ( name, pattern ) | ||
| ### .pattern | ||
| Get or set regular expression or string. | ||
| Set or get a string or regex pattern to be used for matching. | ||
| ```js | ||
| strings.pattern(name, pattern, flags); | ||
| ``` | ||
| **Example** | ||
| ```js | ||
| strings.pattern('prop', ':([\\w]+)'); | ||
| strings.pattern('anyProp', ':([\\w]+)'); | ||
| ``` | ||
| * `name` {String}: | ||
| * `pattern` {String}: | ||
| * `return` {Object} Instance of the current Strings object | ||
| * `name` {String}: The name of the stored pattern. | ||
| * `pattern` {String|RegExp|Function}: The pattern to use for matching. | ||
| * `flags` {String}: Optionally pass RegExp flags to use. | ||
| * `return`{Strings} to allow chaining | ||
| ### .replacement ( name, replacement ) | ||
| ### .replacement | ||
| Get or set a replacement string or function. | ||
| Set or get a replacement pattern. Replacement patterns can be a | ||
| regular expression, string or function. | ||
| ```js | ||
| strings.replacement(name, replacement) | ||
| ``` | ||
| **Example** | ||
@@ -84,11 +98,15 @@ | ||
| * `name` {String}: | ||
| * `replacement` {String}: | ||
| * `return` {Object} Instance of the current Strings object | ||
| * `name` {String} | ||
| * `replacement` {String|Function}: The replacement to use when patterns are matched. | ||
| * `return`{Strings} to allow chaining | ||
| ### .parser ( name, replacement-patterns ) | ||
| ### .parser | ||
| Define a named parser to be used against any given string. | ||
| Set a parser that can later be used to parse any given string. | ||
| ```js | ||
| strings.parser (name, replacements) | ||
| ``` | ||
| **Example** | ||
@@ -106,3 +124,2 @@ | ||
| ``` | ||
| Or an array | ||
@@ -123,14 +140,15 @@ | ||
| * `name` {String}: name of the parser. | ||
| * `pairings` {Object|Array}: array of replacement patterns to store with the given name. | ||
| * `pattern` {String|RegExp}: | ||
| * `replacement` {String|Function}: | ||
| * `return` {Object} Instance of the current Strings object | ||
| * `name` {String} | ||
| * `arr` {Object|Array}: Object or array of replacement patterns to associate. | ||
| * `return`{Strings} to allow chaining | ||
| ### .parsers ( parsers ) | ||
| ### .parsers | ||
| Return a list of parsers based on the given list of named | ||
| parsers or parser objects. | ||
| Get an array of stored parsers by passing a parser name or array of parser names. | ||
| ```js | ||
| strings.parsers(array) | ||
| ``` | ||
| **Example** | ||
@@ -146,2 +164,3 @@ | ||
| Using `parsers` like this: | ||
@@ -176,17 +195,22 @@ | ||
| * `parsers` {String|Array}: named parsers or parser objects to use. | ||
| * `return` {Array} | ||
| * `parsers` {String|Array}: string or array of parsers to get. | ||
| * `return`{Array} | ||
| ### .extend ( parser, replacement-patterns ) | ||
| ### .extendParser | ||
| Extend a parser. | ||
| Extend a parser with additional replacement patterns. Useful if you're using | ||
| an external module for replacement patterns and you need to extend it. | ||
| ```js | ||
| strings.extendParser(parser, replacements) | ||
| ``` | ||
| **Example** | ||
| ```js | ||
| strings.extend('prop', { | ||
| strings.extendParser('prop', { | ||
| pattern: /:([\\w]+)/, | ||
| replacement: function(match) { | ||
| return match.toUpperCase(); | ||
| replacement: function(str) { | ||
| return str.toUpperCase(); | ||
| } | ||
@@ -198,110 +222,79 @@ ); | ||
| * `arr` {Object|Array}: array of replacement patterns to store with the given name. | ||
| * `pattern` {String|RegExp}: | ||
| * `replacement` {String|Function}: | ||
| * `return` {Object} Instance of the current Strings object | ||
| * `pattern` {String|RegExp} | ||
| * `replacement` {String|Function} | ||
| * `return`{Strings} to allow chaining | ||
| ### .template ( name, propstring, parsers ) | ||
| ### .template | ||
| Store, by name, a named propstring and an array of parsers. | ||
| Set or get a reusable Strings template, consisting of a propstring | ||
| and an array of parsers. | ||
| **Example** | ||
| Templates are useful since they can be stored and then later used | ||
| with any context. | ||
| ```js | ||
| // strings.template(name string, array); | ||
| strings.template('prop', ['prop'], { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| }); | ||
| strings.template(name, propstring, parsers); | ||
| ``` | ||
| * `name` {String}: The name of the template to store | ||
| * `name` {String}: Name of replacement group to use for building the final string | ||
| * `context` {Object}: Optional Object to bind to replacement function as `this` | ||
| * `return` {String} | ||
| ### .transform ( named-propstring, named-parsers, context ) | ||
| Similar to `.process`, except that the first parameter is the name | ||
| of the stored `propstring` to use, rather than any given string. | ||
| **Example** | ||
| ```js | ||
| strings.transform('propstring', ['parser'], { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| }); | ||
| strings.template('abc', ':a/:b/:c', ['a', 'b', 'c']); | ||
| // or use a named propstring | ||
| strings.template('abc', 'foo', ['a', 'b', 'c']); | ||
| here ^ | ||
| ``` | ||
| Or pass an object, `strings.transform({})`: | ||
| * `name` {String} | ||
| * `propstring` {String} | ||
| * `parsers` {Array}: Names of the parsers to use with the template. | ||
| * `return`{Strings} to allow chaining | ||
| ```js | ||
| strings.transform({ | ||
| propstring: 'prop', | ||
| parsers: ['prop'], | ||
| context: { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| } | ||
| }); | ||
| ``` | ||
| * `name` {String}: The name of the stored template to use | ||
| * `context` {Object}: The optional context object to bind to replacement functions as `this` | ||
| * `return` {String} | ||
| ### .replace | ||
| Replace `:propstrings` with the real values. | ||
| ### .use ( named-propstring, named-parsers, context ) | ||
| Similar to `.process`, except that the first parameter is the name | ||
| of the stored `propstring` to use, rather than any given string. | ||
| **Example** | ||
| ```js | ||
| strings.use('propstring', ['parser'], { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| }); | ||
| strings.replace(str, context) | ||
| ``` | ||
| Or pass an object, `strings.use({})`: | ||
| **Example** | ||
| ```js | ||
| strings.use({ | ||
| propstring: 'prop', | ||
| parsers: ['prop'], | ||
| context: { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| } | ||
| strings.replace(':a/:b/:c', { | ||
| a: 'foo', | ||
| b: 'bar', | ||
| c: 'baz' | ||
| }); | ||
| //=> foo/bar/baz | ||
| ``` | ||
| * `name` {String}: The name of the stored template to use | ||
| * `context` {Object}: The optional context object to bind to replacement functions as `this` | ||
| * `return` {String} | ||
| * `str` {String}: The string with `:propstrings` to replace. | ||
| * `context` {String}: The object with replacement properties. | ||
| * `return`{Strings} to allow chaining | ||
| ### .process ( str, parsers, context ) | ||
| ### .process | ||
| Directly process the given string, using a named replacement | ||
| Directly process the given prop-string, using a named replacement | ||
| pattern or array of named replacement patterns, with the given | ||
| context. | ||
| **Example** | ||
| ```js | ||
| strings.process(str, parsers, context) | ||
| ``` | ||
| **Examples:** | ||
| Pass a propstring and the parsers to use: | ||
| ```js | ||
| strings.process(':foo/:bar/:baz', ['a', 'b', 'c'], { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| }); | ||
| // define some parsers to do simple key-value replacements | ||
| strings.parser('a', {'{foo}': 'AAA'}); | ||
| strings.parser('b', {'{bar}': 'BBB'}); | ||
| strings.parser('c', {'{baz}': 'CCC'}); | ||
| console.log(strings.process('{foo}/{bar}/{baz}', ['a', 'b', 'c'])); | ||
| // => 'AAA/BBB/CCC' | ||
| ``` | ||
@@ -311,63 +304,42 @@ | ||
| * `parsers` {String|Object|Array}: named parsers or parser objects to use when processing. | ||
| * `context` {Object}: context to use. optional if a global context is passed. | ||
| * `return` {String} | ||
| * `context` {Object}: context to use. optional if a global context is passed. | ||
| * `return`{String} | ||
| ### .group ( name, propstring, parsers ) | ||
| ### .run | ||
| Define a named group of propstring/parser mappings, or get a | ||
| group if only the name is passed. | ||
| Process a template with the given context. | ||
| **Example** | ||
| ```js | ||
| strings.group('my-group-name', ':foo/:bar/:baz', ['a', 'b', 'c']); | ||
| strings.run(template, context) | ||
| ``` | ||
| To get a group: | ||
| ```js | ||
| strings.group( name ); | ||
| ``` | ||
| * `name` {String}: | ||
| * `propstring` {String}: the name of the propstring to use | ||
| * `parsers` {String|Array}: name or array of names of parsers to use | ||
| * `return` {Object} Instance of the current Strings object | ||
| ### .run ( groupname, context ) | ||
| Process the specified group using the given context. | ||
| **Example** | ||
| Set: (`strings.run( string, object )`) | ||
| ```js | ||
| strings.run('my-group-name', { | ||
| foo: 'aaa', | ||
| bar: 'bbb', | ||
| baz: 'ccc' | ||
| strings.run('blogTemplate', { | ||
| dest: '_gh_pages', | ||
| basename: '2014-07-01-post', | ||
| ext: '.html' | ||
| }); | ||
| ``` | ||
| * `group` {String}: The group to run. | ||
| * `context` {Object}: Optional context object, to bind to replacement function as `this` | ||
| * `return` {String} | ||
| * `template` {String}: The template to process. | ||
| * `context` {Object}: Optional context object, to bind to replacement function as `this` | ||
| * `return`{String} | ||
| ## Authors | ||
| **Jon Schlinkert** | ||
| + [github/jonschlinkert](https://github.com/jonschlinkert) | ||
| + [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
| **Brian Woodward** | ||
| + [github/doowb](https://github.com/doowb) | ||
| + [twitter/doowb](http://twitter.com/doowb) | ||
| + [twitter/doowb](http://twitter.com/doowb) | ||
| **Jon Schlinkert** | ||
| + [github/jonschlinkert](https://github.com/jonschlinkert) | ||
| + [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
| ## License | ||
@@ -379,2 +351,2 @@ Copyright (c) 2014 Brian Woodward, contributors. | ||
| _This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 27, 2014._ | ||
| _This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 30, 2014._ |
+23
-23
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.parser() - add', function() { | ||
| var strings = new Strings(); | ||
| describe('.parser', function() { | ||
| var strings; | ||
| beforeEach(function() { | ||
| strings = new Strings(); | ||
| }); | ||
| describe('when a named parser is defined', function() { | ||
| it('should replace values with strings', function () { | ||
| var name = 'test-parser-1'; | ||
| var actual = [{ | ||
@@ -21,9 +27,8 @@ ':basename': 'foo', | ||
| }]; | ||
| strings.parser(name, actual); | ||
| expect(strings._parsers).to.have.property(name); | ||
| expect(actual).to.eql(strings._parsers[name]); | ||
| strings.parser('a', actual); | ||
| expect(strings._parsers).to.have.property('a'); | ||
| expect(actual).to.eql(strings._parsers['a']); | ||
| }); | ||
| it('should replace values with functions', function () { | ||
| var name = 'test-parser-1'; | ||
| var actual = [{ | ||
@@ -38,16 +43,11 @@ ':basename': function () { | ||
| strings.parser(name, actual); | ||
| expect(strings._parsers).to.have.property(name); | ||
| expect(actual).to.eql(strings._parsers[name]); | ||
| strings.parser('b', actual); | ||
| expect(strings._parsers).to.have.property('b'); | ||
| expect(actual).to.eql(strings._parsers['b']); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('.parser() - get', function() { | ||
| var strings = new Strings(); | ||
| describe('when only one paramter is passed', function() { | ||
| it('it should retrieve the stored parser with the given name', function () { | ||
| var name = 'test-parser-2'; | ||
| var actual = [{ | ||
| it('it should get the parser with the given name', function () { | ||
| var parser = { | ||
| ':basename': function () { | ||
@@ -59,7 +59,7 @@ return 'foo'; | ||
| } | ||
| }]; | ||
| strings.parser(name, actual); | ||
| expect(actual).to.eql(strings.parser(name)); | ||
| }; | ||
| strings.parser('c', parser); | ||
| expect(strings.parser('c')).to.eql([parser]); | ||
| }); | ||
| }); | ||
| }); |
+4
-3
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
@@ -10,0 +11,0 @@ var Strings = require('../'); |
+5
-4
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.pattern()', function() { | ||
| describe('.pattern', function() { | ||
| var strings = new Strings(); | ||
@@ -14,0 +15,0 @@ describe('when a pattern is set', function() { |
+307
-33
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var path = require('path'); | ||
| var expect = require('chai').expect; | ||
@@ -13,3 +15,3 @@ var Strings = require('../'); | ||
| describe('.template()', function () { | ||
| describe('.template', function () { | ||
@@ -19,23 +21,184 @@ var strings; | ||
| strings = new Strings(); | ||
| strings.propstring('pathProps', ':destbase/:dirname/:basename/index:ext'); | ||
| strings.parser('parsePath', [ | ||
| { | ||
| pattern: ':destbase', | ||
| replacement: function () { | ||
| return this.destbase; | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':dirname', | ||
| replacement: function () { | ||
| return path.dirname(this.src); | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':basename', | ||
| replacement: function () { | ||
| return path.basename(this.src, path.extname(this.src)); | ||
| }, | ||
| }, | ||
| { | ||
| pattern: ':ext', | ||
| replacement: function () { | ||
| return path.extname(this.src); | ||
| } | ||
| } | ||
| ]); | ||
| strings.template('permalinks', 'pathProps', ['parsePath']); | ||
| }); | ||
| it('when a template is passed in', function () { | ||
| var expected = ':basename/index:ext'; | ||
| var actual = strings.process(':basename/index:ext'); | ||
| expect(actual).to.eql(expected); | ||
| describe('when no context is passed', function () { | ||
| it('should process the propstring with an array of parsers', function () { | ||
| strings.parser('a', {'{foo}': 'AAA'}); | ||
| strings.parser('b', {'{bar}': 'BBB'}); | ||
| strings.parser('c', {'{baz}': 'CCC'}); | ||
| var actual = strings.process('{foo}/{bar}/{baz}', ['a', 'b', 'c']); | ||
| expect(actual).to.eql('AAA/BBB/CCC'); | ||
| }); | ||
| }); | ||
| it('when a template and parser object are passed in', function () { | ||
| var expected = 'file/index.html'; | ||
| var parser = { | ||
| ':basename': 'file', | ||
| ':ext': '.html' | ||
| }; | ||
| var actual = strings.process(':basename/index:ext', parser); | ||
| expect(actual).to.eql(expected); | ||
| describe('when a context is passed', function () { | ||
| it('should process the propstring with an array of parsers', function () { | ||
| strings.parser('a', {'{foo}': function() { | ||
| return this.alpha.toUpperCase(); | ||
| }}); | ||
| strings.parser('b', {'{bar}': function() { | ||
| return this.beta.toUpperCase(); | ||
| }}); | ||
| strings.parser('c', {'{baz}': function() { | ||
| return this.gamma.toUpperCase(); | ||
| }}); | ||
| var ctx = { | ||
| alpha: 'aaa', | ||
| beta: 'bbb', | ||
| gamma: 'ccc' | ||
| }; | ||
| var actual = strings.process('{foo}/{bar}/{baz}', ['a', 'b', 'c'], ctx); | ||
| expect(actual).to.eql('AAA/BBB/CCC'); | ||
| }); | ||
| }); | ||
| it('when a template, parser object, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = 'file/index.html'; | ||
| describe('when the name of a stored template is passed', function () { | ||
| it('should use the propstring and parsers from the template with the given context', function () { | ||
| var actual = strings.process('permalinks', { | ||
| destbase: 'foo', | ||
| src: 'a/b.html' | ||
| }); | ||
| expect(actual).to.eql('foo/a/b/index.html'); | ||
| }); | ||
| it('should process the stored propstring with the given context', function () { | ||
| var actual = strings.process('permalinks', { | ||
| destbase: '_gh_pages', | ||
| src: 'blog/file.html' | ||
| }); | ||
| expect(actual).to.eql('_gh_pages/blog/file/index.html'); | ||
| }); | ||
| it('should use the propstring and parsers from the template with the given context', function () { | ||
| var actual = strings.process('permalinks', { | ||
| destbase: 'bar', | ||
| src: 'a/b.html' | ||
| }); | ||
| expect(actual).to.eql('bar/a/b/index.html'); | ||
| }); | ||
| }); | ||
| describe('when a single argument is passed:', function () { | ||
| it('should throw an error', function () { | ||
| var actual; | ||
| try { | ||
| strings.process(':basename/index:ext'); | ||
| } catch(err) { | ||
| actual = err; | ||
| } | ||
| expect(/Error/.test(actual)).to.be.true; | ||
| }); | ||
| }); | ||
| describe('when a template...:', function () { | ||
| describe('and parser object are passed:', function () { | ||
| it('should replace propstrings with the parser', function () { | ||
| var actual = strings.process(':basename/index:ext', { | ||
| ':basename': 'file', | ||
| ':ext': '.html' | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| }); | ||
| describe('and parser object and context are passed:', function () { | ||
| it('should replace propstrings with the parser using the given context', function () { | ||
| var parser = [ | ||
| { | ||
| pattern: ':basename', | ||
| replacement: function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':ext', | ||
| replacement: function () { | ||
| return path.extname(this.filepath); | ||
| } | ||
| } | ||
| ]; | ||
| var actual = strings.process(':basename/index:ext', parser, { | ||
| filepath: 'path/to/my/file.html' | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| }); | ||
| }); | ||
| it('when a template, parser object, and context are passed', function () { | ||
| var parser = [ | ||
| { | ||
| pattern: /:basename/, | ||
| replacement: function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| } | ||
| }, | ||
| { | ||
| pattern: /:ext/, | ||
| replacement: function () { | ||
| return path.extname(this.filepath); | ||
| } | ||
| } | ||
| ] | ||
| var actual = strings.process(':basename/index:ext', parser, { | ||
| filepath: 'path/to/my/file.html' | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| it('when a template, parser object, and context are passed', function () { | ||
| var parser = [ | ||
| { | ||
| pattern: /\{basename}/, | ||
| replacement: function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| } | ||
| }, | ||
| { | ||
| pattern: /\{ext}/, | ||
| replacement: function () { | ||
| return path.extname(this.filepath); | ||
| } | ||
| } | ||
| ]; | ||
| var actual = strings.process('{basename}/index{ext}', parser, { | ||
| filepath: 'path/to/my/file.html' | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| it('when a template, parser object, and context are passed', function () { | ||
| var parser = { | ||
@@ -49,13 +212,10 @@ ':basename': function () { | ||
| }; | ||
| var context = { | ||
| var actual = strings.process(':basename/index:ext', parser, { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| var actual = strings.process(':basename/index:ext', parser, context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| it('when a template, named parser, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = 'file/index.html'; | ||
| var parser = { | ||
| it('when a template, named parser, and context are passed', function () { | ||
| strings.parser('path', { | ||
| ':basename': function () { | ||
@@ -67,12 +227,126 @@ return path.basename(this.filepath, path.extname(this.filepath)); | ||
| } | ||
| }; | ||
| var context = { | ||
| }); | ||
| var actual = strings.process(':basename/index:ext', 'path', { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| }); | ||
| expect(actual).to.eql('file/index.html'); | ||
| }); | ||
| strings.parser('path', parser); | ||
| var actual = strings.process(':basename/index:ext', 'path', context); | ||
| expect(actual).to.eql(expected); | ||
| describe('when a named propstring and parser object are defined', function () { | ||
| it('should get the propstring and parse it.', function () { | ||
| var actual = strings.process('{a}/{b}', { | ||
| '{a}': 'foo', | ||
| '{b}': 'bar' | ||
| }); | ||
| expect(actual).to.eql('foo/bar'); | ||
| }); | ||
| }); | ||
| describe('when a parser has replacement functions', function () { | ||
| describe('when fallback values are defined in the functions', function () { | ||
| it('should use the fallbacks when a value is not on the context', function () { | ||
| strings.parser('nonsensical', [ | ||
| { | ||
| pattern: /\{a}/g, | ||
| replacement: function () { | ||
| return this.a || '__UNKNOWN_A__'; | ||
| } | ||
| }, | ||
| { | ||
| pattern: /\{b}/g, | ||
| replacement: function () { | ||
| return this.b || '__UNKNOWN_B__'; | ||
| } | ||
| }, | ||
| { | ||
| pattern: /\{c}/g, | ||
| replacement: function () { | ||
| return this.c || '__UNKNOWN_C__'; | ||
| } | ||
| } | ||
| ]); | ||
| var actual = strings.process('{a}/{b}/{c}', 'nonsensical', {a: 'foo', c: 'bar'}); | ||
| expect(actual).to.eql('foo/__UNKNOWN_B__/bar'); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('when a propstrings are defined but a value is missing on the context', function () { | ||
| it('should just return the actual propstring in the result.', function () { | ||
| var parser = { | ||
| '{base}': function () { | ||
| return this.base; | ||
| }, | ||
| '{name}': function () { | ||
| return this.name; | ||
| }, | ||
| '{ext}': function () { | ||
| return this.ext; | ||
| } | ||
| }; | ||
| strings.template('permalink', '{base}/{dirname}/{name}/index{ext}', parser); | ||
| var actual = strings.process('permalink', { | ||
| base: '_gh_pages', | ||
| name: 'blog', | ||
| ext: '.html' | ||
| }); | ||
| expect(actual).to.eql('_gh_pages/{dirname}/blog/index.html'); | ||
| }); | ||
| }); | ||
| it('when a propstring and parser object are passed', function () { | ||
| var actual = strings.process(':a/:b/:c/index:d', {':c': 'file', ':d': '.html'}); | ||
| expect(actual).to.eql(':a/:b/file/index.html'); | ||
| }); | ||
| describe('when a propstring, parser object, and context are passed:', function () { | ||
| it('should process the string with the given context.', function () { | ||
| var parser = { | ||
| ':c': function () { | ||
| return path.basename(this.foo, path.extname(this.foo)); | ||
| }, | ||
| ':d': function () { | ||
| return path.extname(this.foo); | ||
| }, | ||
| ':a': function () { | ||
| return this.destbase; | ||
| } | ||
| }; | ||
| var actual = strings.process(':a/:b/:c/index:d', parser, { | ||
| foo: 'path/to/my/file.html', | ||
| destbase: '_gh_pages' | ||
| }); | ||
| expect(actual).to.eql('_gh_pages/:b/file/index.html'); | ||
| }); | ||
| }); | ||
| describe('when a default value is passed the parser', function () { | ||
| it('should be used if it\'s not on the context', function () { | ||
| var parser = { | ||
| ':c': function () { | ||
| return path.basename(this.foo, path.extname(this.foo)); | ||
| }, | ||
| ':d': function () { | ||
| return path.extname(this.foo); | ||
| }, | ||
| ':a': function () { | ||
| return this.destbase || '.'; | ||
| } | ||
| }; | ||
| strings.parser('path', parser); | ||
| var actual = strings.process(':a/:b/:c/index:d', 'path', { | ||
| foo: 'path/to/my/file.html' | ||
| }); | ||
| expect(actual).to.eql('./:b/file/index.html'); | ||
| }); | ||
| }); | ||
| }); |
+22
-15
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
@@ -14,20 +15,26 @@ var Strings = require('../'); | ||
| var strings = new Strings(); | ||
| strings.propstring('pretty', ':destbase/:dirname/:basename/index:ext'); | ||
| strings.propstring('test1', ':foo/:baz/:basename/index:ext'); | ||
| strings.propstring('test2', ':basename/index:ext'); | ||
| describe('when a propstring is set', function() { | ||
| it('should be stored by Strings on the `_propstrings` object:', function () { | ||
| var name = 'test1'; | ||
| var template = ':foo/:baz/:basename/index:ext'; | ||
| strings.propstring(name, template); | ||
| var actual = strings._propstrings[name]; | ||
| expect(strings._propstrings).to.have.property(name); | ||
| expect(actual).to.eql(template); | ||
| var actual = strings._propstrings['test1']; | ||
| expect(strings._propstrings).to.have.property('test1'); | ||
| expect(actual).to.eql(':foo/:baz/:basename/index:ext'); | ||
| }); | ||
| it('should be retrievable using `propstring(name)`', function () { | ||
| var name = 'test2'; | ||
| var template = ':basename/index:ext'; | ||
| strings.propstring(name, template); | ||
| var actual = strings.propstring(name); | ||
| expect(template).to.eql(template); | ||
| it('should be able to get the propstring using the name', function () { | ||
| var actual = strings.propstring('test2'); | ||
| expect(actual).to.eql(':basename/index:ext'); | ||
| }); | ||
| it('should get a stored propstring', function () { | ||
| var actual = strings.propstring('pretty'); | ||
| expect(actual).to.eql(':destbase/:dirname/:basename/index:ext'); | ||
| }); | ||
| }); | ||
| }); |
+12
-14
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
@@ -14,21 +15,18 @@ var Strings = require('../'); | ||
| var strings = new Strings(); | ||
| describe('when a replacement is set', function() { | ||
| it('should be stored by Strings on the `_replacements` object:', function () { | ||
| var name = 'a'; | ||
| var replacement = 'b'; | ||
| strings.replacement(name, replacement); | ||
| var actual = strings._replacements[name]; | ||
| expect(strings._replacements).to.have.property(name); | ||
| expect(actual).to.eql(replacement); | ||
| strings.replacement('a', 'b'); | ||
| expect(strings._replacements).to.have.property('a'); | ||
| expect(strings._replacements['a']).to.eql('b'); | ||
| }); | ||
| it('should be retrievable using `replacement(name)`', function () { | ||
| var name = 'b'; | ||
| var replacement = function(match) { return match; }; | ||
| strings.replacement(name, replacement); | ||
| var actual = strings.replacement(name); | ||
| expect(replacement).to.eql(replacement); | ||
| expect(actual).to.be.an.instanceof(Function); | ||
| strings.replacement('b', replacement); | ||
| expect(strings.replacement('b')).to.eql(replacement); | ||
| expect(strings.replacement('b')).to.be.an.instanceof(Function); | ||
| }); | ||
| }); | ||
| }); |
+48
-100
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * Strings <https://github.com/assemble/strings> | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Copyright (c) 2014 Sellside, Jon Schlinkert and Brian Woodward | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| 'use strict'; | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| var path = require('path'); | ||
| var Strings = require('..'); | ||
| describe('.template()', function () { | ||
| describe('.template', function() { | ||
| var strings; | ||
| before(function () { | ||
| beforeEach(function () { | ||
| strings = new Strings(); | ||
| strings.propstring('pretty', ':destbase/:dirname/:basename/index:ext'); | ||
| strings.parser('path', [ | ||
| { | ||
| pattern: ':destbase', | ||
| replacement: function () { | ||
| return this.destbase() | ||
| } | ||
| strings.propstring('pretty', ':a/:b/:c/index:d'); | ||
| strings.parser('path', { | ||
| ':a': function () { | ||
| return this.destbase; | ||
| }, | ||
| { | ||
| pattern: ':dirname', | ||
| replacement: function () { | ||
| return path.dirname(this.src); | ||
| } | ||
| ':b': function () { | ||
| return path.dirname(this.src); | ||
| }, | ||
| { | ||
| pattern: ':basename', | ||
| replacement: function () { | ||
| return path.basename(this.src, path.extname(this.src)); | ||
| }, | ||
| ':c': function () { | ||
| return path.basename(this.src, path.extname(this.src)); | ||
| }, | ||
| { | ||
| pattern: ':ext', | ||
| replacement: function () { | ||
| return path.extname(this.src); | ||
| } | ||
| ':d': function () { | ||
| return path.extname(this.src); | ||
| } | ||
| ]); | ||
| }); | ||
| strings.template('permalinks', 'pretty', ['path']); | ||
| }); | ||
| describe('when propstring and parsers are passed as params', function () { | ||
| it('should return the template by name', function () { | ||
| it('when a template without a parser object is passed', function () { | ||
| strings.propstring('aaa', ':basename/index:ext'); | ||
| var actual = ''; | ||
| try { | ||
| strings.template('foo', 'aaa'); | ||
| } catch(err) { | ||
| actual = err; | ||
| } | ||
| expect(/Error/.test(actual)).to.be.true; | ||
| strings._propstrings = {}; | ||
| }); | ||
| describe('when a single argument is passed', function () { | ||
| it('should lookup template by the given string', function () { | ||
| var expected = { | ||
| propstring: ':destbase/:dirname/:basename/index:ext', | ||
| propstring: ':a/:b/:c/index:d', | ||
| parsers: ['path'] | ||
| }; | ||
| var actual = strings.template('permalinks'); | ||
| expect(actual).to.eql(expected); | ||
| expect(strings.template('permalinks')).to.eql(expected); | ||
| }); | ||
| }); | ||
| describe('when template is set', function () { | ||
| it('should be in on the `_templates` object', function () { | ||
| strings.template('a', 'b', ['a', 'b']); | ||
| expect(strings._templates).to.have.property('a'); | ||
| expect(strings._templates['a']).to.eql({propstring: 'b', parsers: ['a', 'b']}); | ||
| expect(strings.template('a')).to.eql({propstring: 'b', parsers: ['a', 'b']}); | ||
| }); | ||
| }); | ||
| describe('when propstring and parsers are passed as properties on an object', function () { | ||
@@ -65,7 +73,6 @@ it('should return the template by name', function () { | ||
| var expected = { | ||
| propstring: ':destbase/:dirname/:basename/index:ext', | ||
| propstring: ':a/:b/:c/index:d', | ||
| parsers: ['path'] | ||
| }; | ||
| var actual = strings.template('foo'); | ||
| expect(actual).to.eql(expected); | ||
| expect(strings.template('foo')).to.eql(expected); | ||
| }); | ||
@@ -75,64 +82,5 @@ }); | ||
| it('should get a stored propstring', function () { | ||
| var expected = ':destbase/:dirname/:basename/index:ext'; | ||
| var actual = strings.propstring('pretty'); | ||
| expect(actual).to.eql(expected); | ||
| expect(actual).to.eql(':a/:b/:c/index:d'); | ||
| }); | ||
| it('when a propstring and parser object are passed in', function () { | ||
| var expected = ':destbase/:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': 'file', | ||
| ':ext': '.html' | ||
| }; | ||
| var actual = strings.transform('pretty', parser); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a propstring, parser object, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = '_gh_pages/:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| }, | ||
| ':destbase': function () { | ||
| return this.destbase; | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html', | ||
| destbase: '_gh_pages' | ||
| }; | ||
| var actual = strings.transform('pretty', parser, context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| describe('when a default value is passed in the parser', function () { | ||
| it('should be used if it\'s not on the context', function () { | ||
| var path = require('path'); | ||
| var expected = './:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| }, | ||
| ':destbase': function () { | ||
| return this.destbase || '.'; | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| strings.parser('path', parser); | ||
| var actual = strings.transform('pretty', 'path', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| }); | ||
| }); |
| Using `parsers` like this: | ||
| ```js | ||
| strings.parsers([ | ||
| 'jumbotron', | ||
| 'labels', | ||
| 'progress', | ||
| 'glyphicons', | ||
| 'badges', | ||
| 'alerts', | ||
| 'newlines' | ||
| ]); | ||
| ``` | ||
| is just sugar for: | ||
| ```js | ||
| var parsers = [ | ||
| strings.parser('jumbotron'), | ||
| strings.parser('labels'), | ||
| strings.parser('progress'), | ||
| strings.parser('glyphicons'), | ||
| strings.parser('badges'), | ||
| strings.parser('alerts'), | ||
| strings.parser('newlines'), | ||
| ]; | ||
| ``` | ||
| For an example, see [markdown-symbols](https://github.com/jonschlinkert/markdown-symbols), which uses this to store replacement patterns for custom markdown symbols. |
| /** | ||
| * Tag plugin for Verb | ||
| */ | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const file = require('fs-utils'); | ||
| const relative = require('relative'); | ||
| const _ = require('lodash'); | ||
| const comments = require('js-comments'); | ||
| /** | ||
| * Extract code comments and format for API | ||
| * documentation. | ||
| */ | ||
| module.exports = function (verb) { | ||
| verb.options = verb.options || {}; | ||
| var utils = verb.utils; | ||
| var tags = {}; | ||
| tags.extract = function (patterns, options) { | ||
| options = _.extend({}, options); | ||
| // Extend the context with options defined in the tag | ||
| _.extend(verb.context, options); | ||
| _.extend(verb.options, options); | ||
| var matches = []; | ||
| var msg; | ||
| matches = file.find(patterns, { | ||
| filter: 'isFile' | ||
| }); | ||
| // If a filename was given, but no results are returned, kindly notify the user. | ||
| if (!matches.length) { | ||
| msg = ' [nomatch] · verb could not find a match for {%%= glob("' + patterns + '") %}'; | ||
| verb.log.warn(' ' + verb.runner.name + msg); | ||
| return; | ||
| } | ||
| var output = _.map(matches, function(filepath) { | ||
| return comments(filepath, 'README.md') | ||
| }).join('\n\n'); | ||
| return utils.adjust.headings(output); | ||
| }; | ||
| return tags; | ||
| }; |
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.extend()', function() { | ||
| var strings = new Strings(); | ||
| strings.parser('a', {pattern: 'a', replacement: 'b'}); | ||
| describe('when a named parser is extended', function() { | ||
| it('should have all values', function () { | ||
| strings.extend('a', {pattern: 'c', replacement: 'd'}); | ||
| var actual = strings.parser('a'); | ||
| expect(actual[0].pattern).to.equal('a'); | ||
| expect(actual[1].pattern).to.equal('c'); | ||
| }); | ||
| }); | ||
| }); |
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.group()', function() { | ||
| var strings; | ||
| before(function () { | ||
| strings = new Strings(); | ||
| }); | ||
| it('when adding a named group, it should be in `_groups`', function () { | ||
| var name = 'a'; | ||
| var propstring = 'b'; | ||
| var parsers = ['a', 'b']; | ||
| var expected = {propstring: propstring, parsers: parsers}; | ||
| strings.group(name, propstring, parsers); | ||
| expect(strings._groups).to.have.property(name); | ||
| expect(expected).to.eql(strings._groups[name]); | ||
| }); | ||
| it('when adding a named group, it should be gotten through `group(name)`', function () { | ||
| var name = 'a'; | ||
| var propstring = 'b'; | ||
| var parsers = ['a', 'b']; | ||
| var actual = strings.group(name); | ||
| var expected = {propstring: propstring, parsers: parsers}; | ||
| strings.group(name, propstring, parsers); | ||
| expect(expected).to.eql(strings.group(name)); | ||
| }); | ||
| }); |
-78
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.run()', function () { | ||
| var strings; | ||
| before(function () { | ||
| strings = new Strings(); | ||
| strings.propstring('pretty', ':basename/index:ext'); | ||
| }); | ||
| it('when a group without a parser object is passed in', function () { | ||
| var expected = ':basename/index:ext'; | ||
| strings.group('blog', 'pretty'); | ||
| var actual = strings.run('blog'); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a group with a parser object are passed in', function () { | ||
| var expected = 'file/index.html'; | ||
| var parser = { | ||
| ':basename': 'file', | ||
| ':ext': '.html' | ||
| }; | ||
| strings.group('blog', 'pretty', parser); | ||
| var actual = strings.run('blog'); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a group with a parser object, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = 'file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| strings.group('blog', 'pretty', parser); | ||
| var actual = strings.run('blog', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a group with a named parser, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = 'file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| strings.parser('path', parser); | ||
| strings.group('blog', 'pretty', 'path'); | ||
| var actual = strings.run('blog', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| }); |
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| var path = require('path'); | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.transform()', function () { | ||
| var strings; | ||
| before(function () { | ||
| strings = new Strings(); | ||
| strings.propstring('pretty', ':destbase/:dirname/:basename/index:ext'); | ||
| strings.parser('pretty', [ | ||
| { | ||
| pattern: ':destbase', | ||
| replacement: function () { | ||
| return this.destbase; | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':dirname', | ||
| replacement: function () { | ||
| return path.dirname(this.src); | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':basename', | ||
| replacement: function () { | ||
| return path.basename(this.src, path.extname(this.src)); | ||
| }, | ||
| }, | ||
| { | ||
| pattern: ':ext', | ||
| replacement: function () { | ||
| return path.extname(this.src); | ||
| } | ||
| } | ||
| ]); | ||
| strings.template('permalinks', 'pretty', ['pretty']); | ||
| }); | ||
| it('should get a stored propstring', function () { | ||
| var expected = '_gh_pages/blog/file/index.html'; | ||
| var context = { | ||
| destbase: '_gh_pages', | ||
| src: 'blog/file.html', | ||
| }; | ||
| var actual = strings.use('permalinks', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('should get a stored propstring', function () { | ||
| var expected = ':destbase/:dirname/:basename/index:ext'; | ||
| var actual = strings.propstring('pretty'); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a propstring and parser object are passed in', function () { | ||
| var expected = ':destbase/:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': 'file', | ||
| ':ext': '.html' | ||
| }; | ||
| var actual = strings.transform('pretty', parser); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('when a propstring, parser object, and context are passed in', function () { | ||
| var path = require('path'); | ||
| var expected = '_gh_pages/:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| }, | ||
| ':destbase': function () { | ||
| return this.destbase; | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html', | ||
| destbase: '_gh_pages' | ||
| }; | ||
| var actual = strings.transform('pretty', parser, context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| describe('when a default value is passed in the parser', function () { | ||
| it('should be used if it\'s not on the context', function () { | ||
| var path = require('path'); | ||
| var expected = './:dirname/file/index.html'; | ||
| var parser = { | ||
| ':basename': function () { | ||
| return path.basename(this.filepath, path.extname(this.filepath)); | ||
| }, | ||
| ':ext': function () { | ||
| return path.extname(this.filepath); | ||
| }, | ||
| ':destbase': function () { | ||
| return this.destbase || '.'; | ||
| } | ||
| }; | ||
| var context = { | ||
| filepath: 'path/to/my/file.html' | ||
| }; | ||
| strings.parser('path', parser); | ||
| var actual = strings.transform('pretty', 'path', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| }); | ||
| }); |
-65
| /** | ||
| * Sellside <http://www.sellside.com> | ||
| * Created and maintained by Jon Schlinkert and Brian Woodward | ||
| * | ||
| * Copyright (c) 2014 Sellside. | ||
| * Licensed under the MIT License (MIT). | ||
| */ | ||
| var path = require('path'); | ||
| var expect = require('chai').expect; | ||
| var Strings = require('../'); | ||
| describe('.use()', function () { | ||
| var strings; | ||
| before(function () { | ||
| strings = new Strings(); | ||
| strings.propstring('pretty', ':destbase/:dirname/:basename/index:ext'); | ||
| strings.parser('pretty', [ | ||
| { | ||
| pattern: ':destbase', | ||
| replacement: function () { | ||
| return this.destbase; | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':dirname', | ||
| replacement: function () { | ||
| return path.dirname(this.src); | ||
| } | ||
| }, | ||
| { | ||
| pattern: ':basename', | ||
| replacement: function () { | ||
| return path.basename(this.src, path.extname(this.src)); | ||
| }, | ||
| }, | ||
| { | ||
| pattern: ':ext', | ||
| replacement: function () { | ||
| return path.extname(this.src); | ||
| } | ||
| } | ||
| ]); | ||
| strings.template('permalinks', 'pretty', ['pretty']); | ||
| }); | ||
| it('should use a stored propstring and stored parsers with the given context', function () { | ||
| var context = {destbase: 'foo', src: 'a/b.html'}; | ||
| var expected = 'foo/a/b/index.html'; | ||
| var actual = strings.use('permalinks', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| it('should use a stored propstring and stored parsers with the given context', function () { | ||
| var context = {destbase: 'bar', src: 'a/b.html'}; | ||
| var expected = 'bar/a/b/index.html'; | ||
| var actual = strings.use('permalinks', context); | ||
| expect(actual).to.eql(expected); | ||
| }); | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
53528
0.98%2
-33.33%9
50%26
-3.7%1227
-0.16%341
-7.59%