-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathindex.js
50 lines (38 loc) · 1.5 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import {htmlEscape} from 'escape-goat';
export class MissingValueError extends Error {
constructor(key) {
super(`Missing a value for ${key ? `the placeholder: ${key}` : 'a placeholder'}`, key);
this.name = 'MissingValueError';
this.key = key;
}
}
export default function pupa(template, data, {ignoreMissing = false, transform = ({value}) => value} = {}) {
if (typeof template !== 'string') {
throw new TypeError(`Expected a \`string\` in the first argument, got \`${typeof template}\``);
}
if (typeof data !== 'object') {
throw new TypeError(`Expected an \`object\` or \`Array\` in the second argument, got \`${typeof data}\``);
}
const replace = (placeholder, key) => {
let value = data;
for (const property of key.split('.')) {
value = value ? value[property] : undefined;
}
const transformedValue = transform({value, key});
if (transformedValue === undefined) {
if (ignoreMissing) {
return placeholder;
}
throw new MissingValueError(key);
}
return String(transformedValue);
};
const composeHtmlEscape = replacer => (...args) => htmlEscape(replacer(...args));
// The regex tries to match either a number inside `{{ }}` or a valid JS identifier or key path.
const doubleBraceRegex = /{{(\d+|[a-z$_][\w\-$]*?(?:\.[\w\-$]*?)*?)}}/gi;
if (doubleBraceRegex.test(template)) {
template = template.replace(doubleBraceRegex, composeHtmlEscape(replace));
}
const braceRegex = /{(\d+|[a-z$_][\w\-$]*?(?:\.[\w\-$]*?)*?)}/gi;
return template.replace(braceRegex, replace);
}