sprintf-kit
Advanced tools
Comparing version 1.3.0 to 1.4.0
@@ -5,2 +5,12 @@ # Change Log | ||
<a name="1.4.0"></a> | ||
# [1.4.0](https://github.com/medikoo/sprintf-kit/compare/v1.3.0...v1.4.0) (2018-08-03) | ||
### Features | ||
* support literal decorator ([305278c](https://github.com/medikoo/sprintf-kit/commit/305278c)) | ||
<a name="1.3.0"></a> | ||
@@ -7,0 +17,0 @@ # [1.3.0](https://github.com/medikoo/sprintf-kit/compare/v1.2.1...v1.3.0) (2018-06-05) |
93
index.js
"use strict"; | ||
var aFrom = require("es5-ext/array/from") | ||
, identity = require("es5-ext/function/identity") | ||
, ensureObject = require("es5-ext/object/valid-object") | ||
, objForEach = require("es5-ext/object/for-each") | ||
, ensurePlainFunction = require("es5-ext/object/ensure-plain-function") | ||
, primitiveSet = require("es5-ext/object/primitive-set") | ||
, typeChars = require("./lib/type-chars") | ||
@@ -12,5 +14,7 @@ , parse = require("./parse"); | ||
module.exports = function (modifiers) { | ||
var customTypes = primitiveSet("literal", "rest"); | ||
var validateModifiers = function (modifiers) { | ||
objForEach(ensureObject(modifiers), function (value, type) { | ||
if (!hasOwnProperty.call(typeChars, type) && type !== "rest") { | ||
if (!hasOwnProperty.call(typeChars, type) && !customTypes[type]) { | ||
throw new TypeError("Invalid modifier type: " + type); | ||
@@ -20,3 +24,51 @@ } | ||
}); | ||
}; | ||
var resolveRest = function (modifier, data, args, placeholderArgsLength) { | ||
if (!modifier || args.length <= placeholderArgsLength) return ""; | ||
return modifier(args.slice(placeholderArgsLength), data); | ||
}; | ||
var resolveStringWithPlaceholders = function (modifiers, data, args) { | ||
var extraPlaceholderArgsLength = 0; | ||
var isParameterIndexingValid = data.isParameterIndexingValid; | ||
var resolvedString = data.literals.reduce(function (result, literal, index) { | ||
if (index === 1 && modifiers.literal) result = modifiers.literal(result, args); | ||
var placeholder = data.placeholders[index - 1]; | ||
var resolvedPlaceholder; | ||
if (placeholder.width === "*") ++extraPlaceholderArgsLength; | ||
if (placeholder.precision === "*") ++extraPlaceholderArgsLength; | ||
if (!isParameterIndexingValid) { | ||
resolvedPlaceholder = "[invalid placeholder parameters]"; | ||
} else if (modifiers[placeholder.type]) { | ||
if (placeholder.parameter) index = placeholder.parameter; | ||
if (index > args.length) { | ||
resolvedPlaceholder = placeholder.content; | ||
} else { | ||
index += extraPlaceholderArgsLength - 1; | ||
var arg = args[index]; | ||
resolvedPlaceholder = modifiers[placeholder.type](arg, placeholder, index, args); | ||
} | ||
} else { | ||
resolvedPlaceholder = placeholder.content; | ||
} | ||
return result + resolvedPlaceholder + (modifiers.literal || identity)(literal, args); | ||
}); | ||
return ( | ||
resolvedString + | ||
resolveRest( | ||
modifiers.rest, data, args, data.placeholders.length + extraPlaceholderArgsLength | ||
) | ||
); | ||
}; | ||
var resolveStringWithoutPlaceholders = function (modifiers, data, args) { | ||
var resolvedString = data.literals[0]; | ||
if (modifiers.literal) resolvedString = modifiers.literal(resolvedString); | ||
return resolvedString + resolveRest(modifiers.rest, data, args, data.placeholders.length); | ||
}; | ||
module.exports = function (modifiers) { | ||
validateModifiers(modifiers); | ||
return function (format/*, ...params*/) { | ||
@@ -27,38 +79,7 @@ if (typeof format !== "string") { | ||
var data = parse(format); | ||
var placeholders = data.placeholders; | ||
var isParameterIndexingValid = data.isParameterIndexingValid; | ||
var args = slice.call(arguments, 1); | ||
var args = slice.call(arguments, 1); | ||
var skippedArgsLength = 0; | ||
var resolvedString = data.literals.reduce(function (result, literal, index) { | ||
var placeholder = placeholders[index - 1]; | ||
var resolvedPlaceholder; | ||
if (placeholder.width === "*") ++skippedArgsLength; | ||
if (placeholder.precision === "*") ++skippedArgsLength; | ||
if (!isParameterIndexingValid) { | ||
resolvedPlaceholder = "[invalid placeholder parameters]"; | ||
} else if (modifiers[placeholder.type]) { | ||
if (placeholder.parameter) index = placeholder.parameter; | ||
if (index > args.length) { | ||
resolvedPlaceholder = placeholder.content; | ||
} else { | ||
index += skippedArgsLength - 1; | ||
var arg = args[index]; | ||
resolvedPlaceholder = modifiers[placeholder.type]( | ||
arg, placeholder, index, args | ||
); | ||
} | ||
} else { | ||
resolvedPlaceholder = placeholder.content; | ||
} | ||
return result + resolvedPlaceholder + literal; | ||
}); | ||
if (!modifiers.rest || args.length <= placeholders.length + skippedArgsLength) { | ||
return resolvedString; | ||
} | ||
return ( | ||
resolvedString + | ||
modifiers.rest(args.slice(placeholders.length + skippedArgsLength), data) | ||
); | ||
if (data.literals.length > 1) return resolveStringWithPlaceholders(modifiers, data, args); | ||
return resolveStringWithoutPlaceholders(modifiers, data, args); | ||
}; | ||
}; |
{ | ||
"name": "sprintf-kit", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "sprintf parser and basic formatter", | ||
@@ -18,10 +18,10 @@ "author": "Mariusz Nowak <medyk@medikoo.com> (http://www.medikoo.com/)", | ||
"dependencies": { | ||
"es5-ext": "^0.10.44" | ||
"es5-ext": "^0.10.45" | ||
}, | ||
"devDependencies": { | ||
"browserstack-tape-runner": "2", | ||
"eslint": "^4.19.1", | ||
"eslint-config-medikoo-es5": "^1.4.11", | ||
"eslint": "^5.2", | ||
"eslint-config-medikoo-es5": "^1.5", | ||
"istanbul": "^0.4.5", | ||
"tape": "^4.9", | ||
"tape": "^4.9.1", | ||
"tape-index": "2" | ||
@@ -28,0 +28,0 @@ }, |
@@ -11,5 +11,5 @@ [![*nix build status][nix-build-image]][nix-build-url] | ||
* Full [printf format parser](#parser) | ||
* Basic (ECMAScript level) modifier [resolvers](#preconfigured-modifiers) | ||
* Format function [generator](#format-function-generator). | ||
- Full [printf format parser](#parser) | ||
- Basic (ECMAScript level) modifier [resolvers](#preconfigured-modifiers) | ||
- Format function [generator](#format-function-generator). | ||
@@ -46,13 +46,13 @@ ### Installation | ||
* `literals` - Surrounding string literals | ||
* `placeholders` - Meta data of parsed placholders. | ||
- `literals` - Surrounding string literals | ||
- `placeholders` - Meta data of parsed placholders. | ||
Placeholder properties map (refer to [spec](https://en.wikipedia.org/wiki/Printf_format_string) for explanation of each property) | ||
* `parameter` - (optional) parameter setting (e.g. `1`) | ||
* `flags` - (optional) array of flags (e.g. `["0", "-"]`) | ||
* `width` - (optional) width (e.g. `4` or `"*"` if dynamic) | ||
* `precision` - (optional) precision (e.g. `4` or `"*"` if dynamic) | ||
* `length` - (optional) length (e.g. `"z"`) | ||
* `type` - Modifier type (e.g. `"s"` or `"d"`) | ||
* `content` - Full string representation of placeholder (e.g. `"%s"`) | ||
* `isParameterIndexingValid` - Whether parameter indexing is valid across all placeholders. | ||
- `parameter` - (optional) parameter setting (e.g. `1`) | ||
- `flags` - (optional) array of flags (e.g. `["0", "-"]`) | ||
- `width` - (optional) width (e.g. `4` or `"*"` if dynamic) | ||
- `precision` - (optional) precision (e.g. `4` or `"*"` if dynamic) | ||
- `length` - (optional) length (e.g. `"z"`) | ||
- `type` - Modifier type (e.g. `"s"` or `"d"`) | ||
- `content` - Full string representation of placeholder (e.g. `"%s"`) | ||
- `isParameterIndexingValid` - Whether parameter indexing is valid across all placeholders. | ||
e.g. if no placeholders come with parameters it'll be true. If some but not all of them will come with parameters, it'll be false (if used, then all placeholders should use them). | ||
@@ -80,2 +80,13 @@ | ||
format("Some %s with %d count", "foo", 12, "rest", "args"); // Some foo with 12 count rest args | ||
// Message string literals (all but placeholders text) can be additionally decorated | ||
// Useful when we want to apply some specific color to message without affecting format of special arguments | ||
const clc = require("cli-color"); | ||
format = require("sprintf-kit")({ | ||
d: require("sprintf-kit/modifiers/d"), | ||
s: require("sprintf-kit/modifiers/s"), | ||
literal: literal => clc.red(literal) | ||
}); | ||
``` | ||
@@ -91,7 +102,7 @@ | ||
* `d` - Number | ||
* `f` - Floating point value | ||
* `i` - Integer | ||
* `j` - JSON | ||
* `s` - String | ||
- `d` - Number | ||
- `f` - Floating point value | ||
- `i` - Integer | ||
- `j` - JSON | ||
- `s` - String | ||
@@ -98,0 +109,0 @@ Every modifier is exception safe, in case of approaching invalid value, adequate error message token is displayed in place of placeholder |
@@ -12,2 +12,3 @@ "use strict"; | ||
var resolve = getResolver({ d: modifierD, s: modifierS }); | ||
t.equal(resolve("foo raz", "marko"), "foo raz", "No placeholders"); | ||
t.equal(resolve("foo %s", "marko"), "foo marko", "Single placeholder"); | ||
@@ -51,2 +52,6 @@ t.equal(resolve("foo %s %d", "marko", 12), "foo marko 12", "Two placeholders"); | ||
}); | ||
var resolve = getResolver({ d: modifierD, literal: function (str) { return str + "foo"; } }); | ||
t.equal(resolve("mar %d ko", 12), "mar foo12 kofoo", "Support 'literal' modifier"); | ||
t.equal(resolve("marlo"), "marlofoo", "Support 'literal' modifier with no placeholder"); | ||
t.throws( | ||
@@ -53,0 +58,0 @@ function () { getResolver({ foo: modifierD }); }, TypeError, "Reject invalid modifiers map" |
29606
724
126
Updatedes5-ext@^0.10.45