Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support default values #72

Closed
wants to merge 11 commits into from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
*.log
.DS_Store
.vscode
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased][unreleased]

- Support default values

## [1.0.7][] - 2023-04-29

- Drop node.js 14 support, add node.js 20
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ const templ = t`${'hello'} ${'myFriend'}, great ${'positions'} of Rome`;
console.log(templ(data));
```

With default values provided (optionally):

```js
const t = require('tickplate');

const data = {
greeting: 'Valē!',
person: {
name: 'Lucius Aurelius Verus',
toString() {
return this.name;
},
},
positions: ['brother', 'emperor', 'co-emperor'],
ruleFrom: 161,
ruleTo: 169,
};

const templ = t`${'greeting='} ${'person="Marcus Aurelius"'}, great ${'positions=["emperor", "philosopher"]'} of Rome from ${'ruleFrom=161'} to ${'ruleTo=180'} AD`;

console.log(templ(data));
```

## License & Contributors

Copyright (c) 2017-2023 [Metarhia contributors](https://github.com/metarhia/tickplate/graphs/contributors).
Expand Down
97 changes: 79 additions & 18 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,83 @@ const assert = require('node:assert').strict;

const t = require('./tickplate.js');

const data = {
hello: 'Ave!',
myFriend: {
name: 'Marcus Aurelius',
toString() {
return this.name;
{
({ description: 'No fallbacks used.' });

const data = {
hello: 'Ave!',
myFriend: {
name: 'Marcus Aurelius',
toString() {
return this.name;
},
},
},
positions: ['imperor', 'philosopher', 'writer'],
};

const templ = t`${'hello'} ${'myFriend'}, great ${'positions'} of Rome`;

const expect = 'Ave! Marcus Aurelius, great imperor,philosopher,writer of Rome';
const result = templ(data);
assert.strictEqual(result, expect);
assert.strictEqual(templ({ myFriend: 'Hadrian' }), ' Hadrian, great of Rome');
assert.strictEqual(templ({ hello: 'Hi!' }), 'Hi! , great of Rome');
assert.strictEqual(templ({}), ' , great of Rome');
positions: ['emperor', 'philosopher', 'writer'],
};

const templ = t`${'hello'} ${'myFriend'}, great ${'positions'} of Rome`;

const expect =
'Ave! Marcus Aurelius, great emperor,philosopher,writer of Rome';
const result = templ(data);
assert.strictEqual(result, expect);
assert.strictEqual(
templ({ myFriend: 'Hadrian' }),
' Hadrian, great of Rome',
);
assert.strictEqual(templ({ hello: 'Hi!' }), 'Hi! , great of Rome');
assert.strictEqual(templ({}), ' , great of Rome');
}

{
({
description:
'Fallback primitives and arrays of primitives provided, with "=" separator, empty spaces around trimmed',
});

const data = {
greeting: 'Ave!',
person: {
name: 'Lucius Verus',
toString() {
return this.name;
},
},
positions: ['brother', 'emperor', 'co-emperor'],
ruleFrom: 161,
ruleTo: 169,
};

const templ = t`${'greeting='} ${'person = "Marcus Aurelius"'}, great ${'positions =["emperor", "philosopher"]'} of Rome from ${'ruleFrom = 161'} to ${'ruleTo=180'} AD`;

const expect =
'Ave! Lucius Verus, great brother,emperor,co-emperor of Rome from 161 to 169 AD';
const result = templ(data);
assert.strictEqual(result, expect);
assert.strictEqual(
templ({}),
' Marcus Aurelius, great emperor,philosopher of Rome from 161 to 180 AD',
);
assert.strictEqual(
templ({ greeting: 'Valē!!!', ruleFrom: '44 BC', ruleTo: 2023 }),
'Valē!!! Marcus Aurelius, great emperor,philosopher of Rome from 44 BC to 2023 AD',
);

const messedUp = t`${'greeting= /\\/'} ${'person = " "'}, great ${'positions ="emperor", "philosopher"]]'} of Rome from ${'ruleFrom = undefined'} to ${'ruleTo==180'} AD`;
assert.strictEqual(messedUp(data), expect);
assert.strictEqual(messedUp({}), ' , great of Rome from to AD');
assert.strictEqual(
messedUp({ greeting: 'No way!' }),
'No way! , great of Rome from to AD',
);
assert.strictEqual(
messedUp({
greeting: 'Papa Roma is',
person: 'a',
positions: 'pizzeria',
ruleFrom: 1970,
ruleTo: 'today',
}),
'Papa Roma is a, great pizzeria of Rome from 1970 to today AD',
);
}
38 changes: 32 additions & 6 deletions tickplate.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
'use strict';

const tickplate =
(strings, ...keys) =>
(values) => {
const SEPARATOR = '=';
tshemsedinov marked this conversation as resolved.
Show resolved Hide resolved

const parseKeyValuePair = (value, sep = SEPARATOR) => {
const [lhs, ...rhs] = value.split(sep);
const key = lhs.trim();
if (rhs.length === 0) return { key };
const rhsRestored = rhs.join(sep).trim();
try {
const value = JSON.parse(rhsRestored);
return { key, value };
} catch {
return { key };
}
tshemsedinov marked this conversation as resolved.
Show resolved Hide resolved
};

const parseKeys = (strKeyValuePairs, sep = SEPARATOR) => {
const defaults = {};
for (const pair of strKeyValuePairs) {
const { key, value } = parseKeyValuePair(pair, sep);
defaults[key] = value;
}
return { keys: Object.keys(defaults), defaults };
};

const tickplate = (strings, ...keys) => {
const { keys: tickplateKeys, defaults } = parseKeys(keys);
return (values) => {
const tickplateValues = { ...defaults, ...values };
const result = [strings[0]];
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
result.push(values[key], strings[i + 1]);
for (let i = 0; i < tickplateKeys.length; i++) {
const key = tickplateKeys[i];
result.push(tickplateValues[key], strings[i + 1]);
}
return result.join('');
};
};

module.exports = tickplate;