@barefootjs/cli 0.4.0 → 0.5.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.
@@ -251,6 +251,17 @@ Client components register their scripts via the `.Scripts` interface:
251
251
  The `ScriptCollector` tracks needed scripts and renders `<script>` tags at page end. Each script loads at most once.
252
252
 
253
253
 
254
+ ## Importmap (externals)
255
+
256
+ This adapter sets `importMapInjection: 'html-snippet'`, so when you configure [`externals`](../advanced/code-splitting.md), `bf build` emits a ready-to-include `barefoot-importmap.html` next to `barefoot-externals.json`. Parse the build output directory into your template set and include the snippet in your page `<head>`:
257
+
258
+ ```go-template
259
+ {{ template "barefoot-importmap.html" . }}
260
+ ```
261
+
262
+ See [Code splitting & externals](../advanced/code-splitting.md#template-string-adapters) for what the snippet contains and how the manifest is generated.
263
+
264
+
254
265
  ## Go Helper Functions
255
266
 
256
267
  These helper functions must be in the Go template `FuncMap`:
@@ -113,6 +113,21 @@ export const renderer = jsxRenderer(({ children }) => (
113
113
  ))
114
114
  ```
115
115
 
116
+ ## Template-string adapters
117
+
118
+ Some adapters have no render-time component like Hono's `BfImportMap` to read the manifest — they target a template-string language where you hand-write the HTML `<head>`. An adapter declares this by setting `importMapInjection: 'html-snippet'` (component-based adapters set `'component'` instead). For `html-snippet` adapters, `bf build` also emits a ready-to-include **`barefoot-importmap.html`** snippet next to `barefoot-externals.json`, generated from the same manifest:
119
+
120
+ ```html
121
+ <!-- dist/barefoot-importmap.html -->
122
+ <script type="importmap">{"imports":{"@barefootjs/client":"/static/components/barefoot.js","yjs":"/static/components/yjs.js","lodash":"https://esm.sh/lodash@4.17.21"}}</script>
123
+ <link rel="modulepreload" href="/static/components/yjs.js" crossorigin>
124
+ <link rel="modulepreload" href="https://esm.sh/lodash@4.17.21" crossorigin>
125
+ ```
126
+
127
+ Include this file in your page `<head>` using your template language's native include directive, and wire the build's output directory into the template search path so it resolves. The exact directive is language-specific — see your adapter's own documentation for the form it uses.
128
+
129
+ Which strategy an adapter uses is the single source of truth in its `TemplateAdapter.importMapInjection` value, enforced for every adapter by the cross-adapter importmap-injection contract in `@barefootjs/adapter-tests` — so this page does not need an entry per adapter.
130
+
116
131
  ## Using the externals list in your own bun build
117
132
 
118
133
  The `externals` array in `barefoot-externals.json` lists every package that the browser will load via the importmap. Pass these as `--external` flags when bundling your app entries:
@@ -64,9 +64,19 @@ return <div>...</div>
64
64
  {items().filter(x => x.active).sort((a, b) => a.name.localeCompare(b.name)).map(item => (
65
65
  <Item key={item.id} item={item} />
66
66
  ))}
67
+
68
+ // ✅ Multi-key: sort by price, break ties by name
69
+ {items().sort((a, b) => a.price - b.price || a.name.localeCompare(b.name)).map(item => (
70
+ <Item key={item.id} item={item} />
71
+ ))}
72
+
73
+ // ✅ Relational ternary
74
+ {items().toSorted((a, b) => a.price > b.price ? 1 : -1).map(item => (
75
+ <Item key={item.id} item={item} />
76
+ ))}
67
77
  ```
68
78
 
69
- Supported comparator shapes: `(a, b) => a - b`, `(a, b) => a.field - b.field`, `(a, b) => a.localeCompare(b)`, `(a, b) => a.field.localeCompare(b.field)` (reverse the operands for descending order). Other shapes — block bodies, ternary returns, custom helpers — produce a compile error; use `/* @client */` in that case.
79
+ Supported comparator shapes: `(a, b) => a - b`, `(a, b) => a.field - b.field`, `(a, b) => a.localeCompare(b)`, `(a, b) => a.field.localeCompare(b.field)`, relational-ternary returns (`(a, b) => a.field > b.field ? 1 : -1`, including the 3-way `a < b ? -1 : a > b ? 1 : 0` form), and any of these `||`-chained for multi-key tie-breaks. A single-`return` block body (`(a, b) => { return a.field - b.field }`) works too. Reverse the operands (or the ternary sign) for descending order. Other shapes — function references (`sort(myCmp)`), multi-statement block bodies, and `localeCompare(b, locale, opts)` — produce a compile error; use `/* @client */` in that case.
70
80
 
71
81
 
72
82
  ## Event Handling
@@ -97,7 +107,7 @@ Some JavaScript expressions cannot be translated into marked template syntax. Wh
97
107
  | `.filter()` with `function` keyword callback | works | **BF101** |
98
108
  | `.reduce()`, `.forEach()`, `.flatMap()` | works | **BF101** |
99
109
  | Nested higher-order in filter predicate (`x => x.tags.filter(...).length > 0`) | works | **BF101** |
100
- | Sort comparator with a block body, ternary return, or other unsupported shape | **BF021** (all adapters) | **BF021** |
110
+ | Sort comparator that's a function reference, multi-statement block body, or `localeCompare(b, locale, opts)` | **BF021** (all adapters) | **BF021** |
101
111
  | `typeof` in a filter predicate | **BF021** (all adapters) | **BF021** |
102
112
 
103
113
  `BF021` is raised at the IR layer and applies to every adapter. `BF101` is raised by adapters that can't lower the expression to their template language. Either way, add [`/* @client */`](./client-directive.md) to opt into client-only evaluation and suppress the error.
@@ -146,16 +156,16 @@ Some JavaScript expressions cannot be translated into marked template syntax. Wh
146
156
 
147
157
  ### Patterns that error on all adapters
148
158
 
149
- **Unsupported sort comparators** (block bodies, ternary returns):
159
+ **Unsupported sort comparators** (multi-statement block bodies, function references):
150
160
 
151
161
  ```tsx
152
162
  // ❌ BF021 (all adapters)
153
- {items().sort((a, b) => a.name > b.name ? 1 : -1).map(item => (
163
+ {items().sort((a, b) => { const an = a.name; return an > b.name ? 1 : -1 }).map(item => (
154
164
  <Item key={item.id} item={item} />
155
165
  ))}
156
166
 
157
167
  // ✅ Use /* @client */
158
- {/* @client */ items().sort((a, b) => a.name > b.name ? 1 : -1).map(item => (
168
+ {/* @client */ items().sort((a, b) => { const an = a.name; return an > b.name ? 1 : -1 }).map(item => (
159
169
  <Item key={item.id} item={item} />
160
170
  ))}
161
171
  ```