boxwood 0.76.0 → 0.77.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.
Files changed (60) hide show
  1. package/README.md +15 -6
  2. package/index.js +20 -9
  3. package/package.json +1 -1
  4. package/benchmark/fixtures/basic/boxwood.js +0 -3
  5. package/benchmark/fixtures/basic/data.json +0 -1
  6. package/benchmark/fixtures/basic/handlebars.hbs +0 -1
  7. package/benchmark/fixtures/basic/lodash.ejs +0 -1
  8. package/benchmark/fixtures/basic/mustache.mst +0 -1
  9. package/benchmark/fixtures/basic/underscore.ejs +0 -1
  10. package/benchmark/fixtures/basic/vanilla.js +0 -3
  11. package/benchmark/fixtures/div/boxwood.js +0 -5
  12. package/benchmark/fixtures/div/data.json +0 -1
  13. package/benchmark/fixtures/div/handlebars.hbs +0 -1
  14. package/benchmark/fixtures/div/lodash.ejs +0 -1
  15. package/benchmark/fixtures/div/mustache.mst +0 -1
  16. package/benchmark/fixtures/div/underscore.ejs +0 -1
  17. package/benchmark/fixtures/div/vanilla.js +0 -4
  18. package/benchmark/fixtures/escape/boxwood.js +0 -3
  19. package/benchmark/fixtures/escape/data.json +0 -3
  20. package/benchmark/fixtures/escape/handlebars.hbs +0 -1
  21. package/benchmark/fixtures/escape/lodash.ejs +0 -1
  22. package/benchmark/fixtures/escape/mustache.mst +0 -1
  23. package/benchmark/fixtures/escape/underscore.ejs +0 -1
  24. package/benchmark/fixtures/escape/vanilla.js +0 -5
  25. package/benchmark/fixtures/friends/boxwood.js +0 -55
  26. package/benchmark/fixtures/friends/data.json +0 -30
  27. package/benchmark/fixtures/friends/handlebars.hbs +0 -45
  28. package/benchmark/fixtures/friends/lodash.ejs +0 -48
  29. package/benchmark/fixtures/friends/mustache.mst +0 -45
  30. package/benchmark/fixtures/friends/underscore.ejs +0 -48
  31. package/benchmark/fixtures/friends/vanilla.js +0 -36
  32. package/benchmark/fixtures/if/boxwood.js +0 -21
  33. package/benchmark/fixtures/if/data.json +0 -12
  34. package/benchmark/fixtures/if/handlebars.hbs +0 -13
  35. package/benchmark/fixtures/if/lodash.ejs +0 -12
  36. package/benchmark/fixtures/if/mustache.mst +0 -13
  37. package/benchmark/fixtures/if/underscore.ejs +0 -12
  38. package/benchmark/fixtures/if/vanilla.js +0 -14
  39. package/benchmark/fixtures/projects/boxwood.js +0 -20
  40. package/benchmark/fixtures/projects/data.json +0 -26
  41. package/benchmark/fixtures/projects/handlebars.hbs +0 -15
  42. package/benchmark/fixtures/projects/lodash.ejs +0 -17
  43. package/benchmark/fixtures/projects/mustache.mst +0 -16
  44. package/benchmark/fixtures/projects/underscore.ejs +0 -17
  45. package/benchmark/fixtures/projects/vanilla.js +0 -21
  46. package/benchmark/fixtures/search/boxwood.js +0 -16
  47. package/benchmark/fixtures/search/data.json +0 -35
  48. package/benchmark/fixtures/search/handlebars.hbs +0 -18
  49. package/benchmark/fixtures/search/lodash.ejs +0 -22
  50. package/benchmark/fixtures/search/mustache.mst +0 -18
  51. package/benchmark/fixtures/search/underscore.ejs +0 -22
  52. package/benchmark/fixtures/search/vanilla.js +0 -26
  53. package/benchmark/fixtures/todos/boxwood.js +0 -9
  54. package/benchmark/fixtures/todos/data.json +0 -9
  55. package/benchmark/fixtures/todos/handlebars.hbs +0 -7
  56. package/benchmark/fixtures/todos/lodash.ejs +0 -7
  57. package/benchmark/fixtures/todos/mustache.mst +0 -7
  58. package/benchmark/fixtures/todos/underscore.ejs +0 -7
  59. package/benchmark/fixtures/todos/vanilla.js +0 -12
  60. package/benchmark/index.js +0 -112
package/README.md CHANGED
@@ -48,6 +48,8 @@ const html = template({ foo: "bar" })
48
48
  console.log(html)
49
49
  ```
50
50
 
51
+ You can use [express-boxwood](https://www.npmjs.com/package/express-boxwood) for [express](https://www.npmjs.com/package/express).
52
+
51
53
  ## Syntax
52
54
 
53
55
  ```js
@@ -56,7 +58,7 @@ const layout = require("./layout")
56
58
  const banner = require("./banner")
57
59
 
58
60
  module.exports = () => {
59
- return layout([
61
+ return layout({ language: "en" }, [
60
62
  banner({
61
63
  title: "Hello, world!",
62
64
  description: "Lorem ipsum dolor sit amet",
@@ -67,22 +69,27 @@ module.exports = () => {
67
69
 
68
70
  ```js
69
71
  // example/layout/index.js
70
-
71
- const { component, css, html, head, body } = require("boxwood")
72
+ const { component, css, doctype, html, body } = require("boxwood")
72
73
  const head = require("./head")
73
74
 
74
75
  const styles = css.load(__dirname)
75
76
 
76
77
  module.exports = component(
77
- (children) => {
78
- return html([head(), body({ className: styles.layout }, children)])
78
+ ({ language }, children) => {
79
+ return [
80
+ doctype(),
81
+ html({ lang: language }, [
82
+ head(),
83
+ body({ className: styles.layout }, children),
84
+ ]),
85
+ ]
79
86
  },
80
87
  { styles }
81
88
  )
82
89
  ```
83
90
 
84
91
  ```js
85
- // example/head/index.js
92
+ // example/layout/head/index.js
86
93
  const { head, title } = require("boxwood")
87
94
 
88
95
  module.exports = () => {
@@ -127,6 +134,8 @@ test("banner renders an optional description", async () => {
127
134
  })
128
135
  ```
129
136
 
137
+ You can check the `test` dir for more examples.
138
+
130
139
  ## Maintainers
131
140
 
132
141
  [@emilos](https://github.com/emilos)
package/index.js CHANGED
@@ -29,6 +29,9 @@ async function compile(path) {
29
29
  node.ignore = true
30
30
  }
31
31
  if (node.name === "script") {
32
+ if (node.attributes && node.attributes.src) {
33
+ return
34
+ }
32
35
  const js = node.children
33
36
  if (
34
37
  node.attributes &&
@@ -46,7 +49,7 @@ async function compile(path) {
46
49
  if (Array.isArray(node)) {
47
50
  node.forEach(walk)
48
51
  } else if (Array.isArray(node.children)) {
49
- node.children.filter(Boolean).forEach(walk)
52
+ node.children.forEach(walk)
50
53
  }
51
54
  }
52
55
  walk(tree)
@@ -135,7 +138,12 @@ const attributes = (options) => {
135
138
  const result = []
136
139
  for (const key in options) {
137
140
  const value = options[key]
138
- if (value) {
141
+ if (
142
+ typeof value === "string" ||
143
+ typeof value === "number" ||
144
+ value === true ||
145
+ Array.isArray(value)
146
+ ) {
139
147
  if (BOOLEAN_ATTRIBUTES.includes(key)) {
140
148
  result.push(key)
141
149
  } else {
@@ -174,15 +182,14 @@ const isUnescapedTag = (name) => {
174
182
  }
175
183
 
176
184
  const render = (input, escape = true) => {
177
- if (!input || input.ignore) {
185
+ if (
186
+ typeof input === "undefined" ||
187
+ typeof input === "boolean" ||
188
+ input === null ||
189
+ input.ignore
190
+ ) {
178
191
  return ""
179
192
  }
180
- if (Array.isArray(input)) {
181
- return input
182
- .filter(Boolean)
183
- .map((input) => render(input))
184
- .join("")
185
- }
186
193
  if (typeof input === "number") {
187
194
  return input.toString()
188
195
  }
@@ -192,6 +199,10 @@ const render = (input, escape = true) => {
192
199
  }
193
200
  return input
194
201
  }
202
+ if (Array.isArray(input)) {
203
+ return input.map((input) => render(input)).join("")
204
+ }
205
+
195
206
  if (input.name === "raw") {
196
207
  return render(input.children, false)
197
208
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boxwood",
3
- "version": "0.76.0",
3
+ "version": "0.77.1",
4
4
  "description": "Compile HTML templates into JS",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,3 +0,0 @@
1
- module.exports = function () {
2
- return 'foo'
3
- }
@@ -1 +0,0 @@
1
- {}
@@ -1 +0,0 @@
1
- foo
@@ -1 +0,0 @@
1
- foo
@@ -1 +0,0 @@
1
- foo
@@ -1 +0,0 @@
1
- foo
@@ -1,3 +0,0 @@
1
- module.exports = function () {
2
- return 'foo'
3
- }
@@ -1,5 +0,0 @@
1
- const { div } = require("../../..")
2
-
3
- module.exports = function () {
4
- return div("foo")
5
- }
@@ -1 +0,0 @@
1
- {}
@@ -1 +0,0 @@
1
- <div>foo</div>
@@ -1 +0,0 @@
1
- <div>foo</div>
@@ -1 +0,0 @@
1
- <div>foo</div>
@@ -1 +0,0 @@
1
- <div>foo</div>
@@ -1,4 +0,0 @@
1
-
2
- module.exports = function () {
3
- return '<div>foo</div>'
4
- }
@@ -1,3 +0,0 @@
1
- module.exports = function ({ foo }) {
2
- return foo
3
- }
@@ -1,3 +0,0 @@
1
- {
2
- "foo": "<img>"
3
- }
@@ -1 +0,0 @@
1
- {{foo}}
@@ -1 +0,0 @@
1
- <%- foo %>
@@ -1 +0,0 @@
1
- {{foo}}
@@ -1 +0,0 @@
1
- <%- foo %>
@@ -1,5 +0,0 @@
1
- const { escape } = require("../../..")
2
-
3
- module.exports = function ({ foo }) {
4
- return escape(foo)
5
- }
@@ -1,55 +0,0 @@
1
- const {
2
- doctype,
3
- html,
4
- head,
5
- body,
6
- meta,
7
- img,
8
- title,
9
- div,
10
- ul,
11
- li,
12
- a,
13
- } = require("../../..")
14
-
15
- module.exports = function ({ friends }) {
16
- return [
17
- doctype(),
18
- html({ lang: "en" }, [
19
- head([meta({ charset: "UTF-8" }), title("Friends")]),
20
- body([
21
- div(
22
- { class: "friends" },
23
- friends.map((friend) => {
24
- return div({ class: "friend" }, [
25
- ul([
26
- li(`Name: ${friend.name}`),
27
- li(`Balance: ${friend.balance}`),
28
- li(`Age: ${friend.age}`),
29
- li(`Address: ${friend.address}`),
30
- li(["Image: ", img({ src: friend.picture })]),
31
- li(`Company: ${friend.company}`),
32
- li([
33
- "Email: ",
34
- a({ href: `mailto:${friend.email}` }, friend.email),
35
- ]),
36
- li(`About: ${friend.about}`),
37
- friend.tags.length &&
38
- li(["Tags: ", ul(friend.tags.map((tag) => li(tag)))]),
39
- friend.friends.length &&
40
- li([
41
- "Friends: ",
42
- ul(
43
- friend.friends.map((friend) =>
44
- li(`${friend.name} (${friend.id})`)
45
- )
46
- ),
47
- ]),
48
- ]),
49
- ])
50
- })
51
- ),
52
- ]),
53
- ]),
54
- ]
55
- }
@@ -1,30 +0,0 @@
1
- {
2
- "friends": [
3
- {
4
- "name": "Jan Kowalski",
5
- "id": 1,
6
- "balance": "100 PLN",
7
- "age": 50,
8
- "address": "Warszawa",
9
- "picture": "jankowalski.png",
10
- "email": "jan@kowalski.pl",
11
- "about": "I like fishing",
12
- "company": "PKO",
13
- "tags": ["fisherman"],
14
- "friends": [
15
- {
16
- "name": "Piotr Nowak",
17
- "id": 2,
18
- "balance": "80 PLN",
19
- "age": 40,
20
- "address": "Kraków",
21
- "picture": "piotrnowak.png",
22
- "email": "piotr@nowak.pl",
23
- "about": "I like cooking",
24
- "company": "ING",
25
- "tags": ["chef"]
26
- }
27
- ]
28
- }
29
- ]
30
- }
@@ -1,45 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Friends</title>
6
- </head>
7
- <body>
8
- <div class="friends">
9
- {{#each friends}}
10
- <div class="friend">
11
- <ul>
12
- <li>Name: {{this.name}}</li>
13
- <li>Balance: {{this.balance}}</li>
14
- <li>Age: {{this.age}}</li>
15
- <li>Address: {{this.address}}</li>
16
- <li>Image: <img src="{{this.picture}}"></li>
17
- <li>Company: {{this.company}}</li>
18
- <li>Email: <a href="mailto:{{this.email}}">{{this.email}}</a></li>
19
- <li>About: {{this.about}}</li>
20
- {{#if tags.length}}
21
- <li>
22
- Tags:
23
- <ul>
24
- {{#each tags}}
25
- <li>{{this}}</li>
26
- {{/each}}
27
- </ul>
28
- </li>
29
- {{/if}}
30
- {{#if friends.length}}
31
- <li>
32
- Friends:
33
- <ul>
34
- {{#each friends}}
35
- <li>{{this.name}} ({{this.id}})</li>
36
- {{/each}}
37
- </ul>
38
- </li>
39
- {{/if}}
40
- </ul>
41
- </div>
42
- {{/each}}
43
- </div>
44
- </body>
45
- </html>
@@ -1,48 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Friends</title>
6
- </head>
7
- <body>
8
- <div class="friends">
9
- <% for (var i = 0, ilen = friends.length; i < ilen; i += 1) { %>
10
- <% var friend = friends[i]; %>
11
- <div class="friend">
12
- <ul>
13
- <li>Name: <%- friend.name %></li>
14
- <li>Balance: <%- friend.balance %></li>
15
- <li>Age: <%- friend.age %></li>
16
- <li>Address: <%- friend.address %></li>
17
- <li>Image: <img src="<%- friend.picture %>"></li>
18
- <li>Company: <%- friend.company %></li>
19
- <li>Email: <a href="mailto:<%- friend.email %>"><%- friend.email %></a></li>
20
- <li>About: <%- friend.about %></li>
21
- <% if (friend.tags.length) { %>
22
- <li>
23
- Tags:
24
- <ul>
25
- <% for (var j = 0, jlen = friend.tags.length; j < jlen; j += 1) { %>
26
- <% var tag = friend.tags[i]; %>
27
- <li><%- tag %></li>
28
- <% } %>
29
- </ul>
30
- </li>
31
- <% } %>
32
- <% if (friend.friends.length) { %>
33
- <li>
34
- Friends:
35
- <ul>
36
- <% for (var k = 0, klen = friend.friends.length; k < klen; k += 1) { %>
37
- <% var fr = friend.friends[i] %>
38
- <li><%- fr.name %> (<%- fr.id %>)</li>
39
- <% } %>
40
- </ul>
41
- </li>
42
- <% } %>
43
- </ul>
44
- </div>
45
- <% } %>
46
- </div>
47
- </body>
48
- </html>
@@ -1,45 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Friends</title>
6
- </head>
7
- <body>
8
- <div class="friends">
9
- {{#friends}}
10
- <div class="friend">
11
- <ul>
12
- <li>Name: {{name}}</li>
13
- <li>Balance: {{balance}}</li>
14
- <li>Age: {{age}}</li>
15
- <li>Address: {{address}}</li>
16
- <li>Image: <img src="{{picture}}"></li>
17
- <li>Company: {{company}}</li>
18
- <li>Email: <a href="mailto:{{email}}">{{email}}</a></li>
19
- <li>About: {{about}}</li>
20
- {{#tags.length}}
21
- <li>
22
- Tags:
23
- <ul>
24
- {{#tags}}
25
- <li>{{.}}</li>
26
- {{/tags}}
27
- </ul>
28
- </li>
29
- {{/tags.length}}
30
- {{#friends.length}}
31
- <li>
32
- Friends:
33
- <ul>
34
- {{#friends}}
35
- <li>{{name}} ({{id}})</li>
36
- {{/friends}}
37
- </ul>
38
- </li>
39
- {{/friends.length}}
40
- </ul>
41
- </div>
42
- {{/friends}}
43
- </div>
44
- </body>
45
- </html>
@@ -1,48 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Friends</title>
6
- </head>
7
- <body>
8
- <div class="friends">
9
- <% for (var i = 0, ilen = friends.length; i < ilen; i += 1) { %>
10
- <% var friend = friends[i]; %>
11
- <div class="friend">
12
- <ul>
13
- <li>Name: <%- friend.name %></li>
14
- <li>Balance: <%- friend.balance %></li>
15
- <li>Age: <%- friend.age %></li>
16
- <li>Address: <%- friend.address %></li>
17
- <li>Image: <img src="<%- friend.picture %>"></li>
18
- <li>Company: <%- friend.company %></li>
19
- <li>Email: <a href="mailto:<%- friend.email %>"><%- friend.email %></a></li>
20
- <li>About: <%- friend.about %></li>
21
- <% if (friend.tags.length) { %>
22
- <li>
23
- Tags:
24
- <ul>
25
- <% for (var j = 0, jlen = friend.tags.length; j < jlen; j += 1) { %>
26
- <% var tag = friend.tags[i]; %>
27
- <li><%- tag %></li>
28
- <% } %>
29
- </ul>
30
- </li>
31
- <% } %>
32
- <% if (friend.friends.length) { %>
33
- <li>
34
- Friends:
35
- <ul>
36
- <% for (var k = 0, klen = friend.friends.length; k < klen; k += 1) { %>
37
- <% var fr = friend.friends[i] %>
38
- <li><%- fr.name %> (<%- fr.id %>)</li>
39
- <% } %>
40
- </ul>
41
- </li>
42
- <% } %>
43
- </ul>
44
- </div>
45
- <% } %>
46
- </div>
47
- </body>
48
- </html>
@@ -1,36 +0,0 @@
1
- module.exports = function ({ friends }) {
2
- let template = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Friends</title></head><body><div class="friends">'
3
- for (let i = 0, ilen = friends.length; i < ilen; i++) {
4
- const friend = friends[i]
5
- template += '<div class="friend">'
6
- template += '<ul>'
7
- template += '<li>Name: ' + friend.name + '</li>'
8
- template += '<li>Balance: ' + friend.balance + '</li>'
9
- template += '<li>Age: ' + friend.age + '</li>'
10
- template += '<li>Address: ' + friend.address + '</li>'
11
- template += '<li>Image: <img src="' + friend.picture + '"></li>'
12
- template += '<li>Company: ' + friend.company + '</li>'
13
- template += '<li>Email: <a href="mailto:' + friend.email + '">' + friend.email + '</a></li>'
14
- template += '<li>About: ' + friend.about + '</li>'
15
- if (friend.tags.length) {
16
- template += '<li>Tags: <ul>'
17
- for (let j = 0, jlen = friend.tags.length; j < jlen; j++) {
18
- const tag = friend.tags[j]
19
- template += '<li>' + tag + '</li>'
20
- }
21
- template += '</ul></li>'
22
- }
23
- if (friend.friends.length) {
24
- template += '<li>Friends: <ul>'
25
- for (let j = 0, jlen = friend.friends.length; j < jlen; j++) {
26
- const person = friend.friends[j]
27
- template += '<li>' + person.name + ' (' + person.id + ')</li>'
28
- }
29
- template += '</ul></li>'
30
- }
31
- template += '</ul>'
32
- template += '</div>'
33
- }
34
- template += '</div></body></html>'
35
- return template
36
- }
@@ -1,21 +0,0 @@
1
- const { div, span } = require("../../..")
2
-
3
- function description(account) {
4
- if (account.status === "closed") {
5
- return "Your account has been closed!"
6
- }
7
- if (account.status === "suspended") {
8
- return "Your account has been temporarily suspended"
9
- }
10
- return (
11
- "Bank balance: " +
12
- span(
13
- { class: account.balance >= 0 ? "positive" : "negative" },
14
- account.balance
15
- )
16
- )
17
- }
18
-
19
- module.exports = function ({ accounts }) {
20
- return accounts.map((account) => div(description(account)))
21
- }
@@ -1,12 +0,0 @@
1
- {
2
- "accounts": [
3
- {
4
- "closed": true,
5
- "suspended": false,
6
- "active": false,
7
- "status": "closed",
8
- "balance": 100,
9
- "balanceClass": "positive"
10
- }
11
- ]
12
- }
@@ -1,13 +0,0 @@
1
- {{#each accounts}}
2
- <div>
3
- {{#if this.closed}}
4
- Your account has been closed!
5
- {{/if}}
6
- {{#if this.suspended}}
7
- Your account has been temporarily suspended
8
- {{/if}}
9
- {{#if this.active}}
10
- Bank balance: <span class="{{ account.balanceClass }}">{{this.balance}}</span>
11
- {{/if}}
12
- </div>
13
- {{/each}}
@@ -1,12 +0,0 @@
1
- <% for (var i = 0, ilen = accounts.length; i < ilen; i += 1) { %>
2
- <% var account = accounts[i]; %>
3
- <div>
4
- <% if (account.status === "closed") { %>
5
- Your account has been closed!
6
- <% } else if (account.status === "suspended") { %>
7
- Your account has been temporarily suspended
8
- <% } else { %>
9
- Bank balance: <span class="<%- account.balance >= 0 ? 'positive' : 'negative' %>"><%- account.balance %></span>
10
- <% } %>
11
- </div>
12
- <% } %>
@@ -1,13 +0,0 @@
1
- {{#accounts}}
2
- <div>
3
- {{#closed}}
4
- Your account has been closed!
5
- {{/closed}}
6
- {{#suspended}}
7
- Your account has been temporarily suspended
8
- {{/suspended}}
9
- {{#active}}
10
- Bank balance: <span class="{{balanceClass}}">{{balance}}</span>
11
- {{/active}}
12
- </div>
13
- {{/accounts}}
@@ -1,12 +0,0 @@
1
- <% for (var i = 0, ilen = accounts.length; i < ilen; i += 1) { %>
2
- <% var account = accounts[i]; %>
3
- <div>
4
- <% if (account.status === "closed") { %>
5
- Your account has been closed!
6
- <% } else if (account.status === "suspended") { %>
7
- Your account has been temporarily suspended
8
- <% } else { %>
9
- Bank balance: <span class="<%- account.balance >= 0 ? 'positive' : 'negative' %>"><%- account.balance %></span>
10
- <% } %>
11
- </div>
12
- <% } %>
@@ -1,14 +0,0 @@
1
- function description (account) {
2
- if (account.status === 'closed') { return 'Your account has been closed!' }
3
- if (account.status === 'suspended') { return 'Your account has been temporarily suspended' }
4
- return 'Bank balance: ' + '<span class="' + account.balance >= 0 ? 'positive' : 'negative' + '">' + account.balance + '</span>'
5
- }
6
-
7
- module.exports = function ({ accounts }) {
8
- let template = ''
9
- for (let i = 0, ilen = accounts.length; i < ilen; i++) {
10
- const account = accounts[i]
11
- template += '<div>' + description(account) + '</div>'
12
- }
13
- return template
14
- }
@@ -1,20 +0,0 @@
1
- const { doctype, tag, html, head, body, p, a } = require("../../..")
2
-
3
- module.exports = ({ title, projects, text }) => {
4
- return [
5
- doctype(),
6
- html([
7
- head([tag("title", title)]),
8
- body([
9
- p(text),
10
- ...projects.map((project) => {
11
- return [
12
- a({ href: project.url }, project.name),
13
- p(project.description),
14
- ]
15
- }),
16
- projects.length === 0 && "No projects",
17
- ]),
18
- ]),
19
- ]
20
- }
@@ -1,26 +0,0 @@
1
- {
2
- "title": "Projects",
3
- "text": "Your projects",
4
- "projects": [
5
- {
6
- "name": "foo",
7
- "url": "foo.bar",
8
- "description": "bar"
9
- },
10
- {
11
- "name": "bar",
12
- "url": "foo.bar",
13
- "description": "bar"
14
- },
15
- {
16
- "name": "baz",
17
- "url": "foo.bar",
18
- "description": "bar"
19
- },
20
- {
21
- "name": "qux",
22
- "url": "foo.bar",
23
- "description": "bar"
24
- }
25
- ]
26
- }
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>{{title}}</title>
5
- </head>
6
- <body>
7
- <p>{{text}}</p>
8
- {{#each projects}}
9
- <a href="{{this.url}}">{{this.name}}</a>
10
- <p>{{this.description}}</p>
11
- {{else}}
12
- No projects
13
- {{/each}}
14
- </body>
15
- </html>
@@ -1,17 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title><%- title %></title>
5
- </head>
6
- <body>
7
- <p><%- text %></p>
8
- <% for (var i = 0, ilen = projects.length; i < ilen; i++) { %>
9
- <% var project = projects[i]; %>
10
- <a href="<%- project.url %>"><%- project.name %></a>
11
- <p><%- project.description %></p>
12
- <% } %>
13
- <% if (projects.length === 0) { %>
14
- No projects
15
- <% } %>
16
- </body>
17
- </html>
@@ -1,16 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>{{title}}</title>
5
- </head>
6
- <body>
7
- <p>{{text}}</p>
8
- {{#projects}}
9
- <a href="{{url}}">{{name}}</a>
10
- <p>{{description}}</p>
11
- {{/projects}}
12
- {{^projects}}
13
- No projects
14
- {{/projects}}
15
- </body>
16
- </html>
@@ -1,17 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title><%- title %></title>
5
- </head>
6
- <body>
7
- <p><%- text %></p>
8
- <% for (var i = 0, ilen = projects.length; i < ilen; i++) { %>
9
- <% var project = projects[i]; %>
10
- <a href="<%- project.url %>"><%- project.name %></a>
11
- <p><%- project.description %></p>
12
- <% } %>
13
- <% if (projects.length === 0) { %>
14
- No projects
15
- <% } %>
16
- </body>
17
- </html>
@@ -1,21 +0,0 @@
1
- module.exports = ({ title, projects, text }) => {
2
- let output =
3
- "<!DOCTYPE html><html><head><title>" +
4
- title +
5
- "</title></head><body><p>" +
6
- text +
7
- "</p>"
8
- projects.forEach((project) => {
9
- output +=
10
- '<a href="' +
11
- project.url +
12
- '">' +
13
- project.name +
14
- "</a><p>" +
15
- project.description +
16
- "</p>"
17
- })
18
- output += projects.length === 0 ? "No projects" : ""
19
- output += "</body></html>"
20
- return output
21
- }
@@ -1,16 +0,0 @@
1
- const { div, ul, li, p } = require("../../..")
2
-
3
- module.exports = function ({ count, results }) {
4
- return div({ class: "search" }, [
5
- div({ class: "loader" }, "Loading..."),
6
- div({ class: "results" }, [
7
- p(`${count} results`),
8
- ...results.map((result) => [
9
- div({ class: "title" }, result.title),
10
- div({ class: "description" }, result.description),
11
- result.featured && div({ class: "highlight" }, "Featured!"),
12
- result.sizes.length && ul(result.sizes.map((size) => li(size))),
13
- ]),
14
- ]),
15
- ])
16
- }
@@ -1,35 +0,0 @@
1
- {
2
- "count": 5,
3
- "results": [
4
- {
5
- "title": "foo",
6
- "description": "foo",
7
- "featured": true,
8
- "sizes": [5, 10, 15]
9
- },
10
- {
11
- "title": "bar",
12
- "description": "bar",
13
- "featured": false,
14
- "sizes": [5, 10, 15, 20]
15
- },
16
- {
17
- "title": "baz",
18
- "description": "baz",
19
- "featured": true,
20
- "sizes": [5, 10, 15, 20, 25]
21
- },
22
- {
23
- "title": "qux",
24
- "description": "qux",
25
- "featured": false,
26
- "sizes": [5, 10, 15, 20, 25, 30]
27
- },
28
- {
29
- "title": "quux",
30
- "description": "quux",
31
- "featured": true,
32
- "sizes": [5, 10, 15, 20, 25, 30, 35]
33
- }
34
- ]
35
- }
@@ -1,18 +0,0 @@
1
- <div class="search">
2
- <div class="loader">Loading...</div>
3
- <div class="results">
4
- <p>{{count}} results</p>
5
- {{#each results}}
6
- <div class="title">{{this.title}}</div>
7
- <div class="description">{{this.description}}</div>
8
- {{#if this.featured}}
9
- <div class="highlight">Featured!</div>
10
- {{/if}}
11
- <ul>
12
- {{#each sizes}}
13
- <li>{{this}}</li>
14
- {{/each}}
15
- </ul>
16
- {{/each}}
17
- </div>
18
- </div>
@@ -1,22 +0,0 @@
1
- <div class="search">
2
- <div class="loader">Loading...</div>
3
- <div class="results">
4
- <p><%- count %> results</p>
5
- <% for (var i = 0, ilen = results.length; i < ilen; i++) { %>
6
- <% var result = results[i]; %>
7
- <div class="title"><%- result.title %></div>
8
- <div class="description"><%- result.description %></div>
9
- <% if (result.featured) { %>
10
- <div class="highlight">Featured!</div>
11
- <% } %>
12
- <% if (result.sizes.length > 0) { %>
13
- <ul>
14
- <% for (var j = 0, jlen = result.sizes.length; j < jlen; j++) { %>
15
- <% var size = result.sizes[j]; %>
16
- <li><%- size %></li>
17
- <% } %>
18
- </ul>
19
- <% } %>
20
- <% } %>
21
- </div>
22
- </div>
@@ -1,18 +0,0 @@
1
- <div class="search">
2
- <div class="loader">Loading...</div>
3
- <div class="results">
4
- <p>{{count}} results</p>
5
- {{#results}}
6
- <div class="title">{{title}}</div>
7
- <div class="description">{{description}}</div>
8
- {{#featured}}
9
- <div class="highlight">Featured!</div>
10
- {{/featured}}
11
- <ul>
12
- {{#sizes}}
13
- <li>{{.}}</li>
14
- {{/sizes}}
15
- </ul>
16
- {{/results}}
17
- </div>
18
- </div>
@@ -1,22 +0,0 @@
1
- <div class="search">
2
- <div class="loader">Loading...</div>
3
- <div class="results">
4
- <p><%- count %> results</p>
5
- <% for (var i = 0, ilen = results.length; i < ilen; i++) { %>
6
- <% var result = results[i]; %>
7
- <div class="title"><%- result.title %></div>
8
- <div class="description"><%- result.description %></div>
9
- <% if (result.featured) { %>
10
- <div class="highlight">Featured!</div>
11
- <% } %>
12
- <% if (result.sizes.length > 0) { %>
13
- <ul>
14
- <% for (var j = 0, jlen = result.sizes.length; j < jlen; j++) { %>
15
- <% var size = result.sizes[j]; %>
16
- <li><%- size %></li>
17
- <% } %>
18
- </ul>
19
- <% } %>
20
- <% } %>
21
- </div>
22
- </div>
@@ -1,26 +0,0 @@
1
- module.exports = function ({ count, results }) {
2
- let template = '<div class="search">' +
3
- '<div class="loader">Loading...</div>' +
4
- '<div class="results">' +
5
- '<p>' + count + ' results</p>'
6
-
7
- for (let i = 0, ilen = results.length; i < ilen; i++) {
8
- const result = results[i]
9
- template += '<div class="title">' + result.title + '</div>'
10
- template += '<div class="description">' + result.description + '</div>'
11
- if (result.featured) {
12
- template += '<div class="highlight">Featured!</div>'
13
- }
14
- if (result.sizes.length) {
15
- template += '<ul>'
16
- for (let j = 0, jlen = result.sizes.length; j < jlen; j += 1) {
17
- const size = result.sizes[j]
18
- template += '<li>' + size + '</li>'
19
- }
20
- template += '</ul>'
21
- }
22
- }
23
-
24
- template += '</div></div>'
25
- return template
26
- }
@@ -1,9 +0,0 @@
1
- const { h1, h2, ul, li } = require("../../..")
2
-
3
- module.exports = function ({ title, subtitle, todos }) {
4
- return [
5
- h1(title),
6
- h2(subtitle),
7
- ul(todos.map((todo) => li(todo.description))),
8
- ]
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "title": "foo",
3
- "subtitle": "baz",
4
- "todos": [
5
- { "description": "lorem ipsum" },
6
- { "description": "dolor sit" },
7
- { "description": "amet" }
8
- ]
9
- }
@@ -1,7 +0,0 @@
1
- <h1>{{title}}</h1>
2
- <h2>{{subtitle}}</h2>
3
- <ul>
4
- {{#each todos}}
5
- <li>{{this.description}}</li>
6
- {{/each}}
7
- </ul>
@@ -1,7 +0,0 @@
1
- <h1><%- title %></h1>
2
- <h2><%- subtitle %></h2>
3
- <ul>
4
- <% for(var i = 0, ilen = todos.length; i < ilen; i++) { %>
5
- <li><%- todos[i].description %></li>
6
- <% } %>
7
- </ul>
@@ -1,7 +0,0 @@
1
- <h1>{{title}}</h1>
2
- <h2>{{subtitle}}</h2>
3
- <ul>
4
- {{#todos}}
5
- <li>{{description}}</li>
6
- {{/todos}}
7
- </ul>
@@ -1,7 +0,0 @@
1
- <h1><%- title %></h1>
2
- <h2><%- subtitle %></h2>
3
- <ul>
4
- <% for(var i = 0, ilen = todos.length; i < ilen; i++) { %>
5
- <li><%- todos[i].description %></li>
6
- <% } %>
7
- </ul>
@@ -1,12 +0,0 @@
1
- module.exports = ({ title, subtitle, todos }) => {
2
- let template = ''
3
- template += '<h1>' + title + '</h1>'
4
- template += '<h2>' + subtitle + '</h2>'
5
- template += '<ul>'
6
- for (let i = 0, ilen = todos.length; i < ilen; i++) {
7
- const todo = todos[i]
8
- template += '<li>' + todo.description + '</li>'
9
- }
10
- template += '</ul>'
11
- return template
12
- }
@@ -1,112 +0,0 @@
1
- const test = require("node:test")
2
- const assert = require("node:assert")
3
- const path = require("path")
4
- const {
5
- promises: { readFile },
6
- } = require("fs")
7
- const { Suite } = require("benchmark")
8
- const underscore = require("underscore")
9
- const handlebars = require("handlebars")
10
- const mustache = require("mustache")
11
- const { compile } = require("..")
12
-
13
- async function benchmark(dir) {
14
- const source2 = await readFile(
15
- path.join(__dirname, `./fixtures/${dir}/underscore.ejs`),
16
- "utf8"
17
- )
18
- const source3 = await readFile(
19
- path.join(__dirname, `./fixtures/${dir}/lodash.ejs`),
20
- "utf8"
21
- )
22
- const source4 = await readFile(
23
- path.join(__dirname, `./fixtures/${dir}/handlebars.hbs`),
24
- "utf8"
25
- )
26
- const source5 = await readFile(
27
- path.join(__dirname, `./fixtures/${dir}/mustache.mst`),
28
- "utf8"
29
- )
30
-
31
- const suite = new Suite()
32
- const { template: fn1 } = await compile(
33
- path.join(__dirname, `./fixtures/${dir}/boxwood.js`)
34
- )
35
- const fn2 = underscore.template(source2)
36
- const fn3 = handlebars.compile(source4)
37
- const fn4 = (data) => mustache.render(source5, data)
38
- const fn5 = require(path.join(__dirname, `./fixtures/${dir}/vanilla.js`))
39
- mustache.parse(source5)
40
-
41
- const data = require(path.join(__dirname, `./fixtures/${dir}/data.json`))
42
-
43
- function normalize(string) {
44
- return string.replace(/\s/g, "")
45
- }
46
- const result = normalize(fn1(data))
47
-
48
- assert.deepEqual(result, normalize(fn1(data)))
49
- assert.deepEqual(result, normalize(fn2(data)))
50
- assert.deepEqual(result, normalize(fn3(data)))
51
- assert.deepEqual(result, normalize(fn4(data)))
52
- assert.deepEqual(result, normalize(fn5(data)))
53
-
54
- await new Promise((resolve) => {
55
- suite
56
- .add("vanilla[js]", function () {
57
- fn5(data)
58
- })
59
- .add("boxwood[js]", function () {
60
- fn1(data)
61
- })
62
- .add("underscore[ejs]", function () {
63
- fn2(data)
64
- })
65
- .add("handlebars[hbs]", function () {
66
- fn3(data)
67
- })
68
- .add("mustache[mst]", function () {
69
- fn4(data)
70
- })
71
- .on("cycle", function (event) {
72
- console.log(`${dir}: ${String(event.target)}`)
73
- })
74
- .on("complete", function () {
75
- console.log("Fastest is " + this.filter("fastest").map("name"))
76
- resolve()
77
- })
78
- .run({ async: true })
79
- })
80
- }
81
-
82
- test("benchmark: basic", async () => {
83
- await benchmark("basic")
84
- })
85
-
86
- test("benchmark: escape", async () => {
87
- await benchmark("escape")
88
- })
89
-
90
- test("benchmark: div", async () => {
91
- await benchmark("div")
92
- })
93
-
94
- test("benchmark: if", async () => {
95
- await benchmark("if")
96
- })
97
-
98
- test("benchmark: todos", async () => {
99
- await benchmark("todos")
100
- })
101
-
102
- test("benchmark: friends", async () => {
103
- await benchmark("friends")
104
- })
105
-
106
- test("benchmark: search", async () => {
107
- await benchmark("search")
108
- })
109
-
110
- test("benchmark: projects", async () => {
111
- await benchmark("projects")
112
- })