@zubra/unplugin 5.2.0 → 5.4.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
@@ -103,6 +103,10 @@ In Vite's dev server, editing a component **updates it in place**: the elements
103
103
 
104
104
  Components that import the edited one are recompiled too. Other bundlers' watch modes (Rollup, webpack) recompile on change.
105
105
 
106
+ The dev server also compiles each component for the **Zubra DevTools** (`--devtools`): select a node in the browser's Elements panel and the Zubra pane shows its component's `.zb` file and line, its props and state, and each binding's line and the signals it reads (see `editors/devtools`). Builds carry none of it.
107
+
108
+ To use the DevTools on a build too (a demo, a staging or preview deploy), pass `zubra({ devtools: true })` or set `ZUBRA_DEVTOOLS=1`: components are compiled the same way and `@zubra/runtime` resolves to its development build, which has the hook. It costs some bytes, so production builds leave it off by default.
109
+
106
110
  ## Tests
107
111
 
108
112
  `npm test` builds real React, Vue and plain Vite apps, runs them in Chromium, type-checks the generated typings with TypeScript, and checks the dev server, `build --watch` and error reporting. It needs a Rust toolchain (the compiler is built from this repository) and Playwright with Chromium.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zubra/unplugin",
3
- "version": "5.2.0",
3
+ "version": "5.4.0",
4
4
  "description": "Compile .zb components in Vite, Rollup, webpack, esbuild and Rspack, with React and Vue wrappers picked automatically",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -34,8 +34,8 @@
34
34
  "unplugin": "3.7.0"
35
35
  },
36
36
  "peerDependencies": {
37
- "@zubra/compiler": "^5.2.0",
38
- "@zubra/runtime": "^5.2.0"
37
+ "@zubra/compiler": "^5.4.0",
38
+ "@zubra/runtime": "^5.4.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@zubra/compiler": "file:../compiler",
package/src/index.js CHANGED
@@ -26,6 +26,7 @@ import { spawnSync } from 'node:child_process';
26
26
  import { readFileSync, writeFileSync, existsSync, statSync } from 'node:fs';
27
27
  import { addProps, zubraImports } from './props.js';
28
28
  import { basename, dirname, extname, relative, resolve, sep } from 'node:path';
29
+ import { createRequire } from 'node:module';
29
30
 
30
31
  const VARIANTS = ['element', 'react', 'vue'];
31
32
  /** A component file: `.zb`, or a JSX component (`.zb.jsx` / `.zb.tsx`). */
@@ -139,6 +140,10 @@ export const unplugin = createUnplugin((options = {}, meta = {}) => {
139
140
  const relativePath = (path) => path.startsWith(process.cwd()) ? path.slice(process.cwd().length + 1) : path;
140
141
  const compilerModule = options.compilerModule ?? '@zubra/compiler';
141
142
  let dev = false; // Vite's dev server: components hot-reload
143
+ // The Zubra DevTools in a build, not only in Vite's dev server: components compiled with
144
+ // --devtools, and @zubra/runtime's development build (which has the hook) instead of its
145
+ // production one. For demos, staging and previews; it costs bytes, so it's opt-in.
146
+ const devtoolsInBuilds = options.devtools ?? process.env.ZUBRA_DEVTOOLS === '1';
142
147
 
143
148
  /** CLI flags → a request for the WebAssembly compiler. */
144
149
  function asRequest(args) {
@@ -147,6 +152,7 @@ export const unplugin = createUnplugin((options = {}, meta = {}) => {
147
152
  const flag = args[i];
148
153
  if (flag === '--keep-imports') request.keepImports = true;
149
154
  else if (flag === '--no-imports') request.noImports = true;
155
+ else if (flag === '--devtools') request.devtools = true;
150
156
  else {
151
157
  const key = { '--emit': 'emit', '--framework': 'framework', '--runtime': 'runtime', '--css-import': 'cssImport', '--css-import-inline': 'cssImportInline' }[flag];
152
158
  if (!key) throw new Error(`zubra: unexpected compiler flag ${flag}`);
@@ -223,6 +229,14 @@ export const unplugin = createUnplugin((options = {}, meta = {}) => {
223
229
  },
224
230
 
225
231
  async resolveId(source, importer) {
232
+ // With devtools in builds: @zubra/runtime's development build, wherever it's imported from.
233
+ if (devtoolsInBuilds && /^@zubra\/runtime(\/|$)/.test(source)) {
234
+ const resolved = await this.resolve?.(source, importer, { skipSelf: true });
235
+ if (resolved && /[\\/]dist[\\/]production[\\/]/.test(resolved.id)) {
236
+ return { ...resolved, id: resolved.id.replace(/([\\/])dist[\\/]production([\\/])/, '$1src$2') };
237
+ }
238
+ return resolved;
239
+ }
226
240
  const [specifier, query] = split(source);
227
241
  if (!COMPONENT.test(specifier)) return null;
228
242
  let path;
@@ -292,11 +306,23 @@ export const unplugin = createUnplugin((options = {}, meta = {}) => {
292
306
  }
293
307
  let output;
294
308
  try {
295
- output = compile(path, '--emit', 'js', '--keep-imports', '--runtime', runtime, ...styles);
309
+ // In Vite's dev server, what the browser DevTools panel reads: each part's place in the
310
+ // `.zb` file and the script's signals by name (the runtime's development build reads them).
311
+ const devtools = ((dev && meta.framework === 'vite') || devtoolsInBuilds) && !server ? ['--devtools'] : [];
312
+ output = compile(path, '--emit', 'js', '--keep-imports', '--runtime', runtime, ...styles, ...devtools);
296
313
  } catch (error) {
297
314
  return fail(this, error, path);
298
315
  }
299
316
  if (output.warnings) this.warn(output.warnings);
317
+ // 'use collection' compiles to an import of @zubra/sync: say what to install, rather than
318
+ // leave the bundler to report an unresolved import.
319
+ if (output.code.includes('from "@zubra/sync"')) {
320
+ try {
321
+ createRequire(path).resolve('@zubra/sync');
322
+ } catch {
323
+ return fail(this, new Error(`${relativePath(path)} starts with 'use collection', which needs @zubra/sync. Install it: npm install @zubra/sync`), path);
324
+ }
325
+ }
300
326
  if (server) return serverRendering ? output.code + serverRenderer(path, compilerModule, runtime) : output.code;
301
327
  return dev && meta.framework === 'vite' ? hot(output.code) : output.code;
302
328
  },