zero-query 1.2.4 → 1.2.6

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
@@ -43,20 +43,32 @@
43
43
 
44
44
  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.
45
45
 
46
+ Pick a scaffold flavor — every variant auto-installs, auto-starts, and opens your browser:
47
+
46
48
  ```bash
47
- npx zero-query create my-app
49
+ # Default: full sidebar layout, router, demo components, responsive styles
50
+ npx zero-query create my-app # → http://localhost:3100
51
+
52
+ # Minimal: lightweight 3-page starter
53
+ npx zero-query create my-app --minimal # → http://localhost:3100 (alias: -m)
54
+
55
+ # SSR: Node.js server-side rendering project
56
+ npx zero-query create my-app --ssr # → http://localhost:3000 (alias: -s)
57
+
58
+ # WebRTC: one-page video room backed by zero-server
59
+ npx zero-query create my-app --webrtc-demo # → http://localhost:3000 (alias: -w)
48
60
  ```
49
61
 
50
- That's it. One command scaffolds the project, installs dependencies, starts the dev server, and opens your browser to <http://localhost:3100>. To restart later:
62
+ That's it. One command scaffolds the project, installs dependencies, starts the server, and opens the browser. To restart later:
51
63
 
52
64
  ```bash
53
65
  cd my-app
54
66
  npm run dev # or: npm start
55
67
  ```
56
68
 
57
- > **Tip:** Stay in the project root (where `node_modules` lives) instead of `cd`-ing into `my-app`. This keeps `index.d.ts` accessible to your IDE for full type/intellisense support.
69
+ > **Tip:** For the default and minimal variants, you can stay in the project root (where `node_modules` lives) instead of `cd`-ing into `my-app`. This keeps `index.d.ts` accessible to your IDE for full type/intellisense support.
58
70
 
59
- The `create` command generates a ready-to-run project with a sidebar layout, router, multiple components (including folder components with external templates and styles), and responsive styles. Use `--minimal` (or `-m`) for a lightweight 3-page starter. Use `--ssr` (or `-s`) for a Node.js server-side rendering project (auto-launches on port 3000). Use `--webrtc-demo` (or `-w`) for a one-page video room backed by [zero-server](https://github.com/tonywied17/zero-server) (also port 3000). Every variant auto-installs, auto-starts, and opens the browser. The dev server watches for file changes, hot-swaps CSS in-place, full-reloads on other changes, and handles SPA fallback routing.
71
+ The default scaffold ships a sidebar layout, router, multiple components (including folder components with external templates and styles), and responsive styles. The SSR variant runs a Node.js server that renders pages to HTML strings. The WebRTC variant is wired to [zero-server](https://github.com/tonywied17/zero-server) for signaling + TURN. The dev server watches for file changes, hot-swaps CSS in-place, full-reloads on other changes, and handles SPA fallback routing.
60
72
 
61
73
  #### Error Overlay
62
74
 
@@ -235,6 +247,24 @@ my-app/ ← SSR scaffold (npx zquery create my-app --ss
235
247
 
236
248
  Components in `app/components/` export plain definition objects - the client registers them with `$.component()`, the server with `app.component()`. The scaffold includes a blog with param-based routing (`/blog/:slug`), per-route SEO metadata, JSON API endpoints (`/api/posts`), and `window.__SSR_DATA__` hydration. The `--ssr` flag handles everything automatically - installs dependencies, starts the server at `http://localhost:3000`, and opens the browser.
237
249
 
250
+ Use `--webrtc-demo` (`-w`) for a one-page video room backed by [zero-server](https://github.com/tonywied17/zero-server):
251
+
252
+ ```
253
+ my-app/ ← webrtc scaffold (npx zquery create my-app --webrtc-demo)
254
+ index.html ← single-page video room shell
255
+ global.css
256
+ package.json ← declares @zero-server/sdk + @zero-server/webrtc deps
257
+ app/
258
+ app.js ← boots the room component
259
+ components/
260
+ video-room.js ← join controls, peer grid, z-stream bindings
261
+ server/
262
+ index.js ← signaling + static server (zero-server-backed)
263
+ assets/
264
+ ```
265
+
266
+ The signaling server is a thin wrapper around `@zero-server/webrtc` that issues join tokens, relays SDP/ICE, and serves the static client. Set `WEBRTC_JWT_SECRET`, `TURN_SECRET`, and `TURN_URLS` env vars to enable TURN. The `--webrtc-demo` flag installs all deps (zQuery + the two `@zero-server` packages), starts the signaling + static server at `http://localhost:3000`, and opens the browser.
267
+
238
268
  - One component per file inside `components/`.
239
269
  - Names **must contain a hyphen** (Web Component convention): `home-page`, `app-counter`, etc.
240
270
  - Components with external templates or styles can use a subfolder (e.g. `contacts/contacts.js` + `contacts.html` + `contacts.css`).
@@ -220,9 +220,17 @@ function htmlToMarkdown(html) {
220
220
  md = md.replace(/<div class="file-tree">[\s\S]*?<\/div>(?:\s*<\/div>)*/g, '');
221
221
 
222
222
  // ---- Pass 5: Convert headings ----
223
- md = md.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/g, (_, c) => '\n## ' + unesc(inlineMd(c)).trim() + '\n');
224
- md = md.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/g, (_, c) => '\n### ' + unesc(inlineMd(c)).trim() + '\n');
225
- md = md.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/g, (_, c) => '\n#### ' + unesc(inlineMd(c)).trim() + '\n');
223
+ // Preserve `id` attributes by emitting an explicit HTML anchor before the
224
+ // heading so cross-section duplicate titles (e.g. "Overview") still resolve
225
+ // to unique anchors in the rendered Markdown TOC.
226
+ const headingRepl = (level) => (_, attrs, c) => {
227
+ const idMatch = /\bid="([^"]+)"/.exec(attrs || '');
228
+ const anchor = idMatch ? `<a id="${idMatch[1]}"></a>\n` : '';
229
+ return '\n' + anchor + '#'.repeat(level) + ' ' + unesc(inlineMd(c)).trim() + '\n';
230
+ };
231
+ md = md.replace(/<h2([^>]*)>([\s\S]*?)<\/h2>/g, headingRepl(2));
232
+ md = md.replace(/<h3([^>]*)>([\s\S]*?)<\/h3>/g, headingRepl(3));
233
+ md = md.replace(/<h4([^>]*)>([\s\S]*?)<\/h4>/g, headingRepl(4));
226
234
 
227
235
  // ---- Pass 6: Convert lists ----
228
236
  md = md.replace(/<ul>([\s\S]*?)<\/ul>/g, (_, content) => {
@@ -298,14 +306,19 @@ function slugify(text) {
298
306
  function buildToc(sections) {
299
307
  const lines = [];
300
308
  for (const section of sections) {
301
- // Get the section title from the first <h2> in content
309
+ // Get the section title from the first <h2> in content, preferring an
310
+ // explicit `id` attribute when present so the TOC link is stable and
311
+ // unique across sections.
302
312
  const html = section.content();
303
- const h2Match = html.match(/<h2[^>]*>([\s\S]*?)<\/h2>/);
304
- const title = h2Match ? unesc(inlineMd(h2Match[1])).trim() : section.label;
305
- lines.push(`- [${title}](#${slugify(title)})`);
313
+ const h2Match = html.match(/<h2([^>]*)>([\s\S]*?)<\/h2>/);
314
+ const title = h2Match ? unesc(inlineMd(h2Match[2])).trim() : section.label;
315
+ const h2Id = h2Match && /\bid="([^"]+)"/.exec(h2Match[1] || '');
316
+ const anchor = h2Id ? h2Id[1] : (section.id || slugify(title));
317
+ lines.push(`- [${title}](#${anchor})`);
306
318
  for (const h of section.headings) {
307
319
  const hText = unesc(h.text);
308
- lines.push(` - [${hText}](#${slugify(hText)})`);
320
+ const hAnchor = h.id || slugify(hText);
321
+ lines.push(` - [${hText}](#${hAnchor})`);
309
322
  }
310
323
  }
311
324
  return lines.join('\n');