boxwood 0.75.0 → 0.76.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 CHANGED
@@ -113,17 +113,17 @@ const test = require("node:test")
113
113
  const assert = require("node:assert")
114
114
  const { compile } = require("boxwood")
115
115
 
116
- test("banner renders a title", () => {
116
+ test("banner renders a title", async () => {
117
117
  const { template } = await compile(__dirname)
118
- const html = template({ title: 'foo' })
119
- assert(html.includes('<h1>foo</h1>'))
118
+ const html = template({ title: "foo" })
119
+ assert(html.includes("<h1>foo</h1>"))
120
120
  })
121
121
 
122
- test('banner renders an optional description', () => {
122
+ test("banner renders an optional description", async () => {
123
123
  const { template } = await compile(__dirname)
124
- const html = template({ title: 'foo', description: 'bar' })
125
- assert(html.includes('<h1>foo</h1>'))
126
- assert(html.includes('<p>bar</p>'))
124
+ const html = template({ title: "foo", description: "bar" })
125
+ assert(html.includes("<h1>foo</h1>"))
126
+ assert(html.includes("<p>bar</p>"))
127
127
  })
128
128
  ```
129
129
 
@@ -1,5 +1,4 @@
1
1
  const {
2
- fragment,
3
2
  doctype,
4
3
  html,
5
4
  head,
@@ -14,7 +13,7 @@ const {
14
13
  } = require("../../..")
15
14
 
16
15
  module.exports = function ({ friends }) {
17
- return fragment([
16
+ return [
18
17
  doctype(),
19
18
  html({ lang: "en" }, [
20
19
  head([meta({ charset: "UTF-8" }), title("Friends")]),
@@ -52,5 +51,5 @@ module.exports = function ({ friends }) {
52
51
  ),
53
52
  ]),
54
53
  ]),
55
- ])
54
+ ]
56
55
  }
@@ -1,4 +1,4 @@
1
- const { fragment, div, span } = require("../../..")
1
+ const { div, span } = require("../../..")
2
2
 
3
3
  function description(account) {
4
4
  if (account.status === "closed") {
@@ -17,5 +17,5 @@ function description(account) {
17
17
  }
18
18
 
19
19
  module.exports = function ({ accounts }) {
20
- return fragment(accounts.map((account) => div(description(account))))
20
+ return accounts.map((account) => div(description(account)))
21
21
  }
@@ -1,18 +1,16 @@
1
- const { fragment, div, ul, li, p } = require("../../..")
1
+ const { div, ul, li, p } = require("../../..")
2
2
 
3
3
  module.exports = function ({ count, results }) {
4
4
  return div({ class: "search" }, [
5
5
  div({ class: "loader" }, "Loading..."),
6
6
  div({ class: "results" }, [
7
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
- ),
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
+ ]),
16
14
  ]),
17
15
  ])
18
16
  }
@@ -1,9 +1,9 @@
1
- const { h1, h2, ul, li, fragment } = require("../../..")
1
+ const { h1, h2, ul, li } = require("../../..")
2
2
 
3
3
  module.exports = function ({ title, subtitle, todos }) {
4
- return fragment([
4
+ return [
5
5
  h1(title),
6
6
  h2(subtitle),
7
7
  ul(todos.map((todo) => li(todo.description))),
8
- ])
8
+ ]
9
9
  }
package/index.js CHANGED
@@ -2,7 +2,6 @@ const { join } = require("path")
2
2
  const { readFileSync } = require("fs")
3
3
  const csstree = require("css-tree")
4
4
  const toHash = require("string-hash")
5
- const YAML = require("yaml")
6
5
 
7
6
  async function compile(path) {
8
7
  const fn = require(path)
@@ -175,7 +174,7 @@ const isUnescapedTag = (name) => {
175
174
  }
176
175
 
177
176
  const render = (input, escape = true) => {
178
- if (input.ignore) {
177
+ if (!input || input.ignore) {
179
178
  return ""
180
179
  }
181
180
  if (Array.isArray(input)) {
@@ -188,10 +187,10 @@ const render = (input, escape = true) => {
188
187
  return input.toString()
189
188
  }
190
189
  if (typeof input === "string") {
191
- return escape ? escapeHTML(input) : input
192
- }
193
- if (input.name === "fragment") {
194
- return render(input.children)
190
+ if (escape) {
191
+ return escapeHTML(input)
192
+ }
193
+ return input
195
194
  }
196
195
  if (input.name === "raw") {
197
196
  return render(input.children, false)
@@ -202,32 +201,14 @@ const render = (input, escape = true) => {
202
201
  }
203
202
  return `<${input.name}>`
204
203
  }
205
- if (input.attributes && input.children) {
206
- return (
207
- `<${input.name} ` +
208
- attributes(input.attributes) +
209
- ">" +
210
- render(input.children, isUnescapedTag(input.name)) +
211
- `</${input.name}>`
212
- )
213
- }
214
- if (input.attributes) {
215
- return (
216
- `<${input.name} ` + attributes(input.attributes) + `></${input.name}>`
217
- )
218
- }
219
- if (input.children) {
220
- return (
221
- `<${input.name}>` +
222
- render(input.children, isUnescapedTag(input.name)) +
223
- `</${input.name}>`
224
- )
225
- }
226
- return `<${input.name}></${input.name}>`
227
- }
228
204
 
229
- const fragment = (children) => {
230
- return { name: "fragment", children }
205
+ return (
206
+ `<${input.name}` +
207
+ (input.attributes ? " " + attributes(input.attributes) : "") +
208
+ ">" +
209
+ render(input.children, isUnescapedTag(input.name)) +
210
+ `</${input.name}>`
211
+ )
231
212
  }
232
213
 
233
214
  const raw = (children) => {
@@ -504,15 +485,6 @@ function classes() {
504
485
  return array.join(" ")
505
486
  }
506
487
 
507
- const yaml = {
508
- load() {
509
- const path = join(...arguments)
510
- const file = path.endsWith(".yaml") ? path : join(path, "index.yaml")
511
- const content = readFileSync(file, "utf8")
512
- return YAML.parse(content)
513
- },
514
- }
515
-
516
488
  const json = {
517
489
  load() {
518
490
  const path = join(...arguments)
@@ -530,23 +502,20 @@ function i18n(translations) {
530
502
 
531
503
  i18n.load = function () {
532
504
  const path = join(...arguments)
533
- const data = path.endsWith(".yaml") ? yaml.load(path) : json.load(path)
505
+ const data = json.load(path)
534
506
  return function translate(language, key) {
535
- if (!key) {
536
- throw new Error(`TranslationError[${key}][${language}]: key is undefined`)
537
- }
538
507
  if (!language) {
539
- throw new Error(
540
- `TranslationError[${key}][${language}]: language is undefined`
541
- )
508
+ throw new Error(`TranslationError: language is undefined`)
509
+ }
510
+ if (!key) {
511
+ throw new Error(`TranslationError: key is undefined`)
542
512
  }
543
- const translation = data[key][language]
544
- if (!translation) {
513
+ if (!data[key] || !data[key][language]) {
545
514
  throw new Error(
546
- `TranslationError[${key}][${language}]: translation is undefined`
515
+ `TranslationError: translation [${key}][${language}] is undefined`
547
516
  )
548
517
  }
549
- return translation
518
+ return data[key][language]
550
519
  }
551
520
  }
552
521
 
@@ -556,24 +525,24 @@ function component(fn, { styles, i18n, scripts } = {}) {
556
525
  return fn({}, a)
557
526
  }
558
527
  if (i18n) {
528
+ if (!a || !a.language) {
529
+ throw new Error(
530
+ `TranslationError: language is undefined for component:\n${fn.toString()}`
531
+ )
532
+ }
559
533
  const { language } = a
560
534
  function translate(key) {
561
535
  if (!key) {
562
536
  throw new Error(
563
- `TranslationError[${key}][${language}]: key is undefined for component:\n${fn.toString()}`
537
+ `TranslationError: key is undefined for component:\n${fn.toString()}`
564
538
  )
565
539
  }
566
- if (!language) {
540
+ if (!i18n[key] || !i18n[key][language]) {
567
541
  throw new Error(
568
- `TranslationError[${key}][${language}]: language is undefined for component:\n${fn.toString()}`
542
+ `TranslationError: translation [${key}][${language}] is undefined for component:\n${fn.toString()}`
569
543
  )
570
544
  }
571
545
  const translation = i18n[key][language]
572
- if (!translation) {
573
- throw new Error(
574
- `TranslationError[${key}][${language}]: translation is undefined for component:\n${fn.toString()}`
575
- )
576
- }
577
546
  return translation
578
547
  }
579
548
  return fn({ ...a, translate }, b || [])
@@ -582,25 +551,19 @@ function component(fn, { styles, i18n, scripts } = {}) {
582
551
  }
583
552
  return function (a, b) {
584
553
  const tree = execute(a, b)
585
- if (styles && scripts) {
586
- if (Array.isArray(tree)) {
587
- return tree.concat(styles.css, scripts.js)
588
- }
589
- return [tree, styles.css, scripts.js]
590
- }
554
+ let nodes = Array.isArray(tree) ? tree : [tree]
555
+
591
556
  if (styles) {
592
- if (Array.isArray(tree)) {
593
- return tree.concat(styles.css)
594
- }
595
- return [tree, styles.css]
557
+ const data = Array.isArray(styles) ? styles : [styles]
558
+ nodes = nodes.concat(data.map((style) => style.css))
596
559
  }
560
+
597
561
  if (scripts) {
598
- if (Array.isArray(tree)) {
599
- return tree.concat(scripts.js)
600
- }
601
- return [tree, scripts.js]
562
+ const data = Array.isArray(scripts) ? scripts : [scripts]
563
+ nodes = nodes.concat(data.map((script) => script.js))
602
564
  }
603
- return tree
565
+
566
+ return nodes
604
567
  }
605
568
  }
606
569
 
@@ -610,11 +573,9 @@ module.exports = {
610
573
  classes,
611
574
  doctype,
612
575
  escape: escapeHTML,
613
- fragment,
614
576
  raw,
615
577
  css,
616
578
  js,
617
- yaml,
618
579
  json,
619
580
  tag,
620
581
  i18n,
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "boxwood",
3
- "version": "0.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "Compile HTML templates into JS",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node --test",
7
+ "test": "node --test --test-reporter=dot",
8
+ "test:debug": "node --test --test-reporter=spec",
8
9
  "coverage": "c8 npm test",
9
10
  "benchmark": "node --test benchmark/index.js",
10
11
  "watch": "npm test -- --watch",
@@ -62,7 +63,6 @@
62
63
  },
63
64
  "dependencies": {
64
65
  "css-tree": "^2.3.1",
65
- "string-hash": "^1.1.3",
66
- "yaml": "^2.4.2"
66
+ "string-hash": "^1.1.3"
67
67
  }
68
68
  }