Skip to content

Commit

Permalink
feat: in parts expose substitutions values with meta data
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
parts.substitutions instead of array of
substitution values now exposes array of
meta data where substitutionMeta.value
 exposes substitution value, and substitutionMeta.placeholder exposes
placeholder meta data
  • Loading branch information
medikoo committed Oct 2, 2018
1 parent 299ffa3 commit c06a929
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 27 deletions.
15 changes: 11 additions & 4 deletions README.md
Expand Up @@ -88,9 +88,9 @@ format = require("sprintf-kit")({
});
```

#### Resolver generator
#### Parts resolver generator

Resolver returns resolved data in form of tokens, which maybe helpful if additional programmatical processing is needed
Resolver returns resolved data in form of object parts, which maybe helpful if additional programmatical processing is needed

```javascript
// Configure format function that resolves 's' and 'd' modifiers
Expand All @@ -102,7 +102,11 @@ let resolve = require("sprintf-kit/get-resolver")({
resolve("Some %s with %d count %x boo", "foo", 12, "ignored");
// {
// literals: ["Some ", " with ", " count ", " boo"],
// substitutions: ["foo", "12", "%x"],
// substitutions: [
// { value: "foo", placeholder: { type: "s", content: "%s" } },
// { value: "12", placeholder: { type: "d", content: "%d" } },
// { value: "%x", placeholder: { type: "x", content: "%x" }
// ],
// rest: null
// }

Expand All @@ -115,7 +119,10 @@ resolve = require("sprintf-kit/get-resolver")({
resolve("Some %s with %d count", "foo", 12, "rest", "args");
// {
// literals: ["Some ", " with ", " count"],
// substitutions: ["foo", "12"],
// substitutions: [
// { value: "foo", placeholder: { type: "s", content: "%s" } },
// { value: "12", placeholder: { type: "d", content: "%d" } }
// ],
// rest: " rest args"
// }
```
Expand Down
2 changes: 1 addition & 1 deletion format-parts.js
Expand Up @@ -12,7 +12,7 @@ module.exports = function (parts) {
var substitutions = ensureArray(parts.substitutions);
var resolvedString = literals.length
? literals.reduce(function (resolved, literal, index) {
return resolved + substitutions[index - 1] + literal;
return resolved + substitutions[index - 1].value + literal;
})
: "";
if (isValue(parts.rest)) resolvedString += ensureString(parts.rest);
Expand Down
17 changes: 13 additions & 4 deletions get-parts-resolver.js
Expand Up @@ -34,13 +34,22 @@ var resolveResultWithPlaceholders = function (modifiers, data, args, result) {
var parameter = index + 1;
if (placeholder.width === "*") ++extraPlaceholderArgsLength;
if (placeholder.precision === "*") ++extraPlaceholderArgsLength;
if (!isParameterIndexingValid) return "[invalid placeholder parameters]";
if (!modifiers[placeholder.type]) return placeholder.content;
if (!isParameterIndexingValid) {
return { value: "[invalid placeholder parameters]", placeholder: placeholder };
}
if (!modifiers[placeholder.type]) {
return { value: placeholder.content, placeholder: placeholder };
}
if (placeholder.parameter) parameter = placeholder.parameter;
if (parameter > args.length) return placeholder.content;
if (parameter > args.length) {
return { value: placeholder.content, placeholder: placeholder };
}
var placeholderIndex = parameter + extraPlaceholderArgsLength - 1;
var arg = args[placeholderIndex];
return modifiers[placeholder.type](arg, placeholder, placeholderIndex, args);
return {
value: modifiers[placeholder.type](arg, placeholder, placeholderIndex, args),
placeholder: placeholder
};
});
result.rest = resolveRest(
modifiers.rest, data, args, data.placeholders.length + extraPlaceholderArgsLength
Expand Down
14 changes: 11 additions & 3 deletions test/format-parts.js
Expand Up @@ -7,13 +7,17 @@ test("formatParts", function (t) {
t.test("Should resolve", function (t) {
t.equal(formatParts({ literals: ["foo raz"], substitutions: [], rest: null }), "foo raz");
t.equal(
formatParts({ literals: ["foo ", ""], substitutions: ["marko"], rest: null }),
formatParts({
literals: ["foo ", ""],
substitutions: [{ value: "marko" }],
rest: null
}),
"foo marko", "Single placeholder"
);
t.equal(
formatParts({
literals: ["foo ", " ", ""],
substitutions: ["marko", "12"],
substitutions: [{ value: "marko" }, { value: "12" }],
rest: null
}),
"foo marko 12", "Two placeholders"
Expand All @@ -24,7 +28,11 @@ test("formatParts", function (t) {
);

t.equal(
formatParts({ literals: ["foo ", ""], substitutions: ["marko"], rest: " 12-elo" }),
formatParts({
literals: ["foo ", ""],
substitutions: [{ value: "marko" }],
rest: " 12-elo"
}),
"foo marko 12-elo", "with rest handling"
);
t.equal(
Expand Down
38 changes: 23 additions & 15 deletions test/get-parts-resolver.js
Expand Up @@ -5,48 +5,55 @@ var test = require("tape")
, modifierS = require("../modifiers/s")
, getResolver = require("../get-parts-resolver");

var normalizeParts = function (parts) {
parts.substitutions = parts.substitutions.map(function (substitution) {
return substitution.value;
});
return parts;
};

test("getPartsResolver", function (t) {
t.test("Should resolve", function (t) {
// eslint-disable-next-line id-length
var resolve = getResolver({ d: modifierD, s: modifierS });
t.deepEqual(
resolve("foo raz", "marko"), { literals: ["foo raz"], substitutions: [], rest: null },
"No placeholders"
normalizeParts(normalizeParts(resolve("foo raz", "marko"))),
{ literals: ["foo raz"], substitutions: [], rest: null }, "No placeholders"
);
t.deepEqual(
resolve("foo %s", "marko"),
normalizeParts(resolve("foo %s", "marko")),
{ literals: ["foo ", ""], substitutions: ["marko"], rest: null }, "Single placeholder"
);
t.deepEqual(
resolve("foo %s %d", "marko", 12),
normalizeParts(resolve("foo %s %d", "marko", 12)),
{ literals: ["foo ", " ", ""], substitutions: ["marko", "12"], rest: null },
"Two placeholders"
);
t.deepEqual(
resolve("foo %s %d", "marko", 12, "elo"),
normalizeParts(resolve("foo %s %d", "marko", 12, "elo")),
{ literals: ["foo ", " ", ""], substitutions: ["marko", "12"], rest: null },
"Two placeholders with arguments overflow and no rest handling defined"
);
t.deepEqual(
resolve("foo %s %d", "marko"),
normalizeParts(resolve("foo %s %d", "marko")),
{ literals: ["foo ", " ", ""], substitutions: ["marko", "%d"], rest: null },
"foo marko %d", "Two placeholders with argument missing"
);
t.deepEqual(
resolve("foo %2$s %1$d", 12, "bar"),
normalizeParts(resolve("foo %2$s %1$d", 12, "bar")),
{ literals: ["foo ", " ", ""], substitutions: ["bar", "12"], rest: null },
"Parameters swap"
);
t.deepEqual(
resolve("foo %*d", 10, 12),
normalizeParts(resolve("foo %*d", 10, 12)),
{ literals: ["foo ", ""], substitutions: ["12"], rest: null }, "Dynamic width"
);
t.deepEqual(
resolve("foo %.*d", 10, 12),
normalizeParts(resolve("foo %.*d", 10, 12)),
{ literals: ["foo ", ""], substitutions: ["12"], rest: null }, "Dynamic precision"
);
t.deepEqual(
resolve("foo %2$s %2$d", 12, "bar"),
normalizeParts(resolve("foo %2$s %2$d", 12, "bar")),
{
literals: ["foo ", " ", ""],
substitutions: [
Expand All @@ -58,7 +65,7 @@ test("getPartsResolver", function (t) {
"Invalid parameters setup"
);
t.deepEqual(
resolve(12, 13), { literals: [], substitutions: [], rest: null },
normalizeParts(resolve(12, 13)), { literals: [], substitutions: [], rest: null },
"Non-string first argument without rest"
);

Expand All @@ -70,21 +77,22 @@ test("getPartsResolver", function (t) {
});

t.deepEqual(
resolve("foo %s", "marko", 12, "elo"),
normalizeParts(resolve("foo %s", "marko", 12, "elo")),
{ literals: ["foo ", ""], substitutions: ["marko"], rest: " 12-elo" },
"Arguments overflow with rest handling"
);
t.deepEqual(
resolve("foo %*s", 10, "marko", 12, "elo"),
normalizeParts(resolve("foo %*s", 10, "marko", 12, "elo")),
{ literals: ["foo ", ""], substitutions: ["marko"], rest: " 12-elo" },
"Arguments overflow with rest handling and width shift"
);
t.deepEqual(
resolve("foo %x", "elo"), { literals: ["foo ", ""], substitutions: ["%x"], rest: null },
normalizeParts(resolve("foo %x", "elo")),
{ literals: ["foo ", ""], substitutions: ["%x"], rest: null },
"Placeholder content on unknown type"
);
t.deepEqual(
resolve(12, 13), { literals: [], substitutions: [], rest: "12-13" },
normalizeParts(resolve(12, 13)), { literals: [], substitutions: [], rest: "12-13" },
"Non-string first argument with rest"
);
t.end();
Expand Down

0 comments on commit c06a929

Please sign in to comment.