@symbiotejs/symbiote 3.5.3 → 3.5.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.5.4
4
+
5
+ ### Fixed
6
+
7
+ - **SSR: `bindAttributes()` crash in linkedom.** `observedAttributes` is a getter-only property in linkedom — direct assignment threw. Now uses `Object.defineProperty` with a configurable getter.
8
+
9
+ - **SSR: `renderCallback()` crash from browser-only APIs.** Components using `IntersectionObserver`, `window.location`, etc. in `renderCallback` crashed the entire SSR process. Now wrapped in try-catch during SSR (`__SYMBIOTE_SSR`); browser-side errors still re-throw normally.
10
+
3
11
  ## 3.5.2
4
12
 
5
13
  ### Fixed
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  [![Tests](https://github.com/symbiotejs/symbiote.js/actions/workflows/tests.yml/badge.svg)](https://github.com/symbiotejs/symbiote.js/actions/workflows/tests.yml)
2
2
  [![npm version](https://img.shields.io/npm/v/@symbiotejs/symbiote)](https://www.npmjs.com/package/@symbiotejs/symbiote)
3
3
  [![npm downloads](https://img.shields.io/npm/dm/@symbiotejs/symbiote)](https://www.npmjs.com/package/@symbiotejs/symbiote)
4
- ![bundle size](https://img.shields.io/badge/brotli-6.4_kb-blue)
4
+ ![bundle size](https://img.shields.io/badge/brotli-5.9_kb-blue)
5
5
  ![types](https://img.shields.io/badge/types-JSDoc+d.ts-blue)
6
6
  ![license](https://img.shields.io/badge/license-MIT-green)
7
7
 
@@ -13,7 +13,7 @@ A lightweight, standards-first UI library built on Web Components. No virtual DO
13
13
 
14
14
  Symbiote.js gives you the convenience of a modern framework while staying close to the native platform — HTML, CSS, and DOM APIs. Components are real custom elements that work everywhere: in any framework, in plain HTML, or in a micro-frontend architecture. And with **isomorphic mode**, the same component code works on the server and the client — server-rendered pages hydrate automatically, no diffing, no mismatch errors.
15
15
 
16
- ## What's new in 3.x
16
+ ## What's new in v3
17
17
 
18
18
  - **Server-Side Rendering** — render components to HTML with `SSR.processHtml()` or stream chunks with `SSR.renderToStream()`. Client-side hydration via `ssrMode` attaches bindings to existing DOM without re-rendering.
19
19
  - **Isomorphic components** — `isoMode` flag makes components work in both SSR and client-only scenarios automatically. If server-rendered content exists, it hydrates; otherwise it renders the template from scratch. One component, zero conditional logic.
@@ -336,12 +336,12 @@ CSS values are parsed automatically — quoted strings become strings, numbers b
336
336
 
337
337
  | Library | Minified | Gzip | Brotli |
338
338
  |---------|----------|------|--------|
339
- | **Symbiote.js** (core) | 20.2 kb | 7.1 kb | **6.4 kb** |
340
- | **Symbiote.js** (full, with AppRouter) | 24.4 kb | 8.5 kb | **7.6 kb** |
339
+ | **Symbiote.js** (core) | 18.9 kb | 6.6 kb | **5.9 kb** |
340
+ | **Symbiote.js** (full, with AppRouter) | 23.2 kb | 7.9 kb | **7.2 kb** |
341
341
  | **Lit** 3.3 | 15.5 kb | 6.0 kb | **~5.1 kb** |
342
342
  | **React 19 + ReactDOM** | ~186 kb | ~59 kb | **~50 kb** |
343
343
 
344
- Symbiote and Lit have similar base sizes, but Symbiote's **6.4 kb** core includes more built-in features: global state management, lists (itemize API), exit animations, computed properties etc. Lit needs additional packages for comparable features. React is **~8× larger** before adding a router, state manager, or SSR framework.
344
+ Symbiote and Lit have similar base sizes, but Symbiote's **5.9 kb** core includes more built-in features: global state management, lists (itemize API), exit animations, computed properties etc. Lit needs additional packages for comparable features. React is **~8× larger** before adding a router, state manager, or SSR framework.
345
345
 
346
346
  ## Browser support
347
347
 
package/core/Symbiote.js CHANGED
@@ -142,7 +142,11 @@ export class Symbiote extends HTMLElement {
142
142
  fr && ((shadow && this.shadowRoot.appendChild(fr)) || this.appendChild(fr));
143
143
  }
144
144
  this.#initCallback();
145
- this.renderCallback?.();
145
+ try {
146
+ this.renderCallback?.();
147
+ } catch (e) {
148
+ if (!globalThis.__SYMBIOTE_SSR) throw e;
149
+ }
146
150
  };
147
151
 
148
152
  if (this.#super.shadowStyleSheets) {
@@ -527,6 +531,7 @@ export class Symbiote extends HTMLElement {
527
531
 
528
532
  destructionDelay = 100;
529
533
  disconnectedCallback() {
534
+ if (globalThis.__SYMBIOTE_SSR) return;
530
535
  // if element wasn't connected, there is no need to disconnect it
531
536
  if (!this.connectedOnce) {
532
537
  return;
@@ -587,9 +592,14 @@ export class Symbiote extends HTMLElement {
587
592
  /** @param {Object<string, string>} desc */
588
593
  static bindAttributes(desc) {
589
594
  /** @type {String[]} */
590
- this.observedAttributes = [
595
+ let attrs = [
596
+ // @ts-ignore - observedAttributes is a native HTMLElement static getter
591
597
  ...new Set((this.observedAttributes || []).concat(Object.keys(desc)))
592
598
  ];
599
+ Object.defineProperty(this, 'observedAttributes', {
600
+ configurable: true,
601
+ get() { return attrs; },
602
+ });
593
603
  /** @private */
594
604
  this.__attrDesc = desc;
595
605
  }
package/node/SSR.js CHANGED
@@ -342,9 +342,6 @@ export class SSR {
342
342
  * Called automatically by processHtml(). Call manually only after renderToString/renderToStream.
343
343
  */
344
344
  static destroy() {
345
- if (SSR.#doc) {
346
- SSR.#doc.body.innerHTML = '';
347
- }
348
345
  delete globalThis.__SYMBIOTE_SSR;
349
346
  delete globalThis.document;
350
347
  delete globalThis.window;
@@ -375,6 +372,13 @@ export class SSR {
375
372
  * ```
376
373
  */
377
374
  static async processHtml(html, options = {}) {
375
+ let doctype = '';
376
+ let doctypeMatch = html.match(/^(\s*<!doctype[^>]*>\s*)/i);
377
+ if (doctypeMatch) {
378
+ doctype = doctypeMatch[1];
379
+ html = html.slice(doctypeMatch[0].length);
380
+ }
381
+
378
382
  let autoInited = !SSR.#doc;
379
383
  if (autoInited) {
380
384
  await SSR.init();
@@ -385,11 +389,10 @@ export class SSR {
385
389
  for (let child of SSR.#doc.body.childNodes) {
386
390
  result += serializeNode(child, emittedStyles, options.nonce);
387
391
  }
388
- SSR.#doc.body.innerHTML = '';
389
392
  if (autoInited) {
390
393
  SSR.destroy();
391
394
  }
392
- return result;
395
+ return doctype + result;
393
396
  }
394
397
 
395
398
  /**
@@ -422,7 +425,6 @@ export class SSR {
422
425
  html = serializeElement(el, new Set(), options.nonce);
423
426
  el.remove();
424
427
  }
425
- SSR.#doc.body.innerHTML = '';
426
428
  return html;
427
429
  }
428
430
 
@@ -454,7 +456,6 @@ export class SSR {
454
456
  yield* streamElement(el, new Set(), options.nonce);
455
457
  el.remove();
456
458
  }
457
- SSR.#doc.body.innerHTML = '';
458
459
  }
459
460
  }
460
461
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@symbiotejs/symbiote",
4
- "version": "3.5.3",
4
+ "version": "3.5.5",
5
5
  "description": "Symbiote.js - zero-dependency close-to-platform frontend library to build super-powered web components",
6
6
  "author": "team@rnd-pro.com",
7
7
  "license": "MIT",
@@ -1 +1 @@
1
- {"version":3,"file":"Symbiote.d.ts","sourceRoot":"","sources":["../../core/Symbiote.js"],"names":[],"mappings":";;AAoBA,sBADc,CAAC;IAuBb,cADW,mBAAmB,CACjB;IAEb,iCAEC;IAED,8BAEC;IAkBD,wBAAgB;IA0JhB,+BAJwB,CAAC,SAAZ,aAAU,uBAEZ,CAAC;;;MA0CX;IAuQD,qCAA+B;IAoC/B,iDAFa,OAAO,QAAQ,CAkB3B;IAED,wBAKC;IAGD;;aAOC;IAmHD,6BADY,SAAS,aAAa,QAOjC;IAGD,+BADY,SAAS,aAAa,QAOjC;IAGD,8BADY,SAAS,aAAa,EAIjC;IAGD,gCADY,SAAS,aAAa,EAIjC;IApkBD,cA6BC;IArID,gCAEC;IAED,qBAAiB;IACjB,uBAAmB;IAiBnB,kBAHW,SAAS,gBAAgB,0BAmFnC;IApDG,aAAiD;IAyDnD,OADW,CAAC,CACoB;IAEhC;;MAAmC;IAEnC,oBADW,GAAG,CAAC,CAAC,EAAE,EAAE,gBAAgB,gBAAW,EAAE,KAAK,eAAU,KAAK,IAAI,CAAC,CACvC;IAEnC;;MAA8B;IAC9B,kBAAwB;IAExB,qBAAwB;IAExB,sBAAyB;IAEzB,wBAA0B;IAE1B,0BAA6B;IAI7B,iBAAoB;IAEpB,6BAAgC;IAEhC,mBAAsB;IAEtB,4BAA8B;IAIhC,yBAEC;IAGD,sBASC;IAGD,4BAKC;IAGD,6BAEC;IAuDD,IALuB,CAAC,SAAX,MAAO,CAAE,QACX,CAAC,WACD,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,wBAuC/B;IAGD,2BAIC;IAGD,uBAIC;IAQD,IALuB,CAAC,SAAX,MAAO,CAAE,qBAEX,CAAC,CAAC,CAAC,CAAC,2BAOd;IAMD,UAHW,OAAO,CAAC,CAAC,CAAC,2BAOpB;IAGD,SADc,CAAC,CA6Bd;IAMD,YAHW,OAAO,CAAC,CAAC,CAAC,mCAcpB;IAED,8BAgBC;IAdG,4CASE;IAmFF,0BAAwC;IAwB1C,uBAAyB;IAG3B,0BAEC;IAED,wBAAoB;IAUpB,yBAAuB;IACvB,6BA0BC;IA0CD,oEAeC;IAMD,yDAoBC;IAYD,0BAME;IAMF,0CAFW,GAAG,QAgBb;IAED,yBAGC;IAOD,8EAmBC;;CA+BF;;mBAjuBkB,aAAa;qBAEX,iBAAiB;2BACX,iBAAiB"}
1
+ {"version":3,"file":"Symbiote.d.ts","sourceRoot":"","sources":["../../core/Symbiote.js"],"names":[],"mappings":";;AAoBA,sBADc,CAAC;IAuBb,cADW,mBAAmB,CACjB;IAEb,iCAEC;IAED,8BAEC;IAkBD,wBAAgB;IA8JhB,+BAJwB,CAAC,SAAZ,aAAU,uBAEZ,CAAC;;;MA0CX;IAuQD,qCAA+B;IAqC/B,iDAFa,OAAO,QAAQ,CAkB3B;IAED,wBAKC;IAGD;;aAYC;IAmHD,6BADY,SAAS,aAAa,QAOjC;IAGD,+BADY,SAAS,aAAa,QAOjC;IAGD,8BADY,SAAS,aAAa,EAIjC;IAGD,gCADY,SAAS,aAAa,EAIjC;IA1kBD,cA6BC;IAzID,gCAEC;IAED,qBAAiB;IACjB,uBAAmB;IAiBnB,kBAHW,SAAS,gBAAgB,0BAuFnC;IAxDG,aAAiD;IA6DnD,OADW,CAAC,CACoB;IAEhC;;MAAmC;IAEnC,oBADW,GAAG,CAAC,CAAC,EAAE,EAAE,gBAAgB,gBAAW,EAAE,KAAK,eAAU,KAAK,IAAI,CAAC,CACvC;IAEnC;;MAA8B;IAC9B,kBAAwB;IAExB,qBAAwB;IAExB,sBAAyB;IAEzB,wBAA0B;IAE1B,0BAA6B;IAI7B,iBAAoB;IAEpB,6BAAgC;IAEhC,mBAAsB;IAEtB,4BAA8B;IAIhC,yBAEC;IAGD,sBASC;IAGD,4BAKC;IAGD,6BAEC;IAuDD,IALuB,CAAC,SAAX,MAAO,CAAE,QACX,CAAC,WACD,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,wBAuC/B;IAGD,2BAIC;IAGD,uBAIC;IAQD,IALuB,CAAC,SAAX,MAAO,CAAE,qBAEX,CAAC,CAAC,CAAC,CAAC,2BAOd;IAMD,UAHW,OAAO,CAAC,CAAC,CAAC,2BAOpB;IAGD,SADc,CAAC,CA6Bd;IAMD,YAHW,OAAO,CAAC,CAAC,CAAC,mCAcpB;IAED,8BAgBC;IAdG,4CASE;IAmFF,0BAAwC;IAwB1C,uBAAyB;IAG3B,0BAEC;IAED,wBAAoB;IAUpB,yBAAuB;IACvB,6BA2BC;IA+CD,oEAeC;IAMD,yDAoBC;IAYD,0BAME;IAMF,0CAFW,GAAG,QAgBb;IAED,yBAGC;IAOD,8EAmBC;;CA+BF;;mBA3uBkB,aAAa;qBAEX,iBAAiB;2BACX,iBAAiB"}
@@ -1 +1 @@
1
- {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../node/SSR.js"],"names":[],"mappings":"AAsQA;IAEE,8BAAmB;IACnB,8BAAmB;IAMnB;;;OAkEC;IAMD,uBAeC;IAkBD,yBAZW,MAAM,YACN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CA0B3B;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,MAAM,CAyBlB;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,cAAc,CAAC,MAAM,CAAC,CAsBlC;CACF"}
1
+ {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../node/SSR.js"],"names":[],"mappings":"AAsQA;IAEE,8BAAmB;IACnB,8BAAmB;IAMnB;;;OAkEC;IAMD,uBAYC;IAkBD,yBAZW,MAAM,YACN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CAgC3B;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,MAAM,CAwBlB;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,cAAc,CAAC,MAAM,CAAC,CAqBlC;CACF"}