@symbiotejs/symbiote 3.5.1 → 3.5.2
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 +17 -1
- package/core/Symbiote.js +1 -1
- package/core/devMessages.js +74 -30
- package/core/warn.js +7 -15
- package/package.json +4 -2
- package/types/core/devMessages.d.ts +12 -1
- package/types/core/devMessages.d.ts.map +1 -1
- package/types/core/warn.d.ts +0 -1
- package/types/core/warn.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.5.2
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`devMode` flag is now cross-module safe.** Moved to `globalThis.__SYMBIOTE_DEV_MODE` so it works correctly across CDN/importmap module scopes (same pattern as `PubSub.globalStore`).
|
|
8
|
+
|
|
9
|
+
### Improved
|
|
10
|
+
|
|
11
|
+
- **`warn.js` — minimal core dispatcher.** Stripped to just `devState`, `warnMsg`, and `errMsg`. All formatting, messages, and styling logic moved to `devMessages.js` via `globalThis.__SYMBIOTE_DEV_LOG` handler. No messages map or `Array.isArray` in core.
|
|
12
|
+
|
|
13
|
+
- **Colored console output.** `devMessages.js` now renders styled badges in browser consoles: purple `Symbiote` badge, amber/red code badge, violet `<component-name>`, and dimmed doc links. Falls back to plain text in Node.js.
|
|
14
|
+
|
|
15
|
+
- **Doc references in all warnings.** Every message now includes a `→` link to the relevant GitHub docs page.
|
|
16
|
+
|
|
17
|
+
- **`devMessages.js` auto-enables `devMode`.** Importing the module sets `globalThis.__SYMBIOTE_DEV_MODE = true` — one import for the full dev experience.
|
|
18
|
+
|
|
3
19
|
## 3.5.0
|
|
4
20
|
|
|
5
21
|
### Added
|
|
6
22
|
|
|
7
23
|
- **External dev messages module (`core/devMessages.js`).** All warning and error message strings have been extracted from core files into an optional module. Core files now emit short numeric codes (e.g. `[Symbiote W5]`). Import `@symbiotejs/symbiote/core/devMessages.js` once to get full human-readable messages. This reduces the core bundle size by removing all formatting strings from `PubSub.js`, `Symbiote.js`, `tpl-processors.js`, `AppRouter.js`, `html.js`, and both itemize processors.
|
|
8
24
|
|
|
9
|
-
- **`core/warn.js` — lightweight message dispatcher.** Exports `warnMsg(code, ...args)
|
|
25
|
+
- **`core/warn.js` — lightweight message dispatcher.** Exports `warnMsg(code, ...args)` and `errMsg(code, ...args)`. All core files now use this dispatcher instead of inline `console.warn`/`console.error` calls.
|
|
10
26
|
|
|
11
27
|
- **AppRouter: `title` accepts functions.** Route descriptors and `setDefaultTitle()` now accept `() => String` in addition to plain strings. The function is called at navigation time, enabling dynamic or localized page titles:
|
|
12
28
|
```js
|
package/core/Symbiote.js
CHANGED
|
@@ -430,7 +430,7 @@ export class Symbiote extends HTMLElement {
|
|
|
430
430
|
if (Symbiote.devMode && this.sharedCtx.has(sharedName)) {
|
|
431
431
|
let existing = this.sharedCtx.read(sharedName);
|
|
432
432
|
if (existing !== sharedVal && typeof sharedVal !== 'function') {
|
|
433
|
-
warnMsg(7, sharedName);
|
|
433
|
+
warnMsg(7, this.localName, sharedName);
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
436
|
this.sharedCtx.add(sharedName, sharedVal);
|
package/core/devMessages.js
CHANGED
|
@@ -1,58 +1,102 @@
|
|
|
1
|
-
import { registerMessages } from './warn.js';
|
|
2
|
-
|
|
3
1
|
globalThis.__SYMBIOTE_DEV_MODE = true;
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
let isBrowser = !globalThis.process;
|
|
4
|
+
|
|
5
|
+
// CSS styles for browser console
|
|
6
|
+
let S = {
|
|
7
|
+
badge: 'background:#7c3aed;color:#fff;border-radius:3px;padding:1px 4px;font-weight:bold',
|
|
8
|
+
code: 'background:#f59e0b;color:#000;border-radius:3px;padding:1px 4px;font-weight:bold',
|
|
9
|
+
errCode: 'background:#ef4444;color:#fff;border-radius:3px;padding:1px 4px;font-weight:bold',
|
|
10
|
+
tag: 'color:#7c3aed;font-weight:bold',
|
|
11
|
+
dim: 'color:#888',
|
|
12
|
+
reset: 'color:inherit',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let DOCS = 'https://github.com/symbiotejs/symbiote.js/blob/main/docs/';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} code - e.g. 'W1' or 'E15'
|
|
19
|
+
* @param {string} body - message body
|
|
20
|
+
* @param {string} doc - doc page name
|
|
21
|
+
* @param {string} [tag] - component tag name
|
|
22
|
+
*/
|
|
23
|
+
function fmt(code, body, doc, tag) {
|
|
24
|
+
if (!isBrowser) {
|
|
25
|
+
return `[Symbiote ${code}]${tag ? ` <${tag}>:` : ''} ${body}\n→ ${DOCS}${doc}.md`;
|
|
26
|
+
}
|
|
27
|
+
let isErr = code.startsWith('E');
|
|
28
|
+
let parts = `%cSymbiote%c${code}%c`;
|
|
29
|
+
let styles = [S.badge, isErr ? S.errCode : S.code, S.reset];
|
|
30
|
+
if (tag) {
|
|
31
|
+
parts += ` %c<${tag}>%c`;
|
|
32
|
+
styles.push(S.tag, S.reset);
|
|
33
|
+
}
|
|
34
|
+
parts += ` ${body} %c→ ${doc}`;
|
|
35
|
+
styles.push(S.dim);
|
|
36
|
+
return [parts, ...styles];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** @type {Map<number, (...args: any[]) => (string | any[])>} */
|
|
40
|
+
let messages = new Map([
|
|
6
41
|
// PubSub
|
|
7
42
|
[1, (uid, action, prop) =>
|
|
8
|
-
`
|
|
43
|
+
fmt('W1', `PubSub (${uid}): cannot ${action}. Property: "${prop}"`, 'pubsub')],
|
|
9
44
|
[2, (uid, prop, prevType, newType, prev, next) =>
|
|
10
|
-
`
|
|
11
|
-
+ `Previous: ${prev}\nNew: ${next}`],
|
|
45
|
+
fmt('W2', `PubSub (${uid}): type change for "${prop}" [${prevType} → ${newType}]. Previous: ${prev} | New: ${next}`, 'pubsub')],
|
|
12
46
|
[3, (uid) =>
|
|
13
|
-
`
|
|
47
|
+
fmt('W3', `PubSub: context "${uid}" is already registered. Returning existing instance.`, 'context')],
|
|
14
48
|
[4, (uid, keys) =>
|
|
15
|
-
`
|
|
16
|
-
+ `Available contexts: [${keys}]`],
|
|
49
|
+
fmt('W4', `PubSub: context "${uid}" not found. Available: [${keys}]`, 'context')],
|
|
17
50
|
|
|
18
51
|
// Symbiote
|
|
19
52
|
[5, (localName, selector) =>
|
|
20
|
-
`
|
|
53
|
+
fmt('W5', `custom template "${selector}" not found.`, 'templates', localName)],
|
|
21
54
|
[6, (localName, sharedName) =>
|
|
22
|
-
`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`[Symbiote] Shared prop "${sharedName}" already has value. Keeping existing.`],
|
|
55
|
+
fmt('W6', `uses *${sharedName} without ctx attribute or --ctx CSS variable. Set ctx="name" or --ctx to share state.`, 'context', localName)],
|
|
56
|
+
[7, (localName, sharedName) =>
|
|
57
|
+
fmt('W7', `shared prop "${sharedName}" already has value. Keeping existing.`, 'context', localName)],
|
|
26
58
|
[8, (tagName, existingClass, newClass) =>
|
|
27
|
-
`
|
|
28
|
-
+ `Attempted re-registration with class "${newClass}" — skipped.`],
|
|
59
|
+
fmt('W8', `already registered (class: ${existingClass}). Re-registration with "${newClass}" — skipped.`, 'get-started', tagName)],
|
|
29
60
|
[9, (localName, propName) =>
|
|
30
|
-
`
|
|
61
|
+
fmt('W9', `CSS data parse error for "${propName}". Check that the CSS custom property is defined.`, 'css-data', localName)],
|
|
31
62
|
[10, (localName, propName) =>
|
|
32
|
-
`
|
|
33
|
-
+ 'The init value will be used instead.'],
|
|
63
|
+
fmt('W10', `CSS data binding "${propName}" will not read computed styles during SSR. The init value will be used instead.`, 'css-data', localName)],
|
|
34
64
|
|
|
35
65
|
// tpl-processors
|
|
36
66
|
[11, (localName, valKey, knownKeys) =>
|
|
37
|
-
`
|
|
38
|
-
+ `Known keys: [${knownKeys}]`],
|
|
67
|
+
fmt('W11', `binding key "${valKey}" not found in init$ (auto-initialized to null). Known keys: [${knownKeys}]`, 'properties', localName)],
|
|
39
68
|
[12, (localName, prop) =>
|
|
40
|
-
`
|
|
41
|
-
|
|
42
|
-
|
|
69
|
+
fmt('W12', `text-node binding "{{${prop}}}" has no hydration attribute. `
|
|
70
|
+
+ 'In ssrMode/isoMode it will be rendered by the server but won\'t update on the client. '
|
|
71
|
+
+ 'Use property binding (${{textContent: \'' + prop + '\'}}) for hydratable text.', 'ssr', localName)],
|
|
43
72
|
|
|
44
73
|
// AppRouter
|
|
45
74
|
[13, (msg) =>
|
|
46
|
-
|
|
75
|
+
fmt('W13', msg, 'routing')],
|
|
47
76
|
[14, () =>
|
|
48
|
-
'
|
|
77
|
+
fmt('W14', 'History API is not available.', 'routing')],
|
|
49
78
|
|
|
50
79
|
// html
|
|
51
80
|
[15, (val) =>
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
fmt('E15', `\`this\` used in template interpolation (value: ${val}). `
|
|
82
|
+
+ 'Templates are context-free — use ${{ prop: \'stateKey\' }} binding syntax instead.', 'templates')],
|
|
54
83
|
|
|
55
84
|
// itemizeProcessor
|
|
56
85
|
[16, (localName, dataType, data) =>
|
|
57
|
-
`
|
|
58
|
-
])
|
|
86
|
+
fmt('W16', `itemize data must be Array or Object, got ${dataType}: ${data}`, 'list-rendering', localName)],
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {'warn' | 'error'} type
|
|
91
|
+
* @param {number} code
|
|
92
|
+
* @param {any[]} args
|
|
93
|
+
*/
|
|
94
|
+
globalThis.__SYMBIOTE_DEV_LOG = (type, code, args) => {
|
|
95
|
+
let formatter = messages.get(code);
|
|
96
|
+
if (formatter) {
|
|
97
|
+
let result = formatter(...args);
|
|
98
|
+
Array.isArray(result) ? console[type](...result) : console[type](result);
|
|
99
|
+
} else {
|
|
100
|
+
console[type](`[Symbiote ${type === 'error' ? 'E' : 'W'}${code}]`);
|
|
101
|
+
}
|
|
102
|
+
};
|
package/core/warn.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/** @type {Map<number, (...args: any[]) => string>} */
|
|
2
|
-
let messages = globalThis.__SYMBIOTE_DEV_MESSAGES || (globalThis.__SYMBIOTE_DEV_MESSAGES = new Map());
|
|
3
|
-
|
|
4
1
|
/** @type {{ devMode: boolean }} */
|
|
5
2
|
export let devState = {
|
|
6
3
|
get devMode() {
|
|
@@ -11,13 +8,17 @@ export let devState = {
|
|
|
11
8
|
},
|
|
12
9
|
};
|
|
13
10
|
|
|
11
|
+
/** @param {string} type @param {number} code */
|
|
12
|
+
function _log(type, code) {
|
|
13
|
+
console[type](`[Symbiote ${type === 'error' ? 'E' : 'W'}${code}]`);
|
|
14
|
+
}
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* @param {number} code
|
|
16
18
|
* @param {...any} args
|
|
17
19
|
*/
|
|
18
20
|
export function warnMsg(code, ...args) {
|
|
19
|
-
|
|
20
|
-
console.warn(fmt ? fmt(...args) : `[Symbiote W${code}]`);
|
|
21
|
+
(globalThis.__SYMBIOTE_DEV_LOG || _log)('warn', code, args);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -25,14 +26,5 @@ export function warnMsg(code, ...args) {
|
|
|
25
26
|
* @param {...any} args
|
|
26
27
|
*/
|
|
27
28
|
export function errMsg(code, ...args) {
|
|
28
|
-
|
|
29
|
-
console.error(fmt ? fmt(...args) : `[Symbiote E${code}]`);
|
|
29
|
+
(globalThis.__SYMBIOTE_DEV_LOG || _log)('error', code, args);
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
/** @param {Map<number, (...args: any[]) => string>} map */
|
|
33
|
-
export function registerMessages(map) {
|
|
34
|
-
for (let [code, fmt] of map) {
|
|
35
|
-
messages.set(code, fmt);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@symbiotejs/symbiote",
|
|
4
|
-
"version": "3.5.
|
|
4
|
+
"version": "3.5.2",
|
|
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",
|
|
@@ -158,6 +158,7 @@
|
|
|
158
158
|
"keywords": [
|
|
159
159
|
"web components",
|
|
160
160
|
"SSR",
|
|
161
|
+
"SSG",
|
|
161
162
|
"server side rendering for web components",
|
|
162
163
|
"ui library",
|
|
163
164
|
"data flow",
|
|
@@ -182,7 +183,8 @@
|
|
|
182
183
|
"https imports",
|
|
183
184
|
"reactive html attributes",
|
|
184
185
|
"MIT",
|
|
185
|
-
"JSDA"
|
|
186
|
+
"JSDA",
|
|
187
|
+
"jsda-kit"
|
|
186
188
|
],
|
|
187
189
|
"devDependencies": {
|
|
188
190
|
"@playwright/test": "^1.58.2",
|
|
@@ -1,2 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
declare function fmt(code: string, body: string, doc: string, tag?: string): string | string[];
|
|
2
|
+
declare let isBrowser: boolean;
|
|
3
|
+
declare namespace S {
|
|
4
|
+
let badge: string;
|
|
5
|
+
let code: string;
|
|
6
|
+
let errCode: string;
|
|
7
|
+
let tag: string;
|
|
8
|
+
let dim: string;
|
|
9
|
+
let reset: string;
|
|
10
|
+
}
|
|
11
|
+
declare let DOCS: string;
|
|
12
|
+
declare let messages: Map<number, (...args: any[]) => (string | any[])>;
|
|
2
13
|
//# sourceMappingURL=devMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devMessages.d.ts","sourceRoot":"","sources":["../../core/devMessages.js"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"devMessages.d.ts","sourceRoot":"","sources":["../../core/devMessages.js"],"names":[],"mappings":"AAsBA,2BALW,MAAM,QACN,MAAM,OACN,MAAM,QACN,MAAM,qBAgBhB;AAlCD,+BAAoC;;;;;;;;;AAYpC,yBAAuE;AAyBvE,sBADW,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAgDzD"}
|
package/types/core/warn.d.ts
CHANGED
package/types/core/warn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warn.d.ts","sourceRoot":"","sources":["../../core/warn.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"warn.d.ts","sourceRoot":"","sources":["../../core/warn.js"],"names":[],"mappings":"AAmBA,8BAHW,MAAM,WACF,GAAG,EAAA,QAIjB;AAMD,6BAHW,MAAM,WACF,GAAG,EAAA,QAIjB;AA5BD,qBADW;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAQ7B"}
|