mikel 0.15.0 → 0.17.0
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/README.md +42 -0
- package/index.js +26 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,6 +142,38 @@ const result = m("User: {{>user userName=name userEmail=email }}", data, {partia
|
|
|
142
142
|
|
|
143
143
|
Please note that providing keyword arguments and a custom context to a partial is not supported. On this situation, the partial will be evaluated only with the custom context.
|
|
144
144
|
|
|
145
|
+
#### Partial blocks
|
|
146
|
+
|
|
147
|
+
> This feature was added in `v0.16.0`.
|
|
148
|
+
|
|
149
|
+
You can pass a block to a partial using a greather than symbol `>>` followed by the partial name to start the partial block, and a slash followed by the partial name to end the partial block. The provided block content will be available in the `@content` variable.
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const options = {
|
|
155
|
+
partials: {
|
|
156
|
+
foo: "Hello {{@content}}!",
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const result = m("{{>>foo}}Bob{{/foo}}", {}, options);
|
|
161
|
+
// Output: 'Hello Bob!'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Inline partials
|
|
165
|
+
|
|
166
|
+
> This feature was added in `v0.16.0`.
|
|
167
|
+
|
|
168
|
+
Inline partials allows you to define partials directly in your template. Use the plus symbol `+` followed by the partial name to start the partial definition, and end the partial definition with a slash `/` followed by the partial name. For example, `{{<foo}}` begins a partial definition called `foo`, and `{{/foo}}` ends it.
|
|
169
|
+
|
|
170
|
+
Example:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
const result = m(`{{<foo}}Hello {{name}}!{{/foo}}{{>foo name="Bob"}}`, {});
|
|
174
|
+
// Output: 'Hello Bob!'
|
|
175
|
+
```
|
|
176
|
+
|
|
145
177
|
### Built-in helpers
|
|
146
178
|
|
|
147
179
|
> Added in `v0.4.0`.
|
|
@@ -279,6 +311,16 @@ const data = {
|
|
|
279
311
|
console.log(m("{{#with autor}}{{name}} <{{email}}>{{/with}}", data)); // --> 'Bob <bob@email.com>'
|
|
280
312
|
```
|
|
281
313
|
|
|
314
|
+
#### escape
|
|
315
|
+
|
|
316
|
+
> Added in `v0.17.0`.
|
|
317
|
+
|
|
318
|
+
The `escape` helper allows to escape the provided block content.
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
console.log(m("{{#escape}}<b>Hello World!</b>{{/escape}}")); // --> '<b>Hello World!</b>
|
|
322
|
+
```
|
|
323
|
+
|
|
282
324
|
### Custom Helpers
|
|
283
325
|
|
|
284
326
|
> Added in `v0.5.0`.
|
package/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const tags = /\{\{|\}\}/;
|
|
2
1
|
const escapedChars = {
|
|
3
2
|
"&": "&",
|
|
4
3
|
"<": "<",
|
|
@@ -11,6 +10,12 @@ const escape = s => s.toString().replace(/[&<>\"']/g, m => escapedChars[m]);
|
|
|
11
10
|
|
|
12
11
|
const get = (c, p) => (p === "." ? c : p.split(".").reduce((x, k) => x?.[k], c)) ?? "";
|
|
13
12
|
|
|
13
|
+
// @description tokenize and untokenize methods
|
|
14
|
+
const tokenize = (str = "") => str.split(/\{\{|\}\}/);
|
|
15
|
+
const untokenize = (ts = [], s = "{{", e = "}}") => {
|
|
16
|
+
return ts.reduce((p, t, i) => p + (i % 2 === 0 ? e : s) + t);
|
|
17
|
+
};
|
|
18
|
+
|
|
14
19
|
// @description parse string arguments
|
|
15
20
|
const parseArgs = (argString = "", context = {}, vars = {}) => {
|
|
16
21
|
const [t, ...args] = argString.trim().match(/(?:[^\s"]+|"[^"]*")+/g);
|
|
@@ -56,13 +61,13 @@ const defaultHelpers = {
|
|
|
56
61
|
"eq": p => p.args[0] === p.args[1] ? p.fn(p.context) : "",
|
|
57
62
|
"ne": p => p.args[0] !== p.args[1] ? p.fn(p.context) : "",
|
|
58
63
|
"with": p => p.fn(p.args[0]),
|
|
64
|
+
"escape": p => escape(p.fn(p.context)),
|
|
59
65
|
};
|
|
60
66
|
|
|
61
67
|
// @description create a new instance of mikel
|
|
62
68
|
const create = (template = "", options = {}) => {
|
|
63
|
-
// initialize internal context
|
|
64
69
|
const helpers = Object.assign({}, defaultHelpers, options?.helpers || {});
|
|
65
|
-
const partials = options?.partials || {};
|
|
70
|
+
const partials = Object.assign({}, options?.partials || {});
|
|
66
71
|
const functions = options?.functions || {};
|
|
67
72
|
// internal method to compile the template
|
|
68
73
|
const compile = (tokens, output, context, vars, index = 0, section = "") => {
|
|
@@ -103,11 +108,26 @@ const create = (template = "", options = {}) => {
|
|
|
103
108
|
i = compile(tokens, includeOutput ? output : [], context, vars, i + 1, t);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
111
|
+
else if (tokens[i].startsWith("<")) {
|
|
112
|
+
const t = tokens[i].slice(1).trim(), partialTokens = tokens.slice(i + 1);
|
|
113
|
+
const lastIndex = partialTokens.findIndex((token, j) => {
|
|
114
|
+
return j % 2 !== 0 && token.trim().startsWith("/") && token.trim().endsWith(t);
|
|
115
|
+
});
|
|
116
|
+
if (typeof partials[t] === "undefined") {
|
|
117
|
+
partials[t] = untokenize(partialTokens.slice(0, lastIndex));
|
|
118
|
+
}
|
|
119
|
+
i = i + lastIndex + 1;
|
|
120
|
+
}
|
|
106
121
|
else if (tokens[i].startsWith(">")) {
|
|
107
|
-
const [t, args, opt] = parseArgs(tokens[i].
|
|
122
|
+
const [t, args, opt] = parseArgs(tokens[i].replace(/^>{1,2}/, ""), context, vars);
|
|
123
|
+
const blockContent = []; // to store partial block content
|
|
124
|
+
if (tokens[i].startsWith(">>")) {
|
|
125
|
+
i = compile(tokens, blockContent, context, vars, i + 1, t);
|
|
126
|
+
}
|
|
108
127
|
if (typeof partials[t] === "string") {
|
|
109
128
|
const newCtx = args.length > 0 ? args[0] : (Object.keys(opt).length > 0 ? opt : context);
|
|
110
|
-
|
|
129
|
+
const newVars = {...vars, content: blockContent.join("")};
|
|
130
|
+
compile(tokenize(partials[t]), output, newCtx, newVars, 0, "");
|
|
111
131
|
}
|
|
112
132
|
}
|
|
113
133
|
else if (tokens[i].startsWith("=")) {
|
|
@@ -139,7 +159,7 @@ const create = (template = "", options = {}) => {
|
|
|
139
159
|
};
|
|
140
160
|
// entry method to compile the template with the provided data object
|
|
141
161
|
const compileTemplate = (data = {}, output = []) => {
|
|
142
|
-
compile(template
|
|
162
|
+
compile(tokenize(template), output, data, {root: data}, 0, "");
|
|
143
163
|
return output.join("");
|
|
144
164
|
};
|
|
145
165
|
// assign api methods and return method to compile the template
|