@cossackframework/renderer 0.1.1 → 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tan Nguyen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,309 @@
1
+ # Cossack Renderer Package
2
+
3
+ Cossack Renderer is a Lit-compatible rendering engine designed for **Light DOM** and **SSR**. It provides a familiar API for building components but focuses on returning HTML strings directly for SSR and managing DOM updates without Shadow DOM isolation.
4
+
5
+ ## Installation
6
+
7
+ This package is intended to use with the Cossack Framework via `create-cossack-app`, but can also be used standalone in any project that needs a lightweight rendering solution.
8
+
9
+ ```bash
10
+ pnpm add @cossackframework/renderer
11
+ ```
12
+
13
+ ## Defining Components
14
+
15
+ Components are classes that extend `CossackElement`. They manage their own state and render template results.
16
+
17
+ ```typescript
18
+ import { CossackElement, html } from '@cossackframework/renderer';
19
+
20
+ export class MyCounter extends CossackElement {
21
+ // Define reactive properties
22
+ static properties = {
23
+ count: { state: true },
24
+ label: { state: true }
25
+ };
26
+
27
+ // Declare fields for TypeScript
28
+ declare count: number;
29
+ declare label: string;
30
+
31
+ constructor() {
32
+ super();
33
+ this.count = 0;
34
+ this.label = 'Count';
35
+ }
36
+
37
+ increment() {
38
+ this.count++;
39
+ }
40
+
41
+ render() {
42
+ return html`
43
+ <div>
44
+ <span>${this.label}: ${this.count}</span>
45
+ <button @click="${() => this.increment()}">+</button>
46
+ </div>
47
+ `;
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## Rendering
53
+
54
+ ### Client-Side Rendering (Hydration/Mounting)
55
+
56
+ To mount a component to the DOM:
57
+
58
+ ```typescript
59
+ import { MyCounter } from './MyCounter';
60
+
61
+ const container = document.getElementById('app');
62
+ const app = new MyCounter();
63
+ app.mount(container); // Mounts and renders to the container
64
+ ```
65
+
66
+ ### Server-Side Rendering (SSR)
67
+
68
+ To render a component to an HTML string:
69
+
70
+ ```typescript
71
+ import { renderToString } from '@cossackframework/renderer';
72
+ import { MyCounter } from './MyCounter';
73
+
74
+ const app = new MyCounter();
75
+ // Optional: Wait for async data or updates
76
+ const htmlString = renderToString(app.render());
77
+ console.log(htmlString);
78
+ ```
79
+
80
+ ## Template Syntax
81
+
82
+ Cossack uses tagged template literals via `html`.
83
+
84
+ ### Basic Expressions
85
+
86
+ ```typescript
87
+ html`<h1>Hello ${name}</h1>`
88
+ ```
89
+
90
+ ### Attributes
91
+
92
+ Boolean attributes are removed if `false/null/undefined`.
93
+
94
+ ```typescript
95
+ html`<button ?disabled="${isDisabled}">Click</button>`
96
+ ```
97
+
98
+ ### Event Binding
99
+
100
+ Bind event listeners using Lit's `@` syntax.
101
+
102
+ ```typescript
103
+ html`<button @click="${(e) => this.handleClick(e)}">Click Me</button>`
104
+ ```
105
+
106
+ ### Property Binding
107
+
108
+ For `<input>` elements, use `.` prefix to bind properties directly.
109
+
110
+ ```typescript
111
+ html`<input type="text" .value="${this.inputValue}" @input="${this.handleInput}" />`
112
+ ```
113
+
114
+ ### Spread Attributes
115
+
116
+ You can spread an object into attributes using the `...` syntax.
117
+
118
+ ```typescript
119
+ const props = { id: 'btn', class: 'primary', 'data-type': 'action' };
120
+ html`<button ...=${props}>Click</button>`
121
+ ```
122
+
123
+ ### Unsafe HTML
124
+
125
+ To render raw HTML strings (careful!):
126
+
127
+ ```typescript
128
+ import { unsafeHTML } from '@cossackframework/renderer';
129
+ html`<div>${unsafeHTML('<script>...</script>')}</div>`
130
+ ```
131
+
132
+ ## Using Components in Templates
133
+
134
+ Use the `component` helper function to include child components in your templates.
135
+
136
+ ```typescript
137
+ import { component } from '@cossackframework/renderer';
138
+ import { ChildComponent } from './ChildComponent';
139
+
140
+ html`
141
+ <div class="parent">
142
+ ${component(ChildComponent, { someProp: 'value' })}
143
+ </div>
144
+ `
145
+ ```
146
+
147
+ You can also pass children to components:
148
+
149
+ ```typescript
150
+ html`
151
+ <div class="parent">
152
+ ${component(ChildComponent, { someProp: 'value' }, html`
153
+ <span>Child content</span>
154
+ `)}
155
+ </div>
156
+ `
157
+ ```
158
+
159
+ ## Directives
160
+
161
+ Cossack includes standard Lit directives.
162
+
163
+ ### `repeat` (Keyed Lists)
164
+
165
+ Efficiently renders lists by key.
166
+
167
+ ```typescript
168
+ import { repeat } from '@cossackframework/renderer';
169
+
170
+ html`
171
+ <ul>
172
+ ${repeat(items, (item) => item.id, (item) => html`
173
+ <li>${item.text}</li>
174
+ `)}
175
+ </ul>
176
+ `
177
+ ```
178
+
179
+ ### `classMap` & `styleMap`
180
+
181
+ Dynamic classes and styles.
182
+
183
+ ```typescript
184
+ import { classMap, styleMap } from '@cossackframework/renderer';
185
+
186
+ const classes = { active: isActive, error: hasError };
187
+ const styles = { color: 'red', display: isVisible ? 'block' : 'none' };
188
+
189
+ html`<div class="${classMap(classes)}" style="${styleMap(styles)}">...</div>`
190
+ ```
191
+
192
+ ### `ref`
193
+
194
+ Get a reference to the DOM element.
195
+
196
+ ```typescript
197
+ import { ref } from '@cossackframework/renderer';
198
+
199
+ html`<input ref="${(el) => console.log(el)}" />`
200
+ ```
201
+
202
+ ### `live`
203
+
204
+ Check against the live DOM value (useful for inputs).
205
+
206
+ ```typescript
207
+ import { live } from '@cossackframework/renderer';
208
+
209
+ html`<input .value="${live(inputValue)}" />`
210
+ ```
211
+
212
+ ## Context API
213
+
214
+ Share state deep in the tree.
215
+
216
+ ### 1. Create Context
217
+
218
+ ```typescript
219
+ import { createContext } from '@cossackframework/renderer';
220
+
221
+ export const ThemeContext = createContext('light'); // Default value
222
+ ```
223
+
224
+ ### 2. Provide Context
225
+
226
+ ```typescript
227
+ class App extends CossackElement {
228
+ render() {
229
+ this.provide(ThemeContext, 'dark');
230
+ return html`${component(Child)}`;
231
+ }
232
+ }
233
+ ```
234
+
235
+ ### 3. Consume Context
236
+
237
+ ```typescript
238
+ class Child extends CossackElement {
239
+ render() {
240
+ const theme = this.consume(ThemeContext);
241
+ return html`<span>Theme is ${theme}</span>`;
242
+ }
243
+ }
244
+ ```
245
+
246
+ ## Reactive Controllers
247
+
248
+ Reuse logic across components using controllers.
249
+
250
+ ```typescript
251
+ import { ReactiveController, ReactiveControllerHost } from '@cossackframework/renderer';
252
+
253
+ class ClockController implements ReactiveController {
254
+ host: ReactiveControllerHost;
255
+ value = new Date();
256
+ private timer?: number;
257
+
258
+ constructor(host: ReactiveControllerHost) {
259
+ this.host = host;
260
+ host.addController(this);
261
+ }
262
+
263
+ hostConnected() {
264
+ this.timer = setInterval(() => {
265
+ this.value = new Date();
266
+ this.host.requestUpdate();
267
+ }, 1000);
268
+ }
269
+
270
+ hostDisconnected() {
271
+ clearInterval(this.timer);
272
+ }
273
+ }
274
+
275
+ class ClockElement extends CossackElement {
276
+ private clock = new ClockController(this);
277
+
278
+ render() {
279
+ return html`<time>${this.clock.value.toLocaleTimeString()}</time>`;
280
+ }
281
+ }
282
+ ```
283
+
284
+ ## Children Projection (Slots)
285
+
286
+ Cossack supports passing children to components.
287
+
288
+ **Parent:**
289
+ ```typescript
290
+ html`
291
+ ${component(Card, {}, html`
292
+ <h1>Title</h1>
293
+ <p>Content</p>
294
+ `)}
295
+ `
296
+ ```
297
+
298
+ **Child (Card):**
299
+ ```typescript
300
+ class Card extends CossackElement {
301
+ render() {
302
+ return html`
303
+ <div class="card">
304
+ ${this.children}
305
+ </div>
306
+ `;
307
+ }
308
+ }
309
+ ```
@@ -28,6 +28,7 @@ export declare const popCurrentInstance: () => CossackElement | undefined;
28
28
  export declare class CossackElement implements ReactiveControllerHost {
29
29
  static properties: PropertyDeclarations;
30
30
  static readonly _isCossackElement = true;
31
+ static components: Record<string, typeof CossackElement>;
31
32
  children: unknown;
32
33
  props: Record<string, unknown>;
33
34
  __parent: CossackElement | null;
@@ -0,0 +1,426 @@
1
+ //#region src/component.ts
2
+ var e = (e) => typeof e == "object" && !!e && e._type === "COMPONENT", t = [], n = (e) => t.push(e), r = () => t.pop(), i = class {
3
+ static properties = {};
4
+ static _isCossackElement = !0;
5
+ static components = {};
6
+ children = null;
7
+ props = {};
8
+ __parent = null;
9
+ _id = "";
10
+ _childCounter = 0;
11
+ __providedContexts = /* @__PURE__ */ new Map();
12
+ __properties = /* @__PURE__ */ new Map();
13
+ __updatePromise = null;
14
+ __changedProperties = /* @__PURE__ */ new Map();
15
+ __renderListeners = /* @__PURE__ */ new Set();
16
+ __controllers = /* @__PURE__ */ new Set();
17
+ __hasConnected = !1;
18
+ __eventListeners = /* @__PURE__ */ new Map();
19
+ constructor() {
20
+ this.initialize();
21
+ }
22
+ static get currentRenderingInstance() {
23
+ return t.length > 0 ? t[t.length - 1] : null;
24
+ }
25
+ resetRenderState() {
26
+ this._childCounter = 0;
27
+ }
28
+ addController(e) {
29
+ this.__controllers.add(e), this.__hasConnected && e.hostConnected && e.hostConnected();
30
+ }
31
+ removeController(e) {
32
+ this.__controllers.delete(e);
33
+ }
34
+ get updateComplete() {
35
+ return this.__updatePromise || Promise.resolve(!0);
36
+ }
37
+ initialize() {
38
+ let e = this.constructor.properties;
39
+ if (e) for (let [t, n] of Object.entries(e)) this.createProperty(t, n);
40
+ }
41
+ createProperty(e, t) {
42
+ Object.prototype.hasOwnProperty.call(this, e) && this.__properties.set(e, this[e]), Object.defineProperty(this, e, {
43
+ get() {
44
+ return this.__properties.get(e);
45
+ },
46
+ set(t) {
47
+ let n = this.__properties.get(e);
48
+ n !== t && (this.__properties.set(e, t), this.requestUpdate(e, n));
49
+ },
50
+ configurable: !0,
51
+ enumerable: !0
52
+ });
53
+ }
54
+ provide(e, t) {
55
+ this.__providedContexts.set(e, t);
56
+ }
57
+ consume(e) {
58
+ let t = this.__parent;
59
+ for (; t;) {
60
+ if (t.__providedContexts.has(e)) return t.__providedContexts.get(e);
61
+ t = t.__parent;
62
+ }
63
+ return e.defaultValue;
64
+ }
65
+ requestUpdate(e, t) {
66
+ return e !== void 0 && (this.__changedProperties.has(e) || this.__changedProperties.set(e, t)), this.__updatePromise ||= this.performUpdate(), this.__updatePromise;
67
+ }
68
+ async performUpdate() {
69
+ await Promise.resolve();
70
+ let e = !1;
71
+ try {
72
+ if (e = this.shouldUpdate(this.__changedProperties), e) {
73
+ this.__controllers.forEach((e) => e.hostUpdate && e.hostUpdate()), this.willUpdate(this.__changedProperties), this.resetRenderState(), n(this);
74
+ let e = this.render();
75
+ this.__notifyListeners(e), r(), this.updated(this.__changedProperties), this.__controllers.forEach((e) => e.hostUpdated && e.hostUpdated());
76
+ }
77
+ } catch (e) {
78
+ console.error("Error during update:", e), t[t.length - 1] === this && r();
79
+ }
80
+ return this.__changedProperties = /* @__PURE__ */ new Map(), this.__updatePromise = null, e;
81
+ }
82
+ __notifyListeners(e) {
83
+ this.__renderListeners.forEach((t) => t(e));
84
+ }
85
+ addRenderListener(e) {
86
+ this.__renderListeners.add(e);
87
+ }
88
+ removeRenderListener(e) {
89
+ this.__renderListeners.delete(e);
90
+ }
91
+ mount(e) {
92
+ this.addRenderListener((t) => {
93
+ t && (h(t) ? O(t, e) : O(f`${t}`, e));
94
+ }), this.requestUpdate();
95
+ }
96
+ addEventListener(e, t, n) {
97
+ t && (this.__eventListeners.has(e) || this.__eventListeners.set(e, /* @__PURE__ */ new Set()), this.__eventListeners.get(e).add(t));
98
+ }
99
+ removeEventListener(e, t, n) {
100
+ if (!t) return;
101
+ let r = this.__eventListeners.get(e);
102
+ r && r.delete(t);
103
+ }
104
+ dispatchEvent(e) {
105
+ let t = this.__eventListeners.get(e.type);
106
+ return t && t.forEach((t) => {
107
+ typeof t == "function" ? t.call(this, e) : t.handleEvent(e);
108
+ }), !e.defaultPrevented;
109
+ }
110
+ shouldUpdate(e) {
111
+ return !0;
112
+ }
113
+ willUpdate(e) {}
114
+ render() {
115
+ return null;
116
+ }
117
+ updated(e) {}
118
+ connectedCallback() {
119
+ this.__hasConnected = !0, this.__controllers.forEach((e) => e.hostConnected && e.hostConnected());
120
+ }
121
+ disconnectedCallback() {
122
+ this.__hasConnected = !1, this.__controllers.forEach((e) => e.hostDisconnected && e.hostDisconnected());
123
+ }
124
+ }, a = class {
125
+ value;
126
+ constructor(e) {
127
+ this.value = e;
128
+ }
129
+ }, o = class {
130
+ items;
131
+ keyFn;
132
+ templateFn;
133
+ constructor(e, t, n) {
134
+ this.items = e, this.keyFn = t, this.templateFn = n;
135
+ }
136
+ }, s = (e) => new a(e), c = (e, t, n) => n === void 0 ? new o(e, (e, t) => t, t) : new o(e, t, n), l = (e) => Object.keys(e).filter((t) => e[t]).join(" "), u = (e) => Object.keys(e).filter((t) => e[t] != null).map((t) => `${t}:${e[t]}`).join(";"), d = class {
137
+ strings;
138
+ values;
139
+ _cossack_template_result = !0;
140
+ constructor(e, t) {
141
+ this.strings = e, this.values = t;
142
+ }
143
+ }, f = (e, ...t) => new d(e, t), p = f, m = (e, t = {}, n) => f`${{
144
+ _type: "COMPONENT",
145
+ clazz: e,
146
+ props: t,
147
+ children: n
148
+ }}`, h = (e) => typeof e == "object" && !!e && e._cossack_template_result === !0, g = class {
149
+ value;
150
+ constructor(e) {
151
+ this.value = e;
152
+ }
153
+ }, _ = (e) => new g(e), v = (e) => e instanceof g, y = (e) => String(e).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"), b = (t) => {
154
+ if (t == null || t === !1) return "";
155
+ if (Array.isArray(t)) return t.map(b).join("");
156
+ if (h(t)) return C(t);
157
+ if (t instanceof a) return b(t.value);
158
+ if (t instanceof o) return t.items.map((e, n) => b(t.templateFn(e, n))).join("");
159
+ if (e(t)) {
160
+ let e = new t.clazz();
161
+ Object.assign(e, t.props), "props" in e && (e.props = t.props), e.children = t.children, e.__parent = i.currentRenderingInstance, e.__parent && (e._id = `${e.__parent._id}:${e.__parent._childCounter++}`), e.connectedCallback(), n(e), e.willUpdate(/* @__PURE__ */ new Map());
162
+ let a = e.render(), o = "";
163
+ return a && (o = h(a) ? C(a) : C(f`${a}`)), r(), o;
164
+ }
165
+ return v(t) ? t.value : typeof t == "function" || typeof t == "object" && t && "value" in t ? "" : y(t);
166
+ }, x = (e) => {
167
+ let t = "";
168
+ if (typeof e == "object" && e) for (let [n, r] of Object.entries(e)) {
169
+ if (n.startsWith("@")) continue;
170
+ let e = n, i = r;
171
+ if (n.startsWith("?")) {
172
+ r && (t += ` ${n.slice(1)}`);
173
+ continue;
174
+ }
175
+ n.startsWith(".") && (e = n.slice(1)), typeof i == "boolean" ? i && (t += ` ${e}`) : typeof i == "function" || i != null && (t += ` ${e}="${y(i)}"`);
176
+ }
177
+ return t;
178
+ }, S = class {
179
+ resultObj;
180
+ result = "";
181
+ stringIdx = 0;
182
+ charIdxForNext = 0;
183
+ constructor(e) {
184
+ this.resultObj = e;
185
+ }
186
+ scan() {
187
+ let { strings: e, values: t } = this.resultObj;
188
+ for (; this.stringIdx < e.length;) {
189
+ let n = e[this.stringIdx].substring(this.charIdxForNext || 0), r = n.match(/(\.\.\.|[.@?]?[a-zA-Z0-9_-]+)=["']?$/);
190
+ if (this.result += n, this.charIdxForNext = 0, this.stringIdx < e.length - 1) {
191
+ let n = t[this.stringIdx];
192
+ if (r) {
193
+ let t = r[0], i = r[1];
194
+ this.result = this.result.substring(0, this.result.length - t.length);
195
+ let a = t.endsWith("\"") ? "\"" : t.endsWith("'") ? "'" : "", o = !0;
196
+ if (i === "..." ? (this.result = this.result.trimEnd(), this.result += x(n)) : i.startsWith("@") ? this.result = this.result.trimEnd() : i.startsWith("?") ? n ? (this.result = this.result.trimEnd(), this.result += ` ${i.slice(1)}`) : this.result = this.result.trimEnd() : i.startsWith(".") ? n != null && n !== !1 ? (this.result = this.result.trimEnd(), this.result += ` ${i.slice(1)}="${b(n)}"`) : this.result = this.result.trimEnd() : (this.result += t, this.result += b(n), o = !1), a && o) {
197
+ let t = e[this.stringIdx + 1];
198
+ t && t.startsWith(a) && (this.charIdxForNext = 1);
199
+ }
200
+ } else this.result += b(n);
201
+ }
202
+ this.stringIdx++;
203
+ }
204
+ return this.result;
205
+ }
206
+ }, C = (e) => new S(e).scan(), w = class t {
207
+ startNode;
208
+ endNode;
209
+ componentInstance = null;
210
+ renderListener = null;
211
+ _childParts = [];
212
+ _partKeys = [];
213
+ _cachedTemplateStrings = null;
214
+ _cachedParts = null;
215
+ constructor(e, t) {
216
+ this.startNode = e, this.endNode = t;
217
+ }
218
+ update(t) {
219
+ this.componentInstance && (!e(t) || t.clazz !== this.componentInstance.constructor) && this.disposeComponent(), !(t instanceof o) && !Array.isArray(t) && this._childParts.length > 0 && this.clearChildParts(), e(t) ? this.updateComponent(t) : t instanceof o ? this.updateRepeat(t) : Array.isArray(t) ? this.updateArray(t) : this.updateNode(t);
220
+ }
221
+ disposeComponent() {
222
+ this.componentInstance && (this.renderListener && this.componentInstance.removeRenderListener(this.renderListener), this.componentInstance.disconnectedCallback(), this.componentInstance = null, this.renderListener = null, this._clearTemplateCache());
223
+ }
224
+ updateComponent(e) {
225
+ this.componentInstance || (this.componentInstance = new e.clazz(), this.componentInstance.__parent = i.currentRenderingInstance, this.componentInstance.__parent && (this.componentInstance._id = `${this.componentInstance.__parent._id}:${this.componentInstance.__parent._childCounter++}`), this.renderListener = (e) => {
226
+ this.updateNode(e);
227
+ }, this.componentInstance.addRenderListener(this.renderListener), this.componentInstance.connectedCallback());
228
+ let t = this.componentInstance;
229
+ Object.assign(t, e.props), "props" in t && (t.props = e.props), t.children = e.children, t.requestUpdate();
230
+ }
231
+ updateRepeat(e) {
232
+ let { items: t, keyFn: n, templateFn: r } = e, i = /* @__PURE__ */ new Map();
233
+ this._childParts.forEach((e, t) => {
234
+ let n = this._partKeys[t];
235
+ n !== void 0 && i.set(n, e);
236
+ });
237
+ let a = [], o = [], s = this.startNode;
238
+ t.forEach((e, t) => {
239
+ let c = n(e, t);
240
+ o.push(c);
241
+ let l = i.get(c);
242
+ l ? (i.delete(c), l.startNode.previousSibling !== s && this.movePart(l, s), l.update(r(e, t))) : (l = this.createChildPart(s), l.update(r(e, t))), a.push(l), s = l.endNode;
243
+ }), i.forEach((e) => e.dispose()), this._childParts = a, this._partKeys = o;
244
+ }
245
+ updateArray(e) {
246
+ this._partKeys = [];
247
+ let t = Math.min(e.length, this._childParts.length);
248
+ for (let n = 0; n < t; n++) this._childParts[n].update(e[n]);
249
+ if (e.length > this._childParts.length) {
250
+ let n = this._childParts.length > 0 ? this._childParts[this._childParts.length - 1].endNode : this.startNode;
251
+ for (let r = t; r < e.length; r++) {
252
+ let t = this.createChildPart(n);
253
+ this._childParts.push(t), t.update(e[r]), n = t.endNode;
254
+ }
255
+ }
256
+ if (e.length < this._childParts.length) for (let t = this._childParts.length - 1; t >= e.length; t--) this._childParts[t].dispose(), this._childParts.pop();
257
+ }
258
+ createChildPart(e) {
259
+ let n = document.createComment("CRP-Item"), r = document.createComment("/CRP-Item"), i = e.nextSibling;
260
+ return e.parentNode.insertBefore(n, i), e.parentNode.insertBefore(r, i), new t(n, r);
261
+ }
262
+ movePart(e, t) {
263
+ let n = t.parentNode, r = [], i = e.startNode;
264
+ for (; i && i !== e.endNode;) r.push(i), i = i.nextSibling;
265
+ r.push(e.endNode);
266
+ let a = t.nextSibling;
267
+ r.forEach((e) => n.insertBefore(e, a));
268
+ }
269
+ clearChildParts() {
270
+ this._childParts.forEach((e) => e.dispose()), this._childParts = [], this._partKeys = [];
271
+ }
272
+ dispose() {
273
+ this.clear(), this._clearTemplateCache(), this.clearChildParts(), this.startNode.parentNode && this.startNode.parentNode.removeChild(this.startNode), this.endNode.parentNode && this.endNode.parentNode.removeChild(this.endNode), this.componentInstance && (this.renderListener && this.componentInstance.removeRenderListener(this.renderListener), this.componentInstance.disconnectedCallback());
274
+ }
275
+ updateNode(t) {
276
+ if (this.startNode.parentNode) if (h(t)) if (this._cachedTemplateStrings === t.strings && this._cachedParts) this._cachedParts.forEach((e, n) => {
277
+ e.update(t.values[n]);
278
+ });
279
+ else {
280
+ this._clearTemplateCache(), this.clear();
281
+ let e = document.createDocumentFragment();
282
+ O(t, e), this.startNode.parentNode.insertBefore(e, this.endNode);
283
+ let n = D.get(e.firstChild?.childNodes[0] || e);
284
+ n && (this._cachedTemplateStrings = n.strings, this._cachedParts = n.parts);
285
+ }
286
+ else if (e(t) || typeof t == "object" && t && !(t instanceof Node) && !Array.isArray(t)) {
287
+ this._clearTemplateCache(), this.clear();
288
+ let e = document.createDocumentFragment();
289
+ O(f`${t}`, e), this.startNode.parentNode.insertBefore(e, this.endNode);
290
+ } else if (v(t)) {
291
+ this._clearTemplateCache(), this.clear();
292
+ let e = document.createElement("template");
293
+ e.innerHTML = t.value, this.startNode.parentNode.insertBefore(e.content, this.endNode);
294
+ } else if (t instanceof Node) this._clearTemplateCache(), this.clear(), this.startNode.parentNode.insertBefore(t, this.endNode);
295
+ else if (t == null || t === !1) this._clearTemplateCache(), this.clear();
296
+ else {
297
+ let e = String(t), n = this.startNode.nextSibling;
298
+ if (n && n.nodeType === Node.TEXT_NODE && n.nextSibling === this.endNode) n.nodeValue !== e && (n.nodeValue = e);
299
+ else {
300
+ this._clearTemplateCache(), this.clear();
301
+ let t = document.createTextNode(e);
302
+ this.startNode.parentNode.insertBefore(t, this.endNode);
303
+ }
304
+ }
305
+ }
306
+ _clearTemplateCache() {
307
+ this._cachedTemplateStrings = null, this._cachedParts = null;
308
+ }
309
+ clear() {
310
+ let e = this.startNode.nextSibling;
311
+ for (; e && e !== this.endNode;) {
312
+ let t = e.nextSibling;
313
+ e.parentNode.removeChild(e), e = t;
314
+ }
315
+ }
316
+ }, T = class {
317
+ element;
318
+ previousValues = {};
319
+ constructor(e) {
320
+ this.element = e;
321
+ }
322
+ update(e) {
323
+ if (typeof e != "object" || !e) return;
324
+ let t = e;
325
+ for (let e of Object.keys(this.previousValues)) if (!(e in t)) if (e.startsWith("@")) {
326
+ let t = e.slice(1), n = `__crp_handler_${t}`, r = this.element[n];
327
+ r && this.element.removeEventListener(t, r);
328
+ } else e.startsWith(".") || (e.startsWith("?") ? this.element.removeAttribute(e.slice(1)) : this.element.removeAttribute(e));
329
+ for (let [e, n] of Object.entries(t)) if (e.startsWith("@") && typeof n == "function") {
330
+ let t = e.slice(1), r = `__crp_handler_${t}`, i = this.element[r];
331
+ i && this.element.removeEventListener(t, i), this.element[r] = n, this.element.addEventListener(t, n);
332
+ } else e.startsWith(".") ? this.element[e.slice(1)] = n : e.startsWith("?") ? n ? this.element.setAttribute(e.slice(1), "") : this.element.removeAttribute(e.slice(1)) : typeof n == "boolean" ? n ? this.element.setAttribute(e, "") : this.element.removeAttribute(e) : n != null && this.element.setAttribute(e, String(n));
333
+ this.previousValues = { ...t };
334
+ }
335
+ }, E = class {
336
+ element;
337
+ name;
338
+ prefix;
339
+ suffix;
340
+ constructor(e, t, n) {
341
+ this.element = e, this.name = t;
342
+ let r = n.indexOf("__CRP_");
343
+ if (r !== -1) {
344
+ let e = r + 6, t = n.indexOf("__", e);
345
+ this.prefix = n.substring(0, r), this.suffix = n.substring(t + 2);
346
+ } else this.prefix = "", this.suffix = "";
347
+ }
348
+ update(e) {
349
+ if (e instanceof a && (e = e.value), this.name === "ref") {
350
+ typeof e == "function" ? e(this.element) : e && typeof e == "object" && "value" in e && (e.value = this.element), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
351
+ return;
352
+ }
353
+ if (this.name.startsWith("@") && typeof e == "function") {
354
+ let t = this.name.slice(1), n = `__crp_handler_${t}`, r = this.element[n];
355
+ r && this.element.removeEventListener(t, r), this.element[n] = e, this.element.addEventListener(t, e), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
356
+ } else if (this.name.startsWith(".")) {
357
+ let t = this.name.slice(1);
358
+ this.element[t] = e, this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
359
+ } else if (this.name.startsWith("?")) {
360
+ let t = this.name.slice(1);
361
+ e ? this.element.setAttribute(t, "") : this.element.removeAttribute(t), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
362
+ } else if (this.name === "value" && (this.element instanceof HTMLInputElement || this.element instanceof HTMLTextAreaElement)) this.element.value !== String(e) && (this.element.value = String(e)), this.element.setAttribute(this.name, String(e));
363
+ else if (this.name === "checked" && this.element instanceof HTMLInputElement) {
364
+ let t = !!e;
365
+ this.element.checked !== t && (this.element.checked = t), t ? this.element.setAttribute(this.name, "") : this.element.removeAttribute(this.name);
366
+ } else typeof e == "boolean" ? e ? this.element.setAttribute(this.name, "") : this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, this.prefix + String(e) + this.suffix);
367
+ }
368
+ }, D = /* @__PURE__ */ new WeakMap(), O = (e, t) => {
369
+ let n = D.get(t);
370
+ if (n && n.strings === e.strings) {
371
+ n.parts.forEach((t, n) => {
372
+ t.update(e.values[n]);
373
+ });
374
+ return;
375
+ }
376
+ let r = [], i = e.values, a = "", o = !1, s = null, c = /(\.\.\.|[.@?]?[a-zA-Z0-9_-]+)=["']?$/;
377
+ for (let t = 0; t < e.strings.length - 1; t++) {
378
+ let n = e.strings[t];
379
+ for (let e = 0; e < n.length; e++) s ? n[e] === s && (s = null) : n[e] === "\"" || n[e] === "'" ? e > 0 && n[e - 1] === "=" && (s = n[e]) : n[e] === "<" && n[e + 1] !== "!" && n[e + 1] !== "/" ? o = !0 : n[e] === ">" && (o = !1);
380
+ a += n;
381
+ let r = n.match(c);
382
+ if (o && (r || s)) {
383
+ if (a += `__CRP_${t}__`, r && !s) {
384
+ let e = r[0].endsWith("\"") ? "\"" : r[0].endsWith("'") ? "'" : null;
385
+ e && (s = e);
386
+ }
387
+ } else a += `<!--CRP_${t}-->`;
388
+ }
389
+ let l = e.strings[e.strings.length - 1];
390
+ for (let e = 0; e < l.length; e++) s ? l[e] === s && (s = null) : l[e] === "<" && l[e + 1] !== "!" && l[e + 1] !== "/" ? o = !0 : l[e] === ">" && (o = !1);
391
+ a += l;
392
+ let u = document.createElement("template");
393
+ u.innerHTML = a;
394
+ let d = u.content.cloneNode(!0), f = document.createTreeWalker(d, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT), p, m = [];
395
+ for (; p = f.nextNode();) m.push(p);
396
+ m.forEach((e) => {
397
+ if (e.nodeType === Node.COMMENT_NODE) {
398
+ let t = e.nodeValue?.match(/CRP_(\d+)/);
399
+ if (t) {
400
+ let n = parseInt(t[1]), i = document.createComment("/CRP");
401
+ e.parentNode.insertBefore(i, e.nextSibling), r[n] = new w(e, i);
402
+ }
403
+ } else if (e.nodeType === Node.ELEMENT_NODE) {
404
+ let t = e;
405
+ Array.from(t.attributes).forEach((e) => {
406
+ let n = e.value.match(/__CRP_(\d+)__/);
407
+ if (n) {
408
+ let i = parseInt(n[1]);
409
+ r[i] || (e.name === "..." ? (r[i] = new T(t), t.removeAttribute("...")) : r[i] = new E(t, e.name, e.value));
410
+ }
411
+ });
412
+ }
413
+ });
414
+ for (let e = 0; e < i.length; e++) r[e] && r[e].update(i[e]);
415
+ if (t instanceof HTMLElement) t.innerHTML = "", t.appendChild(d);
416
+ else if (t instanceof DocumentFragment) {
417
+ for (; t.firstChild;) t.removeChild(t.firstChild);
418
+ t.appendChild(d);
419
+ }
420
+ D.set(t, {
421
+ strings: e.strings,
422
+ parts: r
423
+ });
424
+ };
425
+ //#endregion
426
+ export { e as S, u as _, f as a, r as b, O as c, _ as d, a as f, c as g, s as h, y as i, C as l, l as m, g as n, h as o, o as p, m as r, v as s, d as t, p as u, i as v, n as x, t as y };
package/dist/index.js CHANGED
@@ -1,32 +1,10 @@
1
- import { C as n, L as r, R as l, T as p, U as o, k as u, c, e as i, h as m, d as R, g as T, i as f, a as C, l as M, f as d, p as L, b as g, r as h, j as H, m as k, s as v, u as x } from "./server-BEO1YttH.js";
2
- function e(s) {
3
- return {
4
- id: Math.random().toString(36).slice(2),
5
- defaultValue: s
6
- };
1
+ import { S as e, _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p, p as m, r as h, s as g, t as _, u as v, v as y, x as b, y as x } from "./cossack-html-CCHKnNWv.js";
2
+ //#region src/context.ts
3
+ function S(e) {
4
+ return {
5
+ id: Math.random().toString(36).slice(2),
6
+ defaultValue: e
7
+ };
7
8
  }
8
- export {
9
- n as CossackElement,
10
- r as LiveResult,
11
- l as RepeatResult,
12
- p as TemplateResult,
13
- o as UnsafeHTMLResult,
14
- u as classMap,
15
- c as component,
16
- e as createContext,
17
- i as escapeHtml,
18
- m as html,
19
- R as instanceStack,
20
- T as isComponentResult,
21
- f as isTemplateResult,
22
- C as isUnsafeHTML,
23
- M as live,
24
- d as popCurrentInstance,
25
- L as pushCurrentInstance,
26
- g as render,
27
- h as renderToString,
28
- H as repeat,
29
- k as styleMap,
30
- v as svg,
31
- x as unsafeHTML
32
- };
9
+ //#endregion
10
+ export { y as CossackElement, o as LiveResult, m as RepeatResult, _ as TemplateResult, f as UnsafeHTMLResult, d as classMap, h as component, S as createContext, l as escapeHtml, n as html, x as instanceStack, e as isComponentResult, p as isTemplateResult, g as isUnsafeHTML, c as live, r as popCurrentInstance, b as pushCurrentInstance, i as render, u as renderToString, s as repeat, t as styleMap, v as svg, a as unsafeHTML };
@@ -0,0 +1 @@
1
+ export declare function minifyHtml(html: string): string;
@@ -0,0 +1 @@
1
+ export {};
package/dist/server.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { renderToString, escapeHtml } from './cossack-html';
2
+ export { minifyHtml } from './minify-html';
package/dist/server.js CHANGED
@@ -1,5 +1,37 @@
1
- import { e as a, r as o } from "./server-BEO1YttH.js";
2
- export {
3
- a as escapeHtml,
4
- o as renderToString
5
- };
1
+ import { i as e, l as t } from "./cossack-html-CCHKnNWv.js";
2
+ //#region src/minify-html.ts
3
+ var n = /<(script|style|pre|textarea)\b[^>]*>[\s\S]*?<\/\1>/gi, r = RegExp(`<(${[...new Set([
4
+ "area",
5
+ "base",
6
+ "br",
7
+ "col",
8
+ "embed",
9
+ "hr",
10
+ "img",
11
+ "input",
12
+ "link",
13
+ "meta",
14
+ "param",
15
+ "source",
16
+ "track",
17
+ "wbr"
18
+ ])].join("|")})(\\s[^>]*)?\\/\\s*>`, "gi"), i = /\s+type\s*=\s*["']text\/(javascript|css)["']/gi, a = /(\w[\w-]*)\s*=\s*["']([a-zA-Z0-9_.-]+)["']/g;
19
+ function o(e) {
20
+ let t = [];
21
+ return {
22
+ html: e.replace(n, (e) => {
23
+ let n = e.replace(i, "");
24
+ return t.push(n), `\x00PRESERVE_${t.length - 1}\x00`;
25
+ }),
26
+ blocks: t
27
+ };
28
+ }
29
+ function s(e, t) {
30
+ return e.replace(/\x00PRESERVE_(\d+)\x00/g, (e, n) => t[parseInt(n, 10)]);
31
+ }
32
+ function c(e) {
33
+ let { html: t, blocks: n } = o(e), c = t.replace(/<!--(?!\[if\s)[\s\S]*?-->/g, "");
34
+ return c = c.replace(i, ""), c = c.replace(/\s+/g, " "), c = c.replace(/>\s+</g, "><"), c = c.replace(a, (e, t, n) => `${t}=${n}`), c = c.replace(r, (e, t, n) => `<${t}${n ? n.trimEnd() : ""}>`), c = s(c, n), c = c.replace(/>\s+</g, "><"), c = c.trim(), c;
35
+ }
36
+ //#endregion
37
+ export { e as escapeHtml, c as minifyHtml, t as renderToString };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cossackframework/renderer",
3
- "version": "0.1.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Light DOM rendering engine for the Cossack Framework",
6
6
  "license": "MIT",
@@ -31,10 +31,10 @@
31
31
  "htmlparser2": "^10.0.0",
32
32
  "magic-string": "^0.30.21",
33
33
  "oxlint": "^1.41.0",
34
- "vite": "^5.3.5",
34
+ "vite": "^8.0.0",
35
35
  "vite-plugin-dts": "^3.9.1",
36
36
  "vite-tsconfig-paths": "^5.1.4",
37
- "vitest": "^1.2.2"
37
+ "vitest": "^3.2.4"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "vite build",
@@ -1,491 +0,0 @@
1
- var F = Object.defineProperty;
2
- var z = (n, e, s) => e in n ? F(n, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : n[e] = s;
3
- var h = (n, e, s) => z(n, typeof e != "symbol" ? e + "" : e, s);
4
- const L = (n) => typeof n == "object" && n !== null && n._type === "COMPONENT", g = [], k = (n) => g.push(n), x = () => g.pop();
5
- class T {
6
- constructor() {
7
- // Holds content projected from the parent
8
- h(this, "children", null);
9
- h(this, "props", {});
10
- // Context Support
11
- h(this, "__parent", null);
12
- h(this, "_id", "");
13
- h(this, "_childCounter", 0);
14
- h(this, "__providedContexts", /* @__PURE__ */ new Map());
15
- h(this, "__properties", /* @__PURE__ */ new Map());
16
- h(this, "__updatePromise", null);
17
- h(this, "__changedProperties", /* @__PURE__ */ new Map());
18
- h(this, "__renderListeners", /* @__PURE__ */ new Set());
19
- // Controllers
20
- h(this, "__controllers", /* @__PURE__ */ new Set());
21
- h(this, "__hasConnected", !1);
22
- h(this, "__eventListeners", /* @__PURE__ */ new Map());
23
- this.initialize();
24
- }
25
- // --- Static Stack Access for cossack-html ---
26
- static get currentRenderingInstance() {
27
- return g.length > 0 ? g[g.length - 1] : null;
28
- }
29
- resetRenderState() {
30
- this._childCounter = 0;
31
- }
32
- // --- Controller API ---
33
- addController(e) {
34
- this.__controllers.add(e), this.__hasConnected && e.hostConnected && e.hostConnected();
35
- }
36
- removeController(e) {
37
- this.__controllers.delete(e);
38
- }
39
- get updateComplete() {
40
- return this.__updatePromise || Promise.resolve(!0);
41
- }
42
- initialize() {
43
- const s = this.constructor.properties;
44
- if (s)
45
- for (const [t, i] of Object.entries(s))
46
- this.createProperty(t, i);
47
- }
48
- createProperty(e, s) {
49
- Object.prototype.hasOwnProperty.call(this, e) && this.__properties.set(e, this[e]), Object.defineProperty(this, e, {
50
- get() {
51
- return this.__properties.get(e);
52
- },
53
- set(t) {
54
- const i = this.__properties.get(e);
55
- i !== t && (this.__properties.set(e, t), this.requestUpdate(e, i));
56
- },
57
- configurable: !0,
58
- enumerable: !0
59
- });
60
- }
61
- provide(e, s) {
62
- this.__providedContexts.set(e, s);
63
- }
64
- consume(e) {
65
- let s = this.__parent;
66
- for (; s; ) {
67
- if (s.__providedContexts.has(e))
68
- return s.__providedContexts.get(e);
69
- s = s.__parent;
70
- }
71
- return e.defaultValue;
72
- }
73
- requestUpdate(e, s) {
74
- return e !== void 0 && (this.__changedProperties.has(e) || this.__changedProperties.set(e, s)), this.__updatePromise || (this.__updatePromise = this.performUpdate()), this.__updatePromise;
75
- }
76
- async performUpdate() {
77
- await Promise.resolve();
78
- let e = !1;
79
- try {
80
- if (e = this.shouldUpdate(this.__changedProperties), e) {
81
- this.__controllers.forEach((t) => t.hostUpdate && t.hostUpdate()), this.willUpdate(this.__changedProperties), this.resetRenderState(), k(this);
82
- const s = this.render();
83
- this.__notifyListeners(s), x(), this.updated(this.__changedProperties), this.__controllers.forEach((t) => t.hostUpdated && t.hostUpdated());
84
- }
85
- } catch (s) {
86
- console.error("Error during update:", s), g[g.length - 1] === this && x();
87
- }
88
- return this.__changedProperties = /* @__PURE__ */ new Map(), this.__updatePromise = null, e;
89
- }
90
- __notifyListeners(e) {
91
- this.__renderListeners.forEach((s) => s(e));
92
- }
93
- addRenderListener(e) {
94
- this.__renderListeners.add(e);
95
- }
96
- removeRenderListener(e) {
97
- this.__renderListeners.delete(e);
98
- }
99
- mount(e) {
100
- this.addRenderListener((s) => {
101
- s && (S(s) ? I(s, e) : I(E`${s}`, e));
102
- }), this.requestUpdate();
103
- }
104
- addEventListener(e, s, t) {
105
- s && (this.__eventListeners.has(e) || this.__eventListeners.set(e, /* @__PURE__ */ new Set()), this.__eventListeners.get(e).add(s));
106
- }
107
- removeEventListener(e, s, t) {
108
- if (!s) return;
109
- const i = this.__eventListeners.get(e);
110
- i && i.delete(s);
111
- }
112
- dispatchEvent(e) {
113
- const s = this.__eventListeners.get(e.type);
114
- return s && s.forEach((t) => {
115
- typeof t == "function" ? t.call(this, e) : t.handleEvent(e);
116
- }), !e.defaultPrevented;
117
- }
118
- shouldUpdate(e) {
119
- return !0;
120
- }
121
- willUpdate(e) {
122
- }
123
- render() {
124
- return null;
125
- }
126
- updated(e) {
127
- }
128
- connectedCallback() {
129
- this.__hasConnected = !0, this.__controllers.forEach((e) => e.hostConnected && e.hostConnected());
130
- }
131
- disconnectedCallback() {
132
- this.__hasConnected = !1, this.__controllers.forEach((e) => e.hostDisconnected && e.hostDisconnected());
133
- }
134
- }
135
- h(T, "properties", {}), h(T, "_isCossackElement", !0);
136
- class R {
137
- constructor(e) {
138
- this.value = e;
139
- }
140
- }
141
- class y {
142
- constructor(e, s, t) {
143
- this.items = e, this.keyFn = s, this.templateFn = t;
144
- }
145
- }
146
- const Z = (n) => new R(n), X = (n, e, s) => s === void 0 ? new y(n, (t, i) => i, e) : new y(n, e, s), G = (n) => Object.keys(n).filter((e) => n[e]).join(" "), J = (n) => Object.keys(n).filter((e) => n[e] != null).map((e) => `${e}:${n[e]}`).join(";");
147
- class B {
148
- constructor(e, s) {
149
- h(this, "_cossack_template_result", !0);
150
- this.strings = e, this.values = s;
151
- }
152
- }
153
- const E = (n, ...e) => new B(n, e), Q = E, Y = (n, e = {}, s) => E`${{
154
- _type: "COMPONENT",
155
- clazz: n,
156
- props: e,
157
- children: s
158
- }}`, S = (n) => typeof n == "object" && n !== null && n._cossack_template_result === !0;
159
- class W {
160
- constructor(e) {
161
- this.value = e;
162
- }
163
- }
164
- const ee = (n) => new W(n), U = (n) => n instanceof W, H = (n) => String(n).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"), N = (n) => {
165
- if (n == null || n === !1)
166
- return "";
167
- if (Array.isArray(n))
168
- return n.map(N).join("");
169
- if (S(n))
170
- return A(n);
171
- if (n instanceof R)
172
- return N(n.value);
173
- if (n instanceof y)
174
- return n.items.map((e, s) => N(n.templateFn(e, s))).join("");
175
- if (L(n)) {
176
- const e = new n.clazz();
177
- Object.assign(e, n.props), "props" in e && (e.props = n.props), e.children = n.children, e.__parent = T.currentRenderingInstance, e.__parent && (e._id = `${e.__parent._id}:${e.__parent._childCounter++}`), e.connectedCallback(), k(e), e.willUpdate(/* @__PURE__ */ new Map());
178
- const s = e.render();
179
- let t = "";
180
- return s && (S(s) ? t = A(s) : t = A(E`${s}`)), x(), t;
181
- }
182
- return U(n) ? n.value : typeof n == "function" || typeof n == "object" && n !== null && "value" in n ? "" : H(n);
183
- }, V = (n) => {
184
- let e = "";
185
- if (typeof n == "object" && n !== null)
186
- for (const [s, t] of Object.entries(n)) {
187
- if (s.startsWith("@")) continue;
188
- let i = s, r = t;
189
- if (s.startsWith("?")) {
190
- t && (e += ` ${s.slice(1)}`);
191
- continue;
192
- }
193
- s.startsWith(".") && (i = s.slice(1)), typeof r == "boolean" ? r && (e += ` ${i}`) : typeof r == "function" || r != null && (e += ` ${i}="${H(r)}"`);
194
- }
195
- return e;
196
- };
197
- class D {
198
- constructor(e) {
199
- h(this, "result", "");
200
- h(this, "stringIdx", 0);
201
- h(this, "charIdxForNext", 0);
202
- this.resultObj = e;
203
- }
204
- scan() {
205
- const { strings: e, values: s } = this.resultObj;
206
- for (; this.stringIdx < e.length; ) {
207
- const i = e[this.stringIdx].substring(this.charIdxForNext || 0), r = i.match(/(\.\.\.|[.@?]?[a-zA-Z0-9_-]+)=["']?$/);
208
- if (this.result += i, this.charIdxForNext = 0, this.stringIdx < e.length - 1) {
209
- const a = s[this.stringIdx];
210
- if (r) {
211
- const c = r[0], d = r[1];
212
- this.result = this.result.substring(0, this.result.length - c.length);
213
- const p = c.endsWith('"') ? '"' : c.endsWith("'") ? "'" : "";
214
- let m = !0;
215
- if (d === "..." ? (this.result = this.result.trimEnd(), this.result += V(a)) : d.startsWith("@") ? this.result = this.result.trimEnd() : d.startsWith("?") ? a ? (this.result = this.result.trimEnd(), this.result += ` ${d.slice(1)}`) : this.result = this.result.trimEnd() : d.startsWith(".") ? a != null && a !== !1 ? (this.result = this.result.trimEnd(), this.result += ` ${d.slice(1)}="${N(a)}"`) : this.result = this.result.trimEnd() : (this.result += c, this.result += N(a), m = !1), p && m) {
216
- const f = e[this.stringIdx + 1];
217
- f && f.startsWith(p) && (this.charIdxForNext = 1);
218
- }
219
- } else
220
- this.result += N(a);
221
- }
222
- this.stringIdx++;
223
- }
224
- return this.result;
225
- }
226
- }
227
- const A = (n) => new D(n).scan();
228
- class $ {
229
- constructor(e, s) {
230
- h(this, "componentInstance", null);
231
- h(this, "renderListener", null);
232
- h(this, "_childParts", []);
233
- h(this, "_partKeys", []);
234
- // Cache for nested template result updates
235
- h(this, "_cachedTemplateStrings", null);
236
- h(this, "_cachedParts", null);
237
- this.startNode = e, this.endNode = s;
238
- }
239
- update(e) {
240
- this.componentInstance && (!L(e) || e.clazz !== this.componentInstance.constructor) && this.disposeComponent(), !(e instanceof y) && !Array.isArray(e) && this._childParts.length > 0 && this.clearChildParts(), L(e) ? this.updateComponent(e) : e instanceof y ? this.updateRepeat(e) : Array.isArray(e) ? this.updateArray(e) : this.updateNode(e);
241
- }
242
- disposeComponent() {
243
- this.componentInstance && (this.renderListener && this.componentInstance.removeRenderListener(this.renderListener), this.componentInstance.disconnectedCallback(), this.componentInstance = null, this.renderListener = null, this._clearTemplateCache());
244
- }
245
- updateComponent(e) {
246
- this.componentInstance || (this.componentInstance = new e.clazz(), this.componentInstance.__parent = T.currentRenderingInstance, this.componentInstance.__parent && (this.componentInstance._id = `${this.componentInstance.__parent._id}:${this.componentInstance.__parent._childCounter++}`), this.renderListener = (t) => {
247
- this.updateNode(t);
248
- }, this.componentInstance.addRenderListener(this.renderListener), this.componentInstance.connectedCallback());
249
- const s = this.componentInstance;
250
- Object.assign(s, e.props), "props" in s && (s.props = e.props), s.children = e.children, s.requestUpdate();
251
- }
252
- updateRepeat(e) {
253
- const { items: s, keyFn: t, templateFn: i } = e, r = /* @__PURE__ */ new Map();
254
- this._childParts.forEach((p, m) => {
255
- const f = this._partKeys[m];
256
- f !== void 0 && r.set(f, p);
257
- });
258
- const a = [], c = [];
259
- let d = this.startNode;
260
- s.forEach((p, m) => {
261
- const f = t(p, m);
262
- c.push(f);
263
- let _ = r.get(f);
264
- _ ? (r.delete(f), _.startNode.previousSibling !== d && this.movePart(_, d), _.update(i(p, m))) : (_ = this.createChildPart(d), _.update(i(p, m))), a.push(_), d = _.endNode;
265
- }), r.forEach((p) => p.dispose()), this._childParts = a, this._partKeys = c;
266
- }
267
- updateArray(e) {
268
- this._partKeys = [];
269
- const s = Math.min(e.length, this._childParts.length);
270
- for (let t = 0; t < s; t++)
271
- this._childParts[t].update(e[t]);
272
- if (e.length > this._childParts.length) {
273
- let t = this._childParts.length > 0 ? this._childParts[this._childParts.length - 1].endNode : this.startNode;
274
- for (let i = s; i < e.length; i++) {
275
- const r = this.createChildPart(t);
276
- this._childParts.push(r), r.update(e[i]), t = r.endNode;
277
- }
278
- }
279
- if (e.length < this._childParts.length)
280
- for (let t = this._childParts.length - 1; t >= e.length; t--)
281
- this._childParts[t].dispose(), this._childParts.pop();
282
- }
283
- createChildPart(e) {
284
- const s = document.createComment("CRP-Item"), t = document.createComment("/CRP-Item"), i = e.nextSibling;
285
- return e.parentNode.insertBefore(s, i), e.parentNode.insertBefore(t, i), new $(s, t);
286
- }
287
- movePart(e, s) {
288
- const t = s.parentNode, i = [];
289
- let r = e.startNode;
290
- for (; r && r !== e.endNode; )
291
- i.push(r), r = r.nextSibling;
292
- i.push(e.endNode);
293
- const a = s.nextSibling;
294
- i.forEach((c) => t.insertBefore(c, a));
295
- }
296
- clearChildParts() {
297
- this._childParts.forEach((e) => e.dispose()), this._childParts = [], this._partKeys = [];
298
- }
299
- dispose() {
300
- this.clear(), this._clearTemplateCache(), this.clearChildParts(), this.startNode.parentNode && this.startNode.parentNode.removeChild(this.startNode), this.endNode.parentNode && this.endNode.parentNode.removeChild(this.endNode), this.componentInstance && (this.renderListener && this.componentInstance.removeRenderListener(this.renderListener), this.componentInstance.disconnectedCallback());
301
- }
302
- updateNode(e) {
303
- var s;
304
- if (this.startNode.parentNode)
305
- if (S(e))
306
- if (this._cachedTemplateStrings === e.strings && this._cachedParts)
307
- this._cachedParts.forEach((t, i) => {
308
- t.update(e.values[i]);
309
- });
310
- else {
311
- this._clearTemplateCache(), this.clear();
312
- const t = document.createDocumentFragment();
313
- I(e, t), this.startNode.parentNode.insertBefore(t, this.endNode);
314
- const i = M.get(((s = t.firstChild) == null ? void 0 : s.childNodes[0]) || t);
315
- i && (this._cachedTemplateStrings = i.strings, this._cachedParts = i.parts);
316
- }
317
- else if (L(e) || typeof e == "object" && e !== null && !(e instanceof Node) && !Array.isArray(e)) {
318
- this._clearTemplateCache(), this.clear();
319
- const t = document.createDocumentFragment();
320
- I(E`${e}`, t), this.startNode.parentNode.insertBefore(t, this.endNode);
321
- } else if (U(e)) {
322
- this._clearTemplateCache(), this.clear();
323
- const t = document.createElement("template");
324
- t.innerHTML = e.value, this.startNode.parentNode.insertBefore(t.content, this.endNode);
325
- } else if (e instanceof Node)
326
- this._clearTemplateCache(), this.clear(), this.startNode.parentNode.insertBefore(e, this.endNode);
327
- else if (e == null || e === !1)
328
- this._clearTemplateCache(), this.clear();
329
- else {
330
- const t = String(e), i = this.startNode.nextSibling;
331
- if (i && i.nodeType === Node.TEXT_NODE && i.nextSibling === this.endNode)
332
- i.nodeValue !== t && (i.nodeValue = t);
333
- else {
334
- this._clearTemplateCache(), this.clear();
335
- const r = document.createTextNode(t);
336
- this.startNode.parentNode.insertBefore(r, this.endNode);
337
- }
338
- }
339
- }
340
- _clearTemplateCache() {
341
- this._cachedTemplateStrings = null, this._cachedParts = null;
342
- }
343
- clear() {
344
- let e = this.startNode.nextSibling;
345
- for (; e && e !== this.endNode; ) {
346
- const s = e.nextSibling;
347
- e.parentNode.removeChild(e), e = s;
348
- }
349
- }
350
- }
351
- class q {
352
- constructor(e) {
353
- h(this, "previousValues", {});
354
- this.element = e;
355
- }
356
- update(e) {
357
- if (typeof e != "object" || e === null) return;
358
- const s = e;
359
- for (const t of Object.keys(this.previousValues))
360
- if (!(t in s))
361
- if (t.startsWith("@")) {
362
- const i = t.slice(1), r = `__crp_handler_${i}`, a = this.element[r];
363
- a && this.element.removeEventListener(i, a);
364
- } else t.startsWith(".") || (t.startsWith("?") ? this.element.removeAttribute(t.slice(1)) : this.element.removeAttribute(t));
365
- for (const [t, i] of Object.entries(s))
366
- if (t.startsWith("@") && typeof i == "function") {
367
- const r = t.slice(1), a = `__crp_handler_${r}`, c = this.element[a];
368
- c && this.element.removeEventListener(r, c), this.element[a] = i, this.element.addEventListener(r, i);
369
- } else t.startsWith(".") ? this.element[t.slice(1)] = i : t.startsWith("?") ? i ? this.element.setAttribute(t.slice(1), "") : this.element.removeAttribute(t.slice(1)) : typeof i == "boolean" ? i ? this.element.setAttribute(t, "") : this.element.removeAttribute(t) : i != null && this.element.setAttribute(t, String(i));
370
- this.previousValues = { ...s };
371
- }
372
- }
373
- class v {
374
- constructor(e, s) {
375
- this.element = e, this.name = s;
376
- }
377
- update(e) {
378
- let s = !1;
379
- if (e instanceof R && (s = !0, e = e.value), this.name === "ref") {
380
- typeof e == "function" ? e(this.element) : e && typeof e == "object" && "value" in e && (e.value = this.element), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
381
- return;
382
- }
383
- if (this.name.startsWith("@") && typeof e == "function") {
384
- const t = this.name.slice(1), i = `__crp_handler_${t}`, r = this.element[i];
385
- r && this.element.removeEventListener(t, r), this.element[i] = e, this.element.addEventListener(t, e), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
386
- } else if (this.name.startsWith(".")) {
387
- const t = this.name.slice(1);
388
- this.element[t] = e, this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
389
- } else if (this.name.startsWith("?")) {
390
- const t = this.name.slice(1);
391
- e ? this.element.setAttribute(t, "") : this.element.removeAttribute(t), this.element.hasAttribute(this.name) && this.element.removeAttribute(this.name);
392
- } else if (this.name === "value" && (this.element instanceof HTMLInputElement || this.element instanceof HTMLTextAreaElement))
393
- s ? this.element.value !== String(e) && (this.element.value = String(e)) : this.element.value !== String(e) && (this.element.value = String(e)), this.element.setAttribute(this.name, String(e));
394
- else if (this.name === "checked" && this.element instanceof HTMLInputElement) {
395
- const t = !!e;
396
- this.element.checked !== t && (this.element.checked = t), t ? this.element.setAttribute(this.name, "") : this.element.removeAttribute(this.name);
397
- } else typeof e == "boolean" ? e ? this.element.setAttribute(this.name, "") : this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, String(e));
398
- }
399
- }
400
- const M = /* @__PURE__ */ new WeakMap(), I = (n, e) => {
401
- const s = M.get(e);
402
- if (s && s.strings === n.strings) {
403
- s.parts.forEach((o, l) => {
404
- o.update(n.values[l]);
405
- });
406
- return;
407
- }
408
- const t = [], i = n.values;
409
- let r = "", a = !1;
410
- const c = (o) => {
411
- for (let l = 0; l < o.length; l++)
412
- o[l] === "<" && o[l + 1] !== "!" && o[l + 1] !== "/" ? a = !0 : o[l] === ">" && (a = !1);
413
- }, d = /(\.\.\.|[.@?]?[a-zA-Z0-9_-]+)=["']?$/;
414
- for (let o = 0; o < n.strings.length - 1; o++) {
415
- const l = n.strings[o];
416
- c(l), r += l;
417
- const u = l.match(d);
418
- a && u ? r += `__CRP_${o}__` : r += `<!--CRP_${o}-->`;
419
- }
420
- const p = n.strings[n.strings.length - 1];
421
- c(p), r += p;
422
- const m = document.createElement("template");
423
- m.innerHTML = r;
424
- const f = m.content.cloneNode(!0), _ = document.createTreeWalker(f, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);
425
- let O;
426
- const j = [];
427
- for (; O = _.nextNode(); )
428
- j.push(O);
429
- j.forEach((o) => {
430
- var l;
431
- if (o.nodeType === Node.COMMENT_NODE) {
432
- const u = (l = o.nodeValue) == null ? void 0 : l.match(/CRP_(\d+)/);
433
- if (u) {
434
- const C = parseInt(u[1]), P = document.createComment("/CRP");
435
- o.parentNode.insertBefore(P, o.nextSibling);
436
- const b = new $(o, P);
437
- t[C] = b;
438
- }
439
- } else if (o.nodeType === Node.ELEMENT_NODE) {
440
- const u = o;
441
- Array.from(u.attributes).forEach((C) => {
442
- const P = C.value.match(/__CRP_(\d+)__/);
443
- if (P) {
444
- const b = parseInt(P[1]);
445
- if (!t[b])
446
- if (C.name === "...") {
447
- const w = new q(u);
448
- t[b] = w, u.removeAttribute("...");
449
- } else {
450
- const w = new v(u, C.name);
451
- t[b] = w;
452
- }
453
- }
454
- });
455
- }
456
- });
457
- for (let o = 0; o < i.length; o++)
458
- t[o] && t[o].update(i[o]);
459
- if (e instanceof HTMLElement)
460
- e.innerHTML = "", e.appendChild(f);
461
- else if (e instanceof DocumentFragment) {
462
- for (; e.firstChild; )
463
- e.removeChild(e.firstChild);
464
- e.appendChild(f);
465
- }
466
- M.set(e, { strings: n.strings, parts: t });
467
- };
468
- export {
469
- T as C,
470
- R as L,
471
- y as R,
472
- B as T,
473
- W as U,
474
- U as a,
475
- I as b,
476
- Y as c,
477
- g as d,
478
- H as e,
479
- x as f,
480
- L as g,
481
- E as h,
482
- S as i,
483
- X as j,
484
- G as k,
485
- Z as l,
486
- J as m,
487
- k as p,
488
- A as r,
489
- Q as s,
490
- ee as u
491
- };