zero-query 0.9.9 → 1.0.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.
Files changed (97) hide show
  1. package/README.md +33 -32
  2. package/cli/args.js +1 -1
  3. package/cli/commands/build.js +2 -2
  4. package/cli/commands/bundle.js +15 -15
  5. package/cli/commands/create.js +2 -2
  6. package/cli/commands/dev/devtools/index.js +1 -1
  7. package/cli/commands/dev/devtools/js/core.js +14 -14
  8. package/cli/commands/dev/devtools/js/elements.js +4 -4
  9. package/cli/commands/dev/devtools/js/stats.js +1 -1
  10. package/cli/commands/dev/devtools/styles.css +2 -2
  11. package/cli/commands/dev/index.js +2 -2
  12. package/cli/commands/dev/logger.js +1 -1
  13. package/cli/commands/dev/overlay.js +21 -14
  14. package/cli/commands/dev/server.js +5 -5
  15. package/cli/commands/dev/validator.js +7 -7
  16. package/cli/commands/dev/watcher.js +6 -6
  17. package/cli/help.js +3 -3
  18. package/cli/index.js +2 -2
  19. package/cli/scaffold/default/app/app.js +17 -18
  20. package/cli/scaffold/default/app/components/about.js +9 -9
  21. package/cli/scaffold/default/app/components/api-demo.js +6 -6
  22. package/cli/scaffold/default/app/components/contact-card.js +4 -4
  23. package/cli/scaffold/default/app/components/contacts/contacts.css +2 -2
  24. package/cli/scaffold/default/app/components/contacts/contacts.html +3 -3
  25. package/cli/scaffold/default/app/components/contacts/contacts.js +11 -11
  26. package/cli/scaffold/default/app/components/counter.js +8 -8
  27. package/cli/scaffold/default/app/components/home.js +13 -13
  28. package/cli/scaffold/default/app/components/not-found.js +1 -1
  29. package/cli/scaffold/default/app/components/playground/playground.css +1 -1
  30. package/cli/scaffold/default/app/components/playground/playground.html +11 -11
  31. package/cli/scaffold/default/app/components/playground/playground.js +11 -11
  32. package/cli/scaffold/default/app/components/todos.js +8 -8
  33. package/cli/scaffold/default/app/components/toolkit/toolkit.css +1 -1
  34. package/cli/scaffold/default/app/components/toolkit/toolkit.html +4 -4
  35. package/cli/scaffold/default/app/components/toolkit/toolkit.js +7 -7
  36. package/cli/scaffold/default/app/routes.js +1 -1
  37. package/cli/scaffold/default/app/store.js +1 -1
  38. package/cli/scaffold/default/global.css +2 -2
  39. package/cli/scaffold/default/index.html +2 -2
  40. package/cli/scaffold/minimal/app/app.js +6 -7
  41. package/cli/scaffold/minimal/app/components/about.js +5 -5
  42. package/cli/scaffold/minimal/app/components/counter.js +6 -6
  43. package/cli/scaffold/minimal/app/components/home.js +8 -8
  44. package/cli/scaffold/minimal/app/components/not-found.js +1 -1
  45. package/cli/scaffold/minimal/app/routes.js +1 -1
  46. package/cli/scaffold/minimal/app/store.js +1 -1
  47. package/cli/scaffold/minimal/global.css +2 -2
  48. package/cli/scaffold/minimal/index.html +1 -1
  49. package/cli/scaffold/ssr/app/app.js +1 -2
  50. package/cli/scaffold/ssr/app/components/about.js +5 -5
  51. package/cli/scaffold/ssr/app/components/home.js +2 -2
  52. package/cli/scaffold/ssr/app/components/not-found.js +1 -1
  53. package/cli/scaffold/ssr/app/routes.js +1 -1
  54. package/cli/scaffold/ssr/global.css +2 -2
  55. package/cli/scaffold/ssr/index.html +2 -2
  56. package/cli/scaffold/ssr/server/index.js +4 -4
  57. package/cli/utils.js +6 -6
  58. package/dist/zquery.dist.zip +0 -0
  59. package/dist/zquery.js +508 -227
  60. package/dist/zquery.min.js +2 -2
  61. package/index.d.ts +16 -13
  62. package/index.js +7 -5
  63. package/package.json +2 -2
  64. package/src/component.js +64 -63
  65. package/src/core.js +15 -15
  66. package/src/diff.js +38 -38
  67. package/src/errors.js +17 -17
  68. package/src/expression.js +15 -17
  69. package/src/http.js +4 -4
  70. package/src/reactive.js +75 -9
  71. package/src/router.js +104 -24
  72. package/src/ssr.js +28 -28
  73. package/src/store.js +103 -21
  74. package/src/utils.js +64 -12
  75. package/tests/audit.test.js +143 -15
  76. package/tests/cli.test.js +20 -20
  77. package/tests/component.test.js +121 -121
  78. package/tests/core.test.js +56 -56
  79. package/tests/diff.test.js +42 -42
  80. package/tests/errors.test.js +5 -5
  81. package/tests/expression.test.js +58 -53
  82. package/tests/http.test.js +20 -20
  83. package/tests/reactive.test.js +185 -24
  84. package/tests/router.test.js +501 -74
  85. package/tests/ssr.test.js +15 -13
  86. package/tests/store.test.js +264 -23
  87. package/tests/utils.test.js +163 -26
  88. package/types/collection.d.ts +2 -2
  89. package/types/component.d.ts +5 -5
  90. package/types/errors.d.ts +3 -3
  91. package/types/http.d.ts +3 -3
  92. package/types/misc.d.ts +9 -9
  93. package/types/reactive.d.ts +25 -3
  94. package/types/router.d.ts +10 -6
  95. package/types/ssr.d.ts +2 -2
  96. package/types/store.d.ts +40 -5
  97. package/types/utils.d.ts +1 -1
package/README.md CHANGED
@@ -15,22 +15,23 @@
15
15
 
16
16
  </p>
17
17
 
18
- > **Lightweight, zero-dependency frontend library that combines jQuery-style DOM manipulation with a modern reactive component system, SPA router, global state management, HTTP client, and utility toolkit all in a single ~100 KB minified browser bundle. Works out of the box with ES modules. An optional CLI bundler is available for single-file production builds.**
18
+ > **Lightweight, zero-dependency frontend library that combines jQuery-style DOM manipulation with a modern reactive component system, SPA router, global state management, HTTP client, and utility toolkit - all in a single ~91 KB minified browser bundle. Works out of the box with ES modules. An optional CLI bundler is available for single-file production builds.**
19
19
 
20
20
  ## Features
21
21
 
22
22
  | Module | Highlights |
23
23
  | --- | --- |
24
- | **Components** | Reactive state, template literals, `@event` delegation (22 modifiers key filters, system keys, `.outside`, timing, and more), `z-model` two-way binding (with `z-trim`, `z-number`, `z-lazy`, `z-debounce`, `z-uppercase`, `z-lowercase`), computed properties, watch callbacks, slot-based content projection, directives (`z-if`/`z-else-if`/`z-else`, `z-for`, `z-show`, `z-bind`/`:attr`, `z-class`, `z-style`, `z-text`, `z-html`, `z-ref`, `z-cloak`, `z-pre`, `z-key`, `z-skip`), DOM morphing engine with LIS-based keyed reconciliation (no innerHTML rebuild), CSP-safe expression evaluation with AST caching, scoped styles, external templates (`templateUrl` / `styleUrl`), lifecycle hooks, auto-injected base styles |
25
- | **Router** | History & hash mode, route params (`:id`), wildcards, guards (`beforeEach`/`afterEach`), lazy loading, `z-link` navigation, `z-to-top` scroll modifier (`instant`/`smooth`), sub-route history substates (`pushSubstate`/`onSubstate`) |
26
- | **Directives** | `z-if`, `z-for`, `z-model`, `z-show`, `z-bind`, `z-class`, `z-style`, `z-text`, `z-html`, `z-ref`, `z-cloak`, `z-pre`, `z-key`, `z-skip` &mdash; 17 built-in template directives |
27
- | **Reactive** | Deep proxy reactivity, Signals (`.value`, `.peek()`), computed values, effects (auto-tracked with dispose) |
28
- | **Store** | Reactive global state, named actions, computed getters, middleware, subscriptions, action history, snapshots |
24
+ | **Components** | Reactive state, template literals, `@event` delegation (22 modifiers - key filters, system keys, `.outside`, timing, and more), `z-model` two-way binding (with `z-trim`, `z-number`, `z-lazy`, `z-debounce`, `z-uppercase`, `z-lowercase`), computed properties, watch callbacks, slot-based content projection, directives (`z-if`/`z-else-if`/`z-else`, `z-for`, `z-show`, `z-bind`/`:attr`, `z-class`, `z-style`, `z-text`, `z-html`, `z-ref`, `z-cloak`, `z-pre`, `z-key`, `z-skip`), DOM morphing engine with LIS-based keyed reconciliation (no innerHTML rebuild), CSP-safe expression evaluation with AST caching, scoped styles, external templates (`templateUrl` / `styleUrl`), lifecycle hooks, auto-injected base styles |
25
+ | **Router** | History & hash mode, route params (`:id`), wildcards, guards (`beforeEach`/`afterEach`), lazy loading, `z-link` navigation with `z-link-params`, `z-to-top` scroll modifier (`instant`/`smooth`), `z-active-route` active-link class directive, `<z-outlet>` declarative mount point, sub-route history substates (`pushSubstate`/`onSubstate`) |
26
+ | **Directives** | `z-if`, `z-else-if`, `z-else`, `z-for`, `z-model`, `z-show`, `z-bind`/`:attr`, `z-class`, `z-style`, `z-text`, `z-html`, `z-ref`, `z-cloak`, `z-pre`, `z-key`, `z-skip`, `@event`/`z-on` &mdash; 17 built-in template directives |
27
+ | **Reactive** | Deep proxy reactivity, Signals (`.value`, `.peek()`), computed values, effects (auto-tracked with dispose), `batch()` for deferred notifications, `untracked()` for dependency-free reads |
28
+ | **Store** | Reactive global state, named actions, computed getters, middleware, subscriptions, `batch()` grouped mutations, `checkpoint()`/`undo()`/`redo()` with configurable stack, action history, snapshots |
29
29
  | **Selectors & DOM** | jQuery-like chainable selectors, traversal, DOM manipulation, events, animation |
30
30
  | **HTTP** | Fetch wrapper with auto-JSON, interceptors (with unsubscribe & clear), HEAD requests, parallel requests (`http.all`), config inspection (`getConfig`), timeout/abort, base URL |
31
- | **Utils** | debounce, throttle, pipe, once, sleep, memoize, escapeHtml, stripHtml, uuid, capitalize, truncate, range, chunk, groupBy, unique, pick, omit, getPath/setPath, isEmpty, clamp, retry, timeout, deepClone, deepMerge, storage/session wrappers, event bus |
31
+ | **Utils** | debounce, throttle, pipe, once, sleep, memoize (LRU), escapeHtml, stripHtml, uuid, capitalize, truncate, range, chunk, groupBy, unique, pick, omit, getPath/setPath, isEmpty, clamp, retry, timeout, deepClone (enhanced fallback), deepMerge (prototype-pollution safe), storage/session wrappers, event bus |
32
+ | **Security** | XSS-safe template expressions (`{{}}` auto-escaping), sandboxed expression evaluator (blocks `window`, `Function`, `eval`, `RegExp`, `Error`, prototype chains), prototype pollution prevention in `deepMerge`/`setPath`, `z-link` protocol validation, SSR error sanitization |
32
33
  | **Dev Tools** | CLI dev server with live-reload, CSS hot-swap, full-screen error overlay, floating toolbar, dark-themed inspector panel (Router view, DOM tree, network log, component viewer, performance dashboard), fetch interceptor, render instrumentation, CLI bundler for single-file production builds |
33
- | **SSR** | Server-side rendering to HTML strings in Node.js `createSSRApp()`, `renderToString()`, `renderPage()` with SEO/Open Graph support, `renderBatch()` for parallel rendering, fragment mode, hydration markers, graceful error handling, `escapeHtml()` utility |
34
+ | **SSR** | Server-side rendering to HTML strings in Node.js - `createSSRApp()`, `renderToString()`, `renderPage()` with SEO/Open Graph support, `renderBatch()` for parallel rendering, fragment mode, hydration markers, graceful error handling, `escapeHtml()` utility |
34
35
 
35
36
  ---
36
37
 
@@ -38,7 +39,7 @@
38
39
 
39
40
  ### Recommended: CLI Dev Server
40
41
 
41
- The fastest way to develop with zQuery is via the built-in **CLI dev server** with **live-reload**. It serves your ES modules as-is and automatically resolves the library no manual downloads required.
42
+ The fastest way to develop with zQuery is via the built-in **CLI dev server** with **live-reload**. It serves your ES modules as-is and automatically resolves the library - no manual downloads required.
42
43
 
43
44
  ```bash
44
45
  # Install (per-project or globally)
@@ -58,25 +59,25 @@ The `create` command generates a ready-to-run project with a sidebar layout, rou
58
59
 
59
60
  #### Error Overlay
60
61
 
61
- The dev server includes a **full-screen error overlay** that surfaces errors directly in the browser similar to Vite or Angular:
62
+ The dev server includes a **full-screen error overlay** that surfaces errors directly in the browser - similar to Vite or Angular:
62
63
 
63
- - **Syntax errors** JS files are validated on every save *before* the reload is triggered. If a syntax error is found the page stays intact and a dark overlay appears with the error message, file path, line:column, and a code frame pointing to the exact location.
64
- - **Runtime errors** uncaught exceptions and unhandled promise rejections are captured and displayed in the same overlay with a cleaned-up stack trace.
64
+ - **Syntax errors** - JS files are validated on every save *before* the reload is triggered. If a syntax error is found the page stays intact and a dark overlay appears with the error message, file path, line:column, and a code frame pointing to the exact location.
65
+ - **Runtime errors** - uncaught exceptions and unhandled promise rejections are captured and displayed in the same overlay with a cleaned-up stack trace.
65
66
  - The overlay **auto-clears** when you fix the error and save. Press `Esc` or click `×` to dismiss manually.
66
67
 
67
68
  #### Floating Toolbar & Inspector
68
69
 
69
- A compact expandable toolbar appears in the bottom-right corner. In its **collapsed** state it shows live render and request counters. Click the chevron to **expand** and reveal the route indicator (color-coded by the last navigation event navigate, pop, replace, hashchange, substate), registered component count, and DOM element count. Click any stat to open a **dark-themed DevTools inspector** as a popup or visit `http://localhost:<port>/_devtools` for a standalone split-view panel with five tabs: **Router** (live route state, guards, history timeline), **Components** (live state cards), **Performance** (render timeline with timing metrics), **Network** (fetch log with JSON viewer), and **Elements** (live DOM tree with component badges, source viewer, expand/collapse).
70
+ A compact expandable toolbar appears in the bottom-right corner. In its **collapsed** state it shows live render and request counters. Click the chevron to **expand** and reveal the route indicator (color-coded by the last navigation event - navigate, pop, replace, hashchange, substate), registered component count, and DOM element count. Click any stat to open a **dark-themed DevTools inspector** as a popup - or visit `http://localhost:<port>/_devtools` for a standalone split-view panel with five tabs: **Router** (live route state, guards, history timeline), **Components** (live state cards), **Performance** (render timeline with timing metrics), **Network** (fetch log with JSON viewer), and **Elements** (live DOM tree with component badges, source viewer, expand/collapse).
70
71
 
71
72
  ### Alternative: Manual Setup (No npm)
72
73
 
73
- If you prefer **zero tooling**, download `dist/zquery.min.js` from the [dist/ folder](https://github.com/tonywied17/zero-query/tree/main/dist) and drop it into your project root or `assets/scripts/`. Then open `index.html` directly in a browser no Node.js required.
74
+ If you prefer **zero tooling**, download `dist/zquery.min.js` from the [dist/ folder](https://github.com/tonywied17/zero-query/tree/main/dist) and drop it into your project root or `assets/scripts/`. Then open `index.html` directly in a browser - no Node.js required.
74
75
 
75
76
  ```bash
76
77
  git clone https://github.com/tonywied17/zero-query.git
77
78
  cd zero-query
78
79
  npx zquery build
79
- # → dist/zquery.min.js (~100 KB)
80
+ # → dist/zquery.min.js (~91 KB)
80
81
  ```
81
82
 
82
83
  ### Include in HTML
@@ -110,7 +111,7 @@ import './components/about.js';
110
111
  import './components/contacts/contacts.js';
111
112
  import { routes } from './routes.js';
112
113
 
113
- $.router({ el: '#app', routes, fallback: 'not-found' });
114
+ $.router({ routes, fallback: 'not-found' });
114
115
  ```
115
116
 
116
117
  ### Define a Component
@@ -130,7 +131,7 @@ $.component('home-page', {
130
131
  });
131
132
  ```
132
133
 
133
- That's it a fully working SPA with the dev server's live-reload.
134
+ That's it - a fully working SPA with the dev server's live-reload.
134
135
 
135
136
  ---
136
137
 
@@ -194,7 +195,7 @@ my-app/ ← SSR scaffold (npx zquery create my-app --ss
194
195
  index.html ← client HTML shell
195
196
  global.css
196
197
  app/
197
- app.js ← client entry registers shared components
198
+ app.js ← client entry - registers shared components
198
199
  routes.js ← shared route definitions
199
200
  components/
200
201
  home.js ← shared component (SSR + client)
@@ -205,12 +206,12 @@ my-app/ ← SSR scaffold (npx zquery create my-app --ss
205
206
  assets/
206
207
  ```
207
208
 
208
- Components in `app/components/` export plain definition objects the client registers them with `$.component()`, the server with `app.component()`. The `--ssr` flag handles everything automatically installs dependencies, starts the server at `http://localhost:3000`, and opens the browser.
209
+ Components in `app/components/` export plain definition objects - the client registers them with `$.component()`, the server with `app.component()`. The `--ssr` flag handles everything automatically - installs dependencies, starts the server at `http://localhost:3000`, and opens the browser.
209
210
 
210
211
  - One component per file inside `components/`.
211
212
  - Names **must contain a hyphen** (Web Component convention): `home-page`, `app-counter`, etc.
212
213
  - Components with external templates or styles can use a subfolder (e.g. `contacts/contacts.js` + `contacts.html` + `contacts.css`).
213
- - `app.js` is the single entry point import components, create the store, and boot the router.
214
+ - `app.js` is the single entry point - import components, create the store, and boot the router.
214
215
  - `global.css` lives next to `index.html` for easy access; the bundler hashes it into `global.<hash>.min.css` for production.
215
216
  - `assets/` holds static files that get copied to `dist/` as-is.
216
217
 
@@ -218,7 +219,7 @@ Components in `app/components/` export plain definition objects — the client r
218
219
 
219
220
  ## CLI Bundler
220
221
 
221
- The CLI compiles your entire app ES modules, the library, external templates, and assets into a **single production-ready bundle**. It outputs two builds in one step: a `server/` build for deploying to any web server, and a `local/` build that works straight from disk. No config, no flags just point it at your app.
222
+ The CLI compiles your entire app - ES modules, the library, external templates, and assets - into a **single production-ready bundle**. It outputs two builds in one step: a `server/` build for deploying to any web server, and a `local/` build that works straight from disk. No config, no flags - just point it at your app.
222
223
 
223
224
  ```bash
224
225
  # Auto-detect entry from any .html with a module script
@@ -240,7 +241,7 @@ dist/
240
241
  z-app.<hash>.min.js
241
242
  global.<hash>.min.css
242
243
  assets/
243
- local/ ← open from disk (file://) no server needed
244
+ local/ ← open from disk (file://) - no server needed
244
245
  index.html
245
246
  z-app.<hash>.min.js
246
247
  ...
@@ -257,11 +258,11 @@ dist/
257
258
 
258
259
  ### What the Bundler Does
259
260
 
260
- 1. **Entry detection** a strict precedence order ensures the correct file is chosen:
261
- 1. **HTML files** `index.html` is checked first, then other `.html` files (root + one level deep).
262
- 2. **Module scripts within HTML** within each HTML file, a `<script type="module">` whose `src` resolves to `app.js` wins; otherwise the first module script tag is used.
263
- 3. **JS file scan** if no HTML match, JS files (up to 2 levels deep) are scanned in two passes: first for `$.router(` (the canonical app entry point), then for `$.mount(`, `$.store(`, or `mountAll(`.
264
- 4. **Convention fallbacks** `app/app.js`, `scripts/app.js`, `src/app.js`, `js/app.js`, `app.js`, `main.js`.
261
+ 1. **Entry detection** - a strict precedence order ensures the correct file is chosen:
262
+ 1. **HTML files** - `index.html` is checked first, then other `.html` files (root + one level deep).
263
+ 2. **Module scripts within HTML** - within each HTML file, a `<script type="module">` whose `src` resolves to `app.js` wins; otherwise the first module script tag is used.
264
+ 3. **JS file scan** - if no HTML match, JS files (up to 2 levels deep) are scanned in two passes: first for `$.router(` (the canonical app entry point), then for `$.mount(`, `$.store(`, or `mountAll(`.
265
+ 4. **Convention fallbacks** - `app/app.js`, `scripts/app.js`, `src/app.js`, `js/app.js`, `app.js`, `main.js`.
265
266
  2. Resolves all `import` statements and topologically sorts dependencies
266
267
  3. Strips `import`/`export` syntax, wraps in an IIFE
267
268
  4. Embeds zQuery library and inlines `templateUrl` / `styleUrl` files
@@ -289,7 +290,7 @@ location / {
289
290
  }
290
291
  ```
291
292
 
292
- **Sub-path deployment** (e.g. `/my-app/`): set `<base href="/my-app/">` in your HTML the router auto-detects it.
293
+ **Sub-path deployment** (e.g. `/my-app/`): set `<base href="/my-app/">` in your HTML - the router auto-detects it.
293
294
 
294
295
  ---
295
296
 
@@ -298,13 +299,13 @@ location / {
298
299
  | Namespace | Methods |
299
300
  | --- | --- |
300
301
  | `$()` | Chainable selector → `ZQueryCollection` (CSS selectors, elements, NodeLists, HTML strings) |
301
- | `$.all()` | Alias for `$()` identical behavior |
302
+ | `$.all()` | Alias for `$()` - identical behavior |
302
303
  | `$.id` `$.class` `$.classes` `$.tag` `$.name` `$.children` `$.qs` `$.qsa` | Quick DOM refs |
303
304
  | `$.create` | Element factory |
304
305
  | `$.ready` `$.on` `$.off` | DOM ready, global event delegation & direct listeners |
305
306
  | `$.fn` | Collection prototype (extend it) |
306
307
  | `$.component` `$.mount` `$.mountAll` `$.getInstance` `$.destroy` `$.components` `$.prefetch` | Component system |
307
- | `$.morph` `$.morphElement` | DOM morphing engine LIS-based keyed reconciliation, `isEqualNode()` bail-outs, `z-skip` opt-out. Patches existing DOM to match new HTML without destroying unchanged nodes. Auto-key detection (`id`, `data-id`, `data-key`) no `z-key` required. `$().html()` and `$().replaceWith()` auto-morph existing content; `$().morph()` for explicit morph |
308
+ | `$.morph` `$.morphElement` | DOM morphing engine - LIS-based keyed reconciliation, `isEqualNode()` bail-outs, `z-skip` opt-out. Patches existing DOM to match new HTML without destroying unchanged nodes. Auto-key detection (`id`, `data-id`, `data-key`) - no `z-key` required. `$().html()` and `$().replaceWith()` auto-morph existing content; `$().morph()` for explicit morph |
308
309
  | `$.safeEval` | CSP-safe expression evaluator (replaces `eval` / `new Function`) |
309
310
  | `$.style` | Dynamically load global stylesheet file(s) at runtime |
310
311
  | `$.router` `$.getRouter` | SPA router |
@@ -321,7 +322,7 @@ location / {
321
322
  | `$.storage` `$.session` | Storage wrappers |
322
323
  | `$.EventBus` `$.bus` | Event bus |
323
324
  | `$.onError` `$.ZQueryError` `$.ErrorCode` `$.guardCallback` `$.guardAsync` `$.formatError` `$.validate` | Error handling |
324
- | `$.version` | Library version |\n| `$.libSize` | Minified bundle size string (e.g. `\"~100 KB\"`) |
325
+ | `$.version` | Library version |\n| `$.libSize` | Minified bundle size string (e.g. `\"~91 KB\"`) |
325
326
  | `$.unitTests` | Build-time test results `{ passed, failed, total, suites, duration, ok }` |
326
327
  | `$.meta` | Build metadata (populated by CLI bundler) |
327
328
  | `$.noConflict` | Release `$` global |
@@ -346,4 +347,4 @@ The official **[zQuery for VS Code](https://marketplace.visualstudio.com/items?i
346
347
 
347
348
  ## License
348
349
 
349
- MIT [Anthony Wiedman / Molex](https://github.com/tonywied17)
350
+ MIT - [Anthony Wiedman / Molex](https://github.com/tonywied17)
package/cli/args.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/args.js CLI argument parsing helpers
2
+ * cli/args.js - CLI argument parsing helpers
3
3
  *
4
4
  * Provides the raw args array and two helper functions for reading
5
5
  * named flags (--verbose, -v) and valued options (--port 8080, -p 8080).
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/commands/build.js library build command
2
+ * cli/commands/build.js - library build command
3
3
  *
4
4
  * Concatenates the zQuery source modules into dist/zquery.js and
5
5
  * dist/zquery.min.js.
@@ -208,7 +208,7 @@ function buildLibrary() {
208
208
  const zipBuf = buildZip(entries);
209
209
  const zipPath = path.join(DIST, 'zquery.dist.zip');
210
210
  fs.writeFileSync(zipPath, zipBuf);
211
- console.log(` ✓ dist/zquery.dist.zip (${sizeKB(zipBuf)} KB) ${entries.length} files`);
211
+ console.log(` ✓ dist/zquery.dist.zip (${sizeKB(zipBuf)} KB) - ${entries.length} files`);
212
212
 
213
213
  return { DIST, OUT_FILE, MIN_FILE };
214
214
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/commands/bundle.js app bundler command
2
+ * cli/commands/bundle.js - app bundler command
3
3
  *
4
4
  * Walks the ES module import graph starting from an entry file,
5
5
  * strips import/export syntax, concatenates everything into a single
@@ -59,7 +59,7 @@ function extractImports(code) {
59
59
  return specifiers;
60
60
  }
61
61
 
62
- /** Walk the import graph topological sort (leaves first). */
62
+ /** Walk the import graph - topological sort (leaves first). */
63
63
  function walkImportGraph(entry) {
64
64
  const visited = new Set();
65
65
  const order = [];
@@ -119,7 +119,7 @@ function rewriteResourceUrls(code, filePath, projectRoot) {
119
119
  (match, prefix, quote, url) => {
120
120
  if (url.startsWith('/') || url.includes('://')) return match;
121
121
  const abs = path.resolve(fileDir, url);
122
- // Only rewrite if the file actually exists avoids mangling code examples
122
+ // Only rewrite if the file actually exists - avoids mangling code examples
123
123
  if (!fs.existsSync(abs)) return match;
124
124
  const rel = path.relative(projectRoot, abs).replace(/\\/g, '/');
125
125
  return `${prefix}${quote}${rel}${quote}`;
@@ -128,7 +128,7 @@ function rewriteResourceUrls(code, filePath, projectRoot) {
128
128
  }
129
129
 
130
130
  /**
131
- * Minify HTML for inlining strips indentation and collapses whitespace
131
+ * Minify HTML for inlining - strips indentation and collapses whitespace
132
132
  * between tags. Preserves content inside <pre>, <code>, and <textarea>
133
133
  * blocks verbatim so syntax-highlighted code samples survive.
134
134
  */
@@ -164,7 +164,7 @@ function minifyHTML(html) {
164
164
  }
165
165
 
166
166
  /**
167
- * Minify CSS for inlining strips comments, collapses whitespace,
167
+ * Minify CSS for inlining - strips comments, collapses whitespace,
168
168
  * removes unnecessary spaces around punctuation.
169
169
  */
170
170
  function minifyCSS(css) {
@@ -396,7 +396,7 @@ function collectInlineResources(files, projectRoot) {
396
396
  inlineMap[relKey] = fs.readFileSync(tmplPath, 'utf-8');
397
397
  }
398
398
  } else if (/templateUrl\s*:/.test(code)) {
399
- // Dynamic templateUrl (e.g. Object.fromEntries, computed map)
399
+ // Dynamic templateUrl (e.g. Object.fromEntries, computed map) -
400
400
  // inline all .html files in the component's directory tree so
401
401
  // the runtime __zqInline lookup can resolve them by suffix.
402
402
  (function scanHtml(dir) {
@@ -412,7 +412,7 @@ function collectInlineResources(files, projectRoot) {
412
412
  scanHtml(full);
413
413
  }
414
414
  }
415
- } catch { /* permission error skip */ }
415
+ } catch { /* permission error - skip */ }
416
416
  })(fileDir);
417
417
  }
418
418
  }
@@ -429,7 +429,7 @@ function collectInlineResources(files, projectRoot) {
429
429
  /**
430
430
  * Auto-detect the app entry point.
431
431
  *
432
- * Strategy ordered by precedence (first match wins):
432
+ * Strategy - ordered by precedence (first match wins):
433
433
  * 1. HTML discovery: index.html first, then other .html files
434
434
  * (root level + one directory deep).
435
435
  * 2. Within each HTML file, prefer a module <script> whose src
@@ -456,7 +456,7 @@ function detectEntry(projectRoot) {
456
456
  htmlFiles.push(path.join(sub, child.name));
457
457
  }
458
458
  }
459
- } catch { /* permission error skip */ }
459
+ } catch { /* permission error - skip */ }
460
460
  }
461
461
  }
462
462
 
@@ -490,8 +490,8 @@ function detectEntry(projectRoot) {
490
490
  }
491
491
 
492
492
  // 2. Search JS files for entry-point patterns.
493
- // Pass 1 $.router (the canonical entry point).
494
- // Pass 2 $.mount, $.store, mountAll (component-level, lower confidence).
493
+ // Pass 1 - $.router (the canonical entry point).
494
+ // Pass 2 - $.mount, $.store, mountAll (component-level, lower confidence).
495
495
  const routerRe = /\$\.router\s*\(/;
496
496
  const otherRe = /\$\.(mount|store)\s*\(|mountAll\s*\(/;
497
497
 
@@ -541,8 +541,8 @@ function detectEntry(projectRoot) {
541
541
  /**
542
542
  * Rewrite an HTML file to replace the module <script> with the bundle.
543
543
  * Produces two variants:
544
- * server/index.html <base href="/"> for SPA deep routes
545
- * local/index.html relative paths for file:// access
544
+ * server/index.html - <base href="/"> for SPA deep routes
545
+ * local/index.html - relative paths for file:// access
546
546
  */
547
547
  function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFiles, serverDir, localDir, globalCssOrigHref, globalCssHash) {
548
548
  const htmlPath = path.resolve(projectRoot, htmlRelPath);
@@ -737,7 +737,7 @@ function bundleApp() {
737
737
  const minimal = flag('minimal', 'm');
738
738
  const globalCssOverride = option('global-css', null, null);
739
739
 
740
- // Entry point positional arg (directory or file) or auto-detection
740
+ // Entry point - positional arg (directory or file) or auto-detection
741
741
  let entry = null;
742
742
  let targetDir = null;
743
743
  for (let i = 1; i < args.length; i++) {
@@ -984,7 +984,7 @@ function bundleApp() {
984
984
  console.log(`\n ✓ ${minBase} (${sizeKB(fs.readFileSync(minFile))} KB)`);
985
985
 
986
986
  // ------------------------------------------------------------------
987
- // Global CSS bundling extract from index.html <link> or --global-css
987
+ // Global CSS bundling - extract from index.html <link> or --global-css
988
988
  // ------------------------------------------------------------------
989
989
  let globalCssHash = null;
990
990
  let globalCssOrigHref = null;
@@ -1,4 +1,4 @@
1
- // cli/commands/create.js scaffold a new zQuery project
1
+ // cli/commands/create.js - scaffold a new zQuery project
2
2
  //
3
3
  // Templates live in cli/scaffold/<variant>/ (default or minimal).
4
4
  // Reads template files, replaces {{NAME}} with the project name,
@@ -48,7 +48,7 @@ function createProject(args) {
48
48
  process.exit(1);
49
49
  }
50
50
 
51
- console.log(`\n zQuery Create Project (${variant})\n`);
51
+ console.log(`\n zQuery - Create Project (${variant})\n`);
52
52
  console.log(` Scaffolding into ${target}\n`);
53
53
 
54
54
  // Resolve the scaffold template directory for the chosen variant
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/commands/dev/devtools/index.js DevTools HTML assembler
2
+ * cli/commands/dev/devtools/index.js - DevTools HTML assembler
3
3
  *
4
4
  * Reads CSS, HTML, and JS partials from this folder and concatenates them
5
5
  * into a single self-contained HTML page served at /_devtools.
@@ -39,7 +39,7 @@ function formatTime(ts) {
39
39
  }
40
40
 
41
41
  // ===================================================================
42
- // Connection find target window (opener popup → iframe fallback)
42
+ // Connection - find target window (opener popup → iframe fallback)
43
43
  // ===================================================================
44
44
  function isConnected() {
45
45
  try { return targetWin && (targetWin === window.opener ? !targetWin.closed : true) && targetWin.document; }
@@ -48,11 +48,11 @@ function isConnected() {
48
48
 
49
49
  function detectMode() {
50
50
  if (window.opener) {
51
- // Opened as popup hide iframe, use opener
51
+ // Opened as popup - hide iframe, use opener
52
52
  mode = 'popup';
53
53
  targetWin = window.opener;
54
54
  } else {
55
- // Standalone tab embed app in iframe
55
+ // Standalone tab - embed app in iframe
56
56
  mode = 'split-h';
57
57
  targetWin = null; // will set from iframe.contentWindow
58
58
  }
@@ -110,11 +110,11 @@ var tbDragging = false;
110
110
 
111
111
  var isH = mode === 'split-h';
112
112
  if (isH) {
113
- // Vertical column divider drag toolbar up/down
113
+ // Vertical column divider - drag toolbar up/down
114
114
  startPos = e.clientY;
115
115
  startOffset = parseInt(toolbar.style.top, 10) || toolbar.offsetTop;
116
116
  } else {
117
- // Horizontal row divider drag toolbar left/right
117
+ // Horizontal row divider - drag toolbar left/right
118
118
  startPos = e.clientX;
119
119
  startOffset = parseInt(toolbar.style.left, 10) || toolbar.offsetLeft;
120
120
  }
@@ -180,7 +180,7 @@ divider.addEventListener('mousedown', function(e) {
180
180
  });
181
181
 
182
182
  // ===================================================================
183
- // Refresh button reload the embedded iframe
183
+ // Refresh button - reload the embedded iframe
184
184
  // ===================================================================
185
185
  document.getElementById('btn-refresh').addEventListener('click', function(e) {
186
186
  e.stopPropagation();
@@ -192,7 +192,7 @@ document.getElementById('btn-refresh').addEventListener('click', function(e) {
192
192
  });
193
193
 
194
194
  // ===================================================================
195
- // Viewport preset buttons resize browser pane to mobile/tablet/desktop
195
+ // Viewport preset buttons - resize browser pane to mobile/tablet/desktop
196
196
  // ===================================================================
197
197
  var viewportBtns = document.querySelectorAll('.viewport-btn');
198
198
 
@@ -219,10 +219,10 @@ viewportBtns.forEach(function(btn) {
219
219
  var total = rootEl.offsetWidth;
220
220
 
221
221
  if (targetWidth === 0) {
222
- // Desktop reset to default CSS proportions
222
+ // Desktop - reset to default CSS proportions
223
223
  rootEl.style.gridTemplateColumns = '';
224
224
  } else {
225
- // Mobile/Tablet set iframe column to exact pixel width
225
+ // Mobile/Tablet - set iframe column to exact pixel width
226
226
  var pct = Math.min(85, Math.max(15, (targetWidth / total) * 100));
227
227
  rootEl.style.gridTemplateColumns = pct.toFixed(1) + '% 4px 1fr';
228
228
  }
@@ -233,7 +233,7 @@ viewportBtns.forEach(function(btn) {
233
233
  });
234
234
 
235
235
  // ===================================================================
236
- // Route indicator toggle label showing current path + hash
236
+ // Route indicator - toggle label showing current path + hash
237
237
  // ===================================================================
238
238
  var routeBtn = document.getElementById('btn-route');
239
239
  var routeLabel = document.getElementById('route-label');
@@ -266,7 +266,7 @@ setInterval(function() {
266
266
  }, 500);
267
267
 
268
268
  // ===================================================================
269
- // init connect to target window (popup or iframe)
269
+ // init - connect to target window (popup or iframe)
270
270
  // ===================================================================
271
271
  function init() {
272
272
  // If popup mode, targetWin is already set
@@ -310,7 +310,7 @@ function init() {
310
310
  }
311
311
 
312
312
  // ===================================================================
313
- // connectToTarget read existing data, start listeners, periodic sync
313
+ // connectToTarget - read existing data, start listeners, periodic sync
314
314
  // ===================================================================
315
315
  function connectToTarget() {
316
316
 
@@ -372,7 +372,7 @@ function connectToTarget() {
372
372
  // Periodic refresh for components + perf (fast when tab is visible)
373
373
  setInterval(function() {
374
374
  if (!isConnected()) {
375
- // Retry connection opener may be mid-mutation, not truly gone
375
+ // Retry connection - opener may be mid-mutation, not truly gone
376
376
  try {
377
377
  if (mode === 'popup' && window.opener && !window.opener.closed) {
378
378
  targetWin = window.opener;
@@ -389,7 +389,7 @@ function connectToTarget() {
389
389
  return;
390
390
  }
391
391
  }
392
- // Keep targetDoc fresh the opener may have reloaded (live-reload)
392
+ // Keep targetDoc fresh - the opener may have reloaded (live-reload)
393
393
  try {
394
394
  var freshDoc = targetWin.document;
395
395
  if (freshDoc !== targetDoc) {
@@ -72,7 +72,7 @@ function buildNode(node, depth) {
72
72
  var nodePath = getNodePath(node);
73
73
  var hasChildren = false;
74
74
  var childNodes = node.childNodes;
75
- // style/script content is shown inline via the peek button treat as leaf
75
+ // style/script content is shown inline via the peek button - treat as leaf
76
76
  if (tag !== 'style' && tag !== 'script') {
77
77
  for (var i = 0; i < childNodes.length; i++) {
78
78
  var cn = childNodes[i];
@@ -238,7 +238,7 @@ function buildNode(node, depth) {
238
238
  toggleNested(childContainer, 0);
239
239
  });
240
240
 
241
- // Row click select element (not toggle)
241
+ // Row click - select element (not toggle)
242
242
  row.addEventListener('click', function(e) {
243
243
  // Don't select when clicking toggle arrow, badge, action buttons, or peek
244
244
  if (e.target.closest('.tree-toggle') || e.target.closest('.tree-badge') || e.target.closest('.tree-action') || e.target.closest('.tree-peek')) return;
@@ -351,7 +351,7 @@ function showDetail(node) {
351
351
  }
352
352
 
353
353
  // ===================================================================
354
- // MutationObserver watch target document for live DOM changes
354
+ // MutationObserver - watch target document for live DOM changes
355
355
  // ===================================================================
356
356
  function startObserver() {
357
357
  if (!targetDoc || observer) return;
@@ -394,7 +394,7 @@ function startObserver() {
394
394
  }
395
395
  }
396
396
 
397
- if (!dominated) return; // All mutations were from devtools highlight skip rebuild
397
+ if (!dominated) return; // All mutations were from devtools highlight - skip rebuild
398
398
 
399
399
  // Debounce tree rebuild
400
400
  clearTimeout(startObserver._timer);
@@ -9,7 +9,7 @@ function updateStats() {
9
9
  document.getElementById('morph-count').textContent = morphCount + ' renders';
10
10
  document.getElementById('req-count').textContent = requests.length + ' requests';
11
11
 
12
- // Route stat show current path
12
+ // Route stat - show current path
13
13
  try {
14
14
  var router = targetWin && targetWin.$ && targetWin.$.getRouter();
15
15
  var routeStat = document.getElementById('route-stat');
@@ -20,7 +20,7 @@ button{font:inherit;cursor:pointer;border:none;background:none;color:inherit}
20
20
  .divider:hover{background:var(--accent)}
21
21
 
22
22
  /* Divider toolbar */
23
- /* split-h: divider is a tall 4px column toolbar sits to its LEFT, overlaying the browser */
23
+ /* split-h: divider is a tall 4px column - toolbar sits to its LEFT, overlaying the browser */
24
24
  .divider-toolbar{position:absolute;display:flex;flex-direction:column;align-items:center;gap:2px;
25
25
  padding:4px 2px;background:var(--bg2);border:1px solid var(--border);border-radius:6px;
26
26
  z-index:11;top:12px;right:100%;margin-right:2px;cursor:grab}
@@ -36,7 +36,7 @@ border:1px solid var(--border);border-radius:4px;font-size:11px;color:var(--acce
36
36
  max-width:0;overflow:hidden;opacity:0;transition:max-width .25s ease,opacity .2s ease,padding .2s ease;
37
37
  padding:0;pointer-events:none;line-height:22px;text-overflow:ellipsis}
38
38
  .route-label.open{max-width:50vw;opacity:1;padding:2px 8px;pointer-events:auto}
39
- /* split-v: divider is a wide 4px row toolbar sits ABOVE it as a horizontal bar */
39
+ /* split-v: divider is a wide 4px row - toolbar sits ABOVE it as a horizontal bar */
40
40
  #root.split-v .divider-toolbar{flex-direction:row;gap:4px;padding:2px 4px;
41
41
  top:auto;right:auto;bottom:100%;left:12px;margin-right:0;margin-bottom:2px}
42
42
  #root.split-v .divider-sep{width:1px;height:14px;margin:0 1px}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/commands/dev/index.js Dev server orchestrator
2
+ * cli/commands/dev/index.js - Dev server orchestrator
3
3
  *
4
4
  * Ties together the HTTP server, file watcher, logger, and overlay
5
5
  * to provide a complete development environment with live-reload,
@@ -44,7 +44,7 @@ function resolveRoot(htmlEntry) {
44
44
  }
45
45
 
46
46
  // ---------------------------------------------------------------------------
47
- // devServer main entry point (called from cli/index.js)
47
+ // devServer - main entry point (called from cli/index.js)
48
48
  // ---------------------------------------------------------------------------
49
49
 
50
50
  async function devServer() {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cli/commands/dev/logger.js Terminal output helpers
2
+ * cli/commands/dev/logger.js - Terminal output helpers
3
3
  *
4
4
  * Provides styled console output for the dev server: startup banner,
5
5
  * timestamped file-change messages, and error formatting.