mikel 0.22.2 → 0.24.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 (4) hide show
  1. package/README.md +36 -20
  2. package/index.d.ts +3 -3
  3. package/index.js +25 -11
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -360,6 +360,16 @@ The `escape` helper allows to escape the provided block content.
360
360
  console.log(m("{{#escape}}<b>Hello World!</b>{{/escape}}")); // --> '&lt;b&gt;Hello World!&lt;/b&gt;
361
361
  ```
362
362
 
363
+ #### raw
364
+
365
+ > Added in `v0.23.0`.
366
+
367
+ The `raw` helper allows to render the content of the block without evaluating it. All the stuff inside the block will be rendered as is, without processing any variables or helpers.
368
+
369
+ ```javascript
370
+ console.log(m("{{#raw}}Hello {{name}}!{{/raw}}", {name: "Bob"})); // --> 'Hello {{name}}!'
371
+ ```
372
+
363
373
  ### Custom Helpers
364
374
 
365
375
  > Added in `v0.5.0`.
@@ -610,83 +620,89 @@ const result = mikel("Hello, {{name}}!", data);
610
620
  console.log(result); // Output: "Hello, World!"
611
621
  ```
612
622
 
613
- ### `mikel.create(template [, options])`
623
+ ### `mikel.create(options)`
624
+
625
+ > Removed `template` argument in `v0.24.0`.
614
626
 
615
- Allows to create an isolated instance of mikel, useful when you want to compile the same template using different data. The `template` argument is the template string, and the optional `options` argument is the same options object that you can pass to `mikel` method.
627
+ Allows to create an isolated instance of mikel, useful when you want to use the same options for multiple templates without passing them every time. You can pass an `options` object with the same structure as the one used in the `mikel` function, which will be used for all templates compiled with this instance.
616
628
 
617
- It returns a function that you can call with the data to compile the template.
629
+ It returns a function that you can call with the template and data to compile the template.
618
630
 
619
631
  ```javascript
620
632
  import mikel from "mikel";
621
633
 
622
- const template = mikel.create("Hello, {{name}}!");
634
+ const mk = mikel.create({
635
+ partials: {
636
+ hello: "Hello, {{name}}!",
637
+ },
638
+ });
623
639
 
624
- console.log(template({name: "Bob"})); // --> "Hello, Bob!"
625
- console.log(template({name: "Susan"})); // --> "Hello, Susan!"
640
+ console.log(mk("{{>hello}}", {name: "Bob"})); // --> "Hello, Bob!"
641
+ console.log(mk("{{>hello}}", {name: "Susan"})); // --> "Hello, Susan!"
626
642
  ```
627
643
 
628
644
  It also exposes the following additional methods:
629
645
 
630
- #### `template.use(options)`
646
+ #### `mk.use(options)`
631
647
 
632
648
  > Added in `v0.19.0`.
633
649
 
634
650
  Allows to extend the templating with custom **helpers**, **functions**, and **partials**.
635
651
 
636
652
  ```javascript
637
- template.use({
653
+ mk.use({
638
654
  partials: {
639
655
  foo: "bar",
640
656
  },
641
657
  });
642
658
  ```
643
659
 
644
- #### `template.addHelper(helperName, helperFn)`
660
+ #### `mk.addHelper(helperName, helperFn)`
645
661
 
646
662
  Allows to register a new helper instead of using the `options` object.
647
663
 
648
664
  ```javascript
649
- template.addHelper("foo", () => { ... });
665
+ mk.addHelper("foo", () => { ... });
650
666
  ```
651
667
 
652
- #### `template.removeHelper(helperName)`
668
+ #### `mk.removeHelper(helperName)`
653
669
 
654
670
  Removes a previously added helper.
655
671
 
656
672
  ```javascript
657
- template.removeHelper("foo");
673
+ mk.removeHelper("foo");
658
674
  ```
659
675
 
660
- #### `template.addPartial(partialName, partialCode)`
676
+ #### `mk.addPartial(partialName, partialCode)`
661
677
 
662
678
  Registers a new partial instead of using the `options` object.
663
679
 
664
680
  ```javascript
665
- template.addPartial("bar", " ... ");
681
+ mk.addPartial("bar", " ... ");
666
682
  ```
667
683
 
668
- #### `template.removePartial(partialName)`
684
+ #### `mk.removePartial(partialName)`
669
685
 
670
686
  Removes a previously added partial.
671
687
 
672
688
  ```javascript
673
- template.removePartial("bar");
689
+ mk.removePartial("bar");
674
690
  ```
675
691
 
676
- #### `template.addFunction(fnName, fn)`
692
+ #### `mk.addFunction(fnName, fn)`
677
693
 
678
694
  Registers a new function instead of using the `options` object.
679
695
 
680
696
  ```javascript
681
- template.addFunction("foo", () => "...");
697
+ mk.addFunction("foo", () => "...");
682
698
  ```
683
699
 
684
- #### `template.removeFunction(fnName)`
700
+ #### `mk.removeFunction(fnName)`
685
701
 
686
702
  Removes a previously added function.
687
703
 
688
704
  ```javascript
689
- template.removeFunction("foo");
705
+ mk.removeFunction("foo");
690
706
  ```
691
707
 
692
708
  ### `mikel.escape(str)`
package/index.d.ts CHANGED
@@ -33,8 +33,8 @@ declare interface MikelOptions {
33
33
  variables?: Variables;
34
34
  }
35
35
 
36
- declare interface MikelTemplate {
37
- (data?: any): string;
36
+ declare interface MikelInstance {
37
+ (template: string, data?: any): string;
38
38
  use(options: Partial<MikelOptions>): MikelTemplate;
39
39
  addHelper(name: string, fn: HelperFunction): void;
40
40
  removeHelper(name: string): void;
@@ -46,7 +46,7 @@ declare interface MikelTemplate {
46
46
 
47
47
  declare const mikel: {
48
48
  (template: string, data?: any, options?: Partial<MikelOptions>): string;
49
- create(template: string, options?: Partial<MikelOptions>): MikelTemplate;
49
+ create(options?: Partial<MikelOptions>): MikelInstance;
50
50
  escape(str: string): string;
51
51
  get(context: any, path: string): any;
52
52
  parse(value: string, context?: any, vars?: any): any;
package/index.js CHANGED
@@ -13,7 +13,7 @@ const get = (c, p) => (p === "." ? c : p.split(".").reduce((x, k) => x?.[k], c))
13
13
  // @description tokenize and untokenize methods
14
14
  const tokenize = (str = "") => str.split(/\{\{|\}\}/);
15
15
  const untokenize = (ts = [], s = "{{", e = "}}") => {
16
- return ts.reduce((p, t, i) => p + (i % 2 === 0 ? e : s) + t);
16
+ return ts.length > 0 ? ts.reduce((p, t, i) => p + (i % 2 === 0 ? e : s) + t) : "";
17
17
  };
18
18
 
19
19
  // @description parse string arguments
@@ -45,6 +45,22 @@ const parse = (v, data = {}, vars = {}) => {
45
45
  return (v || "").startsWith("@") ? get(vars, v.slice(1)) : get(data, v || ".");
46
46
  };
47
47
 
48
+ // @description find the index of the closing token
49
+ const findClosingToken = (tokens, i, token) => {
50
+ while(i < tokens.length) {
51
+ if (i % 2 > 0) {
52
+ if (tokens[i].startsWith("/") && tokens[i].slice(1).trim() === token) {
53
+ return i;
54
+ }
55
+ else if (tokens[i].startsWith("#") && tokens[i].slice(1).trim().split(" ")[0] === token) {
56
+ i = findClosingToken(tokens, i + 1, token);
57
+ }
58
+ }
59
+ i = i + 1;
60
+ }
61
+ throw new Error(`Unmatched section end: {{${token}}}`);
62
+ };
63
+
48
64
  // @description default helpers
49
65
  const defaultHelpers = {
50
66
  "each": p => {
@@ -60,12 +76,12 @@ const defaultHelpers = {
60
76
  "ne": p => p.args[0] !== p.args[1] ? p.fn(p.data) : "",
61
77
  "with": p => p.fn(p.args[0]),
62
78
  "escape": p => escape(p.fn(p.data)),
79
+ "raw": p => untokenize(p.tokens),
63
80
  };
64
81
 
65
82
  // @description create a new instance of mikel
66
- const create = (template = "", options = {}) => {
83
+ const create = (options = {}) => {
67
84
  const ctx = {
68
- tokens: tokenize(template),
69
85
  helpers: Object.assign({}, defaultHelpers, options?.helpers || {}),
70
86
  partials: Object.assign({}, options?.partials || {}),
71
87
  functions: options?.functions || {},
@@ -81,20 +97,18 @@ const create = (template = "", options = {}) => {
81
97
  else if (tokens[i].startsWith("#") && typeof ctx.helpers[tokens[i].slice(1).trim().split(" ")[0]] === "function") {
82
98
  const [t, args, opt] = parseArgs(tokens[i].slice(1), data, vars);
83
99
  const j = i + 1;
100
+ i = findClosingToken(tokens, j, t);
84
101
  output.push(ctx.helpers[t]({
85
102
  args: args,
86
103
  opt: opt,
104
+ tokens: tokens.slice(j, i),
87
105
  data: data,
88
106
  variables: vars,
89
107
  fn: (blockData = {}, blockVars = {}, blockOutput = []) => {
90
- i = compile(tokens, blockOutput, blockData, {...vars, ...blockVars, parent: data, root: vars.root}, j, t);
108
+ compile(tokens, blockOutput, blockData, {...vars, ...blockVars, parent: data, root: vars.root}, j, t);
91
109
  return blockOutput.join("");
92
110
  },
93
111
  }));
94
- // Make sure that this block is executed at least once
95
- if (i + 1 === j) {
96
- i = compile(tokens, [], {}, {}, j, t);
97
- }
98
112
  }
99
113
  else if (tokens[i].startsWith("#") || tokens[i].startsWith("^")) {
100
114
  const t = tokens[i].slice(1).trim();
@@ -155,8 +169,8 @@ const create = (template = "", options = {}) => {
155
169
  return i;
156
170
  };
157
171
  // entry method to compile the template with the provided data object
158
- const compileTemplate = (data = {}, output = []) => {
159
- compile(ctx.tokens, output, data, {root: data, ...ctx.variables}, 0, "");
172
+ const compileTemplate = (template, data = {}, output = []) => {
173
+ compile(tokenize(template), output, data, {root: data, ...ctx.variables}, 0, "");
160
174
  return output.join("");
161
175
  };
162
176
  // assign api methods and return method to compile the template
@@ -183,7 +197,7 @@ const create = (template = "", options = {}) => {
183
197
 
184
198
  // @description main compiler function
185
199
  const mikel = (template = "", data = {}, options = {}) => {
186
- return create(template, options)(data);
200
+ return create(options)(template, data);
187
201
  };
188
202
 
189
203
  // @description assign utilities
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.22.2",
4
+ "version": "0.24.0",
5
5
  "type": "module",
6
6
  "author": {
7
7
  "name": "Josemi Juanes",