boxwood 0.74.0 → 0.74.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/benchmark/fixtures/basic/boxwood.js +3 -0
- package/benchmark/fixtures/basic/data.json +1 -0
- package/benchmark/fixtures/basic/handlebars.hbs +1 -0
- package/benchmark/fixtures/basic/lodash.ejs +1 -0
- package/benchmark/fixtures/basic/mustache.mst +1 -0
- package/benchmark/fixtures/basic/underscore.ejs +1 -0
- package/benchmark/fixtures/basic/vanilla.js +3 -0
- package/benchmark/fixtures/div/boxwood.js +5 -0
- package/benchmark/fixtures/div/data.json +1 -0
- package/benchmark/fixtures/div/handlebars.hbs +1 -0
- package/benchmark/fixtures/div/lodash.ejs +1 -0
- package/benchmark/fixtures/div/mustache.mst +1 -0
- package/benchmark/fixtures/div/underscore.ejs +1 -0
- package/benchmark/fixtures/div/vanilla.js +4 -0
- package/benchmark/fixtures/escape/boxwood.js +3 -0
- package/benchmark/fixtures/escape/data.json +3 -0
- package/benchmark/fixtures/escape/handlebars.hbs +1 -0
- package/benchmark/fixtures/escape/lodash.ejs +1 -0
- package/benchmark/fixtures/escape/mustache.mst +1 -0
- package/benchmark/fixtures/escape/underscore.ejs +1 -0
- package/benchmark/fixtures/escape/vanilla.js +5 -0
- package/benchmark/fixtures/friends/boxwood.js +56 -0
- package/benchmark/fixtures/friends/data.json +30 -0
- package/benchmark/fixtures/friends/handlebars.hbs +45 -0
- package/benchmark/fixtures/friends/lodash.ejs +48 -0
- package/benchmark/fixtures/friends/mustache.mst +45 -0
- package/benchmark/fixtures/friends/underscore.ejs +48 -0
- package/benchmark/fixtures/friends/vanilla.js +36 -0
- package/benchmark/fixtures/if/boxwood.js +21 -0
- package/benchmark/fixtures/if/data.json +12 -0
- package/benchmark/fixtures/if/handlebars.hbs +13 -0
- package/benchmark/fixtures/if/lodash.ejs +12 -0
- package/benchmark/fixtures/if/mustache.mst +13 -0
- package/benchmark/fixtures/if/underscore.ejs +12 -0
- package/benchmark/fixtures/if/vanilla.js +14 -0
- package/benchmark/fixtures/projects/boxwood.js +20 -0
- package/benchmark/fixtures/projects/data.json +26 -0
- package/benchmark/fixtures/projects/handlebars.hbs +15 -0
- package/benchmark/fixtures/projects/lodash.ejs +17 -0
- package/benchmark/fixtures/projects/mustache.mst +16 -0
- package/benchmark/fixtures/projects/underscore.ejs +17 -0
- package/benchmark/fixtures/projects/vanilla.js +21 -0
- package/benchmark/fixtures/search/boxwood.js +18 -0
- package/benchmark/fixtures/search/data.json +35 -0
- package/benchmark/fixtures/search/handlebars.hbs +18 -0
- package/benchmark/fixtures/search/lodash.ejs +22 -0
- package/benchmark/fixtures/search/mustache.mst +18 -0
- package/benchmark/fixtures/search/underscore.ejs +22 -0
- package/benchmark/fixtures/search/vanilla.js +26 -0
- package/benchmark/fixtures/todos/boxwood.js +9 -0
- package/benchmark/fixtures/todos/data.json +9 -0
- package/benchmark/fixtures/todos/handlebars.hbs +7 -0
- package/benchmark/fixtures/todos/lodash.ejs +7 -0
- package/benchmark/fixtures/todos/mustache.mst +7 -0
- package/benchmark/fixtures/todos/underscore.ejs +7 -0
- package/benchmark/fixtures/todos/vanilla.js +12 -0
- package/benchmark/index.js +118 -0
- package/package.json +10 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div>foo</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div>foo</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div>foo</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div>foo</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{foo}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%- foo %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{foo}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%- foo %>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const {
|
|
2
|
+
fragment,
|
|
3
|
+
doctype,
|
|
4
|
+
html,
|
|
5
|
+
head,
|
|
6
|
+
body,
|
|
7
|
+
meta,
|
|
8
|
+
img,
|
|
9
|
+
title,
|
|
10
|
+
div,
|
|
11
|
+
ul,
|
|
12
|
+
li,
|
|
13
|
+
a,
|
|
14
|
+
} = require("../../..")
|
|
15
|
+
|
|
16
|
+
module.exports = function ({ friends }) {
|
|
17
|
+
return fragment([
|
|
18
|
+
doctype(),
|
|
19
|
+
html({ lang: "en" }, [
|
|
20
|
+
head([meta({ charset: "UTF-8" }), title("Friends")]),
|
|
21
|
+
body([
|
|
22
|
+
div(
|
|
23
|
+
{ class: "friends" },
|
|
24
|
+
friends.map((friend) => {
|
|
25
|
+
return div({ class: "friend" }, [
|
|
26
|
+
ul([
|
|
27
|
+
li(`Name: ${friend.name}`),
|
|
28
|
+
li(`Balance: ${friend.balance}`),
|
|
29
|
+
li(`Age: ${friend.age}`),
|
|
30
|
+
li(`Address: ${friend.address}`),
|
|
31
|
+
li(["Image: ", img({ src: friend.picture })]),
|
|
32
|
+
li(`Company: ${friend.company}`),
|
|
33
|
+
li([
|
|
34
|
+
"Email: ",
|
|
35
|
+
a({ href: `mailto:${friend.email}` }, friend.email),
|
|
36
|
+
]),
|
|
37
|
+
li(`About: ${friend.about}`),
|
|
38
|
+
friend.tags.length &&
|
|
39
|
+
li(["Tags: ", ul(friend.tags.map((tag) => li(tag)))]),
|
|
40
|
+
friend.friends.length &&
|
|
41
|
+
li([
|
|
42
|
+
"Friends: ",
|
|
43
|
+
ul(
|
|
44
|
+
friend.friends.map((friend) =>
|
|
45
|
+
li(`${friend.name} (${friend.id})`)
|
|
46
|
+
)
|
|
47
|
+
),
|
|
48
|
+
]),
|
|
49
|
+
]),
|
|
50
|
+
])
|
|
51
|
+
})
|
|
52
|
+
),
|
|
53
|
+
]),
|
|
54
|
+
]),
|
|
55
|
+
])
|
|
56
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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>
|
|
@@ -0,0 +1,48 @@
|
|
|
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>
|
|
@@ -0,0 +1,45 @@
|
|
|
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>
|
|
@@ -0,0 +1,48 @@
|
|
|
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>
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { fragment, 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 fragment(accounts.map((account) => div(description(account))))
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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}}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
<% } %>
|
|
@@ -0,0 +1,13 @@
|
|
|
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}}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
<% } %>
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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>
|
|
@@ -0,0 +1,17 @@
|
|
|
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>
|
|
@@ -0,0 +1,16 @@
|
|
|
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>
|
|
@@ -0,0 +1,17 @@
|
|
|
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>
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { fragment, 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
|
+
fragment([
|
|
10
|
+
div({ class: "title" }, result.title),
|
|
11
|
+
div({ class: "description" }, result.description),
|
|
12
|
+
result.featured && div({ class: "highlight" }, "Featured!"),
|
|
13
|
+
result.sizes.length && ul(result.sizes.map((size) => li(size))),
|
|
14
|
+
])
|
|
15
|
+
),
|
|
16
|
+
]),
|
|
17
|
+
])
|
|
18
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
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>
|
|
@@ -0,0 +1,22 @@
|
|
|
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>
|
|
@@ -0,0 +1,18 @@
|
|
|
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>
|
|
@@ -0,0 +1,22 @@
|
|
|
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>
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
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 template = require("lodash.template")
|
|
10
|
+
const handlebars = require("handlebars")
|
|
11
|
+
const mustache = require("mustache")
|
|
12
|
+
const { compile } = require("..")
|
|
13
|
+
|
|
14
|
+
async function benchmark(dir) {
|
|
15
|
+
const source2 = await readFile(
|
|
16
|
+
path.join(__dirname, `./fixtures/${dir}/underscore.ejs`),
|
|
17
|
+
"utf8"
|
|
18
|
+
)
|
|
19
|
+
const source3 = await readFile(
|
|
20
|
+
path.join(__dirname, `./fixtures/${dir}/lodash.ejs`),
|
|
21
|
+
"utf8"
|
|
22
|
+
)
|
|
23
|
+
const source4 = await readFile(
|
|
24
|
+
path.join(__dirname, `./fixtures/${dir}/handlebars.hbs`),
|
|
25
|
+
"utf8"
|
|
26
|
+
)
|
|
27
|
+
const source5 = await readFile(
|
|
28
|
+
path.join(__dirname, `./fixtures/${dir}/mustache.mst`),
|
|
29
|
+
"utf8"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const suite = new Suite()
|
|
33
|
+
const { template: fn1 } = await compile(
|
|
34
|
+
path.join(__dirname, `./fixtures/${dir}/boxwood.js`)
|
|
35
|
+
)
|
|
36
|
+
const fn2 = underscore.template(source2)
|
|
37
|
+
const fn3 = template(source3)
|
|
38
|
+
const fn4 = handlebars.compile(source4)
|
|
39
|
+
const fn5 = (data) => mustache.render(source5, data)
|
|
40
|
+
const fn6 = require(path.join(__dirname, `./fixtures/${dir}/vanilla.js`))
|
|
41
|
+
mustache.parse(source5)
|
|
42
|
+
|
|
43
|
+
const data = require(path.join(__dirname, `./fixtures/${dir}/data.json`))
|
|
44
|
+
|
|
45
|
+
function normalize(string) {
|
|
46
|
+
return string.replace(/\s/g, "")
|
|
47
|
+
}
|
|
48
|
+
const result = normalize(fn1(data))
|
|
49
|
+
|
|
50
|
+
assert.deepEqual(result, normalize(fn1(data)))
|
|
51
|
+
assert.deepEqual(result, normalize(fn2(data)))
|
|
52
|
+
assert.deepEqual(result, normalize(fn3(data)))
|
|
53
|
+
assert.deepEqual(result, normalize(fn4(data)))
|
|
54
|
+
assert.deepEqual(result, normalize(fn5(data)))
|
|
55
|
+
assert.deepEqual(result, normalize(fn6(data)))
|
|
56
|
+
|
|
57
|
+
await new Promise((resolve) => {
|
|
58
|
+
suite
|
|
59
|
+
.add("vanilla[js]", function () {
|
|
60
|
+
fn6(data)
|
|
61
|
+
})
|
|
62
|
+
.add("boxwood[js]", function () {
|
|
63
|
+
fn1(data)
|
|
64
|
+
})
|
|
65
|
+
.add("underscore[ejs]", function () {
|
|
66
|
+
fn2(data)
|
|
67
|
+
})
|
|
68
|
+
.add("lodash[ejs]", function () {
|
|
69
|
+
fn3(data)
|
|
70
|
+
})
|
|
71
|
+
.add("handlebars[hbs]", function () {
|
|
72
|
+
fn4(data)
|
|
73
|
+
})
|
|
74
|
+
.add("mustache[mst]", function () {
|
|
75
|
+
fn5(data)
|
|
76
|
+
})
|
|
77
|
+
.on("cycle", function (event) {
|
|
78
|
+
console.log(`${dir}: ${String(event.target)}`)
|
|
79
|
+
})
|
|
80
|
+
.on("complete", function () {
|
|
81
|
+
console.log("Fastest is " + this.filter("fastest").map("name"))
|
|
82
|
+
resolve()
|
|
83
|
+
})
|
|
84
|
+
.run({ async: true })
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
test("benchmark: basic", async () => {
|
|
89
|
+
await benchmark("basic")
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test("benchmark: escape", async () => {
|
|
93
|
+
await benchmark("escape")
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test("benchmark: div", async () => {
|
|
97
|
+
await benchmark("div")
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test("benchmark: if", async () => {
|
|
101
|
+
await benchmark("if")
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test("benchmark: todos", async () => {
|
|
105
|
+
await benchmark("todos")
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test("benchmark: friends", async () => {
|
|
109
|
+
await benchmark("friends")
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test("benchmark: search", async () => {
|
|
113
|
+
await benchmark("search")
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test("benchmark: projects", async () => {
|
|
117
|
+
await benchmark("projects")
|
|
118
|
+
})
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "boxwood",
|
|
3
|
-
"version": "0.74.
|
|
3
|
+
"version": "0.74.1",
|
|
4
4
|
"description": "Compile HTML templates into JS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"coverage": "
|
|
9
|
-
"benchmark": "
|
|
7
|
+
"test": "node --test",
|
|
8
|
+
"coverage": "c8 npm test",
|
|
9
|
+
"benchmark": "node --test benchmark/index.js",
|
|
10
10
|
"watch": "npm test -- --watch",
|
|
11
11
|
"prepush": "npm test"
|
|
12
12
|
},
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
]
|
|
18
18
|
},
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">= 20.11.1"
|
|
21
21
|
},
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
},
|
|
46
46
|
"homepage": "https://github.com/buxlabs/boxwood#readme",
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"ava": "^
|
|
48
|
+
"ava": "^6.1.2",
|
|
49
49
|
"benchmark": "2.1.4",
|
|
50
|
-
"
|
|
50
|
+
"c8": "^9.1.0",
|
|
51
|
+
"express": "^4.19.2",
|
|
51
52
|
"handlebars": "^4.7.8",
|
|
52
|
-
"jsdom": "^
|
|
53
|
+
"jsdom": "^24.0.0",
|
|
53
54
|
"lodash.template": "4.5.0",
|
|
54
55
|
"mustache": "^4.2.0",
|
|
55
|
-
"nyc": "15.1.0",
|
|
56
56
|
"underscore": "^1.13.6"
|
|
57
57
|
},
|
|
58
58
|
"standard": {
|
|
@@ -65,6 +65,6 @@
|
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"css-tree": "^2.3.1",
|
|
67
67
|
"string-hash": "^1.1.3",
|
|
68
|
-
"yaml": "^2.
|
|
68
|
+
"yaml": "^2.4.1"
|
|
69
69
|
}
|
|
70
70
|
}
|