Skip to content

Commit

Permalink
Add support for default values
Browse files Browse the repository at this point in the history
PR-URL: #72
  • Loading branch information
Pavel authored and tshemsedinov committed Nov 7, 2023
1 parent 28989e0 commit af59e49
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 24 deletions.
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
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@
"eslint-plugin-prettier": "^5.0.0",
"prettier": "^3.0.3",
"typescript": "^5.0.4"
},
"dependencies": {
"metautil": "^3.15.0"
}
}
107 changes: 89 additions & 18 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,93 @@ 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: ['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: ['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: ['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',
);
}

{
({ description: 'No fallbacks used, but values not passed either' });

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

assert.strictEqual(result, expect);
}
36 changes: 30 additions & 6 deletions tickplate.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
'use strict';

const tickplate =
(strings, ...keys) =>
(values) => {
const metautil = require('metautil');

const SEPARATOR = '=';

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();
const parsed = metautil.jsonParse(rhsRestored);
return { key, value: parsed };
};

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;

0 comments on commit af59e49

Please sign in to comment.