@bedrockio/templates 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/TemplateRenderer.js +6 -9
- package/dist/cjs/helpers.js +45 -8
- package/dist/cjs/utils.js +19 -3
- package/dist/esm/TemplateRenderer.js +7 -10
- package/dist/esm/helpers.js +45 -8
- package/dist/esm/utils.js +18 -3
- package/package.json +2 -2
- package/types/TemplateRenderer.d.ts.map +1 -1
- package/types/helpers.d.ts +2 -2
- package/types/helpers.d.ts.map +1 -1
- package/types/utils.d.ts +1 -0
- package/types/utils.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -20,12 +20,6 @@ class TemplateRenderer {
|
|
|
20
20
|
}
|
|
21
21
|
run(options) {
|
|
22
22
|
const { template, params, helpers, ...rest } = this.resolveOptions(options);
|
|
23
|
-
if (!template) {
|
|
24
|
-
return {
|
|
25
|
-
body: '',
|
|
26
|
-
sections: [],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
23
|
const compiled = this.loadTemplate(template, rest);
|
|
30
24
|
return compiled(params, {
|
|
31
25
|
helpers: (0, helpers_1.resolveHelpers)(helpers, rest),
|
|
@@ -35,7 +29,7 @@ class TemplateRenderer {
|
|
|
35
29
|
// Private
|
|
36
30
|
/** @returns {Object} */
|
|
37
31
|
resolveOptions(options = {}) {
|
|
38
|
-
|
|
32
|
+
const resolved = {
|
|
39
33
|
...this.options,
|
|
40
34
|
...options,
|
|
41
35
|
params: {
|
|
@@ -43,12 +37,15 @@ class TemplateRenderer {
|
|
|
43
37
|
...options.params,
|
|
44
38
|
},
|
|
45
39
|
};
|
|
40
|
+
resolved.template ||= resolved.body;
|
|
41
|
+
return resolved;
|
|
46
42
|
}
|
|
47
|
-
loadTemplate = (0, lodash_memoize_1.default)((input, options) => {
|
|
43
|
+
loadTemplate = (0, lodash_memoize_1.default)((input = '', options) => {
|
|
48
44
|
const source = (0, utils_1.resolveTemplateSource)(input, options);
|
|
49
45
|
const template = handlebars_1.default.compile(source.trim());
|
|
50
46
|
return (params, options) => {
|
|
51
|
-
|
|
47
|
+
let output = template(params, options);
|
|
48
|
+
output = (0, utils_1.unescapeHtml)(output);
|
|
52
49
|
const { body, meta } = (0, utils_1.runFrontMatter)(output);
|
|
53
50
|
const sections = (0, utils_1.getSections)(body);
|
|
54
51
|
return {
|
package/dist/cjs/helpers.js
CHANGED
|
@@ -95,15 +95,14 @@ exports.DEFAULT_HELPERS = {
|
|
|
95
95
|
}
|
|
96
96
|
return index + 1;
|
|
97
97
|
},
|
|
98
|
-
link(
|
|
98
|
+
link(text, url) {
|
|
99
99
|
return new handlebars_1.default.SafeString(`[${text}](${url})`);
|
|
100
100
|
},
|
|
101
|
-
button(
|
|
101
|
+
button(text, url) {
|
|
102
102
|
return generateHtml('a', {
|
|
103
103
|
text,
|
|
104
104
|
href: url,
|
|
105
105
|
class: 'button',
|
|
106
|
-
target: '_blank',
|
|
107
106
|
});
|
|
108
107
|
},
|
|
109
108
|
list(arr) {
|
|
@@ -124,7 +123,8 @@ function resolveHelpers(helpers, options) {
|
|
|
124
123
|
function resolveHelper(arg, options) {
|
|
125
124
|
const { names, handler } = resolveArgumentNames(arg);
|
|
126
125
|
return (...args) => {
|
|
127
|
-
|
|
126
|
+
const result = handler(...resolveHelperArgs(args, names, options));
|
|
127
|
+
return generateHtml(result);
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
// Arguments
|
|
@@ -162,7 +162,12 @@ function resolveHelperArgs(args, names, options) {
|
|
|
162
162
|
params[name] = value;
|
|
163
163
|
});
|
|
164
164
|
const resolved = names.map((name) => {
|
|
165
|
-
|
|
165
|
+
if (name === 'params') {
|
|
166
|
+
return meta.hash;
|
|
167
|
+
}
|
|
168
|
+
let value = params[name];
|
|
169
|
+
value = normalizeParam(name, value, params, options);
|
|
170
|
+
return value;
|
|
166
171
|
});
|
|
167
172
|
options = {
|
|
168
173
|
options,
|
|
@@ -170,7 +175,34 @@ function resolveHelperArgs(args, names, options) {
|
|
|
170
175
|
};
|
|
171
176
|
return [...resolved, options];
|
|
172
177
|
}
|
|
173
|
-
|
|
178
|
+
// Param normalization
|
|
179
|
+
function normalizeParam(name, value, params, options) {
|
|
180
|
+
if (name === 'url' || name === 'href') {
|
|
181
|
+
value = normalizeUrl(value, params, options);
|
|
182
|
+
}
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
const PARAM_REG = /:([a-z]+)/gi;
|
|
186
|
+
function normalizeUrl(str, params, options) {
|
|
187
|
+
const { baseUrl } = options;
|
|
188
|
+
if (baseUrl && str.startsWith('/')) {
|
|
189
|
+
str = baseUrl + str;
|
|
190
|
+
}
|
|
191
|
+
str = str.replace(PARAM_REG, (_, key) => {
|
|
192
|
+
const value = params[key];
|
|
193
|
+
// Need to delete the injected params or they
|
|
194
|
+
// will be passed on to the HTML element.
|
|
195
|
+
delete params[key];
|
|
196
|
+
return value;
|
|
197
|
+
});
|
|
198
|
+
return str;
|
|
199
|
+
}
|
|
200
|
+
function generateHtml(...args) {
|
|
201
|
+
const arg = args.length > 1 ? args : args[0];
|
|
202
|
+
if (!Array.isArray(arg)) {
|
|
203
|
+
return arg || '';
|
|
204
|
+
}
|
|
205
|
+
const [tag, props] = arg;
|
|
174
206
|
const { text, ...rest } = props;
|
|
175
207
|
const attr = Object.entries(rest)
|
|
176
208
|
.map((entry) => {
|
|
@@ -181,9 +213,14 @@ function generateHtml(tag, props) {
|
|
|
181
213
|
})
|
|
182
214
|
.filter((a) => a)
|
|
183
215
|
.join(' ');
|
|
184
|
-
let html = `<${tag} ${attr}
|
|
216
|
+
let html = `<${tag} ${attr}`;
|
|
185
217
|
if (text) {
|
|
186
|
-
html +=
|
|
218
|
+
html += '>';
|
|
219
|
+
html += generateHtml(text);
|
|
220
|
+
html += `</${tag}>`;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
html += ` />`;
|
|
187
224
|
}
|
|
188
225
|
return new handlebars_1.default.SafeString(html);
|
|
189
226
|
}
|
package/dist/cjs/utils.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.resolveTemplateSource = resolveTemplateSource;
|
|
7
7
|
exports.runFrontMatter = runFrontMatter;
|
|
8
8
|
exports.getSections = getSections;
|
|
9
|
+
exports.unescapeHtml = unescapeHtml;
|
|
9
10
|
const fs_1 = require("fs");
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
11
12
|
const front_matter_1 = __importDefault(require("front-matter"));
|
|
@@ -26,9 +27,9 @@ function runFrontMatter(str) {
|
|
|
26
27
|
body: body.trim(),
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
|
-
function tryReadFile(filepath
|
|
30
|
+
function tryReadFile(filepath) {
|
|
30
31
|
try {
|
|
31
|
-
return (0, fs_1.readFileSync)(filepath
|
|
32
|
+
return (0, fs_1.readFileSync)(filepath, 'utf-8');
|
|
32
33
|
}
|
|
33
34
|
catch (error) {
|
|
34
35
|
if (error.code !== 'ENOENT') {
|
|
@@ -37,7 +38,12 @@ function tryReadFile(filepath, ext) {
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
function readSource(filepath) {
|
|
40
|
-
|
|
41
|
+
if (path_1.default.extname(filepath)) {
|
|
42
|
+
return tryReadFile(filepath);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return tryReadFile(filepath + '.md') || tryReadFile(filepath + '.txt');
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
// Sections
|
|
43
49
|
const SECTIONS_REG = /^=== (\w+) ===\n\n/gm;
|
|
@@ -60,3 +66,13 @@ function getSections(str) {
|
|
|
60
66
|
}
|
|
61
67
|
return sections;
|
|
62
68
|
}
|
|
69
|
+
// Whitespace
|
|
70
|
+
// Handlebars doesn't allow a way to selectively
|
|
71
|
+
// escape so instead unescape some basic tokens.
|
|
72
|
+
function unescapeHtml(html) {
|
|
73
|
+
html = html.replace(/'/g, "'");
|
|
74
|
+
html = html.replace(/"/g, '"');
|
|
75
|
+
html = html.replace(/'/g, "'");
|
|
76
|
+
html = html.replace(/=/g, '=');
|
|
77
|
+
return html;
|
|
78
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Handlebars from 'handlebars';
|
|
2
2
|
import memoize from 'lodash.memoize';
|
|
3
3
|
import { DEFAULT_HELPERS, resolveHelpers } from './helpers.js';
|
|
4
|
-
import { getSections, resolveTemplateSource, runFrontMatter } from './utils.js';
|
|
4
|
+
import { getSections, resolveTemplateSource, runFrontMatter, unescapeHtml, } from './utils.js';
|
|
5
5
|
export default class TemplateRenderer {
|
|
6
6
|
constructor(options = {}) {
|
|
7
7
|
/** @type {Object} */
|
|
@@ -15,12 +15,6 @@ export default class TemplateRenderer {
|
|
|
15
15
|
}
|
|
16
16
|
run(options) {
|
|
17
17
|
const { template, params, helpers, ...rest } = this.resolveOptions(options);
|
|
18
|
-
if (!template) {
|
|
19
|
-
return {
|
|
20
|
-
body: '',
|
|
21
|
-
sections: [],
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
18
|
const compiled = this.loadTemplate(template, rest);
|
|
25
19
|
return compiled(params, {
|
|
26
20
|
helpers: resolveHelpers(helpers, rest),
|
|
@@ -30,7 +24,7 @@ export default class TemplateRenderer {
|
|
|
30
24
|
// Private
|
|
31
25
|
/** @returns {Object} */
|
|
32
26
|
resolveOptions(options = {}) {
|
|
33
|
-
|
|
27
|
+
const resolved = {
|
|
34
28
|
...this.options,
|
|
35
29
|
...options,
|
|
36
30
|
params: {
|
|
@@ -38,12 +32,15 @@ export default class TemplateRenderer {
|
|
|
38
32
|
...options.params,
|
|
39
33
|
},
|
|
40
34
|
};
|
|
35
|
+
resolved.template ||= resolved.body;
|
|
36
|
+
return resolved;
|
|
41
37
|
}
|
|
42
|
-
loadTemplate = memoize((input, options) => {
|
|
38
|
+
loadTemplate = memoize((input = '', options) => {
|
|
43
39
|
const source = resolveTemplateSource(input, options);
|
|
44
40
|
const template = Handlebars.compile(source.trim());
|
|
45
41
|
return (params, options) => {
|
|
46
|
-
|
|
42
|
+
let output = template(params, options);
|
|
43
|
+
output = unescapeHtml(output);
|
|
47
44
|
const { body, meta } = runFrontMatter(output);
|
|
48
45
|
const sections = getSections(body);
|
|
49
46
|
return {
|
package/dist/esm/helpers.js
CHANGED
|
@@ -88,15 +88,14 @@ export const DEFAULT_HELPERS = {
|
|
|
88
88
|
}
|
|
89
89
|
return index + 1;
|
|
90
90
|
},
|
|
91
|
-
link(
|
|
91
|
+
link(text, url) {
|
|
92
92
|
return new Handlebars.SafeString(`[${text}](${url})`);
|
|
93
93
|
},
|
|
94
|
-
button(
|
|
94
|
+
button(text, url) {
|
|
95
95
|
return generateHtml('a', {
|
|
96
96
|
text,
|
|
97
97
|
href: url,
|
|
98
98
|
class: 'button',
|
|
99
|
-
target: '_blank',
|
|
100
99
|
});
|
|
101
100
|
},
|
|
102
101
|
list(arr) {
|
|
@@ -117,7 +116,8 @@ export function resolveHelpers(helpers, options) {
|
|
|
117
116
|
function resolveHelper(arg, options) {
|
|
118
117
|
const { names, handler } = resolveArgumentNames(arg);
|
|
119
118
|
return (...args) => {
|
|
120
|
-
|
|
119
|
+
const result = handler(...resolveHelperArgs(args, names, options));
|
|
120
|
+
return generateHtml(result);
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
// Arguments
|
|
@@ -155,7 +155,12 @@ function resolveHelperArgs(args, names, options) {
|
|
|
155
155
|
params[name] = value;
|
|
156
156
|
});
|
|
157
157
|
const resolved = names.map((name) => {
|
|
158
|
-
|
|
158
|
+
if (name === 'params') {
|
|
159
|
+
return meta.hash;
|
|
160
|
+
}
|
|
161
|
+
let value = params[name];
|
|
162
|
+
value = normalizeParam(name, value, params, options);
|
|
163
|
+
return value;
|
|
159
164
|
});
|
|
160
165
|
options = {
|
|
161
166
|
options,
|
|
@@ -163,7 +168,34 @@ function resolveHelperArgs(args, names, options) {
|
|
|
163
168
|
};
|
|
164
169
|
return [...resolved, options];
|
|
165
170
|
}
|
|
166
|
-
|
|
171
|
+
// Param normalization
|
|
172
|
+
function normalizeParam(name, value, params, options) {
|
|
173
|
+
if (name === 'url' || name === 'href') {
|
|
174
|
+
value = normalizeUrl(value, params, options);
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
const PARAM_REG = /:([a-z]+)/gi;
|
|
179
|
+
function normalizeUrl(str, params, options) {
|
|
180
|
+
const { baseUrl } = options;
|
|
181
|
+
if (baseUrl && str.startsWith('/')) {
|
|
182
|
+
str = baseUrl + str;
|
|
183
|
+
}
|
|
184
|
+
str = str.replace(PARAM_REG, (_, key) => {
|
|
185
|
+
const value = params[key];
|
|
186
|
+
// Need to delete the injected params or they
|
|
187
|
+
// will be passed on to the HTML element.
|
|
188
|
+
delete params[key];
|
|
189
|
+
return value;
|
|
190
|
+
});
|
|
191
|
+
return str;
|
|
192
|
+
}
|
|
193
|
+
function generateHtml(...args) {
|
|
194
|
+
const arg = args.length > 1 ? args : args[0];
|
|
195
|
+
if (!Array.isArray(arg)) {
|
|
196
|
+
return arg || '';
|
|
197
|
+
}
|
|
198
|
+
const [tag, props] = arg;
|
|
167
199
|
const { text, ...rest } = props;
|
|
168
200
|
const attr = Object.entries(rest)
|
|
169
201
|
.map((entry) => {
|
|
@@ -174,9 +206,14 @@ function generateHtml(tag, props) {
|
|
|
174
206
|
})
|
|
175
207
|
.filter((a) => a)
|
|
176
208
|
.join(' ');
|
|
177
|
-
let html = `<${tag} ${attr}
|
|
209
|
+
let html = `<${tag} ${attr}`;
|
|
178
210
|
if (text) {
|
|
179
|
-
html +=
|
|
211
|
+
html += '>';
|
|
212
|
+
html += generateHtml(text);
|
|
213
|
+
html += `</${tag}>`;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
html += ` />`;
|
|
180
217
|
}
|
|
181
218
|
return new Handlebars.SafeString(html);
|
|
182
219
|
}
|
package/dist/esm/utils.js
CHANGED
|
@@ -18,9 +18,9 @@ export function runFrontMatter(str) {
|
|
|
18
18
|
body: body.trim(),
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
function tryReadFile(filepath
|
|
21
|
+
function tryReadFile(filepath) {
|
|
22
22
|
try {
|
|
23
|
-
return readFileSync(filepath
|
|
23
|
+
return readFileSync(filepath, 'utf-8');
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
26
|
if (error.code !== 'ENOENT') {
|
|
@@ -29,7 +29,12 @@ function tryReadFile(filepath, ext) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
function readSource(filepath) {
|
|
32
|
-
|
|
32
|
+
if (path.extname(filepath)) {
|
|
33
|
+
return tryReadFile(filepath);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return tryReadFile(filepath + '.md') || tryReadFile(filepath + '.txt');
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
// Sections
|
|
35
40
|
const SECTIONS_REG = /^=== (\w+) ===\n\n/gm;
|
|
@@ -52,3 +57,13 @@ export function getSections(str) {
|
|
|
52
57
|
}
|
|
53
58
|
return sections;
|
|
54
59
|
}
|
|
60
|
+
// Whitespace
|
|
61
|
+
// Handlebars doesn't allow a way to selectively
|
|
62
|
+
// escape so instead unescape some basic tokens.
|
|
63
|
+
export function unescapeHtml(html) {
|
|
64
|
+
html = html.replace(/'/g, "'");
|
|
65
|
+
html = html.replace(/"/g, '"');
|
|
66
|
+
html = html.replace(/'/g, "'");
|
|
67
|
+
html = html.replace(/=/g, '=');
|
|
68
|
+
return html;
|
|
69
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrockio/templates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Bedrock utility for custom templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"url": "https://github.com/bedrockio/templates"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@bedrockio/chrono": "^0.
|
|
37
|
+
"@bedrockio/chrono": "^0.8.0",
|
|
38
38
|
"front-matter": "^4.0.2",
|
|
39
39
|
"handlebars": "^4.7.8",
|
|
40
40
|
"lodash.memoize": "^4.1.2"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateRenderer.d.ts","sourceRoot":"","sources":["../src/TemplateRenderer.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TemplateRenderer.d.ts","sourceRoot":"","sources":["../src/TemplateRenderer.js"],"names":[],"mappings":"AAYA;IACE,0BASC;IARC,qBAAqB;IACrB,aAMC;IAGH,uBASC;IAID,wBAAwB;IACxB,kCAWC;IAED,kBAkBG;CACJ"}
|
package/types/helpers.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ export namespace DEFAULT_HELPERS {
|
|
|
22
22
|
function dateTimeShort(arg: any, meridiem: any): any;
|
|
23
23
|
function relTime(arg: any, min: any, max: any): any;
|
|
24
24
|
function number(options: any): any;
|
|
25
|
-
function link(
|
|
26
|
-
function button(
|
|
25
|
+
function link(text: any, url: any): Handlebars.SafeString;
|
|
26
|
+
function button(text: any, url: any): any;
|
|
27
27
|
function list(arr: any): any;
|
|
28
28
|
}
|
|
29
29
|
import Handlebars from 'handlebars';
|
package/types/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.js"],"names":[],"mappings":"AAwHA,+DAMC;;IAzHC,gCAEC;IACD,iCAEC;IACD,mCAEC;IACD,kCAEC;IAGD,4CAIC;IAED;;OAEG;IACH,mDAFW,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,OAOpD;IACD,gDAIC;IACD,kDAIC;IACD,iDAIC;IAGD,gDAIC;IAED;;OAEG;IACH,uDAFW,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,OAOpD;IACD,oDAIC;IACD,sDAIC;IACD,qDAIC;IAID,oDAKC;IAED,mCAMC;IAED,0DAEC;IAED,0CAMC;IAED,6BAMC;;uBApHoB,YAAY"}
|
package/types/utils.d.ts
CHANGED
package/types/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":"AAKA,mEASC;AAED;;;EAOC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":"AAKA,mEASC;AAED;;;EAOC;AAwBD;;;;;IAsBC;AAMD,6CAMC"}
|