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
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 = '=';
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();
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;
Loading