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.
Files changed (3) hide show
  1. package/README.md +42 -0
  2. package/index.js +26 -6
  3. 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}}")); // --> '&lt;b&gt;Hello World!&lt;/b&gt;
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
  "&": "&amp;",
4
3
  "<": "&lt;",
@@ -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].slice(1), context, vars);
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
- compile(partials[t].split(tags), output, newCtx, vars, 0, "");
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.split(tags), output, data, {root: data}, 0, "");
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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mikel",
3
3
  "description": "Micro templating library with zero dependencies",
4
- "version": "0.15.0",
4
+ "version": "0.17.0",
5
5
  "type": "module",
6
6
  "author": {
7
7
  "name": "Josemi Juanes",